File Index
Files and directories
Sign in
FILE

test_tc_edt.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c C
  1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2
  3/*
  4 * BPF-based flow shaping
  5 *
  6 * The test brings up two veth in two isolated namespaces, attach some flow
  7 * shaping program onto it, and ensures that a manual speedtest maximum
  8 * value matches the rate set in the BPF shapers.
  9 */
 10
 11#include <asm-generic/socket.h>
 12#include <stdio.h>
 13#include <unistd.h>
 14#include <fcntl.h>
 15#include <math.h>
 16#include <sys/time.h>
 17#include <sys/socket.h>
 18#include <bpf/libbpf.h>
 19#include <pthread.h>
 20#include "test_progs.h"
 21#include "network_helpers.h"
 22#include "test_tc_edt.skel.h"
 23
 24#define SERVER_NS "tc-edt-server-ns"
 25#define CLIENT_NS "tc-edt-client-ns"
 26#define IP4_ADDR_VETH1 "192.168.1.1"
 27#define IP4_ADDR_VETH2 "192.168.1.2"
 28#define IP4_ADDR_VETH2_HEX 0xC0A80102
 29
 30#define TIMEOUT_MS		2000
 31#define TEST_PORT		9000
 32#define TARGET_RATE_MBPS	5.0
 33#define TX_BYTES_COUNT		(1 * 1000 * 1000)
 34#define RATE_ERROR_PERCENT	2.0
 35
 36struct connection {
 37	int server_listen_fd;
 38	int server_conn_fd;
 39	int client_conn_fd;
 40};
 41
 42static int setup(struct test_tc_edt *skel)
 43{
 44	struct nstoken *nstoken_client, *nstoken_server;
 45	int ret;
 46
 47	if (!ASSERT_OK(make_netns(CLIENT_NS), "create client ns"))
 48		goto fail;
 49	if (!ASSERT_OK(make_netns(SERVER_NS), "create server ns"))
 50		goto fail_delete_client_ns;
 51
 52	nstoken_client = open_netns(CLIENT_NS);
 53	if (!ASSERT_OK_PTR(nstoken_client, "open client ns"))
 54		goto fail_delete_server_ns;
 55	SYS(fail_close_client_ns, "ip link add veth1 type veth peer name %s",
 56	    "veth2 netns " SERVER_NS);
 57	SYS(fail_close_client_ns, "ip -4 addr add " IP4_ADDR_VETH1 "/24 dev veth1");
 58	SYS(fail_close_client_ns, "ip link set veth1 up");
 59
 60	nstoken_server = open_netns(SERVER_NS);
 61	if (!ASSERT_OK_PTR(nstoken_server, "enter server ns"))
 62		goto fail_close_client_ns;
 63	SYS(fail_close_server_ns, "ip -4 addr add " IP4_ADDR_VETH2 "/24 dev veth2");
 64	SYS(fail_close_server_ns, "ip link set veth2 up");
 65	SYS(fail_close_server_ns, "tc qdisc add dev veth2 root fq");
 66	ret = tc_prog_attach("veth2", -1, bpf_program__fd(skel->progs.tc_prog));
 67	if (!ASSERT_OK(ret, "attach bpf prog"))
 68		goto fail_close_server_ns;
 69	skel->bss->target_rate = TARGET_RATE_MBPS * 1000 * 1000;
 70	close_netns(nstoken_server);
 71	close_netns(nstoken_client);
 72
 73	return 0;
 74
 75fail_close_server_ns:
 76	close_netns(nstoken_server);
 77fail_close_client_ns:
 78	close_netns(nstoken_client);
 79fail_delete_server_ns:
 80	remove_netns(SERVER_NS);
 81fail_delete_client_ns:
 82	remove_netns(CLIENT_NS);
 83fail:
 84	return -1;
 85}
 86
 87static void cleanup(void)
 88{
 89	remove_netns(CLIENT_NS);
 90	remove_netns(SERVER_NS);
 91}
 92
 93static void run_test(void)
 94{
 95	int server_fd, client_fd, err;
 96	double rate_mbps, rate_error;
 97	struct nstoken *nstoken;
 98	__u64 ts_start, ts_end;
 99
100	nstoken = open_netns(SERVER_NS);
101	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
102		return;
103	server_fd = start_server(AF_INET, SOCK_STREAM, IP4_ADDR_VETH2,
104			TEST_PORT, TIMEOUT_MS);
105	if (!ASSERT_OK_FD(server_fd, "start server"))
106		return;
107
108	close_netns(nstoken);
109	nstoken = open_netns(CLIENT_NS);
110	if (!ASSERT_OK_PTR(nstoken, "open client ns"))
111		return;
112	client_fd = connect_to_fd(server_fd, 0);
113	if (!ASSERT_OK_FD(client_fd, "connect client"))
114		return;
115
116	ts_start = get_time_ns();
117	err = send_recv_data(server_fd, client_fd, TX_BYTES_COUNT);
118	ts_end = get_time_ns();
119	close_netns(nstoken);
120	ASSERT_OK(err, "send_recv_data");
121
122	rate_mbps = TX_BYTES_COUNT / ((ts_end - ts_start) / 1000.0);
123	rate_error =
124		fabs((rate_mbps - TARGET_RATE_MBPS) * 100.0 / TARGET_RATE_MBPS);
125
126	ASSERT_LE(rate_error, RATE_ERROR_PERCENT,
127		  "rate error is lower than threshold");
128}
129
130void test_tc_edt(void)
131{
132	struct test_tc_edt *skel;
133
134	skel = test_tc_edt__open_and_load();
135	if (!ASSERT_OK_PTR(skel, "skel open and load"))
136		return;
137
138	if (!ASSERT_OK(setup(skel), "global setup"))
139		return;
140
141	run_test();
142
143	cleanup();
144	test_tc_edt__destroy(skel);
145}
~/ Read-only file preview.