On Thu, Aug 13, 2026 at 6:33 AM Chia-Yu Chang (Nokia) <[email protected]> wrote: > > > 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. > > > > I added a test case in patch 6f74bc8b6e8d related to the CWR flag. > In that case, there are 5 packets with CWR values of 0, 1, 1, 0, and 0, and > packets are flushed after the 1st, 3rd, and 5th packets. > The gro.py uses this case in tools/testing/selftests/net/lib/gro.c to verify > CWR behavior. > But indeed, that does not cover whether SKB_GSO_TCP_ECN or SKB_GSO_TCP_ACCECN > shall be set during the GRO. > So, a test might be added to verify the SKB_GSO_TCP_ECN or SKB_GSO_TCP_ACCECN > flags (if there is another suggested way, please let me know)? > > > 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. > > Before adding an extra test, we need to clarify the definition and usages of > these flags. > At the TX path, in tcp_gso_segment() of net/ipv4/tcp_offload.c, the > SKB_GSO_TCP_ACCECN flag is used to preserve the CWR flags for AccECN flows. > Otherwise, when without SKB_GSO_TCP_ACCECN (RFC3168 ECN or Non-ECN flows), > cwr will be cleared from the following packets. > > For the RX path, unfortunately I do not find a clear rule of when > SKB_GSO_TCP_ECN shall be set except in include/linux/skbuff.h. > Plus, the device usually does not track packets belonging to RFC3168 ECN or > ACCECN flows. > So, my previous thought is to always use SKB_GSO_TCP_ACCECN in the RX path to > avoid any potential CWR bleaching.
This would be a case where AccECN support causes a regression for regular ECN handling, if that is no longer allowed to be coalesced. Most HW-GRO hardware out there today likely only supports ECN. In which case they can set SKB_GSO_TCP_ECN fine. If AccECN flows cannot be differentiated from ECN flows, on such devices, does the admin have to disable HW-GRO with ECN if they care about preserving AccECN signals? What does SW GRO do here?
