blob: 4aa67b3382bfd9d7fbeec7153f49a3df5ce67bc3 [file] [log] [blame]
kelvin-onlabd9e23de2015-08-06 10:34:44 -07001#!/usr/bin/python
2
3"""
4Custom topology for Mininet
5Author: kelvin@onlab.us
6"""
7from mininet.topo import Topo
8from mininet.net import Mininet
9from mininet.node import Host, RemoteController
10from mininet.node import Node
11from mininet.node import CPULimitedHost
12from mininet.link import TCLink
13from mininet.cli import CLI
14from mininet.log import setLogLevel
15from mininet.util import dumpNodeConnections
16from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
17import sys
18coreSwitches = {}
19spineSwitches = {}
20leafSwitches = {}
21endSwitches = {}
22allSwitches = {}
23# Counters for nodes
24totalSwitches = 0
25totalEndSwitches = 0
26totalHosts = 0
27endSwitchCount = 0 # total count of end switch in each row in gui
28class spineTopo( Topo ):
29
30 def __init__( self, **opts ):
31 "Create a topology."
32 Topo.__init__( self, **opts )
33
34 def build( self, s, l, c, e, h, **opts ):
35 """
36 s = number of spine switches
37 l = number of leaf switches
38 c = number of core
39 e = number of end switch
40 h = number of end host
41 """
42 global totalSwitches
43 global coreSwitches
44 global spineSwitches
45 global leafSwitches
46 global endSwitches
47 global totalEndSwitches
48 global totalHosts
49 global allSwitches
50 global endSwitchCount
51 endSwitchCount = e
52
53 print "Creating topology with", s,"spine", l,"leaf", c,"core",\
54 e,"end switches and",h,"host for each end switches"
55
56 self.addCore( c )
57 self.addSpine( s )
58 self.addLeaf( l )
59 self.linkLayer( coreSwitches, spineSwitches )
60 self.linkLayer( spineSwitches, leafSwitches )
61 self.linkEndSwitch( e, leafSwitches )
62 self.linkHosts( h )
63
64 allSwitches = coreSwitches
65 allSwitches.update( spineSwitches )
66 allSwitches.update( leafSwitches )
67 allSwitches.update( endSwitches )
68 deviceData = self.createSwitchDict()
69 self.genCfgJson( deviceData )
70
71
72 def addCore( self, numSwitch ):
73 global totalSwitches
74 global coreSwitches
75 for i in range( numSwitch ):
76 coreSwitches[ 'core' + str( i + 1 ) ] = self.addSwitch(
77 's' + str( totalSwitches + 1 ) )
78 totalSwitches += 1
79
80 def addSpine( self, numSwitch ):
81 global totalSwitches
82 global spineSwitches
83 for i in range( numSwitch ):
84 spineSwitches[ 'spine' + str( i + 1 ) ] = self.addSwitch(
85 's' + str( totalSwitches + 1 ) )
86 totalSwitches += 1
87
88 def addLeaf( self, numSwitch ):
89 global totalSwitches
90 global leafSwitches
91 for i in range( numSwitch ):
92 leafSwitches[ 'leaf' + str( i + 1 ) ] = self.addSwitch(
93 's' + str( totalSwitches + 1 ) )
94 totalSwitches += 1
95
96 def addEnd( self ):
97 global totalSwitches
98 global totalEndSwitches
99 global endSwitches
100
101 endSwitches[ 'end' + str( totalEndSwitches + 1 ) ] = self.addSwitch(
102 's' + str( totalSwitches + 1 ) )
103 totalSwitches += 1
104 totalEndSwitches += 1
105
106 return endSwitches[ 'end' + str( totalEndSwitches ) ]
107
108 def addEndHosts( self ):
109 global totalHosts
110
111 totalHosts += 1
112 host = self.addHost( 'h' + str( totalHosts ) )
113
114 return host
115
116
117 def linkHosts( self, numHosts ):
118 global endSwitches
119 switches = sorted( endSwitches.values() )
120
121 for sw in switches:
122 for i in xrange( numHosts ):
123 self.addLink( sw, self.addEndHosts() )
124
125
126 def linkLayer( self, topLayer, botLayer ):
127 """
128 Description:
129 The top layer is the upper layer in the spine topology eg. top layer
130 can be the spine and the bottom layer is the leaf, another is the
131 core layer is the top layer and the spine is the bottom layer and
132 so on.
133 Required:
134 topLayer - Upper layer in the spine topology to be linked in the
135 layer below
136 botLater - Layer that is below the upper layer to be linked at
137 """
138
139 topSwitches = sorted( topLayer.keys() )
140 botSwitches = sorted( botLayer.keys() )
141
142 for topSw in topSwitches:
143 for botSw in botSwitches:
144 self.addLink( topLayer.get( topSw ), botLayer.get( botSw ) )
145
146
147 def linkEndSwitch( self, numSwitch, leafLayer ):
148 global totalSwitches
149 global totalEndSwitches
150
151 leaf = sorted( leafLayer.values() )
152
153 for i in xrange( len( leafSwitches ) ):
154 if len( leafSwitches ) == 1:
155 for j in xrange( numSwitch ):
156 self.addLink( leaf[ 0 ], self.addEnd() )
157 break
158 if len( leafSwitches ) == 2:
159 for j in xrange( numSwitch ):
160 endSw = self.addEnd()
161 self.addLink( leaf[ i ], endSw )
162 self.addLink( leaf[ i + 1 ], endSw )
163 break
164 if i == ( len( leafSwitches ) - 1 ) and len( leafSwitches )%2:
165 for j in xrange( numSwitch ):
166 self.addLink( leaf[ i ], self.addEnd() )
167 break
168 if i == 0:
169 for j in xrange( numSwitch ):
170 endSw = self.addEnd()
171 self.addLink( leaf[ i ], endSw )
172 self.addLink( leaf[ i + 1 ], endSw )
173 continue
174 if i == 1:
175 continue
176 if i%2 == 0:
177 for j in xrange( numSwitch ):
178 endSw = self.addEnd()
179 self.addLink( leaf[ i ], endSw )
180 self.addLink( leaf[ i + 1 ], endSw )
181
182 def genCfgJson( self, deviceData ):
183 import json
184 configJson = {}
185 configJson[ "devices" ] = deviceData
186 with open( 'spine.json', 'w+' ) as outfile:
187 json.dump( configJson, outfile )
188 #cfgFile = open( "spine.json" , 'w+' )
189 #cfgFile.write( configJson )
190 #cfgFile.close()
191
192
193
194 def createSwitchDict( self ):
195 global allSwitches
196 global endSwitchCount
197
198 latitude = 0
199 longitude = 0
200 coreLong = -70
201 spineLong = -80
202 leafLong = -90
203 endLat = 30
204 rowCount = 0 # count of end switches or rows
205 colOffSet = 0 # off set for end switches; longitude
206
207 #for i in xrange( len( allSwitches ) ):
208 deviceList = []
209 deviceDict = {}
210 for sw in allSwitches:
211 tempSw = allSwitches.get( sw )
212 uri = str( "{0:0>16}".format( str( hex( int( tempSw[ 1: ] ) )\
213 ).split( "x" )[ 1 ] ) )
214 mac = str( "{0:0>12}".format( str( hex( int( tempSw[ 1: ] ) )\
215 ).split( "x" )[ 1 ] ) )
216
217 if "core" in sw:
218 latitude = 45
219 longitude = coreLong
220 coreLong += 2.5
221 elif "spine" in sw:
222 latitude = 40
223 longitude = spineLong
224 spineLong += 1.5
225 elif "leaf" in sw:
226 latitude = 35
227 longitude = leafLong
228 leafLong += 1.5
229 elif "end" in sw:
230 # Reset position and move to the right once every
231 # number of end switches
232 if rowCount == endSwitchCount:
233 colOffSet += 2.5
234 rowCount = 0
235 endLat = 30
236 longitude = -80 + colOffSet
237 latitude = endLat
238 endLat -= 1
239 rowCount += 1
240
241 tempItem = { "alias": allSwitches.get( sw ) ,
242 "uri": "of:" + uri,
243 "mac": mac,
244 "annotations": { "name": sw,
245 "latitude": latitude,
246 "longitude": longitude },
247 "type": "SWITCH" }
248 deviceList.append( tempItem )
249
250 return deviceList
251 #def createHostsJson( hostDict ):
252
253topos = { 'spine': ( lambda s=2, l=3, c=1, e=5, h=1: spineTopo( s=s,
254 l=l,
255 c=c,
256 e=e,
257 h=h) ) }
258
259# HERE THE CODE DEFINITION OF THE TOPOLOGY ENDS
260
261def setupNetwork():
262 "Create network"
263 topo = spineTopo()
264 #if controller_ip == '':
265 #controller_ip = '10.0.2.2';
266 # controller_ip = '127.0.0.1';
267 network = Mininet( topo=topo,
268 autoSetMacs=True,
269 controller=None )
270 network.start()
271 CLI( network )
272 network.stop()
273
274if __name__ == '__main__':
275 setLogLevel( 'info' )
276 #setLogLevel('debug')
277 setupNetwork()