P4 的概念已经了解了,现在动手搭建开发环境,跑通第一个 P4 程序。


一、P4 开发环境概述

P4 程序需要两个核心组件:

组件 作用 类比
p4c P4 编译器,把 .p4 源码编译成 JSON 类似 gcc 编译 C 语言
BMv2 (Behavioral Model v2) P4 软件交换机,运行编译后的程序 类似 Mininet 中的交换机

1.1 两种安装方式

方式 优点 缺点
Docker 省心,一键启动,不污染系统 需要 Docker,性能略低
Ubuntu 直装 性能好,调试方便 步骤多,可能踩坑

推荐先用 Docker 跑通流程,后续需要深入调试再考虑直装。


二、Docker 方式安装(推荐)

2.1 前置条件

1
2
3
4
5
6
7
8
# 确认 Docker 已安装
docker --version

# 如果没装,Ubuntu 下快速安装
sudo apt update
sudo apt install -y docker.io
sudo usermod -aG docker $USER
# 重新登录终端生效

2.2 拉取 P4 官方镜像

1
2
3
4
5
# P4 官方提供的 Docker 镜像(包含 p4c + BMv2)
docker pull p4lang/p4c

# 查看镜像
docker images | grep p4

2.3 启动容器

1
2
3
4
5
6
# 启动一个交互式容器,挂载当前目录
docker run -it --rm \
  -v $(pwd):/workdir \
  -w /workdir \
  --name p4-dev \
  p4lang/p4c bash

进入容器后,验证两个核心组件:

1
2
3
4
5
6
7
# 验证 p4c 编译器
p4c --version
# 输出类似:p4c from https://github.com/p4lang/p4c.git ...

# 验证 BMv2 软件交换机
simple_switch --version
# 输出类似:BMv2 simple_switch ...

两个命令都能正常输出版本号,说明环境搭建成功。


三、Ubuntu 直装方式

如果不想用 Docker,也可以直接在 Ubuntu 24.04 上安装。

3.1 安装依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
sudo apt update
sudo apt install -y \
  build-essential \
  cmake \
  g++ \
  libgmp-dev \
  libboost-dev \
  libboost-thread-dev \
  libboost-filesystem-dev \
  libevent-dev \
  libtool \
  libboost-program-options-dev \
  libboost-test-dev \
  libboost-all-dev \
  automake \
  pkg-config \
  libelf-dev \
  libffi-dev \
  python3 \
  python3-pip \
  python3-dev

3.2 安装 BMv2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 安装 PI (Protocol Independent) API
git clone https://github.com/p4lang/PI.git
cd PI
git submodule update --init --recursive
./autogen.sh
./configure
make -j$(nproc)
sudo make install
sudo ldconfig
cd ..

# 安装 BMv2
git clone https://github.com/p4lang/behavioral-model.git
cd behavioral-model
./autogen.sh
./configure
make -j$(nproc)
sudo make install
sudo ldconfig
cd ..

3.3 安装 p4c

1
2
3
4
5
6
7
git clone --recursive https://github.com/p4lang/p4c.git
cd p4c
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
cd ../..

3.4 验证安装

1
2
p4c --version
simple_switch --version

四、跑通第一个 P4 程序

4.1 获取官方示例

1
2
3
# 克隆 P4 官方教程仓库
git clone https://github.com/p4lang/tutorials.git
cd tutorials/exercises/basic

4.2 认识 basic.p4

打开 basic.p4,核心结构分三段:

// 1. Parser(包解析器):定义如何从原始字节中提取字段
parser MyParser(packet_in packet, ...) {
    state start {
        transition parse_ethernet;
    }
    state parse_ethernet {
        packet.extract(tmp_hdr.ethernet);
        transition select(tmp_hdr.ethernet.etherType) {
            0x0800: parse_ipv4;
            default: accept;
        }
    }
    state parse_ipv4 {
        packet.extract(tmp_hdr.ipv4);
        transition accept;
    }
}

// 2. Control(控制逻辑):定义转发行为
control MyIngress(inout headers hdr, ...) {
    action ipv4_forward(macAddr_t dstAddr, ...) {
        hdr.ethernet.dstAddr = dstAddr;
        standard_metadata.egress_spec = port;
    }
    table ipv4_lpm {
        key = { hdr.ipv4.dstAddr: lpm; }
        actions = { ipv4_forward; NoAction; }
    }
    apply {
        ipv4_lpm.apply();
    }
}

// 3. Deparser(包组装器):定义输出顺序
control MyDeparser(packet_out packet, ...) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}

4.3 编译并运行

1
2
3
4
5
6
7
8
# 编译 P4 程序
make run

# 这个命令会:
# 1. 用 p4c 编译 basic.p4 → basic.json
# 2. 启动 BMv2 软件交换机
# 3. 启动 Mininet 拓扑(2 台主机)
# 4. 配置转发表

4.4 验证转发

在 Mininet 中测试:

1
2
3
4
5
6
7
# 测试连通性
mininet> pingall
*** Ping: testing ping reachability
h1 h2
h1 -> h2
h2 -> h1
*** Results: 0% dropped (8/8 received)

pingall 成功,说明 P4 程序正确实现了 IP 转发。

4.5 查看流表

打开另一个终端,查看 BMv2 的转发表:

1
2
3
4
# 查看当前流表
simple_switch_CLI --thrift-port 9090 <<EOF
table_dump ipv4_lpm
EOF

输出类似:

mafia@2d98f85d5c27:/workdir/tutorials/exercises/basic$ simple_switch_CLI --thrift-port 9090 <<EOF
> table_dump ipv4_lpm
> EOF
Dumping entry ipv4_lpm 0 { 10.0.2.2/32 => port=2 (10 bytes) }

五、Docker 调试技巧

5.1 容器内网络问题

如果 Docker 容器内 Mininet 无法创建网络:

1
2
3
4
5
# 检查是否需要特权模式
docker run -it --rm --privileged \
  -v $(pwd):/workdir \
  -w /workdir \
  p4lang/p4c bash

5.2 端口映射

BMv2 的 Thrift 控制端口(默认 9090)需要映射出来:

1
2
3
4
5
docker run -it --rm \
  -p 9090:9090 \
  -v $(pwd):/workdir \
  -w /workdir \
  p4lang/p4c bash

5.3 保存容器状态

如果想保存调试环境:

1
2
3
4
5
# 查看容器 ID
docker ps -a

# 提交为新镜像
docker commit <container_id> my-p4-dev

六、踩坑记录

问题 原因 解决方案
p4c: command not found PATH 未配置 Docker 镜像已内置,直装需 sudo make install
simple_switch: error while loading shared libraries 动态库未刷新 sudo ldconfig
Mininet pingall 全部丢包 转发表未配置 检查 make run 是否成功,查看 s1-app.log
Docker 容器内无法创建 veth pair 权限不足 --privileged 参数
make run 报错 sudo: mininet: command not found 容器内未装 Mininet 安装:apt install mininet

七、今日学习总结

项目 内容
环境搭建 Docker 方式安装 p4c + BMv2
验证 p4c --versionsimple_switch --version
首个程序 编译并运行 basic.p4,pingall 验证成功
流表查看 使用 simple_switch_CLI 查看转发表
下一篇预告 P4 实验 1:深入理解 basic 程序的 parser / 控制流 / deparser 结构