Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright Amazon.com Inc. or its affiliates. */
  3
  4#define _GNU_SOURCE
  5#include <sched.h>
  6#include <stdlib.h>
  7#include <net/if.h>
  8
  9#include "test_progs.h"
 10#include "cgroup_helpers.h"
 11#include "network_helpers.h"
 12#include "test_tcp_custom_syncookie.skel.h"
 13
 14static struct test_tcp_custom_syncookie_case {
 15	int family, type;
 16	char addr[16];
 17	char name[10];
 18} test_cases[] = {
 19	{
 20		.name = "IPv4 TCP",
 21		.family = AF_INET,
 22		.type = SOCK_STREAM,
 23		.addr = "127.0.0.1",
 24	},
 25	{
 26		.name = "IPv6 TCP",
 27		.family = AF_INET6,
 28		.type = SOCK_STREAM,
 29		.addr = "::1",
 30	},
 31};
 32
 33static int setup_netns(void)
 34{
 35	if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
 36		return -1;
 37
 38	if (!ASSERT_OK(system("ip link set dev lo up"), "ip"))
 39		goto err;
 40
 41	if (!ASSERT_OK(write_sysctl("/proc/sys/net/ipv4/tcp_ecn", "1"),
 42		       "write_sysctl"))
 43		goto err;
 44
 45	return 0;
 46err:
 47	return -1;
 48}
 49
 50static int setup_tc(struct test_tcp_custom_syncookie *skel)
 51{
 52	LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = BPF_TC_INGRESS);
 53	LIBBPF_OPTS(bpf_tc_opts, tc_attach,
 54		    .prog_fd = bpf_program__fd(skel->progs.tcp_custom_syncookie));
 55
 56	qdisc_lo.ifindex = if_nametoindex("lo");
 57	if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo clsact"))
 58		goto err;
 59
 60	if (!ASSERT_OK(bpf_tc_attach(&qdisc_lo, &tc_attach),
 61		       "filter add dev lo ingress"))
 62		goto err;
 63
 64	return 0;
 65err:
 66	return -1;
 67}
 68
 69#define msg "Hello World"
 70#define msglen 11
 71
 72static void transfer_message(int sender, int receiver)
 73{
 74	char buf[msglen];
 75	int ret;
 76
 77	ret = send(sender, msg, msglen, 0);
 78	if (!ASSERT_EQ(ret, msglen, "send"))
 79		return;
 80
 81	memset(buf, 0, sizeof(buf));
 82
 83	ret = recv(receiver, buf, msglen, 0);
 84	if (!ASSERT_EQ(ret, msglen, "recv"))
 85		return;
 86
 87	ret = strncmp(buf, msg, msglen);
 88	if (!ASSERT_EQ(ret, 0, "strncmp"))
 89		return;
 90}
 91
 92static void create_connection(struct test_tcp_custom_syncookie_case *test_case)
 93{
 94	int server, client, child;
 95
 96	server = start_server(test_case->family, test_case->type, test_case->addr, 0, 0);
 97	if (!ASSERT_NEQ(server, -1, "start_server"))
 98		return;
 99
100	client = connect_to_fd(server, 0);
101	if (!ASSERT_NEQ(client, -1, "connect_to_fd"))
102		goto close_server;
103
104	child = accept(server, NULL, 0);
105	if (!ASSERT_NEQ(child, -1, "accept"))
106		goto close_client;
107
108	transfer_message(client, child);
109	transfer_message(child, client);
110
111	close(child);
112close_client:
113	close(client);
114close_server:
115	close(server);
116}
117
118void test_tcp_custom_syncookie(void)
119{
120	struct test_tcp_custom_syncookie *skel;
121	int i;
122
123	if (setup_netns())
124		return;
125
126	skel = test_tcp_custom_syncookie__open_and_load();
127	if (!ASSERT_OK_PTR(skel, "open_and_load"))
128		return;
129
130	if (setup_tc(skel))
131		goto destroy_skel;
132
133	for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
134		if (!test__start_subtest(test_cases[i].name))
135			continue;
136
137		skel->bss->handled_syn = false;
138		skel->bss->handled_ack = false;
139
140		create_connection(&test_cases[i]);
141
142		ASSERT_EQ(skel->bss->handled_syn, true, "SYN is not handled at tc.");
143		ASSERT_EQ(skel->bss->handled_ack, true, "ACK is not handled at tc");
144	}
145
146destroy_skel:
147	system("tc qdisc del dev lo clsact");
148
149	test_tcp_custom_syncookie__destroy(skel);
150}
1