blob: d78bd9d0361097ca2789975f63cb4285757abb43 [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
14from trellislib import DhcpClient, Dhcp6Client, DhcpRelay, DhcpServer, Dhcp6Server
15from trellislib import DualHomedDhcpClient
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')
65 self.addLink(h1, s204)
66 self.addLink(h2, s204)
67 self.addLink(h3, s205)
68 self.addLink(h4, s205)
69
70 # IPv6 Hosts
71 h1v6 = self.addHost('h1v6', cls=Dhcp6Client, mac='00:bb:00:00:00:01')
72 h2v6 = self.addHost('h2v6', cls=Dhcp6Client, mac='00:bb:00:00:00:02')
73 h3v6 = self.addHost('h3v6', cls=Dhcp6Client, mac='00:bb:00:00:00:03')
74 h4v6 = self.addHost('h4v6', cls=Dhcp6Client, mac='00:bb:00:00:00:04')
75 self.addLink(h1v6, s204)
76 self.addLink(h2v6, s204)
77 self.addLink(h3v6, s205)
78 self.addLink(h4v6, s205)
79
80 # Dual-homed IPv4 Host 203-204
81 dh1 = self.addHost('dh1', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:01')
82 self.addLink(dh1, s204)
83 self.addLink(dh1, s203)
84
85 # DHCP server
86 dhcp = self.addHost('dhcp', cls=DhcpServer, mac='00:99:00:00:00:01', ips=['10.0.3.253/24'], gateway='10.0.3.254')
87
88 # DHCPv6 server
89 dhcp6 = self.addHost('dhcp6', cls=Dhcp6Server, mac='00:99:66:00:00:01', ips=['2000::3fd/120'], gateway='2000::3ff')
90
91 # Dataplane L2 plane switch (for DHCP servers)
92 cs1 = self.addSwitch('cs1', cls=OVSBridge)
93 self.addLink(cs1, s205)
94 self.addLink(dhcp, cs1)
95 self.addLink(dhcp6, cs1)
96
97 # Control plane switch (for quagga fpm)
98 cs0 = self.addSwitch('cs0', cls=OVSBridge)
99
100 # Control plane NAT (for quagga fpm)
101 nat = self.addHost('nat', cls=NAT,
102 ip='172.16.0.1/12',
103 subnet=str(ip_network(u'172.16.0.0/12')), inNamespace=False)
104 self.addLink(cs0, nat)
105
106 # Internal Quagga bgp1
107 """
108 intfs = {'bgp1-eth0': [{'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
109 {'ipAddrs': ['10.0.7.2/24', '2000::702/120'], 'mac': '00:88:00:00:00:03', 'vlan': '170'}],
110 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/12']}}
111 """
112 intfs = {'bgp1-eth0': {'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
113 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/12']}}
114 bgp1 = self.addHost('bgp1', cls=BgpRouter,
115 interfaces=intfs,
116 quaggaConfFile='./bgpdbgp1.conf',
117 zebraConfFile='./zebradbgp1.conf')
118 self.addLink(bgp1, s205)
119 self.addLink(bgp1, cs0)
120
121 # Internal Quagga bgp2
122 """
123 intfs = {'bgp2-eth0': [{'ipAddrs': ['10.0.5.2/24', '2000::502/120'], 'mac': '00:88:00:00:00:04', 'vlan': '150'},
124 {'ipAddrs': ['10.0.6.2/24', '2000::602/120'], 'mac': '00:88:00:00:00:04', 'vlan': '160'}],
125 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/12']}}
126 """
127 intfs = {'bgp2-eth0': {'ipAddrs': ['10.0.6.2/24', '2000::602/120'], 'mac': '00:88:00:00:00:04', 'vlan': '160'},
128 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/12']}}
129 bgp2 = self.addHost('bgp2', cls=BgpRouter,
130 interfaces=intfs,
131 quaggaConfFile='./bgpdbgp2.conf',
132 zebraConfFile='./zebradbgp2.conf')
133 self.addLink(bgp2, s206)
134 self.addLink(bgp2, cs0)
135
136 # External Quagga r1
137 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
138 #'r1-eth1': {'ipAddrs': ['10.0.5.1/24', '2000::501/120'], 'mac': '00:88:00:00:00:11'},
139 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']},
140 'r1-eth2': {'ipAddrs': ['2000::9901/120']},
141 'r1-eth3': {'ipAddrs': ['2000::7701/120']}}
142 r1 = self.addHost('r1', cls=BgpRouter,
143 interfaces=intfs,
144 quaggaConfFile='./bgpdr1.conf')
145 self.addLink(r1, s205)
146 #self.addLink(r1, s206)
147
148 # External IPv4 Host behind r1
149 rh1 = self.addHost('rh1', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
150 self.addLink(r1, rh1)
151
152 # External IPv6 Host behind r1
153 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
154 self.addLink(r1, rh1v6)
155
156 # Another external IPv6 Host behind r1
157 rh11v6 = self.addHost('rh11v6', cls=RoutedHost, ips=['2000::7702/120'], gateway='2000::7701')
158 self.addLink(r1, rh11v6)
159
160 # External Quagga r2
161 intfs = {'r2-eth0': {'ipAddrs': ['10.0.6.1/24', '2000::601/120'], 'mac': '00:88:00:00:00:02'},
162 #'r2-eth1': {'ipAddrs': ['10.0.7.1/24', '2000::701/120'], 'mac': '00:88:00:00:00:22'},
163 'r2-eth1': {'ipAddrs': ['10.0.99.1/16']},
164 'r2-eth2': {'ipAddrs': ['2000::9901/120']},
165 'r2-eth3': {'ipAddrs': ['2000::8801/120']}}
166 r2 = self.addHost('r2', cls=BgpRouter,
167 interfaces=intfs,
168 quaggaConfFile='./bgpdr2.conf')
169 self.addLink(r2, s206)
170 #self.addLink(r2, s205)
171
172 # External IPv4 Host behind r2
173 rh2 = self.addHost('rh2', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
174 self.addLink(r2, rh2)
175
176 # External IPv6 Host behind r2
177 rh2v6 = self.addHost('rh126', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
178 self.addLink(r2, rh2v6)
179
180 # Another external IPv6 Host behind r1
181 rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
182 self.addLink(r2, rh22v6)
183
184 # Dual-homed IPv4 Host for 205-206
185 dh2 = self.addHost('dh2', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:02')
186 self.addLink(dh2, s205)
187 self.addLink(dh2, s206)
188
189 # ----- Secondary fabric -----
190
191 # Spines(HAG)
192 s246 = self.addSwitch('s246', dpid='246')
193 s247 = self.addSwitch('s247', dpid='247')
194
195 # Leaves(DAAS)
196 s207 = self.addSwitch('s207', dpid='207')
197 s208 = self.addSwitch('s208', dpid='208')
198
199 # HAG-DAAS Links
200 self.addLink(s246, s207)
201 self.addLink(s246, s208)
202 self.addLink(s247, s207)
203 self.addLink(s247, s208)
204
205 # HAG - Spine Links
206 self.addLink(s246, s226)
207 self.addLink(s247, s227)
208
209 # IPv4 Hosts - RPDs
210 rpd5 = self.addHost('rpd5', cls=DhcpClient, mac='00:dd:00:00:00:01')
211 rpd6 = self.addHost('rpd6', cls=DhcpClient, mac='00:dd:00:00:00:02')
212 self.addLink(rpd5, s207)
213 self.addLink(rpd6, s208)
Ray Milkey1df260d2018-03-28 11:52:34 -0700214
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800215 # IPv6 Hosts - RPDs
216 rpd5v6 = self.addHost('rpd5v6', cls=Dhcp6Client, mac='00:ee:00:00:00:01')
217 rpd6v6 = self.addHost('rpd6v6', cls=Dhcp6Client, mac='00:ee:00:00:00:02')
218 self.addLink(rpd5v6, s207)
219 self.addLink(rpd6v6, s208)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800220
221
Ray Milkey1df260d2018-03-28 11:52:34 -0700222
223
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800224
225topos = { 'trellis' : Trellis }
226
227if __name__ == "__main__":
228 setLogLevel('debug')
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800229
Ray Milkey1df260d2018-03-28 11:52:34 -0700230 topo = Trellis()
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800231 switch = partial(OVSSwitch, protocols='OpenFlow13')
Ray Milkey1df260d2018-03-28 11:52:34 -0700232 arguments = parse_trellis_args()
233 set_up_zebra_config(arguments.controllers)
234 net = get_mininet(arguments, topo, switch)
Andrea Campanella6d2ae8a2018-03-09 08:44:35 -0800235
236 net.start()
237 CLI(net)
238 net.stop()