Skip to content

Commit b73e56f

Browse files
committed
Merge branch 'xdp-a-fistful-of-generic-changes-pt-iii'
Alexander Lobakin says: ==================== xdp: a fistful of generic changes pt. III XDP for idpf is currently 5.(6) chapters: * convert Rx to libeth; * convert Tx and stats to libeth; * generic XDP and XSk code changes; * generic XDP and XSk code additions pt. 1; * generic XDP and XSk code additions pt. 2 (you are here); * actual XDP for idpf via new libeth_xdp; * XSk for idpf (via ^). Part III.3 does the following: * adds generic functions to build skbs from xdp_buffs (regular and XSk) and attach frags to xdp_buffs (regular and XSk); * adds helper to optimize XSk xmit in drivers. Everything is prereq for libeth_xdp, but will be useful standalone as well: less code in drivers, faster XSk XDP_PASS, smaller object code. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 29b5407 + 560d958 commit b73e56f

File tree

7 files changed

+316
-65
lines changed

7 files changed

+316
-65
lines changed

drivers/net/ethernet/intel/i40e/i40e_xsk.c

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -395,32 +395,6 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring,
395395
WARN_ON_ONCE(1);
396396
}
397397

398-
static int
399-
i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first,
400-
struct xdp_buff *xdp, const unsigned int size)
401-
{
402-
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
403-
404-
if (!xdp_buff_has_frags(first)) {
405-
sinfo->nr_frags = 0;
406-
sinfo->xdp_frags_size = 0;
407-
xdp_buff_set_frags_flag(first);
408-
}
409-
410-
if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
411-
xsk_buff_free(first);
412-
return -ENOMEM;
413-
}
414-
415-
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
416-
virt_to_page(xdp->data_hard_start),
417-
XDP_PACKET_HEADROOM, size);
418-
sinfo->xdp_frags_size += size;
419-
xsk_buff_add_frag(xdp);
420-
421-
return 0;
422-
}
423-
424398
/**
425399
* i40e_clean_rx_irq_zc - Consumes Rx packets from the hardware ring
426400
* @rx_ring: Rx ring
@@ -486,8 +460,10 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
486460

487461
if (!first)
488462
first = bi;
489-
else if (i40e_add_xsk_frag(rx_ring, first, bi, size))
463+
else if (!xsk_buff_add_frag(first, bi)) {
464+
xsk_buff_free(first);
490465
break;
466+
}
491467

492468
if (++next_to_process == count)
493469
next_to_process = 0;

drivers/net/ethernet/intel/ice/ice_xsk.c

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -801,35 +801,6 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
801801
return result;
802802
}
803803

804-
static int
805-
ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first,
806-
struct xdp_buff *xdp, const unsigned int size)
807-
{
808-
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
809-
810-
if (!size)
811-
return 0;
812-
813-
if (!xdp_buff_has_frags(first)) {
814-
sinfo->nr_frags = 0;
815-
sinfo->xdp_frags_size = 0;
816-
xdp_buff_set_frags_flag(first);
817-
}
818-
819-
if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
820-
xsk_buff_free(first);
821-
return -ENOMEM;
822-
}
823-
824-
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
825-
virt_to_page(xdp->data_hard_start),
826-
XDP_PACKET_HEADROOM, size);
827-
sinfo->xdp_frags_size += size;
828-
xsk_buff_add_frag(xdp);
829-
830-
return 0;
831-
}
832-
833804
/**
834805
* ice_clean_rx_irq_zc - consumes packets from the hardware ring
835806
* @rx_ring: AF_XDP Rx ring
@@ -895,7 +866,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
895866

896867
if (!first) {
897868
first = xdp;
898-
} else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) {
869+
} else if (likely(size) && !xsk_buff_add_frag(first, xdp)) {
870+
xsk_buff_free(first);
899871
break;
900872
}
901873

include/linux/skbuff.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -608,11 +608,19 @@ struct skb_shared_info {
608608
* Warning : all fields before dataref are cleared in __alloc_skb()
609609
*/
610610
atomic_t dataref;
611-
unsigned int xdp_frags_size;
612611

613-
/* Intermediate layers must ensure that destructor_arg
614-
* remains valid until skb destructor */
615-
void * destructor_arg;
612+
union {
613+
struct {
614+
u32 xdp_frags_size;
615+
u32 xdp_frags_truesize;
616+
};
617+
618+
/*
619+
* Intermediate layers must ensure that destructor_arg
620+
* remains valid until skb destructor.
621+
*/
622+
void *destructor_arg;
623+
};
616624

617625
/* must be last field, see pskb_expand_head() */
618626
skb_frag_t frags[MAX_SKB_FRAGS];

include/net/page_pool/helpers.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ static inline netmem_ref page_pool_alloc_netmem(struct page_pool *pool,
144144
return netmem;
145145
}
146146

147+
static inline netmem_ref page_pool_dev_alloc_netmem(struct page_pool *pool,
148+
unsigned int *offset,
149+
unsigned int *size)
150+
{
151+
gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN;
152+
153+
return page_pool_alloc_netmem(pool, offset, size, gfp);
154+
}
155+
147156
static inline struct page *page_pool_alloc(struct page_pool *pool,
148157
unsigned int *offset,
149158
unsigned int *size, gfp_t gfp)

include/net/xdp.h

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,93 @@ xdp_get_buff_len(const struct xdp_buff *xdp)
167167
return len;
168168
}
169169

170+
void xdp_return_frag(netmem_ref netmem, const struct xdp_buff *xdp);
171+
172+
/**
173+
* __xdp_buff_add_frag - attach frag to &xdp_buff
174+
* @xdp: XDP buffer to attach the frag to
175+
* @netmem: network memory containing the frag
176+
* @offset: offset at which the frag starts
177+
* @size: size of the frag
178+
* @truesize: total memory size occupied by the frag
179+
* @try_coalesce: whether to try coalescing the frags (not valid for XSk)
180+
*
181+
* Attach frag to the XDP buffer. If it currently has no frags attached,
182+
* initialize the related fields, otherwise check that the frag number
183+
* didn't reach the limit of ``MAX_SKB_FRAGS``. If possible, try coalescing
184+
* the frag with the previous one.
185+
* The function doesn't check/update the pfmemalloc bit. Please use the
186+
* non-underscored wrapper in drivers.
187+
*
188+
* Return: true on success, false if there's no space for the frag in
189+
* the shared info struct.
190+
*/
191+
static inline bool __xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
192+
u32 offset, u32 size, u32 truesize,
193+
bool try_coalesce)
194+
{
195+
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
196+
skb_frag_t *prev;
197+
u32 nr_frags;
198+
199+
if (!xdp_buff_has_frags(xdp)) {
200+
xdp_buff_set_frags_flag(xdp);
201+
202+
nr_frags = 0;
203+
sinfo->xdp_frags_size = 0;
204+
sinfo->xdp_frags_truesize = 0;
205+
206+
goto fill;
207+
}
208+
209+
nr_frags = sinfo->nr_frags;
210+
prev = &sinfo->frags[nr_frags - 1];
211+
212+
if (try_coalesce && netmem == skb_frag_netmem(prev) &&
213+
offset == skb_frag_off(prev) + skb_frag_size(prev)) {
214+
skb_frag_size_add(prev, size);
215+
/* Guaranteed to only decrement the refcount */
216+
xdp_return_frag(netmem, xdp);
217+
} else if (unlikely(nr_frags == MAX_SKB_FRAGS)) {
218+
return false;
219+
} else {
220+
fill:
221+
__skb_fill_netmem_desc_noacc(sinfo, nr_frags++, netmem,
222+
offset, size);
223+
}
224+
225+
sinfo->nr_frags = nr_frags;
226+
sinfo->xdp_frags_size += size;
227+
sinfo->xdp_frags_truesize += truesize;
228+
229+
return true;
230+
}
231+
232+
/**
233+
* xdp_buff_add_frag - attach frag to &xdp_buff
234+
* @xdp: XDP buffer to attach the frag to
235+
* @netmem: network memory containing the frag
236+
* @offset: offset at which the frag starts
237+
* @size: size of the frag
238+
* @truesize: total memory size occupied by the frag
239+
*
240+
* Version of __xdp_buff_add_frag() which takes care of the pfmemalloc bit.
241+
*
242+
* Return: true on success, false if there's no space for the frag in
243+
* the shared info struct.
244+
*/
245+
static inline bool xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
246+
u32 offset, u32 size, u32 truesize)
247+
{
248+
if (!__xdp_buff_add_frag(xdp, netmem, offset, size, truesize, true))
249+
return false;
250+
251+
if (unlikely(netmem_is_pfmemalloc(netmem)))
252+
xdp_buff_set_frag_pfmemalloc(xdp);
253+
254+
return true;
255+
}
256+
170257
struct xdp_frame {
171258
void *data;
172259
u32 len;
@@ -230,7 +317,14 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
230317
unsigned int size, unsigned int truesize,
231318
bool pfmemalloc)
232319
{
233-
skb_shinfo(skb)->nr_frags = nr_frags;
320+
struct skb_shared_info *sinfo = skb_shinfo(skb);
321+
322+
sinfo->nr_frags = nr_frags;
323+
/*
324+
* ``destructor_arg`` is unionized with ``xdp_frags_{,true}size``,
325+
* reset it after that these fields aren't used anymore.
326+
*/
327+
sinfo->destructor_arg = NULL;
234328

235329
skb->len += size;
236330
skb->data_len += size;
@@ -242,6 +336,8 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
242336
void xdp_warn(const char *msg, const char *func, const int line);
243337
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)
244338

339+
struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp);
340+
struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp);
245341
struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp);
246342
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
247343
struct sk_buff *skb,

include/net/xdp_sock_drv.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,21 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
136136
xp_free(xskb);
137137
}
138138

139-
static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
139+
static inline bool xsk_buff_add_frag(struct xdp_buff *head,
140+
struct xdp_buff *xdp)
140141
{
141-
struct xdp_buff_xsk *frag = container_of(xdp, struct xdp_buff_xsk, xdp);
142+
const void *data = xdp->data;
143+
struct xdp_buff_xsk *frag;
144+
145+
if (!__xdp_buff_add_frag(head, virt_to_netmem(data),
146+
offset_in_page(data), xdp->data_end - data,
147+
xdp->frame_sz, false))
148+
return false;
142149

150+
frag = container_of(xdp, struct xdp_buff_xsk, xdp);
143151
list_add_tail(&frag->list_node, &frag->pool->xskb_list);
152+
153+
return true;
144154
}
145155

146156
static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
@@ -357,8 +367,10 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
357367
{
358368
}
359369

360-
static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
370+
static inline bool xsk_buff_add_frag(struct xdp_buff *head,
371+
struct xdp_buff *xdp)
361372
{
373+
return false;
362374
}
363375

364376
static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)

0 commit comments

Comments
 (0)