151 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright Amazon.com Inc. or its affiliates. */3 4#define _GNU_SOURCE5#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 1171 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}151