P4学习之路
记录自己进行P4实验过程中所了解到的一些简单的P4知识
概念
- P4的全称是Programming Protocol-independent Packet Processor,即对协议无关的包处理器进行编程的语言
- 所谓对协议无关,即根据用户的需求实现一个全新的网络协议
- 定义自己想要的数据面,然后通过南向协议(openFlow)添加流表项
流程
- P4的流程如下图所示,当数据包进入交换机,首先解析数据包包头,然后ingress进行处理,最后封包转发走
- P4写的就是数据包怎么处理
包解析
- 包解析就是 提取出数据报文中我们要的数据这一步骤
PS:(工程师提醒我)提取的是按照报文的顺序往后提取的,有一个指针指向了报文已经提取的位置 - 已经提取的部分,再提取就不对
比如,我本来已经提取数据包IPv4的头部,包含了目的IP地址,我想将其作为四个8比特字符提取出来,不能再写一个提取目的地址,我就犯过这个错误
举例如下,需求:将目的IP地址解析为四个8比特字符
代码如下:
// 修改IPv4的header
header ipv4_h {
bit<4> version;
bit<4> ihl;
bit<8> diffserv;
bit<16> total_len;
bit<16> identification;
bit<3> flags;
bit<13> frag_offset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdr_checksum;
ipv4_addr_t src_addr;
// ipv4_addr_t dst_addr;
bit<8> ch1;
bit<8> ch2;
bit<8> ch3;
bit<8> ch4;
}
// 包解析逻辑部分
parser SwitchIngressParser(
packet_in pkt,
out header_t hdr,
out metadata_t ig_md,
out ingress_intrinsic_metadata_t ig_intr_md) {
// 解析器从start状态开始执行到结束,其中reject或accept表示已达到结束状态
// transition表示转换到其他状态
state start {
pkt.extract(ig_intr_md);
pkt.advance(PORT_METADATA_SIZE);
transition parse_ethernet;
}
state parse_ethernet {
pkt.extract(hdr.ethernet);
transition parse_ipv4;
}
// 解析器状态的最后一条语句是可选的transition语句,将控制权转移到另一个状态,可能accept 或者reject
state parse_ipv4 {
pkt.extract(hdr.ipv4);
transition accept;
}
}
写表查表
- 写表,表包括以下几个部分
- 表名
- key值与匹配类型,匹配类型有exact、ternary、lpm三种
- actions,包含所有可能的action
- 定义默认的动作
- 表的大小
table tableName {
key = {
a : exact; // 关键字a是确切匹配
b : ternary; // 关键字b是ternary类型
}
actions = {
get_value; // 包含所有可能的动作
}
size=1024; //表的大小
}
- 查表
- 一个表只能查一次,一个表对应一个match-action unit(匹配动作单元)
- 若要对一个表多次查找,则需要被实例化多次,即写多个名字不同的表
- 查表在apply里面进行
apply {
// 进行操作
// 查表
tableName.apply();
}
- actions
(个人感觉只能进行赋值操作…)- 只允许straight-line代码
- 没有条件语句或表达式
包封装
暂未进行了解…
其它
- switch
对于switch语句,表达式必须是t.apply().action_run(),所有标签必须是表的动作t,或者是default - select
选择表达式select将提取的标头字段与一组常量比较