32
32
#define VETH_RING_SIZE 256
33
33
#define VETH_XDP_HEADROOM (XDP_PACKET_HEADROOM + NET_IP_ALIGN)
34
34
35
+ /* Separating two types of XDP xmit */
36
+ #define VETH_XDP_TX BIT(0)
37
+ #define VETH_XDP_REDIR BIT(1)
38
+
35
39
struct pcpu_vstats {
36
40
u64 packets ;
37
41
u64 bytes ;
@@ -45,6 +49,7 @@ struct veth_priv {
45
49
struct bpf_prog * _xdp_prog ;
46
50
struct net_device __rcu * peer ;
47
51
atomic64_t dropped ;
52
+ struct xdp_mem_info xdp_mem ;
48
53
unsigned requested_headroom ;
49
54
bool rx_notify_masked ;
50
55
struct ptr_ring xdp_ring ;
@@ -317,12 +322,44 @@ static int veth_xdp_xmit(struct net_device *dev, int n,
317
322
return n - drops ;
318
323
}
319
324
325
+ static void veth_xdp_flush (struct net_device * dev )
326
+ {
327
+ struct veth_priv * rcv_priv , * priv = netdev_priv (dev );
328
+ struct net_device * rcv ;
329
+
330
+ rcu_read_lock ();
331
+ rcv = rcu_dereference (priv -> peer );
332
+ if (unlikely (!rcv ))
333
+ goto out ;
334
+
335
+ rcv_priv = netdev_priv (rcv );
336
+ /* xdp_ring is initialized on receive side? */
337
+ if (unlikely (!rcu_access_pointer (rcv_priv -> xdp_prog )))
338
+ goto out ;
339
+
340
+ __veth_xdp_flush (rcv_priv );
341
+ out :
342
+ rcu_read_unlock ();
343
+ }
344
+
345
+ static int veth_xdp_tx (struct net_device * dev , struct xdp_buff * xdp )
346
+ {
347
+ struct xdp_frame * frame = convert_to_xdp_frame (xdp );
348
+
349
+ if (unlikely (!frame ))
350
+ return - EOVERFLOW ;
351
+
352
+ return veth_xdp_xmit (dev , 1 , & frame , 0 );
353
+ }
354
+
320
355
static struct sk_buff * veth_xdp_rcv_one (struct veth_priv * priv ,
321
- struct xdp_frame * frame )
356
+ struct xdp_frame * frame ,
357
+ unsigned int * xdp_xmit )
322
358
{
323
359
void * hard_start = frame -> data - frame -> headroom ;
324
360
void * head = hard_start - sizeof (struct xdp_frame );
325
361
int len = frame -> len , delta = 0 ;
362
+ struct xdp_frame orig_frame ;
326
363
struct bpf_prog * xdp_prog ;
327
364
unsigned int headroom ;
328
365
struct sk_buff * skb ;
@@ -346,6 +383,29 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_priv *priv,
346
383
delta = frame -> data - xdp .data ;
347
384
len = xdp .data_end - xdp .data ;
348
385
break ;
386
+ case XDP_TX :
387
+ orig_frame = * frame ;
388
+ xdp .data_hard_start = head ;
389
+ xdp .rxq -> mem = frame -> mem ;
390
+ if (unlikely (veth_xdp_tx (priv -> dev , & xdp ) < 0 )) {
391
+ trace_xdp_exception (priv -> dev , xdp_prog , act );
392
+ frame = & orig_frame ;
393
+ goto err_xdp ;
394
+ }
395
+ * xdp_xmit |= VETH_XDP_TX ;
396
+ rcu_read_unlock ();
397
+ goto xdp_xmit ;
398
+ case XDP_REDIRECT :
399
+ orig_frame = * frame ;
400
+ xdp .data_hard_start = head ;
401
+ xdp .rxq -> mem = frame -> mem ;
402
+ if (xdp_do_redirect (priv -> dev , & xdp , xdp_prog )) {
403
+ frame = & orig_frame ;
404
+ goto err_xdp ;
405
+ }
406
+ * xdp_xmit |= VETH_XDP_REDIR ;
407
+ rcu_read_unlock ();
408
+ goto xdp_xmit ;
349
409
default :
350
410
bpf_warn_invalid_xdp_action (act );
351
411
case XDP_ABORTED :
@@ -370,12 +430,13 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_priv *priv,
370
430
err_xdp :
371
431
rcu_read_unlock ();
372
432
xdp_return_frame (frame );
373
-
433
+ xdp_xmit :
374
434
return NULL ;
375
435
}
376
436
377
437
static struct sk_buff * veth_xdp_rcv_skb (struct veth_priv * priv ,
378
- struct sk_buff * skb )
438
+ struct sk_buff * skb ,
439
+ unsigned int * xdp_xmit )
379
440
{
380
441
u32 pktlen , headroom , act , metalen ;
381
442
void * orig_data , * orig_data_end ;
@@ -447,6 +508,26 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_priv *priv,
447
508
switch (act ) {
448
509
case XDP_PASS :
449
510
break ;
511
+ case XDP_TX :
512
+ get_page (virt_to_page (xdp .data ));
513
+ consume_skb (skb );
514
+ xdp .rxq -> mem = priv -> xdp_mem ;
515
+ if (unlikely (veth_xdp_tx (priv -> dev , & xdp ) < 0 )) {
516
+ trace_xdp_exception (priv -> dev , xdp_prog , act );
517
+ goto err_xdp ;
518
+ }
519
+ * xdp_xmit |= VETH_XDP_TX ;
520
+ rcu_read_unlock ();
521
+ goto xdp_xmit ;
522
+ case XDP_REDIRECT :
523
+ get_page (virt_to_page (xdp .data ));
524
+ consume_skb (skb );
525
+ xdp .rxq -> mem = priv -> xdp_mem ;
526
+ if (xdp_do_redirect (priv -> dev , & xdp , xdp_prog ))
527
+ goto err_xdp ;
528
+ * xdp_xmit |= VETH_XDP_REDIR ;
529
+ rcu_read_unlock ();
530
+ goto xdp_xmit ;
450
531
default :
451
532
bpf_warn_invalid_xdp_action (act );
452
533
case XDP_ABORTED :
@@ -477,9 +558,15 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_priv *priv,
477
558
rcu_read_unlock ();
478
559
kfree_skb (skb );
479
560
return NULL ;
561
+ err_xdp :
562
+ rcu_read_unlock ();
563
+ page_frag_free (xdp .data );
564
+ xdp_xmit :
565
+ return NULL ;
480
566
}
481
567
482
- static int veth_xdp_rcv (struct veth_priv * priv , int budget )
568
+ static int veth_xdp_rcv (struct veth_priv * priv , int budget ,
569
+ unsigned int * xdp_xmit )
483
570
{
484
571
int i , done = 0 ;
485
572
@@ -490,10 +577,12 @@ static int veth_xdp_rcv(struct veth_priv *priv, int budget)
490
577
if (!ptr )
491
578
break ;
492
579
493
- if (veth_is_xdp_frame (ptr ))
494
- skb = veth_xdp_rcv_one (priv , veth_ptr_to_xdp (ptr ));
495
- else
496
- skb = veth_xdp_rcv_skb (priv , ptr );
580
+ if (veth_is_xdp_frame (ptr )) {
581
+ skb = veth_xdp_rcv_one (priv , veth_ptr_to_xdp (ptr ),
582
+ xdp_xmit );
583
+ } else {
584
+ skb = veth_xdp_rcv_skb (priv , ptr , xdp_xmit );
585
+ }
497
586
498
587
if (skb )
499
588
napi_gro_receive (& priv -> xdp_napi , skb );
@@ -508,9 +597,11 @@ static int veth_poll(struct napi_struct *napi, int budget)
508
597
{
509
598
struct veth_priv * priv =
510
599
container_of (napi , struct veth_priv , xdp_napi );
600
+ unsigned int xdp_xmit = 0 ;
511
601
int done ;
512
602
513
- done = veth_xdp_rcv (priv , budget );
603
+ xdp_set_return_frame_no_direct ();
604
+ done = veth_xdp_rcv (priv , budget , & xdp_xmit );
514
605
515
606
if (done < budget && napi_complete_done (napi , done )) {
516
607
/* Write rx_notify_masked before reading ptr_ring */
@@ -521,6 +612,12 @@ static int veth_poll(struct napi_struct *napi, int budget)
521
612
}
522
613
}
523
614
615
+ if (xdp_xmit & VETH_XDP_TX )
616
+ veth_xdp_flush (priv -> dev );
617
+ if (xdp_xmit & VETH_XDP_REDIR )
618
+ xdp_do_flush_map ();
619
+ xdp_clear_return_frame_no_direct ();
620
+
524
621
return done ;
525
622
}
526
623
@@ -567,6 +664,9 @@ static int veth_enable_xdp(struct net_device *dev)
567
664
err = veth_napi_add (dev );
568
665
if (err )
569
666
goto err ;
667
+
668
+ /* Save original mem info as it can be overwritten */
669
+ priv -> xdp_mem = priv -> xdp_rxq .mem ;
570
670
}
571
671
572
672
rcu_assign_pointer (priv -> xdp_prog , priv -> _xdp_prog );
@@ -584,6 +684,7 @@ static void veth_disable_xdp(struct net_device *dev)
584
684
585
685
rcu_assign_pointer (priv -> xdp_prog , NULL );
586
686
veth_napi_del (dev );
687
+ priv -> xdp_rxq .mem = priv -> xdp_mem ;
587
688
xdp_rxq_info_unreg (& priv -> xdp_rxq );
588
689
}
589
690
0 commit comments