Build VPP startup configuration file 43/65243/10
authortreyad <treyad@viosoft.com>
Tue, 20 Nov 2018 08:37:40 +0000 (00:37 -0800)
committerTarek Reyad <treyad@viosoft.com>
Wed, 27 Mar 2019 18:14:59 +0000 (18:14 +0000)
Provided configuration parameters into /etc/vpp/startup.conf

JIRA: YARDSTICK-1502

Change-Id: Ib64908a2975a13a1cecd2e6bd7232071628ad431
Signed-off-by: treyad <treyad@viosoft.com>
15 files changed:
setup.py
yardstick/network_services/helpers/cpu.py
yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py
yardstick/network_services/vnf_generic/vnf/vpp_helpers.py
yardstick/resources/templates/add_ip_address.vat [new file with mode: 0644]
yardstick/resources/templates/add_ip_neighbor.vat [new file with mode: 0644]
yardstick/resources/templates/add_route.vat [new file with mode: 0644]
yardstick/resources/templates/del_route.vat [new file with mode: 0644]
yardstick/resources/templates/flush_ip_addresses.vat [new file with mode: 0644]
yardstick/resources/templates/hw_interface_set_mtu.vat [new file with mode: 0644]
yardstick/resources/templates/interface_dump.vat [new file with mode: 0644]
yardstick/resources/templates/set_if_state.vat [new file with mode: 0644]
yardstick/tests/unit/network_services/helpers/test_cpu.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py

index 881ef92..cbf8b15 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -33,7 +33,8 @@ setup(
             'network_services/nfvi/collectd.sh',
             'resources/files/*',
             'resources/scripts/install/*.bash',
-            'resources/scripts/remove/*.bash'
+            'resources/scripts/remove/*.bash',
+            'resources/templates/*.vat'
         ],
         'etc': [
             'yardstick/nodes/*/*.yaml',
index 8cdd829..279af20 100644 (file)
 
 import io
 
+# Number of threads per core.
+NR_OF_THREADS = 2
+
 
 class CpuSysCores(object):
 
     def __init__(self, connection=""):
         self.core_map = {}
+        self.cpuinfo = {}
         self.connection = connection
 
     def _open_cpuinfo(self):
@@ -62,13 +66,14 @@ class CpuSysCores(object):
 
     def get_cpu_layout(self):
         _, stdout, _ = self.connection.execute("lscpu -p")
-        cpuinfo = {}
-        cpuinfo['cpuinfo'] = list()
+        self.cpuinfo = {}
+        self.cpuinfo['cpuinfo'] = list()
         for line in stdout.split("\n"):
             if line and line[0] != "#":
-                cpuinfo['cpuinfo'].append([CpuSysCores._str2int(x) for x in
-                                           line.split(",")])
-        return cpuinfo
+                self.cpuinfo['cpuinfo'].append(
+                    [CpuSysCores._str2int(x) for x in
+                     line.split(",")])
+        return self.cpuinfo
 
     def validate_cpu_cfg(self, vnf_cfg=None):
         if vnf_cfg is None:
@@ -89,9 +94,80 @@ class CpuSysCores(object):
 
         return 0
 
+    def is_smt_enabled(self):
+        return CpuSysCores.smt_enabled(self.cpuinfo)
+
+    def cpu_list_per_node(self, cpu_node, smt_used=False):
+        cpu_node = int(cpu_node)
+        cpu_info = self.cpuinfo.get("cpuinfo")
+        if cpu_info is None:
+            raise RuntimeError("Node cpuinfo not available.")
+
+        smt_enabled = self.is_smt_enabled()
+        if not smt_enabled and smt_used:
+            raise RuntimeError("SMT is not enabled.")
+
+        cpu_list = []
+        for cpu in cpu_info:
+            if cpu[3] == cpu_node:
+                cpu_list.append(cpu[0])
+
+        if not smt_enabled or smt_enabled and smt_used:
+            pass
+
+        if smt_enabled and not smt_used:
+            cpu_list_len = len(cpu_list)
+            cpu_list = cpu_list[:int(cpu_list_len / NR_OF_THREADS)]
+
+        return cpu_list
+
+    def cpu_slice_of_list_per_node(self, cpu_node, skip_cnt=0, cpu_cnt=0,
+                                   smt_used=False):
+        cpu_list = self.cpu_list_per_node(cpu_node, smt_used)
+
+        cpu_list_len = len(cpu_list)
+        if cpu_cnt + skip_cnt > cpu_list_len:
+            raise RuntimeError("cpu_cnt + skip_cnt > length(cpu list).")
+
+        if cpu_cnt == 0:
+            cpu_cnt = cpu_list_len - skip_cnt
+
+        if smt_used:
+            cpu_list_0 = cpu_list[:int(cpu_list_len / NR_OF_THREADS)]
+            cpu_list_1 = cpu_list[int(cpu_list_len / NR_OF_THREADS):]
+            cpu_list = [cpu for cpu in cpu_list_0[skip_cnt:skip_cnt + cpu_cnt]]
+            cpu_list_ex = [cpu for cpu in
+                           cpu_list_1[skip_cnt:skip_cnt + cpu_cnt]]
+            cpu_list.extend(cpu_list_ex)
+        else:
+            cpu_list = [cpu for cpu in cpu_list[skip_cnt:skip_cnt + cpu_cnt]]
+
+        return cpu_list
+
+    def cpu_list_per_node_str(self, cpu_node, skip_cnt=0, cpu_cnt=0, sep=",",
+                              smt_used=False):
+        cpu_list = self.cpu_slice_of_list_per_node(cpu_node,
+                                                   skip_cnt=skip_cnt,
+                                                   cpu_cnt=cpu_cnt,
+                                                   smt_used=smt_used)
+        return sep.join(str(cpu) for cpu in cpu_list)
+
     @staticmethod
     def _str2int(string):
         try:
             return int(string)
         except ValueError:
             return 0
+
+    @staticmethod
+    def smt_enabled(cpuinfo):
+        cpu_info = cpuinfo.get("cpuinfo")
+        if cpu_info is None:
+            raise RuntimeError("Node cpuinfo not available.")
+        cpu_mems = [item[-4:] for item in cpu_info]
+        cpu_mems_len = int(len(cpu_mems) / NR_OF_THREADS)
+        count = 0
+        for cpu_mem in cpu_mems[:cpu_mems_len]:
+            if cpu_mem in cpu_mems[cpu_mems_len:]:
+                count += 1
+        return count == cpu_mems_len
index 75a8cce..55313ef 100644 (file)
 import logging
 import re
 import time
+from collections import Counter
+from enum import Enum
 
 from yardstick.benchmark.contexts.base import Context
 from yardstick.common.process import check_if_process_failed
 from yardstick.network_services import constants
-from yardstick.network_services.helpers.cpu import CpuSysCores
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
 from yardstick.network_services.vnf_generic.vnf.vpp_helpers import \
-    VppSetupEnvHelper
+    VppSetupEnvHelper, VppConfigGenerator
 
 LOG = logging.getLogger(__name__)
 
 
+class CryptoAlg(Enum):
+    """Encryption algorithms."""
+    AES_CBC_128 = ('aes-cbc-128', 'AES-CBC', 16)
+    AES_CBC_192 = ('aes-cbc-192', 'AES-CBC', 24)
+    AES_CBC_256 = ('aes-cbc-256', 'AES-CBC', 32)
+    AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 20)
+
+    def __init__(self, alg_name, scapy_name, key_len):
+        self.alg_name = alg_name
+        self.scapy_name = scapy_name
+        self.key_len = key_len
+
+
+class IntegAlg(Enum):
+    """Integrity algorithms."""
+    SHA1_96 = ('sha1-96', 'HMAC-SHA1-96', 20)
+    SHA_256_128 = ('sha-256-128', 'SHA2-256-128', 32)
+    SHA_384_192 = ('sha-384-192', 'SHA2-384-192', 48)
+    SHA_512_256 = ('sha-512-256', 'SHA2-512-256', 64)
+    AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 20)
+
+    def __init__(self, alg_name, scapy_name, key_len):
+        self.alg_name = alg_name
+        self.scapy_name = scapy_name
+        self.key_len = key_len
+
+
 class VipsecApproxSetupEnvHelper(VppSetupEnvHelper):
     DEFAULT_IPSEC_VNF_CFG = {
         'crypto_type': 'SW_cryptodev',
@@ -99,17 +127,39 @@ class VipsecApproxSetupEnvHelper(VppSetupEnvHelper):
                 return flow_src_start_ip
 
     def build_config(self):
-        # TODO Implement later
-        pass
+        vnf_cfg = self.scenario_helper.options.get('vnf_config',
+                                                   self.DEFAULT_IPSEC_VNF_CFG)
+        rxq = vnf_cfg.get('rxq', 1)
+        phy_cores = vnf_cfg.get('worker_threads', 1)
+        # worker_config = vnf_cfg.get('worker_config', '1C/1T').split('/')[1].lower()
+
+        vpp_cfg = self.create_startup_configuration_of_vpp()
+        self.add_worker_threads_and_rxqueues(vpp_cfg, phy_cores, rxq)
+        self.add_pci_devices(vpp_cfg)
+
+        frame_size_cfg = self.scenario_helper.all_options.get('framesize', {})
+        uplink_cfg = frame_size_cfg.get('uplink', {})
+        downlink_cfg = frame_size_cfg.get('downlink', {})
+        framesize = min(self.calculate_frame_size(uplink_cfg),
+                        self.calculate_frame_size(downlink_cfg))
+        if framesize < 1522:
+            vpp_cfg.add_dpdk_no_multi_seg()
+
+        crypto_algorithms = self._get_crypto_algorithms()
+        if crypto_algorithms == 'aes-gcm':
+            self.add_dpdk_cryptodev(vpp_cfg, 'aesni_gcm', phy_cores)
+        elif crypto_algorithms == 'cbc-sha1':
+            self.add_dpdk_cryptodev(vpp_cfg, 'aesni_mb', phy_cores)
+
+        vpp_cfg.add_dpdk_dev_default_rxd(2048)
+        vpp_cfg.add_dpdk_dev_default_txd(2048)
 
     def setup_vnf_environment(self):
         resource = super(VipsecApproxSetupEnvHelper,
                          self).setup_vnf_environment()
 
         self.start_vpp_service()
-
-        sys_cores = CpuSysCores(self.ssh_helper)
-        self._update_vnfd_helper(sys_cores.get_cpu_layout())
+        self._update_vnfd_helper(self.sys_cores.get_cpu_layout())
 
         return resource
 
@@ -144,8 +194,51 @@ class VipsecApproxSetupEnvHelper(VppSetupEnvHelper):
         return ipsec_created
 
     def get_vpp_statistics(self):
-        # TODO Implement later
-        return None
+        cmd = "vppctl show int {intf}"
+        result = {}
+        for interface in self.vnfd_helper.interfaces:
+            iface_name = self.get_value_by_interface_key(
+                interface["virtual-interface"]["ifname"], "vpp_name")
+            command = cmd.format(intf=iface_name)
+            _, stdout, _ = self.ssh_helper.execute(command)
+            result.update(
+                self.parser_vpp_stats(interface["virtual-interface"]["ifname"],
+                                      iface_name, stdout))
+        self.ssh_helper.execute("vppctl clear interfaces")
+        return result
+
+    @staticmethod
+    def parser_vpp_stats(interface, iface_name, stats):
+        packets_in = 0
+        packets_fwd = 0
+        packets_dropped = 0
+        result = {}
+
+        entries = re.split(r"\n+", stats)
+        tmp = [re.split(r"\s\s+", entry, 5) for entry in entries]
+
+        for item in tmp:
+            if isinstance(item, list):
+                if item[0] == iface_name and len(item) >= 5:
+                    if item[3] == 'rx packets':
+                        packets_in = int(item[4])
+                    elif item[4] == 'rx packets':
+                        packets_in = int(item[5])
+                elif len(item) == 3:
+                    if item[1] == 'tx packets':
+                        packets_fwd = int(item[2])
+                    elif item[1] == 'drops' or item[1] == 'rx-miss':
+                        packets_dropped = int(item[2])
+        if packets_dropped == 0 and packets_in > 0 and packets_fwd > 0:
+            packets_dropped = abs(packets_fwd - packets_in)
+
+        result[interface] = {
+            'packets_in': packets_in,
+            'packets_fwd': packets_fwd,
+            'packets_dropped': packets_dropped,
+        }
+
+        return result
 
     def create_ipsec_tunnels(self):
         # TODO Implement later
@@ -160,6 +253,110 @@ class VipsecApproxSetupEnvHelper(VppSetupEnvHelper):
     def find_encrypted_data_interface(self):
         return self.vnfd_helper.find_virtual_interface(vld_id="ciphertext")
 
+    def create_startup_configuration_of_vpp(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_log()
+        vpp_config_generator.add_unix_cli_listen()
+        vpp_config_generator.add_unix_nodaemon()
+        vpp_config_generator.add_unix_coredump()
+        vpp_config_generator.add_dpdk_socketmem('1024,1024')
+        vpp_config_generator.add_dpdk_no_tx_checksum_offload()
+        vpp_config_generator.add_dpdk_log_level('debug')
+        for interface in self.vnfd_helper.interfaces:
+            vpp_config_generator.add_dpdk_uio_driver(
+                interface["virtual-interface"]["driver"])
+        vpp_config_generator.add_heapsize('4G')
+        # TODO Enable configuration depend on VPP version
+        vpp_config_generator.add_statseg_size('4G')
+        vpp_config_generator.add_plugin('disable', ['default'])
+        vpp_config_generator.add_plugin('enable', ['dpdk_plugin.so'])
+        vpp_config_generator.add_ip6_hash_buckets('2000000')
+        vpp_config_generator.add_ip6_heap_size('4G')
+        vpp_config_generator.add_ip_heap_size('4G')
+        return vpp_config_generator
+
+    def add_worker_threads_and_rxqueues(self, vpp_cfg, phy_cores,
+                                        rx_queues=None):
+        thr_count_int = phy_cores
+        cpu_count_int = phy_cores
+        num_mbufs_int = 32768
+
+        numa_list = []
+
+        if_list = [self.find_encrypted_data_interface()["ifname"],
+                   self.find_raw_data_interface()["ifname"]]
+        for if_key in if_list:
+            try:
+                numa_list.append(
+                    self.get_value_by_interface_key(if_key, 'numa_node'))
+            except KeyError:
+                pass
+        numa_cnt_mc = Counter(numa_list).most_common()
+
+        if numa_cnt_mc and numa_cnt_mc[0][0] is not None and \
+                numa_cnt_mc[0][0] != -1:
+            numa = numa_cnt_mc[0][0]
+        elif len(numa_cnt_mc) > 1 and numa_cnt_mc[0][0] == -1:
+            numa = numa_cnt_mc[1][0]
+        else:
+            numa = 0
+
+        try:
+            smt_used = self.sys_cores.is_smt_enabled()
+        except KeyError:
+            smt_used = False
+
+        cpu_main = self.sys_cores.cpu_list_per_node_str(numa, skip_cnt=1,
+                                                        cpu_cnt=1)
+        cpu_wt = self.sys_cores.cpu_list_per_node_str(numa, skip_cnt=2,
+                                                      cpu_cnt=cpu_count_int,
+                                                      smt_used=smt_used)
+
+        if smt_used:
+            thr_count_int = 2 * cpu_count_int
+
+        if rx_queues is None:
+            rxq_count_int = int(thr_count_int / 2)
+        else:
+            rxq_count_int = rx_queues
+
+        if rxq_count_int == 0:
+            rxq_count_int = 1
+
+        num_mbufs_int = num_mbufs_int * rxq_count_int
+
+        vpp_cfg.add_cpu_main_core(cpu_main)
+        vpp_cfg.add_cpu_corelist_workers(cpu_wt)
+        vpp_cfg.add_dpdk_dev_default_rxq(rxq_count_int)
+        vpp_cfg.add_dpdk_num_mbufs(num_mbufs_int)
+
+    def add_pci_devices(self, vpp_cfg):
+        pci_devs = [self.find_encrypted_data_interface()["vpci"],
+                    self.find_raw_data_interface()["vpci"]]
+        vpp_cfg.add_dpdk_dev(*pci_devs)
+
+    def add_dpdk_cryptodev(self, vpp_cfg, sw_pmd_type, count):
+        crypto_type = self._get_crypto_type()
+        smt_used = self.sys_cores.is_smt_enabled()
+        cryptodev = self.find_encrypted_data_interface()["vpci"]
+        socket_id = self.get_value_by_interface_key(
+            self.find_encrypted_data_interface()["ifname"], "numa_node")
+
+        if smt_used:
+            thr_count_int = count * 2
+            if crypto_type == 'HW_cryptodev':
+                vpp_cfg.add_dpdk_cryptodev(thr_count_int, cryptodev)
+            else:
+                vpp_cfg.add_dpdk_sw_cryptodev(sw_pmd_type, socket_id,
+                                              thr_count_int)
+        else:
+            thr_count_int = count
+            if crypto_type == 'HW_cryptodev':
+                vpp_cfg.add_dpdk_cryptodev(thr_count_int, cryptodev)
+            else:
+                vpp_cfg.add_dpdk_sw_cryptodev(sw_pmd_type, socket_id,
+                                              thr_count_int)
+
 
 class VipsecApproxVnf(SampleVNF):
     """ This class handles vIPSEC VNF model-driver definitions """
index 86c42ec..1eee537 100644 (file)
 # limitations under the License.
 
 import logging
+import re
+from collections import OrderedDict
 
+from yardstick.network_services.helpers.cpu import CpuSysCores
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import \
     DpdkVnfSetupEnvHelper
 
 LOG = logging.getLogger(__name__)
 
 
+class VppConfigGenerator(object):
+    VPP_LOG_FILE = '/tmp/vpe.log'
+
+    def __init__(self):
+        self._nodeconfig = {}
+        self._vpp_config = ''
+
+    def add_config_item(self, config, value, path):
+        if len(path) == 1:
+            config[path[0]] = value
+            return
+        if path[0] not in config:
+            config[path[0]] = {}
+        elif isinstance(config[path[0]], str):
+            config[path[0]] = {} if config[path[0]] == '' \
+                else {config[path[0]]: ''}
+        self.add_config_item(config[path[0]], value, path[1:])
+
+    def add_unix_log(self, value=None):
+        path = ['unix', 'log']
+        if value is None:
+            value = self.VPP_LOG_FILE
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_unix_cli_listen(self, value='/run/vpp/cli.sock'):
+        path = ['unix', 'cli-listen']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_unix_nodaemon(self):
+        path = ['unix', 'nodaemon']
+        self.add_config_item(self._nodeconfig, '', path)
+
+    def add_unix_coredump(self):
+        path = ['unix', 'full-coredump']
+        self.add_config_item(self._nodeconfig, '', path)
+
+    def add_dpdk_dev(self, *devices):
+        for device in devices:
+            if VppConfigGenerator.pci_dev_check(device):
+                path = ['dpdk', 'dev {0}'.format(device)]
+                self.add_config_item(self._nodeconfig, '', path)
+
+    def add_dpdk_cryptodev(self, count, cryptodev):
+        for i in range(count):
+            cryptodev_config = 'dev {0}'.format(
+                re.sub(r'\d.\d$', '1.' + str(i), cryptodev))
+            path = ['dpdk', cryptodev_config]
+            self.add_config_item(self._nodeconfig, '', path)
+        self.add_dpdk_uio_driver('igb_uio')
+
+    def add_dpdk_sw_cryptodev(self, sw_pmd_type, socket_id, count):
+        for _ in range(count):
+            cryptodev_config = 'vdev cryptodev_{0}_pmd,socket_id={1}'. \
+                format(sw_pmd_type, str(socket_id))
+            path = ['dpdk', cryptodev_config]
+            self.add_config_item(self._nodeconfig, '', path)
+
+    def add_dpdk_dev_default_rxq(self, value):
+        path = ['dpdk', 'dev default', 'num-rx-queues']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_dev_default_rxd(self, value):
+        path = ['dpdk', 'dev default', 'num-rx-desc']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_dev_default_txd(self, value):
+        path = ['dpdk', 'dev default', 'num-tx-desc']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_log_level(self, value):
+        path = ['dpdk', 'log-level']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_socketmem(self, value):
+        path = ['dpdk', 'socket-mem']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_num_mbufs(self, value):
+        path = ['dpdk', 'num-mbufs']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_dpdk_uio_driver(self, value=None):
+        path = ['dpdk', 'uio-driver']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_cpu_main_core(self, value):
+        path = ['cpu', 'main-core']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_cpu_corelist_workers(self, value):
+        path = ['cpu', 'corelist-workers']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_heapsize(self, value):
+        path = ['heapsize']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_ip6_hash_buckets(self, value):
+        path = ['ip6', 'hash-buckets']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_ip6_heap_size(self, value):
+        path = ['ip6', 'heap-size']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_ip_heap_size(self, value):
+        path = ['ip', 'heap-size']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_statseg_size(self, value):
+        path = ['statseg', 'size']
+        self.add_config_item(self._nodeconfig, value, path)
+
+    def add_plugin(self, state, *plugins):
+        for plugin in plugins:
+            path = ['plugins', 'plugin {0}'.format(plugin), state]
+            self.add_config_item(self._nodeconfig, ' ', path)
+
+    def add_dpdk_no_multi_seg(self):
+        path = ['dpdk', 'no-multi-seg']
+        self.add_config_item(self._nodeconfig, '', path)
+
+    def add_dpdk_no_tx_checksum_offload(self):
+        path = ['dpdk', 'no-tx-checksum-offload']
+        self.add_config_item(self._nodeconfig, '', path)
+
+    def dump_config(self, obj=None, level=-1):
+        if obj is None:
+            obj = self._nodeconfig
+        obj = OrderedDict(sorted(obj.items()))
+
+        indent = '  '
+        if level >= 0:
+            self._vpp_config += '{}{{\n'.format(level * indent)
+        if isinstance(obj, dict):
+            for key, val in obj.items():
+                if hasattr(val, '__iter__') and not isinstance(val, str):
+                    self._vpp_config += '{}{}\n'.format((level + 1) * indent,
+                                                        key)
+                    self.dump_config(val, level + 1)
+                else:
+                    self._vpp_config += '{}{} {}\n'.format(
+                        (level + 1) * indent,
+                        key, val)
+        if level >= 0:
+            self._vpp_config += '{}}}\n'.format(level * indent)
+
+        return self._vpp_config
+
+    @staticmethod
+    def pci_dev_check(pci_dev):
+        pattern = re.compile("^[0-9A-Fa-f]{4}:[0-9A-Fa-f]{2}:"
+                             "[0-9A-Fa-f]{2}\\.[0-9A-Fa-f]$")
+        if not pattern.match(pci_dev):
+            raise ValueError('PCI address {addr} is not in valid format '
+                             'xxxx:xx:xx.x'.format(addr=pci_dev))
+        return True
+
+
 class VppSetupEnvHelper(DpdkVnfSetupEnvHelper):
     APP_NAME = "vpp"
     CFG_CONFIG = "/etc/vpp/startup.conf"
@@ -31,6 +193,7 @@ class VppSetupEnvHelper(DpdkVnfSetupEnvHelper):
     def __init__(self, vnfd_helper, ssh_helper, scenario_helper):
         super(VppSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper,
                                                 scenario_helper)
+        self.sys_cores = CpuSysCores(self.ssh_helper)
 
     def kill_vnf(self):
         ret_code, _, _ = \
diff --git a/yardstick/resources/templates/add_ip_address.vat b/yardstick/resources/templates/add_ip_address.vat
new file mode 100644 (file)
index 0000000..d59480c
--- /dev/null
@@ -0,0 +1 @@
+sw_interface_add_del_address sw_if_index {sw_if_index} {address}/{prefix_length}
diff --git a/yardstick/resources/templates/add_ip_neighbor.vat b/yardstick/resources/templates/add_ip_neighbor.vat
new file mode 100644 (file)
index 0000000..730e711
--- /dev/null
@@ -0,0 +1 @@
+ip_neighbor_add_del sw_if_index {sw_if_index} dst {ip_address} mac {mac_address}
diff --git a/yardstick/resources/templates/add_route.vat b/yardstick/resources/templates/add_route.vat
new file mode 100644 (file)
index 0000000..64c6a6c
--- /dev/null
@@ -0,0 +1 @@
+ip_add_del_route {network}/{prefix_length} {via} {vrf} {interface} {resolve_attempts} {count} {lookup_vrf} {multipath} {weight} {local}
\ No newline at end of file
diff --git a/yardstick/resources/templates/del_route.vat b/yardstick/resources/templates/del_route.vat
new file mode 100644 (file)
index 0000000..e7fe4bc
--- /dev/null
@@ -0,0 +1 @@
+ip_add_del_route {network}/{prefix_length} via {gateway} sw_if_index {sw_if_index} del
\ No newline at end of file
diff --git a/yardstick/resources/templates/flush_ip_addresses.vat b/yardstick/resources/templates/flush_ip_addresses.vat
new file mode 100644 (file)
index 0000000..f38fcf1
--- /dev/null
@@ -0,0 +1 @@
+sw_interface_add_del_address sw_if_index {sw_if_index} del-all
\ No newline at end of file
diff --git a/yardstick/resources/templates/hw_interface_set_mtu.vat b/yardstick/resources/templates/hw_interface_set_mtu.vat
new file mode 100644 (file)
index 0000000..645d1a8
--- /dev/null
@@ -0,0 +1 @@
+hw_interface_set_mtu sw_if_index {sw_if_index} mtu {mtu}
diff --git a/yardstick/resources/templates/interface_dump.vat b/yardstick/resources/templates/interface_dump.vat
new file mode 100644 (file)
index 0000000..850c348
--- /dev/null
@@ -0,0 +1 @@
+sw_interface_dump
diff --git a/yardstick/resources/templates/set_if_state.vat b/yardstick/resources/templates/set_if_state.vat
new file mode 100644 (file)
index 0000000..e2c2d4b
--- /dev/null
@@ -0,0 +1 @@
+sw_interface_set_flags sw_if_index {sw_if_index} {state}
index c28178d..a1c0826 100644 (file)
@@ -141,3 +141,75 @@ class TestCpuSysCores(unittest.TestCase):
 
     def test__str2int_error(self):
         self.assertEqual(0, CpuSysCores._str2int("err"))
+
+    def test_smt_enabled(self):
+        self.assertEqual(False, CpuSysCores.smt_enabled(
+            {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                         [1, 1, 0, 0, 0, 1, 1, 1, 0]]}))
+
+    def test_is_smt_enabled(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            self.assertEqual(False, cpu_topo.is_smt_enabled())
+
+    def test_cpu_list_per_node(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            self.assertEqual([0, 1], cpu_topo.cpu_list_per_node(0, False))
+
+    def test_cpu_list_per_node_error(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'err': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                        [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            with self.assertRaises(RuntimeError) as raised:
+                cpu_topo.cpu_list_per_node(0, False)
+            self.assertIn('Node cpuinfo not available.', str(raised.exception))
+
+    def test_cpu_list_per_node_smt_error(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            with self.assertRaises(RuntimeError) as raised:
+                cpu_topo.cpu_list_per_node(0, True)
+            self.assertIn('SMT is not enabled.', str(raised.exception))
+
+    def test_cpu_slice_of_list_per_node(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            self.assertEqual([1],
+                             cpu_topo.cpu_slice_of_list_per_node(0, 1, 0,
+                                                                 False))
+
+    def test_cpu_slice_of_list_per_node_error(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            with self.assertRaises(RuntimeError) as raised:
+                cpu_topo.cpu_slice_of_list_per_node(1, 1, 1, False)
+            self.assertIn('cpu_cnt + skip_cnt > length(cpu list).',
+                          str(raised.exception))
+
+    def test_cpu_list_per_node_str(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            cpu_topo = CpuSysCores(ssh_mock)
+            cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+                                            [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+            self.assertEqual("1",
+                             cpu_topo.cpu_list_per_node_str(0, 1, 1, ',',
+                                                            False))
index f812630..e94f83f 100644 (file)
@@ -19,11 +19,12 @@ import mock
 
 from yardstick.benchmark.contexts import base as ctx_base
 from yardstick.common import utils
+from yardstick.network_services.helpers import cpu
 from yardstick.network_services.nfvi.resource import ResourceProfile
-from yardstick.network_services.vnf_generic.vnf import ipsec_vnf
+from yardstick.network_services.vnf_generic.vnf import ipsec_vnf, vpp_helpers
 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-from yardstick.network_services.vnf_generic.vnf.ipsec_vnf import \
-    VipsecApproxSetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.ipsec_vnf import CryptoAlg, \
+    IntegAlg, VipsecApproxSetupEnvHelper
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import \
     mock_ssh
 
@@ -32,6 +33,24 @@ SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper
 NAME = 'vnf__1'
 
 
+class TestCryptoAlg(unittest.TestCase):
+
+    def test__init__(self):
+        encr_alg = CryptoAlg.AES_GCM_128
+        self.assertEqual('aes-gcm-128', encr_alg.alg_name)
+        self.assertEqual('AES-GCM', encr_alg.scapy_name)
+        self.assertEqual(20, encr_alg.key_len)
+
+
+class TestIntegAlg(unittest.TestCase):
+
+    def test__init__(self):
+        auth_alg = IntegAlg.AES_GCM_128
+        self.assertEqual('aes-gcm-128', auth_alg.alg_name)
+        self.assertEqual('AES-GCM', auth_alg.scapy_name)
+        self.assertEqual(20, auth_alg.key_len)
+
+
 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
 class TestVipsecApproxVnf(unittest.TestCase):
     VNFD = {'vnfd:vnfd-catalog':
@@ -791,6 +810,62 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
         }
     }
 
+    ALL_OPTIONS_CBC_ALGORITHMS = {
+        "flow": {
+            "count": 1,
+            "dst_ip": [
+                "20.0.0.0-20.0.0.100"
+            ],
+            "src_ip": [
+                "10.0.0.0-10.0.0.100"
+            ]
+        },
+        "framesize": {
+            "downlink": {
+                "64B": 100
+            },
+            "uplink": {
+                "64B": 100
+            }
+        },
+        "rfc2544": {
+            "allowed_drop_rate": "0.0 - 0.005"
+        },
+        "tg__0": {
+            "collectd": {
+                "interval": 1
+            },
+            "queues_per_port": 7
+        },
+        "traffic_type": 4,
+        "vnf__0": {
+            "collectd": {
+                "interval": 1
+            },
+            "vnf_config": {
+                "crypto_type": "SW_cryptodev",
+                "rxq": 1,
+                "worker_config": "1C/1T",
+                "worker_threads": 4
+            }
+        },
+        "vnf__1": {
+            "collectd": {
+                "interval": 1
+            },
+            "vnf_config": {
+                "crypto_type": "SW_cryptodev",
+                "rxq": 1,
+                "worker_config": "1C/1T",
+                "worker_threads": 4
+            }
+        },
+        "vpp_config": {
+            "crypto_algorithms": "cbc-sha1",
+            "tunnel": 1
+        }
+    }
+
     ALL_OPTIONS_ERROR = {
         "flow_error": {
             "count": 1,
@@ -859,6 +934,18 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
         }
     }
 
+    OPTIONS_HW = {
+        "collectd": {
+            "interval": 1
+        },
+        "vnf_config": {
+            "crypto_type": "HW_cryptodev",
+            "rxq": 1,
+            "worker_config": "1C/1T",
+            "worker_threads": 4
+        }
+    }
+
     CPU_LAYOUT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
                               [1, 0, 0, 0, 0, 1, 1, 0],
                               [2, 1, 0, 0, 0, 2, 2, 1],
@@ -877,6 +964,24 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
                               [15, 8, 0, 1, 0, 15, 15, 7],
                               [16, 9, 0, 1, 0, 16, 16, 8],
                               [17, 9, 0, 1, 0, 17, 17, 8]]}
+    CPU_SMT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
+                           [1, 0, 0, 0, 0, 1, 1, 0],
+                           [2, 1, 0, 0, 0, 2, 2, 1],
+                           [3, 1, 0, 0, 0, 3, 3, 1],
+                           [4, 2, 0, 0, 0, 4, 4, 2],
+                           [5, 2, 0, 0, 0, 5, 5, 2],
+                           [6, 3, 0, 0, 0, 6, 6, 3],
+                           [7, 3, 0, 0, 0, 7, 7, 3],
+                           [8, 4, 0, 0, 0, 8, 8, 4],
+                           [9, 5, 0, 1, 0, 0, 0, 0],
+                           [10, 6, 0, 1, 0, 1, 1, 0],
+                           [11, 6, 0, 1, 0, 2, 2, 1],
+                           [12, 7, 0, 1, 0, 3, 3, 1],
+                           [13, 7, 0, 1, 0, 4, 4, 2],
+                           [14, 8, 0, 1, 0, 5, 5, 2],
+                           [15, 8, 0, 1, 0, 6, 6, 3],
+                           [16, 9, 0, 1, 0, 7, 7, 3],
+                           [17, 9, 0, 1, 0, 8, 8, 4]]}
 
     VPP_INTERFACES_DUMP = [
         {
@@ -1126,12 +1231,45 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
         vnfd_helper = VnfdHelper(
             TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
         ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.build_config())
+
+    def test_build_config_cbc_algorithms(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
         scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS_CBC_ALGORITHMS
 
         ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
                                                                ssh_helper,
                                                                scenario_helper)
-        ipsec_approx_setup_helper.build_config()
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.build_config())
 
     @mock.patch.object(utils, 'setup_hugepages')
     def test_setup_vnf_environment(self, *args):
@@ -1147,9 +1285,12 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
         ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
                                                                ssh_helper,
                                                                scenario_helper)
-        self.assertIsInstance(
-            ipsec_approx_setup_helper.setup_vnf_environment(),
-            ResourceProfile)
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            self.assertIsInstance(
+                ipsec_approx_setup_helper.setup_vnf_environment(),
+                ResourceProfile)
 
     def test_calculate_frame_size(self):
         vnfd_helper = VnfdHelper(
@@ -1217,6 +1358,7 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
         vnfd_helper = VnfdHelper(
             TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
         ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '', ''
         scenario_helper = mock.Mock()
 
         ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
@@ -1224,6 +1366,66 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
                                                                scenario_helper)
         ipsec_approx_setup_helper.get_vpp_statistics()
 
+    def test_parser_vpp_stats(self):
+        output = \
+            '         Name               Idx    State  MTU (L3/IP4/IP6/MPLS)' \
+            'Counter          Count     \n' \
+            'TenGigabitEthernetff/6/0          1      up        9200/0/0/0  ' \
+            'rx packets              23373568\n' \
+            '                                                               ' \
+            'rx bytes              1402414080\n' \
+            '                                                               ' \
+            'tx packets              20476416\n' \
+            '                                                               ' \
+            'tx bytes              1228584960\n' \
+            '                                                               ' \
+            'ip4                     23373568\n' \
+            '                                                               ' \
+            'rx-miss                 27789925'
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        scenario_helper = mock.Mock()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+        self.assertEqual({'xe0': {'packets_dropped': 27789925,
+                                  'packets_fwd': 20476416,
+                                  'packets_in': 23373568}},
+                         ipsec_approx_setup_helper.parser_vpp_stats('xe0',
+                                                                    'TenGigabitEthernetff/6/0',
+                                                                    output))
+
+    def test_parser_vpp_stats_no_miss(self):
+        output = \
+            '              Name               Idx    State              ' \
+            'Counter          Count     \n' \
+            'TenGigabitEthernetff/6/0          1      up                ' \
+            'rx packets              23373568\n' \
+            '                                                           ' \
+            'rx bytes              1402414080\n' \
+            '                                                           ' \
+            'tx packets              20476416\n' \
+            '                                                           ' \
+            'tx bytes              1228584960\n' \
+            '                                                           ' \
+            'ip4                     23373568'
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        scenario_helper = mock.Mock()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+        self.assertEqual({'xe0': {'packets_dropped': 2897152,
+                                  'packets_fwd': 20476416,
+                                  'packets_in': 23373568}},
+                         ipsec_approx_setup_helper.parser_vpp_stats('xe0',
+                                                                    'TenGigabitEthernetff/6/0',
+                                                                    output))
+
     def test_create_ipsec_tunnels(self):
         vnfd_helper = VnfdHelper(
             TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
@@ -1325,3 +1527,247 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
                                                                scenario_helper)
         self.assertEqual(expected,
                          ipsec_approx_setup_helper.find_encrypted_data_interface())
+
+    def test_create_startup_configuration_of_vpp(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                sys_cores.get_cpu_layout())
+            self.assertIsInstance(
+                ipsec_approx_setup_helper.create_startup_configuration_of_vpp(),
+                vpp_helpers.VppConfigGenerator)
+
+    def test_add_worker_threads_and_rxqueues(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(
+                ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+                    vpp_config_generator, 1, 1))
+        self.assertEqual(
+            'cpu\n{\n  corelist-workers 2\n  main-core 1\n}\ndpdk\n{\n  ' \
+            'dev default\n  {\n    num-rx-queues 1\n  }\n  num-mbufs 32768\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_worker_threads_and_rxqueues_smt(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_SMT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(
+                ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+                    vpp_config_generator, 1))
+        self.assertEqual(
+            'cpu\n{\n  corelist-workers 2,6\n  main-core 1\n}\ndpdk\n{\n  ' \
+            'dev default\n  {\n    num-rx-queues 1\n  }\n  num-mbufs 32768\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_worker_threads_and_rxqueues_with_numa(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(
+                ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+                    vpp_config_generator, 1, 1))
+        self.assertEqual(
+            'cpu\n{\n  corelist-workers 2\n  main-core 1\n}\ndpdk\n{\n  ' \
+            'dev default\n  {\n    num-rx-queues 1\n  }\n  num-mbufs 32768\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_pci_devices(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.add_pci_devices(
+                vpp_config_generator))
+        self.assertEqual(
+            'dpdk\n{\n  dev 0000:ff:06.0 \n  dev 0000:ff:07.0 \n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_cryptodev(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+                vpp_config_generator, 'aesni_gcm', 1))
+        self.assertEqual(
+            'dpdk\n{\n  vdev cryptodev_aesni_gcm_pmd,socket_id=None \n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_cryptodev_hw(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS_HW
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+                vpp_config_generator, 'aesni_gcm', 1))
+        self.assertEqual(
+            'dpdk\n{\n  dev 0000:ff:01.0 \n  uio-driver igb_uio\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_cryptodev_smt_used(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_SMT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+                vpp_config_generator, 'aesni_gcm', 1))
+        self.assertEqual(
+            'dpdk\n{\n  vdev cryptodev_aesni_gcm_pmd,socket_id=None \n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_cryptodev_smt_used_hw(self):
+        vnfd_helper = VnfdHelper(
+            TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        ssh_helper = mock.Mock()
+        ssh_helper.execute.return_value = 0, '0', ''
+        scenario_helper = mock.Mock()
+        scenario_helper.options = self.OPTIONS_HW
+        scenario_helper.all_options = self.ALL_OPTIONS
+        vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+        ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+                                                               ssh_helper,
+                                                               scenario_helper)
+
+        with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+                mock_get_cpu_layout:
+            mock_get_cpu_layout.return_value = self.CPU_SMT
+            ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+            ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT
+            ipsec_approx_setup_helper._update_vnfd_helper(
+                ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+            self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+                vpp_config_generator, 'aesni_gcm', 1))
+        self.assertEqual(
+            'dpdk\n{\n  dev 0000:ff:01.0 \n  dev 0000:ff:01.1 \n  uio-driver igb_uio\n}\n',
+            vpp_config_generator.dump_config())
index 597844c..52d2c0e 100644 (file)
@@ -17,7 +17,189 @@ import mock
 
 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
 from yardstick.network_services.vnf_generic.vnf.vpp_helpers import \
-    VppSetupEnvHelper
+    VppSetupEnvHelper, VppConfigGenerator
+
+
+class TestVppConfigGenerator(unittest.TestCase):
+
+    def test_add_config_item(self):
+        test_item = {}
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log',
+                                             ['unix', 'log'])
+        self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item)
+
+    def test_add_config_item_str(self):
+        test_item = {'unix': ''}
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log',
+                                             ['unix', 'log'])
+        self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item)
+
+    def test_add_unix_log(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_log()
+        self.assertEqual('unix\n{\n  log /tmp/vpe.log\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_unix_cli_listen(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_cli_listen()
+        self.assertEqual('unix\n{\n  cli-listen /run/vpp/cli.sock\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_unix_nodaemon(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_nodaemon()
+        self.assertEqual('unix\n{\n  nodaemon \n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_unix_coredump(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_coredump()
+        self.assertEqual('unix\n{\n  full-coredump \n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_dev(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_dev('0000:00:00.0')
+        self.assertEqual('dpdk\n{\n  dev 0000:00:00.0 \n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_cryptodev(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_cryptodev(2, '0000:00:00.0')
+        self.assertEqual(
+            'dpdk\n{\n  dev 0000:00:01.0 \n  dev 0000:00:01.1 \n  uio-driver igb_uio\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_sw_cryptodev(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_sw_cryptodev('aesni_gcm', 0, 2)
+        self.assertEqual(
+            'dpdk\n{\n  vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_dev_default_rxq(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_dev_default_rxq(1)
+        self.assertEqual(
+            'dpdk\n{\n  dev default\n  {\n    num-rx-queues 1\n  }\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_dev_default_rxd(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_dev_default_rxd(2048)
+        self.assertEqual(
+            'dpdk\n{\n  dev default\n  {\n    num-rx-desc 2048\n  }\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_dev_default_txd(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_dev_default_txd(2048)
+        self.assertEqual(
+            'dpdk\n{\n  dev default\n  {\n    num-tx-desc 2048\n  }\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_log_level(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_log_level('debug')
+        self.assertEqual('dpdk\n{\n  log-level debug\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_socketmem(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_socketmem('1024,1024')
+        self.assertEqual('dpdk\n{\n  socket-mem 1024,1024\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_num_mbufs(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_num_mbufs(32768)
+        self.assertEqual('dpdk\n{\n  num-mbufs 32768\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_uio_driver(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_uio_driver('igb_uio')
+        self.assertEqual('dpdk\n{\n  uio-driver igb_uio\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_cpu_main_core(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_cpu_main_core('1,2')
+        self.assertEqual('cpu\n{\n  main-core 1,2\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_cpu_corelist_workers(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_cpu_corelist_workers('1,2')
+        self.assertEqual('cpu\n{\n  corelist-workers 1,2\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_heapsize(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_heapsize('4G')
+        self.assertEqual('heapsize 4G\n', vpp_config_generator.dump_config())
+
+    def test_add_ip6_hash_buckets(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_ip6_hash_buckets(2000000)
+        self.assertEqual('ip6\n{\n  hash-buckets 2000000\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_ip6_heap_size(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_ip6_heap_size('4G')
+        self.assertEqual('ip6\n{\n  heap-size 4G\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_ip_heap_size(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_ip_heap_size('4G')
+        self.assertEqual('ip\n{\n  heap-size 4G\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_statseg_size(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_statseg_size('4G')
+        self.assertEqual('statseg\n{\n  size 4G\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_plugin(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_plugin('enable', ['dpdk_plugin.so'])
+        self.assertEqual(
+            'plugins\n{\n  plugin [\'dpdk_plugin.so\']\n  {\n    enable  \n  }\n}\n',
+            vpp_config_generator.dump_config())
+
+    def test_add_dpdk_no_multi_seg(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_no_multi_seg()
+        self.assertEqual('dpdk\n{\n  no-multi-seg \n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_add_dpdk_no_tx_checksum_offload(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_dpdk_no_tx_checksum_offload()
+        self.assertEqual('dpdk\n{\n  no-tx-checksum-offload \n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_dump_config(self):
+        vpp_config_generator = VppConfigGenerator()
+        vpp_config_generator.add_unix_log()
+        self.assertEqual('unix\n{\n  log /tmp/vpe.log\n}\n',
+                         vpp_config_generator.dump_config())
+
+    def test_pci_dev_check(self):
+        self.assertTrue(VppConfigGenerator.pci_dev_check('0000:00:00.0'))
+
+    def test_pci_dev_check_error(self):
+        with self.assertRaises(ValueError) as raised:
+            VppConfigGenerator.pci_dev_check('0000:00:0.0')
+        self.assertIn(
+            'PCI address 0000:00:0.0 is not in valid format xxxx:xx:xx.x',
+            str(raised.exception))
 
 
 class TestVppSetupEnvHelper(unittest.TestCase):