P4

成大資訊所

JAN 17, 2018

@NCKU-IMSLab

瞿旭民

@kevinbird61

  • Introduction: What is P4?

  • Build the environment for P4

  • How does it work ?

  • Run exercises to illustrate P4

    • Data Structure(Header)

    • Parser,Control,Table, Match/Action

    • Apply algorithm with P4

Outline

本篇主軸會以 p4lang/tutorial/SIGCOMM2017 這個 repo 來做介紹

並且以 P4_16 版本為主做討論!

What is P4 ?

P4 : Programming Protocol-Independent Packet Processors

Intro

  • 特色
    • Target independent(目標獨立性)
    • Protocol independence(協定獨立性)
    • Reconfigurability(動態配置)
  • 與現有 SDN 比較
  • 現在 P4 的運作進度

Target Independence

  • 不限部署的硬體裝置
  • 由 P4 Programmer 編寫 P4 Program,交由 p4c (P4 compiler) 來做編譯,產生適合不同硬體裝置可讀的檔案 ( ex: Tofino -> binary, bmv2 -> JSON, ... )
  • 最後由 target switch model 來讀取程式作部署 ( e.g. 通常稱為 P4 Switch,正式名稱為 P4 Target )

 

Protocol Indepenece

  • P4 特色為無視現有的 protocol 格式 ( i.e. IP, Ethernet, MPLS, ... )
  • 直接解析來源封包做使用 
  • 依據 P4 Programmer 編寫的 *.p4 來決定如何解析、以及如何利用 (比對格式、處理資料 ... )
  • 全部取決於 P4 程式 !

 

Reconfigurability

  • 在部署 P4 Program 後,能夠在 Runtime 改變現行程式處理 packet 的方式 !
    • 動態新增、刪減規則
  • 以往能夠有這種功能都需要使用 general-purpose 的 CPU 加上 network processor 來完成,並無法使用現有固定的 ASICs 
  • 所以 P4 實際運行上,會需要晶片廠商的配合 (Ex: Barefoot 所製的 Tofino 晶片便是 )

Problem

  • SDN 推出到現在,由於各大廠有各自的硬體實作,並仍然各自宣稱自己的 switch 較優; 因此達到真正的 SDN 還有一段距離
  • OpenFlow Limitations:
    • 受限制的介面(影響擴展性、特性)
    • 定義不明確的介面,使得匹配正確,但結果不正確的情況
    • 一個相同的行為不同的硬體種類上結果會不一致
  • 這些限制也造成這些亂象
    • 新功能需要額外改動(解決受限制介面的問題)
    • 對於特殊行為做出規範
    • 自定義的 OpenFlow
    • 第3方裝置無法加入網路

Solution

  • 因此 P4 則為了解決這個問題而誕生,背負著 SDN 原本該完成的使命 - "deliver highly-configurable pipelines" 而前進 
  • 由 Barefoot 推出標榜 Target Independent 的晶片 - Tofino,目前由 Google, Amazon, Facebook, MicroSoft 等等公司支援、而非以往的硬體設備商 Cisco, Nokia 等等
  • 希望 SDN switch 俱備:
    • 對 Program, configure, manage 都很容易
    • 對於新的硬體可以快速且簡單的做部署、使用
    • 快速的推出新的功能

Current  

  • 實際使用:
    • Barefoot/Tofino: 使用於 Data Center 
    • 造價昂貴,但速度快、且為可編程
    • Barefoot 提供 IDE: Capilano,及相關的 API / SDK 做 Tofino Switch 上的開發、偵錯等等,加速 P4 開發
    • 並且開發 Switch 上頭的 Agent,與 Controller 做溝通
  • NetFPGA + P4 
    • 價格相對低 ( 50000~70000 NTD )
  • VMWare : XDP + P4 
  • 最便宜的 - Software switch 
    • 也就是今天要帶來的展示

Other

  • Barefoot/U.S.C(University of Southern California)/Yale University/Facebook
    • SilkRoad: Stateful Layer-4 Load Balancing in Switching ASICs
  • 北京清華大學
    • ClickP4: 為模組化編程架構,可以大大減輕 P4 程序的複雜性,提供靈活的程序編排及更加可靠的執行策略
    • CacheP4: 用於 P4 的緩存機制,作用方式首先將 P4 程序的 match-action table 添加到 cache 當中,允許 control plane 在運行時動態更新緩存內容;可以將延遲降低 20%,轉發效率提高超過 60%
    • NS4: P4 驅動網路模擬器,能夠摹擬支持 P4 的設備以及網路系統,具有好的兼容性和可擴展性

Capilano (補充)

Build enviroment

P4 Architecture

Overview

這段會講述如何於實體機器上面安裝 P4 的開發環境!

有詳細的連結置於 dropbox paper 當中,紀錄一些當時安裝的方式以及遇到的問題!

 

我目前安裝且成功過的系統:

  • ubuntu 16.04
  • lubuntu 17.10 

p4c

  • Build from source code
  • P4 Compiler,負責處理 logical pipeline 對應到 physical pipeline ( hardware specified, e.g. switch ); 使得 P4 Programmer 只需要關注要加入的功能,而不需擔心每台硬體架構上的異質性

*.p4

p4c

*.json

target

format

bmv2

  • Build from source code
  • 為 P4 定義的 behavior model,可以理解為 P4 software switch
  • bmv2 可代表多種 switch 架構,可提供給 chip vendor/networking company 來做為生產 switch 元件時的依據

*.json

bmv2

switch

feed

PI

  • Build from source code
  • Runtime control,也就是 Reconfigurability 的部分
  • 運作方式( 直接操作 ) :

Running P4 program ( Process )

runtime_CLI.py

Rules

Read

Insert

有了三項模組

就可以開始實驗囉!

How does it work ?

一般運行

SUME

1G-CML

軟體摹擬

  • 為接下來範例操作所使用的環境
  • Switch 的部分由 bmv2 提供的 simple_switch 作執行
  • Controller 的部分由 PI 提供的 runtime_CLI.py 以及教學內部的 txt 檔案 (作為 rules 依據) 做執行
  • 最後是模擬總體網路架構,由 mininet 這套軟體負責
    • 控制網路連結的 bandwidth、host 的數量、以及 hosts/switches 之間的連結
    • 由於 mininet 提供完整的 python API 做使用,所以教學內部是透過 python 來橫貫整個流程 ( 接下來會做詳細說明 )

Network Interface

由於使用的是軟體摹擬的網路介面(由 mininet API 來達到網路介面的實作)


透過 mininet 來建立 network nameless namespace,建立虛擬化的獨立網卡介面, routing table, resolver 設定, 防火牆設定等等

利用 bmv2 提供的 soft switch 建立連接的 interface 後即可讓這些 host 來互相連接!


使用上非常方便,整體透過 mininet 建立好環境後,直接開啟 mn CLI 就可以進入摹擬環境當中,並且透過 xterm 開啟每個 host 各自虛擬化出來的網路介面做使用

Runtime Control

P4 提供的 Control 能夠動態對 match-action table 做新增、修改等等的動作,而溝通方式則可以透過這幾項工具來達成:

  • Apache Thrift
  • gRPC/google protocol buffer(protobuf)

 

而目前編譯成功使用的是 Thrift,目前以 thrift 使用(P4_14 版本時以 Thrift 為主,後來演進到 P4_16 後主要以 gPRC 為主)

Run exercise

mininet + software switch

Structure

tutorial/

| - vm/

|     - * /  => using vagrantfile (Build from virtual machine)

| - util/

|     - * /  => contain essential python script (mininet)

| - exercise/

|     - * /   => contain all the exercises(等等介紹的部份會在這邊!)

Tutorial

  • 由於 python 對 Mininet 相容性高,教學利用 shell script 搭配 python 腳本來完成搭建 P4 實驗環境所需
    • sh 來打包程式、p4c 編譯 P4 程式
    • 呼叫提供的 python + mininet 作為骨幹 ( 呼叫 simple_switch、控制網路環境參數 ... )
    • 透過讀取規則文件(*.txt)來加入起始規則 ( 會針對每種不同的 case 做調整,相當佛心! )
    • 最後便是加入使用者的 P4 程式做運行 !
  • 另外也可透過 vagrant 來啟動虛擬機來做運行 ( 本篇先不討論)
  • 本篇挑選 tutorial 底下的 SIGCOMM2017 做說明
  • 練習如何用 P4 實作來達到"原本由 switch 設備商所提供的功能" ( e.g. 原本硬體提供的 : ECN, Load-balancing ... 等機制 )
  • 介紹每個機制如何運行後,在解說程式碼、語法介紹;以及 table 的 match-action 機制 + parser 
  • 先來看看如何運行吧 !

Workflow

Step 1.

透過 p4c 來 compile 檔案:

p4c-bm2-ss --p4v 16 "basic.p4" -o "output.p4.json"

選擇 P4_16 版本做編譯

從 P4 開發者所編寫的 P4 程式轉換成 json 格式

產生為 simple switch 讀取格式(json)

Step 2.

利用 mininet 來搭建網路環境:

 

透過 mininet API 來建立 host, switch 以及之間的連線;

連線可依據要實驗的環境而做調整 (bandwidth、使用的 CPU 等等)

 

* Scenario : basic routing

Step 3.

透過 bmv2 提供的 simple_switch 來執行!

* Scenario : source routing

simple_switch -i 1@s1-eth1 -i 2@s1-eth2 -i 3@s1-eth3 
    --pcap --thrift-port 9090 
    --nanolog ipc:///tmp/bm-0-log.ipc 
    --device-id 0 source_routing.p4.json 
    --log-console

設定 switch 上的網路介面

controller 溝通使用: thrift

(也可使用 P4Runtime)

以 pcap 格式儲存封包

前面 p4c 產生的檔案!

(範例使用的是 ss )

Step 4.

提供 CLI 工具來做 table 的新增/刪除/修改!

 

而範例來看,置放在資料夾底下的幾個 sX-commands.txt 則透過 p4app.json 來讓 python 讀取後作為 topo 產生依據

* Scenario : basic routing

table name

table_set_default ipv4_lpm drop
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 1
table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:02:02:00 2
table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:03:03:00 3

action name

command

起始規則:

像是範例中一開始預設的 scenario

Diagram

  • 使用者只需要修改 .p4 檔案即可,其餘的部分都是由 tutorial 提供
  • 在 mininet_CLI 中透過 xterm 開啟模擬的 host machine: 
    • 開啟後的 host X 的 namespace 是獨立的! (與原本的介面卡做區別)
    • main process 中 fork 出來的 process,所以操作同一塊 workspace (只有在記憶體 & 介面使用上是各自獨立的)
    • 而這個動作主要是利用多個 host 來模擬使用者及伺服器的運作情形;模擬使用者的執行 send.py,而模擬伺服器的則是開啟 receive.py 做接收
    • 由於實驗的關係,這兩隻程式都會印出所送出的封包內容,可以直接從 IO 上看到結果!

GO!

  • Exercise 1 - Basic forwarding
  • Exercise 2 - Source routing
  • Exercise 3 - ECN (Eplicit Congestion Notification)
  • Exercise 4 - MRI ( Multi-Hop Route Inspection )

以下選用這幾個範例做說明:

並且使用這幾個範例來帶出 P4 的一些特性!

Exercise 1

basic forwarding !

Introduction

Scenario

Overview

由基礎範例,我們先來介紹幾項 P4 基本性質吧!

資料結構:

  • Header
  • Metadata
  • Extern

PSA 主架構:

  • Package 概念
  • Parser
  • Control block(Ingress, Egress)
  • Deparser

Overview

從這個範例中,我們先來看到結構吧!

P4 中定義有 control、parser、package 等等

我們先從 package 開始吧!

在 Example 1 中先主要介紹 P4 的基礎架構! 並再後續範例中再來針對 P4 的一些功能做闡述!

Package

Package: 

為最主要的結構,其內定義了像是 parser、ingress/egress 等等操作,以及像是 checksum() 的呼叫

程式會依據他定義的項目去做運行!而在範例中,V1Switch 的定義於 v1model.p4 這個 include file 裡頭(於 p4c 編譯時所包含再內)

Parser

Parser: 

為第1個處理外部封包的地方;下方展示在這個範例中 Parser 的定義,可以由圖像化的方式做理解!

 

Parser (conti.)

extern packet_in {
    void  extract<T>(out T  hdr);
    void  extract<T>(out T  variableSizeHeader,in bit<32>  variableFieldSizeInBits);
    T  lookahead<T>();
    void  advance(in bit<32>  sizeInBits);
    bit<32>  length();
}

在 parser 之中,我們可以利用現有的 state 來做封包上資料的擷取;

來看看 packet_in 吧!

是為 packet_in 內定義的 method,主要負責把 source flow 當中的 packet 資料來 map 到 hdr 這個 output variable 裏面,長度由 hdr 的 type "T" 來做決定!

Parser (conti.)

parameter
    : optAnnotations direction typedef name
    ;

...

direction
    : IN
    | OUT
    | INOUT
    | /* empty */
    ;

in, out, inout:

這個是 P4 內定義的 direction keyword,主要表示這個資料流的方向,以及可寫 or 唯讀的作用存在 !

讓我們來看看他的 grammar :

 

其中 optAnnotations 為輔助使用(像是 Java,C# 中 annotation 用途,不改文法情況下增加功能)

而 direction 便是方向、 typedef  則是該 variable 的型態、最後才是變數名稱 name

 

(* annotation 可參考 spec 第 17 章 ! )

Parser (conti.)

state start {
    transition parse_ethernet;
}

state parse_ethernet {
    packet.extract(hdr.ethernet);
    transition select(hdr.ethernet.etherType) {
        TYPE_IPV4: parse_ipv4;
        default: accept;
    }
}

state parse_ipv4 {
    packet.extract(hdr.ipv4);
    transition accept;
}

state:

 

* 在 state 中做 extract 到 hdr 動作! 以 state machine 方式運作

(p4c 有提供 graphviz 輸出!)

何謂 Extern?

由 architecture 提供的 object ,讓 P4 程式能夠使用;

像是一般的物件導向語言中定義的 class 一樣,能夠提供封裝來實作一個物件的功能(像是屬性、method 等等)

 

像是剛剛用的 packet_in,以及實作的 checksum:

extern Checksum16 {
    Checksum16();              // constructor
    void clear();              // prepare unit for computation
    void update<T>(in T data); // add data to checksum
    void remove<T>(in T data); // remove data from existing checksum
    bit<16> get(); // get the checksum for the data added since last clear
}

注意! extern 只要描述這個物件的行為,並無實作!

(對於 extern 內的 method,是由 P4 內部定義所實作 e.g.  由 target device 提供)

Metadata

在 P4 中,Metadata 用於讓 P4 在 pipeline 中不同 stage 處理之間可以傳遞訊息與資料

 

和 packet_in 等等相似,內部也可以存放像是進入的 port、傳輸目的、用於 packet 標記的 timestamp 等等

 

而這些 metadata 並不涉及改變 packet 解析後的表現!

* 於 ecn.p4 擷取,可看到使用 standard_metadata 做 queue length 標記使用

Checksum

來看看範例其中一個呼叫 extern object 的使用:

control MyComputeChecksum(
    inout headers hdr,
    inout metadata meta) 
    {
     apply {
	update_checksum(
	    hdr.ipv4.isValid(),
            { hdr.ipv4.version,
	      hdr.ipv4.ihl,
              hdr.ipv4.diffserv,
              hdr.ipv4.totalLen,
              hdr.ipv4.identification,
              hdr.ipv4.flags,
              hdr.ipv4.fragOffset,
              hdr.ipv4.ttl,
              hdr.ipv4.protocol,
              hdr.ipv4.srcAddr,
              hdr.ipv4.dstAddr },
            hdr.ipv4.hdrChecksum,
            HashAlgorithm.csum16
        );
    }
}

basic.p4

extern void update_checksum<T, O>(
    in bool condition,

    in T data,

    inout O checksum,

    HashAlgorithm algo

);

v1model.p4

用以檢查 payload 的 checksum

若發現錯誤,則會透過 standard_metadata 做 checksum_error bit 的設定,表示錯誤發生

Control(egress, ingress)

在 P4 當中,PSA(Portable Switch Architecture) 架構如下:

剛才提到的 Parser

接續於 Parser 後,使用 Parser 解析 Header 資料做處理;並決定 packet 的出口、也決定會放到哪一個 queue 中

Control

可以分成幾個部份做說明: table, key, action

為 table 中 match 的依據!後面接的是比對的 policy( P4 Programmer 無法自行定義 );在 core.p4 中定義的基本款三種: exact、ternary、以及 lpm

鍵值比對後,依據結果來選擇 actions 做執行!

以上述例子來看,比對成功後即執行 ipv4_forward 這個對應的 action

Control (conti.)

在進入 action 前,先來剖析了解 match-action 機制吧!

Control (conti.)

Action:

基本上可以理解為 function,分兩種: Directional 及 Directionless;

並且 action 的 parameter 的來源有兩種:只透過 control plane 做指定或是透過其他 calling action 來 assign (行為像是帶有 "in" direction 的變數)

Action Type From
Directional Data plane
Directionless Control plane

Control (conti.)

match policy:

key 值匹配的決定方式,由 P4 提供,一般 programmer 無法自行定義與新增; 透過 match_kind 的關鍵字做定義

大多由 core.p4、v1model.p4 所提供!

Match type 說明
exact key 值需完全匹配
ternary 透過一組 mask 來做匹配
lpm longest prefix match

Control (conti.)

如何執行一個定義好的 table?

以範例中 control block 做解釋

control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {
    ... (action goes here)
    
    apply {
        if (hdr.ipv4.isValid()) {
            ipv4_lpm.apply();
        }
    }
}

以傳入的 hdr 做 condition 判斷

如果符合規定,就可以呼叫 <table_name>.apply() 來啟動剛剛定義過的 table 機制 (當然 action 還可以再呼叫另一個自定義的 action,後面再詳細介紹)

Control (conti.)

運行範例:

...
apply {
    if (hdr.ipv4.isValid()) {
        ipv4_lpm.apply();
    }
}

匹配 ipv4_forward

table ipv4_lpm {
    key = {
        hdr.ipv4.dstAddr: lpm;
    }
    actions = {
        ipv4_forward;
        drop;
        NoAction;
    }
    size = 1024;
    default_action = NoAction();
}

呼叫 table :  ipv4_lpm

action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
    standard_metadata.egress_spec = port;
    hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
    hdr.ethernet.dstAddr = dstAddr;
    hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}

進入 action 內,即可對封包內部做改動!

Deparser

基本上到這邊,已經差不多完成了!

來到最後一個部份:Deparser

Deparser 會依據 control block 給予的設定,來對 queue 內的 packet 做複製、轉發、丟棄等等動作(可參考圖中的連線)

Deparser

如何達到發送?

透過 emit() method !

control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}

於 packet_out 型態中定義了 emit 這個 method

透過呼叫 emit 來把 in 的 hdr 資料倒進 packet_out 的 packet 當中,告知其可以準備做下一步

Deparser( conti. )

讓我們來看看 emit() 做了什麼!

packet_out {

    byte[] data;
    unsigned lengthInBits;

    void initializeForWriting() {
        this.data.clear();
        this.lengthInBits = 0;
    }

    void emit<T>(T data) {
        if (isHeader(T))
            if(data.valid$) {
                this.data.append(data);
                this.lengthInBits += data.lengthInBits;
            }
        else if (isHeaderStack(T))
            for (e : data)
                 emit(e);
        else if (isHeaderUnion(T) || isStruct(T))
            for (f : data.fields$)
                 emit(e.f)
        // Other cases for T are illegal
    }
}

依據給定的 header 來做 append data 的動作!

可以看到當 header 合法時( e.g. header stack, header union 或甚至是由這些型態 recursively 組合成的結構 ),會去抓取其長度後加入到自己目前 packet_out 的 data 的 buffer 內

* 參考 spec Chapter 14

DEMO!

這麼一來

我們便完成一個擁有基本 forwarding 功能的

switch 囉! 剩餘的 send.py , receive.py 由 DEMO 中做介紹

 

[1] p4-tutorial

[2] P4-Play

Exercise 2

source routing !

Advanced Data Structure

Scenario

1

2

3

3

2

1

1

2

3

黃色: switch port 標示

紅色: 標示流向

輸入序列: 

2,3,2,2,1

Overview

由於在 Example 1 大多已經介紹過主要架構,所以在這部分將主軸放在 "如何操作" 上

在第一個基本 forwarding 中,我們只有簡單的設定,將所有封包都往 h2 送 ( 在 send.py 當中 )

而現在則需要在多個 switch 上面做特定輸入來做 forwarding; 接下來可以透過 P4 來實作這部分的功能 !

理解 P4 如何運作

操作 P4

Main Part

  • 修改 P4 header 資料結構,以適應儲存每個輸入的節點內容 ( 一開始輸入的多個序列 -> 對應一開始那張圖 )

 

  • 修改 Parser state 來做額外的這些處理

 

  • 新增 table action 來做額外的處理

Data Structure

修改 Data Structure !

額外新增自定義的型態 - srcRoute_t 來作為每個要 hop 的 port;

struct headers {
    ethernet_t              ethernet;
    srcRoute_t[MAX_HOPS]    srcRoutes;
    ipv4_t                  ipv4;
}
header srcRoute_t {
    bit<1>    bos;
    bit<15>   port;
}

bos: bottom of stack,表示該 element 為 stack 中最後一筆

port: 紀錄目前這個 hop 要走哪一個 switch port 出去

Why this?

因為 P4 內無法針對這個變數取 element 長度,所以 bos 的欄位作取代,用以標記這個是最後一個,parse 完之後就可以進到下一個 parsing process - ipv4

* 在 P4 中沒有 loop 的功能!只能夠過上述的 iterative 方式來達到相同功能!

Parser

透過 p4c-graphs 來生成 diagram (由上而下,從 start 開始)

 

可以看到多了一個 state: 

parse_srcRouting,利用剛才新增的 bos 來判斷是否為最後一個 hop,並且進入 parse_ipv4 

Parser(conti.)

這邊邏輯上是去判斷目前進入的 srcRoutes 中正在處理的 element 的 bos 是否為 1;若為 1,則表示該 element 為 stack 中最後一個;便可以進入下一個 state

 

若不是,則呼叫自己來取出要跳往的下一個位置!並儲存在 要輸出的 hdr 內!

透過提供的 next, last 的方式做寫入!

state parse_srcRouting {
    packet.extract(hdr.srcRoutes.next);
    transition select(hdr.srcRoutes.last.bos){
        1       : parse_ipv4;
        default : parse_srcRouting;
    }
}

Parser( conti. )

這邊介紹一下在 parse_srcRouting 中使用到的特殊方法 - 

由 headers 所提供的 next, last

packet_in

目前讀取位置

size

由 extract 內的 variable 決定 size 大小

copy

(out) hdr

size

目前讀取位置

next, last

next: 

hdr (headers) 實作的 method,提取下一個 element,以提供寫入的位址;若第一次 call,則提取第一個 element

 

last: 

從目前 hdr 中提取剛才用 next 存入的那個 element 之位置

(out) hdr

last

值得注意的是,由各自 object

來保存讀寫位置( e.g. buffer index )!

next

到這邊的操作為止,我們成功的在 parser 中把資料從 packet 中擷取到我們訂定的 data structure 當中 ( e.g. hdr);

 

現在我們可以進到 "依據擷取資訊來決定 packet 的行為" 這一步驟,那麼就需要修改到 table 裡頭的內容來達成!

Ingress

這裡便接收來自 parser 處理過後的 hdr,來做進一步的操作!

這裡定義了 switch 的動作:

當發現 bos == 1 時,該 switch 便會執行 srcRoute_finish(),並且把狀態設成 TYPE_IPV4,讓他能夠在該 switch 時被接收;

 

若非 1,表示還需要繼續 routing,便會 pop 出目前的 srcRoute 物件,並傳到該物件指定的 port (e.g. 下一個 switch)

Deparser

最後在 deparser 內呼叫 packet_out 的 emit method,來把這3個 header 指定做 transmit 的設定,使其對應的 payload 能夠在可傳送時 copy 到 deparser 的 output buffer 當中

DEMO

看看是否於 host 2 能夠接收到 routing 多次後的封包

Exercise 3

ECN !

(Explicit Congestion Notification)

Monitoring & Debugging

Scenario

一般流量

大流量 (iperf)

Congestion!!

利用 iperf 這項工具,來達到瞬間大量封包的功能!

Overview

有了基本操作知識後,我們可以更上一層樓,到達施做演算法的部份!

ECN (Explicit Congestion Notification):

對於擁擠的網路控制的端對端通知,從而避免丟包;

傳統 TCP/IP 網路通過丟棄封包來表明 channel 阻塞;在無ECN時,擁塞指示回傳是通過檢測分組遺失來間接實現

 

而 ECN 成功協商的狀況下, ECN 感知路由器可以在 IP 頭中設定一個標記來代替丟棄封包! ( 而不是 drop! ) → 以標示 阻塞即將發生” ,回應給傳送端 !

TOS

diffserv ( 6 bits )

ecn ( 2 bits )

tos ( 8 bits ) =

+

ECN 機制

ECN 為一個 2 bits 的資料內容來標示目前網路情況:

ECN  意義
00 表示不支援 ECN 傳輸
10 支持 ECN
01 支持 ECN
11 發生擁塞情況

所以現在我們得運用剛才的學習內容,來做到修改 ECN 項目,判斷網路是否壅塞後,把結果塞進要回去的封包當中!

What we need to do?

  • 修改資料結構,加入 ECN field

 

  • 在 parser 中取出需要的欄位

 

  • 在 Egress 中利用 parser 中取出的資料做 ECN 比對,並且依據狀況調整要輸出的 header 內容

DEMO

看看是否在 h2 看到 ecn 的改變!

Exercise 4

MRI !

(Multi-Hop Route Inspection)

Monitoring & Debugging

Scenario

一般流量

大流量 (iperf)

Congestion!!

和 ECN 相似,不過此時著重在封包修改;我們可以在 h22 看到修改的結果,e.g. 壅塞在 s1 上的 queue 長度

DEMO!

Appendix

  1. p4c compiler 相關
  2. 測試(1):不使用 python scripts 的支援來使用 P4 (e.g. simple_switch + P4 program + simple_switch_CLI)
  3. 測試(2):使用 mininet + P4 class 來快速建立相同實驗模型

Appendix

p4c compiler

p4c 的專案編譯安裝完成後,提供了三個執行檔方式來針對不同對象產生目標檔,分別是:

  • p4c-bm2-ss
    • 最主要用來產生 json 的檔案格式以供 simple switch 做讀取,也是人工可閱讀的格式
  • p4c-ebpf
    • 產生 C 程式提供給 ebpf 做編譯使用 ( 規格會跟 p4c-bm2-ss 不同! )
  • p4c-graphs
    • 可以依據使用者目前寫得程式做不同結構區分( e.g. Parser, Control, Deparser, 等等),並從 *.p4 中產生數個 dot 檔案;並可透過 graphviz 來產生 diagram ! 

Run without python 

  • 建立 network namespace (hx-eth0)
  • veth pair 建立 switch 的 network interface (sx-eth0)
  • 利用 simple_switch 來接取這幾個接口
  • simple_switch_CLI 來加入規則 

參考專案目錄: P4_Play

Next...

Todo Lists

  • 嘗試去除 mininet 之輔助,獨立運行的測試
  • 進而能夠 porting 到實際機器上做運行 (優先選擇 NetFPGA)
    • 學習於真實情況下如何使用 P4 
  • 閱讀 Heavy-Hitter detection,構思如何運用 P4 來解決現有問題 !
    • 該篇論文便是利用 P4 建構的 switch 於 data center、ISC backbone 中來做到 Heavy-Hitter detection 
    • 於 P4 中實作作者挑選並改良的演算法

Reference

  • Nameless namespace:
    • http://www.haifux.org/lectures/299/netLec7.pdf
    • http://man7.org/linux/man-pages/man2/unshare.2.html

Reference

找到 nameless namespace!

Reference

Made with Slides.com