diff options
author | treyad <treyad@viosoft.com> | 2018-11-20 00:37:40 -0800 |
---|---|---|
committer | Tarek Reyad <treyad@viosoft.com> | 2019-03-27 18:14:59 +0000 |
commit | faa02f995c7e22bb1bb2ff5cd745c375b3fb3b51 (patch) | |
tree | db55414a26ebdd4b1d246f412ac0d41c2091bff5 /yardstick/network_services/vnf_generic | |
parent | a7f84ade30af4c10bcceedcd590b42e5caa53ff3 (diff) |
Build VPP startup configuration file
Provided configuration parameters into /etc/vpp/startup.conf
JIRA: YARDSTICK-1502
Change-Id: Ib64908a2975a13a1cecd2e6bd7232071628ad431
Signed-off-by: treyad <treyad@viosoft.com>
Diffstat (limited to 'yardstick/network_services/vnf_generic')
-rw-r--r-- | yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py | 215 | ||||
-rw-r--r-- | yardstick/network_services/vnf_generic/vnf/vpp_helpers.py | 163 |
2 files changed, 369 insertions, 9 deletions
diff --git a/yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py b/yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py index 75a8cce06..55313ef41 100644 --- a/yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/ipsec_vnf.py @@ -15,18 +15,46 @@ 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 """ diff --git a/yardstick/network_services/vnf_generic/vnf/vpp_helpers.py b/yardstick/network_services/vnf_generic/vnf/vpp_helpers.py index 86c42ecfd..1eee537ee 100644 --- a/yardstick/network_services/vnf_generic/vnf/vpp_helpers.py +++ b/yardstick/network_services/vnf_generic/vnf/vpp_helpers.py @@ -13,13 +13,175 @@ # 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, _, _ = \ |