每一個封包在處理時,都會夾帶一個獨立的 metadata,我們可以把 metadata 視同為區域變數,以方便我們在判斷封包時使用。
自定義 Metadata
有關於 meatadata,在 P4 當中,開發者可以自定數個不同的 metadata,定義方式跟 header 一樣,如下:
header_type my_metadata_t {
fields {
field1: 8; // size, bits
field2: 4;
field3: 2;
/* ... */
}
}
header my_metadata_t my_metadata;
如此一來就可以直接在 action 或是 control 之中直接使用。
Standard Metadata
這一個 metadata 比較特別,當每一個封包進來時就會自動產生好該封包的基礎元素,例如 ingress port、packet length 等;這一個 metadata 也可以用來設定 out port。
使用他的方法很簡單,只需要使用:
standard_metadata.some_field
下面說明他所包含的欄位:
- ingress_port:封包進來的 port,唯讀
- packet_length:封包長度(byte),不包含 ethernet header CRC。如果 switch 開啟 cut-length 模式,則不能用在 match 中,也不能在 action 被參考;唯讀。
- egress_spec:在 ingress control flow 中可以被設定,可以是實體 port、或是虛擬 port,或是 multicast 群組。
- egress_port:真正實際要出去的實體 port,若 egress_spec 指向實體 port 就會相同,若是虛擬 port 則會轉換後寫在這邊,ingress 階段沒有讀取的意義。唯讀。
- egress_instance:僅在 egress 中有意義,跟 egress_port 一樣是在中間的 buffer/queue 階段產生的資料。
有這一份資料的目的是,當封包被複製(flood、multicast),則每一個封包都會有一個不同的 ID 以方便辨認。 - instance_type:這一個資料表示了該封包是「一般的」、「被複製的」或是重新再送的,有以下幾種可能:
- normal:一般的
- ingress clone:透過 clone_i2i 或 clone_i2e 的方式產生的封包
- egress clone:透過 clone_e2i 或 c;one_e2e 的方式產生的封包
- recirculated:透過 resubmit 跟 recirculate 重送的封包
註:這部份官方還在討論當中
- parser_status:0 表示 parser 沒有問題,否則就會是錯誤代碼。
註:這部份官方還在討論當中 - parser_error_location:詳細的 parser 錯誤位置。
註:這部份官方還在討論當中