blob: 21dd1f20bcbcd27da95c8818ec5c47b4ad2e6cff [file] [log] [blame]
Brian O'Connoreb27c452014-12-07 02:43:58 -08001#!/usr/bin/python
2
3'''
4Notes:
5
6This file contains classes and methods useful for integrating LincOE with Mininet,
fahad44e62c72015-03-04 14:55:35 -08007such as startOE, stopOE, LINCLink, and OpticalSwitch
Brian O'Connoreb27c452014-12-07 02:43:58 -08008
9- $ONOS_ROOT ust be set
10- Need to run with sudo -E to preserve ONOS_ROOT env var
11- We assume LINC-Config-Generator is named LINC-Config-Generator
12- We also assume linc-oe is named linc-oe
13- LINC-config-generator and linc-oe must be subdirectories of the user's
14 home directory
15
16 TODO
17 -----------
18 - clean up files after runtime
19 - maybe save the old files in a separate directory?
20 - modify script to allow startOE to run before net.start()
21 - add ONOS as a controller in script
22
23 Usage:
24 ------------
fahad44e62c72015-03-04 14:55:35 -080025 - import LINCLink and OpticalSwitch from this module
Brian O'Connoreb27c452014-12-07 02:43:58 -080026 - import startOE and stopOE from this module
27 - create topology as you would a normal topology. when
fahad44e62c72015-03-04 14:55:35 -080028 to an optical switch with topo.addLink, always specify cls=LINCLink
Brian O'Connoreb27c452014-12-07 02:43:58 -080029 - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch
30 - for annotations on links and switches, a dictionary must be passed in as
31 the annotations argument
32 - startOE must be run AFTER net.start() with net as an argument.
33 - stopOE can be run at any time
34
35I created a separate function to start lincOE to avoid subclassing Mininet.
36In case anyone wants to write something that DOES subclass Mininet, I
37thought I would outline how:
38
39If we want an object that starts lincOE within the mininet class itself,
40we need to add another object to Mininet that contains all of the json object
41information for each switch. We would still subclass switch and link, but these
42classes would basically be dummy classes that store their own json information
43in the Mininet class object. We may also change the default switch class to add
44it's tap interfaces from lincOE during startup. The start() method for mininet would
45grab all of the information from these switches and links, write configuration files
46for lincOE using the json module, start lincOE, then run the start methodfor each
47switch. The new start() method for each switch would parse through the sys.config
48file that was created and find the tap interface it needs to connect to, similar
49to the findTap function that I currently use. After all of the controllers and
50switches have been started, the new Mininet start() method should also push the
51Topology configuration file to ONOS.
52
53'''
fahad44e62c72015-03-04 14:55:35 -080054import sys
Brian O'Connoreb27c452014-12-07 02:43:58 -080055import re
56import json
57import os
58from time import sleep
59
60from mininet.node import Switch, RemoteController
61from mininet.topo import Topo
62from mininet.util import quietRun
63from mininet.net import Mininet
64from mininet.log import setLogLevel, info, error, warn
65from mininet.link import Link, Intf
66from mininet.cli import CLI
67
fahad44e62c72015-03-04 14:55:35 -080068class OpticalSwitch(Switch):
69 """
70 For now, same as Switch class.
71 """
72 pass
Brian O'Connoreb27c452014-12-07 02:43:58 -080073
fahad44e62c72015-03-04 14:55:35 -080074class OpticalIntf(Intf):
75 """
76 For now,same as Intf class.
77 """
78 pass
79
80class OpticalLink(Link):
81 """
82 For now, same as Link.
83 """
84 pass
85
86class LINCSwitch(OpticalSwitch):
87 """
88 LINCSwitch class
89 """
90 # FIXME:Sometimes LINC doesn't remove pipes and on restart increase the pipe
91 # number from erlang.pipe.1.* to erlang.pipe.2.*, so should read and write
92 # from latest pipe files. For now we are removing all the pipes before
93 # starting LINC.
94 ### User Name ###
95 user = os.getlogin()
96 ### pipes ###
97 readPipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.r".format(user)
98 writePipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.w".format(user)
99 ### sys.config path ###
100 sysConfig = "/home/{}/linc-oe/rel/linc/releases/1.0/sys.config".format(user)
101 ### method, mapping dpid to LINC switchId ###
102 @staticmethod
103 def dpids_to_ids(sysConfig):
104 '''
105 return the dict containing switch dpids as key and LINC switch id as values
106 '''
107 dpids_to_ids = {}
108 fd = None
109 try:
110 with open(sysConfig, 'r', 0) as fd:
111 switch_id = 1
112 for line in fd:
113 dpid = re.search(r'([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})+', line, re.I)
114 if dpid:
115 dpids_to_ids[dpid.group().replace(':', '')] = switch_id
116 switch_id += 1
117 return dpids_to_ids
118 except:
119 print "Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info())
120 fd.close()
121 return None
122 ### dict of containing dpids as key and corresponding LINC switchId as values ###
123 dpidsToLINCSwitchId = dpids_to_ids.__func__(sysConfig)
124 @staticmethod
125 def findDir(directory, userName):
126 "finds and returns the path of any directory in the user's home directory"
127 homeDir = '/home/' + userName
128 Dir = quietRun('find %s -maxdepth 1 -name %s -type d' % (homeDir, directory)).strip('\n')
129 DirList = Dir.split('\n')
130 if not Dir:
131 return None
132 elif len(DirList) > 1 :
133 warn('***WARNING: Found multiple instances of %s; using %s\n'
134 % (directory, DirList[ 0 ]))
135 return DirList[ 0 ]
136 else:
137 return Dir
138 ### ONOS Directory ###
139 try:
140 onosDir = os.environ[ 'ONOS_ROOT' ]
141 except:
142 onosDir = findDir('onos', user)
143 if not onosDir:
144 error('Please set ONOS_ROOT environment variable!\n')
145 else:
146 os.environ[ 'ONOS_ROOT' ] = onosDir
147 ### LINC-directory
148 lincDir = findDir.__func__('linc-oe', user)
149 if not lincDir:
150 error("***ERROR: Could not find linc-oe in user's home directory\n")
151 ### LINC config generator directory###
152 configGen = findDir.__func__('LINC-config-generator', user)
153 if not configGen:
154 error("***ERROR: Could not find LINC-config-generator in user's home directory\n")
155 # list of all the controllers
156 controllers = None
157 def __init__(self, name, dpid=None, allowed=True,
158 switchType='ROADM', topo=None, annotations={}, controller=None, **params):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800159 params[ 'inNamespace' ] = False
fahad44e62c72015-03-04 14:55:35 -0800160 Switch.__init__(self, name, dpid=dpid, **params)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800161 self.name = name
162 self.annotations = annotations
163 self.allowed = allowed
164 self.switchType = switchType
fahad44e62c72015-03-04 14:55:35 -0800165 self.configDict = {} # dictionary that holds all of the JSON configuration data
166 self.crossConnects = []
167 self.deletedCrossConnects = []
168 self.controller = controller
169 self.lincId = self._get_linc_id() # use to communicate with LINC
170 self.lincStarted = False
Brian O'Connoreb27c452014-12-07 02:43:58 -0800171
fahad44e62c72015-03-04 14:55:35 -0800172 def start(self, *opts, **params):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800173 '''Instead of starting a virtual switch, we build the JSON
174 dictionary for the emulated optical switch'''
fahad44e62c72015-03-04 14:55:35 -0800175 # TODO:Once LINC has the ability to spawn network element dynamically
176 # we need to use this method to spawn new logical LINC switch rather then
177 # bulding JSON.
178 # if LINC is started then we can start and stop logical switches else create JSON
179 if self.lincStarted:
180 return self.start_oe()
Brian O'Connoreb27c452014-12-07 02:43:58 -0800181 self.configDict[ 'uri' ] = 'of:' + self.dpid
182 self.configDict[ 'annotations' ] = self.annotations
fahad44e62c72015-03-04 14:55:35 -0800183 self.configDict[ 'annotations' ].setdefault('name', self.name)
184 self.configDict[ 'hw' ] = 'LINC-OE'
Brian O'Connoreb27c452014-12-07 02:43:58 -0800185 self.configDict[ 'mfr' ] = 'Linc'
186 self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
187 self.configDict[ 'type' ] = self.switchType
188 self.configDict[ 'ports' ] = []
189 for port, intf in self.intfs.items():
190 if intf.name == 'lo':
191 continue
192 else:
fahad44e62c72015-03-04 14:55:35 -0800193 self.configDict[ 'ports' ].append(intf.json())
194 self.lincStarted = True
Brian O'Connoreb27c452014-12-07 02:43:58 -0800195
fahad44e62c72015-03-04 14:55:35 -0800196 def stop(self, deleteIntfs=False):
197 '''
198 stop the existing switch
199 '''
200 # TODO:Add support for deleteIntf
201 self.stop_oe()
Brian O'Connoreb27c452014-12-07 02:43:58 -0800202
fahad44e62c72015-03-04 14:55:35 -0800203 def dpctl( self, *args ):
204 "Run dpctl command: ignore for now"
Brian O'Connoreb27c452014-12-07 02:43:58 -0800205 pass
206
fahad44e62c72015-03-04 14:55:35 -0800207 def write_to_cli(self, command):
208 '''
209 send command to LINC
210 '''
211 fd = None
212 try:
213 fd = open(self.writePipe, 'w', 0)
214 fd.write(command)
215 fd.close()
216 except:
217 print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info())
218 if fd:
219 fd.close()
Brian O'Connoreb27c452014-12-07 02:43:58 -0800220
fahad44e62c72015-03-04 14:55:35 -0800221 def read_from_cli(self):
222 '''
223 read the output from the LINC CLI
224 '''
225 response = None
226 fd = None
227 try:
228 fd = open(self.readPipe, 'r', 0)
229 fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) # for non-blocking read
230 # FIXME:Due to non-blocking read most for the time we read nothing
231 response = fd.read()
232 fd.close()
233 except :
234 # print "Error working with {}\nError: {}\n".format(self.readPipe, sys.exc_info())
235 if fd:
236 fd.close()
237 return response
238
239 def _get_linc_id(self):
240 '''
241 return the corresponding LINC switchId.
242 '''
243 return LINCSwitch.dpidsToLINCSwitchId.get(self.dpid)
244 #--------------------------------------------------------------------------
245 # LINC CLI commands
246 #--------------------------------------------------------------------------
247 def start_oe(self):
248 '''
249 start the existing LINC switch
250 '''
251 #starting Switch
252 cmd = "linc:start_switch({}).\r\n".format(self.lincId)
253 self.write_to_cli(cmd)
254 #hanlding taps interfaces related to the switch
255 crossConnectJSON = {}
256 linkConfig = []
257 for i in range(0,len(self.deletedCrossConnects)):
258 crossConnect = self.deletedCrossConnects.pop()
259 tap = None
260 if isinstance(crossConnect.intf1.node, LINCSwitch):
261 intf = crossConnect.intf2
262 tapPort = crossConnect.intf1.port
263 else:
264 intf = crossConnect.intf1
265 tapPort = crossConnect.intf2.port
266 tap = LINCSwitch.findTap(self, tapPort)
267 if tap:
268 LINCSwitch.setupInts([tap])
269 intf.node.attach(tap)
270 self.crossConnects.append(crossConnect)
271 linkConfig.append(crossConnect.json())
272 #Sending crossConnect info to the ONOS.
273 crossConnectJSON['links'] = linkConfig
274 with open("crossConnect.json", 'w') as fd:
275 json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': '))
276 info('*** Pushing crossConnect.json to ONOS\n')
277 output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\
278 Topology.json' % (self.onosDir, self.controllers[ 0 ].ip), shell=True)
279
280 def stop_oe(self):
281 '''
282 stop the existing LINC switch
283 '''
284 cmd = "linc:stop_switch({}).\r\n".format(self.lincId)
285 self.write_to_cli(cmd)
286 #handling taps if any
287 for i in range(0, len(self.crossConnects)):
288 crossConnect = self.crossConnects.pop()
289 if isinstance(crossConnect.intf1.node, LINCSwitch):
290 intf = crossConnect.intf2
291 tapPort = crossConnect.intf1.port
292 else:
293 intf = crossConnect.intf1
294 tapPort = crossConnect.intf2.port
295 intf.node.detach(LINCSwitch.findTap(self, tapPort))
296 self.deletedCrossConnects.append(crossConnect)
297
298 def w_port_up(self, port):
299 '''
300 port_up
301 '''
302 cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port)
303 self.write_to_cli(cmd)
304
305 def w_port_down(self, port):
306 '''
307 port_down
308 '''
309 cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port)
310 self.write_to_cli(cmd)
311
312 # helper functions
313 @staticmethod
314 def switchJSON(switch):
315 "Returns the json configuration for a packet switch"
316 configDict = {}
317 configDict[ 'uri' ] = 'of:' + switch.dpid
318 configDict[ 'mac' ] = quietRun('cat /sys/class/net/%s/address' % switch.name).strip('\n').translate(None, ':')
319 configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
320 configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
321 configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
322 annotations = switch.params.get('annotations', {})
323 annotations.setdefault('name', switch.name)
324 configDict[ 'annotations' ] = annotations
325 ports = []
326 for port, intf in switch.intfs.items():
327 if intf.name == 'lo':
328 continue
329 portDict = {}
330 portDict[ 'port' ] = port
331 portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER'
332 intfList = [ intf.link.intf1, intf.link.intf2 ]
333 intfList.remove(intf)
334 portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0
335 ports.append(portDict)
336 configDict[ 'ports' ] = ports
337 return configDict
338
339 @staticmethod
340 def bootOE(net):
341 "Start the LINC optical emulator within a mininet instance"
342 opticalJSON = {}
343 linkConfig = []
344 devices = []
345 #setting up the controllers for LINCSwitch class
346 LINCSwitch.controllers = net.controllers
347
348 for switch in net.switches:
349 if isinstance(switch, OpticalSwitch):
350 devices.append(switch.json())
351 else:
352 devices.append(LINCSwitch.switchJSON(switch))
353 opticalJSON[ 'devices' ] = devices
354
355 for link in net.links:
356 if isinstance(link, LINCLink) :
357 linkConfig.append(link.json())
358 opticalJSON[ 'links' ] = linkConfig
359
360 info('*** Writing Topology.json file\n')
361 with open('Topology.json', 'w') as outfile:
362 json.dump(opticalJSON, outfile, indent=4, separators=(',', ': '))
363
364 info('*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n')
365 output = quietRun('%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' % LINCSwitch.onosDir, shell=True)
366 if output:
367 error('***ERROR: Error creating topology file: %s ' % output + '\n')
368 return False
369
370 info('*** Creating sys.config...\n')
371 output = quietRun('%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
372 % (LINCSwitch.configGen, LINCSwitch.configGen, LINCSwitch.controllers[ 0 ].ip, LINCSwitch.controllers[ 0 ].port), shell=True)
373 if output:
374 error('***ERROR: Error creating sys.config file: %s\n' % output)
375 return False
376
377 info ('*** Setting multiple controllers in sys.config...\n')
378 searchStr = '\[{"Switch.*$'
379 ctrlStr = ''
380 for index in range(len(LINCSwitch.controllers)):
381 ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port)
382 replaceStr = '[%s]},' % ctrlStr[:-1] # Cut off last comma
383 sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
384 output = quietRun(sedCmd, shell=True)
385
386 info('*** Copying sys.config to linc-oe directory: ', output + '\n')
387 output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' % LINCSwitch.lincDir, shell=True).strip('\n')
388 info(output + '\n')
389
390 info('*** Adding taps and bringing them up...\n')
391 LINCSwitch.setupInts(LINCSwitch.getTaps())
392
393 info('*** removing pipes if any \n')
394 quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user, shell=True)
395
396 info('*** Starting linc OE...\n')
397 output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir, shell=True)
398 if output:
399 error('***ERROR: LINC-OE: %s' % output + '\n')
400 quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
401 return False
402
403 info('*** Waiting for linc-oe to start...\n')
404 LINCSwitch.waitStarted(net)
405
406 info('*** Adding cross-connect (tap) interfaces to packet switches...\n')
407 for link in net.links:
408 if isinstance(link, LINCLink):
409 if link.annotations[ 'optical.type' ] == 'cross-connect':
410 for intf in [ link.intf1, link.intf2 ]:
411 if not isinstance(intf, LINCIntf):
412 intfList = [ intf.link.intf1, intf.link.intf2 ]
413 intfList.remove(intf)
414 intf2 = intfList[ 0 ]
415 intf.node.attach(LINCSwitch.findTap(intf2.node, intf2.node.ports[ intf2 ]))
416
417 info('*** Press ENTER to push Topology.json to onos...\n')
418 raw_input() # FIXME... we should eventually remove this
419 info('*** Pushing Topology.json to ONOS\n')
420 output = quietRun('%s/tools/test/bin/onos-topo-cfg %s Topology.json' % (LINCSwitch.onosDir, LINCSwitch.controllers[ 0 ].ip), shell=True)
421 # successful output contains the two characters '{}'
422 # if there is more output than this, there is an issue
423 if output.strip('{}'):
424 warn('***WARNING: Could not push topology file to ONOS: %s' % output)
425
426 @staticmethod
427 def waitStarted(net, timeout=None):
428 "wait until all tap interfaces are available"
429 tapCount = 0
430 time = 0
431 for link in net.links:
432 if isinstance(link, LINCLink):
433 if link.annotations[ 'optical.type' ] == 'cross-connect':
434 tapCount += 1
435
436 while True:
437 if str(tapCount) == quietRun('ip addr | grep tap | wc -l', shell=True).strip('\n'):
438 return True
439 if timeout:
440 if time >= timeout:
441 error('***ERROR: Linc OE did not start within %s seconds' % timeout)
442 return False
443 time += .5
444 sleep(.5)
445
446 @staticmethod
447 def shutdownOE():
448 "stop the optical emulator"
449 info('*** Stopping linc OE...\n')
450 quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
451
452 @staticmethod
453 def setupInts(intfs):
454 '''
455 add taps and bring them up.
456 '''
457 for i in intfs:
458 quietRun('ip tuntap add dev %s mode tap' % i)
459 quietRun('ip link set dev %s up' % i)
460 info('*** Intf %s set\n' % i)
461
462 @staticmethod
463 def getTaps(path=None):
464 '''
465 return list of all the tops in sys.config
466 '''
467 if path is None:
468 path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
469 fd = open(path, 'r', 0)
470 sys_data = fd.read()
471 taps = re.findall('tap\d+', sys_data)
472 fd.close()
473 return taps
474
475 @staticmethod
476 def findUser():
477 "Try to return logged-in (usually non-root) user"
478 try:
479 # If we're running sudo
480 return os.environ[ 'SUDO_USER' ]
481 except:
482 try:
483 # Logged-in user (if we have a tty)
484 return quietRun('who am i').split()[ 0 ]
485 except:
486 # Give up and return effective user
487 return quietRun('whoami')
488
489
490 @staticmethod
491 def findTap(node, port, path=None):
492 '''utility function to parse through a sys.config
493 file to find tap interfaces for a switch'''
494 switch = False
495 portLine = ''
496 intfLines = []
497
498 if path is None:
499 path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
500
501 with open(path) as f:
502 for line in f:
503 if 'tap' in line:
504 intfLines.append(line)
505 if node.dpid in line.translate(None, ':'):
506 switch = True
507 continue
508 if switch:
509 if 'switch' in line:
510 switch = False
511 if 'port_no,%s}' % port in line:
512 portLine = line
513 break
514
515 if portLine:
516 m = re.search('port,\d+', portLine)
517 port = m.group(0).split(',')[ 1 ]
518 else:
519 error('***ERROR: Could not find any ports in sys.config\n')
520 return
521
522 for intfLine in intfLines:
523 if 'port,%s' % port in intfLine:
524 return re.findall('tap\d+', intfLine)[ 0 ]
525
526 def json(self):
527 "return json configuration dictionary for switch"
528 return self.configDict
529
530 def terminate(self):
531 pass
532
533class LINCLink(Link):
534 """
535 LINC link class
536 """
537 def __init__(self, node1, node2, port1=None, port2=None, allowed=True,
Brian O'Connoreb27c452014-12-07 02:43:58 -0800538 intfName1=None, intfName2=None, linkType='OPTICAL',
fahad44e62c72015-03-04 14:55:35 -0800539 annotations={}, speed1=0, speed2=0, **params):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800540 "Creates a dummy link without a virtual ethernet pair."
541 self.allowed = allowed
542 self.annotations = annotations
543 self.linkType = linkType
fahad44e62c72015-03-04 14:55:35 -0800544 self.port1 = port1
545 self.port2 = port2
Brian O'Connoreb27c452014-12-07 02:43:58 -0800546 params1 = { 'speed': speed1 }
547 params2 = { 'speed': speed2 }
fahad44e62c72015-03-04 14:55:35 -0800548 # self.isCrossConnect = True if self.annotations.get('optical.type') == 'cross-connect' else False
549 if isinstance(node1, LINCSwitch) and isinstance(node2, LINCSwitch):
550 self.isCrossConnect = False
551 else:
552 self.isCrossConnect = True
553 if isinstance(node1, LINCSwitch):
554 cls1 = LINCIntf
555 if self.isCrossConnect:
556 node1.crossConnects.append(self)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800557 else:
558 cls1 = Intf
559 # bad hack to stop error message from appearing when we try to set up intf in a packet switch,
560 # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up
561 intfName1 = 'lo'
fahad44e62c72015-03-04 14:55:35 -0800562 if isinstance(node2, LINCSwitch):
563 cls2 = LINCIntf
564 if self.isCrossConnect:
565 node2.crossConnects.append(self)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800566 else:
567 cls2 = Intf
568 intfName2 = 'lo'
fahad44e62c72015-03-04 14:55:35 -0800569 Link.__init__(self, node1, node2, port1=port1, port2=port2,
Brian O'Connoreb27c452014-12-07 02:43:58 -0800570 intfName1=intfName1, intfName2=intfName2, cls1=cls1,
fahad44e62c72015-03-04 14:55:35 -0800571 cls2=cls2, params1=params1, params2=params2)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800572
573 @classmethod
fahad44e62c72015-03-04 14:55:35 -0800574 def makeIntfPair(_cls, intfName1, intfName2, *args, **kwargs):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800575 pass
576
fahad44e62c72015-03-04 14:55:35 -0800577 def json(self):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800578 "build and return the json configuration dictionary for this link"
579 configData = {}
fahad44e62c72015-03-04 14:55:35 -0800580 configData[ 'src' ] = ('of:' + self.intf1.node.dpid +
581 '/%s' % self.intf1.node.ports[ self.intf1 ])
582 configData[ 'dst' ] = ('of:' + self.intf2.node.dpid +
583 '/%s' % self.intf2.node.ports[ self.intf2 ])
Brian O'Connoreb27c452014-12-07 02:43:58 -0800584 configData[ 'type' ] = self.linkType
585 configData[ 'annotations' ] = self.annotations
586 return configData
587
fahad44e62c72015-03-04 14:55:35 -0800588class LINCIntf(OpticalIntf):
589 """
590 LINC interface class
591 """
592 def __init__(self, name=None, node=None, speed=0,
593 port=None, link=None, **params):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800594 self.node = node
595 self.speed = speed
596 self.port = port
597 self.link = link
598 self.name = name
fahad44e62c72015-03-04 14:55:35 -0800599 node.addIntf(self, port=port)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800600 self.params = params
601 self.ip = None
602
fahad44e62c72015-03-04 14:55:35 -0800603 def json(self):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800604 "build and return the JSON information for this interface( not used right now )"
605 configDict = {}
606 configDict[ 'port' ] = self.port
607 configDict[ 'speed' ] = self.speed
608 configDict[ 'type' ] = 'FIBER'
609 return configDict
610
fahad44e62c72015-03-04 14:55:35 -0800611 def config(self, *args, **kwargs):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800612 "dont configure a dummy interface"
613 pass
614
fahad44e62c72015-03-04 14:55:35 -0800615 def ifconfig(self, status):
616 "configure the status"
617 if status == "up":
618 return self.node.w_port_up(self.port)
619 elif status == "down":
620 return self.node.w_port_down(self.port)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800621
622
fahad44e62c72015-03-04 14:55:35 -0800623class MininetOE(Mininet):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800624 "Mininet with Linc-OE support (starts and stops linc-oe)"
625
fahad44e62c72015-03-04 14:55:35 -0800626 def start(self):
627 Mininet.start(self)
628 LINCSwitch.bootOE(self)
Brian O'Connoreb27c452014-12-07 02:43:58 -0800629
fahad44e62c72015-03-04 14:55:35 -0800630 def stop(self):
631 Mininet.stop(self)
632 LINCSwitch.shutdownOE()
Brian O'Connoreb27c452014-12-07 02:43:58 -0800633
fahad44e62c72015-03-04 14:55:35 -0800634 def addControllers(self, controllers):
Brian O'Connoreb27c452014-12-07 02:43:58 -0800635 i = 0
636 for ctrl in controllers:
fahad44e62c72015-03-04 14:55:35 -0800637 self.addController(RemoteController('c%d' % i, ip=ctrl))
638 i += 1
Brian O'Connoreb27c452014-12-07 02:43:58 -0800639
640if __name__ == '__main__':
fahad44e62c72015-03-04 14:55:35 -0800641 pass