blob: e08e5a6993eabc4c99caae482688ec4d330142db [file] [log] [blame]
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -08001#!/usr/bin/python
2import os
3import re
4from optparse import OptionParser
5from ipaddress import ip_network
6from mininet.node import RemoteController, OVSBridge, Host
7from mininet.link import TCLink
8from mininet.log import setLogLevel
9from mininet.net import Mininet
10from mininet.topo import Topo
11from mininet.nodelib import NAT
12from mininet.cli import CLI
13
14from routinglib import BgpRouter, RoutedHost
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080015from trellislib import DhcpServer, TaggedRoutedHost, DualHomedRoutedHost, DualHomedTaggedRoutedHost, DhcpClient, Dhcp6Client, DhcpServer, Dhcp6Server, TrellisHost
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080016
17# Parse command line options and dump results
18def parseOptions():
19 "Parse command line options"
20 parser = OptionParser()
21 parser.add_option( '--dhcp', dest='dhcp', type='int', default=0,
22 help='Configure hosts with dhcp or not' )
23 parser.add_option( '--routers', dest='routers', type='int', default=0,
24 help='Configure external routers or not in the topology' )
25 parser.add_option( '--ipv6', dest='ipv6', type='int', default=0,
26 help='Configure hosts with ipv6 or not' )
27 parser.add_option( '--ipv4', dest='ipv4', type='int', default=1,
28 help='Configure hosts with ipv4 or not' )
29 parser.add_option( '--onos-ip', dest='onosIp', type='str', default='',
30 help='IP address list of ONOS instances, separated by comma(,). Overrides --onos option' )
31
32 ( options, args ) = parser.parse_args()
33 return options, args
34
35opts, args = parseOptions()
36
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080037class ComcastLeafSpineFabric(Topo):
38
39 spines = dict()
40 leafs = dict()
41 hosts_dict = dict()
42
43 def createIpv4Hosts(self, dhcp):
44
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080045 h1 = self.addHost('h1v4', cls=TrellisHost,
46 mac='00:aa:00:00:00:01', ips=['10.1.0.1/24'],
47 gateway='10.1.0.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080048 self.addLink(h1, self.leafs[0])
49 self.hosts_dict['h1v4'] = h1
50
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080051 h2 = self.addHost('h2v4', cls=TrellisHost,
52 mac='00:aa:00:00:01:01', ips=['10.1.10.1/24'],
53 gateway='10.1.10.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080054 self.addLink(h2, self.leafs[0])
55 self.hosts_dict['h2v4'] = h2
56
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080057 h3 = self.addHost('h3v4', cls=TrellisHost,
58 mac='00:aa:00:00:00:02', ips=['10.2.0.1/24'],
59 gateway='10.2.0.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080060 self.addLink(h3, self.leafs[1])
61 self.hosts_dict['h3v4'] = h3
62
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080063 h4 = self.addHost('h4v4', cls=TrellisHost,
64 mac='00:aa:00:00:00:03', ips=['10.2.30.1/24'],
65 gateway='10.2.30.254', dhcpClient=dhcp,
66 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080067 self.addLink(h4, self.leafs[1])
68 self.addLink(h4, self.leafs[2])
69 self.hosts_dict['h4v4'] = h4
70
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080071 h5 = self.addHost('h5v4', cls=TrellisHost,
72 mac='00:aa:00:00:00:04', ips=['10.2.20.1/24'],
73 gateway='10.2.20.254', dhcpClient=dhcp, vlan=30,
74 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080075 self.addLink(h5, self.leafs[1])
76 self.addLink(h5, self.leafs[2])
77 self.hosts_dict['h5v4'] = h5
78
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080079 h6 = self.addHost('h6v4', cls=TrellisHost,
80 mac='00:aa:00:00:00:05', ips=['10.2.10.1/24'],
81 gateway='10.2.10.254', dhcpClient=dhcp, vlan=20)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080082 self.addLink(h6, self.leafs[2])
83 self.hosts_dict['h6v4'] = h6
84
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080085 h7 = self.addHost('h7v4', cls=TrellisHost,
86 mac='00:aa:00:00:01:05', ips=['10.2.40.1/24'],
87 gateway='10.2.40.254', dhcpClient=dhcp, vlan=40)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080088 self.addLink(h7, self.leafs[2])
89 self.hosts_dict['h7v4'] = h7
90
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080091 h8 = self.addHost('h8v4', cls=TrellisHost,
92 mac='00:aa:00:00:00:06', ips=['10.3.0.1/24'],
93 gateway='10.3.0.254', dhcpClient=dhcp, vlan=30)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080094 self.addLink(h8, self.leafs[3])
95 self.hosts_dict['h8v4'] = h8
96
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080097 h9 = self.addHost('h9v4', cls=TrellisHost,
98 mac='00:aa:00:00:00:07', ips=['10.3.10.1/24'],
99 gateway='10.3.10.254', dhcpClient=dhcp, vlan=40,
100 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800101 self.addLink(h9, self.leafs[3])
102 self.addLink(h9, self.leafs[4])
103 self.hosts_dict['h9v4'] = h9
104
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800105 h10 = self.addHost('h10v4', cls=TrellisHost,
106 mac='00:aa:00:00:00:08', ips=['10.3.30.1/24'],
107 gateway='10.3.30.254', dhcpClient=dhcp, vlan=40,
108 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800109 self.addLink(h10, self.leafs[3])
110 self.addLink(h10, self.leafs[4])
111 self.hosts_dict['h10v4'] = h10
112
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800113 h11 = self.addHost('h11v4', cls=TrellisHost,
114 mac='00:aa:00:00:00:0a', ips=['10.3.20.1/24'],
115 gateway='10.3.20.254', dhcpClient=dhcp, vlan=40)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800116 self.addLink(h11, self.leafs[4])
117 self.hosts_dict['h11v4'] = h11
118
119 return
120
121 def createIpv6Hosts(self, dhcp):
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800122
123 h1 = self.addHost('h1v6', cls=TrellisHost,
124 mac='00:aa:00:00:00:01', ips=["1000::3fe/120"],
125 gateway='1000::3ff', dhcpClient=dhcp)
126 self.addLink(h1, self.leafs[0])
127 self.hosts_dict['h1v6'] = h1
128
129 h2 = self.addHost('h2v6', cls=TrellisHost,
130 mac='00:aa:00:00:01:01', ips=['1001::3fe/120'],
131 gateway='1001::3ff', dhcpClient=dhcp)
132 self.addLink(h2, self.leafs[0])
133 self.hosts_dict['h2v6'] = h2
134
135 h3 = self.addHost('h3v6', cls=TrellisHost,
136 mac='00:aa:00:00:00:02', ips=['1002::3fe/120'],
137 gateway='1002::3ff', dhcpClient=dhcp)
138 self.addLink(h3, self.leafs[1])
139 self.hosts_dict['h3v6'] = h3
140
141 h4 = self.addHost('h4v6', cls=TrellisHost,
142 mac='00:aa:00:00:00:03', ips=['1003::3fe/120'],
143 gateway='1003::3ff', dhcpClient=dhcp,
144 dualHomed=True)
145 self.addLink(h4, self.leafs[1])
146 self.addLink(h4, self.leafs[2])
147 self.hosts_dict['h4v6'] = h4
148
149 h5 = self.addHost('h5v6', cls=TrellisHost,
150 mac='00:aa:00:00:00:04', ips=['1004::3fe/120'],
151 gateway='1004::3ff', dhcpClient=dhcp, vlan=30,
152 dualHomed=True)
153 self.addLink(h5, self.leafs[1])
154 self.addLink(h5, self.leafs[2])
155 self.hosts_dict['h5v6'] = h5
156
157 h6 = self.addHost('h6v6', cls=TrellisHost,
158 mac='00:aa:00:00:00:05', ips=['1005::3fe/120'],
159 gateway='1005::3ff', dhcpClient=dhcp, vlan=20)
160 self.addLink(h6, self.leafs[2])
161 self.hosts_dict['h6v6'] = h6
162
163 h7 = self.addHost('h7v6', cls=TrellisHost,
164 mac='00:aa:00:00:01:05', ips=['1006::3fe/120'],
165 gateway='1006::3ff', dhcpClient=dhcp, vlan=40)
166 self.addLink(h7, self.leafs[2])
167 self.hosts_dict['h7v6'] = h7
168
169 h8 = self.addHost('h8v6', cls=TrellisHost,
170 mac='00:aa:00:00:00:06', ips=['1007::3fe/120'],
171 gateway='1007::3ff', dhcpClient=dhcp, vlan=30)
172 self.addLink(h8, self.leafs[3])
173 self.hosts_dict['h8v6'] = h8
174
175 h9 = self.addHost('h9v6', cls=TrellisHost,
176 mac='00:aa:00:00:00:07', ips=['1008::3fe/120'],
177 gateway='1008::3ff', dhcpClient=dhcp, vlan=40,
178 dualHomed=True)
179 self.addLink(h9, self.leafs[3])
180 self.addLink(h9, self.leafs[4])
181 self.hosts_dict['h9v6'] = h9
182
183 h10 = self.addHost('h10v6', cls=TrellisHost,
184 mac='00:aa:00:00:00:08', ips=['1009::3fe/120'],
185 gateway='1009::3ff', dhcpClient=dhcp, vlan=40,
186 dualHomed=True)
187 self.addLink(h10, self.leafs[3])
188 self.addLink(h10, self.leafs[4])
189 self.hosts_dict['h10v6'] = h10
190
191 h11 = self.addHost('h11v6', cls=TrellisHost,
192 mac='00:aa:00:00:00:0a', ips=['1010::3fe/120'],
193 gateway='1010::3ff', dhcpClient=dhcp, vlan=40)
194 self.addLink(h11, self.leafs[4])
195 self.hosts_dict['h11v6'] = h11
196
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800197 return
198
199 '''
200 Creates the topology employed by Comcast which is a 2x5
201 leaf spine traffic.
202
203 S1 S2
204
205 L1 L2 L3 L4 L5
206
207 Where L2/L3 and L4/L5 are paired switches.
208 Parameters for this topology :
209 dhcp = True/False : set up dhcp servers
210 routers = True/False : set up external routers
211 '''
212 def __init__(self, dhcp=False, routers=False, ipv4=False, ipv6=False, **opts):
213 Topo.__init__(self, **opts)
214
215 # TODO: support IPv6 hosts
216 linkopts = dict( bw=10 )
217
218 spine = 2
219 leaf = 5
220
221 # Create spine switches
222 for s in range(spine):
223 self.spines[s] = self.addSwitch('spine10%s' % (s + 1), dpid = "00000000010%s" % (s + 1) )
224
225 # Create leaf switches
226 for ls in range(leaf):
227 self.leafs[ls] = self.addSwitch('leaf%s' % (ls + 1), dpid = "00000000000%s" % ( ls + 1) )
228
229 # connecting leaf and spines, leafs 1-5 have double links
230 for s in range( spine ):
231 spine_switch = self.spines[s]
232
233 for ls in range( leaf ):
234 leaf_switch = self.leafs[ls]
235
236 self.addLink( spine_switch, leaf_switch, **linkopts )
237 if ls > 0:
238 self.addLink( spine_switch, leaf_switch, **linkopts )
239
240 # connect paired leafs
241 self.addLink(self.leafs[1], self.leafs[2], **linkopts)
242 self.addLink(self.leafs[3], self.leafs[4], **linkopts)
243
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800244 # create dhcp servers
245 if dhcp:
246 if ipv4:
247 dhcp4 = self.addHost( 'dhcp', cls=TrellisHost,
248 mac="00:bb:00:00:00:01", ips=["10.0.3.253/24"],
249 gateway="10.0.3.254", dhcpServer=True)
250 self.addLink(self.spines[1], dhcp4, **linkopts)
251 if ipv6:
252 dhcp6 = self.addHost( 'dhcp', cls=TrellisHost,
253 mac="00:bb:00:00:00:02", ips=["2000::3fd/120"],
254 gateway="2000::3ff")
255 self.addLink(self.spines[1], dhcp4, **linkopts)
256 # creatte quagga routers
257 if routers:
258 print("NYI (quagga)!")
259
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800260 # create hosts
261 if ipv6:
262 self.createIpv6Hosts(dhcp)
263
264 if ipv4:
265 self.createIpv4Hosts(dhcp)
266
267 if not ipv4 and not ipv6:
268 print("No hosts were created!")
269
270def config( opts ):
271
272 dhcp = bool(opts.dhcp)
273 routers = bool(opts.routers)
274 ipv6 = bool(opts.ipv6)
275 ipv4 = bool(opts.ipv4)
276
277 if opts.onosIp != '':
278 controllers = opts.onosIp.split( ',' )
279 else:
280 controllers = ['127.0.0.1']
281 topo = ComcastLeafSpineFabric(dhcp=dhcp, routers=routers, ipv6=ipv6,
282 ipv4=ipv4)
283
284 net = Mininet( topo=topo, link=TCLink, build=False,
285 controller=None, autoSetMacs=True )
286 i = 0
287 for ip in controllers:
288 net.addController( "c%s" % ( i ), controller=RemoteController, ip=ip )
289 i += 1
290
291 net.build()
292 net.start()
293 CLI( net )
294 net.stop()
295
296
297if __name__ == '__main__':
298 setLogLevel('info')
299 config(opts)
300 os.system('sudo mn -c')
301