1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <test_progs.h>
4 #include <network_helpers.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>
8 #include <unistd.h>
9 #include <string.h>
10
11 #include "test_tc_qevent.skel.h"
12
13 #define NS_TX "tc_qevent_tx"
14 #define NS_RX "tc_qevent_rx"
15 #define IP_TX "10.255.0.1"
16 #define IP_RX "10.255.0.2"
17 #define PIN_PATH "/sys/fs/bpf/tc_qevent_redirect"
18
blast_udp(void)19 static void blast_udp(void)
20 {
21 struct sockaddr_in dst = {};
22 char buf[1400] = {};
23 int fd, i;
24
25 fd = socket(AF_INET, SOCK_DGRAM, 0);
26 if (!ASSERT_GE(fd, 0, "udp socket"))
27 return;
28
29 dst.sin_family = AF_INET;
30 dst.sin_port = htons(12345);
31 inet_pton(AF_INET, IP_RX, &dst.sin_addr);
32
33 /*
34 * Push far more than the RED queue can hold. Once qavg crosses qth_min
35 * every further packet hits the congestion_drop / early_drop qevent.
36 */
37 for (i = 0; i < 50000; i++)
38 sendto(fd, buf, sizeof(buf), MSG_DONTWAIT,
39 (struct sockaddr *)&dst, sizeof(dst));
40
41 close(fd);
42 }
43
run_qevent_redirect(struct bpf_program * prog,__u64 * counter)44 static void run_qevent_redirect(struct bpf_program *prog, __u64 *counter)
45 {
46 struct nstoken *tok = NULL;
47 int err;
48
49 SYS_NOFAIL("ip netns del %s", NS_TX);
50 SYS_NOFAIL("ip netns del %s", NS_RX);
51 unlink(PIN_PATH);
52
53 err = bpf_program__pin(prog, PIN_PATH);
54 if (!ASSERT_OK(err, "pin prog"))
55 return;
56
57 SYS(unpin, "ip netns add %s", NS_TX);
58 SYS(del_tx, "ip netns add %s", NS_RX);
59 SYS(del_rx, "ip -n %s link add veth0 type veth peer name veth1 netns %s", NS_TX, NS_RX);
60 SYS(del_rx, "ip -n %s addr add %s/24 dev veth0", NS_TX, IP_TX);
61 SYS(del_rx, "ip -n %s link set veth0 up", NS_TX);
62 SYS(del_rx, "ip -n %s addr add %s/24 dev veth1", NS_RX, IP_RX);
63 SYS(del_rx, "ip -n %s link set veth1 up", NS_RX);
64
65 tok = open_netns(NS_TX);
66 if (!ASSERT_OK_PTR(tok, "open_netns"))
67 goto del_rx;
68
69 SYS(close_ns, "tc qdisc add dev veth0 root handle 1: htb default 1");
70 SYS(close_ns, "tc class add dev veth0 parent 1: classid 1:1 htb rate 1mbit ceil 1mbit");
71
72 if (system("tc qdisc add dev veth0 parent 1:1 handle 11: red "
73 "limit 500000 avpkt 1000 probability 1 min 5000 max 6000 "
74 "burst 6 qevent early_drop block 10 2>/dev/null")) {
75 test__skip();
76 goto close_ns;
77 }
78
79 if (system("tc filter add block 10 bpf da object-pinned "
80 PIN_PATH " 2>/dev/null")) {
81 test__skip();
82 goto close_ns;
83 }
84
85 blast_udp();
86 ASSERT_GT(*counter, 0, "qevent classifier ran");
87 close_ns:
88 close_netns(tok);
89 del_rx:
90 SYS_NOFAIL("ip netns del %s", NS_RX);
91 del_tx:
92 SYS_NOFAIL("ip netns del %s", NS_TX);
93 unpin:
94 bpf_program__unpin(prog, PIN_PATH);
95 }
96
test_tc_qevent(void)97 void test_tc_qevent(void)
98 {
99 struct test_tc_qevent *skel;
100
101 skel = test_tc_qevent__open_and_load();
102 if (!ASSERT_OK_PTR(skel, "open_and_load"))
103 return;
104
105 if (test__start_subtest("redirect_verdict"))
106 run_qevent_redirect(skel->progs.qevent_redirect_verdict,
107 &skel->bss->verdict_calls);
108 if (test__start_subtest("redirect_helper"))
109 run_qevent_redirect(skel->progs.qevent_redirect_helper,
110 &skel->bss->helper_calls);
111
112 test_tc_qevent__destroy(skel);
113 }
114