def convertSDPRouteToLinks(self, source_ep, dest_ep, route): nl_route = [] prev_source_ep = source_ep for sdp in route: nl_route.append( nsa.Link(prev_source_ep, sdp.stp1) ) prev_source_ep = sdp.stp2 # last hop nl_route.append( nsa.Link(prev_source_ep, dest_ep) ) return nl_route
def testPruningEnd(self): ndn_link = nsa.Link( nsa.STP('nordu.net:2013:topology', 'funet', nsa.Label('vlan', '2031-2035')), nsa.STP('nordu.net:2013:topology', 'surfnet', nsa.Label('vlan', '2-4094')) ) sfn_link = nsa.Link( nsa.STP('surfnet.nl:1990:production7', 'nordunet', nsa.Label('vlan', '2-4094')), nsa.STP('surfnet.nl:1990:production7', '19523', nsa.Label('vlan', '2077')) ) path = [ ndn_link, sfn_link ] pruned_path = pruner.pruneLabels(path) self.assertEquals(pruned_path[0].dst_stp.label.labelValue(), '2077') self.assertEquals(pruned_path[1].src_stp.label.labelValue(), '2077')
def findPaths(self, source_stp, dest_stp, bandwidth=None): """ Find possible paths between two endpoints. """ # check that STPs exist snw = self.getNetwork(source_stp.network) sep = snw.getEndpoint(source_stp.endpoint) dnw = self.getNetwork(dest_stp.network) dep = dnw.getEndpoint(dest_stp.endpoint) # find endpoint pairs #print "FIND PATH", source_stp, dest_stp if snw == dnw: # same network, make direct connection and nothing else network_paths = [ [ nsa.Link(sep.network, sep.endpoint, dep.endpoint) ] ] else: network_paths = self.findPathEndpoints(source_stp, dest_stp) if bandwidth is not None: network_paths = self.filterBandwidth(network_paths, bandwidth) # topology cannot represent vlans properly yet # this means that all ports can be matched with all ports internally in a network # this is incorrect if the network does not support vlan rewriting # currently only netherlight supports vlan rewriting (nov. 2011) network_paths = self._pruneMismatchedPorts(network_paths) paths = [ nsa.Path(np) for np in network_paths ] return paths
def testPruningStart(self): sfn_link = nsa.Link( nsa.STP('surfnet.nl:1990:production7', 'ps', nsa.Label('vlan', '1784')), nsa.STP('surfnet.nl:1990:production7', 'sara-ndn1', nsa.Label('vlan', '1780-1799')) ) ndn_link = nsa.Link( nsa.STP('nordu.net:2013:topology', 'surfnet', nsa.Label('vlan', '1784-1789')), nsa.STP('nordu.net:2013:topology', 'deic1', nsa.Label('vlan', '1784-1789')) ) dec_link = nsa.Link( nsa.STP('deic.dk:2013:topology', 'ndn1', nsa.Label('vlan', '1784-1789')), nsa.STP('deic.dk:2013:topology', 'ps', nsa.Label('vlan', '1784')) ) path = [ sfn_link, ndn_link, dec_link ] pruned_path = pruner.pruneLabels(path) self.assertEquals(pruned_path[0].dst_stp.label.labelValue(), '1784') self.assertEquals(pruned_path[1].src_stp.label.labelValue(), '1784')
def findPathEndpoints(self, source_stp, dest_stp, visited_networks=None): #print "FIND PATH EPS", source_stp, visited_networks snw = self.getNetwork(source_stp.network) routes = [] for ep in snw.endpoints: #print " Path:", ep, " ", dest_stp if ep.dest_stp is None: #print " Rejecting endpoint due to no pairing" continue if visited_networks is None: visited_networks = [ source_stp.network ] if ep.dest_stp.network in visited_networks: #print " Rejecting endpoint due to loop" continue source_ep = self.getEndpoint(source_stp.network, source_stp.endpoint) if ep.dest_stp.network == dest_stp.network: sp = nsa.Link(ep.network, source_ep.endpoint, ep.endpoint) # this means last network, so we add the last hop last_source_ep = self.getEndpoint(ep.dest_stp.network, ep.dest_stp.endpoint) last_dest_ep = self.getEndpoint(dest_stp.network, dest_stp.endpoint) sp_end = nsa.Link(last_dest_ep.network, last_source_ep.endpoint, last_dest_ep.endpoint) routes.append( [ sp, sp_end ] ) else: nvn = visited_networks[:] + [ ep.dest_stp.network ] subroutes = self.findPathEndpoints(ep.dest_stp, dest_stp, nvn) if subroutes: for sr in subroutes: src = sr[:] sp = nsa.Link(ep.network, source_ep.endpoint, ep.endpoint) src.insert(0, sp) routes.append( src ) return routes
import StringIO from twisted.trial import unittest from opennsa import nsa from opennsa.topology import gole from . import topology as testtopology TEST_PATH_1 = { 'source_stp': nsa.STP('Aruba', 'A2'), 'dest_stp': nsa.STP('Curacao', 'C3'), 'paths': [[ nsa.Link('Aruba', 'A2', 'A4'), nsa.Link('Bonaire', 'B1', 'B4'), nsa.Link('Curacao', 'C1', 'C3') ], [ nsa.Link('Aruba', 'A2', 'A1'), nsa.Link('Dominica', 'D4', 'D1'), nsa.Link('Curacao', 'C4', 'C3') ]] } TEST_PATH_2 = { 'source_stp': nsa.STP('Aruba', 'A2'), 'dest_stp': nsa.STP('Bonaire', 'B2'),
def _findPathsRecurse(self, source_stp, dest_stp, bandwidth, exclude_networks=None): source_network = self.getNetwork(source_stp.network) dest_network = self.getNetwork(dest_stp.network) source_port = source_network.getPort(source_stp.port) dest_port = dest_network.getPort(dest_stp.port) if not (source_port.canMatchLabel(source_stp.label) or dest_port.canMatchLabel(dest_stp.label)): return [] # if not (source_port.canProvideBandwidth(bandwidth) and dest_port.canProvideBandwidth(bandwidth)): # return [] if source_port.isBidirectional() and dest_port.isBidirectional(): # bidirectional path finding, easy case first if source_stp.network == dest_stp.network: # while it is possible to cross other network in order to connect to intra-network STPs # it is not something we really want to do in the real world, so we don't try: if source_network.canSwapLabel(source_stp.label.type_): source_label = source_port.label().intersect( source_stp.label) dest_label = dest_port.label().intersect( dest_stp.label) else: source_label = source_port.label().intersect( dest_port.label()).intersect( source_stp.label).intersect(dest_stp.label) dest_label = source_label link = nsa.Link(source_stp.network, source_stp.port, dest_stp.port, source_label, dest_label) return [[link]] except nsa.EmptyLabelSet: return [] # no path else: # ok, time for real pathfinding link_ports = source_network.findPorts(True, source_stp.label, source_stp.port) link_ports = [port for port in link_ports if port.hasRemote() ] # filter out termination ports links = [] for lp in link_ports: demarcation = self.findDemarcationPort(lp) if demarcation is None: continue d_network_id, d_port_id = demarcation if exclude_networks is not None and demarcation[ 0] in exclude_networks: continue # don't do loops in path finding demarcation_label = lp.label( ) if source_network.canSwapLabel( source_stp.label.type_ ) else source_stp.label.intersect(lp.label()) demarcation_stp = nsa.STP(demarcation[0], demarcation[1], demarcation_label) sub_exclude_networks = [source_network.id_ ] + (exclude_networks or []) sub_links = self._findPathsRecurse(demarcation_stp, dest_stp, bandwidth, sub_exclude_networks) # if we didn't find any sub paths, just continue if not sub_links: continue for sl in sub_links: # -- if source_network.canSwapLabel(source_stp.label.type_): source_label = source_port.label().intersect( source_stp.label) dest_label = lp.label().intersect( sl[0].src_stp.label) else: source_label = source_port.label().intersect( source_stp.label).intersect( lp.label()).intersect(sl[0].src_stp.label) dest_label = source_label first_link = nsa.Link(source_stp.network, source_stp.port, lp.id_, source_label, dest_label) path = [first_link] + sl links.append(path) return sorted(links, key=len) # sort by length, shortest first else: raise error.TopologyError( 'Unidirectional path-finding not implemented yet')
def reserve(self, requester_nsa, provider_nsa, session_security_attr, global_reservation_id, description, connection_id, service_parameters, sub): # -- log.msg('', system='opennsa') log.msg('Connection %s. Reserve request from %s.' % (connection_id, requester_nsa), system=LOG_SYSTEM) if connection_id in self.connections.get(requester_nsa, {}): return defer.fail( error.ReserveError('Connection with id %s already exists' % connection_id)) source_stp = service_parameters.source_stp dest_stp = service_parameters.dest_stp if source_stp == dest_stp: return defer.fail( error.ReserveError('Cannot connect %s to itself.' % source_stp)) conn = connection.Connection(self.service_registry, requester_nsa, connection_id, source_stp, dest_stp, service_parameters, global_reservation_id, description) self.connections.setdefault(requester_nsa, {})[conn.connection_id] = conn # figure out nature of request path_info = (connection_id, source_stp.network, source_stp.endpoint, dest_stp.network, dest_stp.endpoint, self.network) if source_stp.network == self.network and dest_stp.network == self.network: log.msg( 'Connection %s: Simple path creation: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM) link = nsa.Link(source_stp.network, source_stp.endpoint, dest_stp.endpoint) self.setupSubConnection(link, conn, service_parameters) # This code is for chaining requests and is currently not used, but might be needed sometime in the future # Once we get proper a topology service, some chaining will be necessary. #elif source_stp.network == self.network: # # make path and chain on - common chaining # log.msg('Reserve %s: Common chain creation: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM) # paths = self.topology.findPaths(source_stp, dest_stp) # # check for no paths # paths.sort(key=lambda e : len(e.endpoint_pairs)) # selected_path = paths[0] # shortest path # log.msg('Attempting to create path %s' % selected_path, system=LOG_SYSTEM) # assert selected_path.source_stp.network == self.network # # setup connection data - does this work with more than one hop? # setupSubConnection(selected_path.source_stp, selected_path.endpoint_pairs[0].sourceSTP(), conn) # setupSubConnection(selected_path.endpoint_pairs[0].destSTP(), dest_stp, conn) #elif dest_stp.network == self.network: # # make path and chain on - backwards chaining # log.msg('Backwards chain creation %s: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM) # paths = self.topology.findPaths(source_stp, dest_stp) # # check for no paths # paths.sort(key=lambda e : len(e.endpoint_pairs)) # selected_path = paths[0] # shortest path # log.msg('Attempting to create path %s' % selected_path, system=LOG_SYSTEM) # assert selected_path.dest_stp.network == self.network # # setup connection data # setupSubConnection(selected_path.source_stp, selected_path.endpoint_pairs[0].sourceSTP(), conn) # setupSubConnection(selected_path.endpoint_pairs[0].destSTP(), dest_stp, conn) #else: # log.msg('Tree creation %s: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM) # create the connection in tree/fanout style else: # log about creation and the connection type log.msg( 'Connection %s: Aggregate path creation: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM) # making the connection is the same for all though :-) paths = self.topology.findPaths(source_stp, dest_stp) # error out if we could not find a path if not paths: error_msg = 'Could not find a path for route %s:%s -> %s:%s' % ( source_stp.network, source_stp.endpoint, dest_stp.network, dest_stp.endpoint) log.msg(error_msg, system=LOG_SYSTEM) raise error.TopologyError(error_msg) # check for no paths paths.sort(key=lambda e: len(e.links())) selected_path = paths[0] # shortest path log.msg('Attempting to create path %s' % selected_path, system=LOG_SYSTEM) for link in selected_path.links(): self.setupSubConnection(link, conn, service_parameters) # now reserve connections needed to create path conn.addSubscription(sub) d = task.deferLater(reactor, 0, conn.reserve) d.addErrback(log.err) return defer.succeed(None)