On Tue, Nov 21, 2023 at 5:20 PM Yoan Picchi <yoan.pic...@foss.arm.com> wrote:
>
> On 11/15/23 13:09, Juraj Linkeš wrote:
> > Format according to the Google format and PEP257, with slight
> > deviations.
> >
> > Signed-off-by: Juraj Linkeš <juraj.lin...@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.
>
> The sentence feels odd. Isn't it supposed to be "or" here? and no need
> for that early of a line break
>

There are two mays, so there probably should be an or. But I'd like to
reword it to this:

All traffic generators count the number of received packets, and they
may additionally
capture individual packets.

What do you think?

> > +
> > +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.
>
> This sentence feels odd too. Maybe "It must be able to handle receiving
> no packets."
>

Right, your suggestion is better.

> >           """
> >
> >       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.
>
> full -> fully
>
> >           """
> >
> >       @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
>

Reply via email to