1 // SPDX-License-Identifier: GPL-2.0 2 #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 10 31 #define UDP_PORT 12345 32 #define UDP_PORT_STR "12345" 33 34 static 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 64 void 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"); 162 out: 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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.