Try   HackMD

SDN P4 的那些事 - by Zephyr Huang

這裡會將學習 P4 過程記錄下來,如果內容有任何錯誤歡迎糾正

基礎環境問題

BMv2

BMv2 是一個軟體包,用於模擬和測試基於 P4 語言設計的可編程網路設備的行為。它提供了一個靈活的框架,允許用戶定義和測試各種網路數據平面行為。

監看當前 BMv2 中有哪些 Table Entries

  1. simple_switch_CLI thrift-port <port_number>
    • port_number: 通常從 9090 開始,或是可以從 P4RuntimeSwitch 的 init 中透過斷點查看指定的 switch 是哪個 port
  2. table_dump <table_name>
    • table_name: 此處填寫要查看的 table 名稱,對應的就是在 P4 中撰寫的 table
    • Ex: table_dump ipv4_lpm

simple_switch

simple_switch 是 BMv2 中的一個具體的數據平面實現。它是基於 P4 語言的簡單交換機模型,通常用於學術研究和開發環境中來測試和驗證 P4 程式。

V1Switch

基於 simple_switch 的 Data plane 資料處理 pipeline,決定一個封包要經過的流程以及每個流程會帶入的參數。

Pipeline 過程

以下會使用 V1Switch 作為代表

Parser

參數

  1. packet_in (型態固定)
    • 封包本人
  2. headers (型態自訂)
    • 可以自訂想要的 header 資料型態
  3. metadata (型態自訂)
    • 可以自訂想要的 metadata 型態
  4. standard_metadata_t (型態固定)
    • 系統定義型態,存放系統所需 metadata
  • 參數的順序是固定的無法自行更動,同時參數量也是固定的就這幾個欄位而已

會使用到的方法

  1. packet.extract(header)
    • 將封包根據指定的 header 類型提取 header
    • extract 會直接根據給定的 header 內部的變數提取指定的 bit 數量,不會管當前正常來說某個欄位應該是 x bit 但是我們卻指定 y bit,同時是根據 header 聲明變數時的順序進行提取的,所以在 header 中定義的順序也很重要。
  2. packet.lookahead<header>()
    • lookahead 可以偷看下一個部分的 header 內容
    • 需要在 <> 中說明要偷看的 header 類型,後面的 () 表示 lookahead 是一個 function 所以需要使用 () 執行。
    • 可以用在 transition select 當中,先偷看如果用某種 header 是否可以正常解析,如果可以在跳到指定的 state 當中使用 packet.extract(header) 完整解析。
    • 如果發生使用 lookahead 時指定的 header 無法正常解析會直接跳到 transition 的 default。
  3. extract v.s. lookahead
    • 上面有提到如果在進行 lookahead 時發生解析失敗會直接到 default 執行,那可能就會有疑問,為何不直接使用 extract 反正解析失敗也會到 default。
    • 當解析失敗時還需要解析其他 header 時就會需要使用 lookahead 因為即使解析失敗也不會導致當前的解析頭位置錯誤,如果使用 extract 則解析失敗時解析頭也已經移動到錯誤的位置了。

Ingress && Egress

參數

  1. headers (型態自訂)
  2. metadata (型態自訂)
  3. standard_metadata_t (型態固定)

會用到的方法

  1. table
    • 在 Data plane 中主要控制封包要怎麼傳送的方法
    • 主要內容 key, actions
      • key: 提供 Control plane 添加 match 的規則
      • actions: 提供 Control plane 添加 action 的規則
    • 其他內容
      • default_action: 在沒有指定 match 到時需要執行的 action 時默認執行的內容
      • entries: 可以在 Data plane 創建時直接添加 table entries 不依靠 control plane(多數情況下不會使用,只有在測試的時候使用)
    • table.apply.hit()
      • 如果有 match 到該 table 的某個 entry 會是 true 反之 false

V1Model

V1Model 是基於 P4 官方提供基於 BMv2 實現的 switch 包含兩種(simple_switch, simple_switch_grpc)。
同時提供最常使用的 Pipeline 框架 V1Switch。

一些細節的內容

  1. 到底是誰定義每個模組當中帶入的參數
    • 哪些是模組
      1. parser
      2. control
    • 定義模組有哪些參數以及順序的是交換機
  2. Pipeline 的順序是怎麼定義的
    • Ex: V1Switch 為什麼一定是以下的順序
      1. Parser
      2. VerifyChecksum
      3. Ingress
      4. Egress
      5. ComputeChecksum
      6. Deparser
    • Pipeline 的順序是根據最終的交換機決定,如果最終的交換機不是 P4 官方提供的 simple_switch 系列就會使用不同的 pipeline
  3. extern 相關的東西
    1. extern 的聲明方法
      ​​​​​​​​extern <module_name> {
      ​​​​​​​​    <function_name>(<function_parameters>)
      ​​​​​​​​}
      
      • 當硬體提供的函數是放在某個指定的模塊時使用
      • 只需將該模塊中會使用到的函數引入即可
      ​​​​​​​​extern <function_name>(<function_parameters>)
      
      • 當硬體提供的函數是全局類型的時候使用
    2. module_name
      • 模塊的名稱須根據實際的交換機決定
    3. function_name
      • 外部函數名稱須根據實際交換機決定
    4. function_parameters
      • 函數帶入的參數須根據實際交換機決定

Tofino

將封包從 CPU port 發送出去並且可以收到

  1. 在 onl 的機器上透過 ip a 檢查所有的網卡
    • 基本上會找到 enp4s0f0, enp4s0f1 這兩個網卡
    • 在 10.30.3.67 的機器上
      • enp4s0f0 對應上 port 66
      • enp4s0f1 對應上 port 64
  2. 將需要的網卡開啟
    • 將網卡啟用
      • ip link set dev enp4s0f0 up
    • 設定 ipv4 (不確定是否真的需要,但是如果開啟後他沒有自動給要記得設定,否則走 ipv4 的封包會收不到)
      • sudo ip addr add 192.168.1.100/24 dev eth0
    • 設定 ipv6
      • sudo ip -6 addr add 2001:db8::1/64 dev eth0
  3. 啟動 tofino
  4. 將對應到 server 的 port 開啟以及對應到 CPU port 開啟
    • port 64: 應該會是 33/0
    • port 66: 應該會是 33/2
    • 同時 CPU port 的也是 10G
  5. 透過 server 發送 ICMP 或是使用 scapy (但需要指定 mac address) 發送封包
  6. 確認在 onl 系統中有收到對應的封包

P4 內容

直接將所有的封包不進行任何處理只設定 egress port 是 CPU port 就可以