+ self._node = None
+ # T-REX interface order mapping
+ self._ifaces_reordered = False
+ # Parameters not given by measure().
+ self.frame_size = None
+ self.traffic_profile = None
+ self.warmup_time = None
+
+ @property
+ def node(self):
+ """Getter.
+
+ :returns: Traffic generator node.
+ :rtype: dict
+ """
+ return self._node
+
+ def get_loss(self):
+ """Return number of lost packets.
+
+ :returns: Number of lost packets.
+ :rtype: str
+ """
+ return self._loss
+
+ def get_sent(self):
+ """Return number of sent packets.
+
+ :returns: Number of sent packets.
+ :rtype: str
+ """
+ return self._sent
+
+ def get_received(self):
+ """Return number of received packets.
+
+ :returns: Number of received packets.
+ :rtype: str
+ """
+ return self._received
+
+ def get_latency_int(self):
+ """Return rounded min/avg/max latency.
+
+ :returns: Latency stats.
+ :rtype: list
+ """
+ return self._latency
+
+ def initialize_traffic_generator(
+ self, tg_node, tg_if1, tg_if2, tg_if1_adj_node, tg_if1_adj_if,
+ tg_if2_adj_node, tg_if2_adj_if, osi_layer, tg_if1_dst_mac=None,
+ tg_if2_dst_mac=None):
+ """TG initialization.
+
+ TODO: Document why do we need (and how do we use) _ifaces_reordered.
+
+ :param tg_node: Traffic generator node.
+ :param tg_if1: TG - name of first interface.
+ :param tg_if2: TG - name of second interface.
+ :param tg_if1_adj_node: TG if1 adjecent node.
+ :param tg_if1_adj_if: TG if1 adjecent interface.
+ :param tg_if2_adj_node: TG if2 adjecent node.
+ :param tg_if2_adj_if: TG if2 adjecent interface.
+ :param osi_layer: 'L2', 'L3' or 'L7' - OSI Layer testing type.
+ :param tg_if1_dst_mac: Interface 1 destination MAC address.
+ :param tg_if2_dst_mac: Interface 2 destination MAC address.
+ :type tg_node: dict
+ :type tg_if1: str
+ :type tg_if2: str
+ :type tg_if1_adj_node: dict
+ :type tg_if1_adj_if: str
+ :type tg_if2_adj_node: dict
+ :type tg_if2_adj_if: str
+ :type osi_layer: str
+ :type tg_if1_dst_mac: str
+ :type tg_if2_dst_mac: str
+ :returns: nothing
+ :raises RuntimeError: In case of issue during initialization.
+ """
+ if tg_node['type'] != NodeType.TG:
+ raise RuntimeError('Node type is not a TG')
+ self._node = tg_node
+
+ if self._node['subtype'] == NodeSubTypeTG.TREX:
+ ssh = SSH()
+ ssh.connect(self._node)
+
+ (ret, _, _) = ssh.exec_command(
+ "sudo -E sh -c '{0}/resources/tools/trex/"
+ "trex_installer.sh {1}'".format(Constants.REMOTE_FW_DIR,
+ Constants.TREX_INSTALL_VERSION),
+ timeout=1800)
+ if int(ret) != 0:
+ raise RuntimeError('TRex installation failed.')
+
+ if1_pci = Topology().get_interface_pci_addr(self._node, tg_if1)
+ if2_pci = Topology().get_interface_pci_addr(self._node, tg_if2)
+ if1_addr = Topology().get_interface_mac(self._node, tg_if1)
+ if2_addr = Topology().get_interface_mac(self._node, tg_if2)
+
+ if osi_layer == 'L2':
+ if1_adj_addr = if2_addr
+ if2_adj_addr = if1_addr
+ elif osi_layer == 'L3':
+ if1_adj_addr = Topology().get_interface_mac(tg_if1_adj_node,
+ tg_if1_adj_if)
+ if2_adj_addr = Topology().get_interface_mac(tg_if2_adj_node,
+ tg_if2_adj_if)
+ elif osi_layer == 'L7':
+ if1_addr = Topology().get_interface_ip4(self._node, tg_if1)
+ if2_addr = Topology().get_interface_ip4(self._node, tg_if2)
+ if1_adj_addr = Topology().get_interface_ip4(tg_if1_adj_node,
+ tg_if1_adj_if)
+ if2_adj_addr = Topology().get_interface_ip4(tg_if2_adj_node,
+ tg_if2_adj_if)
+ else:
+ raise ValueError("Unknown Test Type")
+
+ # in case of switched environment we can override MAC addresses
+ if tg_if1_dst_mac is not None and tg_if2_dst_mac is not None:
+ if1_adj_addr = tg_if1_dst_mac
+ if2_adj_addr = tg_if2_dst_mac
+
+ if min(if1_pci, if2_pci) != if1_pci:
+ if1_pci, if2_pci = if2_pci, if1_pci
+ if1_addr, if2_addr = if2_addr, if1_addr
+ if1_adj_addr, if2_adj_addr = if2_adj_addr, if1_adj_addr
+ self._ifaces_reordered = True
+
+ if osi_layer == 'L2' or osi_layer == 'L3':
+ (ret, _, _) = ssh.exec_command(
+ "sudo sh -c 'cat << EOF > /etc/trex_cfg.yaml\n"
+ "- version: 2\n"
+ " interfaces: [\"{0}\",\"{1}\"]\n"
+ " port_info:\n"
+ " - dest_mac: [{2}]\n"
+ " src_mac: [{3}]\n"
+ " - dest_mac: [{4}]\n"
+ " src_mac: [{5}]\n"
+ "EOF'"\
+ .format(if1_pci, if2_pci,
+ "0x"+if1_adj_addr.replace(":", ",0x"),
+ "0x"+if1_addr.replace(":", ",0x"),
+ "0x"+if2_adj_addr.replace(":", ",0x"),
+ "0x"+if2_addr.replace(":", ",0x")))
+ elif osi_layer == 'L7':
+ (ret, _, _) = ssh.exec_command(
+ "sudo sh -c 'cat << EOF > /etc/trex_cfg.yaml\n"
+ "- version: 2\n"
+ " interfaces: [\"{0}\",\"{1}\"]\n"
+ " port_info:\n"
+ " - ip: [{2}]\n"
+ " default_gw: [{3}]\n"
+ " - ip: [{4}]\n"
+ " default_gw: [{5}]\n"
+ "EOF'"\
+ .format(if1_pci, if2_pci,
+ if1_addr, if1_adj_addr,
+ if2_addr, if2_adj_addr))
+ else:
+ raise ValueError("Unknown Test Type")
+ if int(ret) != 0:
+ raise RuntimeError('TRex config generation error')
+
+ self._startup_trex(osi_layer)
+
+ def _startup_trex(self, osi_layer):
+ """Startup sequence for the TRex traffic generator.
+
+ :param osi_layer: 'L2', 'L3' or 'L7' - OSI Layer testing type.
+ :type osi_layer: str
+ :raises RuntimeError: If node subtype is not a TREX or startup failed.
+ """
+ if self._node['subtype'] != NodeSubTypeTG.TREX:
+ raise RuntimeError('Node subtype is not a TREX!')
+
+ for _ in range(0, 3):
+ # Kill TRex only if it is already running.
+ cmd = "sh -c 'pgrep t-rex && pkill t-rex && sleep 3 || true'"
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True, message='Kill TRex failed!')
+
+ # Configure TRex.
+ ports = ''
+ for port in self._node['interfaces'].values():
+ ports += ' {pci}'.format(pci=port.get('pci_address'))
+
+ cmd = ("sh -c 'cd {dir}/scripts/ && "
+ "./dpdk_nic_bind.py -u {ports} || true'"
+ .format(dir=Constants.TREX_INSTALL_DIR, ports=ports))
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True,
+ message='Unbind PCI ports from driver failed!')
+
+ cmd = ("sh -c 'cd {dir}/scripts/ && ./trex-cfg'"
+ .format(dir=Constants.TREX_INSTALL_DIR))
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True, message='Config TRex failed!')
+
+ # Start TRex.
+ cmd = ("sh -c 'cd {dir}/scripts/ && "
+ "nohup ./t-rex-64 {mode} -i -c 7 > "
+ "/tmp/trex.log 2>&1 &' > /dev/null"
+ .format(dir=Constants.TREX_INSTALL_DIR,
+ mode='--astf' if osi_layer == 'L7' else ''))
+ try:
+ exec_cmd_no_error(self._node, cmd, sudo=True)
+ except RuntimeError:
+ cmd = "sh -c 'cat /tmp/trex.log'"
+ exec_cmd_no_error(self._node, cmd, sudo=True,
+ message='Get TRex logs failed!')
+ raise RuntimeError('Start TRex failed!')
+
+ # Test if TRex starts successfuly.
+ cmd = ("sh -c '{dir}/resources/tools/trex/trex_server_info.py'"
+ .format(dir=Constants.REMOTE_FW_DIR))
+ try:
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True, message='Test TRex failed!',
+ retries=20)
+ except RuntimeError:
+ continue
+ return
+ # After max retries TRex is still not responding to API critical error
+ # occurred.
+ raise RuntimeError('Start TRex failed after multiple retries!')