例程拓扑

拓扑描述文件
以下为拓扑描述文件的Python脚本形式,JSON格式同理可参考之前的几篇文章。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
from p4utils.mininetlib.network_API import NetworkAPI
net = NetworkAPI()
# Network general options
net.setLogLevel('info')
# Network definition
net.addP4Switch('s1')
net.setP4Source('s1','./p4src/l2_basic_forwarding.p4')
net.setP4CliInput('s1', './s1-commands.txt')
net.addHost('h1')
net.addHost('h2')
net.addHost('h3')
net.addHost('h4')
net.addLink('s1', 'h1')
net.addLink('s1', 'h2')
net.addLink('s1', 'h3')
net.addLink('s1', 'h4')
# Assignment strategy
net.l2()
# Nodes general options
net.disablePcapDumpAll()
net.disableLogAll()
net.enableCli()
net.startNetwork()
|
交换机程序
main函数
1
2
3
4
5
6
7
8
9
10
11
|
#include <core.p4>
#include <v1model.p4>
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
|
定义头部
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// 定义占48个比特的MAC地址
typedef bit<48> macAddr_t;
// 定义链路层头部的各字段
header ethernet_t {
macAddr_t dstAddr;
macAddr_t srcAddr;
bit<16> etherType;
}
// 即使未使用到元数据,但同样需求定义
struct metadata {
}
// 实例化数据包头部
struct headers {
ethernet_t ethernet;
}
|
数据包解析
1
2
3
4
5
6
7
8
9
10
11
|
parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
// 解析提取数据包的头部,并填充进headers的ethernet中
packet.extract(hdr.ethernet);
// 解析器以accept结束,accept表示解析成功
transition accept;
}
}
|
检查校验和
1
2
3
|
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
|
入队列侧处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
action drop() {
// v1model提供的动作原语mark_to_drop
// 功能是将standard_metadata.egress_spec赋值为DROP_PORT
mark_to_drop(standard_metadata);
}
// 定义转发动作forward,将匹配值egress_port写入标准元数据中的出端口
action forward(bit<9> egress_port) {
standard_metadata.egress_spec = egress_port;
}
// 定义名为dmac的匹配表
table dmac {
// 精确匹配以太网头部的dstAddr字段
key = {
hdr.ethernet.dstAddr: exact;
}
// 定义动作集合
actions = {
forward;
drop;
NoAction;
}
// 定义匹配表的大小
size = 256;
// 定义默认动作
default_action = NoAction;
}
apply {
// 查询名为dmac的匹配表
dmac.apply();
}
}
|
出队列侧处理
1
2
3
4
5
|
control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}
|
计算校验和
1
2
3
|
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
|
封装数据包
1
2
3
4
5
6
7
|
control MyDeparser(packet_out packet, in headers hdr) {
apply {
// 使用emit函数重新封装headers中的ethernet头部
packet.emit(hdr.ethernet);
}
}
|
运行测试
在s1-commands.txt文件中填写匹配表项,使用P4Runtime同理可参考之前的几篇文章。
1
|
table-add <表的名字> <动作的名字> <匹配项> => <目标端口>
|
1
2
3
4
|
table_add dmac forward 00:00:0a:00:00:01 => 1
table_add dmac forward 00:00:0a:00:00:02 => 2
table_add dmac forward 00:00:0a:00:00:03 => 3
table_add dmac forward 00:00:0a:00:00:04 => 4
|
随后即可启动网络,进行测试。
1
2
3
|
sudo p4run
mininet > pingall
mininet > iperf h1 h4
|
