31
31
#include <linux/in6.h>
32
32
#include <linux/udp.h>
33
33
#include <linux/tcp.h>
34
+ #include <linux/netdev.h>
34
35
35
36
#include "params.h"
36
37
#include "logging.h"
@@ -54,6 +55,42 @@ DEFINE_SAMPLE_INIT(xdp_trafficgen);
54
55
55
56
static bool status_exited = false;
56
57
58
+ static const char * driver_pass_list [] = {
59
+ "bnxt" ,
60
+ "ena" ,
61
+ "gve" ,
62
+ "i40e" ,
63
+ "ice" ,
64
+ "igb" ,
65
+ "igc"
66
+ "ixgbe" ,
67
+ "octeontx2" ,
68
+ "stmmac" ,
69
+ };
70
+
71
+ static bool driver_needs_xdp_pass (const struct iface * iface )
72
+ {
73
+ const char * name = get_driver_name (iface -> ifindex );
74
+ __u64 feature_flags ;
75
+ size_t i ;
76
+ int err ;
77
+
78
+ /* If the interface already has the NDO_XMIT feature, we don't need to load anything */
79
+ err = iface_get_xdp_feature_flags (iface -> ifindex , & feature_flags );
80
+ if (!err && feature_flags & NETDEV_XDP_ACT_NDO_XMIT )
81
+ return false;
82
+
83
+ for (i = 0 ; i < ARRAY_SIZE (driver_pass_list ); i ++ ) {
84
+ if (!strcmp (name , driver_pass_list [i ])) {
85
+ pr_debug ("Driver %s on interface %s needs an xdp_pass program to use XDP_REDIRECT\n" ,
86
+ name , iface -> ifname );
87
+ return true;
88
+ }
89
+ }
90
+
91
+ return false;
92
+ }
93
+
57
94
struct udp_packet {
58
95
struct ethhdr eth ;
59
96
struct ipv6hdr iph ;
@@ -400,6 +437,7 @@ static struct prog_option udp_options[] = {
400
437
401
438
int do_udp (const void * opt , __unused const char * pin_root_path )
402
439
{
440
+ struct xdp_program * prog = NULL , * pass_prog = NULL ;
403
441
const struct udpopt * cfg = opt ;
404
442
405
443
DECLARE_LIBXDP_OPTS (xdp_program_opts , opts );
@@ -411,7 +449,6 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
411
449
struct xdp_trafficgen * skel = NULL ;
412
450
struct udp_packet * payload = NULL ;
413
451
pthread_t * runner_threads = NULL ;
414
- struct xdp_program * prog = NULL ;
415
452
int err = 0 , i ;
416
453
char buf [100 ];
417
454
__u32 key = 0 ;
@@ -459,10 +496,31 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
459
496
goto out ;
460
497
}
461
498
499
+ if (driver_needs_xdp_pass (& cfg -> iface )) {
500
+ opts .prog_name = "xdp_pass" ;
501
+ pass_prog = xdp_program__create (& opts );
502
+ if (!pass_prog ) {
503
+ err = - errno ;
504
+ pr_warn ("Couldn't load xdp_pass program\n" );
505
+ goto out ;
506
+ }
507
+ }
508
+
462
509
err = xdp_trafficgen__load (skel );
463
510
if (err )
464
511
goto out ;
465
512
513
+ if (pass_prog ) {
514
+ err = xdp_program__attach (pass_prog , cfg -> iface .ifindex ,
515
+ XDP_MODE_NATIVE , 0 );
516
+ if (err ) {
517
+ pr_warn ("Couldn't attach xdp_pass program" );
518
+ xdp_program__close (pass_prog );
519
+ pass_prog = NULL ;
520
+ goto out ;
521
+ }
522
+ }
523
+
466
524
err = bpf_map_update_elem (bpf_map__fd (skel -> maps .state_map ),
467
525
& key , & bpf_state , BPF_EXIST );
468
526
if (err ) {
@@ -493,6 +551,11 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
493
551
}
494
552
495
553
out :
554
+ if (pass_prog ) {
555
+ xdp_program__detach (pass_prog , cfg -> iface .ifindex ,
556
+ XDP_MODE_NATIVE , 0 );
557
+ xdp_program__close (pass_prog );
558
+ }
496
559
xdp_program__close (prog );
497
560
xdp_trafficgen__destroy (skel );
498
561
free (runner_threads );
0 commit comments