The reason for the relocation of these methods is not entirely
clear given the commit message. It would be helpful to give a
brief explanation in the commit message.

 > +    def setup(self, topology: Topology) -> None:
> +        """Overrides :meth:`.traffic_generator.TrafficGenerator.setup`."""
> +        for port in self._tg_node.ports:
> +            self._tg_node.main_session.configure_port_mtu(2000, port)

Reiterating Luca's suggestion, it is cleaner to do:
  port.configure_mtu(2000)

@dataclass(slots=True)
+class PerformanceTrafficStats:
+    """Data structure to store performance statistics for a given test run.
+
+    Attributes:
+        tx_pps: Recorded tx packets per second
+        tx_bps: Recorded tx bytes per second
+        rx_pps: Recorded rx packets per second
+        rx_bps: Recorded rx bytes per second
+        frame_size: The total length of the frame
+    """
Small nit: missing full stops on attributes. 

Other than that, it looks good.

Reviewed-by: Andrew Bailey <abailey@iol.unh.edu>