Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says:

====================
pull-request: bpf-next 2024-10-31

We've added 13 non-merge commits during the last 16 day(s) which contain
a total of 16 files changed, 710 insertions(+), 668 deletions(-).

The main changes are:

1) Optimize and homogenize bpf_csum_diff helper for all archs and also
add a batch of new BPF selftests for it, from Puranjay Mohan.

2) Rewrite and migrate the test_tcp_check_syncookie.sh BPF selftest
into test_progs so that it can be run in BPF CI, from Alexis Lothoré.

3) Two BPF sockmap selftest fixes, from Zijian Zhang.

4) Small XDP synproxy BPF selftest cleanup to remove IP_DF check,
from Vincent Li.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next:
selftests/bpf: Add a selftest for bpf_csum_diff()
selftests/bpf: Don't mask result of bpf_csum_diff() in test_verifier
bpf: bpf_csum_diff: Optimize and homogenize for all archs
net: checksum: Move from32to16() to generic header
selftests/bpf: remove xdp_synproxy IP_DF check
selftests/bpf: remove test_tcp_check_syncookie
selftests/bpf: test MSS value returned with bpf_tcp_gen_syncookie
selftests/bpf: add ipv4 and dual ipv4/ipv6 support in btf_skc_cls_ingress
selftests/bpf: get rid of global vars in btf_skc_cls_ingress
selftests/bpf: add missing ns cleanups in btf_skc_cls_ingress
selftests/bpf: factorize conn and syncookies tests in a single runner
selftests/bpf: Fix txmsg_redir of test_txmsg_pull in test_sockmap
selftests/bpf: Fix msg_verify_data in test_sockmap

====================

Link: https://patch.msgid.link/20241031221543.108853-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+724 -669
+2 -11
arch/parisc/lib/checksum.c
··· 25 25 : "=r"(_t) \ 26 26 : "r"(_r), "0"(_t)); 27 27 28 - static inline unsigned short from32to16(unsigned int x) 29 - { 30 - /* 32 bits --> 16 bits + carry */ 31 - x = (x & 0xffff) + (x >> 16); 32 - /* 16 bits + carry --> 16 bits including carry */ 33 - x = (x & 0xffff) + (x >> 16); 34 - return (unsigned short)x; 35 - } 36 - 37 28 static inline unsigned int do_csum(const unsigned char * buff, int len) 38 29 { 39 30 int odd, count; ··· 76 85 } 77 86 if (len & 1) 78 87 result += le16_to_cpu(*buff); 79 - result = from32to16(result); 88 + result = csum_from32to16(result); 80 89 if (odd) 81 90 result = swab16(result); 82 91 out: ··· 93 102 { 94 103 unsigned int result = do_csum(buff, len); 95 104 addc(result, sum); 96 - return (__force __wsum)from32to16(result); 105 + return (__force __wsum)csum_from32to16(result); 97 106 } 98 107 99 108 EXPORT_SYMBOL(csum_partial);
+6
include/net/checksum.h
··· 151 151 *csum = csum_add(csum_sub(*csum, old), new); 152 152 } 153 153 154 + static inline unsigned short csum_from32to16(unsigned int sum) 155 + { 156 + sum += (sum >> 16) | (sum << 16); 157 + return (unsigned short)(sum >> 16); 158 + } 159 + 154 160 struct sk_buff; 155 161 void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, 156 162 __be32 from, __be32 to, bool pseudohdr);
+1 -10
lib/checksum.c
··· 34 34 #include <asm/byteorder.h> 35 35 36 36 #ifndef do_csum 37 - static inline unsigned short from32to16(unsigned int x) 38 - { 39 - /* add up 16-bit and 16-bit for 16+c bit */ 40 - x = (x & 0xffff) + (x >> 16); 41 - /* add up carry.. */ 42 - x = (x & 0xffff) + (x >> 16); 43 - return x; 44 - } 45 - 46 37 static unsigned int do_csum(const unsigned char *buff, int len) 47 38 { 48 39 int odd; ··· 81 90 #else 82 91 result += (*buff << 8); 83 92 #endif 84 - result = from32to16(result); 93 + result = csum_from32to16(result); 85 94 if (odd) 86 95 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); 87 96 out:
+11 -28
net/core/filter.c
··· 1654 1654 bpf_prog_destroy(prog); 1655 1655 } 1656 1656 1657 - struct bpf_scratchpad { 1658 - union { 1659 - __be32 diff[MAX_BPF_STACK / sizeof(__be32)]; 1660 - u8 buff[MAX_BPF_STACK]; 1661 - }; 1662 - local_lock_t bh_lock; 1663 - }; 1664 - 1665 - static DEFINE_PER_CPU(struct bpf_scratchpad, bpf_sp) = { 1666 - .bh_lock = INIT_LOCAL_LOCK(bh_lock), 1667 - }; 1668 - 1669 1657 static inline int __bpf_try_make_writable(struct sk_buff *skb, 1670 1658 unsigned int write_len) 1671 1659 { ··· 2010 2022 BPF_CALL_5(bpf_csum_diff, __be32 *, from, u32, from_size, 2011 2023 __be32 *, to, u32, to_size, __wsum, seed) 2012 2024 { 2013 - struct bpf_scratchpad *sp = this_cpu_ptr(&bpf_sp); 2014 - u32 diff_size = from_size + to_size; 2015 - int i, j = 0; 2016 - __wsum ret; 2017 - 2018 2025 /* This is quite flexible, some examples: 2019 2026 * 2020 2027 * from_size == 0, to_size > 0, seed := csum --> pushing data ··· 2018 2035 * 2019 2036 * Even for diffing, from_size and to_size don't need to be equal. 2020 2037 */ 2021 - if (unlikely(((from_size | to_size) & (sizeof(__be32) - 1)) || 2022 - diff_size > sizeof(sp->diff))) 2023 - return -EINVAL; 2024 2038 2025 - local_lock_nested_bh(&bpf_sp.bh_lock); 2026 - for (i = 0; i < from_size / sizeof(__be32); i++, j++) 2027 - sp->diff[j] = ~from[i]; 2028 - for (i = 0; i < to_size / sizeof(__be32); i++, j++) 2029 - sp->diff[j] = to[i]; 2039 + __wsum ret = seed; 2030 2040 2031 - ret = csum_partial(sp->diff, diff_size, seed); 2032 - local_unlock_nested_bh(&bpf_sp.bh_lock); 2033 - return ret; 2041 + if (from_size && to_size) 2042 + ret = csum_sub(csum_partial(to, to_size, ret), 2043 + csum_partial(from, from_size, 0)); 2044 + else if (to_size) 2045 + ret = csum_partial(to, to_size, ret); 2046 + 2047 + else if (from_size) 2048 + ret = ~csum_partial(from, from_size, ~ret); 2049 + 2050 + return csum_from32to16((__force unsigned int)ret); 2034 2051 } 2035 2052 2036 2053 static const struct bpf_func_proto bpf_csum_diff_proto = {
-1
tools/testing/selftests/bpf/.gitignore
··· 24 24 flow_dissector_load 25 25 test_tcpnotify_user 26 26 test_libbpf 27 - test_tcp_check_syncookie_user 28 27 test_sysctl 29 28 xdping 30 29 test_cpp
+17 -7
tools/testing/selftests/bpf/Makefile
··· 137 137 test_xdp_vlan_mode_generic.sh \ 138 138 test_xdp_vlan_mode_native.sh \ 139 139 test_lwt_ip_encap.sh \ 140 - test_tcp_check_syncookie.sh \ 141 140 test_tc_tunnel.sh \ 142 141 test_tc_edt.sh \ 143 142 test_xdping.sh \ ··· 153 154 154 155 # Compile but not part of 'make run_tests' 155 156 TEST_GEN_PROGS_EXTENDED = \ 156 - flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \ 157 - test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \ 158 - xskxceiver xdp_redirect_multi xdp_synproxy veristat xdp_hw_metadata \ 159 - xdp_features bpf_test_no_cfi.ko bpf_test_modorder_x.ko \ 160 - bpf_test_modorder_y.ko 157 + bench \ 158 + bpf_testmod.ko \ 159 + bpf_test_modorder_x.ko \ 160 + bpf_test_modorder_y.ko \ 161 + bpf_test_no_cfi.ko \ 162 + flow_dissector_load \ 163 + runqslower \ 164 + test_cpp \ 165 + test_flow_dissector \ 166 + test_lirc_mode2_user \ 167 + veristat \ 168 + xdp_features \ 169 + xdp_hw_metadata \ 170 + xdp_redirect_multi \ 171 + xdp_synproxy \ 172 + xdping \ 173 + xskxceiver 161 174 162 175 TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi 163 176 ··· 372 361 $(OUTPUT)/test_maps: $(TESTING_HELPERS) 373 362 $(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) $(UNPRIV_HELPERS) 374 363 $(OUTPUT)/xsk.o: $(BPFOBJ) 375 - $(OUTPUT)/test_tcp_check_syncookie_user: $(NETWORK_HELPERS) 376 364 377 365 BPFTOOL ?= $(DEFAULT_BPFTOOL) 378 366 $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
+159 -105
tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c
··· 17 17 #include "test_progs.h" 18 18 #include "test_btf_skc_cls_ingress.skel.h" 19 19 20 - static struct test_btf_skc_cls_ingress *skel; 21 - static struct sockaddr_in6 srv_sa6; 22 - static __u32 duration; 20 + #define TEST_NS "skc_cls_ingress" 23 21 24 - static int prepare_netns(void) 22 + #define BIT(n) (1 << (n)) 23 + #define TEST_MODE_IPV4 BIT(0) 24 + #define TEST_MODE_IPV6 BIT(1) 25 + #define TEST_MODE_DUAL (TEST_MODE_IPV4 | TEST_MODE_IPV6) 26 + 27 + #define SERVER_ADDR_IPV4 "127.0.0.1" 28 + #define SERVER_ADDR_IPV6 "::1" 29 + #define SERVER_ADDR_DUAL "::0" 30 + /* RFC791, 576 for minimal IPv4 datagram, minus 40 bytes of TCP header */ 31 + #define MIN_IPV4_MSS 536 32 + 33 + static struct netns_obj *prepare_netns(struct test_btf_skc_cls_ingress *skel) 25 34 { 26 35 LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = BPF_TC_INGRESS); 27 36 LIBBPF_OPTS(bpf_tc_opts, tc_attach, 28 37 .prog_fd = bpf_program__fd(skel->progs.cls_ingress)); 38 + struct netns_obj *ns = NULL; 29 39 30 - if (CHECK(unshare(CLONE_NEWNET), "create netns", 31 - "unshare(CLONE_NEWNET): %s (%d)", 32 - strerror(errno), errno)) 33 - return -1; 34 - 35 - if (CHECK(system("ip link set dev lo up"), 36 - "ip link set dev lo up", "failed\n")) 37 - return -1; 40 + ns = netns_new(TEST_NS, true); 41 + if (!ASSERT_OK_PTR(ns, "create and join netns")) 42 + return ns; 38 43 39 44 qdisc_lo.ifindex = if_nametoindex("lo"); 40 45 if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo clsact")) 41 - return -1; 46 + goto free_ns; 42 47 43 48 if (!ASSERT_OK(bpf_tc_attach(&qdisc_lo, &tc_attach), 44 49 "filter add dev lo ingress")) 45 - return -1; 50 + goto free_ns; 46 51 47 52 /* Ensure 20 bytes options (i.e. in total 40 bytes tcp header) for the 48 53 * bpf_tcp_gen_syncookie() helper. ··· 55 50 if (write_sysctl("/proc/sys/net/ipv4/tcp_window_scaling", "1") || 56 51 write_sysctl("/proc/sys/net/ipv4/tcp_timestamps", "1") || 57 52 write_sysctl("/proc/sys/net/ipv4/tcp_sack", "1")) 58 - return -1; 53 + goto free_ns; 59 54 60 - return 0; 55 + return ns; 56 + 57 + free_ns: 58 + netns_free(ns); 59 + return NULL; 61 60 } 62 61 63 - static void reset_test(void) 62 + static void reset_test(struct test_btf_skc_cls_ingress *skel) 64 63 { 64 + memset(&skel->bss->srv_sa4, 0, sizeof(skel->bss->srv_sa4)); 65 65 memset(&skel->bss->srv_sa6, 0, sizeof(skel->bss->srv_sa6)); 66 66 skel->bss->listen_tp_sport = 0; 67 67 skel->bss->req_sk_sport = 0; 68 68 skel->bss->recv_cookie = 0; 69 69 skel->bss->gen_cookie = 0; 70 70 skel->bss->linum = 0; 71 + skel->bss->mss = 0; 71 72 } 72 73 73 - static void print_err_line(void) 74 + static void print_err_line(struct test_btf_skc_cls_ingress *skel) 74 75 { 75 76 if (skel->bss->linum) 76 77 printf("bpf prog error at line %u\n", skel->bss->linum); 77 78 } 78 79 79 - static void test_conn(void) 80 + static int v6only_true(int fd, void *opts) 80 81 { 82 + int mode = true; 83 + 84 + return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode)); 85 + } 86 + 87 + static int v6only_false(int fd, void *opts) 88 + { 89 + int mode = false; 90 + 91 + return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode)); 92 + } 93 + 94 + static void run_test(struct test_btf_skc_cls_ingress *skel, bool gen_cookies, 95 + int ip_mode) 96 + { 97 + const char *tcp_syncookies = gen_cookies ? "2" : "1"; 81 98 int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; 82 - socklen_t addrlen = sizeof(srv_sa6); 99 + struct network_helper_opts opts = { 0 }; 100 + struct sockaddr_storage *addr; 101 + struct sockaddr_in6 srv_sa6; 102 + struct sockaddr_in srv_sa4; 103 + socklen_t addr_len; 104 + int sock_family; 105 + char *srv_addr; 83 106 int srv_port; 84 107 85 - if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1")) 108 + switch (ip_mode) { 109 + case TEST_MODE_IPV4: 110 + sock_family = AF_INET; 111 + srv_addr = SERVER_ADDR_IPV4; 112 + addr = (struct sockaddr_storage *)&srv_sa4; 113 + addr_len = sizeof(srv_sa4); 114 + break; 115 + case TEST_MODE_IPV6: 116 + opts.post_socket_cb = v6only_true; 117 + sock_family = AF_INET6; 118 + srv_addr = SERVER_ADDR_IPV6; 119 + addr = (struct sockaddr_storage *)&srv_sa6; 120 + addr_len = sizeof(srv_sa6); 121 + break; 122 + case TEST_MODE_DUAL: 123 + opts.post_socket_cb = v6only_false; 124 + sock_family = AF_INET6; 125 + srv_addr = SERVER_ADDR_DUAL; 126 + addr = (struct sockaddr_storage *)&srv_sa6; 127 + addr_len = sizeof(srv_sa6); 128 + break; 129 + default: 130 + PRINT_FAIL("Unknown IP mode %d", ip_mode); 131 + return; 132 + } 133 + 134 + if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", tcp_syncookies)) 86 135 return; 87 136 88 - listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0); 89 - if (CHECK_FAIL(listen_fd == -1)) 137 + listen_fd = start_server_str(sock_family, SOCK_STREAM, srv_addr, 0, 138 + &opts); 139 + if (!ASSERT_OK_FD(listen_fd, "start server")) 90 140 return; 91 141 92 - err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen); 93 - if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err, 94 - errno)) 142 + err = getsockname(listen_fd, (struct sockaddr *)addr, &addr_len); 143 + if (!ASSERT_OK(err, "getsockname(listen_fd)")) 95 144 goto done; 96 - memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6)); 97 - srv_port = ntohs(srv_sa6.sin6_port); 145 + 146 + switch (ip_mode) { 147 + case TEST_MODE_IPV4: 148 + memcpy(&skel->bss->srv_sa4, &srv_sa4, sizeof(srv_sa4)); 149 + srv_port = ntohs(srv_sa4.sin_port); 150 + break; 151 + case TEST_MODE_IPV6: 152 + case TEST_MODE_DUAL: 153 + memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6)); 154 + srv_port = ntohs(srv_sa6.sin6_port); 155 + break; 156 + default: 157 + goto done; 158 + } 98 159 99 160 cli_fd = connect_to_fd(listen_fd, 0); 100 - if (CHECK_FAIL(cli_fd == -1)) 161 + if (!ASSERT_OK_FD(cli_fd, "connect client")) 101 162 goto done; 102 163 103 164 srv_fd = accept(listen_fd, NULL, NULL); 104 - if (CHECK_FAIL(srv_fd == -1)) 165 + if (!ASSERT_OK_FD(srv_fd, "accept connection")) 105 166 goto done; 106 167 107 - if (CHECK(skel->bss->listen_tp_sport != srv_port || 108 - skel->bss->req_sk_sport != srv_port, 109 - "Unexpected sk src port", 110 - "listen_tp_sport:%u req_sk_sport:%u expected:%u\n", 111 - skel->bss->listen_tp_sport, skel->bss->req_sk_sport, 112 - srv_port)) 113 - goto done; 168 + ASSERT_EQ(skel->bss->listen_tp_sport, srv_port, "listen tp src port"); 114 169 115 - if (CHECK(skel->bss->gen_cookie || skel->bss->recv_cookie, 116 - "Unexpected syncookie states", 117 - "gen_cookie:%u recv_cookie:%u\n", 118 - skel->bss->gen_cookie, skel->bss->recv_cookie)) 119 - goto done; 120 - 121 - CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n", 122 - skel->bss->linum); 170 + if (!gen_cookies) { 171 + ASSERT_EQ(skel->bss->req_sk_sport, srv_port, 172 + "request socket source port with syncookies disabled"); 173 + ASSERT_EQ(skel->bss->gen_cookie, 0, 174 + "generated syncookie with syncookies disabled"); 175 + ASSERT_EQ(skel->bss->recv_cookie, 0, 176 + "received syncookie with syncookies disabled"); 177 + } else { 178 + ASSERT_EQ(skel->bss->req_sk_sport, 0, 179 + "request socket source port with syncookies enabled"); 180 + ASSERT_NEQ(skel->bss->gen_cookie, 0, 181 + "syncookie properly generated"); 182 + ASSERT_EQ(skel->bss->gen_cookie, skel->bss->recv_cookie, 183 + "matching syncookies on client and server"); 184 + ASSERT_GT(skel->bss->mss, MIN_IPV4_MSS, 185 + "MSS in cookie min value"); 186 + ASSERT_LT(skel->bss->mss, USHRT_MAX, 187 + "MSS in cookie max value"); 188 + } 123 189 124 190 done: 125 191 if (listen_fd != -1) ··· 201 125 close(srv_fd); 202 126 } 203 127 204 - static void test_syncookie(void) 128 + static void test_conn_ipv4(struct test_btf_skc_cls_ingress *skel) 205 129 { 206 - int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; 207 - socklen_t addrlen = sizeof(srv_sa6); 208 - int srv_port; 130 + run_test(skel, false, TEST_MODE_IPV4); 131 + } 209 132 210 - /* Enforce syncookie mode */ 211 - if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "2")) 212 - return; 133 + static void test_conn_ipv6(struct test_btf_skc_cls_ingress *skel) 134 + { 135 + run_test(skel, false, TEST_MODE_IPV6); 136 + } 213 137 214 - listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0); 215 - if (CHECK_FAIL(listen_fd == -1)) 216 - return; 138 + static void test_conn_dual(struct test_btf_skc_cls_ingress *skel) 139 + { 140 + run_test(skel, false, TEST_MODE_DUAL); 141 + } 217 142 218 - err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen); 219 - if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err, 220 - errno)) 221 - goto done; 222 - memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6)); 223 - srv_port = ntohs(srv_sa6.sin6_port); 143 + static void test_syncookie_ipv4(struct test_btf_skc_cls_ingress *skel) 144 + { 145 + run_test(skel, true, TEST_MODE_IPV4); 146 + } 224 147 225 - cli_fd = connect_to_fd(listen_fd, 0); 226 - if (CHECK_FAIL(cli_fd == -1)) 227 - goto done; 148 + static void test_syncookie_ipv6(struct test_btf_skc_cls_ingress *skel) 149 + { 150 + run_test(skel, true, TEST_MODE_IPV6); 151 + } 228 152 229 - srv_fd = accept(listen_fd, NULL, NULL); 230 - if (CHECK_FAIL(srv_fd == -1)) 231 - goto done; 232 - 233 - if (CHECK(skel->bss->listen_tp_sport != srv_port, 234 - "Unexpected tp src port", 235 - "listen_tp_sport:%u expected:%u\n", 236 - skel->bss->listen_tp_sport, srv_port)) 237 - goto done; 238 - 239 - if (CHECK(skel->bss->req_sk_sport, 240 - "Unexpected req_sk src port", 241 - "req_sk_sport:%u expected:0\n", 242 - skel->bss->req_sk_sport)) 243 - goto done; 244 - 245 - if (CHECK(!skel->bss->gen_cookie || 246 - skel->bss->gen_cookie != skel->bss->recv_cookie, 247 - "Unexpected syncookie states", 248 - "gen_cookie:%u recv_cookie:%u\n", 249 - skel->bss->gen_cookie, skel->bss->recv_cookie)) 250 - goto done; 251 - 252 - CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n", 253 - skel->bss->linum); 254 - 255 - done: 256 - if (listen_fd != -1) 257 - close(listen_fd); 258 - if (cli_fd != -1) 259 - close(cli_fd); 260 - if (srv_fd != -1) 261 - close(srv_fd); 153 + static void test_syncookie_dual(struct test_btf_skc_cls_ingress *skel) 154 + { 155 + run_test(skel, true, TEST_MODE_DUAL); 262 156 } 263 157 264 158 struct test { 265 159 const char *desc; 266 - void (*run)(void); 160 + void (*run)(struct test_btf_skc_cls_ingress *skel); 267 161 }; 268 162 269 163 #define DEF_TEST(name) { #name, test_##name } 270 164 static struct test tests[] = { 271 - DEF_TEST(conn), 272 - DEF_TEST(syncookie), 165 + DEF_TEST(conn_ipv4), 166 + DEF_TEST(conn_ipv6), 167 + DEF_TEST(conn_dual), 168 + DEF_TEST(syncookie_ipv4), 169 + DEF_TEST(syncookie_ipv6), 170 + DEF_TEST(syncookie_dual), 273 171 }; 274 172 275 173 void test_btf_skc_cls_ingress(void) 276 174 { 175 + struct test_btf_skc_cls_ingress *skel; 176 + struct netns_obj *ns; 277 177 int i; 278 178 279 179 skel = test_btf_skc_cls_ingress__open_and_load(); 280 - if (CHECK(!skel, "test_btf_skc_cls_ingress__open_and_load", "failed\n")) 180 + if (!ASSERT_OK_PTR(skel, "test_btf_skc_cls_ingress__open_and_load")) 281 181 return; 282 182 283 183 for (i = 0; i < ARRAY_SIZE(tests); i++) { 284 184 if (!test__start_subtest(tests[i].desc)) 285 185 continue; 286 186 287 - if (prepare_netns()) 187 + ns = prepare_netns(skel); 188 + if (!ns) 288 189 break; 289 190 290 - tests[i].run(); 191 + tests[i].run(skel); 291 192 292 - print_err_line(); 293 - reset_test(); 193 + print_err_line(skel); 194 + reset_test(skel); 195 + netns_free(ns); 294 196 } 295 197 296 198 test_btf_skc_cls_ingress__destroy(skel);
+408
tools/testing/selftests/bpf/prog_tests/test_csum_diff.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright Amazon.com Inc. or its affiliates */ 3 + #include <test_progs.h> 4 + #include "csum_diff_test.skel.h" 5 + 6 + #define BUFF_SZ 512 7 + 8 + struct testcase { 9 + unsigned long long to_buff[BUFF_SZ / 8]; 10 + unsigned int to_buff_len; 11 + unsigned long long from_buff[BUFF_SZ / 8]; 12 + unsigned int from_buff_len; 13 + unsigned short seed; 14 + unsigned short result; 15 + }; 16 + 17 + #define NUM_PUSH_TESTS 4 18 + 19 + struct testcase push_tests[NUM_PUSH_TESTS] = { 20 + { 21 + .to_buff = { 22 + 0xdeadbeefdeadbeef, 23 + }, 24 + .to_buff_len = 8, 25 + .from_buff = {}, 26 + .from_buff_len = 0, 27 + .seed = 0, 28 + .result = 0x3b3b 29 + }, 30 + { 31 + .to_buff = { 32 + 0xdeadbeefdeadbeef, 33 + 0xbeefdeadbeefdead, 34 + }, 35 + .to_buff_len = 16, 36 + .from_buff = {}, 37 + .from_buff_len = 0, 38 + .seed = 0x1234, 39 + .result = 0x88aa 40 + }, 41 + { 42 + .to_buff = { 43 + 0xdeadbeefdeadbeef, 44 + 0xbeefdeadbeefdead, 45 + }, 46 + .to_buff_len = 15, 47 + .from_buff = {}, 48 + .from_buff_len = 0, 49 + .seed = 0x1234, 50 + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 51 + .result = 0xcaa9 52 + #else 53 + .result = 0x87fd 54 + #endif 55 + }, 56 + { 57 + .to_buff = { 58 + 0x327b23c66b8b4567, 59 + 0x66334873643c9869, 60 + 0x19495cff74b0dc51, 61 + 0x625558ec2ae8944a, 62 + 0x46e87ccd238e1f29, 63 + 0x507ed7ab3d1b58ba, 64 + 0x41b71efb2eb141f2, 65 + 0x7545e14679e2a9e3, 66 + 0x5bd062c2515f007c, 67 + 0x4db127f812200854, 68 + 0x1f16e9e80216231b, 69 + 0x66ef438d1190cde7, 70 + 0x3352255a140e0f76, 71 + 0x0ded7263109cf92e, 72 + 0x1befd79f7fdcc233, 73 + 0x6b68079a41a7c4c9, 74 + 0x25e45d324e6afb66, 75 + 0x431bd7b7519b500d, 76 + 0x7c83e4583f2dba31, 77 + 0x62bbd95a257130a3, 78 + 0x628c895d436c6125, 79 + 0x721da317333ab105, 80 + 0x2d1d5ae92443a858, 81 + 0x75a2a8d46763845e, 82 + 0x79838cb208edbdab, 83 + 0x0b03e0c64353d0cd, 84 + 0x54e49eb4189a769b, 85 + 0x2ca8861171f32454, 86 + 0x02901d820836c40e, 87 + 0x081386413a95f874, 88 + 0x7c3dbd3d1e7ff521, 89 + 0x6ceaf087737b8ddc, 90 + 0x4516dde922221a70, 91 + 0x614fd4a13006c83e, 92 + 0x5577f8e1419ac241, 93 + 0x05072367440badfc, 94 + 0x77465f013804823e, 95 + 0x5c482a977724c67e, 96 + 0x5e884adc2463b9ea, 97 + 0x2d51779651ead36b, 98 + 0x153ea438580bd78f, 99 + 0x70a64e2a3855585c, 100 + 0x2a487cb06a2342ec, 101 + 0x725a06fb1d4ed43b, 102 + 0x57e4ccaf2cd89a32, 103 + 0x4b588f547a6d8d3c, 104 + 0x6de91b18542289ec, 105 + 0x7644a45c38437fdb, 106 + 0x684a481a32fff902, 107 + 0x749abb43579478fe, 108 + 0x1ba026fa3dc240fb, 109 + 0x75c6c33a79a1deaa, 110 + 0x70c6a52912e685fb, 111 + 0x374a3fe6520eedd1, 112 + 0x23f9c13c4f4ef005, 113 + 0x275ac794649bb77c, 114 + 0x1cf10fd839386575, 115 + 0x235ba861180115be, 116 + 0x354fe9f947398c89, 117 + 0x741226bb15b5af5c, 118 + 0x10233c990d34b6a8, 119 + 0x615740953f6ab60f, 120 + 0x77ae35eb7e0c57b1, 121 + 0x310c50b3579be4f1, 122 + }, 123 + .to_buff_len = 512, 124 + .from_buff = {}, 125 + .from_buff_len = 0, 126 + .seed = 0xffff, 127 + .result = 0xca45 128 + }, 129 + }; 130 + 131 + #define NUM_PULL_TESTS 4 132 + 133 + struct testcase pull_tests[NUM_PULL_TESTS] = { 134 + { 135 + .from_buff = { 136 + 0xdeadbeefdeadbeef, 137 + }, 138 + .from_buff_len = 8, 139 + .to_buff = {}, 140 + .to_buff_len = 0, 141 + .seed = 0, 142 + .result = 0xc4c4 143 + }, 144 + { 145 + .from_buff = { 146 + 0xdeadbeefdeadbeef, 147 + 0xbeefdeadbeefdead, 148 + }, 149 + .from_buff_len = 16, 150 + .to_buff = {}, 151 + .to_buff_len = 0, 152 + .seed = 0x1234, 153 + .result = 0x9bbd 154 + }, 155 + { 156 + .from_buff = { 157 + 0xdeadbeefdeadbeef, 158 + 0xbeefdeadbeefdead, 159 + }, 160 + .from_buff_len = 15, 161 + .to_buff = {}, 162 + .to_buff_len = 0, 163 + .seed = 0x1234, 164 + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 165 + .result = 0x59be 166 + #else 167 + .result = 0x9c6a 168 + #endif 169 + }, 170 + { 171 + .from_buff = { 172 + 0x327b23c66b8b4567, 173 + 0x66334873643c9869, 174 + 0x19495cff74b0dc51, 175 + 0x625558ec2ae8944a, 176 + 0x46e87ccd238e1f29, 177 + 0x507ed7ab3d1b58ba, 178 + 0x41b71efb2eb141f2, 179 + 0x7545e14679e2a9e3, 180 + 0x5bd062c2515f007c, 181 + 0x4db127f812200854, 182 + 0x1f16e9e80216231b, 183 + 0x66ef438d1190cde7, 184 + 0x3352255a140e0f76, 185 + 0x0ded7263109cf92e, 186 + 0x1befd79f7fdcc233, 187 + 0x6b68079a41a7c4c9, 188 + 0x25e45d324e6afb66, 189 + 0x431bd7b7519b500d, 190 + 0x7c83e4583f2dba31, 191 + 0x62bbd95a257130a3, 192 + 0x628c895d436c6125, 193 + 0x721da317333ab105, 194 + 0x2d1d5ae92443a858, 195 + 0x75a2a8d46763845e, 196 + 0x79838cb208edbdab, 197 + 0x0b03e0c64353d0cd, 198 + 0x54e49eb4189a769b, 199 + 0x2ca8861171f32454, 200 + 0x02901d820836c40e, 201 + 0x081386413a95f874, 202 + 0x7c3dbd3d1e7ff521, 203 + 0x6ceaf087737b8ddc, 204 + 0x4516dde922221a70, 205 + 0x614fd4a13006c83e, 206 + 0x5577f8e1419ac241, 207 + 0x05072367440badfc, 208 + 0x77465f013804823e, 209 + 0x5c482a977724c67e, 210 + 0x5e884adc2463b9ea, 211 + 0x2d51779651ead36b, 212 + 0x153ea438580bd78f, 213 + 0x70a64e2a3855585c, 214 + 0x2a487cb06a2342ec, 215 + 0x725a06fb1d4ed43b, 216 + 0x57e4ccaf2cd89a32, 217 + 0x4b588f547a6d8d3c, 218 + 0x6de91b18542289ec, 219 + 0x7644a45c38437fdb, 220 + 0x684a481a32fff902, 221 + 0x749abb43579478fe, 222 + 0x1ba026fa3dc240fb, 223 + 0x75c6c33a79a1deaa, 224 + 0x70c6a52912e685fb, 225 + 0x374a3fe6520eedd1, 226 + 0x23f9c13c4f4ef005, 227 + 0x275ac794649bb77c, 228 + 0x1cf10fd839386575, 229 + 0x235ba861180115be, 230 + 0x354fe9f947398c89, 231 + 0x741226bb15b5af5c, 232 + 0x10233c990d34b6a8, 233 + 0x615740953f6ab60f, 234 + 0x77ae35eb7e0c57b1, 235 + 0x310c50b3579be4f1, 236 + }, 237 + .from_buff_len = 512, 238 + .to_buff = {}, 239 + .to_buff_len = 0, 240 + .seed = 0xffff, 241 + .result = 0x35ba 242 + }, 243 + }; 244 + 245 + #define NUM_DIFF_TESTS 4 246 + 247 + struct testcase diff_tests[NUM_DIFF_TESTS] = { 248 + { 249 + .from_buff = { 250 + 0xdeadbeefdeadbeef, 251 + }, 252 + .from_buff_len = 8, 253 + .to_buff = { 254 + 0xabababababababab, 255 + }, 256 + .to_buff_len = 8, 257 + .seed = 0, 258 + .result = 0x7373 259 + }, 260 + { 261 + .from_buff = { 262 + 0xdeadbeefdeadbeef, 263 + }, 264 + .from_buff_len = 7, 265 + .to_buff = { 266 + 0xabababababababab, 267 + }, 268 + .to_buff_len = 7, 269 + .seed = 0, 270 + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 271 + .result = 0xa673 272 + #else 273 + .result = 0x73b7 274 + #endif 275 + }, 276 + { 277 + .from_buff = { 278 + 0, 279 + }, 280 + .from_buff_len = 8, 281 + .to_buff = { 282 + 0xabababababababab, 283 + }, 284 + .to_buff_len = 8, 285 + .seed = 0, 286 + .result = 0xaeae 287 + }, 288 + { 289 + .from_buff = { 290 + 0xdeadbeefdeadbeef 291 + }, 292 + .from_buff_len = 8, 293 + .to_buff = { 294 + 0, 295 + }, 296 + .to_buff_len = 8, 297 + .seed = 0xffff, 298 + .result = 0xc4c4 299 + }, 300 + }; 301 + 302 + #define NUM_EDGE_TESTS 4 303 + 304 + struct testcase edge_tests[NUM_EDGE_TESTS] = { 305 + { 306 + .from_buff = {}, 307 + .from_buff_len = 0, 308 + .to_buff = {}, 309 + .to_buff_len = 0, 310 + .seed = 0, 311 + .result = 0 312 + }, 313 + { 314 + .from_buff = { 315 + 0x1234 316 + }, 317 + .from_buff_len = 0, 318 + .to_buff = { 319 + 0x1234 320 + }, 321 + .to_buff_len = 0, 322 + .seed = 0, 323 + .result = 0 324 + }, 325 + { 326 + .from_buff = {}, 327 + .from_buff_len = 0, 328 + .to_buff = {}, 329 + .to_buff_len = 0, 330 + .seed = 0x1234, 331 + .result = 0x1234 332 + }, 333 + { 334 + .from_buff = {}, 335 + .from_buff_len = 512, 336 + .to_buff = {}, 337 + .to_buff_len = 0, 338 + .seed = 0xffff, 339 + .result = 0xffff 340 + }, 341 + }; 342 + 343 + static unsigned short trigger_csum_diff(const struct csum_diff_test *skel) 344 + { 345 + u8 tmp_out[64 << 2] = {}; 346 + u8 tmp_in[64] = {}; 347 + int err; 348 + int pfd; 349 + 350 + LIBBPF_OPTS(bpf_test_run_opts, topts, 351 + .data_in = tmp_in, 352 + .data_size_in = sizeof(tmp_in), 353 + .data_out = tmp_out, 354 + .data_size_out = sizeof(tmp_out), 355 + .repeat = 1, 356 + ); 357 + pfd = bpf_program__fd(skel->progs.compute_checksum); 358 + err = bpf_prog_test_run_opts(pfd, &topts); 359 + if (err) 360 + return -1; 361 + 362 + return skel->bss->result; 363 + } 364 + 365 + static void test_csum_diff(struct testcase *tests, int num_tests) 366 + { 367 + struct csum_diff_test *skel; 368 + unsigned short got; 369 + int err; 370 + 371 + for (int i = 0; i < num_tests; i++) { 372 + skel = csum_diff_test__open(); 373 + if (!ASSERT_OK_PTR(skel, "csum_diff_test open")) 374 + return; 375 + 376 + skel->rodata->to_buff_len = tests[i].to_buff_len; 377 + skel->rodata->from_buff_len = tests[i].from_buff_len; 378 + 379 + err = csum_diff_test__load(skel); 380 + if (!ASSERT_EQ(err, 0, "csum_diff_test load")) 381 + goto out; 382 + 383 + memcpy(skel->bss->to_buff, tests[i].to_buff, tests[i].to_buff_len); 384 + memcpy(skel->bss->from_buff, tests[i].from_buff, tests[i].from_buff_len); 385 + skel->bss->seed = tests[i].seed; 386 + 387 + got = trigger_csum_diff(skel); 388 + ASSERT_EQ(got, tests[i].result, "csum_diff result"); 389 + 390 + csum_diff_test__destroy(skel); 391 + } 392 + 393 + return; 394 + out: 395 + csum_diff_test__destroy(skel); 396 + } 397 + 398 + void test_test_csum_diff(void) 399 + { 400 + if (test__start_subtest("csum_diff_push")) 401 + test_csum_diff(push_tests, NUM_PUSH_TESTS); 402 + if (test__start_subtest("csum_diff_pull")) 403 + test_csum_diff(pull_tests, NUM_PULL_TESTS); 404 + if (test__start_subtest("csum_diff_diff")) 405 + test_csum_diff(diff_tests, NUM_DIFF_TESTS); 406 + if (test__start_subtest("csum_diff_edge")) 407 + test_csum_diff(edge_tests, NUM_EDGE_TESTS); 408 + }
+42
tools/testing/selftests/bpf/progs/csum_diff_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright Amazon.com Inc. or its affiliates */ 3 + #include <linux/types.h> 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + 8 + #define BUFF_SZ 512 9 + 10 + /* Will be updated by benchmark before program loading */ 11 + char to_buff[BUFF_SZ]; 12 + const volatile unsigned int to_buff_len = 0; 13 + char from_buff[BUFF_SZ]; 14 + const volatile unsigned int from_buff_len = 0; 15 + unsigned short seed = 0; 16 + 17 + short result; 18 + 19 + char _license[] SEC("license") = "GPL"; 20 + 21 + SEC("tc") 22 + int compute_checksum(void *ctx) 23 + { 24 + int to_len_half = to_buff_len / 2; 25 + int from_len_half = from_buff_len / 2; 26 + short result2; 27 + 28 + /* Calculate checksum in one go */ 29 + result2 = bpf_csum_diff((void *)from_buff, from_buff_len, 30 + (void *)to_buff, to_buff_len, seed); 31 + 32 + /* Calculate checksum by concatenating bpf_csum_diff()*/ 33 + result = bpf_csum_diff((void *)from_buff, from_buff_len - from_len_half, 34 + (void *)to_buff, to_buff_len - to_len_half, seed); 35 + 36 + result = bpf_csum_diff((void *)from_buff + (from_buff_len - from_len_half), from_len_half, 37 + (void *)to_buff + (to_buff_len - to_len_half), to_len_half, result); 38 + 39 + result = (result == result2) ? result : 0; 40 + 41 + return 0; 42 + }
+55 -27
tools/testing/selftests/bpf/progs/test_btf_skc_cls_ingress.c
··· 10 10 #endif 11 11 12 12 struct sockaddr_in6 srv_sa6 = {}; 13 + struct sockaddr_in srv_sa4 = {}; 13 14 __u16 listen_tp_sport = 0; 14 15 __u16 req_sk_sport = 0; 15 16 __u32 recv_cookie = 0; 16 17 __u32 gen_cookie = 0; 18 + __u32 mss = 0; 17 19 __u32 linum = 0; 18 20 19 21 #define LOG() ({ if (!linum) linum = __LINE__; }) 20 22 21 - static void test_syncookie_helper(struct ipv6hdr *ip6h, struct tcphdr *th, 22 - struct tcp_sock *tp, 23 + static void test_syncookie_helper(void *iphdr, int iphdr_size, 24 + struct tcphdr *th, struct tcp_sock *tp, 23 25 struct __sk_buff *skb) 24 26 { 25 27 if (th->syn) { ··· 40 38 return; 41 39 } 42 40 43 - mss_cookie = bpf_tcp_gen_syncookie(tp, ip6h, sizeof(*ip6h), 41 + mss_cookie = bpf_tcp_gen_syncookie(tp, iphdr, iphdr_size, 44 42 th, 40); 45 43 if (mss_cookie < 0) { 46 44 if (mss_cookie != -ENOENT) 47 45 LOG(); 48 46 } else { 49 47 gen_cookie = (__u32)mss_cookie; 48 + mss = mss_cookie >> 32; 50 49 } 51 50 } else if (gen_cookie) { 52 51 /* It was in cookie mode */ 53 - int ret = bpf_tcp_check_syncookie(tp, ip6h, sizeof(*ip6h), 52 + int ret = bpf_tcp_check_syncookie(tp, iphdr, iphdr_size, 54 53 th, sizeof(*th)); 55 54 56 55 if (ret < 0) { ··· 63 60 } 64 61 } 65 62 66 - static int handle_ip6_tcp(struct ipv6hdr *ip6h, struct __sk_buff *skb) 63 + static int handle_ip_tcp(struct ethhdr *eth, struct __sk_buff *skb) 67 64 { 68 - struct bpf_sock_tuple *tuple; 65 + struct bpf_sock_tuple *tuple = NULL; 66 + unsigned int tuple_len = 0; 69 67 struct bpf_sock *bpf_skc; 70 - unsigned int tuple_len; 68 + void *data_end, *iphdr; 69 + struct ipv6hdr *ip6h; 70 + struct iphdr *ip4h; 71 71 struct tcphdr *th; 72 - void *data_end; 72 + int iphdr_size; 73 73 74 74 data_end = (void *)(long)(skb->data_end); 75 75 76 - th = (struct tcphdr *)(ip6h + 1); 77 - if (th + 1 > data_end) 76 + switch (eth->h_proto) { 77 + case bpf_htons(ETH_P_IP): 78 + ip4h = (struct iphdr *)(eth + 1); 79 + if (ip4h + 1 > data_end) 80 + return TC_ACT_OK; 81 + if (ip4h->protocol != IPPROTO_TCP) 82 + return TC_ACT_OK; 83 + th = (struct tcphdr *)(ip4h + 1); 84 + if (th + 1 > data_end) 85 + return TC_ACT_OK; 86 + /* Is it the testing traffic? */ 87 + if (th->dest != srv_sa4.sin_port) 88 + return TC_ACT_OK; 89 + tuple_len = sizeof(tuple->ipv4); 90 + tuple = (struct bpf_sock_tuple *)&ip4h->saddr; 91 + iphdr = ip4h; 92 + iphdr_size = sizeof(*ip4h); 93 + break; 94 + case bpf_htons(ETH_P_IPV6): 95 + ip6h = (struct ipv6hdr *)(eth + 1); 96 + if (ip6h + 1 > data_end) 97 + return TC_ACT_OK; 98 + if (ip6h->nexthdr != IPPROTO_TCP) 99 + return TC_ACT_OK; 100 + th = (struct tcphdr *)(ip6h + 1); 101 + if (th + 1 > data_end) 102 + return TC_ACT_OK; 103 + /* Is it the testing traffic? */ 104 + if (th->dest != srv_sa6.sin6_port) 105 + return TC_ACT_OK; 106 + tuple_len = sizeof(tuple->ipv6); 107 + tuple = (struct bpf_sock_tuple *)&ip6h->saddr; 108 + iphdr = ip6h; 109 + iphdr_size = sizeof(*ip6h); 110 + break; 111 + default: 78 112 return TC_ACT_OK; 113 + } 79 114 80 - /* Is it the testing traffic? */ 81 - if (th->dest != srv_sa6.sin6_port) 82 - return TC_ACT_OK; 83 - 84 - tuple_len = sizeof(tuple->ipv6); 85 - tuple = (struct bpf_sock_tuple *)&ip6h->saddr; 86 115 if ((void *)tuple + tuple_len > data_end) { 87 116 LOG(); 88 117 return TC_ACT_OK; ··· 161 126 162 127 listen_tp_sport = tp->inet_conn.icsk_inet.sk.__sk_common.skc_num; 163 128 164 - test_syncookie_helper(ip6h, th, tp, skb); 129 + test_syncookie_helper(iphdr, iphdr_size, th, tp, skb); 165 130 bpf_sk_release(tp); 166 131 return TC_ACT_OK; 167 132 } ··· 177 142 SEC("tc") 178 143 int cls_ingress(struct __sk_buff *skb) 179 144 { 180 - struct ipv6hdr *ip6h; 181 145 struct ethhdr *eth; 182 146 void *data_end; 183 147 ··· 186 152 if (eth + 1 > data_end) 187 153 return TC_ACT_OK; 188 154 189 - if (eth->h_proto != bpf_htons(ETH_P_IPV6)) 155 + if (eth->h_proto != bpf_htons(ETH_P_IP) && 156 + eth->h_proto != bpf_htons(ETH_P_IPV6)) 190 157 return TC_ACT_OK; 191 158 192 - ip6h = (struct ipv6hdr *)(eth + 1); 193 - if (ip6h + 1 > data_end) 194 - return TC_ACT_OK; 195 - 196 - if (ip6h->nexthdr == IPPROTO_TCP) 197 - return handle_ip6_tcp(ip6h, skb); 198 - 199 - return TC_ACT_OK; 159 + return handle_ip_tcp(eth, skb); 200 160 } 201 161 202 162 char _license[] SEC("license") = "GPL";
-167
tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - // Copyright (c) 2018 Facebook 3 - // Copyright (c) 2019 Cloudflare 4 - 5 - #include <string.h> 6 - 7 - #include <linux/bpf.h> 8 - #include <linux/pkt_cls.h> 9 - #include <linux/if_ether.h> 10 - #include <linux/in.h> 11 - #include <linux/ip.h> 12 - #include <linux/ipv6.h> 13 - #include <sys/socket.h> 14 - #include <linux/tcp.h> 15 - 16 - #include <bpf/bpf_helpers.h> 17 - #include <bpf/bpf_endian.h> 18 - 19 - struct { 20 - __uint(type, BPF_MAP_TYPE_ARRAY); 21 - __type(key, __u32); 22 - __type(value, __u32); 23 - __uint(max_entries, 3); 24 - } results SEC(".maps"); 25 - 26 - static __always_inline __s64 gen_syncookie(void *data_end, struct bpf_sock *sk, 27 - void *iph, __u32 ip_size, 28 - struct tcphdr *tcph) 29 - { 30 - __u32 thlen = tcph->doff * 4; 31 - 32 - if (tcph->syn && !tcph->ack) { 33 - // packet should only have an MSS option 34 - if (thlen != 24) 35 - return 0; 36 - 37 - if ((void *)tcph + thlen > data_end) 38 - return 0; 39 - 40 - return bpf_tcp_gen_syncookie(sk, iph, ip_size, tcph, thlen); 41 - } 42 - return 0; 43 - } 44 - 45 - static __always_inline void check_syncookie(void *ctx, void *data, 46 - void *data_end) 47 - { 48 - struct bpf_sock_tuple tup; 49 - struct bpf_sock *sk; 50 - struct ethhdr *ethh; 51 - struct iphdr *ipv4h; 52 - struct ipv6hdr *ipv6h; 53 - struct tcphdr *tcph; 54 - int ret; 55 - __u32 key_mss = 2; 56 - __u32 key_gen = 1; 57 - __u32 key = 0; 58 - __s64 seq_mss; 59 - 60 - ethh = data; 61 - if (ethh + 1 > data_end) 62 - return; 63 - 64 - switch (bpf_ntohs(ethh->h_proto)) { 65 - case ETH_P_IP: 66 - ipv4h = data + sizeof(struct ethhdr); 67 - if (ipv4h + 1 > data_end) 68 - return; 69 - 70 - if (ipv4h->ihl != 5) 71 - return; 72 - 73 - tcph = data + sizeof(struct ethhdr) + sizeof(struct iphdr); 74 - if (tcph + 1 > data_end) 75 - return; 76 - 77 - tup.ipv4.saddr = ipv4h->saddr; 78 - tup.ipv4.daddr = ipv4h->daddr; 79 - tup.ipv4.sport = tcph->source; 80 - tup.ipv4.dport = tcph->dest; 81 - 82 - sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv4), 83 - BPF_F_CURRENT_NETNS, 0); 84 - if (!sk) 85 - return; 86 - 87 - if (sk->state != BPF_TCP_LISTEN) 88 - goto release; 89 - 90 - seq_mss = gen_syncookie(data_end, sk, ipv4h, sizeof(*ipv4h), 91 - tcph); 92 - 93 - ret = bpf_tcp_check_syncookie(sk, ipv4h, sizeof(*ipv4h), 94 - tcph, sizeof(*tcph)); 95 - break; 96 - 97 - case ETH_P_IPV6: 98 - ipv6h = data + sizeof(struct ethhdr); 99 - if (ipv6h + 1 > data_end) 100 - return; 101 - 102 - if (ipv6h->nexthdr != IPPROTO_TCP) 103 - return; 104 - 105 - tcph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); 106 - if (tcph + 1 > data_end) 107 - return; 108 - 109 - memcpy(tup.ipv6.saddr, &ipv6h->saddr, sizeof(tup.ipv6.saddr)); 110 - memcpy(tup.ipv6.daddr, &ipv6h->daddr, sizeof(tup.ipv6.daddr)); 111 - tup.ipv6.sport = tcph->source; 112 - tup.ipv6.dport = tcph->dest; 113 - 114 - sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv6), 115 - BPF_F_CURRENT_NETNS, 0); 116 - if (!sk) 117 - return; 118 - 119 - if (sk->state != BPF_TCP_LISTEN) 120 - goto release; 121 - 122 - seq_mss = gen_syncookie(data_end, sk, ipv6h, sizeof(*ipv6h), 123 - tcph); 124 - 125 - ret = bpf_tcp_check_syncookie(sk, ipv6h, sizeof(*ipv6h), 126 - tcph, sizeof(*tcph)); 127 - break; 128 - 129 - default: 130 - return; 131 - } 132 - 133 - if (seq_mss > 0) { 134 - __u32 cookie = (__u32)seq_mss; 135 - __u32 mss = seq_mss >> 32; 136 - 137 - bpf_map_update_elem(&results, &key_gen, &cookie, 0); 138 - bpf_map_update_elem(&results, &key_mss, &mss, 0); 139 - } 140 - 141 - if (ret == 0) { 142 - __u32 cookie = bpf_ntohl(tcph->ack_seq) - 1; 143 - 144 - bpf_map_update_elem(&results, &key, &cookie, 0); 145 - } 146 - 147 - release: 148 - bpf_sk_release(sk); 149 - } 150 - 151 - SEC("tc") 152 - int check_syncookie_clsact(struct __sk_buff *skb) 153 - { 154 - check_syncookie(skb, (void *)(long)skb->data, 155 - (void *)(long)skb->data_end); 156 - return TC_ACT_OK; 157 - } 158 - 159 - SEC("xdp") 160 - int check_syncookie_xdp(struct xdp_md *ctx) 161 - { 162 - check_syncookie(ctx, (void *)(long)ctx->data, 163 - (void *)(long)ctx->data_end); 164 - return XDP_PASS; 165 - } 166 - 167 - char _license[] SEC("license") = "GPL";
+1 -2
tools/testing/selftests/bpf/progs/verifier_array_access.c
··· 368 368 r4 = 0; \ 369 369 r5 = 0; \ 370 370 call %[bpf_csum_diff]; \ 371 - l0_%=: r0 &= 0xffff; \ 372 - exit; \ 371 + l0_%=: exit; \ 373 372 " : 374 373 : __imm(bpf_csum_diff), 375 374 __imm(bpf_map_lookup_elem),
+1 -2
tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
··· 21 21 22 22 #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3]) 23 23 24 - #define IP_DF 0x4000 25 24 #define IP_MF 0x2000 26 25 #define IP_OFFSET 0x1fff 27 26 ··· 441 442 /* TCP doesn't normally use fragments, and XDP can't reassemble 442 443 * them. 443 444 */ 444 - if ((hdr->ipv4->frag_off & bpf_htons(IP_DF | IP_MF | IP_OFFSET)) != bpf_htons(IP_DF)) 445 + if ((hdr->ipv4->frag_off & bpf_htons(IP_MF | IP_OFFSET)) != 0) 445 446 return XDP_DROP; 446 447 447 448 tup.ipv4.saddr = hdr->ipv4->saddr;
+21 -11
tools/testing/selftests/bpf/test_sockmap.c
··· 56 56 #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.bpf.o" 57 57 #define CG_PATH "/sockmap" 58 58 59 + #define EDATAINTEGRITY 2001 60 + 59 61 /* global sockets */ 60 62 int s1, s2, c1, c2, p1, p2; 61 63 int test_cnt; ··· 512 510 return -ENOMEM; 513 511 } 514 512 515 - static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz) 513 + /* TODO: Add verification logic for push, pull and pop data */ 514 + static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz, 515 + unsigned char *k_p, int *bytes_cnt_p) 516 516 { 517 - int i, j = 0, bytes_cnt = 0; 518 - unsigned char k = 0; 517 + int i, j, bytes_cnt = *bytes_cnt_p; 518 + unsigned char k = *k_p; 519 519 520 - for (i = 0; i < msg->msg_iovlen; i++) { 520 + for (i = 0, j = 0; i < msg->msg_iovlen && size; i++, j = 0) { 521 521 unsigned char *d = msg->msg_iov[i].iov_base; 522 522 523 523 /* Special case test for skb ingress + ktls */ 524 524 if (i == 0 && txmsg_ktls_skb) { 525 525 if (msg->msg_iov[i].iov_len < 4) 526 - return -EIO; 526 + return -EDATAINTEGRITY; 527 527 if (memcmp(d, "PASS", 4) != 0) { 528 528 fprintf(stderr, 529 529 "detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", 530 530 i, 0, d[0], d[1], d[2], d[3]); 531 - return -EIO; 531 + return -EDATAINTEGRITY; 532 532 } 533 533 j = 4; /* advance index past PASS header */ 534 534 } ··· 540 536 fprintf(stderr, 541 537 "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n", 542 538 i, j, d[j], k - 1, d[j+1], k); 543 - return -EIO; 539 + return -EDATAINTEGRITY; 544 540 } 545 541 bytes_cnt++; 546 542 if (bytes_cnt == chunk_sz) { ··· 550 546 size--; 551 547 } 552 548 } 549 + *k_p = k; 550 + *bytes_cnt_p = bytes_cnt; 553 551 return 0; 554 552 } 555 553 ··· 608 602 float total_bytes, txmsg_pop_total; 609 603 int fd_flags = O_NONBLOCK; 610 604 struct timeval timeout; 605 + unsigned char k = 0; 606 + int bytes_cnt = 0; 611 607 fd_set w; 612 608 613 609 fcntl(fd, fd_flags); ··· 704 696 iov_length * cnt : 705 697 iov_length * iov_count; 706 698 707 - errno = msg_verify_data(&msg, recv, chunk_sz); 699 + errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt); 708 700 if (errno) { 709 701 perror("data verify msg failed"); 710 702 goto out_errno; ··· 712 704 if (recvp) { 713 705 errno = msg_verify_data(&msg_peek, 714 706 recvp, 715 - chunk_sz); 707 + chunk_sz, 708 + &k, 709 + &bytes_cnt); 716 710 if (errno) { 717 711 perror("data verify msg_peek failed"); 718 712 goto out_errno; ··· 822 812 s.bytes_sent, sent_Bps, sent_Bps/giga, 823 813 s.bytes_recvd, recvd_Bps, recvd_Bps/giga, 824 814 peek_flag ? "(peek_msg)" : ""); 825 - if (err && txmsg_cork) 815 + if (err && err != -EDATAINTEGRITY && txmsg_cork) 826 816 err = 0; 827 817 exit(err ? 1 : 0); 828 818 } else if (rxpid == -1) { ··· 1606 1596 test_send_large(opt, cgrp); 1607 1597 1608 1598 /* Test pull + redirect */ 1609 - txmsg_redir = 0; 1599 + txmsg_redir = 1; 1610 1600 txmsg_start = 1; 1611 1601 txmsg_end = 2; 1612 1602 test_send(opt, cgrp);
-85
tools/testing/selftests/bpf/test_tcp_check_syncookie.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0 3 - # Copyright (c) 2018 Facebook 4 - # Copyright (c) 2019 Cloudflare 5 - 6 - set -eu 7 - readonly NS1="ns1-$(mktemp -u XXXXXX)" 8 - 9 - wait_for_ip() 10 - { 11 - local _i 12 - printf "Wait for IP %s to become available " "$1" 13 - for _i in $(seq ${MAX_PING_TRIES}); do 14 - printf "." 15 - if ns1_exec ping -c 1 -W 1 "$1" >/dev/null 2>&1; then 16 - echo " OK" 17 - return 18 - fi 19 - sleep 1 20 - done 21 - echo 1>&2 "ERROR: Timeout waiting for test IP to become available." 22 - exit 1 23 - } 24 - 25 - get_prog_id() 26 - { 27 - awk '/ id / {sub(/.* id /, "", $0); print($1)}' 28 - } 29 - 30 - ns1_exec() 31 - { 32 - ip netns exec ${NS1} "$@" 33 - } 34 - 35 - setup() 36 - { 37 - ip netns add ${NS1} 38 - ns1_exec ip link set lo up 39 - 40 - ns1_exec sysctl -w net.ipv4.tcp_syncookies=2 41 - ns1_exec sysctl -w net.ipv4.tcp_window_scaling=0 42 - ns1_exec sysctl -w net.ipv4.tcp_timestamps=0 43 - ns1_exec sysctl -w net.ipv4.tcp_sack=0 44 - 45 - wait_for_ip 127.0.0.1 46 - wait_for_ip ::1 47 - } 48 - 49 - cleanup() 50 - { 51 - ip netns del ns1 2>/dev/null || : 52 - } 53 - 54 - main() 55 - { 56 - trap cleanup EXIT 2 3 6 15 57 - setup 58 - 59 - printf "Testing clsact..." 60 - ns1_exec tc qdisc add dev "${TEST_IF}" clsact 61 - ns1_exec tc filter add dev "${TEST_IF}" ingress \ 62 - bpf obj "${BPF_PROG_OBJ}" sec "${CLSACT_SECTION}" da 63 - 64 - BPF_PROG_ID=$(ns1_exec tc filter show dev "${TEST_IF}" ingress | \ 65 - get_prog_id) 66 - ns1_exec "${PROG}" "${BPF_PROG_ID}" 67 - ns1_exec tc qdisc del dev "${TEST_IF}" clsact 68 - 69 - printf "Testing XDP..." 70 - ns1_exec ip link set "${TEST_IF}" xdp \ 71 - object "${BPF_PROG_OBJ}" section "${XDP_SECTION}" 72 - BPF_PROG_ID=$(ns1_exec ip link show "${TEST_IF}" | get_prog_id) 73 - ns1_exec "${PROG}" "${BPF_PROG_ID}" 74 - } 75 - 76 - DIR=$(dirname $0) 77 - TEST_IF=lo 78 - MAX_PING_TRIES=5 79 - BPF_PROG_OBJ="${DIR}/test_tcp_check_syncookie_kern.bpf.o" 80 - CLSACT_SECTION="tc" 81 - XDP_SECTION="xdp" 82 - BPF_PROG_ID=0 83 - PROG="${DIR}/test_tcp_check_syncookie_user" 84 - 85 - main
-213
tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - // Copyright (c) 2018 Facebook 3 - // Copyright (c) 2019 Cloudflare 4 - 5 - #include <limits.h> 6 - #include <string.h> 7 - #include <stdlib.h> 8 - #include <unistd.h> 9 - 10 - #include <arpa/inet.h> 11 - #include <netinet/in.h> 12 - #include <sys/types.h> 13 - #include <sys/socket.h> 14 - 15 - #include <bpf/bpf.h> 16 - #include <bpf/libbpf.h> 17 - 18 - #include "cgroup_helpers.h" 19 - #include "network_helpers.h" 20 - 21 - static int get_map_fd_by_prog_id(int prog_id, bool *xdp) 22 - { 23 - struct bpf_prog_info info = {}; 24 - __u32 info_len = sizeof(info); 25 - __u32 map_ids[1]; 26 - int prog_fd = -1; 27 - int map_fd = -1; 28 - 29 - prog_fd = bpf_prog_get_fd_by_id(prog_id); 30 - if (prog_fd < 0) { 31 - log_err("Failed to get fd by prog id %d", prog_id); 32 - goto err; 33 - } 34 - 35 - info.nr_map_ids = 1; 36 - info.map_ids = (__u64)(unsigned long)map_ids; 37 - 38 - if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len)) { 39 - log_err("Failed to get info by prog fd %d", prog_fd); 40 - goto err; 41 - } 42 - 43 - if (!info.nr_map_ids) { 44 - log_err("No maps found for prog fd %d", prog_fd); 45 - goto err; 46 - } 47 - 48 - *xdp = info.type == BPF_PROG_TYPE_XDP; 49 - 50 - map_fd = bpf_map_get_fd_by_id(map_ids[0]); 51 - if (map_fd < 0) 52 - log_err("Failed to get fd by map id %d", map_ids[0]); 53 - err: 54 - if (prog_fd >= 0) 55 - close(prog_fd); 56 - return map_fd; 57 - } 58 - 59 - static int run_test(int server_fd, int results_fd, bool xdp) 60 - { 61 - int client = -1, srv_client = -1; 62 - int ret = 0; 63 - __u32 key = 0; 64 - __u32 key_gen = 1; 65 - __u32 key_mss = 2; 66 - __u32 value = 0; 67 - __u32 value_gen = 0; 68 - __u32 value_mss = 0; 69 - 70 - if (bpf_map_update_elem(results_fd, &key, &value, 0) < 0) { 71 - log_err("Can't clear results"); 72 - goto err; 73 - } 74 - 75 - if (bpf_map_update_elem(results_fd, &key_gen, &value_gen, 0) < 0) { 76 - log_err("Can't clear results"); 77 - goto err; 78 - } 79 - 80 - if (bpf_map_update_elem(results_fd, &key_mss, &value_mss, 0) < 0) { 81 - log_err("Can't clear results"); 82 - goto err; 83 - } 84 - 85 - client = connect_to_fd(server_fd, 0); 86 - if (client == -1) 87 - goto err; 88 - 89 - srv_client = accept(server_fd, NULL, 0); 90 - if (srv_client == -1) { 91 - log_err("Can't accept connection"); 92 - goto err; 93 - } 94 - 95 - if (bpf_map_lookup_elem(results_fd, &key, &value) < 0) { 96 - log_err("Can't lookup result"); 97 - goto err; 98 - } 99 - 100 - if (value == 0) { 101 - log_err("Didn't match syncookie: %u", value); 102 - goto err; 103 - } 104 - 105 - if (bpf_map_lookup_elem(results_fd, &key_gen, &value_gen) < 0) { 106 - log_err("Can't lookup result"); 107 - goto err; 108 - } 109 - 110 - if (xdp && value_gen == 0) { 111 - // SYN packets do not get passed through generic XDP, skip the 112 - // rest of the test. 113 - printf("Skipping XDP cookie check\n"); 114 - goto out; 115 - } 116 - 117 - if (bpf_map_lookup_elem(results_fd, &key_mss, &value_mss) < 0) { 118 - log_err("Can't lookup result"); 119 - goto err; 120 - } 121 - 122 - if (value != value_gen) { 123 - log_err("BPF generated cookie does not match kernel one"); 124 - goto err; 125 - } 126 - 127 - if (value_mss < 536 || value_mss > USHRT_MAX) { 128 - log_err("Unexpected MSS retrieved"); 129 - goto err; 130 - } 131 - 132 - goto out; 133 - 134 - err: 135 - ret = 1; 136 - out: 137 - close(client); 138 - close(srv_client); 139 - return ret; 140 - } 141 - 142 - static int v6only_true(int fd, void *opts) 143 - { 144 - int mode = true; 145 - 146 - return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode)); 147 - } 148 - 149 - static int v6only_false(int fd, void *opts) 150 - { 151 - int mode = false; 152 - 153 - return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode)); 154 - } 155 - 156 - int main(int argc, char **argv) 157 - { 158 - struct network_helper_opts opts = { 0 }; 159 - int server = -1; 160 - int server_v6 = -1; 161 - int server_dual = -1; 162 - int results = -1; 163 - int err = 0; 164 - bool xdp; 165 - 166 - if (argc < 2) { 167 - fprintf(stderr, "Usage: %s prog_id\n", argv[0]); 168 - exit(1); 169 - } 170 - 171 - /* Use libbpf 1.0 API mode */ 172 - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 173 - 174 - results = get_map_fd_by_prog_id(atoi(argv[1]), &xdp); 175 - if (results < 0) { 176 - log_err("Can't get map"); 177 - goto err; 178 - } 179 - 180 - server = start_server_str(AF_INET, SOCK_STREAM, "127.0.0.1", 0, NULL); 181 - if (server == -1) 182 - goto err; 183 - 184 - opts.post_socket_cb = v6only_true; 185 - server_v6 = start_server_str(AF_INET6, SOCK_STREAM, "::1", 0, &opts); 186 - if (server_v6 == -1) 187 - goto err; 188 - 189 - opts.post_socket_cb = v6only_false; 190 - server_dual = start_server_str(AF_INET6, SOCK_STREAM, "::0", 0, &opts); 191 - if (server_dual == -1) 192 - goto err; 193 - 194 - if (run_test(server, results, xdp)) 195 - goto err; 196 - 197 - if (run_test(server_v6, results, xdp)) 198 - goto err; 199 - 200 - if (run_test(server_dual, results, xdp)) 201 - goto err; 202 - 203 - printf("ok\n"); 204 - goto out; 205 - err: 206 - err = 1; 207 - out: 208 - close(server); 209 - close(server_v6); 210 - close(server_dual); 211 - close(results); 212 - return err; 213 - }