RE: [RFC PATCH bpf-next 0/8] XDP_REDIRECT_XSK and Batched AF_XDP Rx
From: Loftus, Ciara <hidden>
Date: 2021-11-16 16:29:47
Also in:
bpf
On 16/11/2021 08.37, Ciara Loftus wrote:quoted
The common case for AF_XDP sockets (xsks) is creating a single xsk on aqueue for sending andquoted
receiving frames as this is analogous to HW packet steering through RSSand other classificationquoted
methods in the NIC. AF_XDP uses the xdp redirect infrastructure to directpackets to the socket. Itquoted
was designed for the much more complicated case of DEVMAPxdp_redirects which directs traffic toquoted
another netdev and thus potentially another driver. In the xsk redirectcase, by skipping thequoted
unnecessary parts of this common code we can significantly improveperformance and pave the wayquoted
for batching in the driver. This RFC proposes one such way to simplify theinfrastructure whichquoted
yields a 27% increase in throughput and a decrease in cycles per packet of24 cycles [1]. The goalquoted
of this RFC is to start a discussion on how best to simplify the single-socketdatapath whilequoted
providing one method as an example. Current approach: 1. XSK pointer: an xsk is created and a handle to the xsk is stored in theXSKMAP.quoted
2. XDP program: bpf_redirect_map helper triggers the XSKMAP lookupwhich stores the result (handlequoted
to the xsk) and the map type (XSKMAP) in the percpu bpf_redirect_infostruct. The XDP_REDIRECTquoted
action is returned. 3. XDP_REDIRECT handling called by the driver: the map type (XSKMAP) isread from thequoted
bpf_redirect_info which selects the xsk_map_redirect path. The xskpointer is retrieved from thequoted
bpf_redirect_info and the XDP descriptor is pushed to the xsk's Rx ring. Thesocket is added to aquoted
list for flushing later. 4. xdp_do_flush: iterate through the lists of all maps that can be used forredirect (CPUMAP,quoted
DEVMAP and XSKMAP). When XSKMAP is flushed, go through all xsks thathad any traffic redirected toquoted
them and bump the Rx ring head pointer(s). For the end goal of submitting the descriptor to the Rx ring and bumpingthe head pointer of thatquoted
ring, only some of these steps are needed. The rest is overhead. Thebpf_redirect_mapquoted
infrastructure is needed for all other redirect operations, but is notnecessary when redirectingquoted
to a single AF_XDP socket. And similarly, flushing the list for every map typein step 4 is notquoted
necessary when only one socket needs to be flushed. Proposed approach: 1. XSK pointer: an xsk is created and a handle to the xsk is stored both inthe XSKMAP and also thequoted
netdev_rx_queue struct. 2. XDP program: new bpf_redirect_xsk helper returns XDP_REDIRECT_XSK. 3. XDP_REDIRECT_XSK handling called by the driver: the xsk pointer isretrieved from thequoted
netdev_rx_queue struct and the XDP descriptor is pushed to the xsk's Rxring.quoted
4. xsk_flush: fetch the handle from the netdev_rx_queue and flush thexsk.quoted
This fast path is triggered on XDP_REDIRECT_XSK if: (i) AF_XDP socket SW Rx ring configured (ii) Exactly one xsk attached to the queue If any of these conditions are not met, fall back to the same behavior as theoriginal approach:quoted
xdp_redirect_map. This is handled under-the-hood in the newbpf_xdp_redirect_xsk helper so the userquoted
does not need to be aware of these conditions. Batching: With this new approach it is possible to optimize the driver by submitting abatch of descriptorsquoted
to the Rx ring in Step 3 of the new approach by simply verifying that theaction returned fromquoted
every program run of each packet in a batch equals XDP_REDIRECT_XSK.That's because with thisquoted
action we know the socket to redirect to will be the same for each packet inthe batch. This isquoted
not possible with XDP_REDIRECT because the xsk pointer is stored in thebpf_redirect_info and notquoted
guaranteed to be the same for every packet in a batch. [1] Performance: The benchmarks were performed on VM running a 2.4GHz Ice Lake hostwith an i40e device passedquoted
through. The xdpsock app was run on a single core with busy polling andconfigured in 'rxonly' mode.quoted
./xdpsock -i <iface> -r -B The improvement in throughput when using the new bpf helper and XDPaction was measured at ~13% forquoted
scalar processing, with reduction in cycles per packet of ~13. A further ~14%improvement inquoted
throughput and reduction of ~11 cycles per packet was measured whenthe batched i40e driver pathquoted
was used, for a total improvement of ~27% in throughput and reduction of~24 cycles per packet.quoted
Other approaches considered: Two other approaches were considered. The advantage of both being thatneither involved introducingquoted
a new XDP action. The first alternative approach considered was to create anew map typequoted
BPF_MAP_TYPE_XSKMAP_DIRECT. When the XDP_REDIRECT action wasreturned, this map type could bequoted
checked and used as an indicator to skip the map lookup and use thenetdev_rx_queue xsk instead.quoted
The second approach considered was similar and involved using a newbpf_redirect_info flag whichquoted
could be used in a similar fashion. While both approaches yielded a performance improvement they weremeasured at about half of whatquoted
was measured for the approach outlined in this RFC. It seems usingbpf_redirect_info is tooquoted
expensive.I think it was Bjørn that discovered that accessing the per CPU bpf_redirect_info struct have an overhead of approx 2 ns (times 2.4GHz ~4.8 cycles). Your reduction in cycles per packet was ~13, where ~4.8 seem to be large. The code access this_cpu_ptr(&bpf_redirect_info) two times. One time in the BPF-helper redirect call and second in xdp_do_redirect. (Hint xdp_redirect_map end-up calling __bpf_xdp_redirect_map) Thus, it seems (as you say), the bpf_redirect_info approach is too expensive. May be should look at storing bpf_redirect_info in a place that doesn't requires the this_cpu_ptr() lookup... or cache the lookup per NAPI cycle. Have you tried this?quoted
Also, centralised processing of XDP actions was investigated. This wouldinvolve porting all driversquoted
to a common interface for handling XDP actions which would greatlysimplify the work involved inquoted
adding support for new XDP actions such as XDP_REDIRECT_XSK. Howeverit was deemed at this point toquoted
be more complex than adding support for the new action to every driver.Should this series bequoted
considered worth pursuing for a proper patch set, the intention would beto update each driverquoted
individually.I'm fine with adding a new helper, but I don't like introducing a new XDP_REDIRECT_XSK action, which requires updating ALL the drivers. With XDP_REDIRECT infra we beleived we didn't need to add more XDP-action code to drivers, as we multiplex/add new features by extending the bpf_redirect_info. In this extreme performance case, it seems the this_cpu_ptr "lookup" of bpf_redirect_info is the performance issue itself. Could you experiement with different approaches that modify xdp_do_redirect() to handle if new helper bpf_redirect_xsk was called, prior to this_cpu_ptr() call. (Thus, avoiding to introduce a new XDP-action).
Thanks for your feedback Jesper. I understand the hesitation of adding a new action. If we can achieve the same improvement without introducing a new action I would be very happy! Without new the action we'll need a new way to indicate that the bpf_redirect_xsk helper was called. Maybe another new field in the netdev alongside the xsk_refcnt. Or else extend bpf_redirect_info - if we find a new home for it that it's too costly to access. Thanks for your suggestions. I'll experiment as you suggested and report back. Thanks, Ciara
quoted
Thank you to Magnus Karlsson and Maciej Fijalkowski for severalsuggestions and insight provided.quoted
TODO: * Add selftest(s) * Add support for all copy and zero copy drivers * Libxdp support The series applies on commit e5043894b21f ("bpftool: Uselibbpf_get_error() to check error")quoted
Thanks, Ciara Ciara Loftus (8): xsk: add struct xdp_sock to netdev_rx_queue bpf: add bpf_redirect_xsk helper and XDP_REDIRECT_XSK action xsk: handle XDP_REDIRECT_XSK and expose xsk_rcv/flush i40e: handle the XDP_REDIRECT_XSK action xsk: implement a batched version of xsk_rcv i40e: isolate descriptor processing in separate function i40e: introduce batched XDP rx descriptor processing libbpf: use bpf_redirect_xsk in the default program drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 +- .../ethernet/intel/i40e/i40e_txrx_common.h | 1 + drivers/net/ethernet/intel/i40e/i40e_xsk.c | 285 +++++++++++++++--- include/linux/netdevice.h | 2 + include/net/xdp_sock_drv.h | 49 +++ include/net/xsk_buff_pool.h | 22 ++ include/uapi/linux/bpf.h | 13 + kernel/bpf/verifier.c | 7 +- net/core/dev.c | 14 + net/core/filter.c | 26 ++ net/xdp/xsk.c | 69 ++++- net/xdp/xsk_queue.h | 31 ++ tools/include/uapi/linux/bpf.h | 13 + tools/lib/bpf/xsk.c | 50 ++- 14 files changed, 551 insertions(+), 44 deletions(-)