How Linux Handles ECN in TCP Traffic

Explicit Congestion Notification (ECN) allows the Linux operating system to detect and respond to network congestion without relying on dropped packets. In TCP traffic, the Linux kernel implements ECN by negotiating capabilities during the three-way handshake, interpreting Congestion Experienced (CE) marks placed by intermediate routers in the IP header, signaling back via TCP flags, and adjusting the congestion window accordingly. Through fine-grained kernel sysctl configurations, Linux provides a reliable mechanism to reduce latency, prevent packet retransmissions, and sustain high throughput under heavy network load.

ECN Negotiation via the TCP Handshake

Before ECN can be utilized, both endpoints must agree to use it during the initial TCP three-way handshake:

  1. SYN Packet: The Linux client advertises ECN support by setting both the ECN-Echo (ECE) and Congestion Window Reduced (CWR) flags in the TCP header of the initial SYN packet.
  2. SYN-ACK Packet: If the responding Linux server supports ECN, it replies with a SYN-ACK packet with only the ECE flag set.
  3. ACK Packet: The client completes the handshake with a standard ACK packet, establishing an ECN-capable TCP session.

If either endpoint does not support ECN or if an intermediate middlebox clears these flags, the Linux kernel automatically falls back to standard, non-ECN TCP operation.

IP-Level Packet Marking

Once negotiated, the Linux networking stack sets the ECN field in the IP header of outgoing data packets. The IP header uses the two least-significant bits of the Differentiated Services (DiffServ) field:

When an intermediate router encounters buffer buildup, instead of dropping an ECT-marked packet (tail drop or active queue management like RED/CoDel), it rewrites the IP bits to 11 (CE) and forwards the packet to its destination.

Handling Congestion Signals in the Linux Stack

When the receiving Linux host accepts a packet marked with CE in the IP header, it acknowledges the congestion event back to the sender through the TCP header:

  1. ECE Generation: The receiver sets the ECE flag on subsequent TCP ACK packets sent back to the sender. It continues setting ECE on ACKs until the sender acknowledges the notification.
  2. Sender Reaction: When the transmitting Linux host receives an ACK with the ECE bit set, it invokes its active congestion control algorithm (such as CUBIC, BBR, or DCTCP). The kernel reduces the Congestion Window (cwnd) and the Slow Start Threshold (ssthresh) in a manner similar to handling a single packet loss event.
  3. CWR Acknowledgment: The sender then sets the CWR flag on the next outgoing data packet. This informs the receiver that the sender has responded to the congestion event, allowing the receiver to stop setting the ECE flag on subsequent ACKs.

Because the window reduction happens without an actual packet drop, the connection avoids costly packet retransmissions and prevents TCP fast recovery timeouts.

Linux Kernel Configuration

Linux manages ECN behavior through sysctl settings located in /proc/sys/net/ipv4/: