169 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <test_progs.h>3#include <network_helpers.h>4#include <bpf/btf.h>5#include <linux/if_link.h>6#include <linux/udp.h>7#include <net/if.h>8#include <unistd.h>9 10#include "xdp_flowtable.skel.h"11 12#define TX_NETNS_NAME "ns0"13#define RX_NETNS_NAME "ns1"14 15#define TX_NAME "v0"16#define FORWARD_NAME "v1"17#define RX_NAME "d0"18 19#define TX_MAC "00:00:00:00:00:01"20#define FORWARD_MAC "00:00:00:00:00:02"21#define RX_MAC "00:00:00:00:00:03"22#define DST_MAC "00:00:00:00:00:04"23 24#define TX_ADDR "10.0.0.1"25#define FORWARD_ADDR "10.0.0.2"26#define RX_ADDR "20.0.0.1"27#define DST_ADDR "20.0.0.2"28 29#define PREFIX_LEN "8"30#define N_PACKETS 1031#define UDP_PORT 1234532#define UDP_PORT_STR "12345"33 34static int send_udp_traffic(void)35{36 struct sockaddr_storage addr;37 int i, sock;38 39 if (make_sockaddr(AF_INET, DST_ADDR, UDP_PORT, &addr, NULL))40 return -EINVAL;41 42 sock = socket(AF_INET, SOCK_DGRAM, 0);43 if (sock < 0)44 return sock;45 46 for (i = 0; i < N_PACKETS; i++) {47 unsigned char buf[] = { 0xaa, 0xbb, 0xcc };48 int n;49 50 n = sendto(sock, buf, sizeof(buf), MSG_NOSIGNAL | MSG_CONFIRM,51 (struct sockaddr *)&addr, sizeof(addr));52 if (n != sizeof(buf)) {53 close(sock);54 return -EINVAL;55 }56 57 usleep(50000); /* 50ms */58 }59 close(sock);60 61 return 0;62}63 64void test_xdp_flowtable(void)65{66 struct xdp_flowtable *skel = NULL;67 struct nstoken *tok = NULL;68 int iifindex, stats_fd;69 __u32 value, key = 0;70 struct bpf_link *link;71 72 if (SYS_NOFAIL("nft -v")) {73 fprintf(stdout, "Missing required nft tool\n");74 test__skip();75 return;76 }77 78 SYS(out, "ip netns add " TX_NETNS_NAME);79 SYS(out, "ip netns add " RX_NETNS_NAME);80 81 tok = open_netns(RX_NETNS_NAME);82 if (!ASSERT_OK_PTR(tok, "setns"))83 goto out;84 85 SYS(out, "sysctl -qw net.ipv4.conf.all.forwarding=1");86 87 SYS(out, "ip link add " TX_NAME " type veth peer " FORWARD_NAME);88 SYS(out, "ip link set " TX_NAME " netns " TX_NETNS_NAME);89 SYS(out, "ip link set dev " FORWARD_NAME " address " FORWARD_MAC);90 SYS(out,91 "ip addr add " FORWARD_ADDR "/" PREFIX_LEN " dev " FORWARD_NAME);92 SYS(out, "ip link set dev " FORWARD_NAME " up");93 94 SYS(out, "ip link add " RX_NAME " type dummy");95 SYS(out, "ip link set dev " RX_NAME " address " RX_MAC);96 SYS(out, "ip addr add " RX_ADDR "/" PREFIX_LEN " dev " RX_NAME);97 SYS(out, "ip link set dev " RX_NAME " up");98 99 /* configure the flowtable */100 SYS(out, "nft add table ip filter");101 SYS(out,102 "nft add flowtable ip filter f { hook ingress priority 0\\; "103 "devices = { " FORWARD_NAME ", " RX_NAME " }\\; }");104 SYS(out,105 "nft add chain ip filter forward "106 "{ type filter hook forward priority 0\\; }");107 SYS(out,108 "nft add rule ip filter forward ip protocol udp th dport "109 UDP_PORT_STR " flow add @f");110 111 /* Avoid ARP calls */112 SYS(out,113 "ip -4 neigh add " DST_ADDR " lladdr " DST_MAC " dev " RX_NAME);114 115 close_netns(tok);116 tok = open_netns(TX_NETNS_NAME);117 if (!ASSERT_OK_PTR(tok, "setns"))118 goto out;119 120 SYS(out, "ip addr add " TX_ADDR "/" PREFIX_LEN " dev " TX_NAME);121 SYS(out, "ip link set dev " TX_NAME " address " TX_MAC);122 SYS(out, "ip link set dev " TX_NAME " up");123 SYS(out, "ip route add default via " FORWARD_ADDR);124 125 close_netns(tok);126 tok = open_netns(RX_NETNS_NAME);127 if (!ASSERT_OK_PTR(tok, "setns"))128 goto out;129 130 iifindex = if_nametoindex(FORWARD_NAME);131 if (!ASSERT_NEQ(iifindex, 0, "iifindex"))132 goto out;133 134 skel = xdp_flowtable__open_and_load();135 if (!ASSERT_OK_PTR(skel, "skel"))136 goto out;137 138 link = bpf_program__attach_xdp(skel->progs.xdp_flowtable_do_lookup,139 iifindex);140 if (!ASSERT_OK_PTR(link, "prog_attach"))141 goto out;142 143 close_netns(tok);144 tok = open_netns(TX_NETNS_NAME);145 if (!ASSERT_OK_PTR(tok, "setns"))146 goto out;147 148 if (!ASSERT_OK(send_udp_traffic(), "send udp"))149 goto out;150 151 close_netns(tok);152 tok = open_netns(RX_NETNS_NAME);153 if (!ASSERT_OK_PTR(tok, "setns"))154 goto out;155 156 stats_fd = bpf_map__fd(skel->maps.stats);157 if (!ASSERT_OK(bpf_map_lookup_elem(stats_fd, &key, &value),158 "bpf_map_update_elem stats"))159 goto out;160 161 ASSERT_GE(value, N_PACKETS - 2, "bpf_xdp_flow_lookup failed");162out:163 xdp_flowtable__destroy(skel);164 if (tok)165 close_netns(tok);166 SYS_NOFAIL("ip netns del " TX_NETNS_NAME);167 SYS_NOFAIL("ip netns del " RX_NETNS_NAME);168}169