diff options
Diffstat (limited to 'framework/src/onos/tools/test/topos/opticalUtils.py')
-rw-r--r-- | framework/src/onos/tools/test/topos/opticalUtils.py | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/framework/src/onos/tools/test/topos/opticalUtils.py b/framework/src/onos/tools/test/topos/opticalUtils.py new file mode 100644 index 00000000..bef9deca --- /dev/null +++ b/framework/src/onos/tools/test/topos/opticalUtils.py @@ -0,0 +1,771 @@ +#!/usr/bin/python + +''' +Notes: + +This file contains classes and methods useful for integrating LincOE with Mininet, +such as startOE, stopOE, LINCLink, and OpticalSwitch + +- $ONOS_ROOT ust be set +- Need to run with sudo -E to preserve ONOS_ROOT env var +- We assume LINC-Config-Generator is named LINC-Config-Generator +- We also assume linc-oe is named linc-oe +- LINC-config-generator and linc-oe must be subdirectories of the user's + home directory + + TODO + ----------- + - clean up files after runtime + - maybe save the old files in a separate directory? + - modify script to allow startOE to run before net.start() + - add ONOS as a controller in script + + Usage: + ------------ + - import LINCLink and OpticalSwitch from this module + - import startOE and stopOE from this module + - create topology as you would a normal topology. when + to an optical switch with topo.addLink, always specify cls=LINCLink + - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch + - for annotations on links and switches, a dictionary must be passed in as + the annotations argument + - startOE must be run AFTER net.start() with net as an argument. + - stopOE can be run at any time + +I created a separate function to start lincOE to avoid subclassing Mininet. +In case anyone wants to write something that DOES subclass Mininet, I +thought I would outline how: + +If we want an object that starts lincOE within the mininet class itself, +we need to add another object to Mininet that contains all of the json object +information for each switch. We would still subclass switch and link, but these +classes would basically be dummy classes that store their own json information +in the Mininet class object. We may also change the default switch class to add +it's tap interfaces from lincOE during startup. The start() method for mininet would +grab all of the information from these switches and links, write configuration files +for lincOE using the json module, start lincOE, then run the start methodfor each +switch. The new start() method for each switch would parse through the sys.config +file that was created and find the tap interface it needs to connect to, similar +to the findTap function that I currently use. After all of the controllers and +switches have been started, the new Mininet start() method should also push the +Topology configuration file to ONOS. + +''' +import sys +import re +import json +import os +from time import sleep +import urllib2 + +from mininet.node import Switch, RemoteController +from mininet.topo import Topo +from mininet.util import quietRun +from mininet.net import Mininet +from mininet.log import setLogLevel, info, error, warn +from mininet.link import Link, Intf +from mininet.cli import CLI + +# Sleep time and timeout values in seconds +SLEEP_TIME = 2 +TIMEOUT = 60 + +REST_USER = 'onos' +REST_PW = 'rocks' + +class OpticalSwitch(Switch): + """ + For now, same as Switch class. + """ + pass + +class OpticalIntf(Intf): + """ + For now,same as Intf class. + """ + pass + +class OpticalLink(Link): + """ + For now, same as Link. + """ + pass + +class LINCSwitch(OpticalSwitch): + """ + LINCSwitch class + """ + # FIXME:Sometimes LINC doesn't remove pipes and on restart increase the pipe + # number from erlang.pipe.1.* to erlang.pipe.2.*, so should read and write + # from latest pipe files. For now we are removing all the pipes before + # starting LINC. + ### User Name ### + user = os.getlogin() + ### pipes ### + readPipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.r".format(user) + writePipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.w".format(user) + ### sys.config path ### + sysConfig = "/home/{}/linc-oe/rel/linc/releases/1.0/sys.config".format(user) + ### method, mapping dpid to LINC switchId ### + @staticmethod + def dpids_to_ids(sysConfig): + ''' + return the dict containing switch dpids as key and LINC switch id as values + ''' + dpids_to_ids = {} + fd = None + try: + with open(sysConfig, 'r', 0) as fd: + switch_id = 1 + for line in fd: + dpid = re.search(r'([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})+', line, re.I) + if dpid: + dpids_to_ids[dpid.group().replace(':', '')] = switch_id + switch_id += 1 + return dpids_to_ids + except: + print "Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info()) + fd.close() + return None + ### dict of containing dpids as key and corresponding LINC switchId as values ### + dpidsToLINCSwitchId = dpids_to_ids.__func__(sysConfig) + @staticmethod + def findDir(directory, userName): + "finds and returns the path of any directory in the user's home directory" + homeDir = '/home/' + userName + Dir = quietRun('find %s -maxdepth 1 -name %s -type d' % (homeDir, directory)).strip('\n') + DirList = Dir.split('\n') + if not Dir: + return None + elif len(DirList) > 1 : + warn('***WARNING: Found multiple instances of %s; using %s\n' + % (directory, DirList[ 0 ])) + return DirList[ 0 ] + else: + return Dir + ### ONOS Directory ### + try: + onosDir = os.environ[ 'ONOS_ROOT' ] + except: + onosDir = findDir('onos', user) + if not onosDir: + error('Please set ONOS_ROOT environment variable!\n') + else: + os.environ[ 'ONOS_ROOT' ] = onosDir + ### LINC-directory + lincDir = findDir.__func__('linc-oe', user) + if not lincDir: + error("***ERROR: Could not find linc-oe in user's home directory\n") + ### LINC config generator directory### + configGen = findDir.__func__('LINC-config-generator', user) + if not configGen: + error("***ERROR: Could not find LINC-config-generator in user's home directory\n") + # list of all the controllers + controllers = None + def __init__(self, name, dpid=None, allowed=True, + switchType='ROADM', topo=None, annotations={}, controller=None, **params): + params[ 'inNamespace' ] = False + Switch.__init__(self, name, dpid=dpid, **params) + self.name = name + self.annotations = annotations + self.allowed = allowed + self.switchType = switchType + self.configDict = {} # dictionary that holds all of the JSON configuration data + self.crossConnects = [] + self.deletedCrossConnects = [] + self.controller = controller + self.lincId = self._get_linc_id() # use to communicate with LINC + self.lincStarted = False + + def start(self, *opts, **params): + '''Instead of starting a virtual switch, we build the JSON + dictionary for the emulated optical switch''' + # TODO:Once LINC has the ability to spawn network element dynamically + # we need to use this method to spawn new logical LINC switch rather then + # bulding JSON. + # if LINC is started then we can start and stop logical switches else create JSON + if self.lincStarted: + return self.start_oe() + self.configDict[ 'uri' ] = 'of:' + self.dpid + self.configDict[ 'annotations' ] = self.annotations + self.configDict[ 'annotations' ].setdefault('name', self.name) + self.configDict[ 'hw' ] = 'LINC-OE' + self.configDict[ 'mfr' ] = 'Linc' + self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1] + self.configDict[ 'type' ] = self.switchType + self.configDict[ 'ports' ] = [] + for port, intf in self.intfs.items(): + if intf.name == 'lo': + continue + else: + self.configDict[ 'ports' ].append(intf.json()) + self.lincStarted = True + + def stop(self, deleteIntfs=False): + ''' + stop the existing switch + ''' + # TODO:Add support for deleteIntf + self.stop_oe() + + def dpctl( self, *args ): + "Run dpctl command: ignore for now" + pass + + def write_to_cli(self, command): + ''' + send command to LINC + ''' + fd = None + try: + fd = open(self.writePipe, 'w', 0) + fd.write(command) + fd.close() + except: + print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info()) + if fd: + fd.close() + + def read_from_cli(self): + ''' + read the output from the LINC CLI + ''' + response = None + fd = None + try: + fd = open(self.readPipe, 'r', 0) + fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) # for non-blocking read + # FIXME:Due to non-blocking read most for the time we read nothing + response = fd.read() + fd.close() + except : + # print "Error working with {}\nError: {}\n".format(self.readPipe, sys.exc_info()) + if fd: + fd.close() + return response + + def _get_linc_id(self): + ''' + return the corresponding LINC switchId. + ''' + return LINCSwitch.dpidsToLINCSwitchId.get(self.dpid) + #-------------------------------------------------------------------------- + # LINC CLI commands + #-------------------------------------------------------------------------- + def start_oe(self): + ''' + existing LINC switch + ''' + #starting Switch + cmd = "linc:start_switch({}).\r\n".format(self.lincId) + self.write_to_cli(cmd) + #hanlding taps interfaces related to the switch + crossConnectJSON = {} + linkConfig = [] + for i in range(0,len(self.deletedCrossConnects)): + crossConnect = self.deletedCrossConnects.pop() + tap = None + if isinstance(crossConnect.intf1.node, LINCSwitch): + intf = crossConnect.intf2 + tapPort = crossConnect.intf1.port + else: + intf = crossConnect.intf1 + tapPort = crossConnect.intf2.port + tap = LINCSwitch.findTap(self, tapPort) + if tap: + LINCSwitch.setupInts([tap]) + intf.node.attach(tap) + self.crossConnects.append(crossConnect) + linkConfig.append(crossConnect.json()) + #Sending crossConnect info to the ONOS. + crossConnectJSON['links'] = linkConfig + with open("crossConnect.json", 'w') as fd: + json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': ')) + info('*** Pushing crossConnect.json to ONOS\n') + output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\ + Topology.json' % (self.onosDir, self.controllers[ 0 ].ip), shell=True) + + def stop_oe(self): + ''' + stop the existing LINC switch + ''' + cmd = "linc:stop_switch({}).\r\n".format(self.lincId) + self.write_to_cli(cmd) + #handling taps if any + for i in range(0, len(self.crossConnects)): + crossConnect = self.crossConnects.pop() + if isinstance(crossConnect.intf1.node, LINCSwitch): + intf = crossConnect.intf2 + tapPort = crossConnect.intf1.port + else: + intf = crossConnect.intf1 + tapPort = crossConnect.intf2.port + intf.node.detach(LINCSwitch.findTap(self, tapPort)) + self.deletedCrossConnects.append(crossConnect) + + def w_port_up(self, port): + ''' + port_up + ''' + cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port) + self.write_to_cli(cmd) + + def w_port_down(self, port): + ''' + port_down + ''' + cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port) + self.write_to_cli(cmd) + + # helper functions + @staticmethod + def switchJSON(switch): + "Returns the json configuration for a packet switch" + configDict = {} + configDict[ 'uri' ] = 'of:' + switch.dpid + configDict[ 'mac' ] = quietRun('cat /sys/class/net/%s/address' % switch.name).strip('\n').translate(None, ':') + configDict[ 'hw' ] = 'PK' # FIXME what about OVS? + configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS? + configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS? + annotations = switch.params.get('annotations', {}) + annotations.setdefault('name', switch.name) + configDict[ 'annotations' ] = annotations + ports = [] + for port, intf in switch.intfs.items(): + if intf.name == 'lo': + continue + portDict = {} + portDict[ 'port' ] = port + portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER' + intfList = [ intf.link.intf1, intf.link.intf2 ] + intfList.remove(intf) + portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0 + ports.append(portDict) + configDict[ 'ports' ] = ports + return configDict + + @staticmethod + def bootOE(net): + "Start the LINC optical emulator within a mininet instance" + LINCSwitch.opticalJSON = {} + linkConfig = [] + devices = [] + #setting up the controllers for LINCSwitch class + LINCSwitch.controllers = net.controllers + + for switch in net.switches: + if isinstance(switch, OpticalSwitch): + devices.append(switch.json()) + else: + devices.append(LINCSwitch.switchJSON(switch)) + LINCSwitch.opticalJSON[ 'devices' ] = devices + + for link in net.links: + if isinstance(link, LINCLink) : + linkConfig.append(link.json()) + LINCSwitch.opticalJSON[ 'links' ] = linkConfig + + info('*** Writing Topology.json file\n') + with open('Topology.json', 'w') as outfile: + json.dump(LINCSwitch.opticalJSON, outfile, indent=4, separators=(',', ': ')) + + info('*** Converting Topology.json to linc-oe format (TopoConfig.json) file (no oecfg) \n') + + topoConfigJson = {}; + dpIdToName = {}; + + topoConfigJson["switchConfig"] = LINCSwitch.getSwitchConfig(dpIdToName); + topoConfigJson["linkConfig"] = LINCSwitch.getLinkConfig(dpIdToName); + + #Writing to TopoConfig.json + with open( 'TopoConfig.json', 'w' ) as outfile: + json.dump( topoConfigJson, outfile, indent=4, separators=(',', ': ') ) + + info('*** Creating sys.config...\n') + output = quietRun('%s/config_generator TopoConfig.json %s/sys.config.template %s %s' + % (LINCSwitch.configGen, LINCSwitch.configGen, LINCSwitch.controllers[ 0 ].ip, LINCSwitch.controllers[ 0 ].port), shell=True) + if output: + error('***ERROR: Error creating sys.config file: %s\n' % output) + return False + + info ('*** Setting multiple controllers in sys.config...\n') + searchStr = '\[{"Switch.*$' + ctrlStr = '' + for index in range(len(LINCSwitch.controllers)): + ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port) + replaceStr = '[%s]},' % ctrlStr[:-1] # Cut off last comma + sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr) + output = quietRun(sedCmd, shell=True) + + info('*** Copying sys.config to linc-oe directory: ', output + '\n') + output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' % LINCSwitch.lincDir, shell=True).strip('\n') + info(output + '\n') + + info('*** Adding taps and bringing them up...\n') + LINCSwitch.setupInts(LINCSwitch.getTaps()) + + info('*** removing pipes if any \n') + quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user, shell=True) + + info('*** Starting linc OE...\n') + output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir, shell=True) + if output: + error('***ERROR: LINC-OE: %s' % output + '\n') + quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True) + return False + + info('*** Waiting for linc-oe to start...\n') + LINCSwitch.waitStarted(net) + + info('*** Adding cross-connect (tap) interfaces to packet switches...\n') + for link in net.links: + if isinstance(link, LINCLink): + if link.annotations[ 'optical.type' ] == 'cross-connect': + for intf in [ link.intf1, link.intf2 ]: + if not isinstance(intf, LINCIntf): + intfList = [ intf.link.intf1, intf.link.intf2 ] + intfList.remove(intf) + intf2 = intfList[ 0 ] + intf.node.attach(LINCSwitch.findTap(intf2.node, intf2.node.ports[ intf2 ])) + + info('*** Waiting for all devices to be available in ONOS...\n') + url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip + time = 0 + # Set up password authentication + pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + pw_mgr.add_password(None, url, REST_USER, REST_PW) + handler = urllib2.HTTPBasicAuthHandler(pw_mgr) + opener = urllib2.build_opener(handler) + opener.open(url) + urllib2.install_opener(opener) + while True: + response = json.load(urllib2.urlopen(url)) + devs = response.get('devices') + + # Wait for all devices to be registered + if (len(devices) != len(devs)): + continue + + # Wait for all devices to available + available = True + for d in devs: + available &= d['available'] + if available: + break + + if (time >= TIMEOUT): + error('***ERROR: ONOS did not register devices within %s seconds\n' % TIMEOUT) + break + + time += SLEEP_TIME + sleep(SLEEP_TIME) + + info('*** Pushing Topology.json to ONOS\n') + for index in range(len(LINCSwitch.controllers)): + output = quietRun('%s/tools/test/bin/onos-topo-cfg %s Topology.json &' % (LINCSwitch.onosDir, LINCSwitch.controllers[ index ].ip), shell=True) + # successful output contains the two characters '{}' + # if there is more output than this, there is an issue + if output.strip('{}'): + warn('***WARNING: Could not push topology file to ONOS: %s\n' % output) + + #converts node ids to linc-oe format, with colons every two chars + @staticmethod + def dpId(id): + nodeDpid = "" + id = id.split("/", 1)[0] + for i in range(3, len(id) - 1, 2): + nodeDpid += (id[i:(i + 2):]) + ":" + return nodeDpid[0:-1]; + + @staticmethod + def getSwitchConfig (dpIdToName): + switchConfig = []; + #Iterate through all switches and convert the ROADM switches to linc-oe format + for switch in LINCSwitch.opticalJSON["devices"]: + if switch.get("type", "none") == "ROADM": + builtSwitch = {} + + #set basic switch params based on annotations + builtSwitch["allowed"] = True; + builtSwitch["latitude"] = switch["annotations"].get("latitude", 0.0); + builtSwitch["longitude"] = switch["annotations"].get("longitude", 0.0); + + #assumed that all switches have this entry + nodeId = switch["uri"] + + #convert the nodeId to linc-oe format + nodeDpid = LINCSwitch.dpId(nodeId); + + builtSwitch["name"] = switch.get("name", "none"); + + #keep track of the name corresponding to each switch dpid + dpIdToName[nodeDpid] = builtSwitch["name"]; + + builtSwitch["nodeDpid"] = nodeDpid + + #set switch params and type + builtSwitch["params"] = {}; + builtSwitch["params"]["numregens"] = switch["annotations"].get("optical.regens", 0); + builtSwitch["type"] = "Roadm" + + #append to list of switches + switchConfig.append(builtSwitch); + return switchConfig + + @staticmethod + def getLinkConfig (dpIdToName): + newLinkConfig = []; + #Iterate through all optical links and convert them to linc-oe format + for link in LINCSwitch.opticalJSON["links"]: + if link.get("type", "none") == "OPTICAL": + builtLink = {} + + #set basic link params for src and dst + builtLink["allowed"] = True; + builtLink["nodeDpid1"] = LINCSwitch.dpId(link["src"]) + builtLink["nodeDpid2"] = LINCSwitch.dpId(link["dst"]) + + #set more params such as name/bandwidth/port/waves if they exist + params = {} + params["nodeName1"] = dpIdToName.get(builtLink["nodeDpid1"], "none") + params["nodeName2"] = dpIdToName.get(builtLink["nodeDpid2"], "none") + + params["port1"] = int(link["src"].split("/")[1]) + params["port2"] = int(link["dst"].split("/")[1]) + + if "bandwidth" in link["annotations"]: + params["bandwidth"] = link["annotations"]["bandwidth"] + + if "optical.waves" in link["annotations"]: + params["numWaves"] = link["annotations"]["optical.waves"] + + builtLink["params"] = params + + #set type of link (WDM or pktOpt) + if link["annotations"].get("optical.type", "cross-connect") == "WDM": + builtLink["type"] = "wdmLink" + else: + builtLink["type"] = "pktOptLink" + + newLinkConfig.append(builtLink); + return newLinkConfig + + + @staticmethod + def waitStarted(net, timeout=TIMEOUT): + "wait until all tap interfaces are available" + tapCount = 0 + time = 0 + for link in net.links: + if isinstance(link, LINCLink): + if link.annotations[ 'optical.type' ] == 'cross-connect': + tapCount += 1 + + while True: + if str(tapCount) == quietRun('ip addr | grep tap | wc -l', shell=True).strip('\n'): + return True + if timeout: + if time >= TIMEOUT: + error('***ERROR: LINC OE did not start within %s seconds\n' % TIMEOUT) + return False + time += SLEEP_TIME + sleep(SLEEP_TIME) + + @staticmethod + def shutdownOE(): + "stop the optical emulator" + info('*** Stopping linc OE...\n') + quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True) + + @staticmethod + def setupInts(intfs): + ''' + add taps and bring them up. + ''' + for i in intfs: + quietRun('ip tuntap add dev %s mode tap' % i) + quietRun('ip link set dev %s up' % i) + info('*** Intf %s set\n' % i) + + @staticmethod + def getTaps(path=None): + ''' + return list of all the tops in sys.config + ''' + if path is None: + path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir + fd = open(path, 'r', 0) + sys_data = fd.read() + taps = re.findall('tap\d+', sys_data) + fd.close() + return taps + + @staticmethod + def findUser(): + "Try to return logged-in (usually non-root) user" + try: + # If we're running sudo + return os.environ[ 'SUDO_USER' ] + except: + try: + # Logged-in user (if we have a tty) + return quietRun('who am i').split()[ 0 ] + except: + # Give up and return effective user + return quietRun('whoami') + + + @staticmethod + def findTap(node, port, path=None): + '''utility function to parse through a sys.config + file to find tap interfaces for a switch''' + switch = False + portLine = '' + intfLines = [] + + if path is None: + path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir + + with open(path) as f: + for line in f: + if 'tap' in line: + intfLines.append(line) + if node.dpid in line.translate(None, ':'): + switch = True + continue + if switch: + if 'switch' in line: + switch = False + if 'port_no,%s}' % port in line: + portLine = line + break + + if portLine: + m = re.search('port,\d+', portLine) + port = m.group(0).split(',')[ 1 ] + else: + error('***ERROR: Could not find any ports in sys.config\n') + return + + for intfLine in intfLines: + if 'port,%s' % port in intfLine: + return re.findall('tap\d+', intfLine)[ 0 ] + + def json(self): + "return json configuration dictionary for switch" + return self.configDict + + def terminate(self): + pass + + + +class LINCLink(Link): + """ + LINC link class + """ + def __init__(self, node1, node2, port1=None, port2=None, allowed=True, + intfName1=None, intfName2=None, linkType='OPTICAL', + annotations={}, speed1=0, speed2=0, **params): + "Creates a dummy link without a virtual ethernet pair." + self.allowed = allowed + self.annotations = annotations + self.linkType = linkType + self.port1 = port1 + self.port2 = port2 + params1 = { 'speed': speed1 } + params2 = { 'speed': speed2 } + # self.isCrossConnect = True if self.annotations.get('optical.type') == 'cross-connect' else False + if isinstance(node1, LINCSwitch) and isinstance(node2, LINCSwitch): + self.isCrossConnect = False + else: + self.isCrossConnect = True + if isinstance(node1, LINCSwitch): + cls1 = LINCIntf + if self.isCrossConnect: + node1.crossConnects.append(self) + else: + cls1 = Intf + # bad hack to stop error message from appearing when we try to set up intf in a packet switch, + # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up + intfName1 = 'lo' + if isinstance(node2, LINCSwitch): + cls2 = LINCIntf + if self.isCrossConnect: + node2.crossConnects.append(self) + else: + cls2 = Intf + intfName2 = 'lo' + Link.__init__(self, node1, node2, port1=port1, port2=port2, + intfName1=intfName1, intfName2=intfName2, cls1=cls1, + cls2=cls2, params1=params1, params2=params2) + + @classmethod + def makeIntfPair(_cls, intfName1, intfName2, *args, **kwargs): + pass + + def json(self): + "build and return the json configuration dictionary for this link" + configData = {} + configData[ 'src' ] = ('of:' + self.intf1.node.dpid + + '/%s' % self.intf1.node.ports[ self.intf1 ]) + configData[ 'dst' ] = ('of:' + self.intf2.node.dpid + + '/%s' % self.intf2.node.ports[ self.intf2 ]) + configData[ 'type' ] = self.linkType + configData[ 'annotations' ] = self.annotations + return configData + +class LINCIntf(OpticalIntf): + """ + LINC interface class + """ + def __init__(self, name=None, node=None, speed=0, + port=None, link=None, **params): + self.node = node + self.speed = speed + self.port = port + self.link = link + self.name = name + node.addIntf(self, port=port) + self.params = params + self.ip = None + + def json(self): + "build and return the JSON information for this interface( not used right now )" + configDict = {} + configDict[ 'port' ] = self.port + configDict[ 'speed' ] = self.speed + configDict[ 'type' ] = 'FIBER' + return configDict + + def config(self, *args, **kwargs): + "dont configure a dummy interface" + pass + + def ifconfig(self, status): + "configure the status" + if status == "up": + return self.node.w_port_up(self.port) + elif status == "down": + return self.node.w_port_down(self.port) + + +class MininetOE(Mininet): + "Mininet with Linc-OE support (starts and stops linc-oe)" + + def start(self): + Mininet.start(self) + LINCSwitch.bootOE(self) + + def stop(self): + Mininet.stop(self) + LINCSwitch.shutdownOE() + + def addControllers(self, controllers): + i = 0 + for ctrl in controllers: + self.addController(RemoteController('c%d' % i, ip=ctrl)) + i += 1 + +if __name__ == '__main__': + pass |