P4语言编程快速开始 实践一
参考:P4语言快速开始 感谢杨老师的分享!
前言及P4程序请参考原文,本文主要是对文章中的两个动手实例的实践记录。
1.通过behavioral-model运行simple_router样例
执行命令:
cd p4factory/targets/simple_router
make bm
sudo ./behavioral-model
在本地启动一个behavior-model,默认使用PD RPC服务的地址为127.0.0.1:9090
当在同一台宿主机上启动多个bmv2时,可以使用
--pd-server=IP:PORT
指定不同的端口,以防止端口占用冲突。更多参数可以使用-h参数查看CLI帮助。
执行./behavioral-model
之后显示如下:
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 2 length 107; first bytes:
33330000 00fffffffbfffffffaffffffcb ffffffaf6d3effffff8c ffffff86ffffffdd600b
new packet, len : 107, ingress : 2
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb924000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 0 length 107; first bytes:
33330000 00fffffffb1213 ffffff91ffffffdefffffffe30 ffffff86ffffffdd6008
new packet, len : 107, ingress : 0
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb928000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 6 length 107; first bytes:
33330000 00fffffffbfffffffa51 fffffff66e382d ffffff86ffffffdd600e
new packet, len : 107, ingress : 6
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb91c000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 1 length 107; first bytes:
33330000 00fffffffb1effffffee 1943ffffffc0ffffffb8 ffffff86ffffffdd6003
new packet, len : 107, ingress : 1
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb934000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 7 length 107; first bytes:
33330000 00fffffffb3e7a ffffffb10bffffff97ffffffe8 ffffff86ffffffdd600a
new packet, len : 107, ingress : 7
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb920000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 4 length 107; first bytes:
33330000 00fffffffbffffff92ffffffe4 4a34ffffff9fffffffeb ffffff86ffffffdd600b
new packet, len : 107, ingress : 4
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb914000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 5 length 107; first bytes:
33330000 00fffffffb2e33 672a7cffffffef ffffff86ffffffdd600f
new packet, len : 107, ingress : 5
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb918000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 0 length 107; first bytes:
33330000 00fffffffb4a23 66ffffffe1724a ffffff86ffffffdd600d
new packet, len : 107, ingress : 0
rmt proc returns 0
Packet in on port 6 length 107; first bytes:
33330000 00fffffffbffffffde59 680dffffffc046 ffffff86ffffffdd600e
new packet, len : 107, ingress : 6
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb928000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb91c000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 2 length 107; first bytes:
33330000 00fffffffbffffffd2ffffffd8 19ffffffce47ffffff99 ffffff86ffffffdd6009
new packet, len : 107, ingress : 2
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb924000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 3 length 107; first bytes:
33330000 00fffffffbfffffff6ffffffdb 21fffffffbffffffa97f ffffff86ffffffdd600d
new packet, len : 107, ingress : 3
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb930000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 4 length 107; first bytes:
33330000 00fffffffbffffffdaffffffec ffffffd4ffffff8fffffffed33 ffffff86ffffffdd600a
new packet, len : 107, ingress : 4
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb914000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
Packet in on port 5 length 107; first bytes:
33330000 00fffffffb1221 447dffffffd3ffffff94 ffffff86ffffffdd6006
new packet, len : 107, ingress : 5
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
one checksum is incorrect
Applying table ipv4_lpm
Lookup key for ipv4_lpm:
ipv4_dstAddr: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
total length for outgoing meta: 24
copying metadata
deparsing standard_metadata
deparsing routing_metadata
queuing system: packet dequeued
egress port set to 0
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
payload length: 93
extracting metadata
extracting all metadata for 0x7fb918000940
Applying table send_frame
Lookup key for send_frame:
standard_metadata_egress_port: 0x00000000,
table miss, applying default action
no default action, doing nothing
total length for outgoing pkt: 107
deparsing ethernet
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[107]: Port[0]
In client_init
之后运行./run_cli.bash
脚本,访问simple_router的运行时API:
root@FZUSDNLab:/home/sdn/p4factory/targets/simple_router# ./run_cli.bash
Using default thrift server and port localhost:9090
(Cmd) ?
Documented commands (type help <topic>):
========================================
EOF dump_table mc_node_destroy
add_entry exit mc_node_update
add_entry_with_member get_first_entry_handle modify_entry
add_entry_with_selector get_next_entry_handles quit
add_member help set_default_action
add_member_to_group mc_associate_node show_actions
create_group mc_dissociate_node show_entry
delete_entry mc_mgrp_create show_tables
delete_group mc_mgrp_destroy
delete_member mc_node_create
(Cmd)
2.通过run_demo.bash脚本 运行启动simple_router示例
注:如果之前进行了第一步,请重启再重新开启虚拟端口,方法是进入p4factory/tools目录下,执行:
./veth_setup.sh
进入simple_router目录,执行run_demo.bash脚本使用mininet构建网络拓扑:
./run_demo.bash
执行后效果如下:
root@FZUSDNLab:/home/sdn/p4factory/targets/simple_router# ./run_demo.bash
*** Creating network
*** Adding hosts:
h1 h2
*** Adding switches:
s1
*** Adding links:
(h1, s1) (h2, s1)
*** Configuring hosts
h1 h2
*** Starting controller
*** Starting 1 switches
s1 Starting P4 switch s1
/home/sdn/p4factory/targets/simple_router/behavioral-model --name s1 --dpid 0000000000000001 -i s1-eth1 -i s1-eth2 --listener 127.0.0.1:11111 --pd-server 127.0.0.1:22222
switch has been started
**********
h1
default interface: eth0 10.0.0.10 00:04:00:00:00:00
**********
**********
h2
default interface: eth0 10.0.1.10 00:04:00:00:00:01
**********
Ready !
*** Starting CLI:
mininet>
注意,此时PD服务端口不再是9090,直接运行run_cli.bash脚本无法访问simple_router的运行时CLI。
有两种方法解决这个问题,一种是修改bash脚本,这里请参照原文。
另外一种是直接采用-c参数指定端口号,笔者采用的是这种方法:
./run_cli.bash -c 127.0.0.1:22222
效果如下:
root@ubuntu:/home/wasdns/p4factory/targets/simple_router# ./run_cli.bash -c 127.0.0.1:22222
(Cmd)
查看此时P4交换机中的流表:
(Cmd) show_tables
forward
ipv4_lpm
send_frame
(Cmd) dump_table forward
No entry handle found
(Cmd) dump_table ipv4_lpm
No entry handle found
(Cmd) dump_table send_frame
No entry handle found
(Cmd)
此时P4交换机中有三张流表,但是都没有内容。
证明了在只有数据平面的情况下,不同host之间是没有办法正常通信的。此时也有两种方法充当控制平面。
(1)通过运行run_add_demo_entries.bash脚本下发流表。其内容如下:
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry send_frame 1 rewrite_mac 00:aa:bb:00:00:00" -c localhost:22222
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry send_frame 2 rewrite_mac 00:aa:bb:00:00:01" -c localhost:22222
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry forward 10.0.0.10 set_dmac 00:04:00:00:00:00" -c localhost:22222
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry forward 10.0.1.10 set_dmac 00:04:00:00:00:01" -c localhost:22222
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry ipv4_lpm 10.0.0.10 32 set_nhop 10.0.0.10 1" -c localhost:22222
python ../../cli/pd_cli.py -p simple_router -i p4_pd_rpc.simple_router -s $PWD/tests/pd_thrift:$PWD/../../testutils -m "add_entry ipv4_lpm 10.0.1.10 32 set_nhop 10.0.1.10 2" -c localhost:22222
执行./run_add_demo_entries.bash
为P4交换机增添表项。
执行之后如下:
Inserted entry with handle 0
Inserted entry with handle 1
Inserted entry with handle 0
Inserted entry with handle 1
Inserted entry with handle 0
Inserted entry with handle 1
在CLI中查看流表:
1.forward:
(Cmd) dump_table forward
Entry handle 0
key:
routing_metadata_nhop_ipv4: 0x0a00000a (10 0 0 10),
action:
set_dmac
action data:
dmac: 0x000400000000,
Entry handle 1
key:
routing_metadata_nhop_ipv4: 0x0a00010a (10 0 1 10),
action:
set_dmac
action data:
dmac: 0x000400000001,
(Cmd)
2.ipv4_lpm
(Cmd) dump_table ipv4_lpm
Entry handle 0
key:
ipv4_dstAddr: 0x0a00000a (10 0 0 10),
prefix_length:
32
action:
set_nhop
action data:
nhop_ipv4: 0x0a00000a (10 0 0 10), port: 0x00000001 (0 0 0 1),
Entry handle 1
key:
ipv4_dstAddr: 0x0a00010a (10 0 1 10),
prefix_length:
32
action:
set_nhop
action data:
nhop_ipv4: 0x0a00010a (10 0 1 10), port: 0x00000002 (0 0 0 2),
(Cmd)
3.send_frame
(Cmd) dump_table send_frame
Entry handle 0
key:
standard_metadata_egress_port: 0x00000001 (0 0 0 1),
action:
rewrite_mac
action data:
smac: 0x00aabb000000,
Entry handle 1
key:
standard_metadata_egress_port: 0x00000002 (0 0 0 2),
action:
rewrite_mac
action data:
smac: 0x00aabb000001,
(Cmd)
在mininet中能够ping通:
(2)编写command.txt,并通过behavioral-model/tools/runtimeCLI下发流表。
在运行之前,请先安装bmv2(behavioral-model),可以参考我的另外一篇博客:P4 前端编译器p4c-bm、后端编译器bmv2命令安装 make error问题
command.txt内容如下:
table_set_default send_frame _drop
table_set_default forward _drop
table_set_default ipv4_lpm _drop
table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00
table_add send_frame rewrite_mac 2 => 00:aa:bb:00:00:01
table_add forward set_dmac 10.0.0.10 => 00:04:00:00:00:00
table_add forward set_dmac 10.0.1.10 => 00:04:00:00:00:01
table_add ipv4_lpm set_nhop 10.0.0.10/32 => 10.0.0.10 1
table_add ipv4_lpm set_nhop 10.0.1.10/32 => 10.0.1.10 2
原文中命令有误,是无法执行的,这里先暂时使用第一种方法,后续会补充上。
从这些流表下发方法中也可以认识到以下几点:
a)没有控制面下发的流表,仅数据面无法工作。
b)控制面下发的流表必须与P4程序中定义的table相吻合,从匹配字段(match-field)到动作(action).
c)P4定义的数据面所对应的控制面,可以是控制器、运行时CLI,也可以是SAI等。
2017/1/15