Commit cc5b114d authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Jeff Kirsher

bpf, i40e: add meta data support

Add support for XDP meta data when using build skb variant of
the i40e driver. Implementation is analogous to the existing
ixgbe and ixgbevf support for meta data from 366a88fe ("bpf,
ixgbe: add meta data support") and be833332 ("ixgbevf: Add
support for meta data"). With the build skb variant we get
192 bytes of extra headroom which can be used for encaps or
meta data.
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Tested-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent e9c72183
...@@ -2032,6 +2032,21 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring, ...@@ -2032,6 +2032,21 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
#if L1_CACHE_BYTES < 128 #if L1_CACHE_BYTES < 128
prefetch(xdp->data + L1_CACHE_BYTES); prefetch(xdp->data + L1_CACHE_BYTES);
#endif #endif
/* Note, we get here by enabling legacy-rx via:
*
* ethtool --set-priv-flags <dev> legacy-rx on
*
* In this mode, we currently get 0 extra XDP headroom as
* opposed to having legacy-rx off, where we process XDP
* packets going to stack via i40e_build_skb(). The latter
* provides us currently with 192 bytes of headroom.
*
* For i40e_construct_skb() mode it means that the
* xdp->data_meta will always point to xdp->data, since
* the helper cannot expand the head. Should this ever
* change in future for legacy-rx mode on, then lets also
* add xdp->data_meta handling here.
*/
/* allocate a skb to store the frags */ /* allocate a skb to store the frags */
skb = __napi_alloc_skb(&rx_ring->q_vector->napi, skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
...@@ -2083,19 +2098,25 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, ...@@ -2083,19 +2098,25 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
struct i40e_rx_buffer *rx_buffer, struct i40e_rx_buffer *rx_buffer,
struct xdp_buff *xdp) struct xdp_buff *xdp)
{ {
unsigned int size = xdp->data_end - xdp->data; unsigned int metasize = xdp->data - xdp->data_meta;
#if (PAGE_SIZE < 8192) #if (PAGE_SIZE < 8192)
unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2; unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
#else #else
unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
SKB_DATA_ALIGN(I40E_SKB_PAD + size); SKB_DATA_ALIGN(I40E_SKB_PAD +
(xdp->data_end -
xdp->data_hard_start));
#endif #endif
struct sk_buff *skb; struct sk_buff *skb;
/* prefetch first cache line of first page */ /* Prefetch first cache line of first page. If xdp->data_meta
prefetch(xdp->data); * is unused, this points exactly as xdp->data, otherwise we
* likely have a consumer accessing first few bytes of meta
* data, and then actual data.
*/
prefetch(xdp->data_meta);
#if L1_CACHE_BYTES < 128 #if L1_CACHE_BYTES < 128
prefetch(xdp->data + L1_CACHE_BYTES); prefetch(xdp->data_meta + L1_CACHE_BYTES);
#endif #endif
/* build an skb around the page buffer */ /* build an skb around the page buffer */
skb = build_skb(xdp->data_hard_start, truesize); skb = build_skb(xdp->data_hard_start, truesize);
...@@ -2103,8 +2124,10 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, ...@@ -2103,8 +2124,10 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
return NULL; return NULL;
/* update pointers within the skb to store the data */ /* update pointers within the skb to store the data */
skb_reserve(skb, I40E_SKB_PAD); skb_reserve(skb, I40E_SKB_PAD + (xdp->data - xdp->data_hard_start));
__skb_put(skb, size); __skb_put(skb, xdp->data_end - xdp->data);
if (metasize)
skb_metadata_set(skb, metasize);
/* buffer is used by skb, update page_offset */ /* buffer is used by skb, update page_offset */
#if (PAGE_SIZE < 8192) #if (PAGE_SIZE < 8192)
...@@ -2341,7 +2364,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) ...@@ -2341,7 +2364,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
if (!skb) { if (!skb) {
xdp.data = page_address(rx_buffer->page) + xdp.data = page_address(rx_buffer->page) +
rx_buffer->page_offset; rx_buffer->page_offset;
xdp_set_data_meta_invalid(&xdp); xdp.data_meta = xdp.data;
xdp.data_hard_start = xdp.data - xdp.data_hard_start = xdp.data -
i40e_rx_offset(rx_ring); i40e_rx_offset(rx_ring);
xdp.data_end = xdp.data + size; xdp.data_end = xdp.data + size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment