From 3933d202a14791dd484d354bfaa61c784d02ecd0 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Wed, 28 Oct 2026 18:56:04 -0700 Subject: [PATCH] Pass IPv6 TCP packets to tcp6 gro_receive in homa_hijack_gro_receive * homa_hijack_gro_receive is installed for both inet_offloads and inet6_offloads, but always passed non-Homa packets to the IPv4 TCP gro_receive, so IPv6 TCP packets went through tcp4_gro_receive (which treats the IPv6 header as an iphdr). homa_hijack_init runs at module load, so this affects all IPv6 TCP traffic. * Use the saved tcp6_net_offload for IPv6 packets. * Pin the existing pass-through test to IPv4 (it relied on the default) and add an IPv6 one. Co-Authored-By: Claude Opus 5.5 --- homa_hijack.c | 8 ++++++-- test/unit_homa_hijack.c | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/homa_hijack.c b/homa_hijack.c index edc9e278..4ae3e1a5 100644 --- a/homa_hijack.c +++ b/homa_hijack.c @@ -76,8 +76,12 @@ struct sk_buff *homa_hijack_gro_receive(struct list_head *held_list, // tt_record4("homa_hijack_gro_receive got type 0x%x, flags 0x%x, " // "urgent 0x%x, id %d", h->type, h->flags, // ntohs(h->urgent), homa_local_id(h->sender_id)); - if (!homa_skb_hijacked(skb)) - return tcp_net_offload->callbacks.gro_receive(held_list, skb); + if (!homa_skb_hijacked(skb)) { + const struct net_offload *tcp_offload = skb_is_ipv6(skb) ? + tcp6_net_offload : tcp_net_offload; + + return tcp_offload->callbacks.gro_receive(held_list, skb); + } /* Change the packet's IP protocol to Homa so that it will get * dispatched directly to Homa in the future. diff --git a/test/unit_homa_hijack.c b/test/unit_homa_hijack.c index 0df6103a..a109dc56 100644 --- a/test/unit_homa_hijack.c +++ b/test/unit_homa_hijack.c @@ -97,11 +97,12 @@ TEST_F(homa_hijack, homa_hijack_init) inet6_offloads[IPPROTO_TCP]->callbacks.gro_receive); } -TEST_F(homa_hijack, homa_hijack_gro_receive__pass_to_tcp) +TEST_F(homa_hijack, homa_hijack_gro_receive__pass_to_tcp_ipv4) { struct homa_common_hdr *h; struct sk_buff *skb; + mock_ipv6 = false; homa_hijack_init(); self->header.seg.offset = htonl(6000); skb = mock_skb_alloc(&self->src_ip, &self->dst_ip, @@ -122,6 +123,22 @@ TEST_F(homa_hijack, homa_hijack_gro_receive__pass_to_tcp) kfree_skb(skb); homa_hijack_end(); } +TEST_F(homa_hijack, homa_hijack_gro_receive__pass_to_tcp_ipv6) +{ + struct homa_common_hdr *h; + struct sk_buff *skb; + + mock_ipv6 = true; + homa_hijack_init(); + skb = mock_skb_alloc(&self->src_ip, &self->dst_ip, + &self->header.common, 1400, 0); + h = (struct homa_common_hdr *)skb_transport_header(skb); + h->flags = 0; + EXPECT_EQ(NULL, homa_hijack_gro_receive(&self->empty_list, skb)); + EXPECT_STREQ("unit_tcp6_gro_receive", unit_log_get()); + kfree_skb(skb); + homa_hijack_end(); +} TEST_F(homa_hijack, homa_hijack_gro_receive__pass_to_homa_ipv6) { struct homa_common_hdr *h;