* [PATCH net-next 0/6] selftests: drv-net: gro: more test cases
@ 2026-04-01 18:26 Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 1/6] selftests: drv-net: gro: add data burst test case Jakub Kicinski
` (6 more replies)
0 siblings, 7 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Add a few more test cases for GRO.
Jakub Kicinski (6):
selftests: drv-net: gro: add data burst test case
selftests: drv-net: gro: add 1 byte payload test
selftests: drv-net: gro: always wait for FIN in the capacity test
selftests: drv-net: gro: prepare for ip6ip6 support
selftests: drv-net: gro: test ip6ip6
selftests: drv-net: gro: add a test for bad IPv4 csum
tools/testing/selftests/net/lib/gro.c | 171 +++++++++++++++------
tools/testing/selftests/drivers/net/gro.py | 24 ++-
2 files changed, 143 insertions(+), 52 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 1/6] selftests: drv-net: gro: add data burst test case
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 2/6] selftests: drv-net: gro: add 1 byte payload test Jakub Kicinski
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Add a test trying to induce a GRO context timeout followed
by another sequence of packets for the same flow. The second
burst arrives 100ms after the first one so any implementation
(SW or HW) must time out waiting at that point. We expect both
bursts to be aggregated successfully but separately.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 21 +++++++++++++++++++++
tools/testing/selftests/drivers/net/gro.py | 2 +-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index 3e611ae25f61..4d002af4a7aa 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -12,6 +12,7 @@
* - data_same: same size packets coalesce
* - data_lrg_sml: large then small coalesces
* - data_sml_lrg: small then large doesn't coalesce
+ * - data_burst: two bursts of two, separated by 100ms
*
* ack:
* Pure ACK does not coalesce.
@@ -1298,6 +1299,21 @@ static void gro_sender(void)
} else if (strcmp(testname, "data_sml_lrg") == 0) {
send_data_pkts(txfd, &daddr, PAYLOAD_LEN / 2, PAYLOAD_LEN);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
+ } else if (strcmp(testname, "data_burst") == 0) {
+ static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
+
+ create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
+ write_packet(txfd, buf, total_hdr_len + PAYLOAD_LEN, &daddr);
+ create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
+ write_packet(txfd, buf, total_hdr_len + PAYLOAD_LEN, &daddr);
+
+ usleep(100 * 1000); /* 100ms */
+ create_packet(buf, PAYLOAD_LEN * 2, 0, PAYLOAD_LEN, 0);
+ write_packet(txfd, buf, total_hdr_len + PAYLOAD_LEN, &daddr);
+ create_packet(buf, PAYLOAD_LEN * 3, 0, PAYLOAD_LEN, 0);
+ write_packet(txfd, buf, total_hdr_len + PAYLOAD_LEN, &daddr);
+
+ write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
/* ack test */
} else if (strcmp(testname, "ack") == 0) {
@@ -1463,6 +1479,11 @@ static void gro_receiver(void)
correct_payload[0] = PAYLOAD_LEN / 2;
correct_payload[1] = PAYLOAD_LEN;
check_recv_pkts(rxfd, correct_payload, 2);
+ } else if (strcmp(testname, "data_burst") == 0) {
+ printf("two bursts of two data packets: ");
+ correct_payload[0] = PAYLOAD_LEN * 2;
+ correct_payload[1] = PAYLOAD_LEN * 2;
+ check_recv_pkts(rxfd, correct_payload, 2);
/* ack test */
} else if (strcmp(testname, "ack") == 0) {
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
index 70709bf670c7..10da5d4bee9b 100755
--- a/tools/testing/selftests/drivers/net/gro.py
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -289,7 +289,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
# Tests that work for all protocols
common_tests = [
- "data_same", "data_lrg_sml", "data_sml_lrg",
+ "data_same", "data_lrg_sml", "data_sml_lrg", "data_burst",
"ack",
"flags_psh", "flags_syn", "flags_rst", "flags_urg", "flags_cwr",
"tcp_csum", "tcp_seq", "tcp_ts", "tcp_opt",
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 2/6] selftests: drv-net: gro: add 1 byte payload test
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 1/6] selftests: drv-net: gro: add data burst test case Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 3/6] selftests: drv-net: gro: always wait for FIN in the capacity test Jakub Kicinski
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Small IPv4 packets get padded to 60B, this may break / confuse
some buggy implementations. Add a test to coalesce a 1B payload.
Keep this separate from the lrg_sml test because I suspect some
implementations may not handle this case (treat padded frames
as ineligible for coalescing).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 12 ++++++++++--
tools/testing/selftests/drivers/net/gro.py | 4 +++-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index 4d002af4a7aa..27ccd742615a 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -10,8 +10,9 @@
* packet coalesced: it can be smaller than the rest and coalesced
* as long as it is in the same flow.
* - data_same: same size packets coalesce
- * - data_lrg_sml: large then small coalesces
- * - data_sml_lrg: small then large doesn't coalesce
+ * - data_lrg_sml: large then small coalesces
+ * - data_lrg_1byte: large then 1 byte coalesces (Ethernet padding)
+ * - data_sml_lrg: small then large doesn't coalesce
* - data_burst: two bursts of two, separated by 100ms
*
* ack:
@@ -1296,6 +1297,9 @@ static void gro_sender(void)
} else if (strcmp(testname, "data_lrg_sml") == 0) {
send_data_pkts(txfd, &daddr, PAYLOAD_LEN, PAYLOAD_LEN / 2);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
+ } else if (strcmp(testname, "data_lrg_1byte") == 0) {
+ send_data_pkts(txfd, &daddr, PAYLOAD_LEN, 1);
+ write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
} else if (strcmp(testname, "data_sml_lrg") == 0) {
send_data_pkts(txfd, &daddr, PAYLOAD_LEN / 2, PAYLOAD_LEN);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
@@ -1474,6 +1478,10 @@ static void gro_receiver(void)
printf("large data packets followed by a smaller one: ");
correct_payload[0] = PAYLOAD_LEN * 1.5;
check_recv_pkts(rxfd, correct_payload, 1);
+ } else if (strcmp(testname, "data_lrg_1byte") == 0) {
+ printf("large data packet followed by a 1 byte one: ");
+ correct_payload[0] = PAYLOAD_LEN + 1;
+ check_recv_pkts(rxfd, correct_payload, 1);
} else if (strcmp(testname, "data_sml_lrg") == 0) {
printf("small data packets followed by a larger one: ");
correct_payload[0] = PAYLOAD_LEN / 2;
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
index 10da5d4bee9b..73436d16b40d 100755
--- a/tools/testing/selftests/drivers/net/gro.py
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -11,6 +11,7 @@ coalescing behavior.
Test cases:
- data_same: Same size data packets coalesce
- data_lrg_sml: Large packet followed by smaller one coalesces
+ - data_lrg_1byte: Large packet followed by 1B one coalesces (Ethernet padding)
- data_sml_lrg: Small packet followed by larger one doesn't coalesce
- ack: Pure ACK packets do not coalesce
- flags_psh: Packets with PSH flag don't coalesce
@@ -289,7 +290,8 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
# Tests that work for all protocols
common_tests = [
- "data_same", "data_lrg_sml", "data_sml_lrg", "data_burst",
+ "data_same", "data_lrg_sml", "data_sml_lrg", "data_lrg_1byte",
+ "data_burst",
"ack",
"flags_psh", "flags_syn", "flags_rst", "flags_urg", "flags_cwr",
"tcp_csum", "tcp_seq", "tcp_ts", "tcp_opt",
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 3/6] selftests: drv-net: gro: always wait for FIN in the capacity test
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 1/6] selftests: drv-net: gro: add data burst test case Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 2/6] selftests: drv-net: gro: add 1 byte payload test Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 4/6] selftests: drv-net: gro: prepare for ip6ip6 support Jakub Kicinski
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
The new capacity/order test exits as soon as it sees the expected
packet sequence. This may allow the "flushing" FIN packet to spill
over to the next test. Let's always wait for the FIN before exiting.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index 27ccd742615a..f05398c18e0c 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -1154,7 +1154,7 @@ static void check_capacity_pkts(int fd)
memset(coalesced, 0, sizeof(coalesced));
memset(flow_order, -1, sizeof(flow_order));
- while (total_data < num_flows * CAPACITY_PAYLOAD_LEN * 2) {
+ while (1) {
ip_ext_len = 0;
pkt_size = recv(fd, buffer, IP_MAXPACKET + ETH_HLEN + 1, 0);
if (pkt_size < 0)
@@ -1167,7 +1167,6 @@ static void check_capacity_pkts(int fd)
tcph = (struct tcphdr *)(buffer + tcp_offset + ip_ext_len);
- /* FIN packet terminates reception */
if (tcph->fin)
break;
@@ -1189,7 +1188,13 @@ static void check_capacity_pkts(int fd)
data_len = pkt_size - total_hdr_len - ip_ext_len;
}
- flow_order[num_pkt] = flow_id;
+ if (num_pkt < num_flows * 2) {
+ flow_order[num_pkt] = flow_id;
+ } else if (num_pkt == num_flows * 2) {
+ vlog("More packets than expected (%d)\n",
+ num_flows * 2);
+ fail_reason = fail_reason ?: "too many packets";
+ }
coalesced[flow_id] = data_len;
if (data_len == CAPACITY_PAYLOAD_LEN * 2) {
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 4/6] selftests: drv-net: gro: prepare for ip6ip6 support
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
` (2 preceding siblings ...)
2026-04-01 18:26 ` [PATCH net-next 3/6] selftests: drv-net: gro: always wait for FIN in the capacity test Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6 Jakub Kicinski
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Try to use already calculated offsets and not depend on the ipip
flag as much. This patch should not change any functionality,
it's just a cleanup to make ip6ip6 support easier.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 73 +++++++++++++++------------
1 file changed, 41 insertions(+), 32 deletions(-)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index f05398c18e0c..57080ecc3df8 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -139,6 +139,14 @@ static bool order_check;
#define TXTIME_DELAY_MS 5
+/* Max TCP payload that GRO will coalesce. The outer header overhead
+ * varies by encapsulation, reducing the effective max payload.
+ */
+static int max_payload(void)
+{
+ return IP_MAXPACKET - (total_hdr_len - ETH_HLEN);
+}
+
static void vlog(const char *fmt, ...)
{
va_list args;
@@ -156,15 +164,13 @@ static void setup_sock_filter(int fd)
const int ethproto_off = offsetof(struct ethhdr, h_proto);
int optlen = 0;
int ipproto_off, opt_ipproto_off;
- int next_off;
- if (ipip)
- next_off = sizeof(struct iphdr) + offsetof(struct iphdr, protocol);
- else if (proto == PF_INET)
- next_off = offsetof(struct iphdr, protocol);
+ if (proto == PF_INET)
+ ipproto_off = tcp_offset - sizeof(struct iphdr) +
+ offsetof(struct iphdr, protocol);
else
- next_off = offsetof(struct ipv6hdr, nexthdr);
- ipproto_off = ETH_HLEN + next_off;
+ ipproto_off = tcp_offset - sizeof(struct ipv6hdr) +
+ offsetof(struct ipv6hdr, nexthdr);
/* Overridden later if exthdrs are used: */
opt_ipproto_off = ipproto_off;
@@ -381,19 +387,23 @@ static void write_packet(int fd, char *buf, int len, struct sockaddr_ll *daddr)
static void create_packet(void *buf, int seq_offset, int ack_offset,
int payload_len, int fin)
{
+ int ip_hdr_len = (proto == PF_INET) ?
+ sizeof(struct iphdr) : sizeof(struct ipv6hdr);
+ int inner_ip_off = tcp_offset - ip_hdr_len;
+
memset(buf, 0, total_hdr_len);
memset(buf + total_hdr_len, 'a', payload_len);
fill_transportlayer(buf + tcp_offset, seq_offset, ack_offset,
payload_len, fin);
- if (ipip) {
- fill_networklayer(buf + ETH_HLEN, payload_len + sizeof(struct iphdr),
- IPPROTO_IPIP);
- fill_networklayer(buf + ETH_HLEN + sizeof(struct iphdr),
- payload_len, IPPROTO_TCP);
- } else {
- fill_networklayer(buf + ETH_HLEN, payload_len, IPPROTO_TCP);
+ fill_networklayer(buf + inner_ip_off, payload_len, IPPROTO_TCP);
+ if (inner_ip_off > ETH_HLEN) {
+ int encap_proto = (proto == PF_INET) ?
+ IPPROTO_IPIP : IPPROTO_IPV6;
+
+ fill_networklayer(buf + ETH_HLEN,
+ payload_len + ip_hdr_len, encap_proto);
}
fill_datalinklayer(buf);
@@ -547,8 +557,7 @@ static void send_ack(int fd, struct sockaddr_ll *daddr)
static void recompute_packet(char *buf, char *no_ext, int extlen)
{
struct tcphdr *tcphdr = (struct tcphdr *)(buf + tcp_offset);
- struct ipv6hdr *ip6h = (struct ipv6hdr *)(buf + ETH_HLEN);
- struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
+ int off;
memmove(buf, no_ext, total_hdr_len);
memmove(buf + total_hdr_len + extlen,
@@ -558,18 +567,22 @@ static void recompute_packet(char *buf, char *no_ext, int extlen)
tcphdr->check = 0;
tcphdr->check = tcp_checksum(tcphdr, PAYLOAD_LEN + extlen);
if (proto == PF_INET) {
- iph->tot_len = htons(ntohs(iph->tot_len) + extlen);
- iph->check = 0;
- iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
+ for (off = ETH_HLEN; off < tcp_offset;
+ off += sizeof(struct iphdr)) {
+ struct iphdr *iph = (struct iphdr *)(buf + off);
- if (ipip) {
- iph += 1;
iph->tot_len = htons(ntohs(iph->tot_len) + extlen);
iph->check = 0;
iph->check = checksum_fold(iph, sizeof(struct iphdr), 0);
}
} else {
- ip6h->payload_len = htons(ntohs(ip6h->payload_len) + extlen);
+ for (off = ETH_HLEN; off < tcp_offset;
+ off += sizeof(struct ipv6hdr)) {
+ struct ipv6hdr *ip6h = (struct ipv6hdr *)(buf + off);
+
+ ip6h->payload_len =
+ htons(ntohs(ip6h->payload_len) + extlen);
+ }
}
}
@@ -1425,14 +1438,12 @@ static void gro_sender(void)
/* large sub-tests */
} else if (strcmp(testname, "large_max") == 0) {
- int offset = (proto == PF_INET && !ipip) ? 20 : 0;
- int remainder = (MAX_PAYLOAD + offset) % MSS;
+ int remainder = max_payload() % MSS;
send_large(txfd, &daddr, remainder);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
} else if (strcmp(testname, "large_rem") == 0) {
- int offset = (proto == PF_INET && !ipip) ? 20 : 0;
- int remainder = (MAX_PAYLOAD + offset) % MSS;
+ int remainder = max_payload() % MSS;
send_large(txfd, &daddr, remainder + 1);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
@@ -1636,19 +1647,17 @@ static void gro_receiver(void)
/* large sub-tests */
} else if (strcmp(testname, "large_max") == 0) {
- int offset = (proto == PF_INET && !ipip) ? 20 : 0;
- int remainder = (MAX_PAYLOAD + offset) % MSS;
+ int remainder = max_payload() % MSS;
- correct_payload[0] = (MAX_PAYLOAD + offset);
+ correct_payload[0] = max_payload();
correct_payload[1] = remainder;
printf("Shouldn't coalesce if exceed IP max pkt size: ");
check_recv_pkts(rxfd, correct_payload, 2);
} else if (strcmp(testname, "large_rem") == 0) {
- int offset = (proto == PF_INET && !ipip) ? 20 : 0;
- int remainder = (MAX_PAYLOAD + offset) % MSS;
+ int remainder = max_payload() % MSS;
/* last segment sent individually, doesn't start new segment */
- correct_payload[0] = (MAX_PAYLOAD + offset) - remainder;
+ correct_payload[0] = max_payload() - remainder;
correct_payload[1] = remainder + 1;
correct_payload[2] = remainder + 1;
printf("last segment sent individually: ");
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
` (3 preceding siblings ...)
2026-04-01 18:26 ` [PATCH net-next 4/6] selftests: drv-net: gro: prepare for ip6ip6 support Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-02 0:20 ` Willem de Bruijn
2026-04-01 18:26 ` [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum Jakub Kicinski
2026-04-02 0:19 ` [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Willem de Bruijn
6 siblings, 1 reply; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
We explicitly test ipip encap. Let's add ip6ip6, too. Having
just ipip seems like favoring IPv4 which we should not do :)
Testing all combinations is left for future work, not sure
it's actually worth it.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 29 ++++++++++++++++------
tools/testing/selftests/drivers/net/gro.py | 19 ++++++++------
2 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index 57080ecc3df8..762e88932ed2 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -94,11 +94,14 @@
#define START_SEQ 100
#define START_ACK 100
#define ETH_P_NONE 0
-#define TOTAL_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
+#define TOTAL_HDR_LEN \
+ (ETH_HLEN + sizeof(struct ipv6hdr) * 2 + sizeof(struct tcphdr))
#define MSS (4096 - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
-#define MAX_PAYLOAD (IP_MAXPACKET - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
+#define MAX_PAYLOAD \
+ (IP_MAXPACKET - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
#define NUM_LARGE_PKT (MAX_PAYLOAD / MSS)
-#define MAX_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
+#define MAX_HDR_LEN \
+ (ETH_HLEN + sizeof(struct ipv6hdr) * 2 + sizeof(struct tcphdr))
#define MIN_EXTHDR_SIZE 8
#define EXT_PAYLOAD_1 "\x00\x00\x00\x00\x00\x00"
#define EXT_PAYLOAD_2 "\x11\x11\x11\x11\x11\x11"
@@ -131,6 +134,7 @@ static int tcp_offset = -1;
static int total_hdr_len = -1;
static int ethhdr_proto = -1;
static bool ipip;
+static bool ip6ip6;
static uint64_t txtime_ns;
static int num_flows = 4;
static bool order_check;
@@ -1113,7 +1117,8 @@ static void check_recv_pkts(int fd, int *correct_payload,
if (iph->version == 4)
ip_ext_len = (iph->ihl - 5) * 4;
- else if (ip6h->version == 6 && ip6h->nexthdr != IPPROTO_TCP)
+ else if (ip6h->version == 6 && !ip6ip6 &&
+ ip6h->nexthdr != IPPROTO_TCP)
ip_ext_len = MIN_EXTHDR_SIZE;
tcph = (struct tcphdr *)(buffer + tcp_offset + ip_ext_len);
@@ -1175,7 +1180,8 @@ static void check_capacity_pkts(int fd)
if (iph->version == 4)
ip_ext_len = (iph->ihl - 5) * 4;
- else if (ip6h->version == 6 && ip6h->nexthdr != IPPROTO_TCP)
+ else if (ip6h->version == 6 && !ip6ip6 &&
+ ip6h->nexthdr != IPPROTO_TCP)
ip_ext_len = MIN_EXTHDR_SIZE;
tcph = (struct tcphdr *)(buffer + tcp_offset + ip_ext_len);
@@ -1688,6 +1694,7 @@ static void parse_args(int argc, char **argv)
{ "ipv4", no_argument, NULL, '4' },
{ "ipv6", no_argument, NULL, '6' },
{ "ipip", no_argument, NULL, 'e' },
+ { "ip6ip6", no_argument, NULL, 'E' },
{ "num-flows", required_argument, NULL, 'n' },
{ "rx", no_argument, NULL, 'r' },
{ "saddr", required_argument, NULL, 's' },
@@ -1699,7 +1706,7 @@ static void parse_args(int argc, char **argv)
};
int c;
- while ((c = getopt_long(argc, argv, "46d:D:ei:n:rs:S:t:ov", opts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "46d:D:eEi:n:rs:S:t:ov", opts, NULL)) != -1) {
switch (c) {
case '4':
proto = PF_INET;
@@ -1714,6 +1721,11 @@ static void parse_args(int argc, char **argv)
proto = PF_INET;
ethhdr_proto = htons(ETH_P_IP);
break;
+ case 'E':
+ ip6ip6 = true;
+ proto = PF_INET6;
+ ethhdr_proto = htons(ETH_P_IPV6);
+ break;
case 'd':
addr4_dst = addr6_dst = optarg;
break;
@@ -1758,12 +1770,15 @@ int main(int argc, char **argv)
if (ipip) {
tcp_offset = ETH_HLEN + sizeof(struct iphdr) * 2;
total_hdr_len = tcp_offset + sizeof(struct tcphdr);
+ } else if (ip6ip6) {
+ tcp_offset = ETH_HLEN + sizeof(struct ipv6hdr) * 2;
+ total_hdr_len = tcp_offset + sizeof(struct tcphdr);
} else if (proto == PF_INET) {
tcp_offset = ETH_HLEN + sizeof(struct iphdr);
total_hdr_len = tcp_offset + sizeof(struct tcphdr);
} else if (proto == PF_INET6) {
tcp_offset = ETH_HLEN + sizeof(struct ipv6hdr);
- total_hdr_len = MAX_HDR_LEN;
+ total_hdr_len = tcp_offset + sizeof(struct tcphdr);
} else {
error(1, 0, "Protocol family is not ipv4 or ipv6");
}
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
index 73436d16b40d..68b7b29ea2ee 100755
--- a/tools/testing/selftests/drivers/net/gro.py
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -213,7 +213,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
return rx_proc
-def _setup(cfg, mode, test_name):
+def _setup(cfg, mode, test_name, protocol):
""" Setup hardware loopback mode for GRO testing. """
if not hasattr(cfg, "bin_remote"):
@@ -225,10 +225,15 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
cfg.remote_feat = ethtool(f"-k {cfg.remote_ifname}",
host=cfg.remote, json=True)[0]
- # "large_*" tests need at least 4k MTU
+ # "large_*" tests need at least 4k MTU, bump more for encapsulation
if test_name.startswith("large_"):
- _set_mtu_restore(cfg.dev, 4096, None)
- _set_mtu_restore(cfg.remote_dev, 4096, cfg.remote)
+ mtu = 4096
+ if protocol == "ipip":
+ mtu += 20 # outer IPv4 header
+ elif protocol == "ip6ip6":
+ mtu += 40 # outer IPv6 header
+ _set_mtu_restore(cfg.dev, mtu, None)
+ _set_mtu_restore(cfg.remote_dev, mtu, cfg.remote)
if mode == "sw":
flush_path = f"/sys/class/net/{cfg.ifname}/gro_flush_timeout"
@@ -313,7 +318,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
]
for mode in ["sw", "hw", "lro"]:
- for protocol in ["ipv4", "ipv6", "ipip"]:
+ for protocol in ["ipv4", "ipv6", "ipip", "ip6ip6"]:
for test_name in common_tests:
yield mode, protocol, test_name
@@ -332,7 +337,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
ipver = "6" if protocol[-1] == "6" else "4"
cfg.require_ipver(ipver)
- _setup(cfg, mode, test_name)
+ _setup(cfg, mode, test_name, protocol)
# Each test is run 6 times to deflake, because given the receive timing,
# not all packets that should coalesce will be considered in the same flow
@@ -382,7 +387,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
"""
max_retries = 3
- _setup(cfg, mode, "capacity")
+ _setup(cfg, mode, "capacity", None)
queue_id = setup_func(cfg)
num_flows = 8
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
` (4 preceding siblings ...)
2026-04-01 18:26 ` [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6 Jakub Kicinski
@ 2026-04-01 18:26 ` Jakub Kicinski
2026-04-02 0:28 ` Willem de Bruijn
2026-04-02 0:19 ` [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Willem de Bruijn
6 siblings, 1 reply; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-01 18:26 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
We have a test for coalescing with bad TCP checksum, let's also
test bad IPv4 header checksum.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/gro.c | 25 ++++++++++++++++++++++
tools/testing/selftests/drivers/net/gro.py | 1 +
2 files changed, 26 insertions(+)
diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
index 762e88932ed2..a458cfbd11eb 100644
--- a/tools/testing/selftests/net/lib/gro.c
+++ b/tools/testing/selftests/net/lib/gro.c
@@ -36,6 +36,7 @@
* Packets with different (ECN, TTL, TOS) header, IP options or
* IP fragments shouldn't coalesce.
* - ip_ecn, ip_tos: shared between IPv4/IPv6
+ * - ip_csum: IPv4 only, bad IP header checksum
* - ip_ttl, ip_opt, ip_frag4: IPv4 only
* - ip_id_df*: IPv4 IP ID field coalescing tests
* - ip_frag6, ip_v6ext_*: IPv6 only
@@ -675,6 +676,21 @@ static void send_changed_checksum(int fd, struct sockaddr_ll *daddr)
write_packet(fd, buf, pkt_size, daddr);
}
+/* Packets with incorrect IPv4 header checksum don't coalesce. */
+static void send_changed_ip_checksum(int fd, struct sockaddr_ll *daddr)
+{
+ static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
+ struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
+ int pkt_size = total_hdr_len + PAYLOAD_LEN;
+
+ create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
+ write_packet(fd, buf, pkt_size, daddr);
+
+ create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
+ iph->check = iph->check - 1;
+ write_packet(fd, buf, pkt_size, daddr);
+}
+
/* Packets with non-consecutive sequence number don't coalesce.*/
static void send_changed_seq(int fd, struct sockaddr_ll *daddr)
{
@@ -1392,6 +1408,10 @@ static void gro_sender(void)
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
/* ip sub-tests - IPv4 only */
+ } else if (strcmp(testname, "ip_csum") == 0) {
+ send_changed_ip_checksum(txfd, &daddr);
+ usleep(fin_delay_us);
+ write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
} else if (strcmp(testname, "ip_ttl") == 0) {
send_changed_ttl(txfd, &daddr);
write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
@@ -1588,6 +1608,11 @@ static void gro_receiver(void)
check_recv_pkts(rxfd, correct_payload, 2);
/* ip sub-tests - IPv4 only */
+ } else if (strcmp(testname, "ip_csum") == 0) {
+ correct_payload[0] = PAYLOAD_LEN;
+ correct_payload[1] = PAYLOAD_LEN;
+ printf("bad ip checksum doesn't coalesce: ");
+ check_recv_pkts(rxfd, correct_payload, 2);
} else if (strcmp(testname, "ip_ttl") == 0) {
correct_payload[0] = PAYLOAD_LEN;
correct_payload[1] = PAYLOAD_LEN;
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
index 68b7b29ea2ee..ba9f4146034c 100755
--- a/tools/testing/selftests/drivers/net/gro.py
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -306,6 +306,7 @@ def _run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
# Tests specific to IPv4
ipv4_tests = [
+ "ip_csum",
"ip_ttl", "ip_opt", "ip_frag4",
"ip_id_df1_inc", "ip_id_df1_fixed",
"ip_id_df0_inc", "ip_id_df0_fixed",
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/6] selftests: drv-net: gro: more test cases
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
` (5 preceding siblings ...)
2026-04-01 18:26 ` [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum Jakub Kicinski
@ 2026-04-02 0:19 ` Willem de Bruijn
6 siblings, 0 replies; 12+ messages in thread
From: Willem de Bruijn @ 2026-04-02 0:19 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Jakub Kicinski wrote:
> Add a few more test cases for GRO.
>
> Jakub Kicinski (6):
> selftests: drv-net: gro: add data burst test case
> selftests: drv-net: gro: add 1 byte payload test
> selftests: drv-net: gro: always wait for FIN in the capacity test
> selftests: drv-net: gro: prepare for ip6ip6 support
> selftests: drv-net: gro: test ip6ip6
> selftests: drv-net: gro: add a test for bad IPv4 csum
>
> tools/testing/selftests/net/lib/gro.c | 171 +++++++++++++++------
> tools/testing/selftests/drivers/net/gro.py | 24 ++-
> 2 files changed, 143 insertions(+), 52 deletions(-)
For the series:
Reviewed-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6
2026-04-01 18:26 ` [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6 Jakub Kicinski
@ 2026-04-02 0:20 ` Willem de Bruijn
0 siblings, 0 replies; 12+ messages in thread
From: Willem de Bruijn @ 2026-04-02 0:20 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Jakub Kicinski wrote:
> We explicitly test ipip encap. Let's add ip6ip6, too. Having
> just ipip seems like favoring IPv4 which we should not do :)
> Testing all combinations is left for future work, not sure
> it's actually worth it.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> tools/testing/selftests/net/lib/gro.c | 29 ++++++++++++++++------
> tools/testing/selftests/drivers/net/gro.py | 19 ++++++++------
> 2 files changed, 34 insertions(+), 14 deletions(-)
>
> diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
> index 57080ecc3df8..762e88932ed2 100644
> --- a/tools/testing/selftests/net/lib/gro.c
> +++ b/tools/testing/selftests/net/lib/gro.c
> @@ -94,11 +94,14 @@
> #define START_SEQ 100
> #define START_ACK 100
> #define ETH_P_NONE 0
> -#define TOTAL_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
> +#define TOTAL_HDR_LEN \
> + (ETH_HLEN + sizeof(struct ipv6hdr) * 2 + sizeof(struct tcphdr))
> #define MSS (4096 - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
> -#define MAX_PAYLOAD (IP_MAXPACKET - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
> +#define MAX_PAYLOAD \
> + (IP_MAXPACKET - sizeof(struct tcphdr) - sizeof(struct ipv6hdr))
> #define NUM_LARGE_PKT (MAX_PAYLOAD / MSS)
> -#define MAX_HDR_LEN (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
> +#define MAX_HDR_LEN \
> + (ETH_HLEN + sizeof(struct ipv6hdr) * 2 + sizeof(struct tcphdr))
Not something that needs to be addressed here (or at all), but
TOTAL_HDR_LEN and MAX_HDR_LEN seem to be the same.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum
2026-04-01 18:26 ` [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum Jakub Kicinski
@ 2026-04-02 0:28 ` Willem de Bruijn
2026-04-02 2:10 ` Jakub Kicinski
0 siblings, 1 reply; 12+ messages in thread
From: Willem de Bruijn @ 2026-04-02 0:28 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, shuah, willemb,
petrm, anubhavsinggh, richardbgobert, linux-kselftest,
Jakub Kicinski
Jakub Kicinski wrote:
> We have a test for coalescing with bad TCP checksum, let's also
> test bad IPv4 header checksum.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> tools/testing/selftests/net/lib/gro.c | 25 ++++++++++++++++++++++
> tools/testing/selftests/drivers/net/gro.py | 1 +
> 2 files changed, 26 insertions(+)
>
> diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c
> index 762e88932ed2..a458cfbd11eb 100644
> --- a/tools/testing/selftests/net/lib/gro.c
> +++ b/tools/testing/selftests/net/lib/gro.c
> @@ -36,6 +36,7 @@
> * Packets with different (ECN, TTL, TOS) header, IP options or
> * IP fragments shouldn't coalesce.
> * - ip_ecn, ip_tos: shared between IPv4/IPv6
> + * - ip_csum: IPv4 only, bad IP header checksum
> * - ip_ttl, ip_opt, ip_frag4: IPv4 only
> * - ip_id_df*: IPv4 IP ID field coalescing tests
> * - ip_frag6, ip_v6ext_*: IPv6 only
> @@ -675,6 +676,21 @@ static void send_changed_checksum(int fd, struct sockaddr_ll *daddr)
> write_packet(fd, buf, pkt_size, daddr);
> }
>
> +/* Packets with incorrect IPv4 header checksum don't coalesce. */
> +static void send_changed_ip_checksum(int fd, struct sockaddr_ll *daddr)
> +{
> + static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
> + struct iphdr *iph = (struct iphdr *)(buf + ETH_HLEN);
> + int pkt_size = total_hdr_len + PAYLOAD_LEN;
> +
> + create_packet(buf, 0, 0, PAYLOAD_LEN, 0);
> + write_packet(fd, buf, pkt_size, daddr);
> +
> + create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
> + iph->check = iph->check - 1;
> + write_packet(fd, buf, pkt_size, daddr);
> +}
> +
> /* Packets with non-consecutive sequence number don't coalesce.*/
> static void send_changed_seq(int fd, struct sockaddr_ll *daddr)
> {
> @@ -1392,6 +1408,10 @@ static void gro_sender(void)
> write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
>
> /* ip sub-tests - IPv4 only */
> + } else if (strcmp(testname, "ip_csum") == 0) {
> + send_changed_ip_checksum(txfd, &daddr);
> + usleep(fin_delay_us);
> + write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
> } else if (strcmp(testname, "ip_ttl") == 0) {
> send_changed_ttl(txfd, &daddr);
> write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
> @@ -1588,6 +1608,11 @@ static void gro_receiver(void)
> check_recv_pkts(rxfd, correct_payload, 2);
>
> /* ip sub-tests - IPv4 only */
> + } else if (strcmp(testname, "ip_csum") == 0) {
> + correct_payload[0] = PAYLOAD_LEN;
> + correct_payload[1] = PAYLOAD_LEN;
> + printf("bad ip checksum doesn't coalesce: ");
> + check_recv_pkts(rxfd, correct_payload, 2);
This verifies that a packet with bad csum does not coalesce to a valid
packet. Perhaps too paranoid but, do you also want to test the reverse
case?
Can be a single test by adding another write_packet and observing all
three separate packets.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum
2026-04-02 0:28 ` Willem de Bruijn
@ 2026-04-02 2:10 ` Jakub Kicinski
2026-04-02 2:39 ` Willem de Bruijn
0 siblings, 1 reply; 12+ messages in thread
From: Jakub Kicinski @ 2026-04-02 2:10 UTC (permalink / raw)
To: Willem de Bruijn
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, shuah,
willemb, petrm, anubhavsinggh, richardbgobert, linux-kselftest
On Wed, 01 Apr 2026 20:28:46 -0400 Willem de Bruijn wrote:
> > /* ip sub-tests - IPv4 only */
> > + } else if (strcmp(testname, "ip_csum") == 0) {
> > + correct_payload[0] = PAYLOAD_LEN;
> > + correct_payload[1] = PAYLOAD_LEN;
> > + printf("bad ip checksum doesn't coalesce: ");
> > + check_recv_pkts(rxfd, correct_payload, 2);
>
> This verifies that a packet with bad csum does not coalesce to a valid
> packet. Perhaps too paranoid but, do you also want to test the reverse
> case?
Will do, easy enough. Tho TBH I can't think of a case where this would
matter. Bad csum pkt must bypass all GRO processing completely right?
Because we don't want a corrupted packet to flush a valid session?
Or you think some implementation may actually feed these packets into
GRO to avoid waiting for a session timeout?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum
2026-04-02 2:10 ` Jakub Kicinski
@ 2026-04-02 2:39 ` Willem de Bruijn
0 siblings, 0 replies; 12+ messages in thread
From: Willem de Bruijn @ 2026-04-02 2:39 UTC (permalink / raw)
To: Jakub Kicinski, Willem de Bruijn
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, shuah,
willemb, petrm, anubhavsinggh, richardbgobert, linux-kselftest
Jakub Kicinski wrote:
> On Wed, 01 Apr 2026 20:28:46 -0400 Willem de Bruijn wrote:
> > > /* ip sub-tests - IPv4 only */
> > > + } else if (strcmp(testname, "ip_csum") == 0) {
> > > + correct_payload[0] = PAYLOAD_LEN;
> > > + correct_payload[1] = PAYLOAD_LEN;
> > > + printf("bad ip checksum doesn't coalesce: ");
> > > + check_recv_pkts(rxfd, correct_payload, 2);
> >
> > This verifies that a packet with bad csum does not coalesce to a valid
> > packet. Perhaps too paranoid but, do you also want to test the reverse
> > case?
>
> Will do, easy enough. Tho TBH I can't think of a case where this would
> matter. Bad csum pkt must bypass all GRO processing completely right?
> Because we don't want a corrupted packet to flush a valid session?
> Or you think some implementation may actually feed these packets into
> GRO to avoid waiting for a session timeout?
Interesting, I thought the opposite: this would flush an RSC context.
That's also how the OCP text is written: "An SO context closes if a
packet matches the flow, but not the other conditions."
There's a slight subtlety when sending three packets p1, p2 and p3, of
which p2 has a corrupted checksum. If three consecutive payloads, then
if p2 bypasses GRO, the other two are not consecutive so will not
coalesce either. This is the likely case for a real bit flip in
transit. Only if p2 and p3 have the same seqno would p1 and p3
coalesce if p2 bypasses GRO. That would be a weird, possibly malicious
packet, which is not much different from other TCP injection attacks.
Which have more serious consequences than coalescing efficiency.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-04-02 2:39 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-01 18:26 [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 1/6] selftests: drv-net: gro: add data burst test case Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 2/6] selftests: drv-net: gro: add 1 byte payload test Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 3/6] selftests: drv-net: gro: always wait for FIN in the capacity test Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 4/6] selftests: drv-net: gro: prepare for ip6ip6 support Jakub Kicinski
2026-04-01 18:26 ` [PATCH net-next 5/6] selftests: drv-net: gro: test ip6ip6 Jakub Kicinski
2026-04-02 0:20 ` Willem de Bruijn
2026-04-01 18:26 ` [PATCH net-next 6/6] selftests: drv-net: gro: add a test for bad IPv4 csum Jakub Kicinski
2026-04-02 0:28 ` Willem de Bruijn
2026-04-02 2:10 ` Jakub Kicinski
2026-04-02 2:39 ` Willem de Bruijn
2026-04-02 0:19 ` [PATCH net-next 0/6] selftests: drv-net: gro: more test cases Willem de Bruijn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox