NFVBENCH-131 Allow list of arbitrary network names for EXT chains 87/67587/2
authorahothan <ahothan@cisco.com>
Mon, 15 Apr 2019 05:23:50 +0000 (22:23 -0700)
committerahothan <ahothan@cisco.com>
Mon, 15 Apr 2019 06:15:36 +0000 (23:15 -0700)
Change-Id: Ide9ee9999242f449c57e40ce2c3bb147bb795452
Signed-off-by: ahothan <ahothan@cisco.com>
.gitignore
nfvbench/cfg.default.yaml
nfvbench/chaining.py
nfvbench/config.py
test/test_chains.py

index 2b16029..c2bb485 100644 (file)
@@ -4,6 +4,7 @@
 .tox
 .cache
 .eggs
+.vscode
 .pytest_cache/
 venv
 nfvbench.egg-info
index 9fc7ae4..3152bb9 100755 (executable)
@@ -390,18 +390,32 @@ internal_networks:
 # SRIOV can be used by toggling below setting.
 use_sriov_middle_net: false
 
-# EXT chain only. Prefix names of edge networks which will be used to send traffic via traffic generator.
+# EXT chain only. Prefix names of edge networks or list of edge network names
+# used to send traffic via traffic generator.
 #
 # If service_chain_shared_net is true, the left and right networks must pre-exist and match exactly by name.
 #
 # If service_chain_shared_net is false, each chain must have its own pre-existing left and right networks.
-# An index will be appended to each network name to form the final name:
+# left and right can take either a string prefix or a list of arbitrary network names
+# If a string prefix is passed, an index will be appended to each network name to form the final name.
+# Example:
+# external_networks:
+#    left:  'ext-lnet'
+#    right: 'ext-rnet'
 # ext-lnet0 ext-rnet0 for chain #0
 # ext-lnet1 ext-rnet1 for chain #1
 # etc...
+# If a list of strings is passed, each string in the list must be the name of the network used for the
+# chain indexed by the entry position in the list.
+# The list must have at least as many entries as there are chains
+# Example:
+# external_networks:
+#   left:  ['ext-lnet', 'ext-lnet2']
+#   right: ['ext-rnet', 'ext-rnet2']
+# 
 external_networks:
-    left: 'ext-lnet'
-    right: 'ext-rnet'
+    left:
+    right:
 
 # Use 'true' to enable VXLAN encapsulation support and sent by the traffic generator
 # When this option enabled internal networks 'network type' parameter value should be 'vxlan'
index a02bc1e..ee8a8e0 100644 (file)
@@ -197,17 +197,24 @@ class ChainNetwork(object):
         """Create a network for given chain.
 
         network_config: a dict containing the network properties
-                        (segmentation_id and physical_network)
+                        (name, segmentation_id and physical_network)
         chain_id: to which chain the networks belong.
                   a None value will mean that these networks are shared by all chains
         """
         self.manager = manager
-        self.name = network_config.name
+        if chain_id is None:
+            self.name = network_config.name
+        else:
+            # the name itself can be either a string or a list of names indexed by chain ID
+            if isinstance(network_config.name, tuple):
+                self.name = network_config.name[chain_id]
+            else:
+                # network_config.name is a prefix string
+                self.name = network_config.name + str(chain_id)
         self.segmentation_id = self._get_item(network_config.segmentation_id,
                                               chain_id, auto_index=True)
         self.physical_network = self._get_item(network_config.physical_network, chain_id)
-        if chain_id is not None:
-            self.name += str(chain_id)
+
         self.reuse = False
         self.network = None
         self.vlan = None
@@ -876,6 +883,12 @@ class ChainManager(object):
                     self.flavor = ChainFlavor(config.flavor_type, config.flavor, self.comp)
                     # Get list of all existing instances to check if some instances can be reused
                     self.existing_instances = self.comp.get_server_list()
+                else:
+                    # For EXT chains, the external_networks left and right fields in the config
+                    # must be either a prefix string or a list of at least chain-count strings
+                    self._check_extnet('left', config.external_networks.left)
+                    self._check_extnet('right', config.external_networks.right)
+
                 # If networks are shared across chains, get the list of networks
                 if config.service_chain_shared_net:
                     self.networks = self.get_networks()
@@ -908,6 +921,14 @@ class ChainManager(object):
             if config.vxlan:
                 raise ChainException('VxLAN is only supported with OpenStack')
 
+    def _check_extnet(self, side, name):
+        if not name:
+            raise ChainException('external_networks.%s must contain a valid network'
+                                 ' name prefix or a list of network names' % side)
+        if isinstance(name, tuple) and len(name) < self.chain_count:
+            raise ChainException('external_networks.%s %s'
+                                 ' must have at least %d names' % (side, name, self.chain_count))
+
     def _get_config_vlans(self):
         re_vlan = "[0-9]*$"
         try:
index 5feeda5..0f0d64a 100644 (file)
@@ -43,7 +43,7 @@ def config_loads(cfg_text, from_cfg=None, whitelist_keys=None):
     """Same as config_load but load from a string
     """
     try:
-        cfg = AttrDict(yaml.load(cfg_text))
+        cfg = AttrDict(yaml.safe_load(cfg_text))
     except TypeError:
         # empty string
         cfg = AttrDict()
index f4b792a..f7a2ce3 100644 (file)
@@ -232,6 +232,9 @@ def test_ext_chain_runner():
             for scc in [1, 2]:
                 config = _get_chain_config(ChainType.EXT, scc, shared_net)
                 config.no_arp = no_arp
+                # this time use a tuple of network names
+                config['external_networks']['left'] = ('ext-lnet00', 'ext-lnet01')
+                config['external_networks']['right'] = ('ext-rnet00', 'ext-rnet01')
                 if no_arp:
                     # If EXT and no arp, the config must provide mac addresses (1 pair per chain)
                     config['traffic_generator']['mac_addrs_left'] = ['00:00:00:00:00:00'] * scc
@@ -244,6 +247,9 @@ def _check_nfvbench_openstack(sc=ChainType.PVP, l2_loopback=False):
         if l2_loopback:
             config.l2_loopback = True
             config.vlans = [[100], [200]]
+        if sc == ChainType.EXT:
+            config['external_networks']['left'] = 'ext-lnet'
+            config['external_networks']['right'] = 'ext-rnet'
         factory = BasicFactory()
         config_plugin = factory.get_config_plugin_class()(config)
         config = config_plugin.get_config()