1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 4 #define _GNU_SOURCE 5 #include <sched.h> 6 #include <linux/socket.h> 7 #include <net/if.h> 8 9 #include "test_progs.h" 10 #include "cgroup_helpers.h" 11 #include "network_helpers.h" 12 13 #include "setget_sockopt.skel.h" 14 15 #define CG_NAME "/setget-sockopt-test" 16 17 static const char addr4_str[] = "127.0.0.1"; 18 static const char addr6_str[] = "::1"; 19 static struct setget_sockopt *skel; 20 static int cg_fd; 21 22 static int create_netns(void) 23 { 24 if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns")) 25 return -1; 26 27 if (!ASSERT_OK(system("ip link set dev lo up"), "set lo up")) 28 return -1; 29 30 if (!ASSERT_OK(system("ip link add dev binddevtest1 type veth peer name binddevtest2"), 31 "add veth")) 32 return -1; 33 34 if (!ASSERT_OK(system("ip link set dev binddevtest1 up"), 35 "bring veth up")) 36 return -1; 37 38 return 0; 39 } 40 41 static void test_tcp(int family) 42 { 43 struct setget_sockopt__bss *bss = skel->bss; 44 int sfd, cfd; 45 46 memset(bss, 0, sizeof(*bss)); 47 48 sfd = start_server(family, SOCK_STREAM, 49 family == AF_INET6 ? addr6_str : addr4_str, 0, 0); 50 if (!ASSERT_GE(sfd, 0, "start_server")) 51 return; 52 53 cfd = connect_to_fd(sfd, 0); 54 if (!ASSERT_GE(cfd, 0, "connect_to_fd_server")) { 55 close(sfd); 56 return; 57 } 58 close(sfd); 59 close(cfd); 60 61 ASSERT_EQ(bss->nr_listen, 1, "nr_listen"); 62 ASSERT_EQ(bss->nr_connect, 1, "nr_connect"); 63 ASSERT_EQ(bss->nr_active, 1, "nr_active"); 64 ASSERT_EQ(bss->nr_passive, 1, "nr_passive"); 65 ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create"); 66 ASSERT_EQ(bss->nr_binddev, 2, "nr_bind"); 67 } 68 69 static void test_udp(int family) 70 { 71 struct setget_sockopt__bss *bss = skel->bss; 72 int sfd; 73 74 memset(bss, 0, sizeof(*bss)); 75 76 sfd = start_server(family, SOCK_DGRAM, 77 family == AF_INET6 ? addr6_str : addr4_str, 0, 0); 78 if (!ASSERT_GE(sfd, 0, "start_server")) 79 return; 80 close(sfd); 81 82 ASSERT_GE(bss->nr_socket_post_create, 1, "nr_socket_post_create"); 83 ASSERT_EQ(bss->nr_binddev, 1, "nr_bind"); 84 } 85 86 void test_setget_sockopt(void) 87 { 88 cg_fd = test__join_cgroup(CG_NAME); 89 if (cg_fd < 0) 90 return; 91 92 if (create_netns()) 93 goto done; 94 95 skel = setget_sockopt__open(); 96 if (!ASSERT_OK_PTR(skel, "open skel")) 97 goto done; 98 99 strcpy(skel->rodata->veth, "binddevtest1"); 100 skel->rodata->veth_ifindex = if_nametoindex("binddevtest1"); 101 if (!ASSERT_GT(skel->rodata->veth_ifindex, 0, "if_nametoindex")) 102 goto done; 103 104 if (!ASSERT_OK(setget_sockopt__load(skel), "load skel")) 105 goto done; 106 107 skel->links.skops_sockopt = 108 bpf_program__attach_cgroup(skel->progs.skops_sockopt, cg_fd); 109 if (!ASSERT_OK_PTR(skel->links.skops_sockopt, "attach cgroup")) 110 goto done; 111 112 skel->links.socket_post_create = 113 bpf_program__attach_cgroup(skel->progs.socket_post_create, cg_fd); 114 if (!ASSERT_OK_PTR(skel->links.socket_post_create, "attach_cgroup")) 115 goto done; 116 117 test_tcp(AF_INET6); 118 test_tcp(AF_INET); 119 test_udp(AF_INET6); 120 test_udp(AF_INET); 121 122 done: 123 setget_sockopt__destroy(skel); 124 close(cg_fd); 125 } 126