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.
15 from __future__ import absolute_import
16 from __future__ import print_function
21 from itertools import product
23 log = logging.getLogger(__name__)
29 class TrafficStreamHelper(object):
31 TEMPLATE = '{0.traffic_item}/{0.stream}:{0.param_id}/{1}'
33 def __init__(self, traffic_item, stream, param_id):
34 super(TrafficStreamHelper, self).__init__()
35 self.traffic_item = traffic_item
37 self.param_id = param_id
39 def __getattr__(self, item):
40 return self.TEMPLATE.format(self, item)
43 class FramesizeHelper(object):
46 super(FramesizeHelper, self).__init__()
47 self.weighted_pairs = []
48 self.weighted_range_pairs = []
51 def weighted_pairs_arg(self):
52 return '-weightedPairs', self.weighted_pairs
55 def weighted_range_pairs_arg(self):
56 return '-weightedRangePairs', self.weighted_range_pairs
58 def make_args(self, *args):
59 return self.weighted_pairs_arg + self.weighted_range_pairs_arg + args
61 def populate_data(self, framesize_data):
62 for key, value in framesize_data.items():
66 replaced = re.sub('[Bb]', '', key)
67 self.weighted_pairs.extend([
76 self.weighted_range_pairs.append(pairs)
79 class IxNextgen(object):
82 "traffic_item": 'Traffic Item',
83 "Tx_Frames": 'Tx Frames',
84 "Rx_Frames": 'Rx Frames',
85 "Tx_Frame_Rate": 'Tx Frame Rate',
86 "Rx_Frame_Rate": 'Tx Frame Rate',
87 "Store-Forward_Avg_latency_ns": 'Store-Forward Avg Latency (ns)',
88 "Store-Forward_Min_latency_ns": 'Store-Forward Min Latency (ns)',
89 "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)',
92 PORT_STATS_NAME_MAP = {
93 "stat_name": 'Stat Name',
94 "Frames_Tx": 'Frames Tx.',
95 "Valid_Frames_Rx": 'Valid Frames Rx.',
96 "Frames_Tx_Rate": 'Frames Tx. Rate',
97 "Valid_Frames_Rx_Rate": 'Valid Frames Rx. Rate',
98 "Tx_Rate_Kbps": 'Tx. Rate (Kbps)',
99 "Rx_Rate_Kbps": 'Rx. Rate (Kbps)',
100 "Tx_Rate_Mbps": 'Tx. Rate (Mbps)',
101 "Rx_Rate_Mbps": 'Rx. Rate (Mbps)',
105 "Store-Forward_Avg_latency_ns": 'Store-Forward Avg Latency (ns)',
106 "Store-Forward_Min_latency_ns": 'Store-Forward Min Latency (ns)',
107 "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)',
111 IP_VERSION_4: '0.0.0.255',
112 IP_VERSION_6: '0:0:0:0:0:0:0:ff',
116 0: ('private', ['256', '2048']),
119 MODE_SEEDS_DEFAULT = 'public', ['2048', '256']
122 def find_view_obj(view_name, views):
123 edited_view_name = '::ixNet::OBJ-/statistics/view:"{}"'.format(view_name)
124 return next((view for view in views if edited_view_name == view), '')
127 def get_config(tg_cfg):
128 external_interface = tg_cfg["vdu"][0]["external-interface"]
129 card_port0 = external_interface[0]["virtual-interface"]["vpci"]
130 card_port1 = external_interface[1]["virtual-interface"]["vpci"]
131 card0, port0 = card_port0.split(':')[:2]
132 card1, port1 = card_port1.split(':')[:2]
134 'py_lib_path': tg_cfg["mgmt-interface"]["tg-config"]["py_lib_path"],
135 'machine': tg_cfg["mgmt-interface"]["ip"],
136 'port': tg_cfg["mgmt-interface"]["tg-config"]["tcl_port"],
137 'chassis': tg_cfg["mgmt-interface"]["tg-config"]["ixchassis"],
142 'output_dir': tg_cfg["mgmt-interface"]["tg-config"]["dut_result_dir"],
143 'version': tg_cfg["mgmt-interface"]["tg-config"]["version"],
148 def __init__(self, ixnet=None):
150 self._objRefs = dict()
152 self._logger = logging.getLogger(__name__)
156 def iter_over_get_lists(self, x1, x2, y2, offset=0):
157 for x in self.ixnet.getList(x1, x2):
158 y_list = self.ixnet.getList(x, y2)
159 for i, y in enumerate(y_list, offset):
162 def set_random_ip_multi_attribute(self, ipv4, seed, fixed_bits, random_mask, l3_count):
163 self.ixnet.setMultiAttribute(
166 '-fixedBits', str(fixed_bits),
167 '-randomMask', str(random_mask),
168 '-valueType', 'random',
169 '-countValue', str(l3_count))
171 def set_random_ip_multi_attributes(self, ip, version, seeds, l3):
173 random_mask = self.RANDOM_MASK_MAP[version]
175 raise ValueError('Unknown version %s' % version)
177 l3_count = l3['count']
179 fixed_bits = l3['srcip4']
180 self.set_random_ip_multi_attribute(ip, seeds[0], fixed_bits, random_mask, l3_count)
182 fixed_bits = l3['dstip4']
183 self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count)
185 def add_ip_header(self, params, version):
186 for it, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement"):
187 mode, seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)
188 l3 = params[mode]['outer_l3']
190 for ip, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
191 self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3)
195 def _connect(self, tg_cfg):
196 self._cfg = self.get_config(tg_cfg)
198 sys.path.append(self._cfg["py_lib_path"])
199 # Import IxNetwork after getting ixia lib path
205 self.ixnet = IxNetwork.IxNet()
207 machine = self._cfg['machine']
208 port = str(self._cfg['port'])
209 version = str(self._cfg['version'])
210 result = self.ixnet.connect(machine, '-port', port, '-version', version)
213 def clear_ixia_config(self):
214 self.ixnet.execute('newConfig')
216 def load_ixia_profile(self, profile):
217 self.ixnet.execute('loadConfig', self.ixnet.readFrom(profile))
219 def ix_load_config(self, profile):
220 self.clear_ixia_config()
221 self.load_ixia_profile(profile)
223 def ix_assign_ports(self):
224 vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
226 (self._cfg['chassis'], self._cfg['card1'], self._cfg['port1']),
227 (self._cfg['chassis'], self._cfg['card2'], self._cfg['port2']),
230 vport_list = self.ixnet.getList("/", "vport")
231 self.ixnet.execute('assignPorts', ports, [], vport_list, True)
235 if self.ixnet.getAttribute(vport, '-state') != 'up':
236 log.error("Both thr ports are down...")
238 def ix_update_frame(self, params):
239 streams = ["configElement"]
241 for param in params.values():
242 framesize_data = FramesizeHelper()
243 traffic_items = self.ixnet.getList('/traffic', 'trafficItem')
244 param_id = param['id']
245 for traffic_item, stream in product(traffic_items, streams):
246 helper = TrafficStreamHelper(traffic_item, stream, param_id)
248 self.ixnet.setMultiAttribute(helper.transmissionControl,
249 '-type', '{0}'.format(param['traffic_type']),
250 '-duration', '{0}'.format(param['duration']))
252 stream_frame_rate_path = helper.frameRate
253 self.ixnet.setMultiAttribute(stream_frame_rate_path, '-rate', param['iload'])
254 if param['outer_l2']['framesPerSecond']:
255 self.ixnet.setMultiAttribute(stream_frame_rate_path,
256 '-type', 'framesPerSecond')
258 framesize_data.populate_data(param['outer_l2']['framesize'])
260 make_attr_args = framesize_data.make_args('-incrementFrom', '66',
263 '-type', 'weightedPairs',
264 '-presetDistribution', 'cisco',
265 '-incrementTo', '1518')
267 self.ixnet.setMultiAttribute(helper.frameSize, *make_attr_args)
271 def update_ether_multi_attribute(self, ether, mac_addr):
272 self.ixnet.setMultiAttribute(ether,
273 '-singleValue', mac_addr,
274 '-fieldValue', mac_addr,
275 '-valueType', 'singleValue')
277 def update_ether_multi_attributes(self, ether, l2):
278 if "ethernet.header.destinationAddress" in ether:
279 self.update_ether_multi_attribute(ether, str(l2['dstmac']))
281 if "ethernet.header.sourceAddress" in ether:
282 self.update_ether_multi_attribute(ether, str(l2['srcmac']))
284 def ix_update_ether(self, params):
285 for ti, ep, index in self.iter_over_get_lists('/traffic', 'trafficItem',
287 iter1 = (v['outer_l2'] for v in params.values() if str(v['id']) == str(index))
293 for ip, ether, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
294 self.update_ether_multi_attributes(ether, l2)
298 def ix_update_udp(self, params):
301 def ix_update_tcp(self, params):
304 def ix_start_traffic(self):
305 tis = self.ixnet.getList('/traffic', 'trafficItem')
307 self.ixnet.execute('generate', [ti])
308 self.ixnet.execute('apply', '/traffic')
309 self.ixnet.execute('start', '/traffic')
311 def ix_stop_traffic(self):
312 tis = self.ixnet.getList('/traffic', 'trafficItem')
314 self.ixnet.execute('stop', '/traffic')
316 def build_stats_map(self, view_obj, name_map):
317 return {kl: self.execute_get_column_values(view_obj, kr) for kl, kr in name_map.items()}
319 def execute_get_column_values(self, view_obj, name):
320 return self.ixnet.execute('getColumnValues', view_obj, name)
322 def ix_get_statistics(self):
323 views = self.ixnet.getList('/statistics', 'view')
325 view_obj = self.find_view_obj("Traffic Item Statistics", views)
326 stats = self.build_stats_map(view_obj, self.STATS_NAME_MAP)
328 view_obj = self.find_view_obj("Port Statistics", views)
329 ports_stats = self.build_stats_map(view_obj, self.PORT_STATS_NAME_MAP)
331 view_obj = self.find_view_obj("Flow Statistics", views)
332 stats["latency"] = self.build_stats_map(view_obj, self.LATENCY_NAME_MAP)
334 return stats, ports_stats