P4學習筆記(三)P4編程語言簡介
上圖展示了P4語言主要結構,下面簡單講解一下P4的基本語法
基本數據類型
header ethernet_h {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}
header vlan_tag_h {
bit<3> pri;
bit<1> cfi;
bit<12> vid;
bit<16> ether_type;
}
struct my_headers_ht {
ethernet_h ethernet;
vlan_tag_h[2] vlan_tag;
}
基本類型
- bit 無符號整型,也稱爲:位串,是具有n位的位字符串的類型,bit等價於bit<1>
- int 有符號整型,n>=2。
- varbit 變長位串
- bool: 布爾類型,true/false
派生類型
- header: 有序成員集合
- 位對齊
- 可以包含bit, int, varbit
- struct: 無序成員集合
- 沒有對齊限制
- 能夠包含所有基本類型以及派生類型
Typedef
typedef bit<48> EthernetAddress;
typedef bit<32> IPv4Address;
// Standard Ethernet header
header Ethernet_h {
EthernetAddress dstAddr;
EthernetAddress srcAddr;
bit<16> etherType;
}
- typedef 和c語言中一樣的意思,相當於取一個類型別名
聲明和初始化變量
bit<16> my_var;
bit<8> another_var=5
const bit<16> ETHERTYPE_IPV4 = 0x0800;
header ethernet_h {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}
header vlan_tag_h {
bit<3> pri;
bit<1> cfi;
bit<12> vid;
bit<16> ether_type;
}
ethernet_h eth;
vlan_tag_h vtag={3w2,0, 12w13, 16w0x8847}
元數據
元數據是用來攜帶數據和配置性和西,元數據的申明與包頭類似,但在實例化的時候有所不同,而且包頭和元數據在字段值的約束上存在一定的差別。元數據分爲兩種,一種是用來攜帶P4程序運行過程中產生的數據的用戶自定義元數據(User-Defined Metadata),如首部字段的運算結果等。另一種是固有元數據(Intrinsic Metadata),用於攜帶交換機自身的配置信息,如數據包進入交換機時的端口號等。
struct ingress_metadata_t{
}
metadate ingress_metadata_t ingress_metadata;
有8種固有元數據,這些元數據攜帶了數據包相關的狀態信息。
字段 | 描述 |
---|---|
ingress_port | 數據包的入端口,解析之前設置,只讀 |
packet_length | 數據包的字節數,當交換機在快速轉發模式下,該元數據不能在動作(action)中匹配或引用。只讀。 |
egress_spec | 在入端口流水線的匹配-動作過程之後設置,指定數據包出端口,可以是物理端口、邏輯端口或者多播組。 |
egress_instance | 用於區分複製後數據包實例的標識符。只讀。 |
instance_type | 數據包實例類型:正常(Normal)、入端口複製(ingress clone)、出端口複製(egress clone)、再循環(recirculated)。 |
parser_sratus | 解析器解析結果,0表示無錯誤,其實數字代表了對應的錯誤類型 |
parser_error_location | 指向P4程序錯誤發生處。 |
注意點:
- 包頭類型的長度需要字節對齊,即長度必須是8bit的整數倍。
- 包頭中字段長度可以是可變值,也可以是首部中其他字段值計算後的值。而元數據中的字段長度只能是定值。
- 只有包頭能夠實例化成數組,元數據則不行。
- 實例化時,首部中已定義名稱的字段的值會被初始化成程序中的指定值,如果首部中只定義字段名稱而未指定值,字段的值將會被初始化成0。
參考資料
1、https://p4.org/assets/P4_tutorial_01_basics.gslide.pdf