P4-相关工具链
P4 程序运行的整体结构
如图:
其主要可以分 4 个步骤
Step1 编译
将 .p4
程序编译为 .json
和 .p4info
文件:
1 |
|
p4c-bm2-ss
指, 使用 BMv2 后端来编译--p4v 16
, p4 version, 指定 P4 的版本, 16 表示 P4-16-o test.json
, 指定编译输出文件名--p4runtime-file test.p4info
指定生成的 P4Runtime 信息文件的名称, 该文件包含有关数据平面对象 (如表, 动作等) 的元数据--p4runtime-format text
, 指定生成的 P4Runtime 文件的格式. text 表示生成的文件将采用文本格式, 而不是二进制格式
一个 p4
程序编译为 p4info
的示例如下:
Step2 创建 veth 接口
veth 指 virtual ethernet, 虚拟以太网接口, 是在 Linux 内核中成对创建的 (这一对是相连的, 形成一个虚拟以太网链路), 用于连接不同的命名空间或容器. 数据包从一个 veth 设备进入, 从另一个 veth 输出.
可以直接用 ip
命令创建:
1 |
|
这里每行命令的作用分别是:
ip link add name veth0 type veth peer name veth1
, 创建了一对虚拟以太网设备, 分别命名为veth0
和veth1
ip link set dev ${ifaace} up
, 启用veth
设备sysctl net.ipv6.conf.${iface}.disable_ipv6=1
, 禁用 IPv6 功能, 用于提高性能, 简化测试场景TOE_OPTIONS="'rx tx sg ufo gso gro lro rxvlan txvlan rxhash"
, 设置一组以太网卡的 TCP 卸载选项/sbin/ethtool --offload $intf "$TOE_OPTION"
, 用ethtool
禁用指定选项
启动 BMv2
BMv2, Behavioral Model version2, 是 P4.org
提供的一个软件交换机实现, 旨在支持 P4 语言编写的程序. 它是一个开源项目, 主要用于开发, 测试和验证 P4 程序, 启用命令如下:
1 |
|
- gRPC (Remote Process Control) 服务, 用于实现控制平面和数据平面之间的通信, P4 程序可以通过 gRPC 接口暴露自己的功能和状态信息, 从而允许外部控制器对其进行编程和管理
simple_switch_grpc
是一中基于 BMv2 的交换机模拟器, 可移植性 P4 程序并提供 gRPC 服务接口--log-console
将日志输出到控制台, 方便调试--dump-packet-data 64
设置数据包转储的最大长度为 64 字节-i 0@veth0 -i 1@veth2 ...
将虚拟网络接口连接到模拟器的输入端口--no-p4
表明不需要编译 P4 程序--grpc-server-addr 0.0.0.0:50051
指定 gRPC 服务器的监听地址和端口--cpu-port 255
, 指定了一个特殊的 CPU 端口, 用于处理不能由数据平面处理的数据包test.json
是前面 P4 程序的编译输出
Step 4: 启用 P4Runtime 静态控制器
静态 P4Runtime 控制器是指一种在运行时预先配置和初始化的控制器, 其主要功能是管理和配置 P4 数据平面设备 (如交换机或路由器). 与动态控制器不同, 静态控制器通常不会根据实时网络流量或事件进行调整, 而是在启动时加载固定的配置.
1 |
|
Runtime Control
对于 P4 而言, 用 P4Runtime 是最好的.
Protocol Buffers
Protocol Buffers (简称 protobuf
) 是一种用于序列化结构化数据的开源库和协议. 它由 Google 开发并开源, 提供了一种语言中立, 平台中立的方式来高效地处理可扩展的结构化数据. P4Runtime 用其作为通信协议, 来序列化要传输的数据.
Protobuf 的消息定义示例如下:
1 |
|
syntax = "proto3"
指定了使用的 Protobuf 语法版本为 proto3message Person
定义一个名为Person
的 Protobuf 消息string name = 1
定义 “Person” 消息中的一个字段, 名为 “name”, 类型为 “string”, 标识号为 1int32 id = 2
, 定义一个字段, 名为 “id”, 类型为 “int32”, 标识号为 2enum PhoneType { ... }
定义一个枚举类型, 包含MOBILE
,HOME
,WORK
三个值repeated PhoneNumber phone = 4;
, 定义一个 名为phone
的字段其可以添加多个 “PhoneNumber” 类型元素 (相当于一个数组, 具体怎么加暂时不谈)
使用 protobuf 的好处在于:
- 主流语言都支持其格式解析
- 跨平台
- 强类型
P4Runtime 所定义的 protobuf 可以在 https://github.com/p4lang/p4runtime/blob/master/proto/p4/v1/p4runtime.proto 查看.
gRPC
gRPC 主要由两部分组成:
- gRPC Server, 处理来自客户端的请求并返回响应
- gRPC Stub, 将客户端 (比如 Ruby 程序) 的调用翻译成 Protocol Buffers 请求, 并将响应转换回客户端可以理解的格式
工作示意图如下:
服务编写示例如:
1 |
|
(可以在 https://grpc.io/docs/guides/ 查看文档 )