Skip to content

Commit 1dad1d6

Browse files
committed
xdp-trafficgen: Load a dummy XDP program if needed
Add logic in xdp-trafficgen to load a dummy XDP program on devices that need this to be able to send packets via ndo_xdp_xmit(). We use a hard-coded list of driver names to determine if an interface needs such an XDP program, and check the XDP feature flags to skip the loading if the NDO_XMIT feature is already set. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
1 parent d527fc0 commit 1dad1d6

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

xdp-trafficgen/xdp-trafficgen.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/in6.h>
3232
#include <linux/udp.h>
3333
#include <linux/tcp.h>
34+
#include <linux/netdev.h>
3435

3536
#include "params.h"
3637
#include "logging.h"
@@ -54,6 +55,42 @@ DEFINE_SAMPLE_INIT(xdp_trafficgen);
5455

5556
static bool status_exited = false;
5657

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+
5794
struct udp_packet {
5895
struct ethhdr eth;
5996
struct ipv6hdr iph;
@@ -400,6 +437,7 @@ static struct prog_option udp_options[] = {
400437

401438
int do_udp(const void *opt, __unused const char *pin_root_path)
402439
{
440+
struct xdp_program *prog = NULL, *pass_prog = NULL;
403441
const struct udpopt *cfg = opt;
404442

405443
DECLARE_LIBXDP_OPTS(xdp_program_opts, opts);
@@ -411,7 +449,6 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
411449
struct xdp_trafficgen *skel = NULL;
412450
struct udp_packet *payload = NULL;
413451
pthread_t *runner_threads = NULL;
414-
struct xdp_program *prog = NULL;
415452
int err = 0, i;
416453
char buf[100];
417454
__u32 key = 0;
@@ -459,10 +496,31 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
459496
goto out;
460497
}
461498

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+
462509
err = xdp_trafficgen__load(skel);
463510
if (err)
464511
goto out;
465512

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+
466524
err = bpf_map_update_elem(bpf_map__fd(skel->maps.state_map),
467525
&key, &bpf_state, BPF_EXIST);
468526
if (err) {
@@ -493,6 +551,11 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
493551
}
494552

495553
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+
}
496559
xdp_program__close(prog);
497560
xdp_trafficgen__destroy(skel);
498561
free(runner_threads);

xdp-trafficgen/xdp_trafficgen.bpf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,9 @@ int xdp_redirect_send_tcp(struct xdp_md *ctx)
356356
ret:
357357
return action;
358358
}
359+
360+
SEC("xdp")
361+
int xdp_pass(struct xdp_md *ctx)
362+
{
363+
return XDP_PASS;
364+
}

0 commit comments

Comments
 (0)