aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/prog_tests/bpf_qdisc.c
blob: 230d8f935303b20d83799b3723f3d6b954772fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-License-Identifier: GPL-2.0

#include <linux/pkt_sched.h>
#include <linux/rtnetlink.h>
#include <test_progs.h>

#include "network_helpers.h"
#include "bpf_qdisc_fifo.skel.h"
#include "bpf_qdisc_fq.skel.h"

#define LO_IFINDEX 1

static const unsigned int total_bytes = 10 * 1024 * 1024;

static void do_test(char *qdisc)
{
	DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = LO_IFINDEX,
			    .attach_point = BPF_TC_QDISC,
			    .parent = TC_H_ROOT,
			    .handle = 0x8000000,
			    .qdisc = qdisc);
	int srv_fd = -1, cli_fd = -1;
	int err;

	err = bpf_tc_hook_create(&hook);
	if (!ASSERT_OK(err, "attach qdisc"))
		return;

	srv_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
	if (!ASSERT_OK_FD(srv_fd, "start server"))
		goto done;

	cli_fd = connect_to_fd(srv_fd, 0);
	if (!ASSERT_OK_FD(cli_fd, "connect to client"))
		goto done;

	err = send_recv_data(srv_fd, cli_fd, total_bytes);
	ASSERT_OK(err, "send_recv_data");

done:
	if (srv_fd != -1)
		close(srv_fd);
	if (cli_fd != -1)
		close(cli_fd);

	bpf_tc_hook_destroy(&hook);
}

static void test_fifo(void)
{
	struct bpf_qdisc_fifo *fifo_skel;
	struct bpf_link *link;

	fifo_skel = bpf_qdisc_fifo__open_and_load();
	if (!ASSERT_OK_PTR(fifo_skel, "bpf_qdisc_fifo__open_and_load"))
		return;

	link = bpf_map__attach_struct_ops(fifo_skel->maps.fifo);
	if (!ASSERT_OK_PTR(link, "bpf_map__attach_struct_ops")) {
		bpf_qdisc_fifo__destroy(fifo_skel);
		return;
	}

	do_test("bpf_fifo");

	bpf_link__destroy(link);
	bpf_qdisc_fifo__destroy(fifo_skel);
}

static void test_fq(void)
{
	struct bpf_qdisc_fq *fq_skel;
	struct bpf_link *link;

	fq_skel = bpf_qdisc_fq__open_and_load();
	if (!ASSERT_OK_PTR(fq_skel, "bpf_qdisc_fq__open_and_load"))
		return;

	link = bpf_map__attach_struct_ops(fq_skel->maps.fq);
	if (!ASSERT_OK_PTR(link, "bpf_map__attach_struct_ops")) {
		bpf_qdisc_fq__destroy(fq_skel);
		return;
	}

	do_test("bpf_fq");

	bpf_link__destroy(link);
	bpf_qdisc_fq__destroy(fq_skel);
}

void test_bpf_qdisc(void)
{
	struct netns_obj *netns;

	netns = netns_new("bpf_qdisc_ns", true);
	if (!ASSERT_OK_PTR(netns, "netns_new"))
		return;

	if (test__start_subtest("fifo"))
		test_fifo();
	if (test__start_subtest("fq"))
		test_fq();

	netns_free(netns);
}