blob: 33ceede413c3b5e938be425ffe8968a98142c40c [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
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080010from ipaddress import ip_network
11from routinglib import BgpRouter
Federico Garcia86582b92020-02-10 12:34:42 -030012from routinglib import RoutedHost, RoutedHost6, UserNAT
Andrea Campanellaba96c612018-04-23 12:09:34 +020013from trellislib import DhcpClient, Dhcp6Client, Dhcp4and6Client, DhcpRelay, DhcpServer, Dhcp6Server
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080014from trellislib import DualHomedDhcpClient
Andrea Campanellaba96c612018-04-23 12:09:34 +020015from trellislib import DualHomedDhcp4and6Client
Ray Milkey1df260d2018-03-28 11:52:34 -070016from trellislib import get_mininet, parse_trellis_args, set_up_zebra_config
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080017from functools import partial
18
Ray Milkey1df260d2018-03-28 11:52:34 -070019
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080020class Trellis( Topo ):
Ray Milkey1df260d2018-03-28 11:52:34 -070021 """Trellis HAG topology"""
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080022
23 def __init__( self, *args, **kwargs ):
24 Topo.__init__( self, *args, **kwargs )
25
26 # Spines
27 s226 = self.addSwitch('s226', dpid='226')
28 s227 = self.addSwitch('s227', dpid='227')
29
30 # Leaves
31 s203 = self.addSwitch('s203', dpid='203')
32 s204 = self.addSwitch('s204', dpid='204')
33 s205 = self.addSwitch('s205', dpid='205')
34 s206 = self.addSwitch('s206', dpid='206')
35
36 # Leaf-Spine Links
37 self.addLink(s226, s203)
38 self.addLink(s226, s203)
39 self.addLink(s226, s204)
40 self.addLink(s226, s204)
41 self.addLink(s226, s205)
42 self.addLink(s226, s205)
43 self.addLink(s226, s206)
44 self.addLink(s226, s206)
45 self.addLink(s227, s203)
46 self.addLink(s227, s203)
47 self.addLink(s227, s204)
48 self.addLink(s227, s204)
49 self.addLink(s227, s205)
50 self.addLink(s227, s205)
51 self.addLink(s227, s206)
52 self.addLink(s227, s206)
53
54 # Leaf-Leaf Links
55 self.addLink(s203, s204)
56 self.addLink(s205, s206)
57
58 # NOTE avoid using 10.0.1.0/24 which is the default subnet of quaggas
59 # NOTE avoid using 00:00:00:00:00:xx which is the default mac of host behind upstream router
60 # IPv4 Hosts
61 h1 = self.addHost('h1', cls=DhcpClient, mac='00:aa:00:00:00:01')
62 h2 = self.addHost('h2', cls=DhcpClient, mac='00:aa:00:00:00:02')
63 h3 = self.addHost('h3', cls=DhcpClient, mac='00:aa:00:00:00:03')
64 h4 = self.addHost('h4', cls=DhcpClient, mac='00:aa:00:00:00:04')
Andrea Campanellaba96c612018-04-23 12:09:34 +020065 h5 = self.addHost('h5', cls=DhcpClient, mac='00:aa:00:00:00:05')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080066 self.addLink(h1, s204)
67 self.addLink(h2, s204)
68 self.addLink(h3, s205)
69 self.addLink(h4, s205)
Andrea Campanellaba96c612018-04-23 12:09:34 +020070 self.addLink(h5, s203)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080071
72 # IPv6 Hosts
73 h1v6 = self.addHost('h1v6', cls=Dhcp6Client, mac='00:bb:00:00:00:01')
74 h2v6 = self.addHost('h2v6', cls=Dhcp6Client, mac='00:bb:00:00:00:02')
75 h3v6 = self.addHost('h3v6', cls=Dhcp6Client, mac='00:bb:00:00:00:03')
76 h4v6 = self.addHost('h4v6', cls=Dhcp6Client, mac='00:bb:00:00:00:04')
Andrea Campanellaba96c612018-04-23 12:09:34 +020077 h5v6 = self.addHost('h5v6', cls=Dhcp6Client, mac='00:bb:00:00:00:05')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080078 self.addLink(h1v6, s204)
79 self.addLink(h2v6, s204)
80 self.addLink(h3v6, s205)
81 self.addLink(h4v6, s205)
Andrea Campanellaba96c612018-04-23 12:09:34 +020082 self.addLink(h5v6, s203)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080083
Andrea Campanellaba96c612018-04-23 12:09:34 +020084 # Dual-homed IPv4 and IPv6 Host on 203-204
85 dh1 = self.addHost('dh1', cls=DualHomedDhcp4and6Client, mac='00:cc:00:00:00:01')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080086 self.addLink(dh1, s204)
87 self.addLink(dh1, s203)
88
89 # DHCP server
90 dhcp = self.addHost('dhcp', cls=DhcpServer, mac='00:99:00:00:00:01', ips=['10.0.3.253/24'], gateway='10.0.3.254')
91
92 # DHCPv6 server
93 dhcp6 = self.addHost('dhcp6', cls=Dhcp6Server, mac='00:99:66:00:00:01', ips=['2000::3fd/120'], gateway='2000::3ff')
94
95 # Dataplane L2 plane switch (for DHCP servers)
Charles Chana60fbd12019-10-22 21:56:35 -070096 cs1 = self.addSwitch('cs1', cls=OVSBridge, datapath='user')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -080097 self.addLink(cs1, s205)
98 self.addLink(dhcp, cs1)
99 self.addLink(dhcp6, cs1)
100
101 # Control plane switch (for quagga fpm)
Charles Chana60fbd12019-10-22 21:56:35 -0700102 cs0 = self.addSwitch('cs0', cls=OVSBridge, datapath='user')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800103
104 # Control plane NAT (for quagga fpm)
Charles Chan4bcd9562019-12-15 00:02:32 -0800105 nat = self.addHost('nat', cls=UserNAT,
Charles Chan947d2432018-08-17 18:13:31 -0700106 ip='172.16.0.1/24',
107 subnet=str(ip_network(u'172.16.0.0/24')), inNamespace=False)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800108 self.addLink(cs0, nat)
109
110 # Internal Quagga bgp1
111 """
112 intfs = {'bgp1-eth0': [{'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
113 {'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 -0700114 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800115 """
116 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 -0700117 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800118 bgp1 = self.addHost('bgp1', cls=BgpRouter,
119 interfaces=intfs,
120 quaggaConfFile='./bgpdbgp1.conf',
121 zebraConfFile='./zebradbgp1.conf')
122 self.addLink(bgp1, s205)
123 self.addLink(bgp1, cs0)
124
125 # Internal Quagga bgp2
126 """
127 intfs = {'bgp2-eth0': [{'ipAddrs': ['10.0.5.2/24', '2000::502/120'], 'mac': '00:88:00:00:00:04', 'vlan': '150'},
128 {'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 -0700129 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800130 """
131 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 -0700132 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800133 bgp2 = self.addHost('bgp2', cls=BgpRouter,
134 interfaces=intfs,
135 quaggaConfFile='./bgpdbgp2.conf',
136 zebraConfFile='./zebradbgp2.conf')
137 self.addLink(bgp2, s206)
138 self.addLink(bgp2, cs0)
139
140 # External Quagga r1
141 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
142 #'r1-eth1': {'ipAddrs': ['10.0.5.1/24', '2000::501/120'], 'mac': '00:88:00:00:00:11'},
143 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']},
144 'r1-eth2': {'ipAddrs': ['2000::9901/120']},
145 'r1-eth3': {'ipAddrs': ['2000::7701/120']}}
146 r1 = self.addHost('r1', cls=BgpRouter,
147 interfaces=intfs,
148 quaggaConfFile='./bgpdr1.conf')
149 self.addLink(r1, s205)
150 #self.addLink(r1, s206)
151
152 # External IPv4 Host behind r1
153 rh1 = self.addHost('rh1', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
154 self.addLink(r1, rh1)
155
156 # External IPv6 Host behind r1
157 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
158 self.addLink(r1, rh1v6)
159
160 # Another external IPv6 Host behind r1
161 rh11v6 = self.addHost('rh11v6', cls=RoutedHost, ips=['2000::7702/120'], gateway='2000::7701')
162 self.addLink(r1, rh11v6)
163
164 # External Quagga r2
165 intfs = {'r2-eth0': {'ipAddrs': ['10.0.6.1/24', '2000::601/120'], 'mac': '00:88:00:00:00:02'},
166 #'r2-eth1': {'ipAddrs': ['10.0.7.1/24', '2000::701/120'], 'mac': '00:88:00:00:00:22'},
167 'r2-eth1': {'ipAddrs': ['10.0.99.1/16']},
168 'r2-eth2': {'ipAddrs': ['2000::9901/120']},
169 'r2-eth3': {'ipAddrs': ['2000::8801/120']}}
170 r2 = self.addHost('r2', cls=BgpRouter,
171 interfaces=intfs,
172 quaggaConfFile='./bgpdr2.conf')
173 self.addLink(r2, s206)
174 #self.addLink(r2, s205)
175
176 # External IPv4 Host behind r2
177 rh2 = self.addHost('rh2', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
178 self.addLink(r2, rh2)
179
180 # External IPv6 Host behind r2
181 rh2v6 = self.addHost('rh126', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
182 self.addLink(r2, rh2v6)
183
184 # Another external IPv6 Host behind r1
185 rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
186 self.addLink(r2, rh22v6)
187
188 # Dual-homed IPv4 Host for 205-206
189 dh2 = self.addHost('dh2', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:02')
190 self.addLink(dh2, s205)
191 self.addLink(dh2, s206)
192
193 # ----- Secondary fabric -----
194
195 # Spines(HAG)
196 s246 = self.addSwitch('s246', dpid='246')
197 s247 = self.addSwitch('s247', dpid='247')
198
199 # Leaves(DAAS)
200 s207 = self.addSwitch('s207', dpid='207')
201 s208 = self.addSwitch('s208', dpid='208')
202
203 # HAG-DAAS Links
204 self.addLink(s246, s207)
205 self.addLink(s246, s208)
206 self.addLink(s247, s207)
207 self.addLink(s247, s208)
208
209 # HAG - Spine Links
210 self.addLink(s246, s226)
211 self.addLink(s247, s227)
212
213 # IPv4 Hosts - RPDs
214 rpd5 = self.addHost('rpd5', cls=DhcpClient, mac='00:dd:00:00:00:01')
215 rpd6 = self.addHost('rpd6', cls=DhcpClient, mac='00:dd:00:00:00:02')
216 self.addLink(rpd5, s207)
217 self.addLink(rpd6, s208)
Ray Milkey1df260d2018-03-28 11:52:34 -0700218
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800219 # IPv6 Hosts - RPDs
220 rpd5v6 = self.addHost('rpd5v6', cls=Dhcp6Client, mac='00:ee:00:00:00:01')
221 rpd6v6 = self.addHost('rpd6v6', cls=Dhcp6Client, mac='00:ee:00:00:00:02')
222 self.addLink(rpd5v6, s207)
223 self.addLink(rpd6v6, s208)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800224
225
Ray Milkey1df260d2018-03-28 11:52:34 -0700226
227
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800228
229topos = { 'trellis' : Trellis }
230
231if __name__ == "__main__":
232 setLogLevel('debug')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800233
Ray Milkey1df260d2018-03-28 11:52:34 -0700234 topo = Trellis()
Charles Chana60fbd12019-10-22 21:56:35 -0700235 switch = partial(OVSSwitch, protocols='OpenFlow13', datapath='user')
Ray Milkey1df260d2018-03-28 11:52:34 -0700236 arguments = parse_trellis_args()
237 set_up_zebra_config(arguments.controllers)
238 net = get_mininet(arguments, topo, switch)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800239
240 net.start()
241 CLI(net)
242 net.stop()