xref: /dpdk/dts/framework/testbed_model/tg_node.py (revision da7e701151ea8b742d4c38ace3e4fefd1b4507fc)
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(
49            self, node_config.traffic_generator
50        )
51        self._logger.info(f"Created node: {self.name}")
52
53    def send_packet_and_capture(
54        self,
55        packet: Packet,
56        send_port: Port,
57        receive_port: Port,
58        duration: float = 1,
59    ) -> list[Packet]:
60        """Send a packet, return received traffic.
61
62        Send a packet on the send_port and then return all traffic captured
63        on the receive_port for the given duration. Also record the captured traffic
64        in a pcap file.
65
66        Args:
67            packet: The packet to send.
68            send_port: The egress port on the TG node.
69            receive_port: The ingress port in the TG node.
70            duration: Capture traffic for this amount of time after sending the packet.
71
72        Returns:
73             A list of received packets. May be empty if no packets are captured.
74        """
75        return self.traffic_generator.send_packet_and_capture(
76            packet, send_port, receive_port, duration
77        )
78
79    def close(self) -> None:
80        """Free all resources used by the node"""
81        self.traffic_generator.close()
82        super(TGNode, self).close()
83
84
85def create_traffic_generator(
86    tg_node: TGNode, traffic_generator_config: ScapyTrafficGeneratorConfig
87) -> CapturingTrafficGenerator:
88    """A factory function for creating traffic generator object from user config."""
89
90    from .scapy import ScapyTrafficGenerator
91
92    match traffic_generator_config.traffic_generator_type:
93        case TrafficGeneratorType.SCAPY:
94            return ScapyTrafficGenerator(tg_node, traffic_generator_config)
95        case _:
96            raise ConfigurationError(
97                "Unknown traffic generator: "
98                f"{traffic_generator_config.traffic_generator_type}"
99            )
100