From e7fdfb5c5e386bb8851b6c583c44ae61bd188627 Mon Sep 17 00:00:00 2001 From: ahothan Date: Sun, 14 Apr 2019 22:23:50 -0700 Subject: NFVBENCH-131 Allow list of arbitrary network names for EXT chains Change-Id: Ide9ee9999242f449c57e40ce2c3bb147bb795452 Signed-off-by: ahothan --- .gitignore | 1 + nfvbench/cfg.default.yaml | 22 ++++++++++++++++++---- nfvbench/chaining.py | 29 +++++++++++++++++++++++++---- nfvbench/config.py | 2 +- test/test_chains.py | 6 ++++++ 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 2b16029..c2bb485 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .tox .cache .eggs +.vscode .pytest_cache/ venv nfvbench.egg-info diff --git a/nfvbench/cfg.default.yaml b/nfvbench/cfg.default.yaml index 9fc7ae4..3152bb9 100755 --- a/nfvbench/cfg.default.yaml +++ b/nfvbench/cfg.default.yaml @@ -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' diff --git a/nfvbench/chaining.py b/nfvbench/chaining.py index a02bc1e..ee8a8e0 100644 --- a/nfvbench/chaining.py +++ b/nfvbench/chaining.py @@ -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: diff --git a/nfvbench/config.py b/nfvbench/config.py index 5feeda5..0f0d64a 100644 --- a/nfvbench/config.py +++ b/nfvbench/config.py @@ -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() diff --git a/test/test_chains.py b/test/test_chains.py index f4b792a..f7a2ce3 100644 --- a/test/test_chains.py +++ b/test/test_chains.py @@ -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() -- cgit 1.2.3-korg