当 P4 遇上 Mininet

前言

上一篇《P4,走进网络数据平面可编程》简单介绍了 P4 ,并通过命令行的方式搭建 P4 的网络拓扑,搭建过程需要敲很多命令,比较烦琐,这篇我们将通过 python 脚本搭建。
本文涉及的代码在:https://github.com/cykun/p4-mininet

相关介绍

Mininet

在这里插入图片描述
Mininet 是一个网络模拟器,或者更准确地说是一个网络模拟编排系统。它在单个 Linux 内核上运行一组终端主机、交换机、路由器和链接。它使用轻量级虚拟化使单个系统看起来像一个完整的网络,运行相同的内核、系统和用户代码。
通过 Mininet ,我们可以写 python 脚本来搭建网络拓扑,但 Mininet 本身是不支持 bmv2 交换机的,因此需要重写 Mininet下的 Switch 和 Host 类,好在 p4lang 已经提供了这些脚本,只要提取出来就能用了:https://github.com/p4lang/tutorials/tree/master/utils

在这里插入图片描述
p4_mininet.py:继承 Mininet 的 Switch 和 Host 类,使其支持 bmv2。
p4runtime_switch.py: 继承 P4Switch 类,在其基础上,支持 grpc 调用。

实验拓扑

在这里插入图片描述
拓扑比较简单,两个虚拟主机连接同一台 bmv2 交换机。

编写拓扑脚本,取名为 run_exercise.py

from mininet.net import Mininet
from mininet.topo import Topo
from mininet.log import setLogLevel, info
from mininet.cli import CLI

from p4_mininet import P4Switch, P4Host
from p4runtime_switch import P4RuntimeSwitch

import argparse
from time import sleep

parser = argparse.ArgumentParser(description='Mininet demo')
parser.add_argument('--behavioral-exe', help='Path to behavioral executable',
                    type=str, action="store", required=True)
parser.add_argument('--thrift-port', help='Thrift server port for table updates',
                    type=int, action="store", default=9090)
parser.add_argument('--num-hosts', help='Number of hosts to connect to switch',
                    type=int, action="store", default=2)
parser.add_argument('--mode', choices=['l2', 'l3'], type=str, default='l3')
parser.add_argument('--json', help='Path to JSON config file',
                    type=str, action="store", required=True)
parser.add_argument('--pcap-dump', help='Dump packets on interfaces to pcap files',
                    type=str, action="store", required=False, default=False)

args = parser.parse_args()

class SingleSwitchTopo(Topo):
    def __init__(self, sw_path, json_path, thrift_port, pcap_dump, n, **opts):
        # Initialize topology and default options
        Topo.__init__(self, **opts)
        switch = self.addSwitch('s1',
                                sw_path = sw_path,
                                json_path = json_path,
                                thrift_port = thrift_port,
                                pcap_dump = pcap_dump)
        for h in range(n):
            host = self.addHost('h%d' % (h + 1),
                                ip = "10.0.0.%d/24" % (h + 1),
                                mac = '00:04:00:00:00:%02x' %h)
            self.addLink(host, switch)
def main():
    num_hosts = args.num_hosts
    mode = args.mode
    topo = SingleSwitchTopo(args.behavioral_exe,
                            args.json,
                            args.thrift_port,
                            args.pcap_dump,
                            num_hosts)
    net = Mininet(topo = topo,
                  host = P4Host,
                  switch = P4RuntimeSwitch,
                  controller = None)
    net.start()
    sw_mac = ["00:aa:bb:00:00:%02x" % n for n in range(num_hosts)]
    sw_addr = ["10.0.%d.1" % n for n in range(num_hosts)]
    for n in range(num_hosts):
        h = net.get('h%d' % (n + 1))
        if mode == "l2":
            h.setDefaultRoute("dev eth0")
        else:
            h.setARP(sw_addr[n], sw_mac[n])
            h.setDefaultRoute("dev eth0 via %s" % sw_addr[n])
    for n in range(num_hosts):
        h = net.get('h%d' % (n + 1))
        h.describe()
    sleep(1)
    print("Ready !")
    CLI( net )
    net.stop()
if __name__ == '__main__':
    setLogLevel( 'info' )

Mininet 的 switch 改成 P4RuntimeSwitch,本质调用 bmv2 交换机。
SingleSwitchTopo 继承 Topo ,星型拓扑,内部添加一台 bmv2 交换机,主机数目自定,默认是2台,ip 前缀都为 10.0.0.0/24
写过 Mininet 脚本的应该对这个比较熟悉。

编写执行脚本,命名为 run.sh

BMV2_SWITCH_EXE="simple_switch_grpc"

p4c --target bmv2 --arch v1model --p4runtime-files demo.p4info.txt --std p4-16 -o build p4src/demo.p4
sudo ./run_exercise.py --behavioral-exe simple_switch_grpc --json build/demo.json

这里的 demo.p4 沿用上一篇 《P4,走进网络数据平面可编程》 的 P4代码。首先先用 p4c 编译 p4src 下的 demo.p4 源码,编译后的文件放在 build 文件夹下,接着运行 run_exercise.py 脚本。

执行运行脚本

cyquen@cyquen-virtual-machine:~/P4/p4_mininet$ ./run.sh 
[sudo] password for cyquen: 
*** 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.
simple_switch_grpc -i 1@s1-eth1 -i 2@s1-eth2 --nanolog ipc:///tmp/bm-0-log.ipc --device-id 0 build/demo.json --thrift-port 9090 -- --grpc-server-addr 0.0.0.0:50051
P4 switch s1 has been started.

**********
h1
default interface: h1-eth0	10.0.0.1	00:04:00:00:00:00
**********
**********
h2
default interface: h2-eth0	10.0.0.2	00:04:00:00:00:01
**********
Ready !
*** Starting CLI:
mininet> 

看到了熟悉的界面😁,但这里的交换机已经不是 Openflow 了,观察到它执行了这条命令

simple_switch_grpc -i 1@s1-eth1 -i 2@s1-eth2 --nanolog ipc:///tmp/bm-0-log.ipc --device-id 0 build/demo.json --thrift-port 9090 -- --grpc-server-addr 0.0.0.0:50051

跟我们手动敲命令行来搭 bmv2 是差不多,只不过它自动帮我们执行了。

向交换机的路由表中下发路由

这里我们先写一个 commands.txt 文件来保存要下发的命令,拓扑就两台虚拟主机,一台 ip 为 10.0.0.1,另一台 10.0.0.2,分别接到交换机的 1 口和 2 口。

table_add ipv4_lpm ipv4_forward 10.0.0.1/32 => 1
table_add ipv4_lpm ipv4_forward 10.0.0.2/32 => 2

之后可以通过 p4lang 提供的 runtime_CLI.py 脚本,用一下命令输入:

cyquen@cyquen-virtual-machine:~/P4/p4_mininet$ ./runtime_CLI.py < commands.txt 
Obtaining JSON from switch...
Done
Control utility for runtime P4 table manipulation
RuntimeCmd: Adding entry to lpm match table ipv4_lpm
match key:           LPM-0a:00:00:01/32
action:              ipv4_forward
runtime data:        00:01
Entry has been added with handle 0
RuntimeCmd: Adding entry to lpm match table ipv4_lpm
match key:           LPM-0a:00:00:02/32
action:              ipv4_forward
runtime data:        00:02
Entry has been added with handle 1
RuntimeCmd: 

这样就完成下发路由操作。

测试交换机的三层转发

在 Mininet 控制台下执行

mininet> xterm h1 h2

调出 h1 和 h2 控制台
在这里插入图片描述
测试 h1 ,h2 连通性:h2 执行 ./receive.py ,h1 执行 ./send.py 10.0.0.2 hello
在这里插入图片描述
结束!

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值