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