diff options
author | Willem de Bruijn <willemb@google.com> | 2015-08-14 22:31:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-17 17:22:48 -0400 |
commit | 30da679e679dbe7bb103c5d9c137ec5a070b7150 (patch) | |
tree | b2a932691177a1608f4c91016eea0a71c244987f /tools/testing/selftests/net | |
parent | 95e22792fa5460e579a69171777ff79d8725be29 (diff) |
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>
Diffstat (limited to 'tools/testing/selftests/net')
-rw-r--r-- | tools/testing/selftests/net/psock_fanout.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/tools/testing/selftests/net/psock_fanout.c b/tools/testing/selftests/net/psock_fanout.c index baf46a20e1b3..412459369686 100644 --- a/tools/testing/selftests/net/psock_fanout.c +++ b/tools/testing/selftests/net/psock_fanout.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * - PACKET_FANOUT_CPU | 20 | * - PACKET_FANOUT_CPU |
21 | * - PACKET_FANOUT_ROLLOVER | 21 | * - PACKET_FANOUT_ROLLOVER |
22 | * - PACKET_FANOUT_CBPF | 22 | * - PACKET_FANOUT_CBPF |
23 | * - PACKET_FANOUT_EBPF | ||
23 | * | 24 | * |
24 | * Todo: | 25 | * Todo: |
25 | * - functionality: PACKET_FANOUT_FLAG_DEFRAG | 26 | * - functionality: PACKET_FANOUT_FLAG_DEFRAG |
@@ -45,7 +46,9 @@ | |||
45 | #include <arpa/inet.h> | 46 | #include <arpa/inet.h> |
46 | #include <errno.h> | 47 | #include <errno.h> |
47 | #include <fcntl.h> | 48 | #include <fcntl.h> |
49 | #include <linux/unistd.h> /* for __NR_bpf */ | ||
48 | #include <linux/filter.h> | 50 | #include <linux/filter.h> |
51 | #include <linux/bpf.h> | ||
49 | #include <linux/if_packet.h> | 52 | #include <linux/if_packet.h> |
50 | #include <net/ethernet.h> | 53 | #include <net/ethernet.h> |
51 | #include <netinet/ip.h> | 54 | #include <netinet/ip.h> |
@@ -92,6 +95,51 @@ static int sock_fanout_open(uint16_t typeflags, int num_packets) | |||
92 | return fd; | 95 | return fd; |
93 | } | 96 | } |
94 | 97 | ||
98 | static void sock_fanout_set_ebpf(int fd) | ||
99 | { | ||
100 | const int len_off = __builtin_offsetof(struct __sk_buff, len); | ||
101 | struct bpf_insn prog[] = { | ||
102 | { BPF_ALU64 | BPF_MOV | BPF_X, 6, 1, 0, 0 }, | ||
103 | { BPF_LDX | BPF_W | BPF_MEM, 0, 6, len_off, 0 }, | ||
104 | { BPF_JMP | BPF_JGE | BPF_K, 0, 0, 1, DATA_LEN }, | ||
105 | { BPF_JMP | BPF_JA | BPF_K, 0, 0, 4, 0 }, | ||
106 | { BPF_LD | BPF_B | BPF_ABS, 0, 0, 0, 0x50 }, | ||
107 | { BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 2, DATA_CHAR }, | ||
108 | { BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1, DATA_CHAR_1 }, | ||
109 | { BPF_ALU | BPF_MOV | BPF_K, 0, 0, 0, 0 }, | ||
110 | { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 } | ||
111 | }; | ||
112 | char log_buf[512]; | ||
113 | union bpf_attr attr; | ||
114 | int pfd; | ||
115 | |||
116 | memset(&attr, 0, sizeof(attr)); | ||
117 | attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; | ||
118 | attr.insns = (unsigned long) prog; | ||
119 | attr.insn_cnt = sizeof(prog) / sizeof(prog[0]); | ||
120 | attr.license = (unsigned long) "GPL"; | ||
121 | attr.log_buf = (unsigned long) log_buf, | ||
122 | attr.log_size = sizeof(log_buf), | ||
123 | attr.log_level = 1, | ||
124 | |||
125 | pfd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); | ||
126 | if (pfd < 0) { | ||
127 | perror("bpf"); | ||
128 | fprintf(stderr, "bpf verifier:\n%s\n", log_buf); | ||
129 | exit(1); | ||
130 | } | ||
131 | |||
132 | if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT_DATA, &pfd, sizeof(pfd))) { | ||
133 | perror("fanout data ebpf"); | ||
134 | exit(1); | ||
135 | } | ||
136 | |||
137 | if (close(pfd)) { | ||
138 | perror("close ebpf"); | ||
139 | exit(1); | ||
140 | } | ||
141 | } | ||
142 | |||
95 | static char *sock_fanout_open_ring(int fd) | 143 | static char *sock_fanout_open_ring(int fd) |
96 | { | 144 | { |
97 | struct tpacket_req req = { | 145 | struct tpacket_req req = { |
@@ -223,6 +271,8 @@ static int test_datapath(uint16_t typeflags, int port_off, | |||
223 | } | 271 | } |
224 | if (type == PACKET_FANOUT_CBPF) | 272 | if (type == PACKET_FANOUT_CBPF) |
225 | sock_setfilter(fds[0], SOL_PACKET, PACKET_FANOUT_DATA); | 273 | sock_setfilter(fds[0], SOL_PACKET, PACKET_FANOUT_DATA); |
274 | else if (type == PACKET_FANOUT_EBPF) | ||
275 | sock_fanout_set_ebpf(fds[0]); | ||
226 | 276 | ||
227 | rings[0] = sock_fanout_open_ring(fds[0]); | 277 | rings[0] = sock_fanout_open_ring(fds[0]); |
228 | rings[1] = sock_fanout_open_ring(fds[1]); | 278 | rings[1] = sock_fanout_open_ring(fds[1]); |
@@ -301,8 +351,11 @@ int main(int argc, char **argv) | |||
301 | port_off, expect_lb[0], expect_lb[1]); | 351 | port_off, expect_lb[0], expect_lb[1]); |
302 | ret |= test_datapath(PACKET_FANOUT_ROLLOVER, | 352 | ret |= test_datapath(PACKET_FANOUT_ROLLOVER, |
303 | port_off, expect_rb[0], expect_rb[1]); | 353 | port_off, expect_rb[0], expect_rb[1]); |
354 | |||
304 | ret |= test_datapath(PACKET_FANOUT_CBPF, | 355 | ret |= test_datapath(PACKET_FANOUT_CBPF, |
305 | port_off, expect_bpf[0], expect_bpf[1]); | 356 | port_off, expect_bpf[0], expect_bpf[1]); |
357 | ret |= test_datapath(PACKET_FANOUT_EBPF, | ||
358 | port_off, expect_bpf[0], expect_bpf[1]); | ||
306 | 359 | ||
307 | set_cpuaffinity(0); | 360 | set_cpuaffinity(0); |
308 | ret |= test_datapath(PACKET_FANOUT_CPU, port_off, | 361 | ret |= test_datapath(PACKET_FANOUT_CPU, port_off, |