import requests
import os
import json
+import copy
from mininet.net import Containernet
from mininet.node import Controller, DefaultController, OVSSwitch, OVSKernelSwitch, Docker, RemoteController
self.deployed_nsds = []
self.deployed_elines = []
self.deployed_elans = []
- self.installed_chains = []
+ self.vlan_dict = {}
# always cleanup environment before we start the emulator
def CLI(self):
CLI(self)
- def setLAN(self, vnf_list):
+ def setLAN(self, vnf_list, vlan=None, action='add'):
"""
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:},...]
+ :param vlan: vlan tag to be used
+ :param action: 'add' or 'delete' the vlan tags for the intefaces
+
:return:
"""
src_sw = None
src_sw_inport_nr = 0
src_sw_inport_name = None
- # get a vlan tag for this E-LAN
- vlan = self.vlans.pop()
+ if vlan is None:
+ # get a vlan tag for this E-LAN
+ vlan = self.vlans.pop()
+ ret = ''
for vnf in vnf_list:
vnf_src_name = vnf['name']
vnf_src_interface = vnf['interface']
# 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)
+ if action == 'add':
+ self._set_vlan_tag(switch_node, src_sw_inport_name, vlan, vnf_src_name, vnf_src_interface)
+ elif action == 'delete':
+ self._remove_vlan_tag(switch_node, src_sw_inport_name, vlan, vnf_src_name, vnf_src_interface)
+ else:
+ ret += "\nERROR: undefined action: {0}".format(action)
+ continue
+
+ ret+= "\n{0} vlan tag: {1} on {2}:{3}".format(action, vlan, vnf_src_name, vnf_src_interface)
+
+ return ret
def _addMonitorFlow(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None,
tag=None, **kwargs):
:return: output log string
"""
+ # check if chain already exists (by checking if a vlan tag has already been assigned for this interface)
+ id_src = "{0}:{1}".format(vnf_src_name, vnf_src_interface)
+ tag_src = self.vlan_dict.get(id_src)
+ id_dst = "{0}:{1}".format(vnf_dst_name, vnf_dst_interface)
+ tag_dst = self.vlan_dict.get(id_dst)
+ if (tag_src == tag_dst) and (tag_src is not None) and (tag_dst is not None):
+ kwargs['tag'] = tag_src
+
# special procedure for monitoring flows
if kwargs.get('monitor'):
-
- # check if chain already exists
- found_chains = [chain_dict for chain_dict in self.installed_chains if
- (chain_dict['vnf_src_name'] == vnf_src_name and chain_dict['vnf_src_interface'] == vnf_src_interface
- and chain_dict['vnf_dst_name'] == vnf_dst_name and chain_dict['vnf_dst_interface'] == vnf_dst_interface)]
-
- if len(found_chains) > 0:
- # this chain exists, so need an extra monitoring flow
+ tag = kwargs.get['tag']
+ if tag is not None:
+ # this chain exists (part of E-LAN or E-Line), so need an extra monitoring flow, reusing the existing vlan
# assume only 1 chain per vnf/interface pair
LOG.debug('*** installing monitoring chain on top of pre-defined chain from {0}:{1} -> {2}:{3}'.
format(vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface))
- tag = found_chains[0]['tag']
ret = self._addMonitorFlow(vnf_src_name, vnf_dst_name, vnf_src_interface, vnf_dst_interface,
tag=tag, table_id=0, **kwargs)
return ret
else:
- # no chain existing (or E-LAN) -> install normal chain
- LOG.warning('*** installing monitoring chain without pre-defined NSD chain from {0}:{1} -> {2}:{3}'.
+ # no chain existing (no common vlan tag) -> install normal chain
+ LOG.warning('*** installing monitoring chain without pre-defined NSD chain from {0}:{1} -> {2}:{3} '
+ '(no matching vlan tags found, installing new chain)'.
format(vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface))
pass
else:
vlan = self.vlans.pop()
- # store the used vlan tag to identify this chain
- if not kwargs.get('monitor'):
- chain_dict = {}
- chain_dict['vnf_src_name'] = vnf_src_name
- chain_dict['vnf_dst_name'] = vnf_dst_name
- chain_dict['vnf_src_interface'] = vnf_src_interface
- chain_dict['vnf_dst_interface'] = vnf_dst_interface
- chain_dict['tag'] = vlan
- self.installed_chains.append(chain_dict)
-
#iterate through the path to install the flow-entries
for i in range(0,len(path)):
current_node = self.getNodeByName(current_hop)
kwargs['switch_inport_name'] = src_sw_inport_name
kwargs['switch_outport_name'] = dst_sw_outport_name
kwargs['pathindex'] = i
+ kwargs['vnf_src_name'] = vnf_src_name
+ kwargs['vnf_src_interface'] = vnf_src_interface
+ kwargs['vnf_dst_name'] = vnf_dst_name
+ kwargs['vnf_dst_interface'] = vnf_dst_interface
if self.controller == RemoteController:
## set flow entry via ryu rest api
prefix = 'stats/flowentry/add'
if vlan != None:
if index == 0: # first node
- # set vlan tag in ovs instance (to isolate E-LANs)
+ # set vlan tag in ovs instance (to isolate from E-LANs)
if not skip_vlan_tag:
in_port_name = kwargs.get('switch_inport_name')
- self._set_vlan_tag(node, in_port_name, vlan)
+ vnf_src_name = kwargs.get('vnf_src_name')
+ vnf_src_interface = kwargs.get('vnf_src_interface')
+ self._set_vlan_tag(node, in_port_name, vlan, vnf_src_name, vnf_src_interface)
# set vlan push action if more than 1 switch in the path
if len(path) > 1:
action = {}
action['value'] = vlan | 0x1000
flow['actions'].append(action)
- elif index == len(path) - 1: # last node
- # set vlan tag in ovs instance (to isolate E-LANs)
+ if index == len(path) - 1: # last node
+ # set vlan tag in ovs instance (to isolate from E-LANs)
if not skip_vlan_tag:
out_port_name = kwargs.get('switch_outport_name')
- self._set_vlan_tag(node, out_port_name, vlan)
+ vnf_dst_name = kwargs.get('vnf_dst_name')
+ vnf_dst_interface = kwargs.get('vnf_dst_interface')
+ self._set_vlan_tag(node, out_port_name, vlan, vnf_dst_name, vnf_dst_interface)
# set vlan pop action if more than 1 switch in the path
if len(path) > 1:
match += ',dl_vlan=%s' % vlan
flow['match'] = self._parse_match(match)
self.ryu_REST(prefix, data=flow)
- def _set_vlan_tag(self, node, switch_port, tag):
+ def _set_vlan_tag(self, node, switch_port, tag, vnf_name, vnf_interface):
+ id = "{0}:{1}".format(vnf_name, vnf_interface)
+ self.vlan_dict[id]=tag
node.vsctl('set', 'port {0} tag={1}'.format(switch_port,tag))
LOG.debug("set vlan in switch: {0} in_port: {1} vlan tag: {2}".format(node.name, switch_port, tag))
+ def _remove_vlan_tag(self, node, switch_port, tag, vnf_name, vnf_interface):
+ id = "{0}:{1}".format(vnf_name, vnf_interface)
+ self.vlan_dict.pop(id)
+ node.vsctl('remove', 'port {0} tag {1}'.format(switch_port,tag))
+ LOG.debug("unset vlan in switch: {0} in_port: {1} vlan tag: {2}".format(node.name, switch_port, tag))
+
def _set_flow_entry_dpctl(self, node, switch_inport_nr, switch_outport_nr, **kwargs):
match = 'in_port=%s' % switch_inport_nr
from mininet.node import Docker, OVSBridge
from mininet.link import Link
from emuvim.dcemulator.resourcemodel import NotEnoughResourcesAvailable
+import threading
import logging
vnf_name = self.name
vnf_interface = str(i)
dc_port_name = self.datacenter.net.find_connected_dc_interface(vnf_name, vnf_interface)
+ id = "{0}:{1}".format(vnf_name, vnf_interface)
+ vlan_tag = self.datacenter.net.vlan_dict.get(id)
# format list of tuples (name, Ip, MAC, isUp, status, dc_portname)
- intf_dict = {'intf_name': str(i), 'ip': "{0}/{1}".format(i.IP(), i.prefixLen), 'netmask': i.prefixLen, 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name}
+ intf_dict = {'intf_name': str(i), 'ip': "{0}/{1}".format(i.IP(), i.prefixLen), 'netmask': i.prefixLen,
+ 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name, 'vlan': vlan_tag}
networkStatusList.append(intf_dict)
return networkStatusList
# do bookkeeping
self.containers[name] = d
+ # Execute SON_EMU_CMD
+ config = d.dcinfo.get("Config", dict())
+ env = config.get("Env", list())
+ for env_var in env:
+ var, cmd = map(str.strip, map(str, env_var.split('=', 1)))
+ LOG.debug("%r = %r" % (var, cmd))
+ if var == "SON_EMU_CMD":
+ LOG.info("Executing entry point script in %r: %r" % (d.name, cmd))
+ # execute command in new thread to ensure that GK is not blocked by VNF
+ t = threading.Thread(target=d.cmdPrint, args=(cmd,))
+ t.daemon = True
+ t.start()
+
return d # we might use UUIDs for naming later on
def stopCompute(self, name):