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"""
28 ROBOT_LIBRARY_SCOPE = 'TEST SUITE'
35 #T-REX interface order mapping
36 self._ifaces_reordered = 0
38 def initialize_traffic_generator(self, tg_node, tg_if1, tg_if2,
39 dut1_node, dut1_if1, dut1_if2,
40 dut2_node, dut2_if1, dut2_if2,
43 :param tg_node: Traffic generator node
44 :param tg_if1: TG - name of first interface
45 :param tg_if2: TG - name of second interface
46 :param dut1_node: DUT1 node
47 :param dut1_if1: DUT1 - name of first interface
48 :param dut1_if2: DUT1 - name of second interface
49 :param dut2_node: DUT2 node
50 :param dut2_if1: DUT2 - name of first interface
51 :param dut2_if2: DUT2 - name of second interface
52 :test_type: 'L2' or 'L3' - src/dst MAC address
66 trex_path = "/opt/trex-core-1.91"
70 if tg_node['type'] != NodeType.TG:
71 raise Exception('Node type is not a TG')
72 if tg_node['subtype'] == NodeSubTypeTG.TREX:
76 if1_pci = topo.get_interface_pci_addr(tg_node, tg_if1)
77 if2_pci = topo.get_interface_pci_addr(tg_node, tg_if2)
78 if1_mac = topo.get_interface_mac(tg_node, tg_if1)
79 if2_mac = topo.get_interface_mac(tg_node, tg_if2)
84 elif test_type == 'L3':
85 if1_adj_mac = topo.get_interface_mac(dut1_node, dut1_if1)
86 if2_adj_mac = topo.get_interface_mac(dut2_node, dut2_if2)
88 raise Exception("test_type unknown")
90 if min(if1_pci, if2_pci) != if1_pci:
91 if1_mac, if2_mac = if2_mac, if1_mac
92 if1_pci, if2_pci = if2_pci, if1_pci
93 if1_adj_mac, if2_adj_mac = if2_adj_mac, if1_adj_mac
94 self._ifaces_reordered = 1
96 if1_mac_hex = "0x"+if1_mac.replace(":", ",0x")
97 if2_mac_hex = "0x"+if2_mac.replace(":", ",0x")
98 if1_adj_mac_hex = "0x"+if1_adj_mac.replace(":", ",0x")
99 if2_adj_mac_hex = "0x"+if2_adj_mac.replace(":", ",0x")
101 (ret, stdout, stderr) = ssh.exec_command(
102 "sudo sh -c 'cat << EOF > /etc/trex_cfg.yaml\n"
105 " interfaces : [\"{}\",\"{}\"]\n"
107 " - dest_mac : [{}]\n"
109 " - dest_mac : [{}]\n"
112 .format(if1_pci, if2_pci,
113 if1_adj_mac_hex, if1_mac_hex,
114 if2_adj_mac_hex, if2_mac_hex))
116 logger.error("failed to create t-rex config: {}"\
117 .format(stdout + stderr))
118 raise RuntimeError('trex config generation error')
120 (ret, stdout, stderr) = ssh.exec_command(
121 "sh -c 'cd {0}/scripts/ && "
125 logger.error('trex-cfg failed: {0}'.format(stdout + stderr))
126 raise RuntimeError('trex-cfg failed')
128 (ret, _, _) = ssh.exec_command(
129 "sh -c 'cd {0}/scripts/ && "
130 "sudo nohup ./t-rex-64 -i -c 4 --iom 0 > /dev/null 2>&1 &'"
134 raise RuntimeError('t-rex-64 startup failed')
137 def teardown_traffic_generator(node):
139 :param node: Traffic generator node
144 if node['type'] != NodeType.TG:
145 raise Exception('Node type is not a TG')
146 if node['subtype'] == NodeSubTypeTG.TREX:
149 (ret, stdout, stderr) = ssh.exec_command(
150 "sh -c 'sudo pkill t-rex'")
152 logger.error('pkill t-rex failed: {0}'.format(stdout + stderr))
153 raise RuntimeError('pkill t-rex failed')
155 def send_traffic_on(self, nodes_info, duration, rate,
156 framesize, traffic_type):
157 """Send traffic from all configured interfaces on TG
158 :param nodes_info: Dictionary containing information on all nodes
160 :param duration: Duration of test traffic generation in seconds
161 :param rate: Offered load per interface (e.g. 1%, 3gbps, 4mpps, ...)
162 :param framesize: Frame size (L2) in Bytes
163 :param traffic_type: Traffic profile
164 :type nodes_info: dict
168 :type traffic_type: str
173 node = nodes_info["TG"]
175 if node['type'] != NodeType.TG:
176 raise Exception('Node type is not a TG')
178 if node['subtype'] is None:
179 raise Exception('TG subtype not defined')
184 if node['subtype'] == NodeSubTypeTG.TREX:
189 if self._ifaces_reordered != 0:
192 if traffic_type in ["3-node-xconnect", "3-node-bridge"]:
193 (ret, stdout, stderr) = ssh.exec_command(
194 "sh -c '/tmp/openvpp-testing/resources/tools/t-rex/"
195 "t-rex-stateless.py "
196 "-d {0} -r {1} -s {2} "
197 "--p{3}_src_start_ip 10.10.10.1 "
198 "--p{3}_src_end_ip 10.10.10.254 "
199 "--p{3}_dst_start_ip 20.20.20.1 "
200 "--p{4}_src_start_ip 20.20.20.1 "
201 "--p{4}_src_end_ip 20.20.20.254 "
202 "--p{4}_dst_start_ip 10.10.10.1'".\
203 format(duration, rate, framesize, _p0, _p1),\
204 timeout=int(duration)+60)
205 elif traffic_type in ["3-node-IPv4"]:
206 (ret, stdout, stderr) = ssh.exec_command(
207 "sh -c '/tmp/openvpp-testing/resources/tools/t-rex/"
208 "t-rex-stateless.py "
209 "-d {0} -r {1} -s {2} "
210 "--p{3}_src_start_ip 10.10.10.2 "
211 "--p{3}_src_end_ip 10.10.10.254 "
212 "--p{3}_dst_start_ip 20.20.20.2 "
213 "--p{4}_src_start_ip 20.20.20.2 "
214 "--p{4}_src_end_ip 20.20.20.254 "
215 "--p{4}_dst_start_ip 10.10.10.2'".\
216 format(duration, rate, framesize, _p0, _p1),\
217 timeout=int(duration)+60)
219 raise NotImplementedError('Unsupported traffic type')
222 raise NotImplementedError("TG subtype not supported")
228 for line in stdout.splitlines():
232 logger.info('TrafficGen result: {0}'.format(self._result))
234 self._loss = self._result.split(', ')[3].split('=')[1]
238 def no_traffic_loss_occured(self):
239 """Fail is loss occured in traffic run
243 if self._loss is None:
244 raise Exception('The traffic generation has not been issued')
245 if self._loss != '0':
246 raise Exception('Traffic loss occured: {0}'.format(self._loss))