1 # Copyright (c) 2016-2019 Intel 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.
18 from yardstick.common import utils
19 from yardstick.network_services.traffic_profile import base as tp_base
20 from yardstick.network_services.traffic_profile import trex_traffic_profile
23 LOG = logging.getLogger(__name__)
26 class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
30 DROP_PERCENT_ROUND = 6
31 STATUS_SUCCESS = "Success"
32 STATUS_FAIL = "Failure"
34 def __init__(self, yaml_data):
35 super(IXIARFC2544Profile, self).__init__(yaml_data)
36 self.rate = self.config.frame_rate
37 self.rate_unit = self.config.rate_unit
39 self.full_profile = {}
41 def _get_ip_and_mask(self, ip_range):
42 _ip_range = ip_range.split('-')
43 if len(_ip_range) == 1:
44 return _ip_range[0], None
46 mask = utils.get_mask_from_ip_range(_ip_range[0], _ip_range[1])
47 return _ip_range[0], mask
49 def _get_fixed_and_mask(self, port_range):
50 _port_range = str(port_range).split('-')
51 if len(_port_range) == 1:
52 return int(_port_range[0]), 0
54 return int(_port_range[0]), int(_port_range[1])
56 def _get_ixia_traffic_profile(self, profile_data, mac=None):
57 mac = {} if mac is None else mac
59 for traffickey, values in profile_data.items():
60 if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
63 # values should be single-item dict, so just grab the first item
65 key, value = next(iter(values.items()))
67 result[traffickey] = {}
70 port_id = value.get('id', 1)
71 port_index = port_id - 1
73 result[traffickey] = {
77 'rate_unit': self.rate_unit,
83 frame_rate = value.get('frame_rate')
85 flow_rate, flow_rate_unit = self.config.parse_rate(frame_rate)
86 result[traffickey]['rate'] = flow_rate
87 result[traffickey]['rate_unit'] = flow_rate_unit
89 outer_l2 = value.get('outer_l2')
91 result[traffickey]['outer_l2'].update({
92 'framesize': outer_l2.get('framesize'),
93 'framesPerSecond': True,
94 'QinQ': outer_l2.get('QinQ'),
95 'srcmac': mac.get('src_mac_{}'.format(port_index)),
96 'dstmac': mac.get('dst_mac_{}'.format(port_index)),
99 if value.get('outer_l3v4'):
100 outer_l3 = value['outer_l3v4']
101 src_key, dst_key = 'srcip4', 'dstip4'
103 outer_l3 = value.get('outer_l3v6')
104 src_key, dst_key = 'srcip6', 'dstip6'
106 srcip = srcmask = dstip = dstmask = None
107 if outer_l3.get(src_key):
108 srcip, srcmask = self._get_ip_and_mask(outer_l3[src_key])
109 if outer_l3.get(dst_key):
110 dstip, dstmask = self._get_ip_and_mask(outer_l3[dst_key])
112 result[traffickey]['outer_l3'].update({
113 'count': outer_l3.get('count', 1),
114 'dscp': outer_l3.get('dscp'),
115 'ttl': outer_l3.get('ttl'),
116 'srcseed': outer_l3.get('srcseed', 1),
117 'dstseed': outer_l3.get('dstseed', 1),
123 'proto': outer_l3.get('proto'),
124 'priority': outer_l3.get('priority')
127 outer_l4 = value.get('outer_l4')
129 src_port = src_port_mask = dst_port = dst_port_mask = None
130 if outer_l4.get('srcport'):
131 src_port, src_port_mask = (
132 self._get_fixed_and_mask(outer_l4['srcport']))
134 if outer_l4.get('dstport'):
135 dst_port, dst_port_mask = (
136 self._get_fixed_and_mask(outer_l4['dstport']))
138 result[traffickey]['outer_l4'].update({
141 'srcportmask': src_port_mask,
142 'dstportmask': dst_port_mask,
143 'count': outer_l4.get('count', 1),
144 'seed': outer_l4.get('seed', 1),
149 def _ixia_traffic_generate(self, traffic, ixia_obj, traffic_gen):
150 ixia_obj.update_frame(traffic, self.config.duration)
151 ixia_obj.update_ip_packet(traffic)
152 ixia_obj.update_l4(traffic)
153 self._update_traffic_tracking_options(traffic_gen)
154 ixia_obj.start_traffic()
156 def _update_traffic_tracking_options(self, traffic_gen):
157 traffic_gen.update_tracking_options()
159 def update_traffic_profile(self, traffic_generator):
160 def port_generator():
161 for vld_id, intfs in sorted(traffic_generator.networks.items()):
162 if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
164 profile_data = self.params.get(vld_id)
167 self.profile_data = profile_data
168 self.full_profile.update({vld_id: self.profile_data})
170 yield traffic_generator.vnfd_helper.port_num(intf)
172 self.ports = [port for port in port_generator()]
174 def execute_traffic(self, traffic_generator, ixia_obj=None, mac=None):
175 mac = {} if mac is None else mac
176 first_run = self.first_run
178 self.first_run = False
180 self.max_rate = self.rate
183 self.rate = self._get_next_rate()
185 self.iteration = traffic_generator.rfc_helper.iteration.value
186 traffic = self._get_ixia_traffic_profile(self.full_profile, mac)
187 self._ixia_traffic_generate(traffic, ixia_obj, traffic_generator)
190 # pylint: disable=unused-argument
191 def get_drop_percentage(self, samples, tol_min, tolerance, precision,
192 resolution, first_run=False, tc_rfc2544_opts=None):
195 num_ifaces = len(samples)
196 duration = self.config.duration
197 in_packets_sum = sum(
198 [samples[iface]['InPackets'] for iface in samples])
199 out_packets_sum = sum(
200 [samples[iface]['OutPackets'] for iface in samples])
202 [samples[iface]['InBytes'] for iface in samples])
204 [samples[iface]['OutBytes'] for iface in samples])
205 rx_throughput = round(float(in_packets_sum) / duration, 3)
206 tx_throughput = round(float(out_packets_sum) / duration, 3)
207 # Rx throughput in Bps
208 rx_throughput_bps = round(float(in_bytes_sum) / duration, 3)
209 # Tx throughput in Bps
210 tx_throughput_bps = round(float(out_bytes_sum) / duration, 3)
211 packet_drop = abs(out_packets_sum - in_packets_sum)
214 drop_percent = round(
215 (packet_drop / float(out_packets_sum)) * 100,
216 self.DROP_PERCENT_ROUND)
217 except ZeroDivisionError:
218 LOG.info('No traffic is flowing')
221 completed = True if drop_percent <= tolerance else False
223 self.rate_unit == tp_base.TrafficProfileConfig.RATE_FPS):
224 self.rate = float(out_packets_sum) / duration / num_ifaces
226 if drop_percent > tolerance:
227 self.max_rate = self.rate
228 elif drop_percent < tol_min:
229 self.min_rate = self.rate
233 last_rate = self.rate
234 next_rate = self._get_next_rate()
235 if abs(next_rate - self.rate) < resolution:
236 LOG.debug("rate=%s, next_rate=%s, resolution=%s", self.rate,
237 next_rate, resolution)
238 # stop test if the difference between the rate transmission
239 # in two iterations is smaller than the value of the resolution
242 LOG.debug("tolerance=%s, tolerance_precision=%s drop_percent=%s "
243 "completed=%s", tolerance, precision, drop_percent,
246 latency_ns_avg = float(sum(
247 [samples[iface]['LatencyAvg'] for iface in samples])) / num_ifaces
248 latency_ns_min = min([samples[iface]['LatencyMin'] for iface in samples])
249 latency_ns_max = max([samples[iface]['LatencyMax'] for iface in samples])
251 samples['Status'] = self.STATUS_FAIL
252 if round(drop_percent, precision) <= tolerance:
253 samples['Status'] = self.STATUS_SUCCESS
255 samples['TxThroughput'] = tx_throughput
256 samples['RxThroughput'] = rx_throughput
257 samples['TxThroughputBps'] = tx_throughput_bps
258 samples['RxThroughputBps'] = rx_throughput_bps
259 samples['DropPercentage'] = drop_percent
260 samples['LatencyAvg'] = latency_ns_avg
261 samples['LatencyMin'] = latency_ns_min
262 samples['LatencyMax'] = latency_ns_max
263 samples['Rate'] = last_rate
264 samples['PktSize'] = self._get_framesize()
265 samples['Iteration'] = self.iteration
267 return completed, samples
270 class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
271 """Class handles BNG PPPoE scenario tests traffic profile"""
273 def __init__(self, yaml_data):
274 super(IXIARFC2544PppoeScenarioProfile, self).__init__(yaml_data)
275 self.full_profile = collections.OrderedDict()
277 def _get_flow_groups_params(self):
278 flows_data = [key for key in self.params.keys()
279 if key.split('_')[0] in [self.UPLINK, self.DOWNLINK]]
280 for i in range(len(flows_data)):
281 uplink = '_'.join([self.UPLINK, str(i)])
282 downlink = '_'.join([self.DOWNLINK, str(i)])
283 if uplink in flows_data:
284 self.full_profile.update({uplink: self.params[uplink]})
285 if downlink in flows_data:
286 self.full_profile.update({downlink: self.params[downlink]})
288 def update_traffic_profile(self, traffic_generator):
290 networks = collections.OrderedDict()
292 # Sort network interfaces pairs
293 for i in range(len(traffic_generator.networks)):
294 uplink = '_'.join([self.UPLINK, str(i)])
295 downlink = '_'.join([self.DOWNLINK, str(i)])
296 if uplink in traffic_generator.networks:
297 networks[uplink] = traffic_generator.networks[uplink]
298 if downlink in traffic_generator.networks:
299 networks[downlink] = traffic_generator.networks[downlink]
301 def port_generator():
302 for intfs in networks.values():
304 yield traffic_generator.vnfd_helper.port_num(intf)
306 self._get_flow_groups_params()
307 self.ports = [port for port in port_generator()]
309 def _get_prio_flows_drop_percentage(self, stats):
311 for prio_id in stats:
312 prio_flow = stats[prio_id]
313 sum_packet_drop = abs(prio_flow['OutPackets'] - prio_flow['InPackets'])
315 drop_percent = round(
316 (sum_packet_drop / float(prio_flow['OutPackets'])) * 100,
317 self.DROP_PERCENT_ROUND)
318 except ZeroDivisionError:
319 LOG.info('No traffic is flowing')
320 prio_flow['DropPercentage'] = drop_percent
323 def _get_summary_pppoe_subs_counters(self, samples):
325 keys = ['SessionsUp',
327 'SessionsNotStarted',
331 sum([samples[port][key] for port in samples
332 if key in samples[port]])
335 def get_drop_percentage(self, samples, tol_min, tolerance, precision,
336 resolution, first_run=False, tc_rfc2544_opts=None):
338 sum_drop_percent = 100
339 num_ifaces = len(samples)
340 duration = self.config.duration
341 last_rate = self.rate
342 priority_stats = samples.pop('priority_stats')
343 priority_stats = self._get_prio_flows_drop_percentage(priority_stats)
344 summary_subs_stats = self._get_summary_pppoe_subs_counters(samples)
345 in_packets_sum = sum(
346 [samples[iface]['InPackets'] for iface in samples])
347 out_packets_sum = sum(
348 [samples[iface]['OutPackets'] for iface in samples])
350 [samples[iface]['InBytes'] for iface in samples])
352 [samples[iface]['OutBytes'] for iface in samples])
353 rx_throughput = round(float(in_packets_sum) / duration, 3)
354 tx_throughput = round(float(out_packets_sum) / duration, 3)
355 # Rx throughput in Bps
356 rx_throughput_bps = round(float(in_bytes_sum) / duration, 3)
357 # Tx throughput in Bps
358 tx_throughput_bps = round(float(out_bytes_sum) / duration, 3)
359 sum_packet_drop = abs(out_packets_sum - in_packets_sum)
362 sum_drop_percent = round(
363 (sum_packet_drop / float(out_packets_sum)) * 100,
364 self.DROP_PERCENT_ROUND)
365 except ZeroDivisionError:
366 LOG.info('No traffic is flowing')
368 latency_ns_avg = float(sum(
369 [samples[iface]['LatencyAvg'] for iface in samples])) / num_ifaces
370 latency_ns_min = min([samples[iface]['LatencyMin'] for iface in samples])
371 latency_ns_max = max([samples[iface]['LatencyMax'] for iface in samples])
373 samples['TxThroughput'] = tx_throughput
374 samples['RxThroughput'] = rx_throughput
375 samples['TxThroughputBps'] = tx_throughput_bps
376 samples['RxThroughputBps'] = rx_throughput_bps
377 samples['DropPercentage'] = sum_drop_percent
378 samples['LatencyAvg'] = latency_ns_avg
379 samples['LatencyMin'] = latency_ns_min
380 samples['LatencyMax'] = latency_ns_max
381 samples['Priority'] = priority_stats
382 samples['Rate'] = last_rate
383 samples['PktSize'] = self._get_framesize()
384 samples['Iteration'] = self.iteration
385 samples.update(summary_subs_stats)
388 priority = tc_rfc2544_opts.get('priority')
390 drop_percent = samples['Priority'][priority]['DropPercentage']
392 drop_percent = sum_drop_percent
394 drop_percent = sum_drop_percent
397 completed = True if drop_percent <= tolerance else False
399 self.rate_unit == tp_base.TrafficProfileConfig.RATE_FPS):
400 self.rate = float(out_packets_sum) / duration / num_ifaces
402 if drop_percent > tolerance:
403 self.max_rate = self.rate
404 elif drop_percent < tol_min:
405 self.min_rate = self.rate
409 next_rate = self._get_next_rate()
410 if abs(next_rate - self.rate) < resolution:
411 LOG.debug("rate=%s, next_rate=%s, resolution=%s", self.rate,
412 next_rate, resolution)
413 # stop test if the difference between the rate transmission
414 # in two iterations is smaller than the value of the resolution
417 LOG.debug("tolerance=%s, tolerance_precision=%s drop_percent=%s "
418 "completed=%s", tolerance, precision, drop_percent,
421 samples['Status'] = self.STATUS_FAIL
422 if round(drop_percent, precision) <= tolerance:
423 samples['Status'] = self.STATUS_SUCCESS
425 return completed, samples