+ def setLAN(self, vnf_list):
+ """
+ setup an E-LAN network by assigning the same VLAN tag to each DC interface of the VNFs in the E-LAN
+
+ :param vnf_list: names of the VNFs in this E-LAN [{name:,interface:},...]
+ :return:
+ """
+ src_sw = None
+ src_sw_inport_name = None
+
+ # get a vlan tag for this E-LAN
+ vlan = self.vlans.pop()
+
+ for vnf in vnf_list:
+ vnf_src_name = vnf['name']
+ vnf_src_interface = vnf['interface']
+
+ # check if port is specified (vnf:port)
+ if vnf_src_interface is None:
+ # take first interface by default
+ connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
+ link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
+ vnf_src_interface = link_dict[0]['src_port_id']
+
+ for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
+ link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
+ for link in link_dict:
+ if (link_dict[link]['src_port_id'] == vnf_src_interface or
+ link_dict[link]['src_port_name'] == vnf_src_interface): # Fix: we might also get interface names, e.g, from a son-emu-cli call
+ # found the right link and connected switch
+ src_sw = connected_sw
+ src_sw_inport_name = link_dict[link]['dst_port_name']
+ break
+
+ # set the tag on the dc switch interface
+ LOG.debug('set E-LAN: vnf name: {0} interface: {1} tag: {2}'.format(
+ vnf_src_name, vnf_src_interface, vlan))
+ switch_node = self.getNodeByName(src_sw)
+ self._set_vlan_tag(switch_node, src_sw_inport_name, vlan)
+
+ def getNodeByName(self, name):
+ """
+ Wraps Containernet's getNodeByName method to avoid
+ key not found exceptions.
+ """
+ try:
+ return super(DCNetwork, self).getNodeByName(name)
+ except BaseException as ex:
+ LOG.warning("Node not found: {}".format(name))
+ LOG.debug("Node not found: {}".format(ex))
+ return None
+
+ def _addMonitorFlow(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None,
+ tag=None, **kwargs):
+ """
+ Add a monitoring flow entry that adds a special flowentry/counter at the begin or end of a chain.
+ So this monitoring flowrule exists on top of a previously defined chain rule and uses the same vlan tag/routing.
+ :param vnf_src_name:
+ :param vnf_dst_name:
+ :param vnf_src_interface:
+ :param vnf_dst_interface:
+ :param tag: vlan tag to be used for this chain (same tag as existing chain)
+ :param monitor_placement: 'tx' or 'rx' indicating to place the extra flowentry resp. at the beginning or end of the chain
+ :return:
+ """
+
+ src_sw = None
+ src_sw_inport_nr = 0
+ src_sw_inport_name = None
+ dst_sw = None
+ dst_sw_outport_nr = 0
+ dst_sw_outport_name = None
+
+ LOG.debug("call AddMonitorFlow vnf_src_name=%r, vnf_src_interface=%r, vnf_dst_name=%r, vnf_dst_interface=%r",
+ vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface)
+
+ # check if port is specified (vnf:port)
+ if vnf_src_interface is None:
+ # take first interface by default
+ connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
+ link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
+ vnf_src_interface = link_dict[0]['src_port_id']
+
+ for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
+ link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
+ for link in link_dict:
+ if (link_dict[link]['src_port_id'] == vnf_src_interface or
+ link_dict[link]['src_port_name'] == vnf_src_interface): # Fix: we might also get interface names, e.g, from a son-emu-cli call
+ # found the right link and connected switch
+ src_sw = connected_sw
+ src_sw_inport_nr = link_dict[link]['dst_port_nr']
+ src_sw_inport_name = link_dict[link]['dst_port_name']
+ break
+
+ if vnf_dst_interface is None:
+ # take first interface by default
+ connected_sw = self.DCNetwork_graph.neighbors(vnf_dst_name)[0]
+ link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
+ vnf_dst_interface = link_dict[0]['dst_port_id']
+
+ vnf_dst_name = vnf_dst_name.split(':')[0]
+ for connected_sw in self.DCNetwork_graph.neighbors(vnf_dst_name):
+ link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
+ for link in link_dict:
+ if link_dict[link]['dst_port_id'] == vnf_dst_interface or \
+ link_dict[link]['dst_port_name'] == vnf_dst_interface: # Fix: we might also get interface names, e.g, from a son-emu-cli call
+ # found the right link and connected switch
+ dst_sw = connected_sw
+ dst_sw_outport_nr = link_dict[link]['src_port_nr']
+ dst_sw_outport_name = link_dict[link]['src_port_name']
+ break
+
+ if not tag >= 0:
+ LOG.exception('tag not valid: {0}'.format(tag))
+
+ # 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
+