From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id CCBCD43339;
	Wed, 15 Nov 2023 14:14:17 +0100 (CET)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id CB57C411F3;
	Wed, 15 Nov 2023 14:12:21 +0100 (CET)
Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com
 [209.85.208.52]) by mails.dpdk.org (Postfix) with ESMTP id 7D22440EA5
 for <dev@dpdk.org>; Wed, 15 Nov 2023 14:12:16 +0100 (CET)
Received: by mail-ed1-f52.google.com with SMTP id
 4fb4d7f45d1cf-5440f25dcc7so10378769a12.0
 for <dev@dpdk.org>; Wed, 15 Nov 2023 05:12:16 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=pantheon.tech; s=google; t=1700053936; x=1700658736; darn=dpdk.org;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:from:to:cc:subject:date
 :message-id:reply-to;
 bh=g4hWHvKq7wmrNScwYf5rL6W0ga2jchBf0GSHuvS0F2E=;
 b=WkTtAltTirdoM0ZbbsiBeNL6BqP16fPAbdqn5HVlHuujGKJpiWMjGbArAtSes4KpgP
 LH0557D5yRUvGiyRHxGdFA7EA/NRCy2Fi3ahvylFOe3DKRFmj2seBbj34Aeal2e0+PnQ
 mq5cFxs/cpo2UtmcbTH4A/WoguLpwWk3HoykULwsB4uASMtnTVHAQaiIftEnjlpIQ8Xm
 jWct8X9sGHBtgcCegDPedClC9CKcSpRlHU/uitlgqPJ+zxqK0/1WCqp+CZfZb4SI22q+
 q9oeOZ8BlMe8f90nPN4+woAoD+wIL5ULw0BVwbFVD2fpt3BprEDRt/cI0NWrRMZHonoK
 KL0w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1700053936; x=1700658736;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=g4hWHvKq7wmrNScwYf5rL6W0ga2jchBf0GSHuvS0F2E=;
 b=j3+1X4wmKYhvMSZ3GS0LlX73sJudYrCnYWy1n9Ki1b5iAWee4eHmzTEvzThCpae1xo
 y1imLp3Dc9pQKIDOREjrEfWpVgy4GRSUyYIkXTCY3zVpWOmKGPZWRQ3lw3DGdM0KR0Q1
 OpprS6FhK06cBVDbwjtKGCg+RI4aMePdtZDZLmFoLR65UmxOHp/r5Xw1fKbl3vOhj3Wc
 1mskgialBPOVNEErrpVNRPBLIbUoqxbX62cul3TqxniMp2pWks/ME0/bHmtFGJYIsfkk
 AO+DZhAV5sH7k4iJhDZ44c06caHkbYPPwVZNRFhVgu5UUoKii4M6JVi/GFw+N5bO4dgp
 q1fA==
X-Gm-Message-State: AOJu0YzLH3xXIkEoq8m3XuxI4I1eW8bv50J3svu1uYVJackubo9YsMuN
 INAmRqoS/xpuSnXnsoqp73PauQ==
X-Google-Smtp-Source: AGHT+IElm3XiBhazL1q4Dynjie7fm8BEbAahRMQ0J9nCSo7nhOoL/ALTqB9Y0zUsOHGsMUoS6tteXQ==
X-Received: by 2002:a17:906:ad4:b0:9e0:4910:1649 with SMTP id
 z20-20020a1709060ad400b009e049101649mr9126882ejf.8.1700053936159; 
 Wed, 15 Nov 2023 05:12:16 -0800 (PST)
Received: from jlinkes-PT-Latitude-5530.pantheon.local
 (81.89.53.154.host.vnet.sk. [81.89.53.154])
 by smtp.gmail.com with ESMTPSA id
 tb16-20020a1709078b9000b009f2b7282387sm1011914ejc.46.2023.11.15.05.12.15
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Wed, 15 Nov 2023 05:12:15 -0800 (PST)
From: =?UTF-8?q?Juraj=20Linke=C5=A1?= <juraj.linkes@pantheon.tech>
To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, jspewock@iol.unh.edu,
 probb@iol.unh.edu, paul.szczepanek@arm.com, yoan.picchi@foss.arm.com
Cc: dev@dpdk.org, =?UTF-8?q?Juraj=20Linke=C5=A1?= <juraj.linkes@pantheon.tech>
Subject: [PATCH v7 19/21] dts: base traffic generators docstring update
Date: Wed, 15 Nov 2023 14:09:57 +0100
Message-Id: <20231115130959.39420-20-juraj.linkes@pantheon.tech>
X-Mailer: git-send-email 2.34.1
In-Reply-To: <20231115130959.39420-1-juraj.linkes@pantheon.tech>
References: <20231108125324.191005-23-juraj.linkes@pantheon.tech>
 <20231115130959.39420-1-juraj.linkes@pantheon.tech>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Format according to the Google format and PEP257, with slight
deviations.

Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>
---
 .../traffic_generator/__init__.py             | 22 ++++++++-
 .../capturing_traffic_generator.py            | 46 +++++++++++--------
 .../traffic_generator/traffic_generator.py    | 33 +++++++------
 3 files changed, 68 insertions(+), 33 deletions(-)

diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index 11bfa1ee0f..51cca77da4 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -1,6 +1,19 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2023 PANTHEON.tech s.r.o.
 
+"""DTS traffic generators.
+
+A traffic generator is capable of generating traffic and then monitor returning traffic.
+A traffic generator may just count the number of received packets
+and it may additionally capture individual packets.
+
+A traffic generator may be software running on generic hardware or it could be specialized hardware.
+
+The traffic generators that only count the number of received packets are suitable only for
+performance testing. In functional testing, we need to be able to dissect each arrived packet
+and a capturing traffic generator is required.
+"""
+
 from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType
 from framework.exception import ConfigurationError
 from framework.testbed_model.node import Node
@@ -12,8 +25,15 @@
 def create_traffic_generator(
     tg_node: Node, traffic_generator_config: ScapyTrafficGeneratorConfig
 ) -> CapturingTrafficGenerator:
-    """A factory function for creating traffic generator object from user config."""
+    """The factory function for creating traffic generator objects from the test run configuration.
+
+    Args:
+        tg_node: The traffic generator node where the created traffic generator will be running.
+        traffic_generator_config: The traffic generator config.
 
+    Returns:
+        A traffic generator capable of capturing received packets.
+    """
     match traffic_generator_config.traffic_generator_type:
         case TrafficGeneratorType.SCAPY:
             return ScapyTrafficGenerator(tg_node, traffic_generator_config)
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index e521211ef0..b0a43ad003 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -23,19 +23,22 @@
 
 
 def _get_default_capture_name() -> str:
-    """
-    This is the function used for the default implementation of capture names.
-    """
     return str(uuid.uuid4())
 
 
 class CapturingTrafficGenerator(TrafficGenerator):
     """Capture packets after sending traffic.
 
-    A mixin interface which enables a packet generator to declare that it can capture
+    The intermediary interface which enables a packet generator to declare that it can capture
     packets and return them to the user.
 
+    Similarly to
+    :class:`~framework.testbed_model.traffic_generator.traffic_generator.TrafficGenerator`,
+    this class exposes the public methods specific to capturing traffic generators and defines
+    a private method that must implement the traffic generation and capturing logic in subclasses.
+
     The methods of capturing traffic generators obey the following workflow:
+
         1. send packets
         2. capture packets
         3. write the capture to a .pcap file
@@ -44,6 +47,7 @@ class CapturingTrafficGenerator(TrafficGenerator):
 
     @property
     def is_capturing(self) -> bool:
+        """This traffic generator can capture traffic."""
         return True
 
     def send_packet_and_capture(
@@ -54,11 +58,12 @@ def send_packet_and_capture(
         duration: float,
         capture_name: str = _get_default_capture_name(),
     ) -> list[Packet]:
-        """Send a packet, return received traffic.
+        """Send `packet` and capture received traffic.
+
+        Send `packet` on `send_port` and then return all traffic captured
+        on `receive_port` for the given `duration`.
 
-        Send a packet on the send_port and then return all traffic captured
-        on the receive_port for the given duration. Also record the captured traffic
-        in a pcap file.
+        The captured traffic is recorded in the `capture_name`.pcap file.
 
         Args:
             packet: The packet to send.
@@ -68,7 +73,7 @@ def send_packet_and_capture(
             capture_name: The name of the .pcap file where to store the capture.
 
         Returns:
-             A list of received packets. May be empty if no packets are captured.
+             The received packets. May be empty if no packets are captured.
         """
         return self.send_packets_and_capture(
             [packet], send_port, receive_port, duration, capture_name
@@ -82,11 +87,14 @@ def send_packets_and_capture(
         duration: float,
         capture_name: str = _get_default_capture_name(),
     ) -> list[Packet]:
-        """Send packets, return received traffic.
+        """Send `packets` and capture received traffic.
 
-        Send packets on the send_port and then return all traffic captured
-        on the receive_port for the given duration. Also record the captured traffic
-        in a pcap file.
+        Send `packets` on `send_port` and then return all traffic captured
+        on `receive_port` for the given `duration`.
+
+        The captured traffic is recorded in the `capture_name`.pcap file. The target directory
+        can be configured with the :option:`--output-dir` command line argument or
+        the :envvar:`DTS_OUTPUT_DIR` environment variable.
 
         Args:
             packets: The packets to send.
@@ -96,7 +104,7 @@ def send_packets_and_capture(
             capture_name: The name of the .pcap file where to store the capture.
 
         Returns:
-             A list of received packets. May be empty if no packets are captured.
+             The received packets. May be empty if no packets are captured.
         """
         self._logger.debug(get_packet_summaries(packets))
         self._logger.debug(
@@ -124,10 +132,12 @@ def _send_packets_and_capture(
         receive_port: Port,
         duration: float,
     ) -> list[Packet]:
-        """
-        The extended classes must implement this method which
-        sends packets on send_port and receives packets on the receive_port
-        for the specified duration. It must be able to handle no received packets.
+        """The implementation of :method:`send_packets_and_capture`.
+
+        The subclasses must implement this method which sends `packets` on `send_port`
+        and receives packets on `receive_port` for the specified `duration`.
+
+        It must be able to handle no received packets.
         """
 
     def _write_capture_from_packets(
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
index ea7c3963da..ed396c6a2f 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
@@ -22,7 +22,8 @@
 class TrafficGenerator(ABC):
     """The base traffic generator.
 
-    Defines the few basic methods that each traffic generator must implement.
+    Exposes the common public methods of all traffic generators and defines private methods
+    that must implement the traffic generation logic in subclasses.
     """
 
     _config: TrafficGeneratorConfig
@@ -30,6 +31,12 @@ class TrafficGenerator(ABC):
     _logger: DTSLOG
 
     def __init__(self, tg_node: Node, config: TrafficGeneratorConfig):
+        """Initialize the traffic generator.
+
+        Args:
+            tg_node: The traffic generator node where the created traffic generator will be running.
+            config: The traffic generator's test run configuration.
+        """
         self._config = config
         self._tg_node = tg_node
         self._logger = getLogger(
@@ -37,9 +44,9 @@ def __init__(self, tg_node: Node, config: TrafficGeneratorConfig):
         )
 
     def send_packet(self, packet: Packet, port: Port) -> None:
-        """Send a packet and block until it is fully sent.
+        """Send `packet` and block until it is fully sent.
 
-        What fully sent means is defined by the traffic generator.
+        Send `packet` on `port`, then wait until `packet` is fully sent.
 
         Args:
             packet: The packet to send.
@@ -48,9 +55,9 @@ def send_packet(self, packet: Packet, port: Port) -> None:
         self.send_packets([packet], port)
 
     def send_packets(self, packets: list[Packet], port: Port) -> None:
-        """Send packets and block until they are fully sent.
+        """Send `packets` and block until they are fully sent.
 
-        What fully sent means is defined by the traffic generator.
+        Send `packets` on `port`, then wait until `packets` are fully sent.
 
         Args:
             packets: The packets to send.
@@ -62,19 +69,17 @@ def send_packets(self, packets: list[Packet], port: Port) -> None:
 
     @abstractmethod
     def _send_packets(self, packets: list[Packet], port: Port) -> None:
-        """
-        The extended classes must implement this method which
-        sends packets on send_port. The method should block until all packets
-        are fully sent.
+        """The implementation of :method:`send_packets`.
+
+        The subclasses must implement this method which sends `packets` on `port`.
+        The method should block until all `packets` are fully sent.
+
+        What full sent means is defined by the traffic generator.
         """
 
     @property
     def is_capturing(self) -> bool:
-        """Whether this traffic generator can capture traffic.
-
-        Returns:
-            True if the traffic generator can capture traffic, False otherwise.
-        """
+        """This traffic generator can't capture traffic."""
         return False
 
     @abstractmethod
-- 
2.34.1