簡體   English   中英

使用 Mininet/POX 模擬帶有路由器的網絡

[英]Simulate a network with routers using Mininet/POX

我是 Mininet 和 POX 控制器來模擬 SDN 的新手。 我想使用 Mininet Python API 創建以下網絡:

網絡拓撲結構

我的目標是讓每個主機/路由器向所有其他主機/路由器發送數據包。 為此,我使用了ip route命令。 這是我用於創建網絡的 Python 代碼:

#!/usr/bin/python
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.node import RemoteController
from mininet.log import setLogLevel, info
from mininet.cli import CLI

class LinuxRouter(Node):
    def config(self, **params):
        super(LinuxRouter, self).config(**params)
        self.cmd('sysctl net.ipv4.ip_forward=1')

    def terminate(self):
        self.cmd('sysctl net.ipv4.ip_forward=0')
        super(LinuxRouter, self).terminate()


class NetworkTopo(Topo):
    def build(self, **_opts):
        # Add 4 routers in four different subnets
        r1 = self.addHost('r1', cls=LinuxRouter, ip='10.0.0.1/24')
        r2 = self.addHost('r2', cls=LinuxRouter, ip='10.1.0.1/24')
        r3 = self.addHost('r3', cls=LinuxRouter, ip='10.2.0.1/24')
        r4 = self.addHost('r4', cls=LinuxRouter, ip='10.3.0.1/24')

        # Add 2 switches
        s1 = self.addSwitch('s1')
        s2 = self.addSwitch('s2')
        s3 = self.addSwitch('s3')
        s4 = self.addSwitch('s4') 

        # Add host-switch links in the same subnet
        self.addLink(s1,
                     r1,
                     intfName2='r1-eth1',
                     params2={'ip': '10.0.0.1/24'})

        self.addLink(s2,
                     r2,
                     intfName2='r2-eth1',
                     params2={'ip': '10.1.0.1/24'})

        self.addLink(s3,
                     r3,
                     intfName2='r3-eth1',
                     params2={'ip': '10.2.0.1/24'})

        self.addLink(s4,
                     r4,
                     intfName2='r4-eth1',
                     params2={'ip': '10.3.0.1/24'})

        # Add router-router links in new subnets for the router-router connections
        self.addLink(r1,
                     r2,
                     intfName1='r1-eth2',
                     intfName2='r2-eth2',
                     params1={'ip': '10.100.0.1/24'},
                     params2={'ip': '10.100.0.2/24'})
    
        self.addLink(r1,
                     r3,
                     intfName1='r1-eth3',
                     intfName2='r3-eth2',
                     params1={'ip': '10.101.0.1/24'},
                     params2={'ip': '10.101.0.2/24'})
    
        self.addLink(r3,
                     r4,
                     intfName1='r3-eth3',
                     intfName2='r4-eth2',
                     params1={'ip': '10.102.0.1/24'},
                     params2={'ip': '10.102.0.2/24'})
    
        self.addLink(r2,
                     r4,
                     intfName1='r2-eth3',
                     intfName2='r4-eth3',
                     params1={'ip': '10.103.0.1/24'},
                     params2={'ip': '10.103.0.2/24'})

        # Adding hosts specifying the default route
        h1 = self.addHost(name='h1',
                          ip='10.0.0.10/24',
                          defaultRoute='via 10.0.0.1')
        h2 = self.addHost(name='h2',
                          ip='10.1.0.10/24',
                          defaultRoute='via 10.1.0.1')
    
        h3 = self.addHost(name='h3',
                          ip='10.2.0.10/24',
                          defaultRoute='via 10.2.0.1')
                      
        h4 = self.addHost(name='h4',
                          ip='10.3.0.10/24',
                          defaultRoute='via 10.3.0.1')

        # Add host-switch links
        self.addLink(h1, s1)
        self.addLink(h2, s2)
        self.addLink(h3, s3)
        self.addLink(h4, s4)


def run():
    topo = NetworkTopo()
    net = Mininet(topo=topo, controller=RemoteController)

    # Add routing for reaching networks that aren't directly connected
    info(net['r1'].cmd("ip route add 10.1.0.0/24 via 10.100.0.2 dev r1-eth2"))
    info(net['r1'].cmd("ip route add 10.2.0.0/24 via 10.101.0.2 dev r1-eth3"))
    info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.101.0.2 dev r1-eth3"))
    info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.100.0.2 dev r1-eth2"))

    info(net['r2'].cmd("ip route add 10.0.0.0/24 via 10.100.0.1 dev r2-eth2"))
    info(net['r2'].cmd("ip route add 10.3.0.0/24 via 10.103.0.2 dev r2-eth3"))
    info(net['r2'].cmd("ip route add 10.2.0.0/24 via 10.103.0.2 dev r2-eth3"))
    info(net['r2'].cmd("ip route add 10.2.0.0/24 via 10.100.0.1 dev r2-eth2"))

    info(net['r3'].cmd("ip route add 10.0.0.0/24 via 10.101.0.1 dev r3-eth2"))
    info(net['r3'].cmd("ip route add 10.3.0.0/24 via 10.102.0.2 dev r3-eth3"))
    info(net['r3'].cmd("ip route add 10.1.0.0/24 via 10.102.0.2 dev r3-eth3"))
    info(net['r3'].cmd("ip route add 10.1.0.0/24 via 10.101.0.1 dev r3-eth2"))

    info(net['r4'].cmd("ip route add 10.1.0.0/24 via 10.103.0.1 dev r4-eth3"))
    info(net['r4'].cmd("ip route add 10.2.0.0/24 via 10.102.0.1 dev r4-eth2"))    
    info(net['r4'].cmd("ip route add 10.0.0.0/24 via 10.102.0.1 dev r4-eth2"))
    info(net['r4'].cmd("ip route add 10.0.0.0/24 via 10.103.0.1 dev r4-eth3"))    

    net.start()
    CLI(net)
    net.stop()


if __name__ == '__main__':
    setLogLevel('info')
    run()

這是 Mininet CLI 上net命令的輸出:

h1 h1-eth0:s1-eth2
h2 h2-eth0:s2-eth2
h3 h3-eth0:s3-eth2
h4 h4-eth0:s4-eth2
r1 r1-eth1:s1-eth1 r1-eth2:r2-eth2 r1-eth3:r3-eth2
r2 r2-eth1:s2-eth1 r2-eth2:r1-eth2 r2-eth3:r4-eth3
r3 r3-eth1:s3-eth1 r3-eth2:r1-eth3 r3-eth3:r4-eth2
r4 r4-eth1:s4-eth1 r4-eth2:r3-eth3 r4-eth3:r2-eth3
s1 lo:  s1-eth1:r1-eth1 s1-eth2:h1-eth0
s2 lo:  s2-eth1:r2-eth1 s2-eth2:h2-eth0
s3 lo:  s3-eth1:r3-eth1 s3-eth2:h3-eth0
s4 lo:  s4-eth1:r4-eth1 s4-eth2:h4-eth0
c0

我有兩個問題:

1- 在 mininet CLI 上運行 pingall,給出以下輸出:

mininet> pingall
*** Ping: testing ping reachability
h1 -> h2 h3 h4 r1 r2 r3 r4 
h2 -> h1 h3 h4 r1 r2 r3 r4 
h3 -> h1 h2 h4 r1 r2 r3 r4 
h4 -> h1 h2 h3 r1 r2 r3 r4 
r1 -> h1 h2 h3 X r2 r3 X 
r2 -> h1 h2 X h4 r1 X r4 
r3 -> h1 X h3 h4 r1 X r4 
r4 -> X h2 h3 h4 X r2 r3 
*** Results: 14% dropped (48/56 received)

為什么路由器不能將數據包發送到“相反的”路由器和主機? 我不明白為什么主機可以將數據包發送到路由器。

2-在“路由表”中使用兩個具有相同目的地的條目,例如:

info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.101.0.2 dev r1-eth3"))
info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.100.0.2 dev r1-eth2"))

在輸出中產生此警告:

RTNETLINK answers: File exists

並且不能使用替代路由路徑。 我想讓 h1 通過路由器 r2 向主機 h4 發送數據包,但也通過路由器 r3。 如何使用 ip route 命令修復“多路徑”?

讓我們從這個開始:

r1 -> h1 h2 h3 X r2 r3 X 

為什么r1不能 ping h4 h410.3.0.10 r1具有以下路由表:

mininet> r1 ip route
10.0.0.0/24 dev r1-eth1 proto kernel scope link src 10.0.0.1
10.1.0.0/24 via 10.100.0.2 dev r1-eth2
10.2.0.0/24 via 10.101.0.2 dev r1-eth3
10.3.0.0/24 via 10.101.0.2 dev r1-eth3 metric 100
10.3.0.0/24 via 10.100.0.2 dev r1-eth2 metric 200
10.100.0.0/24 dev r1-eth2 proto kernel scope link src 10.100.0.1
10.101.0.0/24 dev r1-eth3 proto kernel scope link src 10.101.0.1

10.3.0.10h4的請求將通過10.101.0.2 ( r3 ) 路由,源地址為10.101.0.1

r3具有以下路由表:

mininet> r3 ip route
10.0.0.0/24 via 10.101.0.1 dev r3-eth2
10.1.0.0/24 via 10.102.0.2 dev r3-eth3 metric 100
10.1.0.0/24 via 10.101.0.1 dev r3-eth2 metric 200
10.2.0.0/24 dev r3-eth1 proto kernel scope link src 10.2.0.1
10.3.0.0/24 via 10.102.0.2 dev r3-eth3
10.101.0.0/24 dev r3-eth2 proto kernel scope link src 10.101.0.2
10.102.0.0/24 dev r3-eth3 proto kernel scope link src 10.102.0.1

所以r3將通過10.102.0.2 10.3.0.10 那是r4 ,它有這個路由表:

mininet> r4 ip route
10.0.0.0/24 via 10.102.0.1 dev r4-eth2 metric 100
10.0.0.0/24 via 10.103.0.1 dev r4-eth3 metric 200
10.1.0.0/24 via 10.103.0.1 dev r4-eth3
10.2.0.0/24 via 10.102.0.1 dev r4-eth2
10.3.0.0/24 dev r4-eth1 proto kernel scope link src 10.3.0.1
10.102.0.0/24 dev r4-eth2 proto kernel scope link src 10.102.0.2
10.103.0.0/24 dev r4-eth3 proto kernel scope link src 10.103.0.2

這里我們有一個問題: r4沒有返回10.101.0.0/24的路由,也沒有默認網關。 這會導致兩個問題:

  1. r4將無法回復那些 ICMP 回顯請求數據包。 嘗試聯系10.101.0.0/24網絡上的任何系統都將失敗:

     mininet> r4 ping 10.101.0.1 ping: connect: Network is unreachable
  2. 由於r4上的rp_filter設置...

     mininet> r4 sysctl -a -r rp_filter net.ipv4.conf.all.arp_filter = 0 net.ipv4.conf.all.rp_filter = 2 net.ipv4.conf.default.arp_filter = 0 net.ipv4.conf.default.rp_filter = 2 net.ipv4.conf.lo.arp_filter = 0 net.ipv4.conf.lo.rp_filter = 2 net.ipv4.conf.r4-eth1.arp_filter = 0 net.ipv4.conf.r4-eth1.rp_filter = 2 net.ipv4.conf.r4-eth2.arp_filter = 0 net.ipv4.conf.r4-eth2.rp_filter = 2 net.ipv4.conf.r4-eth3.arp_filter = 0 net.ipv4.conf.r4-eth3.rp_filter = 2

    ...來自無法訪問的網絡的傳入數據包將被簡單地丟棄,因此請求在r4停止並且永遠不會傳遞到h4

這里的解決方案是給r4一條返回10.101.0.0/24主機的路由。 顯而易見的選擇似乎是通過r3 ,所以:

mininet> r4 ip route add 10.101.0.0/24 via 10.102.0.1

有了這條新路由,我們可以從r1 ping h4

mininet> r1 ping -c3 h4
PING 10.3.0.10 (10.3.0.10) 56(84) bytes of data.
64 bytes from 10.3.0.10: icmp_seq=1 ttl=62 time=1.15 ms
64 bytes from 10.3.0.10: icmp_seq=2 ttl=62 time=0.160 ms
64 bytes from 10.3.0.10: icmp_seq=3 ttl=62 time=0.048 ms

--- 10.3.0.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.048/0.451/1.147/0.493 ms

在“路由表”中使用具有相同目標的兩個條目...在輸出中產生此警告: RTNETLINK answers: File exists

在做出路由決策時,內核希望找到一個匹配的路由。 如果沒有某種方式來區分兩者,您就不能使用不同的網關有多個路由到同一個目的地。 首先,您希望這兩條路線有什么行為? 一個典型的解決方案是為路由分配不同的權重,以便優先使用一個,但它變得不可用(例如,接口關閉),將選擇輔助路由。 例如:

    info(net['r1'].cmd("ip route add 10.1.0.0/24 via 10.100.0.2 dev r1-eth2"))
    info(net['r1'].cmd("ip route add 10.2.0.0/24 via 10.101.0.2 dev r1-eth3"))
    info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.101.0.2 dev r1-eth3 metric 100"))
    info(net['r1'].cmd("ip route add 10.3.0.0/24 via 10.100.0.2 dev r1-eth2 metric 200"))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM