RFC-0184:系統 Netstack 的 POSIX 相容性

RFC-0184:系統網路堆疊的 POSIX 相容性
狀態已接受
區域
  • 外部 ABI 相容性
  • 網路堆疊
說明

說明在 Fuchsia 上支援類似 POSIX 的網路 API 的政策。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-07-15
審查日期 (年-月-日)2022-08-17

摘要

Fuchsia 的目標是透過 fdio 和系統網路堆疊,向元件公開與 POSIX 相容的網路 API。它也支援其他以 POSIX 為導向的作業系統常見的非 POSIX 功能。

提振精神

Fuchsia 現有的系統網路堆疊是圍繞著以 Linux 相容性為目標的核心建構而成。由於這個網狀堆疊的替換作業正在進行中,因此相容性問題一再浮現。這項提案要求任何系統網狀堆疊都以類似 POSIX 的 API 為目標,讓這些問題消失。

POSIX 網路介面說明元件存取網路資源的標準方式。為 Fuchsia 元件支援 POSIX 的網路子集,可輕鬆 1) 重複使用 Fuchsia 上的現有程式碼,以及 2) 使用熟悉的 API 為 Fuchsia 編寫新程式碼。

相關人員

誰會受到這項 RFC 是否通過的影響?(此為選用部分,但建議您填寫)。

協助人員:

hjfreyer@google.com

審查者:

  • abarth@google.com (RFC-0082 作者)
  • brunodalbo@google.com (網路堆疊)
  • dhobsd@google.com (網路政策)

諮詢:

brunodalbo@google.com, hanjh@google.com, hjfreyer@google.com, martinjeffrey@google.com, nickbrow@google.com, tamird@google.com, wildenhain@google.com

社會化:

這份 RFC 已通過網路堆疊團隊的設計審查。

設計

本文件中的關鍵字「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「MAY」和「OPTIONAL」應依 IETF RFC 2119 所述進行解讀。

在 Fuchsia 裝置上,系統網路堆疊會公開多個 fuchsia.posix.socket FIDL 服務,為元件提供網路功能。雖然支援 FIDL 的元件可以指定這些元件,但我們不建議直接使用這類元件。相反地,為 POSIX 系統呼叫 API 編寫的元件應連結 fdio 相容性程式庫,將 libc 系統呼叫轉譯為 FIDL 服務呼叫。

Fuchsia 的 fdio 程式庫可做為翻譯層,將 POSIX 的有限子集轉換為適當的 FIDL 服務。針對網路功能,fdio 提供多項 POSIX 呼叫的實作方式,包括 socketsetsockoptgetsockoptreadwritesendrecv 等。搭配使用 fdio 的 FIDL 服務實作,可完整實作這些呼叫和其他呼叫。

本文件的目標並非提供完整的系統呼叫清單,而是定義用於決定何時實作 POSIX 或同級系統定義網路功能的條件。fdio 和網路堆疊會視需要實作系統呼叫和選項,主要用於第一方 Fuchsia 程式碼,然後在其他應用程式需要時使用。本文不討論可透過使用 fdio 提供的系統呼叫來實作的 POSIX 函式。

請注意,雖然此提案規定 Fuchsia 必須提供與 POSIX 相容的網路介面,但並未強制要求使用該介面。特別是,沒有任何因素會阻止未來規格或開發 Fuchsia 優先 API 與 POSIX 一同實作。

實作

現有的 fdio 程式庫和系統網路堆疊,已為元件提供大致與 POSIX 相容的介面。這項提案旨在將尚未正式決定的目標,以與類似 POSIX 的作業系統保持一致,並引導網路堆疊和 fdio 程式庫的未來開發工作。變更系統網路堆疊和 fdio 時,應考量下列三項原則:

遵循 POSIX 規範

Fuchsia 的系統網路堆疊和 fdio 程式庫旨在為 POSIX 指定的網路 API 提供相容性。針對 POSIX 網路 API 的元件,如果連結至 fdio 並路由適當的 Socket 建立功能,應可正常運作。

與同類系統的相容性

POSIX 規格未定義某些互動的行為,因此針對 POSIX 介面編寫的元件通常會預期並考量特定作業系統或作業系統系列的行為。如果這項行為已清楚定義,且在多個類 POSIX 作業系統中一致,Fuchsia 的網路子系統應與之相符 (除了下文所述的少數情況)。如果同級系統的行為不一致,Fuchsia 無法保證能與任何特定同級系統的行為相符。

允許不同的行為

Fuchsia 網路子系統可能需要實作與同級系統不同的行為。發生以下情況時,就會出現這種差異:

  • 對等系統的行為彼此不一致。
  • 實作與同儕系統一致的行為會帶來安全性風險,或
  • 由於 Fuchsia 的架構限制,實作一致的行為可能會很困難,甚至無法實現。

在這些情況下,差異應有充分的理由、詳細的說明和充分的測試。此外,元件應能輕鬆觀察到行為差異 (例如 POSIX 系統呼叫傳回錯誤)。

已知限制

POSIX 會使用多個全域 ID 空間,包括 UID、GID、PID 和檔案路徑。許多此類 ID 會與內建支援功能一併使用,以便限制類似 POSIX 系統的網路作業存取權。包括但不限於:

  • 使用 SO_REUSEPORTSO_REUSEADDR 將位於相同位址的 Socket 繫結,僅限於使用相同 UID 執行的元件。
  • 在 Linux 上,只有透過 CAP_NET_RAW 執行的應用程式才能清除 SO_BINDTODEVICE 通訊端選項。
  • 在 Linux 上,只有透過 CAP_NET_RAW 執行的應用程式才能建立原始 IP 通訊端。
  • 在 Linux 上,如果要將 Socket 繫結至低編號的連接埠,應用程式必須具備 CAP_NET_BIND_SERVICE (雖然在近期 macOS 版本中,這項操作不需特權)。

在可行情況下,Fuchsia 會支援這些行為,但這取決於將功能對應至 Fuchsia 概念的可行性,且可能需要考量 Fuchsia 的架構限制。舉例來說,類似 POSIX 的系統會隱含使用程序的 UID 來設定連接埠共用權限範圍。由於 Fuchsia 沒有 UID,元件必須採取明確的行動,才能選擇啟用端口共用功能,這可能會以額外呼叫至 fdio 的形式呈現。

成效

為了正式支援 POSIX 網路介面,Fuchsia 的網路子系統將提供高效能 API 實作。Fuchsia 網路堆疊和 fdio 已提供可執行 POSIX 介面的大量基準測試工具。這會用於評估成效改善情形,並偵測回歸情形。

人體工學

由於 Fuchsia 以 POSIX 為目標,這是應用程式常用的知名介面,因此開發人員可以輕鬆移植現有程式碼,並透過熟悉的介面編寫新程式碼。雖然某些 POSIX 概念並未直接對應至 Fuchsia (例如 UID),但絕大多數的網路概念都會。如果網路連線使用熟悉的介面,就能大幅改善在 Fuchsia 上開發及移植程式碼的體驗。

回溯相容性

這項提案並非原則的變更,只是將非正式原則納入規範。由於沒有任何變更,因此不必考量向後相容性。

安全性考量

這份 RFC 會將現有的非正式原則編碼,因此不會引入任何新的安全考量。此外,提供與 POSIX 相容的 API 並非承諾,日後仍可針對網路堆疊進行個別元件隔離或分割,以解決安全性問題。

隱私權注意事項

這項提案只會將現有 POSIX API 的支援內容編碼化,因此不會引入任何新的隱私權考量。

測試

我們使用現有的相容性套件測試 Fuchsia 系統網狀堆疊,以便檢查與 POSIX 和 Linux 的相容性 (不過,後者只是為了方便起見,並非暗示 Linux 行為的隱含推薦)。這個測試套件會對系統回應 POSIX 呼叫的預期行為進行編碼,藉此防止回歸並引導日後的功能開發作業。Fuchsia 網路子系統與 POSIX 或類 POSIX 系統之間的行為差異,會在測試套件中編碼並記錄。已知的非預期差異也會經過編碼和記錄,並在 Fuchsia 的錯誤追蹤系統中標記。這項整合層級測試,加上系統網路堆疊內部現有的單元測試,可為 POSIX 相容性提供足夠的涵蓋率。

說明文件

這項提案需要兩項額外的文件:

  1. 使用 fdio API 與系統網路堆疊通訊的操作說明,以及
  2. 列出 Fuchsia 網路堆疊/fdio 與 POSIX/POSIX 類似系統行為之間的不同行為。

缺點、替代方案和未知事項

這項提案要求在 Fuchsia 系統網路堆疊和 fdio 程式庫中,實作 POSIX 和同級相容行為的重要子集。由於這項提案是現有計畫的正式版本,因此許多功能都已存在。這項提案承諾 Fuchsia 會擴充現有的 API 介面,並長期支援該介面。

雖然 POSIX 是眾所皆知的標準,但其設計並未支援 Fuchsia 的功能或豐富的 IPC 規格機制。為了支援與類似 POSIX 的系統相容性,您必須為元件提供更受限的介面 (同步系統呼叫、未指定類型的檔案描述符),並將這些概念塞入 Fuchsia 原始碼。此外,為 Fuchsia 元件採用類似 POSIX 的介面,可能會妨礙開發實用的 Fuchsia 優先網路 API。

作為更激進的選項,Fuchsia 可以明確避免 POSIX 相容性,轉而採用 Fuchsia 優先 API。考量到大量 Fuchsia 系統服務程式碼已針對類似 POSIX 的 API 編寫,這似乎會適得其反,而且缺乏遠見。

至於未知項目,主要預期類別是 POSIX 支援的未完成實作項目,以及 Fuchsia 相對於同類作業系統的不相容行為。這些問題會在發生或發現時加以處理及記錄。

既有技術與參考資料

  • POSIX 2017 規格列出 POSIX 相容系統的要求。
  • RFC-0082 說明 Fuchsia 在 Fuchsia 上執行未經修改的 Linux 程式的目標。
  • gVisor 專案的網路程式碼是現有 Fuchsia 系統網路堆疊的核心。

附錄:導入決策個案研究

POSIX 的 setsockopt 函式提供一種方法,讓程式碼在 Socket 上設定會影響其行為的選項。POSIX 定義了幾個選項標記,但符合規定的系統可自行新增自訂標記。其中一個相當常用的選項是 SO_REUSEPORT 選項,設定後可讓您在相同的位址和通訊埠上 bind 套接字。由於其語意已清楚定義,且在多個系統 (包括 FreeBSD、macOS 和其他 BSD 衍生版本) 中一致,Fuchsia 的網路堆疊可讓元件在 UDP 通訊端設定 SO_REUSEPORT 選項。

Linux 和 BSD 衍生版本的 SO_REUSEPORT 實作方式之間的差異之一,是 Linux 要求套接字必須綁定至相同位址,且屬於使用者 ID 相同的程序。由於 Fuchsia 的架構不允許類似的使用者 ID 概念,因此這項限制並未在 Fuchsia 中實作。

此外,Linux 的 SO_REUSEPORT 實作會導致行為不一致,這取決於是否在呼叫 bind 之前在通訊端上設定選項,然後在呼叫之後清除,或是完全不設定。依賴不可見的系統狀態和定義不佳的行為,會導致系統決定不模擬 Linux 的行為。

詳情請參閱 https://fxbug.dev/42051599。