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