On Wed, 12 Aug 2026 10:33:19 +0000 Chia-Yu Chang (Nokia) wrote: > > > - /* This indicates the tcp segment has CWR set. */ > > > + /* For TX, this indicates that the first TCP segment has CWR set, > > > and > > > + * any subsequent segment in the same skb has CWR cleared. This flag > > > + * must not be used in RX, because the connection to which the > > > segment > > > + * belongs is not tracked to use RFC3168 or AccECN. Using RFC3168 > > > ECN > > > + * offload may clear CWR and corrupt ACE signal (CWR is part of it). > > > + * Instead, SKB_GSO_TCP_ACCECN shall be used to avoid CWR > > > corruption. > > > + */ > > > > I still can't wrap my head around this TBH. > > > > SKB_GSO_TCP_ECN means RFC3168 > > SKB_GSO_TCP_ACCECN means AccECN > > > > If the HW can correctly detect cwr on first frame and then no cwr and > > report that as ECN/RFC3168 - what's the problem? TSO will produce the exact > > expected segment sequence. > > > > Is the program that if we re-GRO that frame in SW we end up with > > ECN+ACCECN on the same skb? > > Yes, this is the problem. > The HW does not know whether the received packets belong to an RFC3168 ECN > flow or an AccECN flow on the RX path. > For example, HW GRO may set SKB_GSO_TCP_ECN after observing that the first > packet has CWR=1: > > +===================+==========+=================+================+ > | Packet id | CWR flag | Flag | Flushed as SKB | > +===================+==========+=================+================+ > | 0 | 1 | SKB_GSO_TCP_ECN | 0 | > | 1 | 0 | - | 0 | > | 2 | 1 | - | 0 | > | 3 | 1 | - | 1 | > +===================+==========+=================+================+ > > If the aggregated skb is forwarded through a device using GSO, e.g., > HW RX (GRO) -> veth TX (GSO), the SKB_GSO_TCP_ECN applies RFC3168 > semantics. This means that only the 1st segment keeps the CWR flag > while all subsequent segments have CWR cleared: > > +===================+==========+ > | Packet id | CWR flag | > +===================+==========+ > | 0 | 1 | > | 1 | 0 | > | 2 | 0 | > | 3 | 0 | > +===================+==========+ > > This behavior is ok for RFC3168, since CWR is expected to appear only > once. However, for AccECN, CWR is part of the ACE signal and must be > preserved across all segments.
But this would be obviously a buggy HW-GRO implementation. The rules for HW-GRO RFC3168 are -- ignore CWR on first segment (host responsible for populating SKB_GSO_TCP_ECN), and CWR _must be 0_ for all subsequent segments. > In the example above, the original CWR sequence was 1,0,1,1. > But after re-segmentation it becomes: 1,0,0,0. > This is why SKB_GSO_TCP_ECN should not be used in RX/GRO paths. We have extensive gro tests under tools/testing/selftests/drivers/net/gro.py If you want to catch bad devices - add appropriate test cases there. The comment as stated seems to be misleading - there's nothing wrong with using the flag if the device follows the RFC3168 semantics correctly. And of course, adding a comment and hoping people will find it is much weaker than adding tests. Again, maybe I'm missing what _actually_ doesn't work here. You mention veth but veth does not participate in GRO directly, it's not a HW driver either.
