diff mbox series

[net-next,v2,09/12] selftests: ncdevmem: Remove hard-coded queue numbers

Message ID 20240930171753.2572922-10-sdf@fomichev.me (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series selftests: ncdevmem: Add ncdevmem to ksft | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 2 maintainers not CCed: shuah@kernel.org linux-kselftest@vger.kernel.org
netdev/build_clang success Errors and warnings before: 9 this patch: 9
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 12 this patch: 12
netdev/checkpatch warning WARNING: line length of 96 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Stanislav Fomichev Sept. 30, 2024, 5:17 p.m. UTC
Use single last queue of the device and probe it dynamically.

Cc: Mina Almasry <almasrymina@google.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 tools/testing/selftests/net/ncdevmem.c | 40 ++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

Comments

Mina Almasry Oct. 3, 2024, 7:14 a.m. UTC | #1
On Mon, Sep 30, 2024 at 10:18 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> Use single last queue of the device and probe it dynamically.
>

Sorry I know there was a pending discussion in the last iteration that
I didn't respond to. Been a rough week with me out sick a bit.

For this, the issue I see is that by default only 1 queue binding will
be tested, but I feel like test coverage for the multiple queues case
by default is very nice because I actually ran into some issues making
multi-queue binding work.

Can we change this so that, by default, it binds to the last rxq_num/2
queues of the device?

> Cc: Mina Almasry <almasrymina@google.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  tools/testing/selftests/net/ncdevmem.c | 40 ++++++++++++++++++++++++--
>  1 file changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/net/ncdevmem.c b/tools/testing/selftests/net/ncdevmem.c
> index a1fa818c8229..900a661a61af 100644
> --- a/tools/testing/selftests/net/ncdevmem.c
> +++ b/tools/testing/selftests/net/ncdevmem.c
> @@ -48,8 +48,8 @@ static char *server_ip;
>  static char *client_ip;
>  static char *port;
>  static size_t do_validation;
> -static int start_queue = 8;
> -static int num_queues = 8;
> +static int start_queue = -1;
> +static int num_queues = 1;
>  static char *ifname;
>  static unsigned int ifindex;
>  static unsigned int dmabuf_id;
> @@ -198,6 +198,33 @@ void validate_buffer(void *line, size_t size)
>         fprintf(stdout, "Validated buffer\n");
>  }
>
> +static int rxq_num(int ifindex)
> +{
> +       struct ethtool_channels_get_req *req;
> +       struct ethtool_channels_get_rsp *rsp;
> +       struct ynl_error yerr;
> +       struct ynl_sock *ys;
> +       int num = -1;
> +
> +       ys = ynl_sock_create(&ynl_ethtool_family, &yerr);
> +       if (!ys) {
> +               fprintf(stderr, "YNL: %s\n", yerr.msg);
> +               return -1;
> +       }
> +
> +       req = ethtool_channels_get_req_alloc();
> +       ethtool_channels_get_req_set_header_dev_index(req, ifindex);
> +       rsp = ethtool_channels_get(ys, req);
> +       if (rsp)
> +               num = rsp->rx_count + rsp->combined_count;
> +       ethtool_channels_get_req_free(req);
> +       ethtool_channels_get_rsp_free(rsp);
> +
> +       ynl_sock_destroy(ys);
> +
> +       return num;
> +}
> +
>  #define run_command(cmd, ...)                                           \
>         ({                                                              \
>                 char command[256];                                      \
> @@ -672,6 +699,15 @@ int main(int argc, char *argv[])
>
>         ifindex = if_nametoindex(ifname);
>
> +       if (start_queue < 0) {
> +               start_queue = rxq_num(ifindex) - 1;

I think the only changes needed are:

start_queue = rxq_num(ifindex) / 2;
num_queues = rxq_num(ifindex) - start_queue;

(I may have an off-by-1 error somewhere with this math).
Stanislav Fomichev Oct. 3, 2024, 5:02 p.m. UTC | #2
On 10/03, Mina Almasry wrote:
> On Mon, Sep 30, 2024 at 10:18 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> >
> > Use single last queue of the device and probe it dynamically.
> >
> 
> Sorry I know there was a pending discussion in the last iteration that
> I didn't respond to. Been a rough week with me out sick a bit.
> 
> For this, the issue I see is that by default only 1 queue binding will
> be tested, but I feel like test coverage for the multiple queues case
> by default is very nice because I actually ran into some issues making
> multi-queue binding work.
> 
> Can we change this so that, by default, it binds to the last rxq_num/2
> queues of the device?

I'm probably missing something, but why do you think exercising this from
the probe/selftest mode is not enough? It might be confusing for the readers
to understand why we bind to half of the queues and flow steer into them
when in reality there is only single tcp flow.

IOW, can we keep these two modes:
1. server / client - use single queue
2. selftest / probe - use more than 1 queue by default (and I'll remove the
   checks that enforce the number of queues for this mode to let the
   users override)
Mina Almasry Oct. 3, 2024, 7:07 p.m. UTC | #3
On Thu, Oct 3, 2024 at 10:02 AM Stanislav Fomichev <stfomichev@gmail.com> wrote:
>
> On 10/03, Mina Almasry wrote:
> > On Mon, Sep 30, 2024 at 10:18 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> > >
> > > Use single last queue of the device and probe it dynamically.
> > >
> >
> > Sorry I know there was a pending discussion in the last iteration that
> > I didn't respond to. Been a rough week with me out sick a bit.
> >
> > For this, the issue I see is that by default only 1 queue binding will
> > be tested, but I feel like test coverage for the multiple queues case
> > by default is very nice because I actually ran into some issues making
> > multi-queue binding work.
> >
> > Can we change this so that, by default, it binds to the last rxq_num/2
> > queues of the device?
>
> I'm probably missing something, but why do you think exercising this from
> the probe/selftest mode is not enough? It might be confusing for the readers
> to understand why we bind to half of the queues and flow steer into them
> when in reality there is only single tcp flow.
>
> IOW, can we keep these two modes:
> 1. server / client - use single queue
> 2. selftest / probe - use more than 1 queue by default (and I'll remove the
>    checks that enforce the number of queues for this mode to let the
>    users override)

Ah, I see. Thanks for the explanation.

My paranoia here is that we don't notice multi-queue binding
regressions because the tests are often run in data path mode and we
don't use or notice failures in the probe mode.

I will concede my paranoia is just that and this is not very likely to
happen, but also if it is confusing to bind multi-queues and then just
use one, then we could remedy that with a comment and keep the
accidental test coverage. It also makes the test simpler to always
bind the same # of queues rather than special case data and control
path tests.

But your 2 mode approach sounds fine as well. But to implement that
you need more than to remove the checks that enforce the number of
queues, right? In probe mode num_queues should be rxq_num/2, and in
server mode num_queues should be 1, yes?
Stanislav Fomichev Oct. 3, 2024, 10:16 p.m. UTC | #4
On 10/03, Mina Almasry wrote:
> On Thu, Oct 3, 2024 at 10:02 AM Stanislav Fomichev <stfomichev@gmail.com> wrote:
> >
> > On 10/03, Mina Almasry wrote:
> > > On Mon, Sep 30, 2024 at 10:18 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> > > >
> > > > Use single last queue of the device and probe it dynamically.
> > > >
> > >
> > > Sorry I know there was a pending discussion in the last iteration that
> > > I didn't respond to. Been a rough week with me out sick a bit.
> > >
> > > For this, the issue I see is that by default only 1 queue binding will
> > > be tested, but I feel like test coverage for the multiple queues case
> > > by default is very nice because I actually ran into some issues making
> > > multi-queue binding work.
> > >
> > > Can we change this so that, by default, it binds to the last rxq_num/2
> > > queues of the device?
> >
> > I'm probably missing something, but why do you think exercising this from
> > the probe/selftest mode is not enough? It might be confusing for the readers
> > to understand why we bind to half of the queues and flow steer into them
> > when in reality there is only single tcp flow.
> >
> > IOW, can we keep these two modes:
> > 1. server / client - use single queue
> > 2. selftest / probe - use more than 1 queue by default (and I'll remove the
> >    checks that enforce the number of queues for this mode to let the
> >    users override)
> 
> Ah, I see. Thanks for the explanation.
> 
> My paranoia here is that we don't notice multi-queue binding
> regressions because the tests are often run in data path mode and we
> don't use or notice failures in the probe mode.
> 
> I will concede my paranoia is just that and this is not very likely to
> happen, but also if it is confusing to bind multi-queues and then just
> use one, then we could remedy that with a comment and keep the
> accidental test coverage. It also makes the test simpler to always
> bind the same # of queues rather than special case data and control
> path tests.
> 
> But your 2 mode approach sounds fine as well. But to implement that
> you need more than to remove the checks that enforce the number of
> queues, right? In probe mode num_queues should be rxq_num/2, and in
> server mode num_queues should be 1, yes?

Yes, I'll follow your suggestion with `start_queues = num_queues / 2`
for the selftest part.

Tentatively (default to 1/2 queues, if want to override - provide both
-t an -q):

index 90aacfb3433f..3a456c058241 100644
--- a/tools/testing/selftests/net/ncdevmem.c
+++ b/tools/testing/selftests/net/ncdevmem.c
@@ -64,7 +64,7 @@ static char *client_ip;
 static char *port;
 static size_t do_validation;
 static int start_queue = -1;
-static int num_queues = 1;
+static int num_queues = -1;
 static char *ifname;
 static unsigned int ifindex;
 static unsigned int dmabuf_id;
@@ -706,19 +706,31 @@ int main(int argc, char *argv[])
                }
        }

-       if (!server_ip)
-               error(1, 0, "Missing -s argument\n");
-
-       if (!port)
-               error(1, 0, "Missing -p argument\n");
-
        if (!ifname)
                error(1, 0, "Missing -f argument\n");

        ifindex = if_nametoindex(ifname);

-       if (start_queue < 0) {
-               start_queue = rxq_num(ifindex) - 1;
+       if (!server_ip && !client_ip) {
+               if (start_queue < 0 && num_queues < 0) {
+                       num_queues = rxq_num(ifindex);
+                       if (num_queues < 0)
+                               error(1, 0, "couldn't detect number of queues\n");
+                       /* make sure can bind to multiple queues */
+                       start_queues = num_queues / 2;
+                       num_queues /= 2;
+               }
+
+               if (start_queue < 0 || num_queues < 0)
+                       error(1, 0, "Both -t and -q are requred\n");
+
+               run_devmem_tests();
+               return 0;
+       }
+
+       if (start_queue < 0 && num_queues < 0) {
+               num_queues = 1;
+               start_queue = rxq_num(ifindex) - num_queues;
diff mbox series

Patch

diff --git a/tools/testing/selftests/net/ncdevmem.c b/tools/testing/selftests/net/ncdevmem.c
index a1fa818c8229..900a661a61af 100644
--- a/tools/testing/selftests/net/ncdevmem.c
+++ b/tools/testing/selftests/net/ncdevmem.c
@@ -48,8 +48,8 @@  static char *server_ip;
 static char *client_ip;
 static char *port;
 static size_t do_validation;
-static int start_queue = 8;
-static int num_queues = 8;
+static int start_queue = -1;
+static int num_queues = 1;
 static char *ifname;
 static unsigned int ifindex;
 static unsigned int dmabuf_id;
@@ -198,6 +198,33 @@  void validate_buffer(void *line, size_t size)
 	fprintf(stdout, "Validated buffer\n");
 }
 
+static int rxq_num(int ifindex)
+{
+	struct ethtool_channels_get_req *req;
+	struct ethtool_channels_get_rsp *rsp;
+	struct ynl_error yerr;
+	struct ynl_sock *ys;
+	int num = -1;
+
+	ys = ynl_sock_create(&ynl_ethtool_family, &yerr);
+	if (!ys) {
+		fprintf(stderr, "YNL: %s\n", yerr.msg);
+		return -1;
+	}
+
+	req = ethtool_channels_get_req_alloc();
+	ethtool_channels_get_req_set_header_dev_index(req, ifindex);
+	rsp = ethtool_channels_get(ys, req);
+	if (rsp)
+		num = rsp->rx_count + rsp->combined_count;
+	ethtool_channels_get_req_free(req);
+	ethtool_channels_get_rsp_free(rsp);
+
+	ynl_sock_destroy(ys);
+
+	return num;
+}
+
 #define run_command(cmd, ...)                                           \
 	({                                                              \
 		char command[256];                                      \
@@ -672,6 +699,15 @@  int main(int argc, char *argv[])
 
 	ifindex = if_nametoindex(ifname);
 
+	if (start_queue < 0) {
+		start_queue = rxq_num(ifindex) - 1;
+
+		if (start_queue < 0)
+			error(1, 0, "couldn't detect number of queues\n");
+
+		fprintf(stderr, "using queues %d..%d\n", start_queue, start_queue + num_queues);
+	}
+
 	for (; optind < argc; optind++)
 		fprintf(stderr, "extra arguments: %s\n", argv[optind]);