Skip to content

Commit 4da233d

Browse files
committed
More content on ECN added
1 parent 9790a92 commit 4da233d

2 files changed

Lines changed: 193 additions & 20 deletions

File tree

_articles/congestion.md

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -307,30 +307,100 @@ corruption. When receiver notices corrupted packet from invalid checksum, it
307307
will ignore the packet. When data sender notices that packet is lost, it reacts
308308
to it as congestion event and reduces transmission rate.
309309

310-
Explicit congestion notification (ECN, [RFC
311-
3168](https://datatracker.ietf.org/doc/html/rfc3168)) was introduced as a
312-
mechanism for network routers to signal that they are congested before dropping
313-
packets. When connection is opened, the transport protocol (e.g. TCP) client
314-
checks if the other end of the connection supports ECN by using a couple of bits
315-
in transport header. When sending packets, it also marks a bit in IP header to
316-
indicate the the current connection is capable of using ECN. When active queue
317-
management algorithm at router wants to signal congestion, it marks another bit
318-
in the IP header. Receiver transport protocol echoes the status of this bit back
319-
to sender with the acknowledgment of the packet, after which the sender should
320-
reduce the transmission rate similarly than it would react to packet loss.
321-
Therefore ECN can help to avoid many of the congestion-related packet losses.
310+
**Explicit congestion notification (ECN, [RFC
311+
3168](https://datatracker.ietf.org/doc/html/rfc3168))** was introduced as a
312+
mechanism for network routers to signal that they are congested without having
313+
to drop packets. Therefore ECN should be used together with one of the active
314+
queue management algorithms discussed above. ECN uses two bits in the IP header
315+
and two bits in the TCP header for its signaling.
316+
317+
If a sender supports ECN, it marks a **"ECN-capable transport (ECT)"** bit in
318+
the IP header for all outgoing packets, to indicate the routers on the path that
319+
ECN is available for this data flow. If this bit is enabled, and router is
320+
congested, it sets another **"congestion experienced (CE)"** bit in the IP
321+
header to tell this. If the ECT bit was not set on IP header, the router behaves
322+
in the traditional way, dropping the IP packet entirely. Because ECN helps to
323+
avoid packet losses due to congestion, data senders have incentive to use ECN if
324+
the implementation supports it.
325+
326+
Because the congestion window and sending rate is managed at the sending end of
327+
the transfer, the received needs to echo the congestion information back, when
328+
it receives a packet with **CE bit** on. This happens inside the TCP header
329+
(because routers do not need to see this information), using a **"ECN-Echo
330+
(ECE)"** bit in TCP acknowledgment header. When the TCP receivers this
331+
acknowledgment, it knows to reduce the sending rate and congestion window, even
332+
if no packet loss is detected. Because it is important that sender actually
333+
receives the congestion information, but it is possible that also acknowledgment
334+
packets are lost in the network, the **ECE** bit is applied in all subsequent
335+
acknowledgments, until the TCP receiver gets a TCP header with "**Congestion
336+
Window Reduced (CWR)**" bit on. Using this the TCP sender tells that it has
337+
received the ECE bit, and has reduced congestion window. After this the receiver
338+
can stop sending **ECE** bits, until another congestion indication comes. This
339+
resembles the three-way handshake in the beginning of TCP connection. From this
340+
we can notice that the basic TCP can deliver only one congestion indication per
341+
round-trip time. This is also the case with loss-based congestion control.
342+
343+
The below diagram illustrates the packet sequence when congestion is noticed at
344+
a router (at red "X").
345+
346+
![ECN operation](/images/cc-ecn.svg){: width="90%" .center-img }
347+
348+
In the beginning of the connection, during TCP connection establishment
349+
handshake, the TCP sender must verify if the receiver also supports ECN. If it
350+
is not able to echo the congestion information back, ECN cannot be used. This is
351+
done by setting the TCP-layer ECN bits on. The receiver echoes back the **ECE**
352+
bit, if it is capable of using ECN, and ECN can be used for this connection.
353+
354+
### Setting up ECN in Linux
355+
356+
Linux supports ECN both at TCP layer and on IP packet forwarding. By default
357+
Linux works in a "passive mode": ECN is enabled only when incoming connection
358+
indicates in TCP handshake that it wants to use ECN, by having the ECN bits set.
359+
In other words, by default a Linux client that opens the connection does not use
360+
ECN. This choice was made after it was observed that there are (outdated and
361+
old) routers in the Internet that cannot handle packets with ECN bit properly,
362+
and in worse case drop them. This is, of course, unfortunate considering the
363+
wider deployment of the ECN protocol.
364+
365+
Linux uses **sysctl** parameters to control various aspects in kernel behavior.
366+
For example, for the networking operations alone, there are tens of parameters
367+
than can be used to tune TCP and IP behavior. One of the parameters is
368+
`net.ipv4.tcp_ecn` that tells whether ECN should be used with TCP. You can query
369+
the current value by:
370+
371+
sysctl net.ipv4.tcp_ecn
372+
373+
This likely returns value 2, which stands for the passive mode ECN described
374+
above. ECN can be enabled in all connections, in active mode, by setting this
375+
parameter to 1:
376+
377+
sudo sysctl -w net.ipv4.tcp_ecn=1
378+
379+
By default many Linux systems apply FQ-CoDel forwarding, with ECN enabled, as we
380+
could see in the Traffic Control `qdisc` example in the above FQ-CoDel section:
381+
"`ecn`" in the tc output tells that ECN is enabled in packet forwarding. If this
382+
was not the case, it could be enabled, for example by:
383+
384+
sudo tc qdisc replace dev eth0 root fq_codel ecn
385+
386+
Replacing the interface name with actual interface.
387+
388+
In Mininet, assuming our **aalto/simple_topo.py**, ECN can be enabled using the
389+
`--ecn` command line option. Note that after this, you'll need to enable the ECN
390+
separately in the Mininet virtual hosts using the above sysctl in each of the
391+
ones you are using to start TCP connections.
322392

323393
## Classes of Modern congestion control
324394

325395
For decades TCP congestion control was based on window-based algorithm, quite
326-
often Reno or NewReno, and it is still typically what is taught on the basic
327-
networking course books. The classical algorithm has been successful, because it
328-
is simple and easy to understand for anyone new to computer networks: if there
329-
are no packet losses, TCP congestion window is increased at steady pace, but
330-
reaction to congestion is stronger: the congestion window is reduced to half on
331-
detected packet loss, or in some cases initialized to one, if there is a
332-
retransmission timeout. This kind of algorithms have been called Additive
333-
Increase, Multiplicative Decrease (AIMD) algorithms.
396+
often Reno (or NewReno) or Tahoe algorithms, and it is still typically what is
397+
taught on the basic networking course books. The classical algorithm has been
398+
successful, because it is simple and easy to understand for anyone new to
399+
computer networks: if there are no packet losses, TCP congestion window is
400+
increased at steady pace, but reaction to congestion is stronger: the congestion
401+
window is reduced to half on detected packet loss, or in some cases initialized
402+
to one, if there is a retransmission timeout. This kind of algorithms have been
403+
called Additive Increase, Multiplicative Decrease (AIMD) algorithms.
334404

335405
The loss based AIMD-algorithms are not ideal: they are reactive and take action
336406
when congestion has already caused problems. The active queue management

images/cc-ecn.drawio

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.0 Chrome/140.0.7339.249 Electron/38.7.2 Safari/537.36" version="29.3.0">
2+
<diagram name="Page-1" id="KHb53CQbkvG6am2rheoO">
3+
<mxGraphModel dx="814" dy="544" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
4+
<root>
5+
<mxCell id="0" />
6+
<mxCell id="1" parent="0" />
7+
<mxCell id="Mfw0hecvXmThsyoLGnsH-29" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=1.1;entryY=0.346;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=8 8;" value="">
8+
<mxGeometry height="50" relative="1" width="50" as="geometry">
9+
<mxPoint x="360" y="310" as="sourcePoint" />
10+
<mxPoint x="62" y="337" as="targetPoint" />
11+
</mxGeometry>
12+
</mxCell>
13+
<mxCell id="Mfw0hecvXmThsyoLGnsH-23" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=1.05;exitY=0.029;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.05;entryY=0.157;entryDx=0;entryDy=0;entryPerimeter=0;" value="">
14+
<mxGeometry height="50" relative="1" width="50" as="geometry">
15+
<mxPoint x="62" y="258.1236823285537" as="sourcePoint" />
16+
<mxPoint x="360" y="293.9636823285537" as="targetPoint" />
17+
</mxGeometry>
18+
</mxCell>
19+
<mxCell id="Mfw0hecvXmThsyoLGnsH-21" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=1.1;entryY=0.346;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=8 8;" value="">
20+
<mxGeometry height="50" relative="1" width="50" as="geometry">
21+
<mxPoint x="360" y="209.99999999999997" as="sourcePoint" />
22+
<mxPoint x="62" y="236.99999999999997" as="targetPoint" />
23+
</mxGeometry>
24+
</mxCell>
25+
<mxCell id="Mfw0hecvXmThsyoLGnsH-19" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=1.1;entryY=0.346;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=8 8;" value="">
26+
<mxGeometry height="50" relative="1" width="50" as="geometry">
27+
<mxPoint x="359" y="179.99999999999997" as="sourcePoint" />
28+
<mxPoint x="61" y="206.99999999999997" as="targetPoint" />
29+
</mxGeometry>
30+
</mxCell>
31+
<mxCell id="Mfw0hecvXmThsyoLGnsH-17" edge="1" parent="1" source="Mfw0hecvXmThsyoLGnsH-2" style="endArrow=classic;html=1;rounded=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=1.1;entryY=0.346;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=8 8;" target="Mfw0hecvXmThsyoLGnsH-1" value="">
32+
<mxGeometry height="50" relative="1" width="50" as="geometry">
33+
<mxPoint x="350" y="340" as="sourcePoint" />
34+
<mxPoint x="110" y="220" as="targetPoint" />
35+
</mxGeometry>
36+
</mxCell>
37+
<mxCell id="Mfw0hecvXmThsyoLGnsH-14" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=1.05;exitY=0.029;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.05;entryY=0.157;entryDx=0;entryDy=0;entryPerimeter=0;" value="">
38+
<mxGeometry height="50" relative="1" width="50" as="geometry">
39+
<mxPoint x="62" y="98.1236823285537" as="sourcePoint" />
40+
<mxPoint x="360" y="133.96368232855372" as="targetPoint" />
41+
</mxGeometry>
42+
</mxCell>
43+
<mxCell id="Mfw0hecvXmThsyoLGnsH-7" edge="1" parent="1" style="endArrow=classic;html=1;rounded=0;exitX=1.05;exitY=0.029;exitDx=0;exitDy=0;exitPerimeter=0;entryX=-0.05;entryY=0.157;entryDx=0;entryDy=0;entryPerimeter=0;" value="">
44+
<mxGeometry height="50" relative="1" width="50" as="geometry">
45+
<mxPoint x="60" y="128.12" as="sourcePoint" />
46+
<mxPoint x="358" y="163.96000000000004" as="targetPoint" />
47+
</mxGeometry>
48+
</mxCell>
49+
<mxCell id="Mfw0hecvXmThsyoLGnsH-1" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" value="" vertex="1">
50+
<mxGeometry height="280" width="20" x="40" y="80" as="geometry" />
51+
</mxCell>
52+
<mxCell id="Mfw0hecvXmThsyoLGnsH-2" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" value="" vertex="1">
53+
<mxGeometry height="280" width="20" x="360" y="80" as="geometry" />
54+
</mxCell>
55+
<mxCell id="Mfw0hecvXmThsyoLGnsH-3" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" value="" vertex="1">
56+
<mxGeometry height="280" width="20" x="200" y="80" as="geometry" />
57+
</mxCell>
58+
<mxCell id="Mfw0hecvXmThsyoLGnsH-4" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="sender" vertex="1">
59+
<mxGeometry height="30" width="60" x="20" y="50" as="geometry" />
60+
</mxCell>
61+
<mxCell id="Mfw0hecvXmThsyoLGnsH-5" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="router" vertex="1">
62+
<mxGeometry height="30" width="60" x="180" y="50" as="geometry" />
63+
</mxCell>
64+
<mxCell id="Mfw0hecvXmThsyoLGnsH-6" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="receiver" vertex="1">
65+
<mxGeometry height="30" width="60" x="340" y="50" as="geometry" />
66+
</mxCell>
67+
<mxCell id="Mfw0hecvXmThsyoLGnsH-8" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="ECT(1)" vertex="1">
68+
<mxGeometry height="30" width="60" x="109" y="110" as="geometry" />
69+
</mxCell>
70+
<mxCell id="Mfw0hecvXmThsyoLGnsH-9" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="CE" vertex="1">
71+
<mxGeometry height="30" width="60" x="259.003583810063" y="130.0036823285537" as="geometry" />
72+
</mxCell>
73+
<mxCell id="Mfw0hecvXmThsyoLGnsH-10" parent="1" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.x;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;" value="" vertex="1">
74+
<mxGeometry height="10" width="10" x="219" y="140" as="geometry" />
75+
</mxCell>
76+
<mxCell id="Mfw0hecvXmThsyoLGnsH-15" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="ECT(1)" vertex="1">
77+
<mxGeometry height="30" width="60" x="111" y="80.0036823285537" as="geometry" />
78+
</mxCell>
79+
<mxCell id="Mfw0hecvXmThsyoLGnsH-16" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="ECT(1)" vertex="1">
80+
<mxGeometry height="30" width="60" x="261.003583810063" y="100.00736465710743" as="geometry" />
81+
</mxCell>
82+
<mxCell id="Mfw0hecvXmThsyoLGnsH-18" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=354;" value="&lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;ACK&lt;/font&gt;" vertex="1">
83+
<mxGeometry height="30" width="60" x="70.00358381006299" y="150.0036823285537" as="geometry" />
84+
</mxCell>
85+
<mxCell id="Mfw0hecvXmThsyoLGnsH-20" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=354;" value="&lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;ACK, ECE&lt;/font&gt;" vertex="1">
86+
<mxGeometry height="30" width="60" x="69.00358381006299" y="180.00368232855368" as="geometry" />
87+
</mxCell>
88+
<mxCell id="Mfw0hecvXmThsyoLGnsH-22" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=354;" value="&lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;ACK, ECE&lt;/font&gt;" vertex="1">
89+
<mxGeometry height="30" width="60" x="70.00358381006299" y="210.00368232855368" as="geometry" />
90+
</mxCell>
91+
<mxCell id="Mfw0hecvXmThsyoLGnsH-24" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="ECT(1), &lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;CWR&lt;/font&gt;" vertex="1">
92+
<mxGeometry height="30" width="80" x="89.95" y="241.05" as="geometry" />
93+
</mxCell>
94+
<mxCell id="Mfw0hecvXmThsyoLGnsH-27" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=6;" value="ECT(1), &lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;CWR&lt;/font&gt;" vertex="1">
95+
<mxGeometry height="30" width="80" x="238.99880276374574" y="259.9989669612302" as="geometry" />
96+
</mxCell>
97+
<mxCell id="Mfw0hecvXmThsyoLGnsH-30" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;rotation=354;" value="&lt;font style=&quot;color: rgb(51, 51, 255);&quot;&gt;ACK&lt;/font&gt;" vertex="1">
98+
<mxGeometry height="30" width="60" x="70.00358381006299" y="310.0036823285537" as="geometry" />
99+
</mxCell>
100+
</root>
101+
</mxGraphModel>
102+
</diagram>
103+
</mxfile>

0 commit comments

Comments
 (0)