blob: ab6e9d7c467609fec3afa288a300ae8e9e5ae820 [file] [log] [blame]
Charles Chanc7ef8a92018-08-05 21:54:58 -07001#!/usr/bin/python
2
3import sys
4sys.path.append('..')
5from mininet.topo import Topo
6from 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, Dhcp4and6Client, DhcpRelay, DhcpServer, Dhcp6Server
15from trellislib import DualHomedDhcpClient
16from trellislib import DualHomedDhcp4and6Client
17from trellislib import get_mininet, parse_trellis_args, set_up_zebra_config
18from functools import partial
19from bmv2 import ONOSBmv2Switch
20
21PIPECONF_ID = 'org.onosproject.pipelines.fabric'
22
23class Trellis( Topo ):
24 """Trellis HAG topology with both OVS and BMV2 switches"""
25
26 def __init__( self, *args, **kwargs ):
27 Topo.__init__( self, *args, **kwargs )
28
29 # Spines
30 s226 = self.addSwitch('s226', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
31 s227 = self.addSwitch('s227', dpid='227')
32
33 # Leaves
34 s203 = self.addSwitch('s203', dpid='203')
35 s204 = self.addSwitch('s204', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
36 s205 = self.addSwitch('s205', dpid='205')
37 s206 = self.addSwitch('s206', dpid='206')
38
39 # Leaf-Spine Links
40 self.addLink(s226, s203)
41 self.addLink(s226, s203)
42 self.addLink(s226, s204)
43 self.addLink(s226, s204)
44 self.addLink(s226, s205)
45 self.addLink(s226, s205)
46 self.addLink(s226, s206)
47 self.addLink(s226, s206)
48 self.addLink(s227, s203)
49 self.addLink(s227, s203)
50 self.addLink(s227, s204)
51 self.addLink(s227, s204)
52 self.addLink(s227, s205)
53 self.addLink(s227, s205)
54 self.addLink(s227, s206)
55 self.addLink(s227, s206)
56
57 # Leaf-Leaf Links
58 self.addLink(s203, s204)
59 self.addLink(s205, s206)
60
61 # NOTE avoid using 10.0.1.0/24 which is the default subnet of quaggas
62 # NOTE avoid using 00:00:00:00:00:xx which is the default mac of host behind upstream router
63 # IPv4 Hosts
64 h1 = self.addHost('h1', cls=DhcpClient, mac='00:aa:00:00:00:01')
65 h2 = self.addHost('h2', cls=DhcpClient, mac='00:aa:00:00:00:02')
66 h3 = self.addHost('h3', cls=DhcpClient, mac='00:aa:00:00:00:03')
67 h4 = self.addHost('h4', cls=DhcpClient, mac='00:aa:00:00:00:04')
68 h5 = self.addHost('h5', cls=DhcpClient, mac='00:aa:00:00:00:05')
69 self.addLink(h1, s204)
70 self.addLink(h2, s204)
71 self.addLink(h3, s205)
72 self.addLink(h4, s205)
73 self.addLink(h5, s203)
74
75 # IPv6 Hosts
76 h1v6 = self.addHost('h1v6', cls=Dhcp6Client, mac='00:bb:00:00:00:01')
77 h2v6 = self.addHost('h2v6', cls=Dhcp6Client, mac='00:bb:00:00:00:02')
78 h3v6 = self.addHost('h3v6', cls=Dhcp6Client, mac='00:bb:00:00:00:03')
79 h4v6 = self.addHost('h4v6', cls=Dhcp6Client, mac='00:bb:00:00:00:04')
80 h5v6 = self.addHost('h5v6', cls=Dhcp6Client, mac='00:bb:00:00:00:05')
81 self.addLink(h1v6, s204)
82 self.addLink(h2v6, s204)
83 self.addLink(h3v6, s205)
84 self.addLink(h4v6, s205)
85 self.addLink(h5v6, s203)
86
87 # Dual-homed IPv4 and IPv6 Host on 203-204
88 dh1 = self.addHost('dh1', cls=DualHomedDhcp4and6Client, mac='00:cc:00:00:00:01')
89 self.addLink(dh1, s204)
90 self.addLink(dh1, s203)
91
92 # DHCP server
93 dhcp = self.addHost('dhcp', cls=DhcpServer, mac='00:99:00:00:00:01', ips=['10.0.3.253/24'], gateway='10.0.3.254')
94
95 # DHCPv6 server
96 dhcp6 = self.addHost('dhcp6', cls=Dhcp6Server, mac='00:99:66:00:00:01', ips=['2000::3fd/120'], gateway='2000::3ff')
97
98 # Dataplane L2 plane switch (for DHCP servers)
Charles Chana60fbd12019-10-22 21:56:35 -070099 cs1 = self.addSwitch('cs1', cls=OVSBridge, datapath='user')
Charles Chanc7ef8a92018-08-05 21:54:58 -0700100 self.addLink(cs1, s205)
101 self.addLink(dhcp, cs1)
102 self.addLink(dhcp6, cs1)
103
104 # Control plane switch (for quagga fpm)
Charles Chana60fbd12019-10-22 21:56:35 -0700105 cs0 = self.addSwitch('cs0', cls=OVSBridge, datapath='user')
Charles Chanc7ef8a92018-08-05 21:54:58 -0700106
107 # Control plane NAT (for quagga fpm)
108 nat = self.addHost('nat', cls=NAT,
Charles Chan947d2432018-08-17 18:13:31 -0700109 ip='172.16.0.1/24',
110 subnet=str(ip_network(u'172.16.0.0/24')), inNamespace=False)
Charles Chanc7ef8a92018-08-05 21:54:58 -0700111 self.addLink(cs0, nat)
112
113 # Internal Quagga bgp1
114 """
115 intfs = {'bgp1-eth0': [{'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
116 {'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 -0700117 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Charles Chanc7ef8a92018-08-05 21:54:58 -0700118 """
119 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 -0700120 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
Charles Chanc7ef8a92018-08-05 21:54:58 -0700121 bgp1 = self.addHost('bgp1', cls=BgpRouter,
122 interfaces=intfs,
123 quaggaConfFile='./bgpdbgp1.conf',
124 zebraConfFile='./zebradbgp1.conf')
125 self.addLink(bgp1, s205)
126 self.addLink(bgp1, cs0)
127
128 # Internal Quagga bgp2
129 """
130 intfs = {'bgp2-eth0': [{'ipAddrs': ['10.0.5.2/24', '2000::502/120'], 'mac': '00:88:00:00:00:04', 'vlan': '150'},
131 {'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']}}
Charles Chanc7ef8a92018-08-05 21:54:58 -0700133 """
134 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 -0700135 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
Charles Chanc7ef8a92018-08-05 21:54:58 -0700136 bgp2 = self.addHost('bgp2', cls=BgpRouter,
137 interfaces=intfs,
138 quaggaConfFile='./bgpdbgp2.conf',
139 zebraConfFile='./zebradbgp2.conf')
140 self.addLink(bgp2, s206)
141 self.addLink(bgp2, cs0)
142
143 # External Quagga r1
144 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
145 #'r1-eth1': {'ipAddrs': ['10.0.5.1/24', '2000::501/120'], 'mac': '00:88:00:00:00:11'},
146 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']},
147 'r1-eth2': {'ipAddrs': ['2000::9901/120']},
148 'r1-eth3': {'ipAddrs': ['2000::7701/120']}}
149 r1 = self.addHost('r1', cls=BgpRouter,
150 interfaces=intfs,
151 quaggaConfFile='./bgpdr1.conf')
152 self.addLink(r1, s205)
153 #self.addLink(r1, s206)
154
155 # External IPv4 Host behind r1
156 rh1 = self.addHost('rh1', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
157 self.addLink(r1, rh1)
158
159 # External IPv6 Host behind r1
160 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
161 self.addLink(r1, rh1v6)
162
163 # Another external IPv6 Host behind r1
164 rh11v6 = self.addHost('rh11v6', cls=RoutedHost, ips=['2000::7702/120'], gateway='2000::7701')
165 self.addLink(r1, rh11v6)
166
167 # External Quagga r2
168 intfs = {'r2-eth0': {'ipAddrs': ['10.0.6.1/24', '2000::601/120'], 'mac': '00:88:00:00:00:02'},
169 #'r2-eth1': {'ipAddrs': ['10.0.7.1/24', '2000::701/120'], 'mac': '00:88:00:00:00:22'},
170 'r2-eth1': {'ipAddrs': ['10.0.99.1/16']},
171 'r2-eth2': {'ipAddrs': ['2000::9901/120']},
172 'r2-eth3': {'ipAddrs': ['2000::8801/120']}}
173 r2 = self.addHost('r2', cls=BgpRouter,
174 interfaces=intfs,
175 quaggaConfFile='./bgpdr2.conf')
176 self.addLink(r2, s206)
177 #self.addLink(r2, s205)
178
179 # External IPv4 Host behind r2
180 rh2 = self.addHost('rh2', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
181 self.addLink(r2, rh2)
182
183 # External IPv6 Host behind r2
184 rh2v6 = self.addHost('rh126', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
185 self.addLink(r2, rh2v6)
186
187 # Another external IPv6 Host behind r1
188 rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
189 self.addLink(r2, rh22v6)
190
191 # Dual-homed IPv4 Host for 205-206
192 dh2 = self.addHost('dh2', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:02')
193 self.addLink(dh2, s205)
194 self.addLink(dh2, s206)
195
196 # ----- Secondary fabric -----
197
198 # Spines(HAG)
199 s246 = self.addSwitch('s246', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
200 s247 = self.addSwitch('s247', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
201
202 # Leaves(DAAS)
203 s207 = self.addSwitch('s207', dpid='207')
204 s208 = self.addSwitch('s208', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
205
206 # HAG-DAAS Links
207 self.addLink(s246, s207)
208 self.addLink(s246, s208)
209 self.addLink(s247, s207)
210 self.addLink(s247, s208)
211
212 # HAG - Spine Links
213 self.addLink(s246, s226)
214 self.addLink(s247, s227)
215
216 # IPv4 Hosts - RPDs
217 rpd5 = self.addHost('rpd5', cls=DhcpClient, mac='00:dd:00:00:00:01')
218 rpd6 = self.addHost('rpd6', cls=DhcpClient, mac='00:dd:00:00:00:02')
219 self.addLink(rpd5, s207)
220 self.addLink(rpd6, s208)
221
222 # IPv6 Hosts - RPDs
223 rpd5v6 = self.addHost('rpd5v6', cls=Dhcp6Client, mac='00:ee:00:00:00:01')
224 rpd6v6 = self.addHost('rpd6v6', cls=Dhcp6Client, mac='00:ee:00:00:00:02')
225 self.addLink(rpd5v6, s207)
226 self.addLink(rpd6v6, s208)
227
228
229
230
231
232topos = { 'trellis' : Trellis }
233
234if __name__ == "__main__":
235 setLogLevel('debug')
236
237 topo = Trellis()
Charles Chana60fbd12019-10-22 21:56:35 -0700238 switch = partial(OVSSwitch, protocols='OpenFlow13', datapath='user')
Charles Chanc7ef8a92018-08-05 21:54:58 -0700239 arguments = parse_trellis_args()
240 set_up_zebra_config(arguments.controllers)
241 net = get_mininet(arguments, topo, switch)
242
243 net.start()
244 CLI(net)
245 net.stop()