P4語法(1)基礎數據類型和Header


文章學習自:P4語言編程詳解
由於原文有一點的年份,所以也繼續閱讀了相關的最新規范。
P4語言規范


基礎數據類型

布爾型(bool)

運算符 描述
and 雙目運算符,結果為布爾型
or 雙目運算符,結果為布爾型
not 單目運算符,結果為布爾型
==,!= 相等或不等,結果為布爾型

無符號整型(bit)

又稱之為位串(bit-string),對位串進行數學運算的時候,位串長度必須是8的整數倍。

運算符 描述
==,!= 是否相等或不等,運算結果為布爾型。
<,>,<=,>= 無符號數比較,操作數的長度(W)要求相同,運算結果為布爾型。
&,|,^ 按位運算符(分別是與,或和異或),操作數的長度(W)要求相同,運算結果為無符號整型。
運算結果為操作數的補碼。
<<,>> 左移運算符操作數為無符號整型,右移運算符操作數必須是無符號數或非負整數。此運算符為邏輯位移。
+(單目) 單目加運算,效果同no-op。(無意義)
-(單目) 單目減運算,計算結果為2W減去操作數,W為操作數長度。
+(雙目) 二目加運算,操作數的長度(W)要求相同。計算結果為操作數的算術和,且運算結果長度也必須為W,超過則截斷。
-(雙目) 二目減運算,操作數的長度(W)要求相同。計算結果為操作數的算術差。
* 無符號乘法運算,操作數的長度(W)要求相同,計算結果為無符號數且長度與操作數相等。

有符號整數型(int(W))

大致與無符號整數相同

運算符 描述
-(單目) 單目減運算,運算結果偉有符號整型,長度和操作數相等
+(雙目) 二目加運算,操作數數據類型必須相同,運算結果也為同類型。
-(雙目) 二目減運算,操作數數據類型必須相同,運算結果也為同類型。
* 有符號乘法運算,操作數的長度(W)要求相同,計算結果為有符號數且長度與操作數相等。

變長位串(varbit)

該數據類型,不支持算術、比較和位運算,也不支持類型轉換,該數據類型在定義時會指定一個靜態的最大寬度值,解析器會提取變長位串數據並設置一個值作為長度。

無限精度整型(int)

運算符 描述
==,!= 是否相等或不等,運算結果為布爾型。
<,>,<=,>= 有符號數比較,運算結果為布爾型。
<<,>> 右移運算符操作數必須為正整數;左移運算結果和操作數相同。a<<b等價於ax2b,a>>b等價於a/2b。
+(單目) 單目加運算,效果同no-op。(無意義)
-(單目) 單目減運算,運算結果為整型,且該運算不會導致溢出。
+(雙目) 二目加運算,操作數類型都必須是整型,運算結果為整型,且該運算不會導致溢出。
-(雙目) 二目減運算,操作數類型都必須是整型,計算結果為整型,且該運算不會導致溢出。
* 無符號乘法運算,操作數必須都是整形,計算結果為整形,該運算不會導致溢出。
/,% 二目有符號除法和取模運算,操作數必須是正整數,運算結果為正整數。

數據類型轉換

可以看出,上述的很多運算都是建立在相同數據類型的前提下,但是對於某些數據類型是不能相互轉換的,p4也提供了合法的數據類型轉換。

from to 描述
bit<1> bool 0代表false,1代表true(中括號里的1代表的是字節數,不是0和1,下同)
bool bit<1> 同上
bit<w> int<w> 保留所有比特位不變
int<w> bit<w> 同上
bit<w> bit<w> 當w>w1時,保留低位w1位長度的數據,小於時新增位補0
int<w> int<w> 當W>W1時,保留低位W1長度的數字,當W<W1時新增位補符號位.(補符號位?)
int bit<w> 保留低位W位長度數據,溢出需要發出警告並轉化為負數。
int intt<w> 保留低位W位長度數據,溢出需要發出警告。

這些屬於顯式類型轉換,p4中同樣存在隱式類型轉換,在運算中會進行強制轉換,這個和大部分語言類似。也容易發生溢出錯誤。


基礎語言組件

之前有學到過,p4程序主要由五個組建構成:header,parser,table,action,和controller

這個類似於固定屬性一樣的東西,有多個成員字段,Header分為兩種,一種是包頭(Packet Header),一種是元數據(Metadata)。

包頭

ipv4例子

header ipv4_t{
    fields{
        version:4;
        ihl:4;
        diffserv:8;
        totallen:16;
        identification:16;
        flags:3;
        fragoffset:13;
        ttl:8;
        protocol:8;
        hdrchecksum:16;
        srcaddr:32;
        dstaddr:32;
        option:*;
    }
}

里面的數字都是以bit為單位的,所以其實應該也能寫成這樣。

header ipv4_t{
    field{
        bit<4> version;
        bit<4> ihl;
        bit<8> diffserv;
        bit<16> totallen;
        bit<16> identification;
        bit<3> flags;
        bit<13> fragoffset;
        bit<8> ttl;
        bit<8> protocol;
        bit<16> hdrchecksum;
        bit<32> srcaddr;
        bit<32> dstaddr;
    }
}

類比寫下ipv6的

header ipv6_t{
    field{
        bit<4> version;
        bit<8> trafficclass;//這個在ipv6中類似於ipv4的diffserv。
        bit<20> flowlabel;
        bit<20> payloadlen;
        bit<8> nxthdr;
        bit<8> hoplimit;
        bit<128> srcaddr;
        bit<128> dstaddr;
        
    }
}

元數據

元數據是用來攜帶數據和配置性和西,元數據的申明與包頭類似,但在實例化的時候有所不同,而且包頭和元數據在字段值的約束上存在一定的差別。元數據分為兩種,一種是用來攜帶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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM