明確擁塞通知

**顯式擁塞通知**（英語：**Explicit Congestion Notification**，簡稱 **ECN**）是一個對網際協定和傳輸控制協定（TCP）的擴充，定義於 RFC 3168（2001）。ECN 允許擁塞控制的端對端通知而避免丟包。ECN 為一項可選功能，如果底層網路設施支援，則可能被啟用 ECN 的兩個端點使用。

通常來說，TCP/IP 網路通過丟棄封包來表明信道阻塞。在 ECN 成功協商的情況下，ECN 感知路由器可以在 IP 頭中設定一個標記來代替丟棄封包，以標明阻塞即將發生。封包的接收端回應傳送端的表示，降低其傳輸速率，就如同在往常中檢測到包遺失那樣。

相比於正確回應或忽略位標記，一些過時或存在故障的網路裝置會丟棄或改動封包中的 ECN 位。截至 2015 年 (2015-Missing required parameter 1=_month_!)，測量顯示，公共網際網路上的網頁伺服器中設定而阻止 ECN 的網路連接已減少到少於 1%。

2015 年 5 月，蘋果公司宣布 ECN 將在其支援的及未來的產品中預設啟用，以幫助推播 ECN 訊號在整個行業中的應用。

## 操作

由於下列原因，ECN 需要網際網路層和傳輸層提供特定支援：

* 在 TCP/IP 中，路由器在網際網路層操作，而傳輸速率由傳輸層處的端點處理。
* 擁塞可能僅由傳送端處理，但由於它是在封包傳送後發生，所以接收端必須向傳送端回傳擁塞指示。

在無 ECN 時，擁塞指示回傳是通過檢測分組遺失來間接實現。在有 ECN 時，擁塞通過設定 IP 分組內的 ECN 欄位為 CE 並由接收端通過在傳輸協定的報頭中設定適當的位來回傳給傳送端。例如，當使用 TCP 時，擁塞指示通過設定 ECE 位來回傳。

### IP 中的 ECN 操作

ECN 使用 IPv4 首部或 IPv6 首部中 ToS (Type of Service，位於首部第 9 到 16 位元位) 欄位的兩個最低有效位（最右側的位編碼）來表示四個狀態碼：

* `00` – 不支援 ECN 的傳輸，非 ECT (Non ECN-Capable Transport)
* `10` – 支援 ECN 的傳輸，ECT (0)
* `01` – 支援 ECN 的傳輸，ECT (1)
* `11` – 發生擁塞，CE (Congestion Experienced)。

當兩端支援 ECN 時，它將封包標為 ECT (0) 或 ECT (1)。如果分組穿過一個遇到阻塞並且相應路由器支援 ECN 的活動佇列管理（AQM）佇列（例如一個使用隨機早期檢測，即 RED 的佇列），它可以將代碼點更改為 `CE` 而非丟包。這種行為就是「標記」，其目的是通知接收端即將發生擁塞。在接收端，該擁塞指示由上層協定（傳輸層協定）處理，並且需要將訊號回傳給傳送端，以通知其降低傳輸速率。

因為 CE 指示只能由支援它的上層協定有效處理，ECN 只能配合上層協定使用。例如 TCP 協定，它支援阻塞控制並且有方法將 CE 指示回傳給傳送端。

### TCP 中的 ECN

TCP 支援使用 TCP 頭中的三個標記（flag）來支援 ECN。第一個標記是隨機和（Nonce Sum，簡稱 NS），用於防止 TCP 傳送者的封包標記被意外或惡意改動。另兩位用於回傳擁塞指示（即指示傳送者應減少資訊傳送量）和確認接收到了擁塞指示回應。這即是 ECN-Echo（ECE）和 Congestion Window Reduced（CWR）位。

在 TCP 連接上使用 ECN 是可選的；當 ECN 被使用時，它必須在連接建立時通過 SYN 和 SYN-ACK 段中包含適當選項來協商。

當在一個 TCP 連接上協商 ECN 後，傳送方指示連接上的 TCP 段攜帶 IP 分組傳輸流量，將支援 ECN 的傳輸用 ECT 碼點標記。這使支援 ECN 的中間路由器可以標記具有 CE 碼點的 IP 分組而不是丟棄它們，以指示即將發生的阻塞。

當接收到具有**遇到阻塞**碼點時，TCP 接收者使用 TCP 頭中的 ECE 標記回傳這個阻塞指示。當一個端點收到 TCP 帶有 ECE 位的段時，它減少其擁塞窗口來代替丟包。然後，它設定段的 CWR 位來確認阻塞指示。

節點保持傳輸設定有 ECE 位的 TCP 段，直到它接收到設定有 CWR 的段。

要使用 tcpdump 檢視受影響的封包，使用過濾方法 `(tcp[13] & 0xc0 != 0)`。

#### ECN 與 TCP 控制包

由於傳輸控制協定（TCP）不對控制分組（純 ACKs、SYN、FIN 段）進行擁塞控制，控制分組通常不被標記為可進行 ECN。

一份 2009 年的提議建議將 SYN-ACK 標記為支援 ECN。這種改進被稱為 ECN+，已經顯示出對短壽命 TCP 連接的效能提供了顯著改善。

ECN 也在其他執行擁塞控制的傳輸層協定中被定義，尤其是資料擁塞控制協定（DCCP）和流控制傳輸協定（SCTP）。其一般原理類似於 TCP，儘管編碼細節有所不同。

在原則上可以在使用者資料報協定（UDP）之上的協定層實行 ECN。但是，UDP 需要應用程式實行擁塞控制，並且當前的網路 API 未提供存取 ECN 位的方法。

## 對效能的影響

由於 ECN 僅在配合活動佇列管理（AQM）策略時有效，因此 ECN 的益處依賴於所用的 AQM 的精確度。

如預期那樣，ECN 減少 TCP 連接中被丟棄的封包數量，以避免重傳、減少等待時間，尤其是網路抖動。當 TCP 連接有單個未完成段時，這種效果最為明顯，它可以避免傳輸控制協定（RTO）逾時；這通常發生在互動式連接時，例如遠端登入，以及事務協定，例如 HTTP 請求、SMTP 的對談階段、SQL 請求。

ECN 對批次吞吐的效果不太明確，因為現代的 TCP 實現在傳送方的窗口足夠大時對於及時處理段遺失相當友好。

ECN 的使用已被發現在高度擁塞的網路上是有害的，AQM 演算法使封包不會被丟棄。現代的 AQM 實現在極高負載下會丟包而非標記包來避免這個陷阱。

## 實現

許多現代產品中的 TCP/IP 協定已部分支援 ECN；但是，大多數產品預設禁用 ECN。

### 主機支援的 TCP 中的 ECN

#### Microsoft Windows

Windows 自 Windows Server 2008 和 Windows Vista 開始支援 TCP 中的 ECN。因為資料中心傳輸控制協定（DCTCP）被使用，從 Windows Server 2012 開始在 Windows Server 版本中預設啟用。在更早的 Windows 版本以及非 Server 版本中，它被預設禁用。

ECN 支援可以用命令啟用，例如 netsh interface tcp set global ecncapability=enabled。

#### 類 Unix

##### BSD

FreeBSD 8.0 和 NetBSD 4.0 為 TCP 實現了 ECN 支援，可以通過 sysctl 介面將 net.inet.tcp.ecn.enable 參數設為 1 來啟用。與此相同，OpenBSD 中可以設定 sysctl net.inet.tcp.ecn。

##### Linux

從發布於 2002 年 11 月的 Linux 核心 2.4.20 版本開始，Linux 支援 TCP 中的 ECN 的三種工作模式，以及通過 sysctl 介面設定 /proc/sys/net/ipv4/tcp\_ecn 參數為下列值：

* 0– 禁用 ECN，不發起也不接受
* 1– 啟用 ECN，當傳入連接請求時，並也在傳出連接時嘗試請求 ECN
* 2– （預設）傳入連接請求時啟用 ECN，但不在傳出連接上請求 ECN

從 2015 年 6 月發布的 Linux 核心 4.1 開始，tcp\_ecn\_fallback 機制按 RFC 3168 中的規定，在 ECN 被啟用（值為 1）時預設啟用。該回退機制在傳出連接的初始設定時嘗試 ECN 連接，對沒有 ECN 能力的傳輸實行良好回退，緩解不支援 ECN 的主機或防火牆問題。

##### Mac OS X

Mac OS X 10.5 和 10.6 為 TCP 實現了 ECN 支援。它採用 sysctl 的布林變數 net.inet.tcp.ecn\_negotiate\_in 和 net.inet.tcp.ecn\_initiate\_out 控制。第一個變數在已經設定 ECN 標記的傳入連接上使用 ECN；第二個則嘗試在傳出連接上啟用 ECN。兩個變數均預設為 0，但可以設定為 1 以實現相應的行為。

2015 年 6 月，蘋果公司宣布將在年內發布的 OS X 10.11 將預設啟用 ECN。

##### iOS

2015 年 6 月，蘋果公司宣布 iOS 的下一版本 ——iOS 9，將支援 ECN 並預設啟用。

##### Solaris

Solaris 核心支援對 TCP 支援 ECN 的三種狀態：

* never– 無 ECN
* active– 使用 ECN
* passive– 僅在被詢問時宣告 ECN 支援。

預設行為是 passive。從 Solaris 11 開始，可以通過 ipadm set-prop -p ecn=active tcp 啟用完整的 ECN 功能。

### 路由器支援的 IP 中的 ECN

由於在路由器中標記 ECN 依賴於某些形式的活動佇列管理，路由器必須組態合適的佇列規則才能實行 ECN 標記。

Cisco IOS 路由器從 12.2 (8) T 版本開始，如果已組態 WRED 排隊規則，則實行 ECN 標記。

Linux 路由器實行 ECN 標記，如果 RED 或 GRED 佇列顯式組態了 _ecn_ 參數，通過使用 sfb 規則，或使用 CoDel 公平排隊（fq\_codel）規則。

現代的 BSD 實現，例如 FreeBSD、NetBSD 和 OpenBSD 支援 ECN 標記，在許多排隊規則的 ALTQ 佇列實現，尤其是 RED 和 Blue。FreeBSD 11 在具有 ECN 標記能力的 ipfw/dummynet 框架中包括 CoDel、PIE、FQ-CoDel 和 FQ-PIE 排隊規則的實現。

### 資料中心 TCP

**資料中心傳輸控制協定**（也稱**資料中心 TCP** 或 **DCTCP**）是利用 ECN 來增強傳輸控制協定的擁塞控制演算法，其用於資料中心網路。標準的 TCP 擁塞控制演算法只能檢測擁塞的**存在**，而使用 ECN 的 DCTCP 可以測量擁塞的**程度**。

DCTCP 修改了 TCP 的接收端以始終中繼傳入連接的精確 ECN 標記，代價是忽略一個保持信令可靠性的功能。這使 DCTCP 的傳送端易受到接受 ACK 遺失的影響，因為它沒有檢測或應對的機制。截至 2014 年 7 月 (2014-07)，以更可靠的方法提供等效或更好的接收器回饋的演算法是一個活躍的研究課題，並有一個被稱為「More accurate ECN feedback in TCP」（「TCP 中更準確的 ECN 回饋」）（Accurate ECN，精準 ECN）的實驗建議。

## 參見

* 擁塞控制
* 反向顯式擁塞通知（BECN）
* 服務類型（ToS）

## 參考資料

## 外部連結

* ECN web page by Sally Floyd（頁面存檔備份，存於網際網路檔案館）
* RFC 4774 (BCP), _Specifying Alternate Semantics for the Explicit Congestion Notification (ECN) Field_, S. Floyd, (November 2006)
* Linux kernel support for defining a per-route/destination congestion control algorithm (merged in Linux kernel 4.0)