blob: 9e2cda9664df3f486c84d739025ebea40e1cff3c [file] [log] [blame]
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -08001#!/usr/bin/python
2
3import sys
4sys.path.append('..')
5from mininet.topo import Topo
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -08006from mininet.cli import CLI
7from mininet.log import setLogLevel
8from mininet.node import RemoteController, OVSBridge, Host, OVSSwitch
9from mininet.link import TCLink
10from mininet.nodelib import NAT
11from ipaddress import ip_network
12from routinglib import BgpRouter
13from routinglib import RoutedHost, RoutedHost6
Andrea Campanellaba96c612018-04-23 12:09:34 +020014from trellislib import DhcpClient, Dhcp6Client, Dhcp4and6Client, DhcpRelay, DhcpServer, Dhcp6Server
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080015from trellislib import DualHomedDhcpClient
Andrea Campanellaba96c612018-04-23 12:09:34 +020016from trellislib import DualHomedDhcp4and6Client
Ray Milkey1df260d2018-03-28 11:52:34 -070017from trellislib import get_mininet, parse_trellis_args, set_up_zebra_config
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080018from functools import partial
19
Ray Milkey1df260d2018-03-28 11:52:34 -070020
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080021class Trellis( Topo ):
Ray Milkey1df260d2018-03-28 11:52:34 -070022 """Trellis HAG topology"""
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080023
24 def __init__( self, *args, **kwargs ):
25 Topo.__init__( self, *args, **kwargs )
26
27 # Spines
28 s226 = self.addSwitch('s226', dpid='226')
29 s227 = self.addSwitch('s227', dpid='227')
30
31 # Leaves
32 s203 = self.addSwitch('s203', dpid='203')
33 s204 = self.addSwitch('s204', dpid='204')
34 s205 = self.addSwitch('s205', dpid='205')
35 s206 = self.addSwitch('s206', dpid='206')
36
37 # Leaf-Spine Links
38 self.addLink(s226, s203)
39 self.addLink(s226, s203)
40 self.addLink(s226, s204)
41 self.addLink(s226, s204)
42 self.addLink(s226, s205)
43 self.addLink(s226, s205)
44 self.addLink(s226, s206)
45 self.addLink(s226, s206)
46 self.addLink(s227, s203)
47 self.addLink(s227, s203)
48 self.addLink(s227, s204)
49 self.addLink(s227, s204)
50 self.addLink(s227, s205)
51 self.addLink(s227, s205)
52 self.addLink(s227, s206)
53 self.addLink(s227, s206)
54
55 # Leaf-Leaf Links
56 self.addLink(s203, s204)
57 self.addLink(s205, s206)
58
59 # NOTE avoid using 10.0.1.0/24 which is the default subnet of quaggas
60 # NOTE avoid using 00:00:00:00:00:xx which is the default mac of host behind upstream router
61 # IPv4 Hosts
62 h1 = self.addHost('h1', cls=DhcpClient, mac='00:aa:00:00:00:01')
63 h2 = self.addHost('h2', cls=DhcpClient, mac='00:aa:00:00:00:02')
64 h3 = self.addHost('h3', cls=DhcpClient, mac='00:aa:00:00:00:03')
65 h4 = self.addHost('h4', cls=DhcpClient, mac='00:aa:00:00:00:04')
Andrea Campanellaba96c612018-04-23 12:09:34 +020066 h5 = self.addHost('h5', cls=DhcpClient, mac='00:aa:00:00:00:05')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080067 self.addLink(h1, s204)
68 self.addLink(h2, s204)
69 self.addLink(h3, s205)
70 self.addLink(h4, s205)
Andrea Campanellaba96c612018-04-23 12:09:34 +020071 self.addLink(h5, s203)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080072
73 # IPv6 Hosts
74 h1v6 = self.addHost('h1v6', cls=Dhcp6Client, mac='00:bb:00:00:00:01')
75 h2v6 = self.addHost('h2v6', cls=Dhcp6Client, mac='00:bb:00:00:00:02')
76 h3v6 = self.addHost('h3v6', cls=Dhcp6Client, mac='00:bb:00:00:00:03')
77 h4v6 = self.addHost('h4v6', cls=Dhcp6Client, mac='00:bb:00:00:00:04')
Andrea Campanellaba96c612018-04-23 12:09:34 +020078 h5v6 = self.addHost('h5v6', cls=Dhcp6Client, mac='00:bb:00:00:00:05')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080079 self.addLink(h1v6, s204)
80 self.addLink(h2v6, s204)
81 self.addLink(h3v6, s205)
82 self.addLink(h4v6, s205)
Andrea Campanellaba96c612018-04-23 12:09:34 +020083 self.addLink(h5v6, s203)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080084
Andrea Campanellaba96c612018-04-23 12:09:34 +020085 # Dual-homed IPv4 and IPv6 Host on 203-204
86 dh1 = self.addHost('dh1', cls=DualHomedDhcp4and6Client, mac='00:cc:00:00:00:01')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080087 self.addLink(dh1, s204)
88 self.addLink(dh1, s203)
89
90 # DHCP server
91 dhcp = self.addHost('dhcp', cls=DhcpServer, mac='00:99:00:00:00:01', ips=['10.0.3.253/24'], gateway='10.0.3.254')
92
93 # DHCPv6 server
94 dhcp6 = self.addHost('dhcp6', cls=Dhcp6Server, mac='00:99:66:00:00:01', ips=['2000::3fd/120'], gateway='2000::3ff')
95
96 # Dataplane L2 plane switch (for DHCP servers)
97 cs1 = self.addSwitch('cs1', cls=OVSBridge)
98 self.addLink(cs1, s205)
99 self.addLink(dhcp, cs1)
100 self.addLink(dhcp6, cs1)
101
102 # Control plane switch (for quagga fpm)
103 cs0 = self.addSwitch('cs0', cls=OVSBridge)
104
105 # Control plane NAT (for quagga fpm)
106 nat = self.addHost('nat', cls=NAT,
Charles Chan947d2432018-08-17 18:13:31 -0700107 ip='172.16.0.1/24',
108 subnet=str(ip_network(u'172.16.0.0/24')), inNamespace=False)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800109 self.addLink(cs0, nat)
110
111 # Internal Quagga bgp1
112 """
113 intfs = {'bgp1-eth0': [{'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
114 {'ipAddrs': ['10.0.7.2/24', '2000::702/120'], 'mac': '00:88:00:00:00:03', 'vlan': '170'}],
Charles Chan947d2432018-08-17 18:13:31 -0700115 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800116 """
117 intfs = {'bgp1-eth0': {'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
Charles Chan947d2432018-08-17 18:13:31 -0700118 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800119 bgp1 = self.addHost('bgp1', cls=BgpRouter,
120 interfaces=intfs,
121 quaggaConfFile='./bgpdbgp1.conf',
122 zebraConfFile='./zebradbgp1.conf')
123 self.addLink(bgp1, s205)
124 self.addLink(bgp1, cs0)
125
126 # Internal Quagga bgp2
127 """
128 intfs = {'bgp2-eth0': [{'ipAddrs': ['10.0.5.2/24', '2000::502/120'], 'mac': '00:88:00:00:00:04', 'vlan': '150'},
129 {'ipAddrs': ['10.0.6.2/24', '2000::602/120'], 'mac': '00:88:00:00:00:04', 'vlan': '160'}],
Charles Chan947d2432018-08-17 18:13:31 -0700130 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800131 """
132 intfs = {'bgp2-eth0': {'ipAddrs': ['10.0.6.2/24', '2000::602/120'], 'mac': '00:88:00:00:00:04', 'vlan': '160'},
Charles Chan947d2432018-08-17 18:13:31 -0700133 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800134 bgp2 = self.addHost('bgp2', cls=BgpRouter,
135 interfaces=intfs,
136 quaggaConfFile='./bgpdbgp2.conf',
137 zebraConfFile='./zebradbgp2.conf')
138 self.addLink(bgp2, s206)
139 self.addLink(bgp2, cs0)
140
141 # External Quagga r1
142 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
143 #'r1-eth1': {'ipAddrs': ['10.0.5.1/24', '2000::501/120'], 'mac': '00:88:00:00:00:11'},
144 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']},
145 'r1-eth2': {'ipAddrs': ['2000::9901/120']},
146 'r1-eth3': {'ipAddrs': ['2000::7701/120']}}
147 r1 = self.addHost('r1', cls=BgpRouter,
148 interfaces=intfs,
149 quaggaConfFile='./bgpdr1.conf')
150 self.addLink(r1, s205)
151 #self.addLink(r1, s206)
152
153 # External IPv4 Host behind r1
154 rh1 = self.addHost('rh1', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
155 self.addLink(r1, rh1)
156
157 # External IPv6 Host behind r1
158 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
159 self.addLink(r1, rh1v6)
160
161 # Another external IPv6 Host behind r1
162 rh11v6 = self.addHost('rh11v6', cls=RoutedHost, ips=['2000::7702/120'], gateway='2000::7701')
163 self.addLink(r1, rh11v6)
164
165 # External Quagga r2
166 intfs = {'r2-eth0': {'ipAddrs': ['10.0.6.1/24', '2000::601/120'], 'mac': '00:88:00:00:00:02'},
167 #'r2-eth1': {'ipAddrs': ['10.0.7.1/24', '2000::701/120'], 'mac': '00:88:00:00:00:22'},
168 'r2-eth1': {'ipAddrs': ['10.0.99.1/16']},
169 'r2-eth2': {'ipAddrs': ['2000::9901/120']},
170 'r2-eth3': {'ipAddrs': ['2000::8801/120']}}
171 r2 = self.addHost('r2', cls=BgpRouter,
172 interfaces=intfs,
173 quaggaConfFile='./bgpdr2.conf')
174 self.addLink(r2, s206)
175 #self.addLink(r2, s205)
176
177 # External IPv4 Host behind r2
178 rh2 = self.addHost('rh2', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
179 self.addLink(r2, rh2)
180
181 # External IPv6 Host behind r2
182 rh2v6 = self.addHost('rh126', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
183 self.addLink(r2, rh2v6)
184
185 # Another external IPv6 Host behind r1
186 rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
187 self.addLink(r2, rh22v6)
188
189 # Dual-homed IPv4 Host for 205-206
190 dh2 = self.addHost('dh2', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:02')
191 self.addLink(dh2, s205)
192 self.addLink(dh2, s206)
193
194 # ----- Secondary fabric -----
195
196 # Spines(HAG)
197 s246 = self.addSwitch('s246', dpid='246')
198 s247 = self.addSwitch('s247', dpid='247')
199
200 # Leaves(DAAS)
201 s207 = self.addSwitch('s207', dpid='207')
202 s208 = self.addSwitch('s208', dpid='208')
203
204 # HAG-DAAS Links
205 self.addLink(s246, s207)
206 self.addLink(s246, s208)
207 self.addLink(s247, s207)
208 self.addLink(s247, s208)
209
210 # HAG - Spine Links
211 self.addLink(s246, s226)
212 self.addLink(s247, s227)
213
214 # IPv4 Hosts - RPDs
215 rpd5 = self.addHost('rpd5', cls=DhcpClient, mac='00:dd:00:00:00:01')
216 rpd6 = self.addHost('rpd6', cls=DhcpClient, mac='00:dd:00:00:00:02')
217 self.addLink(rpd5, s207)
218 self.addLink(rpd6, s208)
Ray Milkey1df260d2018-03-28 11:52:34 -0700219
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800220 # IPv6 Hosts - RPDs
221 rpd5v6 = self.addHost('rpd5v6', cls=Dhcp6Client, mac='00:ee:00:00:00:01')
222 rpd6v6 = self.addHost('rpd6v6', cls=Dhcp6Client, mac='00:ee:00:00:00:02')
223 self.addLink(rpd5v6, s207)
224 self.addLink(rpd6v6, s208)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800225
226
Ray Milkey1df260d2018-03-28 11:52:34 -0700227
228
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800229
230topos = { 'trellis' : Trellis }
231
232if __name__ == "__main__":
233 setLogLevel('debug')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800234
Ray Milkey1df260d2018-03-28 11:52:34 -0700235 topo = Trellis()
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800236 switch = partial(OVSSwitch, protocols='OpenFlow13')
Ray Milkey1df260d2018-03-28 11:52:34 -0700237 arguments = parse_trellis_args()
238 set_up_zebra_config(arguments.controllers)
239 net = get_mininet(arguments, topo, switch)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800240
241 net.start()
242 CLI(net)
243 net.stop()