本文目標:
在核心網路中的所有訊息都可以被分成兩大類:
Control plane 的部分就像是之前介紹的那樣,有各式各樣的網路協定(NAS、NGAP、PFCP、GTP-C)會在核網中被用到。
而 Data plane 不像前者有這麼多協議(只使用 GTP-U),當我們撇開那些控制訊號不看,整個核心網路其實就是一個巨大的 gateway(將通訊網路與外部網路相連),所以接觸核心網路時我們總是可以看到很多處理網路封包的相關技術,對於像筆者這樣的小白來說真的是非常頭痛。
經過了一段時間的磨練後,筆者也漸漸搞懂了一些技術與觀念將它記錄下來,本篇文章會注重在一些 Linux 中常見的網路觀念或是技術上,讓大家可以更好的銜接之後的技術文章:
insmod
或是 modprobe
將模組載入到 kernel,free5gc 的 gtp5g 專案(Data plane of UPF)就屬於 kernel module。Traffic control 包含了幾個重要的功能:
簡單來說,tc 的這些功能是透過 filter + queuing disciplines(qdisc)組成的:
圖片來源:https://www.cnblogs.com/charlieroro/p/13993695.html
上圖是一個最基本的 queuing disciplines:pfifo,我們可以看到它由多個 queue 所組成:
而 filter 則是決定哪些封包能夠被放入 queue,而 filter 有多個種類可供使用者挑選。
在談 eBPF 之前,我們需要來聊聊 BPF(Berkeley Packet Filter)這項技術,BPF 最初由 berkeley 提出,是一項用於過濾封包的機制。
雖著 Linux kernel 的演進,BPF 被採納到核心中並且逐步擴充為 eBPF(Extended BPF),成為 Linux kernel 內建的內部行為分析工具,功能包含:
圖片來源:https://speakerdeck.com/johnlin/ebpf-based-container-networking
eBPF 提供了一種特別的資料結構:map,讓我們可以在 user space 與 kernel space 存取它:
struct bpf_map_def SEC("maps") stat_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(struct datarec),
.max_entries = 10,
};
參考上方程式碼,它宣告了 BPF_MAP_TYPE_ARRAY
類型的 map,key 的大小為 4 bytes,每個 value 能容下一個 datarec structure。stat_map
可容納 10 筆資料,超過以後便會出錯。
DPDK 是由 Intel 提出的技術,它可以繞過 kernel space 的封包處理(kernel bypass),直接將封包內容透過 zero-copy 技術複製到 user space,提高系統的 throughput。
參考上圖,左側的架構為傳統 Linux 的封包處理流程,在一般情況下,網路封包必須經過 kernel 的 protocol stack、分配 socket buffer(代表封包本身),最後再利用系統呼叫將 socket buffer 的資料拷貝至 user space(假設有 user space application 在監聽 socket,這時候 application 會取得封包資料),這個作法會因為以下原因拖累效能:
而 dpdk 直接跳過 kernel space,利用 PMD(Poll Mode Driver)關注網卡的 tx/rx ring,直接將封包複製到 user space 進行處理。這樣一來,可以大大的提升系統的吞吐量,不過這也會讓系統開發者面臨一些挑戰:
幸運的是,Intel 的開源專案:nff-go 幫助我們解決上面大部分惱人的問題,這個專案是一個 high-level 的 dpdk framework,可以幫助開發者快速的打造基於 DPDK 的 Network Function。
參考上圖,nff-go 的開發概念是讓開發者描述 flow graph,透過它提供的 hook function 綁定開發者自定義的 user-defined function,來決定封包應該被:
除此之外,它還提供了 L2 到 L4 的封包處理函式(Parsing、Encapsulate、Decapsulate),讓我們不用重複造輪子。
更多資訊請參考 Intel 開發者提供的投影片。
圖片來源:https://sematext.com/blog/ebpf-and-xdp-for-processing-packets-at-bare-metal-speed/
XDP(eXpress Data Path)是以 eBPF 為基礎的高性能、可編程的網路路徑技術,它可以讓網路封包在不經過作業系統的 networking stack 的情況下完成封包的處理(轉發或是丟棄),它常見於:
補充:
XDP 與 dpdk 不同,它並不是 kernel bypass 的技術,因為網路封包已經進入到 kernel space 了,只不過這些封包會在 socket buffer allocation 之前被處理掉。
除此之外,也有開發者使用 xdp 技術開發 5G UPF 並且發表了論文:
XDP 之所以能夠這麼快,最大的原因是:它能夠在作業系統分配 socket buffer 就將封包處理完畢(也可以理解是網路封包將不會經過系統的網路堆疊處理):
上圖取自 Securing Linux with a Faster and Scalable Iptables,它比較了傳統 iptables 以及 bpf-iptables 之間的效能差異。
雖然造成差異如此巨大的原因有很多(匹配演算法、連線追蹤實作),但最根本的原因仍離不開 early processing 帶來的影響。
因為這個優秀的效能表現,在 Kubernetes 生態圈也能夠見到相關的應用:Cilium:
Cilium 可以直接取代 kube-proxy,接手原本由 kube-proxy 負責的:附載均衡
、封包路由
、服務探索
...等工作。
本篇文章大致介紹了網路封包從硬體到 kernel space、再到 user space 會經過哪些系統處理,並且介紹了一些不同於傳統的網路封包處理技術(DPDK、XDP),這幾項技術常見於高效能的網路服務。或許一般的工程師並不需要掌握這些技術,但我認爲學習作業系統如何解決網路帶來的效能瓶頸是一個工程師的基本素養(有益無害)。
本系列文從一開始探討 5G 系統的概念以及 control plane 的設計、user plane 的技術細節,緊接著的兩篇文章會詳細地介紹 TCP/IP Stack、Linux network device driver 的一些概念,帶大家透過解讀優秀的開源專案增加 computer science 的基礎知識。