Commit b4b8a3bf authored by Jakub Sitnicki's avatar Jakub Sitnicki Committed by Alexei Starovoitov

selftests/bpf: Convert test_flow_dissector to use BPF skeleton

Switch flow dissector test setup from custom BPF object loader to BPF
skeleton to save boilerplate and prepare for testing higher-level API for
attaching flow dissector with bpf_link.

To avoid depending on program order in the BPF object when populating the
flow dissector PROG_ARRAY map, change the program section names to contain
the program index into the map. This follows the example set by tailcall
tests.
Signed-off-by: default avatarJakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200531082846.2117903-12-jakub@cloudflare.com
parent b8215dce
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <sys/uio.h> #include <sys/uio.h>
#include "bpf_flow.skel.h"
#ifndef IP_MF #ifndef IP_MF
#define IP_MF 0x2000 #define IP_MF 0x2000
#endif #endif
...@@ -444,17 +446,54 @@ static int ifup(const char *ifname) ...@@ -444,17 +446,54 @@ static int ifup(const char *ifname)
return 0; return 0;
} }
static int init_prog_array(struct bpf_object *obj, struct bpf_map *prog_array)
{
int i, err, map_fd, prog_fd;
struct bpf_program *prog;
char prog_name[32];
map_fd = bpf_map__fd(prog_array);
if (map_fd < 0)
return -1;
for (i = 0; i < bpf_map__def(prog_array)->max_entries; i++) {
snprintf(prog_name, sizeof(prog_name), "flow_dissector/%i", i);
prog = bpf_object__find_program_by_title(obj, prog_name);
if (!prog)
return -1;
prog_fd = bpf_program__fd(prog);
if (prog_fd < 0)
return -1;
err = bpf_map_update_elem(map_fd, &i, &prog_fd, BPF_ANY);
if (err)
return -1;
}
return 0;
}
void test_flow_dissector(void) void test_flow_dissector(void)
{ {
int i, err, prog_fd, keys_fd = -1, tap_fd; int i, err, prog_fd, keys_fd = -1, tap_fd;
struct bpf_object *obj; struct bpf_flow *skel;
__u32 duration = 0; __u32 duration = 0;
err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector", skel = bpf_flow__open_and_load();
"jmp_table", "last_dissection", &prog_fd, &keys_fd); if (CHECK(!skel, "skel", "failed to open/load skeleton\n"))
if (CHECK_FAIL(err))
return; return;
prog_fd = bpf_program__fd(skel->progs._dissect);
if (CHECK(prog_fd < 0, "bpf_program__fd", "err %d\n", prog_fd))
goto out_destroy_skel;
keys_fd = bpf_map__fd(skel->maps.last_dissection);
if (CHECK(keys_fd < 0, "bpf_map__fd", "err %d\n", keys_fd))
goto out_destroy_skel;
err = init_prog_array(skel->obj, skel->maps.jmp_table);
if (CHECK(err, "init_prog_array", "err %d\n", err))
goto out_destroy_skel;
for (i = 0; i < ARRAY_SIZE(tests); i++) { for (i = 0; i < ARRAY_SIZE(tests); i++) {
struct bpf_flow_keys flow_keys; struct bpf_flow_keys flow_keys;
struct bpf_prog_test_run_attr tattr = { struct bpf_prog_test_run_attr tattr = {
...@@ -526,5 +565,6 @@ void test_flow_dissector(void) ...@@ -526,5 +565,6 @@ void test_flow_dissector(void)
close(tap_fd); close(tap_fd);
bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR); bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
bpf_object__close(obj); out_destroy_skel:
bpf_flow__destroy(skel);
} }
...@@ -20,20 +20,20 @@ ...@@ -20,20 +20,20 @@
#include <bpf/bpf_endian.h> #include <bpf/bpf_endian.h>
int _version SEC("version") = 1; int _version SEC("version") = 1;
#define PROG(F) SEC(#F) int bpf_func_##F #define PROG(F) PROG_(F, _##F)
#define PROG_(NUM, NAME) SEC("flow_dissector/"#NUM) int bpf_func##NAME
/* These are the identifiers of the BPF programs that will be used in tail /* These are the identifiers of the BPF programs that will be used in tail
* calls. Name is limited to 16 characters, with the terminating character and * calls. Name is limited to 16 characters, with the terminating character and
* bpf_func_ above, we have only 6 to work with, anything after will be cropped. * bpf_func_ above, we have only 6 to work with, anything after will be cropped.
*/ */
enum { #define IP 0
IP, #define IPV6 1
IPV6, #define IPV6OP 2 /* Destination/Hop-by-Hop Options IPv6 Ext. Header */
IPV6OP, /* Destination/Hop-by-Hop Options IPv6 Extension header */ #define IPV6FR 3 /* Fragmentation IPv6 Extension Header */
IPV6FR, /* Fragmentation IPv6 Extension Header */ #define MPLS 4
MPLS, #define VLAN 5
VLAN, #define MAX_PROG 6
};
#define IP_MF 0x2000 #define IP_MF 0x2000
#define IP_OFFSET 0x1FFF #define IP_OFFSET 0x1FFF
...@@ -59,7 +59,7 @@ struct frag_hdr { ...@@ -59,7 +59,7 @@ struct frag_hdr {
struct { struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY); __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(max_entries, 8); __uint(max_entries, MAX_PROG);
__uint(key_size, sizeof(__u32)); __uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32)); __uint(value_size, sizeof(__u32));
} jmp_table SEC(".maps"); } jmp_table SEC(".maps");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment