CLI 参考¶
p4net 命令启动拓扑后会进入交互式命令行,可在其中执行主机命令、测试连通性、配置交换机表项、读取计数器和管理组播组。安装 p4net 后即可使用该命令。
启动命令行¶
拓扑文件必须定义模块级变量 topology,其值为 Topology 实例。文件还可以定义 setup(net),在网络启动后、进入交互命令行前执行。IPv4 转发示例 包含这两部分。
每个文件作为独立的 Python 模块加载,可以定义辅助类和 dataclass,用于构建拓扑或执行 setup(net)。
使用安装了 p4net 的 Python 环境启动,两种入口等效:
两种入口接受相同的参数:
usage: p4net [-h] [--no-shell] [--unsafe] [--log-dir LOG_DIR]
[--pcap-dir PCAP_DIR] [--extra-compile-arg ARG] [-v]
topology_file
| 参数 | 作用 |
|---|---|
-h、--help |
显示启动参数说明并退出。 |
--no-shell |
启动网络、运行 setup(net)(如有),等待 SIGINT 或 SIGTERM 后关闭网络。 |
--unsafe |
启动前跳过 Topology.validate()。 |
--log-dir DIR |
将 BMv2 日志写入 DIR,默认新建临时目录。 |
--pcap-dir DIR |
将 BMv2 按端口抓取的数据包保存到 DIR,不指定时不抓包。 |
--extra-compile-arg ARG |
向 p4c 传递额外参数,可重复指定。值以 - 开头时使用 --extra-compile-arg=-DDEBUG 这样的形式。 |
-v、--verbose |
将日志级别设为 INFO,-vv 设为 DEBUG,默认级别为 WARNING。 |
指定 --pcap-dir 后,可在 Topology.add_switch() 中设置 pcap_enabled=False,关闭某台交换机的抓包。
虚拟环境与 sudo¶
如果系统的 sudo 用 secure_path 替换了 PATH,它可能找不到当前环境中的 p4net、Python 或外部工具。上面的启动命令通过 env 传入当前 PATH,使两个入口都使用当前环境。
以下示例使用主机 h1、h2 和交换机 s1。IPv6 命令需要主机配置 IPv6 地址。表名、动作名、计数器和控制器元数据由加载的 P4 程序决定。p4net> 后的每条命令均在一行内输入。
网络命令¶
help 与 help <command>¶
help 列出可用命令,指定主题后显示对应语法和说明:
查询节点命令的帮助时,使用字面占位名,例如 help <host> ping 或 help <switch> table add。
exit、quit¶
退出命令行并关闭网络。在空输入行上按 Ctrl-D 效果相同。
status¶
显示网络是否运行、主机和交换机数量,以及 BMv2 日志目录。
hosts¶
列出每台主机配置的首个 IPv4 地址、首个 IPv6 地址及接口名。地址保留前缀长度,未配置的地址以 - 表示。
p4net> hosts
name primary_ip primary_ip6 interfaces
h1 10.0.0.1/24 fd00::1/64 h1-eth0
h2 10.0.0.2/24 fd00::2/64 h2-eth0
switches¶
列出每台交换机的 gRPC 地址、BMv2 进程 PID 和日志文件路径。
pingall [count] [timeout]¶
在配置了主 IPv4 地址的主机之间逐方向执行 ping。矩阵列出全部主机,行表示源主机,列表示目标主机。count 默认 1,timeout 默认 2.0 秒,取值范围见 ping 参数说明。1 表示成功,X 表示失败,- 表示自身。未配置 IPv4 的主机所涉及的方向不执行测试,以 ? 表示。
pingall6 [count] [timeout]¶
在配置了主 IPv6 地址的主机之间执行 IPv6 ping,排除未配置 IPv6 的主机。参数规则和输出格式与 pingall 相同。如果没有主机配置 IPv6,返回 (no IPv6-equipped hosts in topology)。
topology graph [path] [layout=LR|TB|BT|RL] [format=png|svg|pdf|dot]¶
校验拓扑并生成图。不指定 path 时显示 DOT 源码,指定路径时按所选格式写入文件,并返回文件的绝对路径。layout 设置 Graphviz 的 rankdir,默认 LR,format 默认 png。
format=dot 直接写入源码,其他格式需要系统安装 dot。
主机命令¶
<host> ping <target> [count] [timeout]¶
从指定主机发起 ping。目标是拓扑中的主机名时,解析为该主机的主 IPv4 地址。其他目标直接传给 ping,字符串中包含 : 时使用 IPv6。按主机名发起 IPv6 ping 使用 ping6。
默认 count=1、timeout=2.0 秒。count 必须为正整数,表示回显请求的次数上限。timeout 必须有限且非负,可以使用小数秒,例如 0.25,并传给 ping -W。超时值为 0 时,由进程的整体等待时限控制退出。
p4net 根据次数、超时和默认一秒的发送间隔计算整体等待时限,上限为 2,147,483 秒。收到至少一次应答就显示 OK,部分丢包也算成功。没有应答或执行失败时显示 FAIL。
<host> ping6 <target> [count] [timeout]¶
执行 IPv6 ping,默认参数与 ping 相同。主机名解析为该主机的主 IPv6 地址,未配置时会报错,也可以直接指定 IPv6 地址。
<host> xterm¶
在主机命名空间内打开运行 bash 的 xterm。需要安装 xterm,并能通过 DISPLAY 连接图形会话。网络会跟踪该进程,并在关闭时终止它。
PID 随实际进程变化。
<host> cmd <argv>...¶
在主机命名空间内执行命令,超时为 30 秒。引号按 shlex 规则将文本组合为参数,随后直接执行命令。需要管道或重定向等 Shell 功能时,使用 sh -c '...'。
先显示 stdout,再逐行显示带 [stderr] 前缀的 stderr。退出状态非零时,末尾追加 [exit N]。
<host> ifconfig¶
在主机命名空间内执行 ip -br addr,显示其 stdout。
交换机命令¶
<switch> log¶
显示交换机的 BMv2 日志文件路径。--log-dir 使用相对路径时,这里也显示相对路径。
<switch> table list¶
列出已加载 P4Info 中的表,每行显示表名,以及匹配字段的类型和名称:
<switch> table dump <table>¶
显示指定表中的表项。值按字段位宽格式化:32 位显示为 IPv4 地址,128 位显示为 IPv6 地址,48 位显示为 MAC 地址,其他位宽显示为十进制数。匹配类型决定是否附带前缀长度、掩码或范围,动作参数也按位宽格式化。
表中只有一条 IPv4 转发表项时,输出如下:
p4net> s1 table dump MyIngress.ipv4_lpm
#0
table: MyIngress.ipv4_lpm
match: {'hdr.ipv4.dstAddr': '10.0.0.1/32'}
action: MyIngress.set_egress_port
params: {'port': '1'}
空表返回 (table 'MyIngress.ipv4_lpm' is empty)。
<switch> table add <table> match: <kv>... action: <name> [params: <kv>...] [priority: <n>]¶
插入表项。match:、action:、params: 和 priority: 分别标记各部分。匹配字段和动作参数用 key=value 表示,多项之间可用空格或逗号分隔。
p4net> s1 table add MyIngress.ipv4_lpm match: hdr.ipv4.dstAddr=10.0.0.5/32 action: MyIngress.set_egress_port params: port=2
ok
匹配值的格式由目标交换机 P4Info 中的字段类型决定:
| 匹配类型 | 示例 |
|---|---|
| exact、optional | key=123 |
| lpm | key=10.0.0.0/24 |
| ternary | key=0x1200&&&0xff00 |
| range | key=100..200 |
各部分可以使用字段支持的值格式,包括十进制或十六进制整数、IP 地址和 MAC 地址。组合值内不加空格,需要空格时用引号包住整个值。
LPM 前缀长度非零时,前缀外的位必须为零。例如 10.0.0.5/24 会显示 EncodingError,应使用 10.0.0.0/24。/0 表示通配,值仍需通过格式和位宽校验,再省略该匹配字段。
ternary 掩码非零时,掩码为零的位置,值也必须为零。例如 0xab&&&0xf0 会显示 EncodingError,应使用 0xa0&&&0xf0。掩码全零表示通配,值和掩码仍需通过格式和位宽校验,再省略该匹配字段,值非零也一样。
range 的下界不能大于上界。上下界相等时匹配单个值,顺序颠倒时显示 EncodingError。
16 位 range 字段可用 key=0..65535 匹配全部值。table dump 不显示这样的通配字段,表仍需要优先级。
仅含 exact/LPM 字段的表不填写 priority:,含 optional、ternary 或 range 字段的表在插入时需要优先级,省略 optional 字段作通配匹配的条目也一样。优先级必须是 1 到 2147483647 之间的整数,零、负数和越界值会在发送请求前报 EncodingError。下面的表按目标 MAC 做 exact 匹配、按源 MAC 做 ternary 匹配,并对 EtherType 做 range 匹配:
p4net> s1 table add MyIngress.l2_match match: hdr.ethernet.dstAddr=00:00:00:00:00:02,hdr.ethernet.srcAddr=00:00:00:00:00:00&&&ff:ff:ff:ff:ff:00,hdr.ethernet.etherType=0x88b0..0x88bf action: MyIngress.set_egress_port params: port=2 priority: 17
ok
<switch> table del <table> match: <kv>... [priority: <n>]¶
按匹配键删除表项,匹配值格式与 table add 相同,也使用 值&&&掩码 和 下界..上界。含 optional、ternary 或 range 字段的表必须用 priority: N 指定条目的原优先级,通配条目也一样。优先级必须是 1 到 2147483647 之间的整数。缺少必需的优先级时显示 EncodingError。仅含 exact/LPM 字段的表不填写 priority:。
<switch> table clear <table>¶
删除表中所有表项,返回 cleared N entries。
<switch> counter [reset] <name> [<index>]¶
读取间接计数器,或用 reset 清零。指定索引时,读取结果为 pkts=N bytes=M。不指定索引时,以表格列出返回的计数单元,没有结果则显示 (no populated cells)。实际记录包数还是字节数由 P4 计数器类型决定,不指定索引的清零操作会清空所有返回的单元。
p4net> s1 counter reset MyIngress.ingress_pkts 1
ok
p4net> s1 counter MyIngress.ingress_pkts 1
pkts=0 bytes=0
<switch> mcast list¶
按组 ID 顺序列出组播组,格式为 <id>: [<port>, ...],没有组时显示 (no multicast groups)。
<switch> mcast add <id> <port,port,...>¶
创建组播组,指定复制端口。
<switch> mcast del <id>¶
删除指定的组播组。
<switch> packet send <hex_payload> [metadata: <k>=<v>[,<k>=<v>...]]¶
将 PacketOut 放入 P4Runtime StreamChannel 的发送队列。载荷是完整数据包的十六进制字符串,元数据名称和位宽来自 P4Info 中的 packet_out 头,未提供的字段填零。
CPU punt 示例 提供了控制器包头和 CPU 端口配置,可使用以下命令发送 PacketOut:
<switch> packet listen [count=N] [timeout=T]¶
收集命令运行期间新到达的 PacketIn。收到 count 个包或达到总超时后返回,默认 count=1、timeout=10.0 秒。count 必须为正整数,timeout 必须有限、非负且不超过系统等待上限,0 表示不等待。超时时会显示已经收集到的包。
每个包输出一行,先按名称排序显示 [name=value] 元数据字段,再显示十六进制内容。十六进制内容超过 64 个字符时截断并追加 ...。没有包到达时,返回 (no packets within 3.0s)。
键盘快捷键¶
Ctrl-C:取消正在编辑的输入行。- 空行上的
Ctrl-D:退出命令行并关闭网络。 ↑/↓:浏览历史记录,历史保存在~/.p4net_history。Tab:补全网络命令、主机名、交换机名,以及ping、table等节点命令。