public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/3] YNL CLI --list-attrs argument
@ 2025-11-18 14:32 Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes Gal Pressman
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Gal Pressman @ 2025-11-18 14:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, netdev
  Cc: Donald Hunter, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev, bpf,
	Gal Pressman

While experimenting with the YNL CLI, I found the process of going back
and forth to examine the YAML spec files in order to figure out how to
use each command quite tiring.

The addition of --list-attrs helps by providing all information needed
directly in the tool. I figured others would likely find it useful as
well.

Changelog -
v1->v2: https://lore.kernel.org/all/20251116192845.1693119-1-gal@nvidia.com/
* Remove dead print in else case.
* Pass 'notify' explicitly in notify operation.
* Move nested functions out of main().
* Fix pylint issues.
* Add a print of the op documentation at the beginning.
* Specify enum vs. flags when displaying enum values.

Gal Pressman (3):
  tools: ynl: cli: Add --list-attrs option to show operation attributes
  tools: ynl: cli: Parse nested attributes in --list-attrs output
  tools: ynl: cli: Display enum values in --list-attrs output

 tools/net/ynl/pyynl/cli.py | 79 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes
  2025-11-18 14:32 [PATCH net-next v2 0/3] YNL CLI --list-attrs argument Gal Pressman
@ 2025-11-18 14:32 ` Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 2/3] tools: ynl: cli: Parse nested attributes in --list-attrs output Gal Pressman
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Gal Pressman @ 2025-11-18 14:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, netdev
  Cc: Donald Hunter, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev, bpf,
	Gal Pressman, Nimrod Oren

Add a --list-attrs option to the YNL CLI that displays information about
netlink operations, including request and reply attributes.
This eliminates the need to manually inspect YAML spec files to
determine the JSON structure required for operations, or understand the
structure of the reply.

Example usage:
  # ./cli.py --family netdev --list-attrs dev-get
  Operation: dev-get
  Get / dump information about a netdev.

  Do request attributes:
    - ifindex: u32
      netdev ifindex

  Do reply attributes:
    - ifindex: u32
      netdev ifindex
    - xdp-features: u64 (enum: xdp-act)
      Bitmask of enabled xdp-features.
    - xdp-zc-max-segs: u32
      max fragment count supported by ZC driver
    - xdp-rx-metadata-features: u64 (enum: xdp-rx-metadata)
      Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.
    - xsk-features: u64 (enum: xsk-flags)
      Bitmask of enabled AF_XDP features.

  Dump reply attributes:
    - ifindex: u32
      netdev ifindex
    - xdp-features: u64 (enum: xdp-act)
      Bitmask of enabled xdp-features.
    - xdp-zc-max-segs: u32
      max fragment count supported by ZC driver
    - xdp-rx-metadata-features: u64 (enum: xdp-rx-metadata)
      Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.
    - xsk-features: u64 (enum: xsk-flags)
      Bitmask of enabled AF_XDP features.

Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
---
 tools/net/ynl/pyynl/cli.py | 56 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 8c192e900bd3..4d91a2cee381 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -7,6 +7,7 @@ import os
 import pathlib
 import pprint
 import sys
+import textwrap
 
 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
 from lib import YnlFamily, Netlink, NlError
@@ -39,6 +40,37 @@ class YnlEncoder(json.JSONEncoder):
         return json.JSONEncoder.default(self, obj)
 
 
+def print_attr_list(attr_names, attr_set):
+    """Print a list of attributes with their types and documentation."""
+    for attr_name in attr_names:
+        if attr_name in attr_set.attrs:
+            attr = attr_set.attrs[attr_name]
+            attr_info = f'  - {attr_name}: {attr.type}'
+            if 'enum' in attr.yaml:
+                attr_info += f" (enum: {attr.yaml['enum']})"
+            if attr.yaml.get('doc'):
+                doc_text = textwrap.indent(attr.yaml['doc'], '    ')
+                attr_info += f"\n{doc_text}"
+            print(attr_info)
+
+
+def print_mode_attrs(mode, mode_spec, attr_set, print_request=True):
+    """Print a given mode (do/dump/event/notify)."""
+    mode_title = mode.capitalize()
+
+    if print_request and 'request' in mode_spec and 'attributes' in mode_spec['request']:
+        print(f'\n{mode_title} request attributes:')
+        print_attr_list(mode_spec['request']['attributes'], attr_set)
+
+    if 'reply' in mode_spec and 'attributes' in mode_spec['reply']:
+        print(f'\n{mode_title} reply attributes:')
+        print_attr_list(mode_spec['reply']['attributes'], attr_set)
+
+    if 'attributes' in mode_spec:
+        print(f'\n{mode_title} attributes:')
+        print_attr_list(mode_spec['attributes'], attr_set)
+
+
 def main():
     description = """
     YNL CLI utility - a general purpose netlink utility that uses YAML
@@ -70,6 +102,8 @@ def main():
     group.add_argument('--dump', dest='dump', metavar='DUMP-OPERATION', type=str)
     group.add_argument('--list-ops', action='store_true')
     group.add_argument('--list-msgs', action='store_true')
+    group.add_argument('--list-attrs', dest='list_attrs', metavar='OPERATION', type=str,
+                       help='List attributes for an operation')
 
     parser.add_argument('--duration', dest='duration', type=int,
                         help='when subscribed, watch for DURATION seconds')
@@ -135,6 +169,28 @@ def main():
         for op_name, op in ynl.msgs.items():
             print(op_name, " [", ", ".join(op.modes), "]")
 
+    if args.list_attrs:
+        op = ynl.msgs.get(args.list_attrs)
+        if not op:
+            print(f'Operation {args.list_attrs} not found')
+            exit(1)
+
+        print(f'Operation: {op.name}')
+        print(op.yaml['doc'])
+
+        for mode in ['do', 'dump', 'event']:
+            if mode in op.yaml:
+                print_mode_attrs(mode, op.yaml[mode], op.attr_set, True)
+
+        if 'notify' in op.yaml:
+            mode_spec = op.yaml['notify']
+            ref_spec = ynl.msgs.get(mode_spec).yaml.get('do')
+            if ref_spec:
+                print_mode_attrs('notify', ref_spec, op.attr_set, False)
+
+        if 'mcgrp' in op.yaml:
+            print(f"\nMulticast group: {op.yaml['mcgrp']}")
+
     try:
         if args.do:
             reply = ynl.do(args.do, attrs, args.flags)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 2/3] tools: ynl: cli: Parse nested attributes in --list-attrs output
  2025-11-18 14:32 [PATCH net-next v2 0/3] YNL CLI --list-attrs argument Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes Gal Pressman
@ 2025-11-18 14:32 ` Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 3/3] tools: ynl: cli: Display enum values " Gal Pressman
  2025-11-20 14:50 ` [PATCH net-next v2 0/3] YNL CLI --list-attrs argument patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Gal Pressman @ 2025-11-18 14:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, netdev
  Cc: Donald Hunter, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev, bpf,
	Gal Pressman, Nimrod Oren

Enhance the --list-attrs option to recursively display nested attributes
instead of just showing "nest" as the type.
Nested attributes now show their attribute set name and expand to
display their contents.

  # ./cli.py --family ethtool --list-attrs rss-get
  [..]
  Do request attributes:
    - header: nest -> header
        - dev-index: u32
        - dev-name: string
        - flags: u32 (enum: header-flags)
        - phy-index: u32
    - context: u32
  [..]

Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
---
 tools/net/ynl/pyynl/cli.py | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 4d91a2cee381..6655ee61081a 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -40,35 +40,52 @@ class YnlEncoder(json.JSONEncoder):
         return json.JSONEncoder.default(self, obj)
 
 
-def print_attr_list(attr_names, attr_set):
+def print_attr_list(ynl, attr_names, attr_set, indent=2):
     """Print a list of attributes with their types and documentation."""
+    prefix = ' ' * indent
     for attr_name in attr_names:
         if attr_name in attr_set.attrs:
             attr = attr_set.attrs[attr_name]
-            attr_info = f'  - {attr_name}: {attr.type}'
+            attr_info = f'{prefix}- {attr_name}: {attr.type}'
             if 'enum' in attr.yaml:
                 attr_info += f" (enum: {attr.yaml['enum']})"
+
+            # Show nested attributes reference and recursively display them
+            nested_set_name = None
+            if attr.type == 'nest' and 'nested-attributes' in attr.yaml:
+                nested_set_name = attr.yaml['nested-attributes']
+                attr_info += f" -> {nested_set_name}"
+
             if attr.yaml.get('doc'):
-                doc_text = textwrap.indent(attr.yaml['doc'], '    ')
+                doc_text = textwrap.indent(attr.yaml['doc'], prefix + '  ')
                 attr_info += f"\n{doc_text}"
             print(attr_info)
 
+            # Recursively show nested attributes
+            if nested_set_name in ynl.attr_sets:
+                nested_set = ynl.attr_sets[nested_set_name]
+                # Filter out 'unspec' and other unused attrs
+                nested_names = [n for n in nested_set.attrs.keys()
+                                if nested_set.attrs[n].type != 'unused']
+                if nested_names:
+                    print_attr_list(ynl, nested_names, nested_set, indent + 4)
 
-def print_mode_attrs(mode, mode_spec, attr_set, print_request=True):
+
+def print_mode_attrs(ynl, mode, mode_spec, attr_set, print_request=True):
     """Print a given mode (do/dump/event/notify)."""
     mode_title = mode.capitalize()
 
     if print_request and 'request' in mode_spec and 'attributes' in mode_spec['request']:
         print(f'\n{mode_title} request attributes:')
-        print_attr_list(mode_spec['request']['attributes'], attr_set)
+        print_attr_list(ynl, mode_spec['request']['attributes'], attr_set)
 
     if 'reply' in mode_spec and 'attributes' in mode_spec['reply']:
         print(f'\n{mode_title} reply attributes:')
-        print_attr_list(mode_spec['reply']['attributes'], attr_set)
+        print_attr_list(ynl, mode_spec['reply']['attributes'], attr_set)
 
     if 'attributes' in mode_spec:
         print(f'\n{mode_title} attributes:')
-        print_attr_list(mode_spec['attributes'], attr_set)
+        print_attr_list(ynl, mode_spec['attributes'], attr_set)
 
 
 def main():
@@ -180,13 +197,13 @@ def main():
 
         for mode in ['do', 'dump', 'event']:
             if mode in op.yaml:
-                print_mode_attrs(mode, op.yaml[mode], op.attr_set, True)
+                print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set, True)
 
         if 'notify' in op.yaml:
             mode_spec = op.yaml['notify']
             ref_spec = ynl.msgs.get(mode_spec).yaml.get('do')
             if ref_spec:
-                print_mode_attrs('notify', ref_spec, op.attr_set, False)
+                print_mode_attrs(ynl, 'notify', ref_spec, op.attr_set, False)
 
         if 'mcgrp' in op.yaml:
             print(f"\nMulticast group: {op.yaml['mcgrp']}")
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next v2 3/3] tools: ynl: cli: Display enum values in --list-attrs output
  2025-11-18 14:32 [PATCH net-next v2 0/3] YNL CLI --list-attrs argument Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes Gal Pressman
  2025-11-18 14:32 ` [PATCH net-next v2 2/3] tools: ynl: cli: Parse nested attributes in --list-attrs output Gal Pressman
@ 2025-11-18 14:32 ` Gal Pressman
  2025-11-20 14:50 ` [PATCH net-next v2 0/3] YNL CLI --list-attrs argument patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Gal Pressman @ 2025-11-18 14:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, netdev
  Cc: Donald Hunter, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev, bpf,
	Gal Pressman, Nimrod Oren

When listing attributes with --list-attrs, display the actual enum
values for attributes that reference an enum type.

  # ./cli.py --family netdev --list-attrs dev-get
  [..]
    - xdp-features: u64 (enum: xdp-act)
      Flags: basic, redirect, ndo-xmit, xsk-zerocopy, hw-offload, rx-sg, ndo-xmit-sg
      Bitmask of enabled xdp-features.
  [..]

Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
---
 tools/net/ynl/pyynl/cli.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 6655ee61081a..ff81ff083764 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -48,7 +48,13 @@ def print_attr_list(ynl, attr_names, attr_set, indent=2):
             attr = attr_set.attrs[attr_name]
             attr_info = f'{prefix}- {attr_name}: {attr.type}'
             if 'enum' in attr.yaml:
-                attr_info += f" (enum: {attr.yaml['enum']})"
+                enum_name = attr.yaml['enum']
+                attr_info += f" (enum: {enum_name})"
+                # Print enum values if available
+                if enum_name in ynl.consts:
+                    const = ynl.consts[enum_name]
+                    enum_values = list(const.entries.keys())
+                    attr_info += f"\n{prefix}  {const.type.capitalize()}: {', '.join(enum_values)}"
 
             # Show nested attributes reference and recursively display them
             nested_set_name = None
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next v2 0/3] YNL CLI --list-attrs argument
  2025-11-18 14:32 [PATCH net-next v2 0/3] YNL CLI --list-attrs argument Gal Pressman
                   ` (2 preceding siblings ...)
  2025-11-18 14:32 ` [PATCH net-next v2 3/3] tools: ynl: cli: Display enum values " Gal Pressman
@ 2025-11-20 14:50 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-11-20 14:50 UTC (permalink / raw)
  To: Gal Pressman
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, netdev,
	donald.hunter, horms, ast, daniel, hawk, john.fastabend, sdf, bpf

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Tue, 18 Nov 2025 16:32:05 +0200 you wrote:
> While experimenting with the YNL CLI, I found the process of going back
> and forth to examine the YAML spec files in order to figure out how to
> use each command quite tiring.
> 
> The addition of --list-attrs helps by providing all information needed
> directly in the tool. I figured others would likely find it useful as
> well.
> 
> [...]

Here is the summary with links:
  - [net-next,v2,1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes
    https://git.kernel.org/netdev/net-next/c/2a2d5a3392b6
  - [net-next,v2,2/3] tools: ynl: cli: Parse nested attributes in --list-attrs output
    https://git.kernel.org/netdev/net-next/c/bc1bc1b357cd
  - [net-next,v2,3/3] tools: ynl: cli: Display enum values in --list-attrs output
    https://git.kernel.org/netdev/net-next/c/6c10f1a1c08a

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-11-20 14:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-18 14:32 [PATCH net-next v2 0/3] YNL CLI --list-attrs argument Gal Pressman
2025-11-18 14:32 ` [PATCH net-next v2 1/3] tools: ynl: cli: Add --list-attrs option to show operation attributes Gal Pressman
2025-11-18 14:32 ` [PATCH net-next v2 2/3] tools: ynl: cli: Parse nested attributes in --list-attrs output Gal Pressman
2025-11-18 14:32 ` [PATCH net-next v2 3/3] tools: ynl: cli: Display enum values " Gal Pressman
2025-11-20 14:50 ` [PATCH net-next v2 0/3] YNL CLI --list-attrs argument patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox