1小時(shí)學(xué)會(huì)P4-16編程基礎(chǔ)

      網(wǎng)友投稿 1442 2025-03-31

      P4開源項(xiàng)目


      項(xiàng)目關(guān)系

      項(xiàng)目功能

      P4開源項(xiàng)目

      項(xiàng)目關(guān)系

      項(xiàng)目功能

      P4語(yǔ)言基礎(chǔ)(P4-16)

      相關(guān)術(shù)語(yǔ)

      PISA

      P4架構(gòu)

      P4-16語(yǔ)言元素

      為一個(gè)目標(biāo)硬件編寫P4程序

      數(shù)據(jù)類型

      基礎(chǔ)類型

      typedef 定義類型別名

      header 類型

      struct 類型

      parser

      parser的輸入與輸出

      parser的狀態(tài)與轉(zhuǎn)換

      狀態(tài)

      轉(zhuǎn)換

      value_set

      emit

      header stacks

      control

      action

      table

      exact

      ternary

      lpm

      apply

      deparser

      表達(dá)式

      集合運(yùn)算

      通用集合

      debug

      查看bmv 日志

      使用debug流表

      常用技巧

      分段IP識(shí)別

      P4Runtime

      運(yùn)行時(shí)控制方法比較

      Protocol Buffers基礎(chǔ)

      gRPC基礎(chǔ)

      P4Runtime Service

      FAQs

      [–Werror=type-error] error: cast: Cannot unify bit<8> to int<16>

      Can I apply a table multiple time in my P4 program?

      Can I modify table entries from my P4 program?

      What happens upon reaching the reject state of the parser?

      How much of the packet can I parse?

      一個(gè)流表可以配置多少個(gè)action,多個(gè)action對(duì)性能是否有影響?

      怎么設(shè)計(jì)流表已節(jié)省流表項(xiàng)所占空間?

      準(zhǔn)備開發(fā)環(huán)境

      參考

      本文主要講述一些P4-16的基本元素,以及相關(guān)基礎(chǔ)架構(gòu),旨在幫助初學(xué)者快速上手P4-16。

      P4開源項(xiàng)目

      P4項(xiàng)目源碼可以在github上直接獲?。╤ttps://github.com/p4lang)。

      項(xiàng)目關(guān)系

      項(xiàng)目關(guān)系如下:

      高級(jí)語(yǔ)言層:高級(jí)抽象的P4語(yǔ)言編寫程序

      前端編譯器:對(duì)高級(jí)語(yǔ)言進(jìn)行與目標(biāo)無(wú)關(guān)的語(yǔ)義分析并生產(chǎn)中間表示

      中間表示層:高級(jí)語(yǔ)言中間表示,可轉(zhuǎn)換成多種其他語(yǔ)言

      后端編譯器:將中間表示轉(zhuǎn)換為目標(biāo)平臺(tái)機(jī)器碼

      目標(biāo)對(duì)象層:受控制硬件/軟件設(shè)備

      項(xiàng)目功能

      P4項(xiàng)目由很多個(gè)單獨(dú)的模塊組成,每個(gè)模塊就是一個(gè)子項(xiàng)目,各子項(xiàng)目功能介紹如下:

      p4-hlir: 前端編譯器。將P4代碼轉(zhuǎn)換成高級(jí)中間表示。目前,高級(jí)中間表示的展示形式與Python對(duì)象的層次結(jié)構(gòu)相同。作用是: 使后端編譯器不用關(guān)心語(yǔ)法分析和目標(biāo)無(wú)關(guān)的語(yǔ)義檢查。

      p4c-bm:后端編譯器??梢詫⒏呒?jí)語(yǔ)言或高級(jí)中間表示轉(zhuǎn)為JSON格式或PD格式的配置文件。

      behavivoral-model: 又稱bmv2,P4軟件交換機(jī)。使用C++語(yǔ)言編寫。該模塊主要實(shí)現(xiàn)三個(gè)目標(biāo),最重要的是simple_switch,即P4語(yǔ)言標(biāo)準(zhǔn)中抽象交換機(jī)模型。另外兩個(gè)目標(biāo)是simple_router, l2_switch

      p4-build: 需要手動(dòng)生成的基礎(chǔ)設(shè)施庫(kù),為執(zhí)行P4程序,編譯安裝PD庫(kù)。

      switch: switch示例,基本完成交換機(jī)的絕大部分功能。

      p4factory: 快速開始,內(nèi)含6個(gè)可快速啟動(dòng)的項(xiàng)目,包括basic_routing, copy_to_cpu, l2_switch, sai_p4, simple_router, switch

      ntf (Network Test Framework): 網(wǎng)絡(luò)測(cè)試框架。內(nèi)含用以執(zhí)行bmv2應(yīng)用的網(wǎng)絡(luò)測(cè)試用例。該框架中集成了mininet和docker。

      ptf:Python測(cè)試框架,基于unittest框架實(shí)現(xiàn),該框架中的大部分代碼從floodlight項(xiàng)目中的OFTest框架移植而來(lái)。

      tutorials:示例教程。包括Basic Forwarding, Basic Tunneling, P4Runtime, Explicit Congestion Notification, Multi-Hop Route Inspection, Source Routing, Calculator, Load Balancing。

      scapy-vxlan: 擴(kuò)展Vxlan和ERSPAN-like協(xié)議包頭處理。

      P4語(yǔ)言基礎(chǔ)(P4-16)

      相關(guān)術(shù)語(yǔ)

      PISA(Protocol-Independent Switch Architecture):協(xié)議無(wú)關(guān)交換機(jī)架構(gòu)。

      P4 Target:特定的硬件實(shí)現(xiàn)。

      P4 Architecture:通過(guò)一組P4可編程、外部(externs)與固定組件,提供對(duì)P4 Target進(jìn)行編程的接口。

      P4語(yǔ)言與核心庫(kù)由社區(qū)發(fā)展而來(lái)。外部(extern)庫(kù)以及P4架構(gòu)定義由設(shè)備上提供。

      PISA

      Parser:根據(jù)程序員聲明的數(shù)據(jù)報(bào)頭,解析數(shù)據(jù)包,生產(chǎn)獨(dú)立的數(shù)據(jù)包頭與中間信息(MetaData);

      Match-Action Pipeline:根據(jù)解析的報(bào)頭與元信息,匹配流表,對(duì)報(bào)頭進(jìn)行修改、添加、刪除等操作;

      Deparser:數(shù)據(jù)包重新被序列化。

      P4架構(gòu)

      V1Model:For 芯片。 P4 v1.0 switch model實(shí)現(xiàn)源碼,公開屬性總結(jié)連接。

      SImpleSumeSwitch:For FPGA開發(fā)板。一個(gè)為NetFPGA SUME開發(fā)辦定義的P4架構(gòu),simpe-sume-switch,NetFPGA Sume;

      PSA:For everithing。參考實(shí)現(xiàn)源碼,手冊(cè)文檔

      除了V1Model,目前還有Portable Switch Architecture和Tofino native等架構(gòu),目標(biāo)是tofino native的架構(gòu)比v1model有更多的功能,PSA的架構(gòu)可以被更多的target (FPGA,ASIC,Software)所支持,提供從V1model到其他兩個(gè)架構(gòu)的translation。所以可以按照v1model的架構(gòu)來(lái)寫程序,之后compiler會(huì)幫助把v1model的程序轉(zhuǎn)換成其他的架構(gòu)的程序。

      P4-16語(yǔ)言元素

      Parser:通過(guò)一系列狀態(tài)(State)轉(zhuǎn)換,提取報(bào)頭字段,與一些元數(shù)據(jù);

      Control:Tables, Actions, control flow聲明;

      Expressions:基本的操作與運(yùn)算符;

      Data Type:BiStrings,header, Struct,array等數(shù)據(jù)類型。

      Architecture Description:目標(biāo)硬件提供的可編程的組件與接口;

      Extern Libraries:目標(biāo)硬件支持的特定組件。

      為一個(gè)目標(biāo)硬件編寫P4程序

      整個(gè)過(guò)程由幾部分組成,如下:

      用戶提供: P4程序與控制面;

      廠家提供:P4架構(gòu)模型與目標(biāo)硬件;

      運(yùn)行時(shí)操作:控制流表,外部控制,數(shù)據(jù)包上報(bào)控制面等。

      數(shù)據(jù)類型

      基礎(chǔ)類型

      bit: n位的無(wú)符號(hào)整型(bitstring);

      bit: 等同于bit<1>;

      int:n(n >=2)位的有符號(hào)整型;

      varbit:最大為n位的變長(zhǎng)bitstring。

      示例:

      bit<4> version; bit<4> ihl; bit<8> diffserv; bit<16> totalLen;

      typedef 定義類型別名

      設(shè)置類型別名,如:

      typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t;

      header 類型

      header類型為有序的程序集合,特點(diǎn)如下:

      可以包含bit、int、varbit基礎(chǔ)數(shù)據(jù)類型;

      必須字節(jié)對(duì)齊;

      可以是valid或invalid,并提供幾種操作測(cè)試或設(shè)置有效位:isValid()/setValid()/setInvalid()

      示例:

      typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; header ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } header ipv4_t { 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; ip4Addr_t srcAddr; ip4Addr_t dstAddr; }

      struct 類型

      struct類型為無(wú)序數(shù)據(jù)類型集合,且不需字節(jié)對(duì)齊??捎糜谠獢?shù)據(jù)的組織。

      示例:

      /* Architecture */ struct standard_metadata_t { bit<9> ingress_port; bit<9> egress_spec; bit<9> egress_port; bit<32> clone_spec; bit<32> instance_type; bit<1> drop; bit<16> recirculate_port; bit<32> packet_length; ... } /* User program */ struct metadata { ... }

      parser

      類似于C語(yǔ)言的function聲明關(guān)鍵字,可以有循環(huán)。通過(guò)一系列狀態(tài)(state)執(zhí)行與轉(zhuǎn)換,提取報(bào)頭字段與元數(shù)據(jù)。

      示例如下:

      /* From core.p4 */ extern packet_in { void extract(out T hdr); void extract(out T variableSizeHeader, in bit<32> variableFieldSizeInBits); T lookahead(); void advance(in bit<32> sizeInBits); bit<32> length(); } /* Architecture */ struct standard_metadata_t { bit<9> ingress_port; bit<9> egress_spec; bit<9> egress_port; bit<32> clone_spec; bit<32> instance_type; bit<1> drop; bit<16> recirculate_port; bit<32> packet_length; ... } /* User program */ struct metadata_t { ... } struct headers_t { ethernet_t ethernet; ipv4_t ipv4; } parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t std_meta) { state start { packet.extract(hdr.ethernet); transition accept; } }

      parser的輸入與輸出

      parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t std_meta) {...}

      parser的輸入與輸出模型如下:

      parser輸入:

      packet_in類型數(shù)據(jù)包,是由目標(biāo)設(shè)備提供的extern類型數(shù)據(jù)。

      metadata: 用戶自定義元數(shù)據(jù);

      standard_metadata_t:**設(shè)備產(chǎn)生提供的元數(shù)據(jù)。

      parser輸出:

      header:用戶定義的數(shù)據(jù)報(bào)頭;

      metadata: 用戶自定義元數(shù)據(jù);

      standard_metadata_t:設(shè)備產(chǎn)生提供的元數(shù)據(jù)。

      注意extern packet_in提供幾個(gè)接口,說(shuō)明如下:

      void extract(out T hdr): 從數(shù)據(jù)報(bào)文指針開始位置,抽取T類型數(shù)據(jù)大小的報(bào)頭,存儲(chǔ)在hdr中**,并將數(shù)據(jù)報(bào)文指針前移??赡苡|發(fā)PacketTooShort or StackOutOfBounds錯(cuò)誤,T類型的數(shù)據(jù)的大小必須為固定值。

      void extract(out T variableSizeHeader, in bit<32> variableFieldSizeInBits):讀取數(shù)據(jù)報(bào)頭到可變大小的報(bào)頭變量variableSizeHeader中,variableSizeHeader必須包含一個(gè)及以上varbit字段。數(shù)據(jù)報(bào)指針前移。

      T lookahead():讀取T類型數(shù)據(jù)大小的報(bào)頭,但不前移數(shù)據(jù)報(bào)指針。

      void advance(in bit<32> sizeInBits):前移數(shù)據(jù)報(bào)頭指針。

      bit<32> length():返回?cái)?shù)據(jù)報(bào)的字節(jié)數(shù)。

      parser的狀態(tài)與轉(zhuǎn)換

      狀態(tài)

      parser有三種預(yù)設(shè)狀態(tài)state,為:

      start:進(jìn)入parser功能塊后的第一個(gè)狀態(tài),自動(dòng)進(jìn)入;

      accept:若進(jìn)入accept狀態(tài),則表示數(shù)據(jù)報(bào)進(jìn)入后續(xù)control流程;

      reject:數(shù)據(jù)包被拋棄。

      其他states,用戶可以自行定義。每個(gè)state執(zhí)行0次或以上,然后轉(zhuǎn)換為其他state。(允許循環(huán))

      轉(zhuǎn)換

      使用transition關(guān)鍵字使parser在狀態(tài)之間轉(zhuǎn)換。

      示例:

      parser MyParser(...) { state start { packet.extract(hdr.ethernet); transition accept; } }

      使用transition select(data){...}根據(jù)data的值轉(zhuǎn)換到不同狀態(tài)。

      select聲明類似C語(yǔ)言中的switch...case,但是其沒有fall-through行為,不用break進(jìn)行中斷后續(xù)選擇。

      state start { transition parse_ethernet; } state parse_ethernet { packet.extract(hdr.ethernet); transition select(hrd.ethernet.etherType) { 0x800: parse_ipv4; default: accept; } } state parse_ipv4 { packet.extract(hdr.ipv4); transition accept; }

      value_set

      只能用在parser 語(yǔ)句塊中。

      emit

      pkt.emit 不支持條件emit,mirror.emit支持單bit的條件emit

      header stacks

      頭堆棧有兩個(gè)屬性 next 與 last,其可以在解析器中解析時(shí)使用。

      舉例如下,使用如下mpls定義表示10個(gè)MPLS頭:

      header Mpls_h { bit<20> label; bit<3> tc; bit bos; bit<8> ttl; } Mpls_h[10] mpls;

      mpls.next 表示 mpls 堆棧中的一個(gè)元素的值。初始時(shí),mpls.next 指向堆棧的第一個(gè)元素,當(dāng)成功調(diào)用extract方法后,mpls.next將自動(dòng)向前偏移,指向下一個(gè)元素。

      mpls.last指向 next 前面的那個(gè)元素(如果元素存在),即最近 extract 出來(lái)的那個(gè)元素。

      注意:通過(guò) next 或 last 屬性訪問(wèn)頭堆棧中不存在的元素將引發(fā) transition reject 狀態(tài)轉(zhuǎn)換,并設(shè)置錯(cuò)誤到 error.StackOutOfBounds

      struct Pkthdr { Ethernet_h ethernet; Mpls_h[3] mpls; // other headers omitted } parser P(packet_in b, out Pkthdr p) { state start { b.extract(p.ethernet); transition select(p.ethernet.etherType) { 0x8847: parse_mpls; 0x0800: parse_ipv4; } } state parse_mpls { b.extract(p.mpls.next); transition select(p.mpls.last.bos) { 0: parse_mpls; // This creates a loop 1: parse_ipv4; } } // other states omitted }

      control

      對(duì)于固定硬件,SwitchIngress 控制流程的參數(shù)固定,如下:

      control SwitchIngress( inout header_t hdr, inout metadata_t ig_md, in ingress_intrinsic_metadata_t ig_intr_md, in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { ... }

      類似于C語(yǔ)言的function聲明關(guān)鍵字,不能有循環(huán)。

      if 語(yǔ)句中表達(dá)式<, >兩側(cè)只能有一個(gè)變量,==兩側(cè)可以都為變量,但判斷條件產(chǎn)生的PHV不能超過(guò) 44 bits,否則報(bào)如下錯(cuò)誤

      if (eg_md.lkp.outer_dst_mac == eg_md.lkp.outer_src_mac) { /home/lihaifeng/test/casteni-gw/p4src/casteni_gw.p4(314): error: : condition too complex, limit of 4 bytes + 12 bits of PHV input exceeded /home/lihaifeng/test/casteni-gw/p4src/casteni_gw.p4(314): [--Werror=legacy] error: condition too complex, one operand of > must be constant

      在control中,可以申明變量、創(chuàng)建tables,以及實(shí)例化externs等。

      在control中,通過(guò)apply聲明功能;

      代表可表達(dá)為DAG的所有類型的處理,包括:

      Match-Action Pipelines;

      Deparsers;

      其他的數(shù)據(jù)報(bào)處理,如更新checksums。

      由用戶與特定架構(gòu)指定的接口,如headers和metadata。

      示例:

      control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t std_meta) { /* Declarations region */ bit<48> tmp; apply { /* Control Flow */ tmp = hdr.ethernet.dstAddr; hdr.ethernet.dstAddr = hdr.ethernet.srcAddr; hdr.ethernet.srcAddr = tmp; std_meta.egress_spec = std_meta.ingress_port; } }

      上述程序的功能是:將源MAC與目的MAC對(duì)換,然后從輸入口轉(zhuǎn)發(fā)出去。

      action

      上小結(jié)的功能可以通過(guò)簡(jiǎn)單的action語(yǔ)句重新實(shí)現(xiàn):

      control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t std_meta) { action swap_mac(inout bit<48> src, inout bit<48> dst) { bit<48> tmp =src; src = dst; dst = tmp; } apply { swap_mac(hdr.ethernet.srcAddr, hdr.ethernet.dstAddr); std_meta.egress_spec = std_meta.ingress_port; } }

      action關(guān)鍵字的特點(diǎn):

      類似C語(yǔ)言中的function

      action可以在control內(nèi)聲明,也可以在control外全局定義;

      參數(shù)需要有類型與方向:有方向的參數(shù)來(lái)自數(shù)據(jù)面;沒方向的參數(shù)來(lái)自控制面。有方向的參數(shù)的action可以直接調(diào)用。沒有方向參數(shù)的action通常在table中被調(diào)用。

      支持在action內(nèi)部實(shí)例化變量;

      支持標(biāo)準(zhǔn)的算術(shù)操作,如-,+,*(注意:無(wú)除與取模運(yùn)算),位運(yùn)算~, &, |, ^, >>, <<,比較運(yùn)算==, !=, >, >=, <, <=。

      支持非標(biāo)準(zhǔn)操作符:1)位切片,[m:l]; 2)自增運(yùn)算,++。

      table

      table主要由key與actions兩部分組成。

      可選的,可以指定table其他屬性,如:

      size:表項(xiàng)大小

      default_action = NoAction:默認(rèn)動(dòng)作

      const entries = {}:

      示例:

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

      一個(gè)table的表項(xiàng)包含如下幾部分:

      用于匹配的特定key;

      當(dāng)數(shù)據(jù)報(bào)匹配這個(gè)表項(xiàng)時(shí),一個(gè)action將被執(zhí)行;

      action data(可能為空)

      match-action 處理流程

      大致過(guò)程主要分為兩部分:

      數(shù)據(jù)面P4程序:

      定義table的格式,包括key字段、可能產(chǎn)生的所有action、action data

      根據(jù)header與metadata,執(zhí)行表查找

      根據(jù)匹配結(jié)果,執(zhí)行相應(yīng)的action

      控制面

      下發(fā)特定的流表項(xiàng),下發(fā)流表的方法有:1)基于配置;2)基于自動(dòng)發(fā)現(xiàn);3)基于協(xié)議計(jì)算。

      標(biāo)準(zhǔn)的匹配種類有:exact,ternary, lpm, index, range, valid

      exact

      精確匹配

      ternary

      基于三態(tài)內(nèi)容尋址器的匹配,匹配表的每個(gè)表項(xiàng)都有一個(gè)掩碼,將掩碼和字段值進(jìn)行邏輯與運(yùn)算,再執(zhí)行匹配。為了避免導(dǎo)致多條表項(xiàng)匹配成功,每條表項(xiàng)都需要設(shè)定一個(gè)優(yōu)先級(jí)。對(duì)于每一個(gè)ternary字段,表項(xiàng)的值由兩部分組成:value &&& mask,先value后mask,順序一定不能錯(cuò)!mask表示在這個(gè)字段上希望匹配哪些bits,1表示匹配,0表示忽略。若 匹配字段 & mask == value 則匹配成功。例如:

      const entries = { // 該表項(xiàng)表示匹配那些ip src address前24位為10.0.1的數(shù)據(jù)包,而忽略了ip src // address的最后8位以及ip dst address (0x0a000100 &&& 0xffffff00, 0x00000000 &&& 0x00000000): your_action(0x66, 0x8888); // 該表項(xiàng)表示匹配ip src address為10.0.2.x,且ip dst address為10.0.1.1的數(shù)據(jù)包 // 如果mask全為1,則可以省略mask而只寫value (0x0a000200 &&& 0xffffff00, 0x0a000101): your_action(0x11, 0x2222); // 最后,由于是ternary匹配,一個(gè)數(shù)據(jù)包可能匹配多條表項(xiàng),因而表項(xiàng)之間需要有優(yōu)先級(jí) // 以上述方式書寫表項(xiàng)時(shí),越早出現(xiàn)的表項(xiàng)優(yōu)先級(jí)越高。 // 當(dāng)使用控制器動(dòng)態(tài)的加入表項(xiàng)時(shí),應(yīng)該顯式指定插入表項(xiàng)的優(yōu)先級(jí)以確保正確性。 }

      當(dāng)然,除了以const entries的形式寫入表項(xiàng),還可以通過(guò)P4 Controller 來(lái)寫入。以下為如何構(gòu)造一個(gè)新的表項(xiàng)(Python)

      table_entry = p4info_helper.buildTableEntry( table_name="MyIngress.ipv4_ternary", match_fields={ "hdr.ipv4.srcAddr": (0x0a000200, 0xffffff00), # (value, mask) "hdr.ipv4.dstAddr": (0x0b000100, 0xffffff00) }, action_name="MyIngress.your_action", action_params={ "param1": 0x66, "param2": 0x1234 }, priority=1 )

      通過(guò)控制器寫入表項(xiàng)時(shí)要注意一點(diǎn),如果你不關(guān)心某個(gè)字段,應(yīng)該直接在match_fields中直接不寫該字段而不是將mask全設(shè)為0,這與const entries是不一樣的。

      table_entry = p4info_helper.buildTableEntry( table_name="MyIngress.ipv4_ternary", match_fields={ "hdr.ipv4.srcAddr": (0x0a000200, 0xffffff00) }, action_name="MyIngress.your_action", action_params={ "param1": 0x66, "param2": 0x1234 }, priority=1 )

      lpm

      lpm match: 最長(zhǎng)前綴匹配,這是三重匹配的一種特殊情況,當(dāng)多個(gè)表項(xiàng)匹配成功時(shí),選擇掩碼最長(zhǎng)的最為最高優(yōu)先級(jí)進(jìn)行匹配。

      上述匹配方法定義在core.p4中:

      /* core.p4 */ match_kind { exact, ternary, lpm }

      v1model架構(gòu)還支持range與selector匹配。

      有些架構(gòu)還支持regexp與fuzzy匹配。

      apply

      在apply執(zhí)行action,或?qū)able應(yīng)用。

      示例:

      control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { table ipv4_lpm { ... } action update() { ... } apply { ... ipv4_lpm.apply(); update(); ... } }

      deparser

      1小時(shí)學(xué)會(huì)P4-16編程基礎(chǔ)

      deparser 將報(bào)頭組裝到數(shù)據(jù)報(bào)中,其不需要額外的新組建,使用control功能進(jìn)行表示即可。

      示例:

      /* From core.p4 */ extern packet_out { void emit(in T hdr); } /* User Program */ control DeparserImpl(packet_out packet, in headers hdr) { apply { ... packet.emit(hdr.ethernet); ... } }

      deparser的參數(shù)由兩部分組成:

      packet_out類型:其為定義在core.p4的extern類型。其void emit(in T hdr)方法,將hdr組裝到數(shù)據(jù)報(bào)中,并移動(dòng)數(shù)據(jù)報(bào)指針。

      hearders: 用戶定義的報(bào)頭類型,方法為in。

      表達(dá)式

      集合運(yùn)算

      通用集合

      default 或者 _ 表示通用集合,包含指定類型的所有可能。

      select (hdr.ipv4.version) { 4: continue; _: reject; }

      debug

      查看bmv 日志

      /tmp/p4s.s1.log /tmp/p4s.s2.log

      使用debug流表

      使用table讀取headers或metadata信息。如:

      control Myingress(...) { table debug { key = { std_meta.egress_spec: exact; } action = {} } apply { debug.apply(); } }

      打印結(jié)果如下:

      ?[15:16:48.145] [bmv2] [D] [thread 4090] [96.0] [cxt 0] Looking up key: * std_meta.egress_spec : 2

      常用技巧

      分段IP識(shí)別

      使用hdr.ipv4.frag_offset字段區(qū)分,如果為0,則解析,否則若數(shù)據(jù)報(bào)文分段,則不解析。

      state parse_ipv4_no_options { ig_md.flags.ipv4_checksum_err = ipv4_checksum.verify(); transition select(hdr.ipv4.protocol, hdr.ipv4.frag_offset) { (IP_PROTOCOLS_ICMP, 0) : parse_icmp; (IP_PROTOCOLS_IGMP, 0) : parse_igmp; (IP_PROTOCOLS_TCP, 0) : parse_tcp; (IP_PROTOCOLS_UDP, 0) : parse_udp; // Do NOT parse the next header if IP packet is fragmented. default : accept; } }

      P4Runtime

      本節(jié)關(guān)注紅框內(nèi)的部分。

      運(yùn)行時(shí)控制方法比較

      P4編譯器自動(dòng)生成的runtime APIs:依賴程序,很難再不重啟控制面的情況下添加新的P4程序

      BMv2 CLI:程序獨(dú)立,但是目標(biāo)依賴,控制面可移植性差

      OpenFlow:目標(biāo)獨(dú)立,但依賴協(xié)議。openflow協(xié)議頭與actions在協(xié)議規(guī)范中定義死了。

      OCP Switch Abstraction Interface (SAI):目標(biāo)獨(dú)立,但協(xié)議依賴。

      各運(yùn)行時(shí)控制API優(yōu)缺點(diǎn)總結(jié)如下:

      可見,P4Runtime API可以做到目標(biāo)與協(xié)議獨(dú)立,那么,什么是P4Runtime?

      P4目標(biāo)的運(yùn)行控制框架,開源了API的服務(wù)端實(shí)現(xiàn)(https://github.com/p4lang/PI)

      目前其草案v1.0已可以獲得

      基于Protocol buffers 的API:p4runtime proto, gRPC transport

      P4程序獨(dú)立:不用隨著P4程序而改變

      域可重配置:push 新P4程序時(shí),無(wú)需重新編譯目標(biāo)交換機(jī)軟件棧

      Protocol Buffers基礎(chǔ)

      Protocol Buffers,簡(jiǎn)稱protobuf,是一種序列化數(shù)據(jù)結(jié)構(gòu)的協(xié)議。

      gRPC基礎(chǔ)

      gRPC是一個(gè)高性能、通用的開源 RPC 框架,其由 Google 主要面向移動(dòng)應(yīng)用開發(fā)并基于HTTP/2協(xié)議標(biāo)準(zhǔn)而設(shè)計(jì),基于ProtoBuf(Protocol Buffers) 序列化協(xié)議開發(fā),且支持眾多開發(fā)語(yǔ)言。

      P4Runtime Service

      使本地或遠(yuǎn)程實(shí)體能夠仲裁主控權(quán),加載管道/程序,發(fā)送/接收數(shù)據(jù)包,以及讀寫轉(zhuǎn)發(fā)表?xiàng)l目,計(jì)數(shù)器和其他P4實(shí)體。

      FAQs

      [–Werror=type-error] error: cast: Cannot unify bit<8> to int<16>

      ig_md.ecmp_hash_int = (ecmp_hash_int_t) ig_md.ecmp_hash;

      解析

      Many arithmetic expressions that would be allowed in other languages are illegal in P4. To illustrate, consider the following declarations:

      bit<8> x; bit<16> y; int<8> z;

      The table below shows several expressions which are illegal because they do not obey the P4 typing rules. For each expression we provide several ways that the expression could be manually rewritten into a legal expression. Note that for some expression there are several legal alternatives, which may produce different results! The compiler cannot guess the user intent, so P4 requires the user to disambiguate.

      解決辦法:

      ig_md.ecmp_hash_int = (int<16>)(bit<16>) ig_md.ecmp_hash;

      Can I apply a table multiple time in my P4 program?

      no (except via resubmit/recirculate)

      Can I modify table entries from my P4 program?

      No(except for direct counters)

      What happens upon reaching the reject state of the parser?

      architecture dependent

      How much of the packet can I parse?

      architecture dependent

      一個(gè)流表可以配置多少個(gè)action,多個(gè)action對(duì)性能是否有影響?

      應(yīng)該不會(huì)影響性能,一個(gè)流表為一個(gè)logic stage,多個(gè)stage連接為一個(gè)pipeline,stage越少,時(shí)延越低。

      vlan id -> vxlan id,寫入metadata vpc級(jí)別

      dst ip cidr -> sg mac 作為 inner src mac vpc子網(wǎng)級(jí)別

      dst ip -> inner dst mac, outer dst ip,走系統(tǒng)路由,arp系統(tǒng)。 ip地址級(jí)別

      匹配 -> 轉(zhuǎn)發(fā)

      怎么設(shè)計(jì)流表已節(jié)省流表項(xiàng)所占空間?

      下行

      標(biāo)志位放哪?

      vlan id -> vxlan id,寫入metadata vpc級(jí)別

      dst ip cidr -> sg mac 作為 inner src mac vpc子網(wǎng)級(jí)別

      dst ip -> inner dst mac, outer dst ip,走系統(tǒng)路由,arp系統(tǒng) ip地址級(jí)別

      上行

      is_keeping 2

      flow的包過(guò)來(lái),若is_keeping為1或2,置is_keeping為2,將數(shù)據(jù)報(bào)轉(zhuǎn)發(fā)給vRouter。vRouter收到包后,vlan轉(zhuǎn)vxlan,發(fā)送到pod,途徑ToR。

      若發(fā)送探測(cè)消息,怎么構(gòu)造識(shí)別?

      在vlan包中加入特殊字段,回來(lái)的是vxlan id,且ip 可選字段中有特殊字段,則若is_keeping為2,則刷為1。再發(fā)一個(gè)探測(cè)包出去?

      直接發(fā)探測(cè)包,一批一個(gè)?

      全部下完后,再切

      上次下的流表,is_keeping為0

      怎么知道流表下完成,有個(gè)開關(guān)流表,下下去后,開始發(fā)送探測(cè)包,若is_keeping全為0,則將開關(guān)流表關(guān)閉。

      若到了下輪下完表時(shí)間,還是沒有切完成怎么辦?那就先不切,下開關(guān)流表,關(guān)閉切流。下新流表后,從新開始切,不會(huì)亂序。

      到了后,構(gòu)造探測(cè)包,探測(cè)包有標(biāo)志,是一個(gè)普通flow的vlan包。

      1: 這次下的流表

      下完后,

      st=>start: 數(shù)據(jù)包進(jìn)來(lái) not_probing=>condition: probing_packet_filter,不是探測(cè)包? vlan2vxlan=>condition: mapping_table,不能執(zhí)行vlan與vxlan的轉(zhuǎn)換? can_probe=>condition: can_probe_table,是否可以發(fā)探測(cè)包? probing=>operation: probing_table,發(fā)送探測(cè)包, 若發(fā)送標(biāo)志位為true,刷mapping_table,將發(fā)送標(biāo)志位置為true。 forward=>operation: forward_table,將數(shù)據(jù)包轉(zhuǎn)發(fā)到相應(yīng)的計(jì)算節(jié)點(diǎn) ecmp_end=>end: ecmp_table,使用ecmp算法將數(shù)據(jù)包轉(zhuǎn)到相應(yīng)vRouter st->not_probing not_probing(yes)->vlan2vxlan(yes)->can_probe(yes)->probing->ecmp_end vlan2vxlan(no)->forward can_probe(no)->ecmp_end not_probing(no)->can_probe(yes)

      準(zhǔn)備開發(fā)環(huán)境

      從P4-developer-day或者騰訊云盤下載虛擬機(jī)鏡像,通過(guò)virtualbox導(dǎo)入,生成虛擬機(jī)。

      參考

      P4語(yǔ)言基礎(chǔ)與實(shí)戰(zhàn)

      P4語(yǔ)言編程詳解

      p4-16中對(duì)main的執(zhí)行順序是怎么樣的?(V1Model, Tofino native, Portable Switch Architecture的討論)

      理論與實(shí)踐2-快速上手

      P4語(yǔ)言編程快速開始

      P4 語(yǔ)言初識(shí)

      智簡(jiǎn)網(wǎng)絡(luò) 網(wǎng)絡(luò)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:word 如何分節(jié)(word目錄怎么制作)
      下一篇:怎么自動(dòng)生成日期(在合并單元格中怎么自動(dòng)生成日期)
      相關(guān)文章
      亚洲AV无一区二区三区久久| 亚洲性日韩精品一区二区三区| 亚洲Av无码国产情品久久 | 亚洲成人网在线观看| 久久久久亚洲AV无码麻豆| 久久亚洲精品AB无码播放| 久久亚洲国产精品| 亚洲成色999久久网站| 亚洲AV无码精品无码麻豆| 久久亚洲精品无码| 亚洲成在人天堂一区二区| 久久亚洲AV午夜福利精品一区 | 国产亚洲综合成人91精品| 亚洲女同成av人片在线观看| 亚洲啪啪AV无码片| 亚洲国产精品无码专区影院| 亚洲福利视频导航| 亚洲黄色在线观看网站| 亚洲天堂一区二区三区| 亚洲一区二区三区高清不卡| 亚洲精品中文字幕无码A片老| 日韩欧美亚洲国产精品字幕久久久| 美国毛片亚洲社区在线观看| 亚洲国产天堂久久久久久| 伊人亚洲综合青草青草久热| 国产亚洲av片在线观看播放| 亚洲国产精品国自产电影| 亚洲精品偷拍无码不卡av| 亚洲六月丁香六月婷婷色伊人| 亚洲成a人片在线不卡| 亚洲精品蜜夜内射| 亚洲精品无码久久毛片| 亚洲中文字幕无码一区二区三区 | 国产成A人亚洲精V品无码性色| 亚洲av无码国产精品夜色午夜| 亚洲色av性色在线观无码| 国产精品亚洲专区在线观看 | 亚洲第一视频网站| 亚洲人成伊人成综合网久久| 亚洲中文字幕一区精品自拍| 春暖花开亚洲性无区一区二区|