xref: /linux/tools/testing/selftests/bpf/prog_tests/tc_qevent.c (revision fab183d632628381b466a41479489541ac0e29a0)
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