blob: 78cdc7bf750f1fe0da6f21e9a8608e82283c675e [file] [log] [blame]
Charles Chan6f149a92017-03-24 19:35:41 -07001#!/usr/bin/python
2
3import sys
4sys.path.append('..')
5from mininet.topo import Topo
6from mininet.net import Mininet
7from mininet.cli import CLI
8from mininet.log import setLogLevel
9from mininet.node import RemoteController, OVSBridge, Host
10from mininet.nodelib import NAT
11from ipaddress import ip_network
12from routinglib import BgpRouter
13from routinglib import RoutedHost
14
15class Trellis( Topo ):
16 "Trellis basic topology"
17
18 def __init__( self, *args, **kwargs ):
19 Topo.__init__( self, *args, **kwargs )
20
21 # Spines
22 s226 = self.addSwitch('s226', dpid='226')
23 s227 = self.addSwitch('s227', dpid='227')
24
25 # Leaves
26 s204 = self.addSwitch('s204', dpid='204')
27 s205 = self.addSwitch('s205', dpid='205')
28
29 # Switch Links
30 self.addLink(s226, s204)
31 self.addLink(s226, s205)
32 self.addLink(s227, s204)
33 self.addLink(s227, s205)
34
35 # NOTE avoid using 10.0.1.0/24 which is the default subnet of quaggas
36 # NOTE avoid using 00:00:00:00:00:xx which is the default mac of host behind upstream router
37 # IPv4 Hosts
38 h1 = self.addHost('h1', cls=DhcpClient, mac='00:aa:00:00:00:01')
39 h2 = self.addHost('h2', cls=DhcpClient, mac='00:aa:00:00:00:02')
40 h3 = self.addHost('h3', cls=DhcpClient, mac='00:aa:00:00:00:03')
41 h4 = self.addHost('h4', cls=DhcpClient, mac='00:aa:00:00:00:04')
42 self.addLink(h1, s204)
43 self.addLink(h2, s204)
44 self.addLink(h3, s205)
45 self.addLink(h4, s205)
46
47 # IPv6 Hosts
48 h1v6 = self.addHost('h1v6', cls=RoutedHost, mac='00:bb:00:00:00:01', ips=['2000::201/120'], gateway='2000::2ff')
49 h2v6 = self.addHost('h2v6', cls=RoutedHost, mac='00:bb:00:00:00:02', ips=['2000::202/120'], gateway='2000::2ff')
50 h3v6 = self.addHost('h3v6', cls=RoutedHost, mac='00:bb:00:00:00:03', ips=['2000::301/120'], gateway='2000::3ff')
51 h4v6 = self.addHost('h4v6', cls=RoutedHost, mac='00:bb:00:00:00:04', ips=['2000::302/120'], gateway='2000::3ff')
52 self.addLink(h1v6, s204)
53 self.addLink(h2v6, s204)
54 self.addLink(h3v6, s205)
55 self.addLink(h4v6, s205)
56
57 # DHCP server
58 dhcp = self.addHost('dhcp', cls=DhcpServer, mac='00:99:00:00:00:01', ips=['10.0.3.253/24'], gateway='10.0.3.254')
59 self.addLink(dhcp, s205)
60
61 # Control plane switch (for quagga fpm)
62 cs0 = self.addSwitch('cs0', cls=OVSBridge)
63
64 # Control plane NAT (for quagga fpm)
65 nat = self.addHost('nat', cls=NAT,
66 ip='172.16.0.1/12',
67 subnet=str(ip_network(u'172.16.0.0/12')), inNamespace=False)
68 self.addLink(cs0, nat)
69
70 # Internal Quagga bgp1
71 intfs = {'bgp1-eth0': {'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:02'},
72 'bgp1-eth1': {'ipAddrs': ['172.16.0.2/12']}}
73 bgp1 = self.addHost('bgp1', cls=BgpRouter,
74 interfaces=intfs,
75 quaggaConfFile='./bgpdbgp1.conf',
76 zebraConfFile='./zebradbgp1.conf')
77 self.addLink(bgp1, s205)
78 self.addLink(bgp1, cs0)
79
80 # External Quagga r1
81 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
82 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']},
83 'r1-eth2': {'ipAddrs': ['2000::9901/120']}}
84 r1 = self.addHost('r1', cls=BgpRouter,
85 interfaces=intfs,
86 quaggaConfFile='./bgpdr1.conf')
87 self.addLink(r1, s205)
88
89 # External IPv4 Host behind r1
90 rh1 = self.addHost('rh1', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
91 self.addLink(r1, rh1)
92
93 # External IPv6 Host behind r1
94 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
95 self.addLink(r1, rh1v6)
96
97topos = { 'trellis' : Trellis }
98
99class DhcpClient(Host):
100 def __init__(self, name, *args, **kwargs):
101 super(DhcpClient, self).__init__(name, **kwargs)
102 self.pidFile = '/run/dhclient-%s.pid' % self.name
103
104 def config(self, **kwargs):
105 super(DhcpClient, self).config(**kwargs)
106 self.cmd('ip addr flush dev %s' % self.defaultIntf())
107 self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
108
109 def terminate(self, **kwargs):
110 self.cmd('kill -9 `cat %s`' % self.pidFile)
111 self.cmd('rm -rf %s' % self.pidFile)
112 super(DhcpClient, self).terminate()
113
114class DhcpServer(RoutedHost):
115 binFile = '/usr/sbin/dhcpd'
116 pidFile = '/run/dhcp-server/dhcpd.pid'
117 configFile = './dhcpd.conf'
118
119 def config(self, **kwargs):
120 super(DhcpServer, self).config(**kwargs)
121 self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
122
123 def terminate(self, **kwargs):
124 self.cmd('kill -9 `cat %s`' % self.pidFile)
125 self.cmd('rm -rf %s' % self.pidFile)
126 super(DhcpServer, self).terminate()
127
128if __name__ == "__main__":
129 setLogLevel('debug')
130 topo = Trellis()
131
132 net = Mininet(topo=topo, controller=None)
133 net.addController(RemoteController('c0', ip='192.168.56.11'))
134 net.addController(RemoteController('c1', ip='192.168.56.12'))
135 net.addController(RemoteController('c2', ip='192.168.56.13'))
136
137 net.start()
138 CLI(net)
139 net.stop()