1 # Copyright (c) 2016-2017 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
32 STATUS_SUCCESS = "Success"
33 STATUS_FAIL = "Failure"
35 def __init__(self, yaml_data):
36 super(IXIARFC2544Profile, self).__init__(yaml_data)
37 self.rate = self.config.frame_rate
38 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 outer_l2 = value.get('outer_l2')
85 result[traffickey]['outer_l2'].update({
86 'framesize': outer_l2.get('framesize'),
87 'framesPerSecond': True,
88 'QinQ': outer_l2.get('QinQ'),
89 'srcmac': mac.get('src_mac_{}'.format(port_index)),
90 'dstmac': mac.get('dst_mac_{}'.format(port_index)),
93 if value.get('outer_l3v4'):
94 outer_l3 = value['outer_l3v4']
95 src_key, dst_key = 'srcip4', 'dstip4'
97 outer_l3 = value.get('outer_l3v6')
98 src_key, dst_key = 'srcip6', 'dstip6'
100 srcip = srcmask = dstip = dstmask = None
101 if outer_l3.get(src_key):
102 srcip, srcmask = self._get_ip_and_mask(outer_l3[src_key])
103 if outer_l3.get(dst_key):
104 dstip, dstmask = self._get_ip_and_mask(outer_l3[dst_key])
106 result[traffickey]['outer_l3'].update({
107 'count': outer_l3.get('count', 1),
108 'dscp': outer_l3.get('dscp'),
109 'ttl': outer_l3.get('ttl'),
110 'srcseed': outer_l3.get('srcseed', 1),
111 'dstseed': outer_l3.get('dstseed', 1),
117 'proto': outer_l3.get('proto'),
118 'priority': outer_l3.get('priority')
121 outer_l4 = value.get('outer_l4')
123 src_port = src_port_mask = dst_port = dst_port_mask = None
124 if outer_l4.get('srcport'):
125 src_port, src_port_mask = (
126 self._get_fixed_and_mask(outer_l4['srcport']))
128 if outer_l4.get('dstport'):
129 dst_port, dst_port_mask = (
130 self._get_fixed_and_mask(outer_l4['dstport']))
132 result[traffickey]['outer_l4'].update({
135 'srcportmask': src_port_mask,
136 'dstportmask': dst_port_mask,
137 'count': outer_l4.get('count', 1),
138 'seed': outer_l4.get('seed', 1),
143 def _ixia_traffic_generate(self, traffic, ixia_obj):
144 ixia_obj.update_frame(traffic, self.config.duration)
145 ixia_obj.update_ip_packet(traffic)
146 ixia_obj.update_l4(traffic)
147 ixia_obj.start_traffic()
149 def update_traffic_profile(self, traffic_generator):
150 def port_generator():
151 for vld_id, intfs in sorted(traffic_generator.networks.items()):
152 if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
154 profile_data = self.params.get(vld_id)
157 self.profile_data = profile_data
158 self.full_profile.update({vld_id: self.profile_data})
160 yield traffic_generator.vnfd_helper.port_num(intf)
162 self.ports = [port for port in port_generator()]
164 def execute_traffic(self, traffic_generator, ixia_obj=None, mac=None):
165 mac = {} if mac is None else mac
166 first_run = self.first_run
168 self.first_run = False
170 self.max_rate = self.rate
173 self.rate = round(float(self.max_rate + self.min_rate) / 2.0,
176 traffic = self._get_ixia_traffic_profile(self.full_profile, mac)
177 self._ixia_traffic_generate(traffic, ixia_obj)
180 def get_drop_percentage(self, samples, tol_min, tolerance, precision,
184 num_ifaces = len(samples)
185 duration = self.config.duration
186 in_packets_sum = sum(
187 [samples[iface]['in_packets'] for iface in samples])
188 out_packets_sum = sum(
189 [samples[iface]['out_packets'] for iface in samples])
190 rx_throughput = round(float(in_packets_sum) / duration, 3)
191 tx_throughput = round(float(out_packets_sum) / duration, 3)
192 packet_drop = abs(out_packets_sum - in_packets_sum)
195 drop_percent = round(
196 (packet_drop / float(out_packets_sum)) * 100,
197 self.DROP_PERCENT_ROUND)
198 except ZeroDivisionError:
199 LOG.info('No traffic is flowing')
202 completed = True if drop_percent <= tolerance else False
204 self.rate_unit == tp_base.TrafficProfileConfig.RATE_FPS):
205 self.rate = float(out_packets_sum) / duration / num_ifaces
207 if drop_percent > tolerance:
208 self.max_rate = self.rate
209 elif drop_percent < tol_min:
210 self.min_rate = self.rate
214 LOG.debug("tolerance=%s, tolerance_precision=%s drop_percent=%s "
215 "completed=%s", tolerance, precision, drop_percent,
218 latency_ns_avg = float(
219 sum([samples[iface]['Store-Forward_Avg_latency_ns']
220 for iface in samples])) / num_ifaces
221 latency_ns_min = float(
222 sum([samples[iface]['Store-Forward_Min_latency_ns']
223 for iface in samples])) / num_ifaces
224 latency_ns_max = float(
225 sum([samples[iface]['Store-Forward_Max_latency_ns']
226 for iface in samples])) / num_ifaces
228 samples['Status'] = self.STATUS_FAIL
229 if round(drop_percent, precision) <= tolerance:
230 samples['Status'] = self.STATUS_SUCCESS
232 samples['TxThroughput'] = tx_throughput
233 samples['RxThroughput'] = rx_throughput
234 samples['DropPercentage'] = drop_percent
235 samples['latency_ns_avg'] = latency_ns_avg
236 samples['latency_ns_min'] = latency_ns_min
237 samples['latency_ns_max'] = latency_ns_max
239 return completed, samples
242 class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
243 """Class handles BNG PPPoE scenario tests traffic profile"""
245 def __init__(self, yaml_data):
246 super(IXIARFC2544PppoeScenarioProfile, self).__init__(yaml_data)
247 self.full_profile = collections.OrderedDict()
249 def _get_flow_groups_params(self):
250 flows_data = [key for key in self.params.keys()
251 if key.split('_')[0] in [self.UPLINK, self.DOWNLINK]]
252 for i in range(len(flows_data)):
253 uplink = '_'.join([self.UPLINK, str(i)])
254 downlink = '_'.join([self.DOWNLINK, str(i)])
255 if uplink in flows_data:
256 self.full_profile.update({uplink: self.params[uplink]})
257 if downlink in flows_data:
258 self.full_profile.update({downlink: self.params[downlink]})
260 def update_traffic_profile(self, traffic_generator):
261 def port_generator():
262 for vld_id, intfs in sorted(traffic_generator.networks.items()):
263 if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
266 yield traffic_generator.vnfd_helper.port_num(intf)
268 self._get_flow_groups_params()
269 self.ports = [port for port in port_generator()]