Merge "bugfix: tc078 fails in some situations"
[yardstick.git] / yardstick / network_services / traffic_profile / ixia_rfc2544.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 from __future__ import absolute_import
16 import logging
17
18 from yardstick.network_services.traffic_profile.traffic_profile import \
19     TrexProfile
20
21 LOG = logging.getLogger(__name__)
22
23
24 class IXIARFC2544Profile(TrexProfile):
25
26     UPLINK = 'uplink'
27     DOWNLINK = 'downlink'
28
29     def _get_ixia_traffic_profile(self, profile_data, mac=None, xfile=None, static_traffic=None):
30         if mac is None:
31             mac = {}
32
33         result = {}
34         for traffickey, values in profile_data.items():
35             if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
36                 continue
37
38             try:
39                 # values should be single-item dict, so just grab the first item
40                 try:
41                     key, value = next(iter(values.items()))
42                 except StopIteration:
43                     result[traffickey] = {}
44                     continue
45
46                 port_id = value.get('id', 1)
47                 port_index = port_id - 1
48                 try:
49                     ip = value['outer_l3v6']
50                 except KeyError:
51                     ip = value['outer_l3v4']
52                     src_key, dst_key = 'srcip4', 'dstip4'
53                 else:
54                     src_key, dst_key = 'srcip6', 'dstip6'
55
56                 result[traffickey] = {
57                     'bidir': False,
58                     'iload': '100',
59                     'id': port_id,
60                     'outer_l2': {
61                         'framesize': value['outer_l2']['framesize'],
62                         'framesPerSecond': True,
63                         'srcmac': mac['src_mac_{}'.format(port_index)],
64                         'dstmac': mac['dst_mac_{}'.format(port_index)],
65                     },
66                     'outer_l3': {
67                         'count': ip['count'],
68                         'dscp': ip['dscp'],
69                         'ttl': ip['ttl'],
70                         src_key: ip[src_key].split("-")[0],
71                         dst_key: ip[dst_key].split("-")[0],
72                         'type': key,
73                         'proto': ip['proto'],
74                     },
75                     'outer_l4': value['outer_l4'],
76                 }
77             except Exception:
78                 continue
79
80         return result
81
82     def _ixia_traffic_generate(self, traffic_generator, traffic, ixia_obj):
83         for key, value in traffic.items():
84             if key.startswith((self.UPLINK, self.DOWNLINK)):
85                 value["iload"] = str(self.rate)
86         ixia_obj.ix_update_frame(traffic)
87         ixia_obj.ix_update_ether(traffic)
88         ixia_obj.add_ip_header(traffic, 4)
89         ixia_obj.ix_start_traffic()
90         self.tmp_drop = 0
91         self.tmp_throughput = 0
92
93     def update_traffic_profile(self, traffic_generator):
94         def port_generator():
95             for vld_id, intfs in sorted(traffic_generator.networks.items()):
96                 if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
97                     continue
98                 profile_data = self.params.get(vld_id)
99                 if not profile_data:
100                     continue
101                 self.profile_data = profile_data
102                 self.get_streams(self.profile_data)
103                 self.full_profile.update({vld_id: self.profile_data})
104                 for intf in intfs:
105                     yield traffic_generator.vnfd_helper.port_num(intf)
106
107         self.ports = [port for port in port_generator()]
108
109     def execute_traffic(self, traffic_generator, ixia_obj, mac=None, xfile=None):
110         if mac is None:
111             mac = {}
112         if self.first_run:
113             self.full_profile = {}
114             self.pg_id = 0
115             self.update_traffic_profile(traffic_generator)
116             traffic = \
117                 self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
118             self.max_rate = self.rate
119             self.min_rate = 0
120             self.get_multiplier()
121             self._ixia_traffic_generate(traffic_generator, traffic, ixia_obj)
122
123     def get_multiplier(self):
124         self.rate = round((self.max_rate + self.min_rate) / 2.0, 2)
125         multiplier = round(self.rate / self.pps, 2)
126         return str(multiplier)
127
128     def start_ixia_latency(self, traffic_generator, ixia_obj,
129                            mac=None, xfile=None):
130         if mac is None:
131             mac = {}
132         self.update_traffic_profile(traffic_generator)
133         traffic = \
134             self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
135         self._ixia_traffic_generate(traffic_generator, traffic, ixia_obj)
136
137     def get_drop_percentage(self, traffic_generator, samples, tol_min,
138                             tolerance, ixia_obj, mac=None, xfile=None):
139         if mac is None:
140             mac = {}
141         status = 'Running'
142         drop_percent = 100
143         in_packets = sum([samples[iface]['in_packets'] for iface in samples])
144         out_packets = sum([samples[iface]['out_packets'] for iface in samples])
145         rx_throughput = \
146             sum([samples[iface]['RxThroughput'] for iface in samples])
147         tx_throughput = \
148             sum([samples[iface]['TxThroughput'] for iface in samples])
149         packet_drop = abs(out_packets - in_packets)
150         try:
151             drop_percent = round((packet_drop / float(out_packets)) * 100, 2)
152         except ZeroDivisionError:
153             LOG.info('No traffic is flowing')
154         samples['TxThroughput'] = round(tx_throughput / 1.0, 2)
155         samples['RxThroughput'] = round(rx_throughput / 1.0, 2)
156         samples['CurrentDropPercentage'] = drop_percent
157         samples['Throughput'] = self.tmp_throughput
158         samples['DropPercentage'] = self.tmp_drop
159         if drop_percent > tolerance and self.tmp_throughput == 0:
160             samples['Throughput'] = round(rx_throughput / 1.0, 2)
161             samples['DropPercentage'] = drop_percent
162         if self.first_run:
163             max_supported_rate = out_packets / 30.0
164             self.rate = max_supported_rate
165             self.first_run = False
166             if drop_percent <= tolerance:
167                 status = 'Completed'
168         if drop_percent > tolerance:
169             self.max_rate = self.rate
170         elif drop_percent < tol_min:
171             self.min_rate = self.rate
172             if drop_percent >= self.tmp_drop:
173                 self.tmp_drop = drop_percent
174                 self.tmp_throughput = round((rx_throughput / 1.0), 2)
175                 samples['Throughput'] = round(rx_throughput / 1.0, 2)
176                 samples['DropPercentage'] = drop_percent
177         else:
178             samples['Throughput'] = round(rx_throughput / 1.0, 2)
179             samples['DropPercentage'] = drop_percent
180             return status, samples
181         self.get_multiplier()
182         traffic = self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
183         self._ixia_traffic_generate(traffic_generator, traffic, ixia_obj)
184         return status, samples