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