SDN

POX 控制器

2018-10-09  本文已影响90人  顽强的猫尾草

默认拓扑

如果我们不指定控制器直接运行 Mininet 提供给我们的默认拓扑:

sudo mn

你会发现节点间是 ping 得通的,因为默认的控制器进行 l2 层学习获得了流表。

要使用 POX 的远程交换机,你可以这样做:

$ cd ~/pox
$ ./pox.py forwarding.l2_learning

在另一个窗口,启动 Mininet 连接到“远程”控制器(这实际上是在本地运行,但 Mininet 的控制范围之外):

$ sudo mn --controller=remote, ip=127.0.0.1, port=6633

注意,这些其实都是默认的 IP 地址和端口值。

要进入命令行模式的话:

python pox.py openflow.of_01 py

下发流表(因为我想让两边 ping 通,所以应该配正反两条流表规则,以下只是单方向的):

POX> from pox.lib.addresses import IPAddr
POX> from pox.lib.addresses import EthAddr
POX> import pox.openflow.libopenflow_01 as of
POX> core.openflow.connections.keys()
[1]
POX> msg=of.ofp_flow_mod()
POX> msg.priority=3    # 数字越大, 优先级越高
POX> msg.match.nw_src="10.0.0.1"
POX> msg.match.in_port=2
POX> msg.actions.append(of.ofp_action_output(port=1))
POX> core.openflow.connections[1].send(msg)    # 这个 1 就是 connections.keys() 返回的 1

反方向的流表只要交换一下出入端口就 OK 了。

看一看 Mininet 这边,在配流表之前,ping 不通:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
mininet> pingall
*** Ping: testing ping reachability
h1 -> X 
h2 -> X 
*** Results: 100% dropped (0/2 received)

配了单方向流表以后,依然 ping 不通:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=4.827s, table=0, n_packets=0, n_bytes=0, idle_age=4, priority=5,in_port=1 actions=output:2
mininet> h1 ping h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
From 10.0.0.1 icmp_seq=1 Destination Host Unreachable
From 10.0.0.1 icmp_seq=2 Destination Host Unreachable
From 10.0.0.1 icmp_seq=3 Destination Host Unreachable
^C
--- 10.0.0.2 ping statistics ---
5 packets transmitted, 0 received, +3 errors, 100% packet loss, time 4000ms

配了双向的以后:

mininet> dpctl dump-flows
*** s1 ------------------------------------------------------------------------
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=151.371s, table=0, n_packets=15, n_bytes=630, idle_age=22, priority=5,in_port=1 actions=output:2
 cookie=0x0, duration=4.423s, table=0, n_packets=0, n_bytes=0, idle_age=4, priority=5,in_port=2 actions=output:1
mininet> h1 ping h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.208 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.035 ms
^C
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.035/0.121/0.208/0.087 ms
mininet> pingall
*** Ping: testing ping reachability
h1 -> h2 
h2 -> h1 
*** Results: 0% dropped (2/2 received)

成功了!

【注】交换机的端口号一般就是从 1 按顺序的,可以在启动 Mininet 以后新打开一个窗口用下面的命令查看都有哪些端口:

$ sudo ovs-vsctl show
0072de5e-fdb2-4e99-91e7-4f5d33acfa10
    Bridge "s1"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        Controller "ptcp:6654"
        fail_mode: secure
        Port "s1-eth2"    # 端口 2
            Interface "s1-eth2"
        Port "s1"
            Interface "s1"
                type: internal
        Port "s1-eth1"    # 端口 1
            Interface "s1-eth1"
    ovs_version: "2.5.4"

POX 控制器里指定端口时不能用字符串,只能用数字,"s1-eth1" 和 "s1-eth2" 写成 1 和 2 就好。

(至于端口对应着哪台主机,可以从网页上看,不知道有没有什么直观的从命令行上就可以查看的方式?或者由 API 指定?)
问题解决,这个顺序是按照 AddLink 的顺序,比如 h1 和 h2 先后与 s1 连,那么 h1 就是端口 1 上的,h2 是端口 2 上的。当然也可以直接在 API 中指定,如:

# specify a different port to connect host 5 to switch 1
net.addLink( h5, s1, 1, 9 )    # h5 的 port 1 连接 s1 的 port 9 (注意如果没定义端口 1 就去定义端口 2 会报错)

另外如果不正常退出 Mininet 或 POX 的话,会对下一次运行产生影响,所以最好用 exit 退出 Mininet,用 Ctrl-D 退出 POX。不然就要 sudo mn -c 来清理 Mininet 的缓存,并手动 kill POX 的进程。

POX 的 API 可以查看这里,是相对很全的了。

自定义拓扑

利用 Mininet 的 Python API 可以很方便地开发各种拓扑以及连接远程控制器。给出一个示例:

#!/usr/bin/python
#coding=utf-8 
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel
from mininet.cli import CLI
from mininet.node import RemoteController

class SingleSwitchTopo(Topo):
        def __init__(self, **opts):
                Topo.__init__(self, **opts)

                switch1 = self.addSwitch( 's1' )    # 添加交换机到拓扑中
                switch2 = self.addSwitch( 's2' )
                switch3 = self.addSwitch( 's3' )
                host1 = self.addHost( 'h1' )    # 添加主机到拓扑中
                host2 = self.addHost( 'h2' )    # 添加主机到拓扑中

                self.addLink( host1, switch1 )
                self.addLink( host2, switch2 )    # 添加双向连接
                self.addLink( switch2, switch1 )
                self.addLink( switch2, switch3 )
                self.addLink( switch3, switch1 )

def simpleTest():
        topo = SingleSwitchTopo()
        net = Mininet(topo)    # 主要类来创建和管理网络
        mycontroller = RemoteController("c0", ip = "127.0.0.1", port=6633)    # 创建远程控制器 (控制器的命名最好是 "c数字", 否则可能报错)
        net.controllers = [mycontroller]
        net.start()    # 启动拓扑网络
        print "Dumping host connections"
        dumpNodeConnections(net.hosts)    # 输出指定的网络信息
        print "Testing network connectivity"
        net.pingAll()    # 所有节点彼此测试互连
        # CLI(net)    # 进入 mininet> 提示符 
        net.stop()    # 停止网络


if __name__ == '__main__':
        setLogLevel('info')  # 设置 Mininet 默认输出级别,设置 info 它将提供一些有用的信息
        simpleTest()

更多 API 参见:http://mininet.org/api/annotated.html

上一篇下一篇

猜你喜欢

热点阅读