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