Try   HackMD

Linux Kernel Networking - Implementation and Theory

This book introduce the implementation of the network stack in Linux Kernel.

Introduction

本書主要介紹 Linux Kernel Networking Stack 以及背後的理論。

The Linux Network Stack

Open Systems Interconnection(OSI),制定了7層的網路架構。但在 Linux Kernel 中,只專注於其中的 Data Link Layer(L2), Network Layer(L3), Transport Layer(L4) 這3層。更高層是由使用者自己掌控,而 L1 則是各個不同的網路卡 Network Interface Controller(NIC) 自己實作。
需要控制的封包可能有很多種狀態,例如

  • 根據 protocol rules 修改封包
  • 丟棄封包
  • 因為該封包而送出錯誤訊息
  • 封包可能需要被切割
  • 封包可能需要組合起來
  • 需要計算封包的 checksum

The Network Device

會用到 net_device 結構,該結構有很多資訊,例如

  • IRQ number
  • MTU
  • MAC
  • name of device(like eth0)
  • flags(for example, it is up or down)
  • multicast address list
  • promiscuity counter
    如果大於0,就不會丟棄目的地不是自己的封包,通常用於像是 Wireshark 或 tcpdump 之類的應用
  • 是否有 GSO/GRO offloading
    本篇有精美的圖可以看,解釋下列各個名詞
    • TSO: TCP Segmentation Offload, fregmentation 在網卡中做
    • GSO: Generic Segmentation Offload, fregmentation 在 Driver 才做
    • LRO: Large Receive Offload, defregmentation 在網卡中做
    • GRO: Generic Receive Offload, defregmentation 在 Driver 就坐
  • network device callbacks(net_device_ops) 可以拿來控制該裝置的開關、修改 MTU 等等
  • ethtool callback, 可以透過 ethtool 查看該裝置的資訊
  • 當該裝置支援 multiqueues 時,接收/發送的佇列數量
  • 最後一次傳送封包的時間
  • 最後一次接收封包的時間

New API(NAPI) in Network Devices

在 2.4(含)以前的 Linux Kernel 在接收到封包時,每接收到一個封包就會觸發一次 interrupt,這在有很多流量的環境中並不是個好的實作。在那之後,出現了 NAPI,核心概念是把 NIC 收到的封包先拿著,等接收到一定量的封包後才觸發中斷,呼叫核心處理這些封包,當然,該機制會限制 NIC 觸發中斷的等待時間,所以也不會等到天荒地老。
在 3.11(含) 之後,因應需要即時接收資料的情境,推出了 Busy Poll Sockets,在第 14 章會有更詳細的介紹。

Receiving and Transmitting Packets

網路裝置驅動主要有兩個任務

  • 收到需要接收的封包後,把封包送給 L3 然後再從 L3 送到 L4
  • 發送封包,或者把封包轉傳出去

對每個封包來說,不管是進來還是出去的封包,都需要透過查看 routing subsystem 的結果來決定要把該封包送到哪裡,這會在第5、6章有更詳細的介紹。

但也不只有 routing subsystem 會影響到封包的傳遞,像是整個 Linux Network Stack 中有5個 netfilter subsystem(netfilter hook)點可以設定。其中的第一個點就是 NF_INET_PRE_ROUTING,hooking 在查看 routing subsystem 之前。這些 hooking point 的 callback function 是由 NF_HOOK 來呼叫,並且這些點的結果(verdict)如果是 NF_ACCEPT 就會接著往下一關送,如果是 NF_DROP 則會丟棄該封包。Netfilter hooks callback 可以透過 nf_register_hook 或者 nf_register_hooks 來註冊。iptables 就是使用 netfilter subsystem 最著名的案例。第9章會更詳細的介紹 netfilter subsystem, netfilter hooks, along with the connection tracking layer of netfilter

除了 netfilter hooks 以外,如果封包有符合 IPsec policy 的設定,還會受到 IPsec subsystem 影響。IPsec 使用 ESP 以及 AH 協議,這個子系統是 VPN 解決方案的其中一種。第10章會透過 NAT 以及 IPsec NAT traversal solution 更加詳細的介紹 IPsec。

第2章會詳細介紹 Netlink protocol
第3章會詳細介紹 ICMP, ICMPv6
第4章會詳細介紹 IPv4 subsystem
第6章會詳細介紹 multicast routing
第7章會詳細介紹 IPv6 Neighbour Discovery Protocol, NDISC protocol, ARP
第8章會詳細介紹 IPv6 subsystem 以及 Multicast Listener Discovery protocol
第11章會詳細介紹 TCP, UDP, SCTP, and DCCP
第12章會詳細介紹 wireless subsystem
第13章會詳細介紹 InfiniBanc, Remote Direct Memory Access(RDMA)
第14章會詳細介紹 namespaces and network namespaces, Bluetooth subsystem, PCI subsystem

The Socket Buffer

sk_buff會貫穿整個 Network Stack,所以多少要了解一點。要注意的是在存取該結構的資料時,不建議直接存取成員。例如想要取得 L2 Header 時可以呼叫 skb_network_header

當收到封包時,network device driver 會呼叫 netdev_alloc_skb 建立新的 socket buffer,並且當要丟棄該封包時,呼叫 kfree_skb 或者 dev_kfree_skb

每個接收到的封包會由各自的 network layer protocol handler 處理,像是 IPv4 由 ip_rcv 處理,IPv6 由 ipv6_rcv 處理。ip_rcv 中主要執行 sanity check,如果一切沒問題,就會執行 NF_INET_PRE_ROUTING hooks,然後執行 ip_rcv_finish 來查看 routing subsystem。

IPv4 VS IPv6

除了可以表示的地址數量不同之外,作者還說明了兩者其他的差異

  • Flexibility: IPv4 header 可以自定義長度,但是 IPv6 header 長度是固定的 128 bits
  • ICMP: 在 IPv6 中,還需要負責 Neighbour Discovery(ND), Multicast Listener Discovery(MLD) 等等的功能

The Linux Kernel Networking Development Model

了解 Linux Kernel 之後可能會想提交 Patch。這個章節提出了下列幾點給有這個需求的讀者

  • How to apply a patch
    可以直接閱讀筆記怎麼給 Linux Kernel 發 patch?
  • How to read and interpret a patch
  • How to find which patches could cause a given problem
  • How to revert a patch
  • How to find which patches are relevant to some feature
  • How to adjust a project to an older kernel version (backporting)
  • How to adjust a project to a newer kernel version (upgrading)
  • How to clone a git tree
  • How to rebase a git tree - How to find out in which kernel version a specified git patch was applied