1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Performance testing traffic generator library."""
16 from robot.api import logger
18 from resources.libraries.python.ssh import SSH
19 from resources.libraries.python.topology import NodeType
20 from resources.libraries.python.topology import NodeSubTypeTG
21 from resources.libraries.python.topology import Topology
23 __all__ = ['TrafficGenerator']
25 class TrafficGenerator(object):
26 """Traffic Generator"""
33 #T-REX interface order mapping
34 self._ifaces_reordered = 0
36 def initialize_traffic_generator(self, node, interface1, interface2, test_type):
38 :param node: Traffic generator node
39 :param interface1: interface name of first interface
40 :param interface2: interface name of second interface
41 :test_type: 'L2' or 'L3' - src/dst MAC address
49 trex_path = "/opt/trex-core-1.91"
53 if node['type'] != NodeType.TG:
54 raise Exception('Node type is not a TG')
55 if node['subtype'] == NodeSubTypeTG.TREX:
59 iface1_pci = topo.get_interface_pci_addr(node, interface1)
60 iface2_pci = topo.get_interface_pci_addr(node, interface2)
61 iface1_mac = topo.get_interface_mac(node, interface1)
62 iface2_mac = topo.get_interface_mac(node, interface2)
63 if min(iface1_pci, iface2_pci) != iface1_pci:
64 iface1_mac, iface2_mac = iface2_mac, iface1_mac
65 iface1_pci, iface2_pci = iface2_pci, iface1_pci
66 self._ifaces_reordered = 1
68 iface1_mac_hex = "0x"+iface1_mac.replace(":", ",0x")
69 iface2_mac_hex = "0x"+iface2_mac.replace(":", ",0x")
72 (ret, stdout, stderr) = ssh.exec_command(
73 "sudo sh -c 'cat << EOF > /etc/trex_cfg.yaml\n"
76 " interfaces : [\"{}\",\"{}\"]\n"
78 " - dest_mac : [{}]\n"
80 " - dest_mac : [{}]\n"
83 .format(iface1_pci, iface2_pci,
84 iface2_mac_hex, iface1_mac_hex,
85 iface1_mac_hex, iface2_mac_hex))
87 logger.error("failed to create t-rex config: {}"\
88 .format(stdout + stderr))
89 raise RuntimeError('trex config generation error')
90 elif test_type == 'L3':
91 raise NotImplementedError("L3 test_type not supported")
93 raise Exception("test_type unknown")
96 (ret, stdout, stderr) = ssh.exec_command(
97 "sh -c 'cd {0}/scripts/ && "
101 logger.error('trex-cfg failed: {0}'.format(stdout + stderr))
102 raise RuntimeError('trex-cfg failed')
104 (ret, _, _) = ssh.exec_command(
105 "sh -c 'cd {0}/scripts/ && "
106 "sudo nohup ./t-rex-64 -i -c 4 --iom 0 > /dev/null 2>&1 &'"
110 raise RuntimeError('t-rex-64 startup failed')
113 def teardown_traffic_generator(node):
115 :param node: Traffic generator node
120 if node['type'] != NodeType.TG:
121 raise Exception('Node type is not a TG')
122 if node['subtype'] == NodeSubTypeTG.TREX:
125 (ret, stdout, stderr) = ssh.exec_command(
126 "sh -c 'sudo pkill t-rex'")
128 def send_traffic_on(self, nodes_info, duration, rate,
129 framesize, traffic_type):
130 """Send traffic from all configured interfaces on TG
131 :param nodes_info: Dictionary containing information on all nodes
133 :param duration: Duration of test traffic generation in seconds
134 :param rate: Offered load per interface (e.g. 1%, 3gbps, 4mpps, ...)
135 :param framesize: Frame size (L2) in Bytes
136 :param traffic_type: Traffic profile
137 :type nodes_info: dict
141 :type traffic_type: str
146 node = nodes_info["TG"]
148 if node['type'] != NodeType.TG:
149 raise Exception('Node type is not a TG')
151 if node['subtype'] is None:
152 raise Exception('TG subtype not defined')
157 if node['subtype'] == NodeSubTypeTG.TREX:
158 if traffic_type in ["3-node-xconnect", "3-node-bridge"]:
159 (ret, stdout, stderr) = ssh.exec_command(
160 "sh -c '/tmp/openvpp-testing/resources/tools/t-rex/t-rex-stateless.py "
161 "-d {0} -r {1} -s {2} "
162 "--p1_src_start_ip 10.10.10.1 "
163 "--p1_src_end_ip 10.10.10.254 "
164 "--p1_dst_start_ip 20.20.20.1 "
165 "--p2_src_start_ip 20.20.20.1 "
166 "--p2_src_end_ip 20.20.20.254 "
167 "--p2_dst_start_ip 10.10.10.1'".\
168 format(duration, rate, framesize), timeout=int(duration)+60)
169 elif traffic_type in ["3-node-IPv4"]:
170 (ret, stdout, stderr) = ssh.exec_command(
171 "sh -c '/tmp/openvpp-testing/resources/tools/t-rex/t-rex-stateless.py "
172 "-d {0} -r {1} -s {2} "
173 "--p1_src_start_ip 10.10.10.2 "
174 "--p1_src_end_ip 10.10.10.254 "
175 "--p1_dst_start_ip 20.20.20.2 "
176 "--p2_src_start_ip 20.20.20.2 "
177 "--p2_src_end_ip 20.20.20.254 "
178 "--p2_dst_start_ip 10.10.10.2'".\
179 format(duration, rate, framesize),\
180 timeout=int(duration)+60)
182 raise NotImplementedError('Unsupported traffic type')
185 raise NotImplementedError("TG subtype not supported")
191 for line in stdout.splitlines():
195 logger.info('TrafficGen result: {0}'.format(self._result))
197 self._loss = self._result.split(', ')[3].split('=')[1]
201 def no_traffic_loss_occured(self):
202 """Fail is loss occured in traffic run
206 if self._loss is None:
207 raise Exception('The traffic generation has not been issued')
208 if self._loss != '0':
209 raise Exception('Traffic loss occured: {0}'.format(self._loss))