多路徑 TCP (MPTCP)¶
簡介¶
多路徑 TCP 或 MPTCP 是標準 TCP 的擴充套件,在 RFC 8684 (MPTCPv1) 中有所描述。它允許裝置同時使用多個介面,透過單個 MPTCP 連線傳送和接收 TCP 資料包。MPTCP 可以聚合多個介面的頻寬,或優先選擇延遲最低的介面。如果其中一條路徑出現故障,它還允許故障轉移,流量將無縫地重新注入到其他路徑上。
有關 Linux 核心中多路徑 TCP 的更多詳細資訊,請參閱官方網站:mptcp.dev。
用例¶
得益於 MPTCP,能夠並行或同時使用多條路徑帶來了與 TCP 相比的新用例
無縫切換:在保留已建立連線的同時從一條路徑切換到另一條路徑,例如用於移動性用例,如智慧手機。
最佳網路選擇:根據某些條件(例如延遲、丟包、成本、頻寬等)使用“最佳”可用路徑。
網路聚合:同時使用多條路徑以獲得更高的吞吐量,例如結合固定網路和行動網路以更快地傳送檔案。
概念¶
從技術上講,當使用 IPPROTO_MPTCP 協議(Linux 特有)建立新的套接字時,會建立一個子流(或路徑)。這個子流由一個常規的 TCP 連線組成,用於透過一個介面傳輸資料。主機之間稍後可以協商額外的子流。為了使遠端主機能夠檢測到 MPTCP 的使用,在底層 TCP 子流的 TCP 選項欄位中添加了一個新欄位。該欄位包含(除其他外)一個 MP_CAPABLE 選項,如果支援 MPTCP,則它會告訴另一個主機使用 MPTCP。如果遠端主機或其間的任何中間裝置不支援 MPTCP,則返回的 SYN+ACK 資料包的 TCP 選項欄位將不包含 MPTCP 選項。在這種情況下,連線將“降級”為普通 TCP,並繼續使用單路徑。
這種行為是透過兩個內部元件實現的:路徑管理器和資料包排程器。
路徑管理器¶
路徑管理器負責子流的建立、刪除以及地址通告。通常,由客戶端發起子流,伺服器端透過 ADD_ADDR 和 REMOVE_ADDR 選項通告附加地址。
路徑管理器由 net.mptcp.pm_type sysctl 旋鈕控制——參見 MPTCP Sysfs 變數。有兩種型別:核心內建型別(型別 0),所有連線都應用相同的規則(參見:ip mptcp);以及使用者空間型別(型別 1),由使用者空間守護程序(即 mptcpd)控制,可以為每個連線應用不同的規則。路徑管理器可以透過 Netlink API 進行控制;參見 Family mptcp_pm netlink specification。
為了能夠在主機上使用多個 IP 地址來建立多個子流(路徑),預設的核心內建 MPTCP 路徑管理器需要知道可以使用哪些 IP 地址。例如,這可以透過 ip mptcp endpoint 進行配置。
資料包排程器¶
資料包排程器負責選擇使用哪些可用子流來發送下一個資料包。它可以決定最大化可用頻寬的使用,或者只選擇延遲較低的路徑,或者根據配置選擇任何其他策略。
資料包排程器由 net.mptcp.scheduler sysctl 旋鈕控制——參見 MPTCP Sysfs 變數。
套接字 API¶
建立 MPTCP 套接字¶
在 Linux 上,建立 socket 時選擇 MPTCP 而不是 TCP 即可使用 MPTCP
int sd = socket(AF_INET(6), SOCK_STREAM, IPPROTO_MPTCP);
請注意,IPPROTO_MPTCP 被定義為 262。
如果不支援 MPTCP,errno 將被設定為
EINVAL:(無效引數):MPTCP 在核心版本 < 5.6 時不可用。EPROTONOSUPPORT(協議不支援):MPTCP 在核心版本 >= v5.6 時未編譯。ENOPROTOOPT(協議不可用):MPTCP 已透過net.mptcp.enabledsysctl 旋鈕停用;參見 MPTCP Sysfs 變數。
MPTCP 隨後是可選的(opt-in):應用程式需要明確請求它。請注意,應用程式可以透過不同的技術強制使用 MPTCP,例如 LD_PRELOAD(參見 mptcpize)、eBPF(參見 mptcpify)、SystemTAP、GODEBUG(GODEBUG=multipathtcp=1)等。
對於使用者空間應用程式來說,從 IPPROTO_TCP 切換到 IPPROTO_MPTCP 應該儘可能透明。
套接字選項¶
MPTCP 支援 TCP 處理的大多數套接字選項。一些不太常用的選項可能不支援,但歡迎貢獻。
通常,相同的值會傳播到所有子流,包括在呼叫 setsockopt() 後建立的子流。eBPF 可用於為每個子流設定不同的值。
在 SOL_MPTCP (284) 級別有一些 MPTCP 特定的套接字選項用於檢索資訊。它們填充 getsockopt() 系統呼叫的 optval 緩衝區
MPTCP_INFO:使用struct mptcp_info。MPTCP_TCPINFO:使用struct mptcp_subflow_data,後跟一個struct tcp_info陣列。MPTCP_SUBFLOW_ADDRS:使用struct mptcp_subflow_data,後跟一個mptcp_subflow_addrs陣列。MPTCP_FULL_INFO:使用struct mptcp_full_info,其中一個指標指向struct mptcp_subflow_info陣列(包括struct mptcp_subflow_addrs),一個指標指向struct tcp_info陣列,後跟struct mptcp_info的內容。
請注意,在 TCP 級別,可以使用 TCP_IS_MPTCP 套接字選項來了解 MPTCP 當前是否正在使用:如果正在使用,其值將設定為 1。
設計選擇¶
針對面向使用者空間的套接字,MPTCP 增加了一種新的套接字型別。核心負責建立子流套接字:它們是使用 TCP-ULP 修改行為的 TCP 套接字。
如果客戶端的連線請求未要求 MPTCP,MPTCP 監聽套接字將建立“普通”的*已接受* TCP 套接字,從而在預設啟用 MPTCP 時將效能影響降至最低。