I'm new to Mininet and POX controller to simulate SDN. I want to create the following network, using Mininet Python API:
My objective is to let each host/router send packets to all the other hosts/routers. To do that, I used ip route command. This is my Python code for creating the network:
#!/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()
This is the output of net command on Mininet CLI:
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
I have two issues:
1- Running pingall on mininet CLI, gives this output:
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)
Why can't routers send packet to "opposite" routers and hosts ? I do not understand why hosts can send packet to router instead.
2- Using two entries with same destination in the "routing table", for example:
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"))
produces this warning in the output:
RTNETLINK answers: File exists
and alternative route paths can't be used. I want to let h1 send packets to host h4 by passing through router r2, but also by passing through router r3. How can I fix "multiple paths" with ip route command?
Let's start with this:
Why can't
r1pingh4?h4is10.3.0.10.r1has the following route table:Requests to
h4at10.3.0.10are going to route via10.101.0.2(r3), with a source address of10.101.0.1.r3has the following route table:So
r3is going to route to10.3.0.10via10.102.0.2. That'sr4, which has this route table:And here we have a problem:
r4has no route back to10.101.0.0/24, nor does it have a default gateway. This causes two problems:r4will be unable to reply to those ICMP echo request packets. Attempts to contact any system on the10.101.0.0/24network will fail:Because of the
rp_filtersettings onr4......incoming packets from a network that is not reachable will simply be dropped, so requests stop at
r4and never get passed on toh4.The solution here is to give
r4a route back to10.101.0.0/24hosts. The obvious choices seems to be viar3, so:With that new route in place, we can ping
h4fromr1:When making a routing decision, the kernel wants to find a single matching route. You can't have multiple routes to the same destination using different gateways without some way to differentiate the two. First, what behavior do you want with these two routes? A typical solution is to assign the routes different weights, so that one will be used by preference, but it it becomes unavailable (e.g., the interface goes down), the secondary route will be selected. For example: