P4 Compiler 系列 – 自創 Architecture package

5 月 11, 2018

這邊先回顧一下編譯一個 P4-16 程式時所需要的大略步驟:

已目前普遍 bmv2 simple_switch 為例,在主程式最前方會先引用 core.p4 以及 v1model.p4 這兩個檔案

core.p4 包含了一些 P4 常用的核心功能,舉例來說他定義了 Parser & Deparser 參數的格式(packet_in, packet_out),或是常用的 Error 類型等等。

基本上,並沒硬性規定一定要引用 core.p4,例如目標並不支援可編程的 Parser/Deparser,則可以不用引用。

接下來要來開始定義自訂的 arch package。

由於使教學用,所以並不打算要將他訂的太具有彈性,這邊假設

  • 該架構並不包含可編程的 Parser/Deparser
  • 該架構僅包含一個 ingress pipeline
  • 可編程的 Pipeline 中僅包含 3 個 Table 可以編程,開發者主要需要定義 Table 的 Match、Action 以及大小
  • 不支援 Checksum 等等額外功能
  • 不支援自定義 Metadata

此架構看起來如下:

撰寫自定義的 arch package 一件事情就是,如果是 Fixed pipeline 的話,就需要預先寫好可以使用的 Header,這邊就假設他可以支援 Ethernet + IPv4,並且定義一個在 Pipeline 中可以使用的 Metadata 像是 Ingress port、Egress port 等。

header ethernet_t {
    bit<48> dst_addr;
    bit<48> src_addr;
    bit<16> ether_type;
}

header ipv4_t {
    bit<4>  version;
    bit<4>  ihl;
    bit<6>  dscp;
    bit<2>  ecn;
    bit<16> len;
    bit<16> identification;
    bit<3>  flags;
    bit<13> frag_offset;
    bit<8>  ttl;
    bit<8>  protocol;
    bit<16> hdr_checksum;
    bit<32> src_addr;
    bit<32> dst_addr;
}

struct headers_t {
    ethernet_t eth;
    ipv4_t ipv4;
}

@metadata
struct arch_metadata_t {
    bit<9>  ingress_port;
    bit<9>  egress_port;
}

可以在 Struct 前加上 @metadata 這一個 annotation 讓 Compiler 可以更容易知道他是一個 metadata,但如果 Compiler 了解的話,也可以不加。

接下來可以定義一下在裝置裡面支援,但 P4 預設不支援的功能(extern),例如定義 mark_to_drop() 或是 packet_in() 這樣的 function。

extern void mark_to_drop();
extern void packet_in();
action NoAction() {
}

若沒有要引用 core.p4 的話,我們還需要去訂有哪些可以 match 的規則,例如:

match_kind {
    exact,
    ternary
}

接著是定義我們架構中的 control block 應該長怎樣,在前方加上 @pipeline 讓 Compiler 知道我們之後會用這樣的格式來定義一個 control block:

@pipeline
control Ingress(inout headers_t hdr, inout arch_metadata_t arch_metadata);

可以從上面程式看到說這一個 pipeline 需要使用固定的 header 以及 metadata。

最後就是定義主程式需要的 package:

package FixedThreeTables(Ingress ig);

這邊將 architecture 名稱定為 FixedThreeTables,我們可以寫出如下的 P4 程式:

#include <FixedThreeTables.h>

control ingress(inout headers_t hdr, inout arch_metadata_t arch_metadata) {
    action drop() {
        mark_to_drop();
    }

    action punt_to_ctrl() {
        packet_in();
    }

    action set_output(bit<9> eport) {
        arch_metadata.egress_port = eport;
    }

    action set_output_and_dst_mac(bit<9> eport, bit<48> dmac) {
        set_output(eport);
        hdr.eth.dst_addr = dmac;
    }

    table filtering {
        key = {
            hdr.eth.ether_type: exact;
        }
        actions = {
            punt_to_ctrl;
            NoAction;
            drop;
        }
        deafult_action = drop;
    }

    table tmac {
        key = {
            hdr.eth.dst_addr: exact;
        }
        actions = {
            NoAction;
            drop;
        }
        deafult_action = drop;
    }

    table routing {
        key = {
            hdr.ipv4.dst_addr: exact;
        }
        actions = {
            set_output_and_dst_mac;
            drop;
            NoAction;
        }
        deafult_action = drop;
    }

    apply{
      filtering.apply();
      tmac.apply();
      routing.apply();
    }
}

FixedThreeTables(ingress()) main;

下一章節會說明要如何準備一個新的 Backend Compiler 到 p4c 中並且編譯。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料