Skip to content

Commit

Permalink
filterc: Test more programs
Browse files Browse the repository at this point in the history
Compile a bunch of programs and check if they pass/fail as expected.

Signed-off-by: Felix Maurer <[email protected]>
  • Loading branch information
fmaurer-rh committed Oct 16, 2023
1 parent 15bf137 commit 0be7232
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 27 deletions.
5 changes: 5 additions & 0 deletions filterc/tests/test-filterc.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ALL_TESTS="\
test_bpfc_standalone \
test_bpfc_linked \
test_bpfc_filters \
"

test_bpfc="tests/test_bpfc"
Expand All @@ -12,3 +13,7 @@ test_bpfc_standalone() {
test_bpfc_linked() {
$test_bpfc test_linked
}

test_bpfc_filters() {
$test_bpfc test_filters
}
181 changes: 154 additions & 27 deletions filterc/tests/test_bpfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,25 +168,64 @@ static struct bpf_object *link_filter(char *filter)
return bpf_obj;
}

int build_udp_packet(void *pkt, int len, int dst_port)
void *insert_eth(void *pkt, int proto)
{
struct ethhdr *eh = pkt;
struct iphdr *iph = (struct iphdr *)(eh + 1);
struct udphdr *udph = (struct udphdr *)(iph + 1);
eh->h_proto = htons(proto);

memset(pkt, 0, len);
return (void *)(eh + 1);
}

struct vlan_hdr {
__be16 h_vlan_TCI;
__be16 h_vlan_encapsulated_proto;
};

eh->h_proto = htons(ETH_P_IP);
void *insert_vlan(void *pkt, int vlan_id, int proto)
{
struct vlan_hdr *vlanh = pkt;
vlanh->h_vlan_TCI = htons(vlan_id);
vlanh->h_vlan_encapsulated_proto = htons(proto);

return (vlanh + 1);
}

iph->protocol = IPPROTO_UDP;
void *insert_ipv4(void *pkt, int proto)
{
struct iphdr *iph = pkt;
iph->protocol = proto;
iph->ihl = 5;

return (iph + 1);
}

void *insert_udp(void *pkt, int dst_port)
{
struct udphdr *udph = pkt;
udph->source = htons(54321);
udph->dest = htons(dst_port);
return (udph + 1);
}

return 0;
void build_vlan_udp_packet(void *pkt, int len, int vlan_id, int dst_port)
{
memset(pkt, 0, len);
pkt = insert_eth(pkt, ETH_P_8021Q);
pkt = insert_vlan(pkt, vlan_id, ETH_P_IP);
pkt = insert_ipv4(pkt, IPPROTO_UDP);
insert_udp(pkt, dst_port);
}

void build_udp_packet(void *pkt, int len, int dst_port)
{
memset(pkt, 0, len);
pkt = insert_eth(pkt, ETH_P_IP);
pkt = insert_ipv4(pkt, IPPROTO_UDP);
insert_udp(pkt, dst_port);
}



TEST_FUNC(standalone)
{
struct bpf_object *bpf_obj;
Expand Down Expand Up @@ -214,11 +253,8 @@ TEST_FUNC(standalone)
}
prog_fd = bpf_program__fd(bpf_prog);

err = build_udp_packet(pkt, len, 53);
if (err) {
printf("Failed to build packet (%d)\n", err);
return 1;
}
build_udp_packet(pkt, len, 53);

DECLARE_LIBBPF_OPTS(bpf_test_run_opts, test_opts,
.data_in = pkt,
.data_size_in = len);
Expand All @@ -233,11 +269,8 @@ TEST_FUNC(standalone)
return 1;
}

err = build_udp_packet(pkt, len, 123);
if (err) {
printf("Failed to build packet (%d)\n", err);
return 1;
}
build_udp_packet(pkt, len, 123);

err = bpf_prog_test_run_opts(prog_fd, &test_opts);
if (err) {
printf("Failed to run bpf prog (%d)\n", err);
Expand Down Expand Up @@ -280,11 +313,8 @@ TEST_FUNC(linked)
}
prog_fd = bpf_program__fd(bpf_prog);

err = build_udp_packet(pkt, len, 53);
if (err) {
printf("Failed to build packet (%d)\n", err);
return 1;
}
build_udp_packet(pkt, len, 53);

DECLARE_LIBBPF_OPTS(bpf_test_run_opts, test_opts,
.data_in = pkt,
.data_size_in = len);
Expand All @@ -299,11 +329,8 @@ TEST_FUNC(linked)
return 1;
}

err = build_udp_packet(pkt, len, 123);
if (err) {
printf("Failed to build packet (%d)\n", err);
return 1;
}
build_udp_packet(pkt, len, 123);

err = bpf_prog_test_run_opts(prog_fd, &test_opts);
if (err) {
printf("Failed to run bpf prog (%d)\n", err);
Expand All @@ -319,9 +346,109 @@ TEST_FUNC(linked)
return 0;
}

typedef void (*pkt_func)(void *, int);
#define PKT_FUNC(fn) void pkt_##fn(void *pkt, int len)

PKT_FUNC(udp53) {
build_udp_packet(pkt, len, 53);
}

PKT_FUNC(udp123) {
build_udp_packet(pkt, len, 123);
}

PKT_FUNC(vlan42_udp53) {
build_vlan_udp_packet(pkt, len, 42, 53);
}

PKT_FUNC(vlan42_udp123) {
build_vlan_udp_packet(pkt, len, 42, 123);
}

PKT_FUNC(vlan100_udp53) {
build_vlan_udp_packet(pkt, len, 100, 53);
}

struct test_filter {
char *filter;
pkt_func good_pkt;
pkt_func bad_pkt;
} test_filters[] = {
{"udp port 53", pkt_udp53, pkt_udp123},
{"vlan 42 and udp port 53", pkt_vlan42_udp53, pkt_vlan100_udp53},
{"vlan 42 and udp port 53", pkt_vlan42_udp53, pkt_udp53},
{"udp port 53 or (vlan and udp port 53)", pkt_udp53, pkt_udp123},
{"udp port 53 or (vlan and udp port 53)", pkt_vlan42_udp53, pkt_vlan42_udp123},
{NULL, NULL, NULL},
};

TEST_FUNC(filters)
{
struct bpf_object *bpf_obj;
struct bpf_program *bpf_prog;
struct test_filter *test;
int err, prog_fd, i = 0, len = 256;
void *pkt = malloc(len);
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, test_opts,
.data_in = pkt,
.data_size_in = len);

while (test_filters[i].filter) {
test = &test_filters[i];
bpf_obj = compile_filter(test->filter);
if (!bpf_obj) {
printf("%d: Failed to compile and open filter'\n", i);
return 1;
}

err = bpf_object__load(bpf_obj);
if (err) {
printf("%d: Failed to load bpf object\n", i);
return 1;
}

bpf_prog = bpf_object__find_program_by_name(bpf_obj, TEST_PROG_NAME);
if (!bpf_prog) {
printf("%d: Failed to find bpf program in object\n", i);
return 1;
}
prog_fd = bpf_program__fd(bpf_prog);

test->good_pkt(pkt, len);
err = bpf_prog_test_run_opts(prog_fd, &test_opts);
if (err) {
printf("%d: Failed to run bpf prog (%d)\n", i, err);
return 1;
}
if (test_opts.retval != XDP_PASS) {
printf("%d: Unexpected return value %d, expected XDP_PASS\n",
i, test_opts.retval);
return 1;
}

test->bad_pkt(pkt, len);
err = bpf_prog_test_run_opts(prog_fd, &test_opts);
if (err) {
printf("%d: Failed to run bpf prog (%d)\n", i, err);
return 1;
}
if (test_opts.retval != XDP_DROP) {
printf("%d: Unexpected return value %d, expected XDP_DROP\n",
i, test_opts.retval);
return 1;
}

i++;
}

free(pkt);
return 0;
}

static const struct prog_command cmds[] = {
TEST(standalone),
TEST(linked),
TEST(filters),
END_COMMANDS
};

Expand Down

0 comments on commit 0be7232

Please sign in to comment.