跳转到内容

P4 — 让交换机的转发逻辑像写代码一样改

是什么

P4 是一门给网络交换机写转发逻辑的语言。日常类比:以前的交换机像一台只能做 12 道菜的预制菜厨房——菜单印在芯片上,想加一道新菜得换芯片。P4 给你一台可编程灶台和一种叫 P4 的食谱描述法,今天写川菜明天写粤菜,不停业改菜谱。

具体一点:你写一份 .p4 文件,描述”包从线缆进来后,先解析哪些字段、按什么规则查表、查到了改哪几个字段、再从哪个口出去”。编译器把这份文件翻译到具体硬件(ASIC、FPGA、SmartNIC、软件交换机都行),交换机就按你写的逻辑跑了。

P4 = Programming Protocol-independent Packet Processors,“协议无关”是它的灵魂。

为什么重要

不理解 P4,下面这些事就解释不清:

  • 为什么 2014 年之后大公司(腾讯、阿里、AT&T)的数据中心交换机突然能”自己改协议”
  • 为什么 Intel 在 2019 年花 $5B 买下一家叫 Barefoot 的小公司——他们的 Tofino 芯片是第一颗商用 P4 可编程交换芯片
  • 为什么 SDN(软件定义网络)只解决了一半问题——OpenFlow 让控制面可编程,P4 才让数据面也可编程
  • 为什么新协议(VXLAN、Geneve、SRv6)一年冒一个还能落地——不再需要等芯片厂商两年后出新版

核心要点

P4 的世界观可以拆成 三块

  1. 抽象转发模型:所有可编程交换机都长一个样——parser → 多级 match-action 表 → deparser。包进来 parser 提字段,然后逐级查表改字段,最后 deparser 拼回去发出去。这套抽象叫 PISA(Protocol Independent Switch Architecture)。

  2. parser 是个状态机:从 ethernet 头开始,按 ethertype 跳到下一个头部(IPv4、IPv6、MPLS、或者你自己定义的私有协议),一直跳到底,把所有字段拿出来。parser 也是你写的——这就是”协议无关”。

  3. match-action 表的字段不再固定:OpenFlow 1.0 写死了 12 个能匹配的字段(MAC、IP、port 等);P4 让你匹配 parser 拿到的任意字段。Action 是一组原语:修改字段、复制、丢弃、转发到端口。

三个设计目标(论文摘要):

  • 协议无关:包格式由你定义,不是由芯片定义
  • 目标无关:同一份 P4 代码可以跑到 ASIC / FPGA / 软件交换机
  • 可重构:已部署的设备现场改逻辑,几秒内生效,不用换硬件

实践案例

案例 1:从 OpenFlow 到 P4,菜单怎么变

OpenFlow 1.0 的 match 字段(写死在标准里):

ingress_port, MAC src/dst, ethertype, VLAN, IP src/dst,
IP proto, IP ToS, TCP/UDP src/dst port -- 共 12 个

要支持 IPv6?等 OpenFlow 1.3。要支持 VXLAN?等 1.4。每加一个协议,标准升一版,芯片重做一轮。

P4 的写法(伪代码片段):

header vxlan_t {
bit<8> flags;
bit<24> reserved;
bit<24> vni;
bit<8> reserved2;
}
parser parse_vxlan {
extract(vxlan);
return parse_inner_ethernet;
}

包格式是你定义的。明天 VXLAN-GBP 出来再加 8 字节,改一下 header 定义重编译就行。

案例 2:可重构的真正含义

数据中心运维场景:

  • 周一:交换机跑标准 IPv4 转发
  • 周二下午:业务方要求加一个『按租户 ID 限速』的功能
  • 周二晚:网络工程师改 P4 代码 → 编译 → 通过控制器下发到 200 台 Tofino 交换机 → 全部生效,零停机

这在 OpenFlow 时代不可能——你只能在控制器层做应用层限速,慢且贵。P4 把这种逻辑下沉到线速硬件(Tbps 级)做。

案例 3:In-band Network Telemetry(INT)

P4 的杀手级应用之一:让每个包自己带回经过路径的延迟、队列长度、出口端口

action add_int_metadata() {
hdr.int.queue_depth = standard_metadata.deq_qdepth;
hdr.int.hop_latency = standard_metadata.deq_timedelta;
}

每个包穿过交换机时,硬件自己把队列状态打到包尾。运维拿到包就知道”这条流经过了哪 5 跳、每跳排了多久”。在 P4 之前这要靠采样 + 采集器 + 离线对齐,现在线上实时拿。

踩过的坑

  1. P4 不是图灵完备。没有循环、没有递归、没有动态内存。这不是 bug 是设计——为了线速(每秒处理 10⁹ 个包),它必须有界、确定。如果你的逻辑需要”看包 N 次”,P4 不适合。

  2. P4_14 和 P4_16 是两门语言。2016 年后基本都用 P4_16(语法更像 C,类型更严)。网上 2014-2016 的教程几乎都是 P4_14,照搬会 compile error。

  3. 可编程不等于无限制。每颗 ASIC 有”表项数上限、stage 数上限、寄存器位宽”。一份漂亮的 P4 程序在 BMv2(软件参考实现)跑通,到 Tofino 上可能编译不过——硬件资源不够。

  4. P4 不替你做控制面。P4 描述的是『进了包之后怎么办』。表里填什么(路由条目、ACL 规则)需要控制器通过 P4Runtime(gRPC API)下发,这块还是 SDN 控制器的活。

适用 vs 不适用场景

适用

  • 数据中心可编程交换机(Tofino、Mellanox Spectrum 部分型号)
  • 网络功能下沉:L4 负载均衡、防火墙、DDoS 防护跑到线速硬件
  • 网络遥测(INT):包级路径、延迟、队列状态采集
  • SmartNIC / DPU:Pensando、Nvidia BlueField 用 P4 描述转发卸载

不适用

  • 需要深度包检测、加密握手等复杂状态——没有循环、状态机表达力有限
  • 通用 CPU 已经够快的小型网络(家用、小企业)
  • 短期项目——硬件不便宜,工具链学习曲线陡

历史小故事(可跳过)

  • 2008 年:OpenFlow 1.0 发表,SDN 概念落地。控制面与数据面分离是大跃进,但数据面 match 字段还是写死。
  • 2013 年:Nick McKeown(OpenFlow 作者之一)和 Jennifer Rexford、David Walker 在 arXiv 挂出 P4 草案 1312.1719。
  • 2014 年:SIGCOMM CCR 正式发表。同年 Pat Bosshart 创立 Barefoot Networks。
  • 2016 年:P4_16 语言规范、P4 Language Consortium 成立。Tofino 1 流片。
  • 2019 年:Intel 以约 $5B 收购 Barefoot,Tofino 并入 Intel 数据中心 SoC 路线图。
  • 2022 年:P4 项目移交 Open Networking Foundation(ONF),成为开源标准。

学到什么

  1. 可编程性是一根链条,不是一个开关——SDN 解决控制面、P4 解决数据面,两段拼起来才是完整的可编程网络。
  2. 抽象的力量——PISA 模型把”千百种交换芯片”压缩成统一的 parser → tables → deparser,写一次 P4 跑多种硬件。
  3. 不图灵完备 ≠ 没用——P4 故意不要循环和递归,换来线速 Tbps 和确定时延。语言设计的”少即是多”。
  4. 学术 → 创业 → 巨头收购:McKeown 实验室出论文 → Bosshart 创业做芯片 → Intel 收购整合。10 年走完一个完整闭环。

延伸阅读

关联

  • openflow-2008 —— OpenFlow 让控制面可编程;P4 把可编程延伸到数据面
  • ethane-2007 —— SDN 的源头,先有它才有后来的可编程网络
  • llvm —— 都是『中间表示 + 多目标后端』的思想:P4 编译器把 P4 程序映射到 ASIC/FPGA/CPU
  • fielding-rest-2000 —— 都是用『约束推导』的方式定义一类系统的设计宪法

反向链接

  • ethane-2007 —— Ethane 2007 — 把企业网安全策略集中到一台中央电脑上
  • llvm —— LLVM — 模块化编译器框架
  • openflow-2008 —— OpenFlow 2008 — 把交换机的『分拣规则』搬到一台中央电脑上