|
11 | 11 | #include <bpf/bpf_endian.h>
|
12 | 12 | #include <uapi/linux/netdev.h>
|
13 | 13 | #include "test_xdp_do_redirect.skel.h"
|
| 14 | +#include "xdp_dummy.skel.h" |
14 | 15 |
|
15 | 16 | struct udp_packet {
|
16 | 17 | struct ethhdr eth;
|
@@ -246,3 +247,166 @@ void test_xdp_do_redirect(void)
|
246 | 247 | SYS_NOFAIL("ip netns del testns");
|
247 | 248 | test_xdp_do_redirect__destroy(skel);
|
248 | 249 | }
|
| 250 | + |
| 251 | +#define NS_NB 3 |
| 252 | +#define NS0 "NS0" |
| 253 | +#define NS1 "NS1" |
| 254 | +#define NS2 "NS2" |
| 255 | +#define IPV4_NETWORK "10.1.1" |
| 256 | +#define VETH1_INDEX 111 |
| 257 | +#define VETH2_INDEX 222 |
| 258 | + |
| 259 | +struct test_data { |
| 260 | + struct netns_obj *ns[NS_NB]; |
| 261 | + u32 xdp_flags; |
| 262 | +}; |
| 263 | + |
| 264 | +static void cleanup(struct test_data *data) |
| 265 | +{ |
| 266 | + int i; |
| 267 | + |
| 268 | + for (i = 0; i < NS_NB; i++) |
| 269 | + netns_free(data->ns[i]); |
| 270 | +} |
| 271 | + |
| 272 | +/** |
| 273 | + * ping_setup - |
| 274 | + * Create two veth peers and forward packets in-between using XDP |
| 275 | + * |
| 276 | + * ------------ ------------ |
| 277 | + * | NS1 | | NS2 | |
| 278 | + * | veth0 | | veth0 | |
| 279 | + * | 10.1.1.1 | | 10.1.1.2 | |
| 280 | + * -----|------ ------|----- |
| 281 | + * | | |
| 282 | + * | | |
| 283 | + * -----|-----------------------|------- |
| 284 | + * | veth1 veth2 | |
| 285 | + * | (id:111) (id:222) | |
| 286 | + * | | | | |
| 287 | + * | ----- xdp forwarding ----- | |
| 288 | + * | | |
| 289 | + * | NS0 | |
| 290 | + * ------------------------------------- |
| 291 | + */ |
| 292 | +static int ping_setup(struct test_data *data) |
| 293 | +{ |
| 294 | + int i; |
| 295 | + |
| 296 | + data->ns[0] = netns_new(NS0, false); |
| 297 | + if (!ASSERT_OK_PTR(data->ns[0], "create ns")) |
| 298 | + return -1; |
| 299 | + |
| 300 | + for (i = 1; i < NS_NB; i++) { |
| 301 | + char ns_name[4] = {}; |
| 302 | + |
| 303 | + snprintf(ns_name, 4, "NS%d", i); |
| 304 | + data->ns[i] = netns_new(ns_name, false); |
| 305 | + if (!ASSERT_OK_PTR(data->ns[i], "create ns")) |
| 306 | + goto fail; |
| 307 | + |
| 308 | + SYS(fail, |
| 309 | + "ip -n %s link add veth%d index %d%d%d type veth peer name veth0 netns %s", |
| 310 | + NS0, i, i, i, i, ns_name); |
| 311 | + SYS(fail, "ip -n %s link set veth%d up", NS0, i); |
| 312 | + |
| 313 | + SYS(fail, "ip -n %s addr add %s.%d/24 dev veth0", ns_name, IPV4_NETWORK, i); |
| 314 | + SYS(fail, "ip -n %s link set veth0 up", ns_name); |
| 315 | + } |
| 316 | + |
| 317 | + return 0; |
| 318 | + |
| 319 | +fail: |
| 320 | + cleanup(data); |
| 321 | + return -1; |
| 322 | +} |
| 323 | + |
| 324 | +static void ping_test(struct test_data *data) |
| 325 | +{ |
| 326 | + struct test_xdp_do_redirect *skel = NULL; |
| 327 | + struct xdp_dummy *skel_dummy = NULL; |
| 328 | + struct nstoken *nstoken = NULL; |
| 329 | + int i, ret; |
| 330 | + |
| 331 | + skel_dummy = xdp_dummy__open_and_load(); |
| 332 | + if (!ASSERT_OK_PTR(skel_dummy, "open and load xdp_dummy skeleton")) |
| 333 | + goto close; |
| 334 | + |
| 335 | + for (i = 1; i < NS_NB; i++) { |
| 336 | + char ns_name[4] = {}; |
| 337 | + |
| 338 | + snprintf(ns_name, 4, "NS%d", i); |
| 339 | + nstoken = open_netns(ns_name); |
| 340 | + if (!ASSERT_OK_PTR(nstoken, "open ns")) |
| 341 | + goto close; |
| 342 | + |
| 343 | + ret = bpf_xdp_attach(if_nametoindex("veth0"), |
| 344 | + bpf_program__fd(skel_dummy->progs.xdp_dummy_prog), |
| 345 | + data->xdp_flags, NULL); |
| 346 | + if (!ASSERT_GE(ret, 0, "bpf_xdp_attach dummy_prog")) |
| 347 | + goto close; |
| 348 | + |
| 349 | + close_netns(nstoken); |
| 350 | + nstoken = NULL; |
| 351 | + } |
| 352 | + |
| 353 | + skel = test_xdp_do_redirect__open_and_load(); |
| 354 | + if (!ASSERT_OK_PTR(skel, "open and load skeleton")) |
| 355 | + goto close; |
| 356 | + |
| 357 | + nstoken = open_netns(NS0); |
| 358 | + if (!ASSERT_OK_PTR(nstoken, "open NS0")) |
| 359 | + goto close; |
| 360 | + |
| 361 | + ret = bpf_xdp_attach(VETH2_INDEX, |
| 362 | + bpf_program__fd(skel->progs.xdp_redirect_to_111), |
| 363 | + data->xdp_flags, NULL); |
| 364 | + if (!ASSERT_GE(ret, 0, "bpf_xdp_attach")) |
| 365 | + goto close; |
| 366 | + |
| 367 | + ret = bpf_xdp_attach(VETH1_INDEX, |
| 368 | + bpf_program__fd(skel->progs.xdp_redirect_to_222), |
| 369 | + data->xdp_flags, NULL); |
| 370 | + if (!ASSERT_GE(ret, 0, "bpf_xdp_attach")) |
| 371 | + goto close; |
| 372 | + |
| 373 | + close_netns(nstoken); |
| 374 | + nstoken = NULL; |
| 375 | + |
| 376 | + nstoken = open_netns(NS1); |
| 377 | + if (!ASSERT_OK_PTR(nstoken, "open NS1")) |
| 378 | + goto close; |
| 379 | + |
| 380 | + SYS(close, "ping -c 1 %s.2 > /dev/null", IPV4_NETWORK); |
| 381 | + |
| 382 | +close: |
| 383 | + close_netns(nstoken); |
| 384 | + xdp_dummy__destroy(skel_dummy); |
| 385 | + test_xdp_do_redirect__destroy(skel); |
| 386 | +} |
| 387 | + |
| 388 | + |
| 389 | +static void xdp_redirect_ping(u32 xdp_flags) |
| 390 | +{ |
| 391 | + struct test_data data = {}; |
| 392 | + |
| 393 | + if (ping_setup(&data) < 0) |
| 394 | + return; |
| 395 | + |
| 396 | + data.xdp_flags = xdp_flags; |
| 397 | + ping_test(&data); |
| 398 | + cleanup(&data); |
| 399 | +} |
| 400 | + |
| 401 | +void test_xdp_index_redirect(void) |
| 402 | +{ |
| 403 | + if (test__start_subtest("noflag")) |
| 404 | + xdp_redirect_ping(0); |
| 405 | + |
| 406 | + if (test__start_subtest("drvflag")) |
| 407 | + xdp_redirect_ping(XDP_FLAGS_DRV_MODE); |
| 408 | + |
| 409 | + if (test__start_subtest("skbflag")) |
| 410 | + xdp_redirect_ping(XDP_FLAGS_SKB_MODE); |
| 411 | +} |
| 412 | + |
0 commit comments