Move ErrorClass definition to exceptions module
[yardstick.git] / yardstick / network_services / vnf_generic / vnf / tg_rfc2544_ixia.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
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
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 import time
16 import os
17 import logging
18 import sys
19
20 from yardstick.common import exceptions
21 from yardstick.common import utils
22 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
23 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
24 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
25
26 LOG = logging.getLogger(__name__)
27
28 WAIT_AFTER_CFG_LOAD = 10
29 WAIT_FOR_TRAFFIC = 30
30 IXIA_LIB = os.path.dirname(os.path.realpath(__file__))
31 IXNET_LIB = os.path.join(IXIA_LIB, "../../libs/ixia_libs/IxNet")
32 sys.path.append(IXNET_LIB)
33
34 try:
35     from IxNet import IxNextgen
36 except ImportError:
37     IxNextgen = exceptions.ErrorClass
38
39
40 class IxiaRfc2544Helper(Rfc2544ResourceHelper):
41
42     def is_done(self):
43         return self.latency and self.iteration.value > 10
44
45
46 class IxiaResourceHelper(ClientResourceHelper):
47
48     LATENCY_TIME_SLEEP = 120
49
50     def __init__(self, setup_helper, rfc_helper_type=None):
51         super(IxiaResourceHelper, self).__init__(setup_helper)
52         self.scenario_helper = setup_helper.scenario_helper
53
54         self.client = IxNextgen()
55
56         if rfc_helper_type is None:
57             rfc_helper_type = IxiaRfc2544Helper
58
59         self.rfc_helper = rfc_helper_type(self.scenario_helper)
60         self.uplink_ports = None
61         self.downlink_ports = None
62         self._connect()
63
64     def _connect(self, client=None):
65         self.client._connect(self.vnfd_helper)
66
67     def get_stats(self, *args, **kwargs):
68         return self.client.ix_get_statistics()
69
70     def stop_collect(self):
71         self._terminated.value = 1
72         if self.client:
73             self.client.ix_stop_traffic()
74
75     def generate_samples(self, ports, key=None, default=None):
76         stats = self.get_stats()
77         last_result = stats[1]
78         latency = stats[0]
79
80         samples = {}
81         # this is not DPDK port num, but this is whatever number we gave
82         # when we selected ports and programmed the profile
83         for port_num in ports:
84             try:
85                 # reverse lookup port name from port_num so the stats dict is descriptive
86                 intf = self.vnfd_helper.find_interface_by_port(port_num)
87                 port_name = intf["name"]
88                 samples[port_name] = {
89                     "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][port_num]),
90                     "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][port_num]),
91                     "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][port_num]),
92                     "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][port_num]),
93                     "in_packets": int(last_result["Valid_Frames_Rx"][port_num]),
94                     "out_packets": int(last_result["Frames_Tx"][port_num]),
95                     "RxThroughput": int(last_result["Valid_Frames_Rx"][port_num]) / 30,
96                     "TxThroughput": int(last_result["Frames_Tx"][port_num]) / 30,
97                 }
98                 if key:
99                     avg_latency = latency["Store-Forward_Avg_latency_ns"][port_num]
100                     min_latency = latency["Store-Forward_Min_latency_ns"][port_num]
101                     max_latency = latency["Store-Forward_Max_latency_ns"][port_num]
102                     samples[port_name][key] = \
103                         {"Store-Forward_Avg_latency_ns": avg_latency,
104                          "Store-Forward_Min_latency_ns": min_latency,
105                          "Store-Forward_Max_latency_ns": max_latency}
106             except IndexError:
107                 pass
108
109         return samples
110
111     def run_traffic(self, traffic_profile):
112         if self._terminated.value:
113             return
114
115         min_tol = self.rfc_helper.tolerance_low
116         max_tol = self.rfc_helper.tolerance_high
117         default = "00:00:00:00:00:00"
118
119         self._build_ports()
120
121         # we don't know client_file_name until runtime as instantiate
122         client_file_name = \
123             utils.find_relative_file(
124                 self.scenario_helper.scenario_cfg['ixia_profile'],
125                 self.scenario_helper.scenario_cfg["task_path"])
126         self.client.ix_load_config(client_file_name)
127         time.sleep(WAIT_AFTER_CFG_LOAD)
128
129         self.client.ix_assign_ports()
130
131         mac = {}
132         for port_name in self.vnfd_helper.port_pairs.all_ports:
133             intf = self.vnfd_helper.find_interface(name=port_name)
134             virt_intf = intf["virtual-interface"]
135             # we only know static traffic id by reading the json
136             # this is used by _get_ixia_trafficrofile
137             port_num = self.vnfd_helper.port_num(intf)
138             mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
139             mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
140
141         samples = {}
142         # Generate ixia traffic config...
143         try:
144             while not self._terminated.value:
145                 traffic_profile.execute_traffic(self, self.client, mac)
146                 self.client_started.value = 1
147                 time.sleep(WAIT_FOR_TRAFFIC)
148                 self.client.ix_stop_traffic()
149                 samples = self.generate_samples(traffic_profile.ports)
150                 self._queue.put(samples)
151                 status, samples = traffic_profile.get_drop_percentage(samples, min_tol,
152                                                                       max_tol, self.client, mac)
153
154                 current = samples['CurrentDropPercentage']
155                 if min_tol <= current <= max_tol or status == 'Completed':
156                     self._terminated.value = 1
157
158             self.client.ix_stop_traffic()
159             self._queue.put(samples)
160
161             if not self.rfc_helper.is_done():
162                 self._terminated.value = 1
163                 return
164
165             traffic_profile.execute_traffic(self, self.client, mac)
166             for _ in range(5):
167                 time.sleep(self.LATENCY_TIME_SLEEP)
168                 self.client.ix_stop_traffic()
169                 samples = self.generate_samples(traffic_profile.ports, 'latency', {})
170                 self._queue.put(samples)
171                 traffic_profile.start_ixia_latency(self, self.client, mac)
172                 if self._terminated.value:
173                     break
174
175             self.client.ix_stop_traffic()
176         except Exception:  # pylint: disable=broad-except
177             LOG.exception("Run Traffic terminated")
178
179         self._terminated.value = 1
180
181     def collect_kpi(self):
182         self.rfc_helper.iteration.value += 1
183         return super(IxiaResourceHelper, self).collect_kpi()
184
185
186 class IxiaTrafficGen(SampleVNFTrafficGen):
187
188     APP_NAME = 'Ixia'
189
190     def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
191         if resource_helper_type is None:
192             resource_helper_type = IxiaResourceHelper
193
194         super(IxiaTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
195                                              resource_helper_type)
196         self._ixia_traffic_gen = None
197         self.ixia_file_name = ''
198         self.vnf_port_pairs = []
199
200     def _check_status(self):
201         pass
202
203     def terminate(self):
204         self.resource_helper.stop_collect()
205         super(IxiaTrafficGen, self).terminate()