blob: 0b0b3bbe51ca2c0a973aadff5f1ad1b0ba9cdc5c [file] [log] [blame]
Charles Chan9c5169f2018-08-29 12:44:44 -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)
99 cs1 = self.addSwitch('cs1', cls=OVSBridge)
100 self.addLink(cs1, s205)
101 self.addLink(dhcp, cs1)
102 #self.addLink(dhcp6, cs1)
103
104 # Control plane switch (for quagga fpm)
105 cs0 = self.addSwitch('cs0', cls=OVSBridge)
106
107 # Control plane NAT (for quagga fpm)
108 nat = self.addHost('nat', cls=NAT,
109 ip='172.16.0.1/24',
110 subnet=str(ip_network(u'172.16.0.0/24')), inNamespace=False)
111 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'}],
117 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
118 """
119 intfs = {'bgp1-eth0': {'ipAddrs': ['10.0.1.2/24'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
120 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/24']}}
121 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'}],
132 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
133 """
134 intfs = {'bgp2-eth0': {'ipAddrs': ['10.0.6.2/24'], 'mac': '00:88:00:00:00:04', 'vlan': '160'},
135 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/24']}}
136 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'], 'mac': '00:88:00:00:00:01'},
145 'r1-eth1': {'ipAddrs': ['10.0.99.1/16']}}
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'], 'mac': '00:88:00:00:00:02'},
166 'r2-eth1': {'ipAddrs': ['10.0.99.1/16']}}
167 r2 = self.addHost('r2', cls=BgpRouter,
168 interfaces=intfs,
169 quaggaConfFile='./bgpdr2.conf')
170 self.addLink(r2, s206)
171 #self.addLink(r2, s205)
172
173 # External IPv4 Host behind r2
174 rh2 = self.addHost('rh2', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
175 self.addLink(r2, rh2)
176
177 # External IPv6 Host behind r2
178 #rh2v6 = self.addHost('rh126', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
179 #self.addLink(r2, rh2v6)
180
181 # Another external IPv6 Host behind r1
182 #rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
183 #self.addLink(r2, rh22v6)
184
185 # Dual-homed IPv4 Host for 205-206
186 dh2 = self.addHost('dh2', cls=DualHomedDhcpClient, mac='00:cc:00:00:00:02')
187 self.addLink(dh2, s205)
188 self.addLink(dh2, s206)
189
190 # ----- Secondary fabric -----
191
192 # Spines(HAG)
193 s246 = self.addSwitch('s246', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
194 s247 = self.addSwitch('s247', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
195
196 # Leaves(DAAS)
197 s207 = self.addSwitch('s207', dpid='207')
198 s208 = self.addSwitch('s208', cls=ONOSBmv2Switch, pipeconf=PIPECONF_ID, portcfg=True)
199
200 # HAG-DAAS Links
201 self.addLink(s246, s207)
202 self.addLink(s246, s208)
203 self.addLink(s247, s207)
204 self.addLink(s247, s208)
205
206 # HAG - Spine Links
207 self.addLink(s246, s226)
208 self.addLink(s247, s227)
209
210 # IPv4 Hosts - RPDs
211 rpd5 = self.addHost('rpd5', cls=DhcpClient, mac='00:dd:00:00:00:01')
212 rpd6 = self.addHost('rpd6', cls=DhcpClient, mac='00:dd:00:00:00:02')
213 self.addLink(rpd5, s207)
214 self.addLink(rpd6, s208)
215
216 # IPv6 Hosts - RPDs
217 #rpd5v6 = self.addHost('rpd5v6', cls=Dhcp6Client, mac='00:ee:00:00:00:01')
218 #rpd6v6 = self.addHost('rpd6v6', cls=Dhcp6Client, mac='00:ee:00:00:00:02')
219 #self.addLink(rpd5v6, s207)
220 #self.addLink(rpd6v6, s208)
221
222
223
224
225
226topos = { 'trellis' : Trellis }
227
228if __name__ == "__main__":
229 setLogLevel('debug')
230
231 topo = Trellis()
232 switch = partial(OVSSwitch, protocols='OpenFlow13')
233 arguments = parse_trellis_args()
234 set_up_zebra_config(arguments.controllers)
235 net = get_mininet(arguments, topo, switch)
236
237 net.start()
238 CLI(net)
239 net.stop()