Add Trex traffic generator to initate Traffic for VPP IPSEC
[yardstick.git] / yardstick / network_services / vnf_generic / vnf / tg_trex_vpp.py
1 # Copyright (c) 2019 Viosoft 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 logging
16
17 from trex_stl_lib.trex_stl_exceptions import STLError
18
19 from yardstick.common.utils import safe_cast
20 from yardstick.network_services.vnf_generic.vnf.sample_vnf import \
21     Rfc2544ResourceHelper
22 from yardstick.network_services.vnf_generic.vnf.sample_vnf import \
23     SampleVNFTrafficGen
24 from yardstick.network_services.vnf_generic.vnf.tg_trex import \
25     TrexDpdkVnfSetupEnvHelper
26 from yardstick.network_services.vnf_generic.vnf.tg_trex import \
27     TrexResourceHelper
28
29 LOGGING = logging.getLogger(__name__)
30
31
32 class TrexVppResourceHelper(TrexResourceHelper):
33
34     def __init__(self, setup_helper, rfc_helper_type=None):
35         super(TrexVppResourceHelper, self).__init__(setup_helper)
36
37         if rfc_helper_type is None:
38             rfc_helper_type = Rfc2544ResourceHelper
39
40         self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
41
42         self.loss = None
43         self.sent = None
44         self.latency = None
45
46     def generate_samples(self, stats=None, ports=None, port_pg_id=None,
47                          latency=False):
48         samples = {}
49         if stats is None:
50             stats = self.get_stats(ports)
51         for pname in (intf['name'] for intf in self.vnfd_helper.interfaces):
52             port_num = self.vnfd_helper.port_num(pname)
53             port_stats = stats.get(port_num, {})
54             samples[pname] = {
55                 'rx_throughput_fps': float(port_stats.get('rx_pps', 0.0)),
56                 'tx_throughput_fps': float(port_stats.get('tx_pps', 0.0)),
57                 'rx_throughput_bps': float(port_stats.get('rx_bps', 0.0)),
58                 'tx_throughput_bps': float(port_stats.get('tx_bps', 0.0)),
59                 'in_packets': int(port_stats.get('ipackets', 0)),
60                 'out_packets': int(port_stats.get('opackets', 0)),
61             }
62
63             if latency:
64                 pg_id_list = port_pg_id.get_pg_ids(port_num)
65                 samples[pname]['latency'] = {}
66                 for pg_id in pg_id_list:
67                     latency_global = stats.get('latency', {})
68                     pg_latency = latency_global.get(pg_id, {}).get('latency')
69
70                     t_min = safe_cast(pg_latency.get("total_min", 0.0), float,
71                                       -1.0)
72                     t_avg = safe_cast(pg_latency.get("average", 0.0), float,
73                                       -1.0)
74                     t_max = safe_cast(pg_latency.get("total_max", 0.0), float,
75                                       -1.0)
76
77                     latency = {
78                         "min_latency": t_min,
79                         "max_latency": t_max,
80                         "avg_latency": t_avg,
81                     }
82                     samples[pname]['latency'][pg_id] = latency
83
84         return samples
85
86     def _run_traffic_once(self, traffic_profile):
87         self.client_started.value = 1
88         traffic_profile.execute_traffic(self)
89         return True
90
91     def run_traffic(self, traffic_profile):
92         self._queue.cancel_join_thread()
93         traffic_profile.init_queue(self._queue)
94         super(TrexVppResourceHelper, self).run_traffic(traffic_profile)
95
96     @staticmethod
97     def fmt_latency(lat_min, lat_avg, lat_max):
98         t_min = int(round(safe_cast(lat_min, float, -1.0)))
99         t_avg = int(round(safe_cast(lat_avg, float, -1.0)))
100         t_max = int(round(safe_cast(lat_max, float, -1.0)))
101
102         return "/".join(str(tmp) for tmp in (t_min, t_avg, t_max))
103
104     def send_traffic_on_tg(self, ports, port_pg_id, duration, rate,
105                            latency=False):
106         try:
107             # Choose rate and start traffic:
108             self.client.start(ports=ports, mult=rate, duration=duration)
109             # Block until done:
110             try:
111                 self.client.wait_on_traffic(ports=ports, timeout=duration + 20)
112             except STLError as err:
113                 self.client.stop(ports)
114                 LOGGING.error("TRex stateless timeout error: %s", err)
115
116             if self.client.get_warnings():
117                 for warning in self.client.get_warnings():
118                     LOGGING.warning(warning)
119
120             # Read the stats after the test
121             stats = self.client.get_stats()
122
123             packets_in = []
124             packets_out = []
125             for port in ports:
126                 packets_in.append(stats[port]["ipackets"])
127                 packets_out.append(stats[port]["opackets"])
128
129                 if latency:
130                     self.latency = []
131                     pg_id_list = port_pg_id.get_pg_ids(port)
132                     for pg_id in pg_id_list:
133                         latency_global = stats.get('latency', {})
134                         pg_latency = latency_global.get(pg_id, {}).get(
135                             'latency')
136                         lat = self.fmt_latency(
137                             str(pg_latency.get("total_min")),
138                             str(pg_latency.get("average")),
139                             str(pg_latency.get("total_max")))
140                         LOGGING.info(
141                             "latencyStream%s(usec)=%s", pg_id, lat)
142                         self.latency.append(lat)
143
144             self.sent = sum(packets_out)
145             total_rcvd = sum(packets_in)
146             self.loss = self.sent - total_rcvd
147             LOGGING.info("rate=%s, totalReceived=%s, totalSent=%s,"
148                          " frameLoss=%s", rate, total_rcvd, self.sent,
149                          self.loss)
150             return stats
151         except STLError as err:
152             LOGGING.error("TRex stateless runtime error: %s", err)
153             raise RuntimeError('TRex stateless runtime error')
154
155
156 class TrexTrafficGenVpp(SampleVNFTrafficGen):
157     APP_NAME = 'TRex'
158     WAIT_TIME = 20
159
160     def __init__(self, name, vnfd, setup_env_helper_type=None,
161                  resource_helper_type=None):
162         if setup_env_helper_type is None:
163             setup_env_helper_type = TrexDpdkVnfSetupEnvHelper
164         if resource_helper_type is None:
165             resource_helper_type = TrexVppResourceHelper
166
167         super(TrexTrafficGenVpp, self).__init__(
168             name, vnfd, setup_env_helper_type, resource_helper_type)
169
170     def _check_status(self):
171         return self.resource_helper.check_status()
172
173     def _start_server(self):
174         super(TrexTrafficGenVpp, self)._start_server()
175         self.resource_helper.start()
176
177     def wait_for_instantiate(self):
178         return self._wait_for_process()