From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2E8DF46A55; Wed, 25 Jun 2025 19:44:27 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D833040B90; Wed, 25 Jun 2025 19:44:26 +0200 (CEST) Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) by mails.dpdk.org (Postfix) with ESMTP id 4FC7A40B90 for ; Wed, 25 Jun 2025 19:44:25 +0200 (CEST) Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-3138b2f0249so76296a91.2 for ; Wed, 25 Jun 2025 10:44:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; t=1750873464; x=1751478264; darn=dpdk.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=tmtHbtNhmI1dgK3IObXvZx4+BL+bL9Ttva7YwdBYlW8=; b=fKpcGHvzPZX9Vz/IzylgdRSVmreFHJR3keYIa1mMQlvYpiN6y5WlmZLWTdUpGBUgYH znuhvYJ2Pl87HuGe1CxPQW5Q5I77+dNd2D2L8lRon+0u+tql2snG4rTjw722rKhQKHUd WM0iPRX8jWTEKf0CW5JZPW8wMbejVaTEUaFGk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750873464; x=1751478264; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=tmtHbtNhmI1dgK3IObXvZx4+BL+bL9Ttva7YwdBYlW8=; b=F+QQEqtf0rKNtmepgqOYySUDLD1ybS1MOT4h19Wf4KRV5Wbhpd6j/AECmsoIXc8r0R zfRy2RCKCsr98rXquX+qkO0Gld9POzNjTg2hQT6JCjp1ONQoXQYFm9uUrfa5G7lqWGnm Uo+EvaYbi029y4tT7yES8+3L7IN8l3GHI+L1ZbHDqO/SsGcfaaH6JdxuLz9z2yRQG7Aa sz6oiZggrchOq+tEEPh294noFbXQ7u2I+VYGSeU6RwJN3hqhLGQ2HsY6VAe0VZlT8/31 rH+pAqP5w0+F7FA4gcwmkBGh3EOlLH9SW+eqkAZx/Xe5GFGEACk4A1cJTIb2CLa9cePh x6OA== X-Forwarded-Encrypted: i=1; AJvYcCWtXkH0vwkaYdlAplzW0dVywg7QA0z6aynjtcpm1GVuyfHh3LWNiXgnajfjPaK2ulnMTXc=@dpdk.org X-Gm-Message-State: AOJu0YyOTTsto6fvuooUCA7KAf4EbbazNB8Nmy+BzvZemRRbSiEOOzmg seBxOEXPLlK7OwXf8/VqjV199CYF8GWfy4rYHPhlyC+hxXnYaKgU5X9YgfrGUp1gMV2yIycDu0y EKIm++7BHAjmxDl0vKiA9Rc5aZth/mDI7SqfAlV78oA== X-Gm-Gg: ASbGnctJQ0g8CysAiyCB38PHnyl37BtA/m+zV7VdmUT4Vyn2GFUOYTlTtcKzTAlcvEa 9el4FEZOVFlfoX0X6ykHk8nqIMuHrsiLe73lFgkqeEMlHaPjMD8t83U6hNbxfuwdWopNV4sSEhY vabB5QBF4j2UwvAAcr6wHjNsWXN6eo+43oqLZH14DBvZn6+wUkbXWlGcR00AdnLmjrxQGDFQuB2 XVVFCrSbkbE1y4= X-Google-Smtp-Source: AGHT+IGWzkWb7dWEKQ8VfZW7UwShzXK3NgvMfMexEsoU0c5IYWA+sTJsvHMsb5h8Svl9sPiPpqFBU6LzhlGwGE01f+4= X-Received: by 2002:a17:90b:2c87:b0:316:e77:e2cf with SMTP id 98e67ed59e1d1-31616040aeamr1079043a91.35.1750873463985; Wed, 25 Jun 2025 10:44:23 -0700 (PDT) MIME-Version: 1.0 References: <20250519181957.228084-1-dmarx@iol.unh.edu> <20250521192629.294265-1-dmarx@iol.unh.edu> <20250521192629.294265-3-dmarx@iol.unh.edu> In-Reply-To: <20250521192629.294265-3-dmarx@iol.unh.edu> From: Patrick Robb Date: Wed, 25 Jun 2025 13:38:58 -0400 X-Gm-Features: AX0GCFsmpwAOmqGwgAYGrX0ReINFEmOdO4KMRZuElH18LH8wgBUAhceR8uOyklY Message-ID: Subject: Re: [PATCH v2 3/3] dts: add flow validation To: Dean Marx Cc: luca.vizzarro@arm.com, yoan.picchi@foss.arm.com, Honnappa.Nagarahalli@arm.com, paul.szczepanek@arm.com, dev@dpdk.org Content-Type: multipart/alternative; boundary="000000000000de2d98063868fe4c" X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org --000000000000de2d98063868fe4c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, May 21, 2025 at 3:26=E2=80=AFPM Dean Marx wrote= : > Add a method for validating flow rules to the testpmd shell class. > Implement test case skipping for flow rules that do not pass > validation. > > Signed-off-by: Dean Marx > --- > dts/framework/remote_session/testpmd_shell.py | 15 ++++ > dts/framework/test_run.py | 3 + > dts/framework/test_suite.py | 21 ++++- > dts/tests/TestSuite_flow.py | 90 +++++++++++++------ > 4 files changed, 102 insertions(+), 27 deletions(-) > > diff --git a/dts/framework/remote_session/testpmd_shell.py > b/dts/framework/remote_session/testpmd_shell.py > index bd5f2659bd..c2c7ade60a 100644 > --- a/dts/framework/remote_session/testpmd_shell.py > +++ b/dts/framework/remote_session/testpmd_shell.py > @@ -1961,6 +1961,21 @@ def flow_create(self, flow_rule: FlowRule, port_id= : > int) -> int: > self._logger.debug(f"Failed to create flow > rule:\n{flow_output}") > raise InteractiveCommandExecutionError(f"Failed to create > flow rule:\n{flow_output}") > > + def flow_validate(self, flow_rule: FlowRule, port_id: int) -> bool: > + """Validates a flow rule in the testpmd session. > + > + Args: > + flow_rule: :class:`FlowRule` object used for validating > testpmd flow rule. > + port_id: Integer representing the port to use. > + > + Returns: > + Boolean representing whether rule is valid or not. > + """ > + flow_output =3D self.send_command(f"flow validate {port_id} > {flow_rule}") > + if "Flow rule validated" in flow_output: > + return True > + return False > + > def flow_delete(self, flow_id: int, port_id: int, verify: bool =3D > True) -> None: > """Deletes the specified flow rule from the testpmd session. > > diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py > index 0fdc57ea9c..cf4af19e8f 100644 > --- a/dts/framework/test_run.py > +++ b/dts/framework/test_run.py > @@ -644,6 +644,9 @@ def next(self) -> State | None: > return self > > self.result.update(Result.FAIL, e) > + except SkippedTestException as e: > + self.logger.info(f"Test case execution SKIPPED: {e}") > + self.result.update(Result.SKIP, e) > else: > self.result.update(Result.PASS) > self.logger.info(f"{self.description.capitalize()} PASSED.") > diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py > index e07c327b77..34e9eb54ea 100644 > --- a/dts/framework/test_suite.py > +++ b/dts/framework/test_suite.py > @@ -39,7 +39,7 @@ > PacketFilteringConfig, > ) > > -from .exception import ConfigurationError, InternalError, > TestCaseVerifyError > +from .exception import ConfigurationError, InternalError, > SkippedTestException, TestCaseVerifyError > from .logger import DTSLogger, get_dts_logger > from .utils import get_packet_summaries, to_pascal_case > > @@ -411,6 +411,25 @@ def _fail_test_case_verify(self, failure_description= : > str) -> None: > self._logger.debug(command_res.command) > raise TestCaseVerifyError(failure_description) > > + def verify_skip(self, condition: bool, skip_reason: str) -> None: > Maybe rename to "verify_else_skip" so it is more descriptive? Up to you. > > Reviewed-by: Patrick Robb --000000000000de2d98063868fe4c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


On Wed, May 21,= 2025 at 3:26=E2=80=AFPM Dean Marx <dmarx@iol.unh.edu> wrote:
Add a method for validating flow rules to the testpmd she= ll class.
Implement test case skipping for flow rules that do not pass
validation.

Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
=C2=A0dts/framework/remote_session/testpmd_shell.py | 15 ++++
=C2=A0dts/framework/test_run.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 3 +
=C2=A0dts/framework/test_suite.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0| 21 ++++-
=C2=A0dts/tests/TestSuite_flow.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0| 90 +++++++++++++------
=C2=A04 files changed, 102 insertions(+), 27 deletions(-)

diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/= remote_session/testpmd_shell.py
index bd5f2659bd..c2c7ade60a 100644
--- a/dts/framework/remote_session/testpmd_shell.py
+++ b/dts/framework/remote_session/testpmd_shell.py
@@ -1961,6 +1961,21 @@ def flow_create(self, flow_rule: FlowRule, port_id: = int) -> int:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(f"F= ailed to create flow rule:\n{flow_output}")
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise InteractiveCommandExe= cutionError(f"Failed to create flow rule:\n{flow_output}")

+=C2=A0 =C2=A0 def flow_validate(self, flow_rule: FlowRule, port_id: int) -= > bool:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 """Validates a flow rule in the= testpmd session.
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Args:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 flow_rule: :class:`FlowRule` obj= ect used for validating testpmd flow rule.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 port_id: Integer representing th= e port to use.
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Returns:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Boolean representing whether rul= e is valid or not.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 """
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 flow_output =3D self.send_command(f"flow = validate {port_id} {flow_rule}")
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if "Flow rule validated" in flow_out= put:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return True
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return False
+
=C2=A0 =C2=A0 =C2=A0def flow_delete(self, flow_id: int, port_id: int, verif= y: bool =3D True) -> None:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"""Deletes the specified f= low rule from the testpmd session.

diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 0fdc57ea9c..cf4af19e8f 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -644,6 +644,9 @@ def next(self) -> State | None:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.result.update(Result.F= AIL, e)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 except SkippedTestException as e:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self.logger.info(f"Test c= ase execution SKIPPED: {e}")
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self.result.update(Result.SKIP, = e)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.result.update(Result.P= ASS)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.logger.info(f"{= self.description.capitalize()} PASSED.")
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index e07c327b77..34e9eb54ea 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -39,7 +39,7 @@
=C2=A0 =C2=A0 =C2=A0PacketFilteringConfig,
=C2=A0)

-from .exception import ConfigurationError, InternalError, TestCaseVerifyEr= ror
+from .exception import ConfigurationError, InternalError, SkippedTestExcep= tion, TestCaseVerifyError
=C2=A0from .logger import DTSLogger, get_dts_logger
=C2=A0from .utils import get_packet_summaries, to_pascal_case

@@ -411,6 +411,25 @@ def _fail_test_case_verify(self, failure_description: = str) -> None:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(command_= res.command)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise TestCaseVerifyError(failure_descrip= tion)

+=C2=A0 =C2=A0 def verify_skip(self, condition: bool, skip_reason: str) -&g= t; None:

Maybe rename to "verify_e= lse_skip" so it is more descriptive? Up to you.
=C2=A0
=


Reviewed-by: Patrick Robb <probb@iol.unh.edu>=C2=A0
--000000000000de2d98063868fe4c--