2015-02-17 12:25, Bruce Richardson:
> On Mon, Feb 16, 2015 at 06:34:37PM +0100, Thomas Monjalon wrote:
> > 2015-02-16 15:16, Bruce Richardson:
> > > On Mon, Feb 16, 2015 at 03:33:40PM +0100, Olivier MATZ wrote:
> > > > Hi John,
> > > > 
> > > > On 02/13/2015 04:39 PM, John McNamara wrote:
> > > > > From: Richardson, Bruce <bruce.richardson at intel.com>
> > > > > 
> > > > > Example showing how callbacks can be used to insert a timestamp
> > > > > into each packet on RX. On TX the timestamp is used to calculate
> > > > > the packet latency through the app, in cycles.
> > > > > 
> > > > > Signed-off-by: Bruce Richardson <bruce.richardson at intel.com>
> > > > 
> > > > 
> > > > I'm looking at the example and I don't understand what is the advantage
> > > > of having callbacks in ethdev layer, knowing that the application can
> > > > do the same job by a standard function call.
> > > > 
> > > > What is the advantage of having callbacks compared to:
> > > > 
> > > > 
> > > > for (port = 0; port < nb_ports; port++) {
> > > >         struct rte_mbuf *bufs[BURST_SIZE];
> > > >         const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
> > > >                         bufs, BURST_SIZE);
> > > >         if (unlikely(nb_rx == 0))
> > > >                 continue;
> > > >         add_timestamp(bufs, nb_rx);
> > > > 
> > > >         const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
> > > >                         bufs, nb_rx);
> > > >         calc_latency(bufs, nb_tx);
> > > > 
> > > >         if (unlikely(nb_tx < nb_rx)) {
> > > >                 uint16_t buf;
> > > >                 for (buf = nb_tx; buf < nb_rx; buf++)
> > > >                         rte_pktmbuf_free(bufs[buf]);
> > > >         }
> > > > }
> > > > 
> > > > 
> > > > To me, doing like the code above has several advantages:
> > > > 
> > > > - code is more readable: the callback is explicitly invoked, so there is
> > > >   no risk to forget it
> > > > - code is faster: the functions calls can be inlined by the compiler
> > > > - easier to handle error cases in the callback function as the error
> > > >   code is accessible to the application
> > > > - there is no need to add code in ethdev api to do this
> > > > - if the application does not want to use callbacks (I suppose most
> > > >   applications), it won't have any performance impact
> > > > 
> > > > Regards,
> > > > Olivier
> > > 
> > > In this specific instance, given that the application does little else, 
> > > there
> > > is no real advantage to using the callbacks - it's just to have a simple 
> > > example
> > > of how they can be used.
> > > 
> > > Where callbacks are really designed to be useful, is for extending or 
> > > augmenting
> > > hardware capabilities. Taking the example of sequence numbers - to use 
> > > the most
> > > trivial example - an application could be written to take advantage of 
> > > sequence
> > > numbers written to packets by the hardware which received them. However, 
> > > if such
> > > an application was to be used with a NIC which does not provide sequence 
> > > numbering
> > > capability, for example, anything using ixgbe driver, the application 
> > > writer has
> > > two choices - either modify his application code to check each packet for
> > > a sequence number in the data path, and add it there post-rx, or 
> > > alternatively,
> > > to check the NIC capabilities at initialization time, and add a callback 
> > > there
> > > at initialization, if the hardware does not support it. In the latter 
> > > case,
> > > the main packet processing body of the application can be written as 
> > > though
> > > hardware always has sequence numbering capability, safe in the knowledge 
> > > that
> > > any hardware not supporting it will be back-filled by a software fallback 
> > > at 
> > > initialization-time.
> > > 
> > > By the same token, we could also look to extend hardware capabilities. For
> > > different filtering or hashing capabilities, there can be limits in 
> > > hardware
> > > which are far less than what we need to use in software. Again, callbacks 
> > > will
> > > allow the data path to be written in a way that is oblivious to the 
> > > underlying
> > > hardware limits, because software will transparently fill in the gaps.
> > > 
> > > Hope this makes the use case clear.
> > 
> > After thinking more about these callbacks, I realize these callbacks won't
> > help, as Olivier said.
> > 
> > With callback,
> > 1/ application checks device capability
> > 2/ application provides hardware emulation as DPDK callback
> > 3/ application forgets previous steps
> > 4/ application calls DPDK Rx
> > 5/ DPDK calls callback (without calling optimization)
> > 
> > Without callback,
> > 1/ application checks device capability
> > 2/ application provides hardware emulation as internal function
> > 3/ application set an internal device-flag to enable this function
> > 4/ application calls DPDK Rx
> > 5/ application calls the hardware emulation if flag is set
> > 
> > So the only difference is to keep persistent the device information in
> > the application instead of storing it as a function pointer in the
> > DPDK struct.
> > You can also be faster with this approach: at initialization time,
> > you can check that your NIC supports the feature and use a specific
> > mainloop that adds or not the sequence number without any runtime
> > test.
> 
> That is assuming that all NICs are equal on your system. It's also assuming
> that you only have a single point in your application where you call RX or
> TX burst. In the case where you have a couple of different NICs on the system,
> or where you want to write an application to take advantage of capabilities of
> different NICs, the ability to resolve all these difference at initialization
> time is useful. The main packet handling code can be written with just the
> processing of packets in mind, rather than having to have a set of branches
> after each RX burst call, or before each TX burst call, to "smooth out" the
> different NIC capabilities. 
> 
> As for the option of maintaining different main loops for different NICs with
> different capabilities - that sounds like a maintenance nightmare to
> me, due to duplicated code! Callbacks is a far cleaner solution than that 
> IMHO.

If you really prefer using callbacks intead of direct calls, why not 
implementing
the callbacks hooks in your application by wrapping Rx and Tx burst functions?

> > A callback could be justified for asynchronous events, or when
> > doing specific processing in the middle of the driver, for instance
> > when freeing a mbuf. But in this case it's exactly similar to do
> > the processing in the application after Rx (or before Tx).

Reply via email to