Currently, packets with fixed IDs will be merged only if their
don't-fragment bit is set. This restriction is unnecessary since
packets without the don't-fragment bit will be forwarded as-is even
if they were merged together. The merged packets will be segmented
into their original forms before being forwarded, either by GSO or
by TSO. The IDs will also remain identical unless NETIF_F_TSO_MANGLEID
is set, in which case the IDs can become incrementing, which is also fine.
Note that IP fragmentation is not an issue here, since packets are
segmented before being further fragmented. Fragmentation happens the
same way regardless of whether the packets were first merged together.
Clean up the code by removing the unnecessary don't-fragment checks.
Signed-off-by: Richard Gobert <richardbgobert@gmail.com>
---
include/net/gro.h | 5 ++---
net/ipv4/af_inet.c | 3 ---
tools/testing/selftests/net/gro.c | 9 ++++-----
3 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/include/net/gro.h b/include/net/gro.h
index e7997a9fb30b..e3affb2e2ca8 100644
--- a/include/net/gro.h
+++ b/include/net/gro.h
@@ -448,17 +448,16 @@ static inline int inet_gro_flush(const struct iphdr *iph, const struct iphdr *ip
const u32 id2 = ntohl(*(__be32 *)&iph2->id);
const u16 ipid_offset = (id >> 16) - (id2 >> 16);
const u16 count = NAPI_GRO_CB(p)->count;
- const u32 df = id & IP_DF;
/* All fields must match except length and checksum. */
- if ((iph->ttl ^ iph2->ttl) | (iph->tos ^ iph2->tos) | (df ^ (id2 & IP_DF)))
+ if ((iph->ttl ^ iph2->ttl) | (iph->tos ^ iph2->tos) | ((id ^ id2) & IP_DF))
return true;
/* When we receive our second frame we can make a decision on if we
* continue this flow as an atomic flow with a fixed ID or if we use
* an incrementing ID.
*/
- if (count == 1 && df && !ipid_offset)
+ if (count == 1 && !ipid_offset)
NAPI_GRO_CB(p)->ip_fixedid |= 1 << inner;
return ipid_offset ^ (count * !(NAPI_GRO_CB(p)->ip_fixedid & (1 << inner)));
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index fc7a6955fa0a..c0542d9187e2 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1393,10 +1393,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
segs = ERR_PTR(-EPROTONOSUPPORT);
- /* fixed ID is invalid if DF bit is not set */
fixedid = !!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCP_FIXEDID << encap));
- if (fixedid && !(ip_hdr(skb)->frag_off & htons(IP_DF)))
- goto out;
if (!skb->encapsulation || encap)
udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
diff --git a/tools/testing/selftests/net/gro.c b/tools/testing/selftests/net/gro.c
index d5824eadea10..3d4a82a2607c 100644
--- a/tools/testing/selftests/net/gro.c
+++ b/tools/testing/selftests/net/gro.c
@@ -670,7 +670,7 @@ static void send_flush_id_case(int fd, struct sockaddr_ll *daddr, int tcase)
iph2->id = htons(9);
break;
- case 3: /* DF=0, Fixed - should not coalesce */
+ case 3: /* DF=0, Fixed - should coalesce */
iph1->frag_off &= ~htons(IP_DF);
iph1->id = htons(8);
@@ -1188,10 +1188,9 @@ static void gro_receiver(void)
correct_payload[0] = PAYLOAD_LEN * 2;
check_recv_pkts(rxfd, correct_payload, 1);
- printf("DF=0, Fixed - should not coalesce: ");
- correct_payload[0] = PAYLOAD_LEN;
- correct_payload[1] = PAYLOAD_LEN;
- check_recv_pkts(rxfd, correct_payload, 2);
+ printf("DF=0, Fixed - should coalesce: ");
+ correct_payload[0] = PAYLOAD_LEN * 2;
+ check_recv_pkts(rxfd, correct_payload, 1);
printf("DF=1, 2 Incrementing and one fixed - should coalesce only first 2 packets: ");
correct_payload[0] = PAYLOAD_LEN * 2;
--
2.36.1
On 9/16/25 4:48 PM, Richard Gobert wrote: > Currently, packets with fixed IDs will be merged only if their > don't-fragment bit is set. This restriction is unnecessary since > packets without the don't-fragment bit will be forwarded as-is even > if they were merged together. The merged packets will be segmented > into their original forms before being forwarded, either by GSO or > by TSO. The IDs will also remain identical unless NETIF_F_TSO_MANGLEID > is set, in which case the IDs can become incrementing, which is also fine. > > Note that IP fragmentation is not an issue here, since packets are > segmented before being further fragmented. Fragmentation happens the > same way regardless of whether the packets were first merged together. I agree with Willem, that an explicit assertion somewhere (in ip_do_fragmentation?!?) could be useful. Also I'm not sure that "packets are segmented before being further fragmented" is always true for the OVS forwarding scenario. /P
Paolo Abeni wrote: > On 9/16/25 4:48 PM, Richard Gobert wrote: >> Currently, packets with fixed IDs will be merged only if their >> don't-fragment bit is set. This restriction is unnecessary since >> packets without the don't-fragment bit will be forwarded as-is even >> if they were merged together. The merged packets will be segmented >> into their original forms before being forwarded, either by GSO or >> by TSO. The IDs will also remain identical unless NETIF_F_TSO_MANGLEID >> is set, in which case the IDs can become incrementing, which is also fine. >> >> Note that IP fragmentation is not an issue here, since packets are >> segmented before being further fragmented. Fragmentation happens the >> same way regardless of whether the packets were first merged together. > > I agree with Willem, that an explicit assertion somewhere (in > ip_do_fragmentation?!?) could be useful. > As I replied to Willem, I'll mention ip_finish_output_gso explicitly in the commit message. Or did you mean I should add some type of WARN_ON assertion that ip_do_fragment isn't called for GSO packets? > Also I'm not sure that "packets are segmented before being further > fragmented" is always true for the OVS forwarding scenario. > If this is really the case, it is a bug in OVS. Segmentation is required before fragmentation as otherwise GRO isn't transparent and fragments will be forwarded that contain data from multiple different packets. It's also probably less efficient, if the segment size is smaller than the MTU. I think this should be addressed in a separate patch series. I'll also mention OVS in the commit message. > /P >
Richard Gobert wrote: > Paolo Abeni wrote: >> On 9/16/25 4:48 PM, Richard Gobert wrote: >>> Currently, packets with fixed IDs will be merged only if their >>> don't-fragment bit is set. This restriction is unnecessary since >>> packets without the don't-fragment bit will be forwarded as-is even >>> if they were merged together. The merged packets will be segmented >>> into their original forms before being forwarded, either by GSO or >>> by TSO. The IDs will also remain identical unless NETIF_F_TSO_MANGLEID >>> is set, in which case the IDs can become incrementing, which is also fine. >>> >>> Note that IP fragmentation is not an issue here, since packets are >>> segmented before being further fragmented. Fragmentation happens the >>> same way regardless of whether the packets were first merged together. >> >> I agree with Willem, that an explicit assertion somewhere (in >> ip_do_fragmentation?!?) could be useful. >> > > As I replied to Willem, I'll mention ip_finish_output_gso explicitly in the > commit message. > > Or did you mean I should add some type of WARN_ON assertion that ip_do_fragment isn't > called for GSO packets? > >> Also I'm not sure that "packets are segmented before being further >> fragmented" is always true for the OVS forwarding scenario. >> > > If this is really the case, it is a bug in OVS. Segmentation is required before > fragmentation as otherwise GRO isn't transparent and fragments will be forwarded > that contain data from multiple different packets. It's also probably less efficient, > if the segment size is smaller than the MTU. I think this should be addressed in a > separate patch series. > > I'll also mention OVS in the commit message. > I looked into it, and it seems that you are correct. Looks like fragmentation can occur without segmentation in the OVS forwarding case. As I said, this is a bug since generated fragments may contain data from multiple packets. Still, this can already happen for packets with incrementing IDs and nothing special in particular will happen for the packets discussed in this patch. This should be fixed in a separate patch series, as do all other cases where ip_do_fragment is called directly without segmenting the packets first. No changes are required for the current series as it does not introduce this issue or give it more exposure. I'll remove the comment about fragmentation from the commit message since it's not entirely correct and it is rather irrelevant to this patch anyway. >> /P >> >
© 2016 - 2025 Red Hat, Inc.