-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: test bpf flow dissection
Adds a test that sends different types of packets over multiple tunnels and verifies that valid packets are dissected correctly. To do so, a tc-flower rule is added to drop packets on UDP src port 9, and packets are sent from ports 8, 9, and 10. Only the packets on port 9 should be dropped. Because tc-flower relies on the flow dissector to match flows, correct classification demonstrates correct dissection. Also add support logic to load the BPF program and to inject the test packets. Signed-off-by: Petar Penkov <ppenkov@google.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Petar Penkov
authored and
Alexei Starovoitov
committed
Sep 14, 2018
1 parent
9c98b13
commit 50b3ed5
Showing
8 changed files
with
1,134 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,4 @@ CONFIG_CRYPTO_HMAC=m | |
CONFIG_CRYPTO_SHA256=m | ||
CONFIG_VXLAN=y | ||
CONFIG_GENEVE=y | ||
CONFIG_NET_CLS_FLOWER=m |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
#include <error.h> | ||
#include <errno.h> | ||
#include <getopt.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/stat.h> | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <bpf/bpf.h> | ||
#include <bpf/libbpf.h> | ||
|
||
const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector"; | ||
const char *cfg_map_name = "jmp_table"; | ||
bool cfg_attach = true; | ||
char *cfg_section_name; | ||
char *cfg_path_name; | ||
|
||
static void load_and_attach_program(void) | ||
{ | ||
struct bpf_program *prog, *main_prog; | ||
struct bpf_map *prog_array; | ||
int i, fd, prog_fd, ret; | ||
struct bpf_object *obj; | ||
int prog_array_fd; | ||
|
||
ret = bpf_prog_load(cfg_path_name, BPF_PROG_TYPE_FLOW_DISSECTOR, &obj, | ||
&prog_fd); | ||
if (ret) | ||
error(1, 0, "bpf_prog_load %s", cfg_path_name); | ||
|
||
main_prog = bpf_object__find_program_by_title(obj, cfg_section_name); | ||
if (!main_prog) | ||
error(1, 0, "bpf_object__find_program_by_title %s", | ||
cfg_section_name); | ||
|
||
prog_fd = bpf_program__fd(main_prog); | ||
if (prog_fd < 0) | ||
error(1, 0, "bpf_program__fd"); | ||
|
||
prog_array = bpf_object__find_map_by_name(obj, cfg_map_name); | ||
if (!prog_array) | ||
error(1, 0, "bpf_object__find_map_by_name %s", cfg_map_name); | ||
|
||
prog_array_fd = bpf_map__fd(prog_array); | ||
if (prog_array_fd < 0) | ||
error(1, 0, "bpf_map__fd %s", cfg_map_name); | ||
|
||
i = 0; | ||
bpf_object__for_each_program(prog, obj) { | ||
fd = bpf_program__fd(prog); | ||
if (fd < 0) | ||
error(1, 0, "bpf_program__fd"); | ||
|
||
if (fd != prog_fd) { | ||
printf("%d: %s\n", i, bpf_program__title(prog, false)); | ||
bpf_map_update_elem(prog_array_fd, &i, &fd, BPF_ANY); | ||
++i; | ||
} | ||
} | ||
|
||
ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0); | ||
if (ret) | ||
error(1, 0, "bpf_prog_attach %s", cfg_path_name); | ||
|
||
ret = bpf_object__pin(obj, cfg_pin_path); | ||
if (ret) | ||
error(1, 0, "bpf_object__pin %s", cfg_pin_path); | ||
|
||
} | ||
|
||
static void detach_program(void) | ||
{ | ||
char command[64]; | ||
int ret; | ||
|
||
ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR); | ||
if (ret) | ||
error(1, 0, "bpf_prog_detach"); | ||
|
||
/* To unpin, it is necessary and sufficient to just remove this dir */ | ||
sprintf(command, "rm -r %s", cfg_pin_path); | ||
ret = system(command); | ||
if (ret) | ||
error(1, errno, command); | ||
} | ||
|
||
static void parse_opts(int argc, char **argv) | ||
{ | ||
bool attach = false; | ||
bool detach = false; | ||
int c; | ||
|
||
while ((c = getopt(argc, argv, "adp:s:")) != -1) { | ||
switch (c) { | ||
case 'a': | ||
if (detach) | ||
error(1, 0, "attach/detach are exclusive"); | ||
attach = true; | ||
break; | ||
case 'd': | ||
if (attach) | ||
error(1, 0, "attach/detach are exclusive"); | ||
detach = true; | ||
break; | ||
case 'p': | ||
if (cfg_path_name) | ||
error(1, 0, "only one prog name can be given"); | ||
|
||
cfg_path_name = optarg; | ||
break; | ||
case 's': | ||
if (cfg_section_name) | ||
error(1, 0, "only one section can be given"); | ||
|
||
cfg_section_name = optarg; | ||
break; | ||
} | ||
} | ||
|
||
if (detach) | ||
cfg_attach = false; | ||
|
||
if (cfg_attach && !cfg_path_name) | ||
error(1, 0, "must provide a path to the BPF program"); | ||
|
||
if (cfg_attach && !cfg_section_name) | ||
error(1, 0, "must provide a section name"); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
parse_opts(argc, argv); | ||
if (cfg_attach) | ||
load_and_attach_program(); | ||
else | ||
detach_program(); | ||
return 0; | ||
} |
Oops, something went wrong.