随着P4编程语言的日益普及,由于其灵活的可编程性,使其在软件定义网络中占据一席之地。
本文主要简介如何用P4写一个简单的vxlan转发并在DPDK上运行,涉及到P4 代码的基本模板,DPDK backend的P4编译方法以及DPDK pipeline example用例三个部分。
一、如何编写一个P4 pipeline
P4是由斯坦福大学的Nick Mckeown教授提出, 最新的规范为2016年发布的P4_16, 随着规范一起发布的还有PSA体系架构(P4~16~ Portable Switch Architecture (PSA))。PSA定义了一个类型库,externs以及一系列的包路径。PSA和P4_16语言的关系类似于C语言标准库和C语言的关系。
图1
图1展示了一个基于PSA架构实现的数据路径,分别是:
1. ingress parser: 检查数据包头,识别每个包里都有什么,每个字节表示什么
2. ingress: 一系列match-action的pipeline,检查是否有某些字节符合某个定义表项的关键字, 然后执行该关键字对应的action
3. Ingress deparser: 重组包头和数据格式,然后将报文送出
4. egress parser: 类似Ingress parser
5. egress: 类似Ingress
6. egress deparser: 类似Ingress deparser packet buffer: 用来存放上一个环节处理完的包
其中1-6为可编程模块,参照这个结构,我们可以实现一个简单的vxlan 报文转发。
/*引用必要的文件,可以直接调用一些已经写好的库函数*/
#include<core.p4>
#include<psa.p4>
/*定义相关协议的结构体*/
struct empty_metadata_t {
}
typedef bit<48> ethernet_addr_t;
header ethernet_t {
ethernet_addr_t dst_addr;
ethernet_addr_t src_addr;
bit<16> ether_type;
}
header ipv4_t {
bit<8> ver_ihl;
bit<8> diffserv;
bit<16> total_len;
bit<16> identification;
bit<16> flags_offset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdr_checksum;
bit<32> src_addr;
bit<32> dst_addr;
}
header udp_t {
bit<16> src_port;
bit<16> dst_port;
bit<16> length;
bit<16> checksum;
}
header vxlan_t {
bit<8> flags;
bit<24> reserved;
bit<24> vni;
bit<8> reserved2;
}
/*在这个示例中,我们需要定义一个完整的vxlan报文的包头格式*/
struct headers_t {
ethernet_t ethernet;
ipv4_t ipv4;
vxlan_t vxlan;
ethernet_t outer_ethernet;
ipv4_t outer_ipv4;