1*cecfe0aaSJuraj Linkeš# SPDX-License-Identifier: BSD-3-Clause 2*cecfe0aaSJuraj Linkeš# Copyright(c) 2010-2014 Intel Corporation 3*cecfe0aaSJuraj Linkeš# Copyright(c) 2022 University of New Hampshire 4*cecfe0aaSJuraj Linkeš# Copyright(c) 2023 PANTHEON.tech s.r.o. 5*cecfe0aaSJuraj Linkeš 6*cecfe0aaSJuraj Linkeš"""Traffic generator node. 7*cecfe0aaSJuraj Linkeš 8*cecfe0aaSJuraj LinkešThis is the node where the traffic generator resides. 9*cecfe0aaSJuraj LinkešThe distinction between a node and a traffic generator is as follows: 10*cecfe0aaSJuraj LinkešA node is a host that DTS connects to. It could be a baremetal server, 11*cecfe0aaSJuraj Linkeša VM or a container. 12*cecfe0aaSJuraj LinkešA traffic generator is software running on the node. 13*cecfe0aaSJuraj LinkešA traffic generator node is a node running a traffic generator. 14*cecfe0aaSJuraj LinkešA node can be a traffic generator node as well as system under test node. 15*cecfe0aaSJuraj Linkeš""" 16*cecfe0aaSJuraj Linkeš 17*cecfe0aaSJuraj Linkešfrom scapy.packet import Packet # type: ignore[import] 18*cecfe0aaSJuraj Linkeš 19*cecfe0aaSJuraj Linkešfrom framework.config import ( 20*cecfe0aaSJuraj Linkeš ScapyTrafficGeneratorConfig, 21*cecfe0aaSJuraj Linkeš TGNodeConfiguration, 22*cecfe0aaSJuraj Linkeš TrafficGeneratorType, 23*cecfe0aaSJuraj Linkeš) 24*cecfe0aaSJuraj Linkešfrom framework.exception import ConfigurationError 25*cecfe0aaSJuraj Linkeš 26*cecfe0aaSJuraj Linkešfrom .capturing_traffic_generator import CapturingTrafficGenerator 27*cecfe0aaSJuraj Linkešfrom .hw.port import Port 28*cecfe0aaSJuraj Linkešfrom .node import Node 29*cecfe0aaSJuraj Linkeš 30*cecfe0aaSJuraj Linkeš 31*cecfe0aaSJuraj Linkešclass TGNode(Node): 32*cecfe0aaSJuraj Linkeš """Manage connections to a node with a traffic generator. 33*cecfe0aaSJuraj Linkeš 34*cecfe0aaSJuraj Linkeš Apart from basic node management capabilities, the Traffic Generator node has 35*cecfe0aaSJuraj Linkeš specialized methods for handling the traffic generator running on it. 36*cecfe0aaSJuraj Linkeš 37*cecfe0aaSJuraj Linkeš Arguments: 38*cecfe0aaSJuraj Linkeš node_config: The user configuration of the traffic generator node. 39*cecfe0aaSJuraj Linkeš 40*cecfe0aaSJuraj Linkeš Attributes: 41*cecfe0aaSJuraj Linkeš traffic_generator: The traffic generator running on the node. 42*cecfe0aaSJuraj Linkeš """ 43*cecfe0aaSJuraj Linkeš 44*cecfe0aaSJuraj Linkeš traffic_generator: CapturingTrafficGenerator 45*cecfe0aaSJuraj Linkeš 46*cecfe0aaSJuraj Linkeš def __init__(self, node_config: TGNodeConfiguration): 47*cecfe0aaSJuraj Linkeš super(TGNode, self).__init__(node_config) 48*cecfe0aaSJuraj Linkeš self.traffic_generator = create_traffic_generator( 49*cecfe0aaSJuraj Linkeš self, node_config.traffic_generator 50*cecfe0aaSJuraj Linkeš ) 51*cecfe0aaSJuraj Linkeš self._logger.info(f"Created node: {self.name}") 52*cecfe0aaSJuraj Linkeš 53*cecfe0aaSJuraj Linkeš def send_packet_and_capture( 54*cecfe0aaSJuraj Linkeš self, 55*cecfe0aaSJuraj Linkeš packet: Packet, 56*cecfe0aaSJuraj Linkeš send_port: Port, 57*cecfe0aaSJuraj Linkeš receive_port: Port, 58*cecfe0aaSJuraj Linkeš duration: float = 1, 59*cecfe0aaSJuraj Linkeš ) -> list[Packet]: 60*cecfe0aaSJuraj Linkeš """Send a packet, return received traffic. 61*cecfe0aaSJuraj Linkeš 62*cecfe0aaSJuraj Linkeš Send a packet on the send_port and then return all traffic captured 63*cecfe0aaSJuraj Linkeš on the receive_port for the given duration. Also record the captured traffic 64*cecfe0aaSJuraj Linkeš in a pcap file. 65*cecfe0aaSJuraj Linkeš 66*cecfe0aaSJuraj Linkeš Args: 67*cecfe0aaSJuraj Linkeš packet: The packet to send. 68*cecfe0aaSJuraj Linkeš send_port: The egress port on the TG node. 69*cecfe0aaSJuraj Linkeš receive_port: The ingress port in the TG node. 70*cecfe0aaSJuraj Linkeš duration: Capture traffic for this amount of time after sending the packet. 71*cecfe0aaSJuraj Linkeš 72*cecfe0aaSJuraj Linkeš Returns: 73*cecfe0aaSJuraj Linkeš A list of received packets. May be empty if no packets are captured. 74*cecfe0aaSJuraj Linkeš """ 75*cecfe0aaSJuraj Linkeš return self.traffic_generator.send_packet_and_capture( 76*cecfe0aaSJuraj Linkeš packet, send_port, receive_port, duration 77*cecfe0aaSJuraj Linkeš ) 78*cecfe0aaSJuraj Linkeš 79*cecfe0aaSJuraj Linkeš def close(self) -> None: 80*cecfe0aaSJuraj Linkeš """Free all resources used by the node""" 81*cecfe0aaSJuraj Linkeš self.traffic_generator.close() 82*cecfe0aaSJuraj Linkeš super(TGNode, self).close() 83*cecfe0aaSJuraj Linkeš 84*cecfe0aaSJuraj Linkeš 85*cecfe0aaSJuraj Linkešdef create_traffic_generator( 86*cecfe0aaSJuraj Linkeš tg_node: TGNode, traffic_generator_config: ScapyTrafficGeneratorConfig 87*cecfe0aaSJuraj Linkeš) -> CapturingTrafficGenerator: 88*cecfe0aaSJuraj Linkeš """A factory function for creating traffic generator object from user config.""" 89*cecfe0aaSJuraj Linkeš 90*cecfe0aaSJuraj Linkeš from .scapy import ScapyTrafficGenerator 91*cecfe0aaSJuraj Linkeš 92*cecfe0aaSJuraj Linkeš match traffic_generator_config.traffic_generator_type: 93*cecfe0aaSJuraj Linkeš case TrafficGeneratorType.SCAPY: 94*cecfe0aaSJuraj Linkeš return ScapyTrafficGenerator(tg_node, traffic_generator_config) 95*cecfe0aaSJuraj Linkeš case _: 96*cecfe0aaSJuraj Linkeš raise ConfigurationError( 97*cecfe0aaSJuraj Linkeš "Unknown traffic generator: " 98*cecfe0aaSJuraj Linkeš f"{traffic_generator_config.traffic_generator_type}" 99*cecfe0aaSJuraj Linkeš ) 100