Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/net: test extended BPF fanout mode

Test PACKET_FANOUT_EBPF by inserting a program into the the kernel
with bpf(), then attaching it to the fanout group. Observe the same
payload-based distribution as in the PACKET_FANOUT_CBPF test.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Willem de Bruijn and committed by
David S. Miller
30da679e 95e22792

+53
+53
tools/testing/selftests/net/psock_fanout.c
··· 20 20 * - PACKET_FANOUT_CPU 21 21 * - PACKET_FANOUT_ROLLOVER 22 22 * - PACKET_FANOUT_CBPF 23 + * - PACKET_FANOUT_EBPF 23 24 * 24 25 * Todo: 25 26 * - functionality: PACKET_FANOUT_FLAG_DEFRAG ··· 46 45 #include <arpa/inet.h> 47 46 #include <errno.h> 48 47 #include <fcntl.h> 48 + #include <linux/unistd.h> /* for __NR_bpf */ 49 49 #include <linux/filter.h> 50 + #include <linux/bpf.h> 50 51 #include <linux/if_packet.h> 51 52 #include <net/ethernet.h> 52 53 #include <netinet/ip.h> ··· 93 90 94 91 pair_udp_setfilter(fd); 95 92 return fd; 93 + } 94 + 95 + static void sock_fanout_set_ebpf(int fd) 96 + { 97 + const int len_off = __builtin_offsetof(struct __sk_buff, len); 98 + struct bpf_insn prog[] = { 99 + { BPF_ALU64 | BPF_MOV | BPF_X, 6, 1, 0, 0 }, 100 + { BPF_LDX | BPF_W | BPF_MEM, 0, 6, len_off, 0 }, 101 + { BPF_JMP | BPF_JGE | BPF_K, 0, 0, 1, DATA_LEN }, 102 + { BPF_JMP | BPF_JA | BPF_K, 0, 0, 4, 0 }, 103 + { BPF_LD | BPF_B | BPF_ABS, 0, 0, 0, 0x50 }, 104 + { BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 2, DATA_CHAR }, 105 + { BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1, DATA_CHAR_1 }, 106 + { BPF_ALU | BPF_MOV | BPF_K, 0, 0, 0, 0 }, 107 + { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 } 108 + }; 109 + char log_buf[512]; 110 + union bpf_attr attr; 111 + int pfd; 112 + 113 + memset(&attr, 0, sizeof(attr)); 114 + attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 115 + attr.insns = (unsigned long) prog; 116 + attr.insn_cnt = sizeof(prog) / sizeof(prog[0]); 117 + attr.license = (unsigned long) "GPL"; 118 + attr.log_buf = (unsigned long) log_buf, 119 + attr.log_size = sizeof(log_buf), 120 + attr.log_level = 1, 121 + 122 + pfd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); 123 + if (pfd < 0) { 124 + perror("bpf"); 125 + fprintf(stderr, "bpf verifier:\n%s\n", log_buf); 126 + exit(1); 127 + } 128 + 129 + if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT_DATA, &pfd, sizeof(pfd))) { 130 + perror("fanout data ebpf"); 131 + exit(1); 132 + } 133 + 134 + if (close(pfd)) { 135 + perror("close ebpf"); 136 + exit(1); 137 + } 96 138 } 97 139 98 140 static char *sock_fanout_open_ring(int fd) ··· 271 223 } 272 224 if (type == PACKET_FANOUT_CBPF) 273 225 sock_setfilter(fds[0], SOL_PACKET, PACKET_FANOUT_DATA); 226 + else if (type == PACKET_FANOUT_EBPF) 227 + sock_fanout_set_ebpf(fds[0]); 274 228 275 229 rings[0] = sock_fanout_open_ring(fds[0]); 276 230 rings[1] = sock_fanout_open_ring(fds[1]); ··· 351 301 port_off, expect_lb[0], expect_lb[1]); 352 302 ret |= test_datapath(PACKET_FANOUT_ROLLOVER, 353 303 port_off, expect_rb[0], expect_rb[1]); 304 + 354 305 ret |= test_datapath(PACKET_FANOUT_CBPF, 306 + port_off, expect_bpf[0], expect_bpf[1]); 307 + ret |= test_datapath(PACKET_FANOUT_EBPF, 355 308 port_off, expect_bpf[0], expect_bpf[1]); 356 309 357 310 set_cpuaffinity(0);