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