1 # Copyright (c) 2019 Viosoft Corporation
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
19 from yardstick.benchmark.contexts.base import Context
20 from yardstick.common.process import check_if_process_failed
21 from yardstick.network_services import constants
22 from yardstick.network_services.helpers.cpu import CpuSysCores
23 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
24 from yardstick.network_services.vnf_generic.vnf.vpp_helpers import \
27 LOG = logging.getLogger(__name__)
30 class VipsecApproxSetupEnvHelper(VppSetupEnvHelper):
31 DEFAULT_IPSEC_VNF_CFG = {
32 'crypto_type': 'SW_cryptodev',
34 'worker_config': '1C/1T',
38 def __init__(self, vnfd_helper, ssh_helper, scenario_helper):
39 super(VipsecApproxSetupEnvHelper, self).__init__(
40 vnfd_helper, ssh_helper, scenario_helper)
42 def _get_crypto_type(self):
43 vnf_cfg = self.scenario_helper.options.get('vnf_config',
44 self.DEFAULT_IPSEC_VNF_CFG)
45 return vnf_cfg.get('crypto_type', 'SW_cryptodev')
47 def _get_crypto_algorithms(self):
48 vpp_cfg = self.scenario_helper.all_options.get('vpp_config', {})
49 return vpp_cfg.get('crypto_algorithms', 'aes-gcm')
51 def _get_n_tunnels(self):
52 vpp_cfg = self.scenario_helper.all_options.get('vpp_config', {})
53 return vpp_cfg.get('tunnels', 1)
55 def _get_n_connections(self):
57 flow_cfg = self.scenario_helper.all_options['flow']
58 return flow_cfg['count']
60 raise KeyError("Missing flow definition in scenario section" +
61 " of the task definition file")
63 def _get_flow_src_start_ip(self):
64 node_name = self.find_encrypted_data_interface()["node_name"]
66 flow_cfg = self.scenario_helper.all_options['flow']
67 src_ips = flow_cfg['src_ip']
68 dst_ips = flow_cfg['dst_ip']
70 raise KeyError("Missing flow definition in scenario section" +
71 " of the task definition file")
73 for src, dst in zip(src_ips, dst_ips):
74 flow_src_start_ip, _ = src.split('-')
75 flow_dst_start_ip, _ = dst.split('-')
77 if node_name == "vnf__0":
78 return flow_src_start_ip
79 elif node_name == "vnf__1":
80 return flow_dst_start_ip
82 def _get_flow_dst_start_ip(self):
83 node_name = self.find_encrypted_data_interface()["node_name"]
85 flow_cfg = self.scenario_helper.all_options['flow']
86 src_ips = flow_cfg['src_ip']
87 dst_ips = flow_cfg['dst_ip']
89 raise KeyError("Missing flow definition in scenario section" +
90 " of the task definition file")
92 for src, dst in zip(src_ips, dst_ips):
93 flow_src_start_ip, _ = src.split('-')
94 flow_dst_start_ip, _ = dst.split('-')
96 if node_name == "vnf__0":
97 return flow_dst_start_ip
98 elif node_name == "vnf__1":
99 return flow_src_start_ip
101 def build_config(self):
102 # TODO Implement later
105 def setup_vnf_environment(self):
106 resource = super(VipsecApproxSetupEnvHelper,
107 self).setup_vnf_environment()
109 self.start_vpp_service()
111 sys_cores = CpuSysCores(self.ssh_helper)
112 self._update_vnfd_helper(sys_cores.get_cpu_layout())
117 def calculate_frame_size(frame_cfg):
121 imix_count = {size.upper().replace('B', ''): int(weight)
122 for size, weight in frame_cfg.items()}
123 imix_sum = sum(imix_count.values())
126 packets_total = sum([int(size) * weight
127 for size, weight in imix_count.items()])
128 return packets_total / imix_sum
130 def check_status(self):
131 ipsec_created = False
132 cmd = "vppctl show int"
133 _, stdout, _ = self.ssh_helper.execute(cmd)
134 entries = re.split(r"\n+", stdout)
135 tmp = [re.split(r"\s\s+", entry, 5) for entry in entries]
138 if isinstance(item, list):
139 if item[0] and item[0] != 'local0':
140 if "ipsec" in item[0] and not ipsec_created:
142 if len(item) > 2 and item[2] == 'down':
146 def get_vpp_statistics(self):
147 # TODO Implement later
150 def create_ipsec_tunnels(self):
151 # TODO Implement later
154 def find_raw_data_interface(self):
156 return self.vnfd_helper.find_virtual_interface(vld_id="uplink_0")
158 return self.vnfd_helper.find_virtual_interface(vld_id="downlink_0")
160 def find_encrypted_data_interface(self):
161 return self.vnfd_helper.find_virtual_interface(vld_id="ciphertext")
164 class VipsecApproxVnf(SampleVNF):
165 """ This class handles vIPSEC VNF model-driver definitions """
171 def __init__(self, name, vnfd, setup_env_helper_type=None,
172 resource_helper_type=None):
173 if setup_env_helper_type is None:
174 setup_env_helper_type = VipsecApproxSetupEnvHelper
175 super(VipsecApproxVnf, self).__init__(
176 name, vnfd, setup_env_helper_type,
177 resource_helper_type)
180 # we can't share ssh paramiko objects to force new connection
181 self.ssh_helper.drop_connection()
182 # kill before starting
183 self.setup_helper.kill_vnf()
185 self.setup_helper.create_ipsec_tunnels()
187 def wait_for_instantiate(self):
188 time.sleep(self.WAIT_TIME)
190 status = self.setup_helper.check_status()
191 if not self._vnf_process.is_alive() and not status:
192 raise RuntimeError("%s VNF process died." % self.APP_NAME)
193 LOG.info("Waiting for %s VNF to start.. ", self.APP_NAME)
194 time.sleep(self.WAIT_TIME_FOR_SCRIPT)
195 status = self.setup_helper.check_status()
197 LOG.info("%s VNF is up and running.", self.APP_NAME)
199 return self._vnf_process.exitcode
202 self.setup_helper.kill_vnf()
204 self.resource_helper.stop_collect()
205 if self._vnf_process is not None:
206 # be proper and join first before we kill
207 LOG.debug("joining before terminate %s", self._vnf_process.name)
208 self._vnf_process.join(constants.PROCESS_JOIN_TIMEOUT)
209 self._vnf_process.terminate()
211 def collect_kpi(self):
212 # we can't get KPIs if the VNF is down
213 check_if_process_failed(self._vnf_process, 0.01)
214 physical_node = Context.get_physical_node_from_server(
215 self.scenario_helper.nodes[self.name])
216 result = {"physical_node": physical_node}
217 result["collect_stats"] = self.setup_helper.get_vpp_statistics()
218 LOG.debug("%s collect KPIs %s", self.APP_NAME, result)