@@ -406,12 +406,38 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
406
406
407
407
void xdp_return_frame (struct xdp_frame * xdpf )
408
408
{
409
+ struct skb_shared_info * sinfo ;
410
+ int i ;
411
+
412
+ if (likely (!xdp_frame_has_frags (xdpf )))
413
+ goto out ;
414
+
415
+ sinfo = xdp_get_shared_info_from_frame (xdpf );
416
+ for (i = 0 ; i < sinfo -> nr_frags ; i ++ ) {
417
+ struct page * page = skb_frag_page (& sinfo -> frags [i ]);
418
+
419
+ __xdp_return (page_address (page ), & xdpf -> mem , false, NULL );
420
+ }
421
+ out :
409
422
__xdp_return (xdpf -> data , & xdpf -> mem , false, NULL );
410
423
}
411
424
EXPORT_SYMBOL_GPL (xdp_return_frame );
412
425
413
426
void xdp_return_frame_rx_napi (struct xdp_frame * xdpf )
414
427
{
428
+ struct skb_shared_info * sinfo ;
429
+ int i ;
430
+
431
+ if (likely (!xdp_frame_has_frags (xdpf )))
432
+ goto out ;
433
+
434
+ sinfo = xdp_get_shared_info_from_frame (xdpf );
435
+ for (i = 0 ; i < sinfo -> nr_frags ; i ++ ) {
436
+ struct page * page = skb_frag_page (& sinfo -> frags [i ]);
437
+
438
+ __xdp_return (page_address (page ), & xdpf -> mem , true, NULL );
439
+ }
440
+ out :
415
441
__xdp_return (xdpf -> data , & xdpf -> mem , true, NULL );
416
442
}
417
443
EXPORT_SYMBOL_GPL (xdp_return_frame_rx_napi );
@@ -447,7 +473,7 @@ void xdp_return_frame_bulk(struct xdp_frame *xdpf,
447
473
struct xdp_mem_allocator * xa ;
448
474
449
475
if (mem -> type != MEM_TYPE_PAGE_POOL ) {
450
- __xdp_return (xdpf -> data , & xdpf -> mem , false, NULL );
476
+ xdp_return_frame (xdpf );
451
477
return ;
452
478
}
453
479
@@ -466,12 +492,38 @@ void xdp_return_frame_bulk(struct xdp_frame *xdpf,
466
492
bq -> xa = rhashtable_lookup (mem_id_ht , & mem -> id , mem_id_rht_params );
467
493
}
468
494
495
+ if (unlikely (xdp_frame_has_frags (xdpf ))) {
496
+ struct skb_shared_info * sinfo ;
497
+ int i ;
498
+
499
+ sinfo = xdp_get_shared_info_from_frame (xdpf );
500
+ for (i = 0 ; i < sinfo -> nr_frags ; i ++ ) {
501
+ skb_frag_t * frag = & sinfo -> frags [i ];
502
+
503
+ bq -> q [bq -> count ++ ] = skb_frag_address (frag );
504
+ if (bq -> count == XDP_BULK_QUEUE_SIZE )
505
+ xdp_flush_frame_bulk (bq );
506
+ }
507
+ }
469
508
bq -> q [bq -> count ++ ] = xdpf -> data ;
470
509
}
471
510
EXPORT_SYMBOL_GPL (xdp_return_frame_bulk );
472
511
473
512
void xdp_return_buff (struct xdp_buff * xdp )
474
513
{
514
+ struct skb_shared_info * sinfo ;
515
+ int i ;
516
+
517
+ if (likely (!xdp_buff_has_frags (xdp )))
518
+ goto out ;
519
+
520
+ sinfo = xdp_get_shared_info_from_buff (xdp );
521
+ for (i = 0 ; i < sinfo -> nr_frags ; i ++ ) {
522
+ struct page * page = skb_frag_page (& sinfo -> frags [i ]);
523
+
524
+ __xdp_return (page_address (page ), & xdp -> rxq -> mem , true, xdp );
525
+ }
526
+ out :
475
527
__xdp_return (xdp -> data , & xdp -> rxq -> mem , true, xdp );
476
528
}
477
529
0 commit comments