@@ -60,12 +60,23 @@ struct xdp_dev_bulk_queue {
60
60
unsigned int count ;
61
61
};
62
62
63
+ /* DEVMAP values */
64
+ struct bpf_devmap_val {
65
+ u32 ifindex ; /* device index */
66
+ union {
67
+ int fd ; /* prog fd on map write */
68
+ u32 id ; /* prog id on map read */
69
+ } bpf_prog ;
70
+ };
71
+
63
72
struct bpf_dtab_netdev {
64
73
struct net_device * dev ; /* must be first member, due to tracepoint */
65
74
struct hlist_node index_hlist ;
66
75
struct bpf_dtab * dtab ;
76
+ struct bpf_prog * xdp_prog ;
67
77
struct rcu_head rcu ;
68
78
unsigned int idx ;
79
+ struct bpf_devmap_val val ;
69
80
};
70
81
71
82
struct bpf_dtab {
@@ -105,12 +116,18 @@ static inline struct hlist_head *dev_map_index_hash(struct bpf_dtab *dtab,
105
116
106
117
static int dev_map_init_map (struct bpf_dtab * dtab , union bpf_attr * attr )
107
118
{
119
+ u32 valsize = attr -> value_size ;
108
120
u64 cost = 0 ;
109
121
int err ;
110
122
111
- /* check sanity of attributes */
123
+ /* check sanity of attributes. 2 value sizes supported:
124
+ * 4 bytes: ifindex
125
+ * 8 bytes: ifindex + prog fd
126
+ */
112
127
if (attr -> max_entries == 0 || attr -> key_size != 4 ||
113
- attr -> value_size != 4 || attr -> map_flags & ~DEV_CREATE_FLAG_MASK )
128
+ (valsize != offsetofend (struct bpf_devmap_val , ifindex ) &&
129
+ valsize != offsetofend (struct bpf_devmap_val , bpf_prog .fd )) ||
130
+ attr -> map_flags & ~DEV_CREATE_FLAG_MASK )
114
131
return - EINVAL ;
115
132
116
133
/* Lookup returns a pointer straight to dev->ifindex, so make sure the
@@ -217,6 +234,8 @@ static void dev_map_free(struct bpf_map *map)
217
234
218
235
hlist_for_each_entry_safe (dev , next , head , index_hlist ) {
219
236
hlist_del_rcu (& dev -> index_hlist );
237
+ if (dev -> xdp_prog )
238
+ bpf_prog_put (dev -> xdp_prog );
220
239
dev_put (dev -> dev );
221
240
kfree (dev );
222
241
}
@@ -231,6 +250,8 @@ static void dev_map_free(struct bpf_map *map)
231
250
if (!dev )
232
251
continue ;
233
252
253
+ if (dev -> xdp_prog )
254
+ bpf_prog_put (dev -> xdp_prog );
234
255
dev_put (dev -> dev );
235
256
kfree (dev );
236
257
}
@@ -317,6 +338,16 @@ static int dev_map_hash_get_next_key(struct bpf_map *map, void *key,
317
338
return - ENOENT ;
318
339
}
319
340
341
+ bool dev_map_can_have_prog (struct bpf_map * map )
342
+ {
343
+ if ((map -> map_type == BPF_MAP_TYPE_DEVMAP ||
344
+ map -> map_type == BPF_MAP_TYPE_DEVMAP_HASH ) &&
345
+ map -> value_size != offsetofend (struct bpf_devmap_val , ifindex ))
346
+ return true;
347
+
348
+ return false;
349
+ }
350
+
320
351
static int bq_xmit_all (struct xdp_dev_bulk_queue * bq , u32 flags )
321
352
{
322
353
struct net_device * dev = bq -> dev ;
@@ -441,6 +472,33 @@ static inline int __xdp_enqueue(struct net_device *dev, struct xdp_buff *xdp,
441
472
return bq_enqueue (dev , xdpf , dev_rx );
442
473
}
443
474
475
+ static struct xdp_buff * dev_map_run_prog (struct net_device * dev ,
476
+ struct xdp_buff * xdp ,
477
+ struct bpf_prog * xdp_prog )
478
+ {
479
+ struct xdp_txq_info txq = { .dev = dev };
480
+ u32 act ;
481
+
482
+ xdp -> txq = & txq ;
483
+
484
+ act = bpf_prog_run_xdp (xdp_prog , xdp );
485
+ switch (act ) {
486
+ case XDP_PASS :
487
+ return xdp ;
488
+ case XDP_DROP :
489
+ break ;
490
+ default :
491
+ bpf_warn_invalid_xdp_action (act );
492
+ fallthrough ;
493
+ case XDP_ABORTED :
494
+ trace_xdp_exception (dev , xdp_prog , act );
495
+ break ;
496
+ }
497
+
498
+ xdp_return_buff (xdp );
499
+ return NULL ;
500
+ }
501
+
444
502
int dev_xdp_enqueue (struct net_device * dev , struct xdp_buff * xdp ,
445
503
struct net_device * dev_rx )
446
504
{
@@ -452,6 +510,11 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
452
510
{
453
511
struct net_device * dev = dst -> dev ;
454
512
513
+ if (dst -> xdp_prog ) {
514
+ xdp = dev_map_run_prog (dev , xdp , dst -> xdp_prog );
515
+ if (!xdp )
516
+ return 0 ;
517
+ }
455
518
return __xdp_enqueue (dev , xdp , dev_rx );
456
519
}
457
520
@@ -472,25 +535,24 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
472
535
static void * dev_map_lookup_elem (struct bpf_map * map , void * key )
473
536
{
474
537
struct bpf_dtab_netdev * obj = __dev_map_lookup_elem (map , * (u32 * )key );
475
- struct net_device * dev = obj ? obj -> dev : NULL ;
476
538
477
- return dev ? & dev -> ifindex : NULL ;
539
+ return obj ? & obj -> val : NULL ;
478
540
}
479
541
480
542
static void * dev_map_hash_lookup_elem (struct bpf_map * map , void * key )
481
543
{
482
544
struct bpf_dtab_netdev * obj = __dev_map_hash_lookup_elem (map ,
483
545
* (u32 * )key );
484
- struct net_device * dev = obj ? obj -> dev : NULL ;
485
-
486
- return dev ? & dev -> ifindex : NULL ;
546
+ return obj ? & obj -> val : NULL ;
487
547
}
488
548
489
549
static void __dev_map_entry_free (struct rcu_head * rcu )
490
550
{
491
551
struct bpf_dtab_netdev * dev ;
492
552
493
553
dev = container_of (rcu , struct bpf_dtab_netdev , rcu );
554
+ if (dev -> xdp_prog )
555
+ bpf_prog_put (dev -> xdp_prog );
494
556
dev_put (dev -> dev );
495
557
kfree (dev );
496
558
}
@@ -541,34 +603,57 @@ static int dev_map_hash_delete_elem(struct bpf_map *map, void *key)
541
603
542
604
static struct bpf_dtab_netdev * __dev_map_alloc_node (struct net * net ,
543
605
struct bpf_dtab * dtab ,
544
- u32 ifindex ,
606
+ struct bpf_devmap_val * val ,
545
607
unsigned int idx )
546
608
{
609
+ struct bpf_prog * prog = NULL ;
547
610
struct bpf_dtab_netdev * dev ;
548
611
549
612
dev = kmalloc_node (sizeof (* dev ), GFP_ATOMIC | __GFP_NOWARN ,
550
613
dtab -> map .numa_node );
551
614
if (!dev )
552
615
return ERR_PTR (- ENOMEM );
553
616
554
- dev -> dev = dev_get_by_index (net , ifindex );
555
- if (!dev -> dev ) {
556
- kfree (dev );
557
- return ERR_PTR (- EINVAL );
617
+ dev -> dev = dev_get_by_index (net , val -> ifindex );
618
+ if (!dev -> dev )
619
+ goto err_out ;
620
+
621
+ if (val -> bpf_prog .fd >= 0 ) {
622
+ prog = bpf_prog_get_type_dev (val -> bpf_prog .fd ,
623
+ BPF_PROG_TYPE_XDP , false);
624
+ if (IS_ERR (prog ))
625
+ goto err_put_dev ;
626
+ if (prog -> expected_attach_type != BPF_XDP_DEVMAP )
627
+ goto err_put_prog ;
558
628
}
559
629
560
630
dev -> idx = idx ;
561
631
dev -> dtab = dtab ;
632
+ if (prog ) {
633
+ dev -> xdp_prog = prog ;
634
+ dev -> val .bpf_prog .id = prog -> aux -> id ;
635
+ } else {
636
+ dev -> xdp_prog = NULL ;
637
+ dev -> val .bpf_prog .id = 0 ;
638
+ }
639
+ dev -> val .ifindex = val -> ifindex ;
562
640
563
641
return dev ;
642
+ err_put_prog :
643
+ bpf_prog_put (prog );
644
+ err_put_dev :
645
+ dev_put (dev -> dev );
646
+ err_out :
647
+ kfree (dev );
648
+ return ERR_PTR (- EINVAL );
564
649
}
565
650
566
651
static int __dev_map_update_elem (struct net * net , struct bpf_map * map ,
567
652
void * key , void * value , u64 map_flags )
568
653
{
569
654
struct bpf_dtab * dtab = container_of (map , struct bpf_dtab , map );
655
+ struct bpf_devmap_val val = { .bpf_prog .fd = -1 };
570
656
struct bpf_dtab_netdev * dev , * old_dev ;
571
- u32 ifindex = * (u32 * )value ;
572
657
u32 i = * (u32 * )key ;
573
658
574
659
if (unlikely (map_flags > BPF_EXIST ))
@@ -578,10 +663,16 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
578
663
if (unlikely (map_flags == BPF_NOEXIST ))
579
664
return - EEXIST ;
580
665
581
- if (!ifindex ) {
666
+ /* already verified value_size <= sizeof val */
667
+ memcpy (& val , value , map -> value_size );
668
+
669
+ if (!val .ifindex ) {
582
670
dev = NULL ;
671
+ /* can not specify fd if ifindex is 0 */
672
+ if (val .bpf_prog .fd != -1 )
673
+ return - EINVAL ;
583
674
} else {
584
- dev = __dev_map_alloc_node (net , dtab , ifindex , i );
675
+ dev = __dev_map_alloc_node (net , dtab , & val , i );
585
676
if (IS_ERR (dev ))
586
677
return PTR_ERR (dev );
587
678
}
@@ -608,13 +699,16 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map,
608
699
void * key , void * value , u64 map_flags )
609
700
{
610
701
struct bpf_dtab * dtab = container_of (map , struct bpf_dtab , map );
702
+ struct bpf_devmap_val val = { .bpf_prog .fd = -1 };
611
703
struct bpf_dtab_netdev * dev , * old_dev ;
612
- u32 ifindex = * (u32 * )value ;
613
704
u32 idx = * (u32 * )key ;
614
705
unsigned long flags ;
615
706
int err = - EEXIST ;
616
707
617
- if (unlikely (map_flags > BPF_EXIST || !ifindex ))
708
+ /* already verified value_size <= sizeof val */
709
+ memcpy (& val , value , map -> value_size );
710
+
711
+ if (unlikely (map_flags > BPF_EXIST || !val .ifindex ))
618
712
return - EINVAL ;
619
713
620
714
spin_lock_irqsave (& dtab -> index_lock , flags );
@@ -623,7 +717,7 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map,
623
717
if (old_dev && (map_flags & BPF_NOEXIST ))
624
718
goto out_err ;
625
719
626
- dev = __dev_map_alloc_node (net , dtab , ifindex , idx );
720
+ dev = __dev_map_alloc_node (net , dtab , & val , idx );
627
721
if (IS_ERR (dev )) {
628
722
err = PTR_ERR (dev );
629
723
goto out_err ;
0 commit comments