Skip to content

Commit c986c33

Browse files
dmarxIOLPatrickRobbIOL
authored andcommitted
dts: add testpmd port queue modification
This patch adds methods for querying and modifying port queue state and configuration. In addition to this, it also adds the ability to capture the forwarding statistics that get outputted when you send the "stop" command in testpmd. Querying of port queue information is handled through a TextParser dataclass in case there is future need for using more of the output from the command used to query the information. Signed-off-by: Jeremy Spewock <[email protected]> Signed-off-by: Dean Marx <[email protected]>
1 parent e3ab9dd commit c986c33

File tree

1 file changed

+182
-34
lines changed

1 file changed

+182
-34
lines changed

dts/framework/remote_session/testpmd_shell.py

Lines changed: 182 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -426,50 +426,65 @@ def make_parser(cls) -> ParserFn:
426426

427427

428428
@dataclass
429-
class TestPmdRxqInfo(TextParser):
429+
class TestPmdQueueInfo(TextParser):
430+
"""Dataclass representation of the common parts of the testpmd `show rxq/txq info` commands."""
431+
432+
#:
433+
prefetch_threshold: int = field(metadata=TextParser.find_int(r"prefetch threshold: (\d+)"))
434+
#:
435+
host_threshold: int = field(metadata=TextParser.find_int(r"host threshold: (\d+)"))
436+
#:
437+
writeback_threshold: int = field(metadata=TextParser.find_int(r"writeback threshold: (\d+)"))
438+
#:
439+
free_threshold: int = field(metadata=TextParser.find_int(r"free threshold: (\d+)"))
440+
#:
441+
deferred_start: bool = field(metadata=TextParser.find("deferred start: on"))
442+
#: The number of RXD/TXDs is just the ring size of the queue.
443+
ring_size: int = field(metadata=TextParser.find_int(r"Number of (?:RXDs|TXDs): (\d+)"))
444+
#:
445+
is_queue_started: bool = field(metadata=TextParser.find("queue state: started"))
446+
#:
447+
burst_mode: str | None = field(
448+
default=None, metadata=TextParser.find(r"Burst mode: ([^\r\n]+)")
449+
)
450+
451+
452+
@dataclass
453+
class TestPmdTxqInfo(TestPmdQueueInfo):
454+
"""Representation of testpmd's ``show txq info <port_id> <queue_id>`` command.
455+
456+
References:
457+
testpmd command function: ``app/test-pmd/cmdline.c:cmd_showqueue()``
458+
testpmd display function: ``app/test-pmd/config.c:rx_queue_infos_display()``
459+
"""
460+
461+
#: Ring size threshold
462+
rs_threshold: int | None = field(
463+
default=None, metadata=TextParser.find_int(r"TX RS threshold: (\d+)\b")
464+
)
465+
466+
467+
@dataclass
468+
class TestPmdRxqInfo(TestPmdQueueInfo):
430469
"""Representation of testpmd's ``show rxq info <port_id> <queue_id>`` command.
431470
432471
References:
433472
testpmd command function: ``app/test-pmd/cmdline.c:cmd_showqueue()``
434473
testpmd display function: ``app/test-pmd/config.c:rx_queue_infos_display()``
435474
"""
436475

437-
#:
438-
port_id: int = field(metadata=TextParser.find_int(r"Infos for port (\d+)\b ?, RX queue \d+\b"))
439-
#:
440-
queue_id: int = field(metadata=TextParser.find_int(r"Infos for port \d+\b ?, RX queue (\d+)\b"))
441476
#: Mempool used by that queue
442-
mempool: str = field(metadata=TextParser.find(r"Mempool: ([^\r\n]+)"))
443-
#: Ring prefetch threshold
444-
rx_prefetch_threshold: int = field(
445-
metadata=TextParser.find_int(r"RX prefetch threshold: (\d+)\b")
446-
)
447-
#: Ring host threshold
448-
rx_host_threshold: int = field(metadata=TextParser.find_int(r"RX host threshold: (\d+)\b"))
449-
#: Ring writeback threshold
450-
rx_writeback_threshold: int = field(
451-
metadata=TextParser.find_int(r"RX writeback threshold: (\d+)\b")
452-
)
453-
#: Drives the freeing of Rx descriptors
454-
rx_free_threshold: int = field(metadata=TextParser.find_int(r"RX free threshold: (\d+)\b"))
477+
mempool: str | None = field(default=None, metadata=TextParser.find(r"Mempool: ([^\r\n]+)"))
455478
#: Drop packets if no descriptors are available
456-
rx_drop_packets: bool = field(metadata=TextParser.find(r"RX drop packets: on"))
457-
#: Do not start queue with rte_eth_dev_start()
458-
rx_deferred_start: bool = field(metadata=TextParser.find(r"RX deferred start: on"))
479+
drop_packets: bool | None = field(
480+
default=None, metadata=TextParser.find(r"RX drop packets: on")
481+
)
459482
#: Scattered packets Rx enabled
460-
rx_scattered_packets: bool = field(metadata=TextParser.find(r"RX scattered packets: on"))
461-
#: The state of the queue
462-
rx_queue_state: str = field(metadata=RxQueueState.make_parser())
463-
#: Configured number of RXDs
464-
number_of_rxds: int = field(metadata=TextParser.find_int(r"Number of RXDs: (\d+)\b"))
465-
#: Hardware receive buffer size
466-
rx_buffer_size: int | None = field(
467-
default=None, metadata=TextParser.find_int(r"RX buffer size: (\d+)\b")
468-
)
469-
#: Burst mode information
470-
burst_mode: str | None = field(
471-
default=None, metadata=TextParser.find(r"Burst mode: ([^\r\n]+)")
483+
scattered_packets: bool | None = field(
484+
default=None, metadata=TextParser.find(r"RX scattered packets: on")
472485
)
486+
#: The state of the queue
487+
queue_state: str | None = field(default=None, metadata=RxQueueState.make_parser())
473488

474489

475490
@dataclass
@@ -2036,6 +2051,139 @@ def get_capabilities_rx_offload(
20362051
rx_offload_capabilities.per_port | rx_offload_capabilities.per_queue,
20372052
)
20382053

2054+
def get_port_queue_info(
2055+
self, port_id: int, queue_id: int, is_rx_queue: bool
2056+
) -> TestPmdQueueInfo:
2057+
"""Returns the current state of the specified queue."""
2058+
command = f"show {'rxq' if is_rx_queue else 'txq'} info {port_id} {queue_id}"
2059+
queue_info = TestPmdQueueInfo.parse(self.send_command(command))
2060+
return queue_info
2061+
2062+
def setup_port_queue(self, port_id: int, queue_id: int, is_rx_queue: bool) -> None:
2063+
"""Setup a given queue on a port.
2064+
2065+
This functionality cannot be verified because the setup action only takes effect when the
2066+
queue is started.
2067+
2068+
Args:
2069+
port_id: ID of the port where the queue resides.
2070+
queue_id: ID of the queue to setup.
2071+
is_rx_queue: Type of queue to setup. If :data:`True` an RX queue will be setup,
2072+
otherwise a TX queue will be setup.
2073+
"""
2074+
self.send_command(f"port {port_id} {'rxq' if is_rx_queue else 'txq'} {queue_id} setup")
2075+
2076+
def stop_port_queue(
2077+
self, port_id: int, queue_id: int, is_rx_queue: bool, verify: bool = True
2078+
) -> None:
2079+
"""Stops a given queue on a port.
2080+
2081+
Args:
2082+
port_id: ID of the port that the queue belongs to.
2083+
queue_id: ID of the queue to stop.
2084+
is_rx_queue: Type of queue to stop. If :data:`True` an RX queue will be stopped,
2085+
otherwise a TX queue will be stopped.
2086+
verify: If :data:`True` an additional command will be sent to verify the queue stopped.
2087+
Defaults to :data:`True`.
2088+
2089+
Raises:
2090+
InteractiveCommandExecutionError: If `verify` is :data:`True` and the queue fails to
2091+
stop.
2092+
"""
2093+
port_type = "rxq" if is_rx_queue else "txq"
2094+
stop_cmd_output = self.send_command(f"port {port_id} {port_type} {queue_id} stop")
2095+
if verify:
2096+
queue_started = self.get_port_queue_info(
2097+
port_id, queue_id, is_rx_queue
2098+
).is_queue_started
2099+
if queue_started:
2100+
self._logger.debug(
2101+
f"Failed to stop {port_type} {queue_id} on port {port_id}:\n{stop_cmd_output}"
2102+
)
2103+
raise InteractiveCommandExecutionError(
2104+
f"Test pmd failed to stop {port_type} {queue_id} on port {port_id}"
2105+
)
2106+
2107+
def start_port_queue(
2108+
self, port_id: int, queue_id: int, is_rx_queue: bool, verify: bool = True
2109+
) -> None:
2110+
"""Starts a given queue on a port.
2111+
2112+
First sets up the port queue, then starts it.
2113+
2114+
Args:
2115+
port_id: ID of the port that the queue belongs to.
2116+
queue_id: ID of the queue to start.
2117+
is_rx_queue: Type of queue to start. If :data:`True` an RX queue will be started,
2118+
otherwise a TX queue will be started.
2119+
verify: if :data:`True` an additional command will be sent to verify that the queue was
2120+
started. Defaults to :data:`True`.
2121+
2122+
Raises:
2123+
InteractiveCommandExecutionError: If `verify` is :data:`True` and the queue fails to
2124+
start.
2125+
"""
2126+
port_type = "rxq" if is_rx_queue else "txq"
2127+
self.setup_port_queue(port_id, queue_id, is_rx_queue)
2128+
start_cmd_output = self.send_command(f"port {port_id} {port_type} {queue_id} start")
2129+
if verify:
2130+
queue_started = self.get_port_queue_info(
2131+
port_id, queue_id, is_rx_queue
2132+
).is_queue_started
2133+
if not queue_started:
2134+
self._logger.debug(
2135+
f"Failed to start {port_type} {queue_id} on port {port_id}:\n{start_cmd_output}"
2136+
)
2137+
raise InteractiveCommandExecutionError(
2138+
f"Test pmd failed to start {port_type} {queue_id} on port {port_id}"
2139+
)
2140+
2141+
def get_queue_ring_size(self, port_id: int, queue_id: int, is_rx_queue: bool) -> int:
2142+
"""Returns the current size of the ring on the specified queue."""
2143+
command = f"show {'rxq' if is_rx_queue else 'txq'} info {port_id} {queue_id}"
2144+
queue_info = TestPmdQueueInfo.parse(self.send_command(command))
2145+
return queue_info.ring_size
2146+
2147+
def set_queue_ring_size(
2148+
self,
2149+
port_id: int,
2150+
queue_id: int,
2151+
size: int,
2152+
is_rx_queue: bool,
2153+
verify: bool = True,
2154+
) -> None:
2155+
"""Update the ring size of an Rx/Tx queue on a given port.
2156+
2157+
Queue is setup after setting the ring size so that the queue info reflects this change and
2158+
it can be verified.
2159+
2160+
Args:
2161+
port_id: The port that the queue resides on.
2162+
queue_id: The ID of the queue on the port.
2163+
size: The size to update the ring size to.
2164+
is_rx_queue: Whether to modify an RX or TX queue. If :data:`True` an RX queue will be
2165+
updated, otherwise a TX queue will be updated.
2166+
verify: If :data:`True` an additional command will be sent to check the ring size of
2167+
the queue in an attempt to validate that the size was changes properly.
2168+
2169+
Raises:
2170+
InteractiveCommandExecutionError: If `verify` is :data:`True` and there is a failure
2171+
when updating ring size.
2172+
"""
2173+
queue_type = "rxq" if is_rx_queue else "txq"
2174+
self.send_command(f"port config {port_id} {queue_type} {queue_id} ring_size {size}")
2175+
self.setup_port_queue(port_id, queue_id, is_rx_queue)
2176+
if verify:
2177+
curr_ring_size = self.get_queue_ring_size(port_id, queue_id, is_rx_queue)
2178+
if curr_ring_size != size:
2179+
self._logger.debug(
2180+
f"Failed up update ring size of queue {queue_id} on port {port_id}. Current"
2181+
f" ring size is {curr_ring_size}."
2182+
)
2183+
raise InteractiveCommandExecutionError(
2184+
f"Failed to update ring size of queue {queue_id} on port {port_id}"
2185+
)
2186+
20392187
def _update_capabilities_from_flag(
20402188
self,
20412189
supported_capabilities: MutableSet["NicCapability"],
@@ -2065,7 +2213,7 @@ def get_capabilities_rxq_info(
20652213
self._logger.debug("Getting rxq capabilities.")
20662214
command = f"show rxq info {self.ports[0].id} 0"
20672215
rxq_info = TestPmdRxqInfo.parse(self.send_command(command))
2068-
if rxq_info.rx_scattered_packets:
2216+
if rxq_info.scattered_packets:
20692217
supported_capabilities.add(NicCapability.SCATTERED_RX_ENABLED)
20702218
else:
20712219
unsupported_capabilities.add(NicCapability.SCATTERED_RX_ENABLED)

0 commit comments

Comments
 (0)