+ # get shortest path
+ try:
+ # returns the first found shortest path
+ # if all shortest paths are wanted, use: all_shortest_paths
+ path = nx.shortest_path(
+ self.DCNetwork_graph, src_sw, dst_sw, weight=kwargs.get('weight'))
+ except BaseException:
+ LOG.exception("No path could be found between {0} and {1} using src_sw={2} and dst_sw={3}".format(
+ vnf_src_name, vnf_dst_name, src_sw, dst_sw))
+ LOG.debug("Graph nodes: %r" % self.DCNetwork_graph.nodes())
+ LOG.debug("Graph edges: %r" % self.DCNetwork_graph.edges())
+ for e, v in self.DCNetwork_graph.edges():
+ LOG.debug("%r" % self.DCNetwork_graph[e][v])
+ return "No path could be found between {0} and {1}".format(
+ vnf_src_name, vnf_dst_name)
+
+ LOG.debug("Creating path between {0} and {1}: {2}".format(
+ vnf_src_name, vnf_dst_name, path))
+
+ current_hop = src_sw
+ switch_inport_nr = src_sw_inport_nr
+
+ cmd = kwargs.get('cmd')
+
+ # iterate through the path to install the flow-entries
+ for i in range(0, len(path)):
+ current_node = self.getNodeByName(current_hop)
+
+ if path.index(current_hop) < len(path) - 1:
+ next_hop = path[path.index(current_hop) + 1]
+ else:
+ # last switch reached
+ next_hop = vnf_dst_name
+
+ next_node = self.getNodeByName(next_hop)
+
+ if next_hop == vnf_dst_name:
+ switch_outport_nr = dst_sw_outport_nr
+ LOG.debug("end node reached: {0}".format(vnf_dst_name))
+ elif not isinstance(next_node, OVSSwitch):
+ LOG.info("Next node: {0} is not a switch".format(next_hop))
+ return "Next node: {0} is not a switch".format(next_hop)
+ else:
+ # take first link between switches by default
+ index_edge_out = 0
+ switch_outport_nr = self.DCNetwork_graph[current_hop][next_hop][index_edge_out]['src_port_nr']
+
+ # set of entry via ovs-ofctl
+ if isinstance(current_node, OVSSwitch):
+ kwargs['vlan'] = tag
+ kwargs['path'] = path
+ kwargs['current_hop'] = current_hop
+ kwargs['switch_inport_name'] = src_sw_inport_name
+ kwargs['switch_outport_name'] = dst_sw_outport_name
+ kwargs['skip_vlan_tag'] = True
+ kwargs['pathindex'] = i
+
+ monitor_placement = kwargs.get('monitor_placement').strip()
+ # put monitor flow at the dst switch
+ insert_flow = False
+ # first node:
+ if monitor_placement == 'tx' and path.index(current_hop) == 0:
+ insert_flow = True
+ # put monitoring flow at the src switch
+ # last node:
+ elif monitor_placement == 'rx' and path.index(current_hop) == len(path) - 1:
+ insert_flow = True
+ elif monitor_placement not in ['rx', 'tx']:
+ LOG.exception(
+ 'invalid monitor command: {0}'.format(monitor_placement))
+
+ if self.controller == RemoteController and insert_flow:
+ # set flow entry via ryu rest api
+ self._set_flow_entry_ryu_rest(
+ current_node, switch_inport_nr, switch_outport_nr, **kwargs)
+ break
+ elif insert_flow:
+ # set flow entry via ovs-ofctl
+ self._set_flow_entry_dpctl(
+ current_node, switch_inport_nr, switch_outport_nr, **kwargs)
+ break
+
+ # take first link between switches by default
+ if isinstance(next_node, OVSSwitch):
+ switch_inport_nr = self.DCNetwork_graph[current_hop][next_hop][0]['dst_port_nr']
+ current_hop = next_hop
+
+ return "path {2} between {0} and {1}".format(
+ vnf_src_name, vnf_dst_name, cmd)
+
+ def setChain(self, vnf_src_name, vnf_dst_name,
+ vnf_src_interface=None, vnf_dst_interface=None, **kwargs):