On 3/25/26 5:59 AM, Martin KaFai Lau wrote:
On 3/23/26 3:54 AM, Jiayuan Chen wrote:
+void test_tcp_custom_syncookie_protocol_check(void)
+{
+    struct test_tcp_custom_syncookie *skel;
+    struct sockaddr_in tcp_addr, udp_addr;
+    socklen_t addr_len = sizeof(tcp_addr);
+    int tcp_server = -1, udp_client = -1;
+    char buf[32] = "test";
+    int ret;
+
+    if (setup_netns())
+        return;
+
+    skel = test_tcp_custom_syncookie__open_and_load();
+    if (!ASSERT_OK_PTR(skel, "open_and_load"))
+        return;
  +    /* Create a TCP listener so the BPF can find a LISTEN socket */
+    tcp_server = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", 0, 0);
+    if (!ASSERT_NEQ(tcp_server, -1, "start tcp_server"))
+        goto destroy_skel;
+
+    ret = getsockname(tcp_server, (struct sockaddr *)&tcp_addr, &addr_len);
+    if (!ASSERT_OK(ret, "getsockname"))
+        goto close_tcp;
+
+    skel->bss->tcp_listener_port = ntohs(tcp_addr.sin_port);
+    skel->bss->udp_test_port = 9999;
+
+    ret = bpf_program__fd(skel->progs.tcp_custom_syncookie_badproto);
+    if (setup_tc(ret))
+        goto close_tcp;
+
+    udp_client = socket(AF_INET, SOCK_DGRAM, 0);
+    if (!ASSERT_NEQ(udp_client, -1, "udp socket"))
+        goto cleanup_tc;
+
+    memset(&udp_addr, 0, sizeof(udp_addr));
+    udp_addr.sin_family = AF_INET;
+    udp_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    udp_addr.sin_port = htons(9999);
+
+    ret = sendto(udp_client, buf, sizeof(buf), 0,
+             (struct sockaddr *)&udp_addr, sizeof(udp_addr));
+    ASSERT_EQ(ret, sizeof(buf), "sendto udp");
+
+    /* Wait for TC ingress BPF to process the skb. */
+    kern_sync_rcu();

hmm... is it guaranteed to work? Regardless, it checks the error returned from bpf_sk_assign_tcp_reqsk(). Maybe bpf_prog_test_run is simpler?

pw-bot: cr

+

I looked into using bpf_prog_test_run, but it won't work here
because bpf_sk_assign_tcp_reqsk() requires the skb to come from TC ingress
— it checks skb_at_tc_ingress() internally and returns -EINVAL otherwise.

For the synchronization concern, instead of kern_sync_rcu(), I now create
a UDP server bound to the target port and recv() the packet after sendto().
Since the BPF program returns TC_ACT_OK, the packet passes through TC ingress and arrives at the UDP socket. The recv() naturally blocks until the BPF program
has finished processing, so no timing tricks are needed.


Reply via email to