public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc
@ 2026-01-10 23:31 Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs Jakub Kicinski
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

I had some time on the plane to LPC, so here are improvements
to the --help and --list-attrs handling of YNL CLI which seem
in order given growing use of YNL as a real CLI tool.

v2:
 - patch 2: remove unnecessary isatty() check
v1: https://lore.kernel.org/20260109211756.3342477-1-kuba@kernel.org

Jakub Kicinski (7):
  tools: ynl: cli: introduce formatting for attr names in --list-attrs
  tools: ynl: cli: wrap the doc text if it's long
  tools: ynl: cli: improve --help
  tools: ynl: cli: add --doc as alias to --list-attrs
  tools: ynl: cli: factor out --list-attrs / --doc handling
  tools: ynl: cli: extract the event/notify handling in --list-attrs
  tools: ynl: cli: print reply in combined format if possible

 tools/net/ynl/pyynl/cli.py | 207 ++++++++++++++++++++++++++-----------
 1 file changed, 144 insertions(+), 63 deletions(-)

-- 
2.52.0


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

* [PATCH net-next v2 1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 2/7] tools: ynl: cli: wrap the doc text if it's long Jakub Kicinski
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

It's a little hard to make sense of the output of --list-attrs,
it looks like a wall of text. Sprinkle a little bit of formatting -
make op and attr names bold, and Enum: / Flags: keywords italics.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 5fee45e48bbf..aa50d42e35ac 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -20,6 +20,29 @@ from lib import YnlFamily, Netlink, NlError, SpecFamily, SpecException, YnlExcep
 SYS_SCHEMA_DIR='/usr/share/ynl'
 RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
 
+# pylint: disable=too-few-public-methods,too-many-locals
+class Colors:
+    """ANSI color and font modifier codes"""
+    RESET = '\033[0m'
+
+    BOLD = '\033[1m'
+    ITALICS = '\033[3m'
+    UNDERLINE = '\033[4m'
+    INVERT = '\033[7m'
+
+
+def color(text, modifiers):
+    """Add color to text if output is a TTY
+
+    Returns:
+        Colored text if stdout is a TTY, otherwise plain text
+    """
+    if sys.stdout.isatty():
+        # Join the colors if they are a list, if it's a string this a noop
+        modifiers = "".join(modifiers)
+        return f"{modifiers}{text}{Colors.RESET}"
+    return text
+
 def schema_dir():
     """
     Return the effective schema directory, preferring in-tree before
@@ -60,7 +83,7 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
     for attr_name in attr_names:
         if attr_name in attr_set.attrs:
             attr = attr_set.attrs[attr_name]
-            attr_info = f'{prefix}- {attr_name}: {attr.type}'
+            attr_info = f'{prefix}- {color(attr_name, Colors.BOLD)}: {attr.type}'
             if 'enum' in attr.yaml:
                 enum_name = attr.yaml['enum']
                 attr_info += f" (enum: {enum_name})"
@@ -68,7 +91,8 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
                 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)}"
+                    type_fmted = color(const.type.capitalize(), Colors.ITALICS)
+                    attr_info += f"\n{prefix}  {type_fmted}: {', '.join(enum_values)}"
 
             # Show nested attributes reference and recursively display them
             nested_set_name = None
@@ -226,7 +250,7 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
             print(f'Operation {args.list_attrs} not found')
             sys.exit(1)
 
-        print(f'Operation: {op.name}')
+        print(f'Operation: {color(op.name, Colors.BOLD)}')
         print(op.yaml['doc'])
 
         for mode in ['do', 'dump', 'event']:
-- 
2.52.0


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

* [PATCH net-next v2 2/7] tools: ynl: cli: wrap the doc text if it's long
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 3/7] tools: ynl: cli: improve --help Jakub Kicinski
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

We already use textwrap when printing "doc" section about an attribute,
but only to indent the text. Switch to using fill() to split and indent
all the lines. While at it indent the text by 2 more spaces, so that it
doesn't align with the name of the attribute.

Before (I'm drawing a "box" at ~60 cols here, in an attempt for clarity):

 |  - irq-suspend-timeout: uint                              |
 |    The timeout, in nanoseconds, of how long to suspend irq|
 |processing, if event polling finds events                  |

After:

 |  - irq-suspend-timeout: uint                              |
 |      The timeout, in nanoseconds, of how long to suspend  |
 |      irq processing, if event polling finds events        |

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
 - remove the explicit sys.stdout.isatty() check
v1: https://lore.kernel.org/20260109211756.3342477-3-kuba@kernel.org
---
 tools/net/ynl/pyynl/cli.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index aa50d42e35ac..dc84619e5518 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -10,6 +10,7 @@ import json
 import os
 import pathlib
 import pprint
+import shutil
 import sys
 import textwrap
 
@@ -101,7 +102,11 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
                 attr_info += f" -> {nested_set_name}"
 
             if attr.yaml.get('doc'):
-                doc_text = textwrap.indent(attr.yaml['doc'], prefix + '  ')
+                doc_prefix = prefix + ' ' * 4
+                term_width = shutil.get_terminal_size().columns
+                doc_text = textwrap.fill(attr.yaml['doc'], width=term_width,
+                                         initial_indent=doc_prefix,
+                                         subsequent_indent=doc_prefix)
                 attr_info += f"\n{doc_text}"
             print(attr_info)
 
-- 
2.52.0


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

* [PATCH net-next v2 3/7] tools: ynl: cli: improve --help
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 2/7] tools: ynl: cli: wrap the doc text if it's long Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 4/7] tools: ynl: cli: add --doc as alias to --list-attrs Jakub Kicinski
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

Improve the clarity of --help. Reorder, provide some grouping and
add help messages to most of the options.

No functional changes intended.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 107 ++++++++++++++++++++++++-------------
 1 file changed, 69 insertions(+), 38 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index dc84619e5518..3aa1f1e816bf 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -151,47 +151,78 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
     """
 
     parser = argparse.ArgumentParser(description=description,
-                                     epilog=epilog)
-    spec_group = parser.add_mutually_exclusive_group(required=True)
-    spec_group.add_argument('--family', dest='family', type=str,
-                            help='name of the netlink FAMILY')
-    spec_group.add_argument('--list-families', action='store_true',
-                            help='list all netlink families supported by YNL (has spec)')
-    spec_group.add_argument('--spec', dest='spec', type=str,
-                            help='choose the family by SPEC file path')
+                                     epilog=epilog, add_help=False)
 
-    parser.add_argument('--schema', dest='schema', type=str)
-    parser.add_argument('--no-schema', action='store_true')
-    parser.add_argument('--json', dest='json_text', type=str)
+    gen_group = parser.add_argument_group('General options')
+    gen_group.add_argument('-h', '--help', action='help',
+                           help='show this help message and exit')
 
-    group = parser.add_mutually_exclusive_group()
-    group.add_argument('--do', dest='do', metavar='DO-OPERATION', type=str)
-    group.add_argument('--multi', dest='multi', nargs=2, action='append',
-                       metavar=('DO-OPERATION', 'JSON_TEXT'), type=str)
-    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')
-    group.add_argument('--validate', action='store_true')
+    spec_group = parser.add_argument_group('Netlink family selection')
+    spec_sel = spec_group.add_mutually_exclusive_group(required=True)
+    spec_sel.add_argument('--list-families', action='store_true',
+                          help=('list Netlink families supported by YNL '
+                                '(which have a spec available in the standard '
+                                'system path)'))
+    spec_sel.add_argument('--family', dest='family', type=str,
+                          help='name of the Netlink FAMILY to use')
+    spec_sel.add_argument('--spec', dest='spec', type=str,
+                          help='full file path to the YAML spec file')
+
+    ops_group = parser.add_argument_group('Operations')
+    ops = ops_group.add_mutually_exclusive_group()
+    ops.add_argument('--do', dest='do', metavar='DO-OPERATION', type=str)
+    ops.add_argument('--dump', dest='dump', metavar='DUMP-OPERATION', type=str)
+    ops.add_argument('--multi', dest='multi', nargs=2, action='append',
+                     metavar=('DO-OPERATION', 'JSON_TEXT'), type=str,
+                     help="Multi-message operation sequence (for nftables)")
+    ops.add_argument('--list-ops', action='store_true',
+                     help="List available --do and --dump operations")
+    ops.add_argument('--list-msgs', action='store_true',
+                     help="List all messages of the family (incl. notifications)")
+    ops.add_argument('--list-attrs', dest='list_attrs', metavar='MSG',
+                     type=str, help='List attributes for a message / operation')
+    ops.add_argument('--validate', action='store_true',
+                     help="Validate the spec against schema and exit")
+
+    io_group = parser.add_argument_group('Input / Output')
+    io_group.add_argument('--json', dest='json_text', type=str,
+                          help=('Specify attributes of the message to send '
+                                'to the kernel in JSON format. Can be left out '
+                                'if the message is expected to be empty.'))
+    io_group.add_argument('--output-json', action='store_true',
+                          help='Format output as JSON')
+
+    ntf_group = parser.add_argument_group('Notifications')
+    ntf_group.add_argument('--subscribe', dest='ntf', type=str)
+    ntf_group.add_argument('--duration', dest='duration', type=int,
+                           help='when subscribed, watch for DURATION seconds')
+    ntf_group.add_argument('--sleep', dest='duration', type=int,
+                           help='alias for duration')
+
+    nlflags = parser.add_argument_group('Netlink message flags (NLM_F_*)',
+                                        ('Extra flags to set in nlmsg_flags of '
+                                         'the request, used mostly by older '
+                                         'Classic Netlink families.'))
+    nlflags.add_argument('--replace', dest='flags', action='append_const',
+                         const=Netlink.NLM_F_REPLACE)
+    nlflags.add_argument('--excl', dest='flags', action='append_const',
+                         const=Netlink.NLM_F_EXCL)
+    nlflags.add_argument('--create', dest='flags', action='append_const',
+                         const=Netlink.NLM_F_CREATE)
+    nlflags.add_argument('--append', dest='flags', action='append_const',
+                         const=Netlink.NLM_F_APPEND)
+
+    schema_group = parser.add_argument_group('Development options')
+    schema_group.add_argument('--schema', dest='schema', type=str,
+                              help="JSON schema to validate the spec")
+    schema_group.add_argument('--no-schema', action='store_true')
+
+    dbg_group = parser.add_argument_group('Debug options')
+    dbg_group.add_argument('--dbg-small-recv', default=0, const=4000,
+                           action='store', nargs='?', type=int, metavar='INT',
+                           help="Length of buffers used for recv()")
+    dbg_group.add_argument('--process-unknown', action=argparse.BooleanOptionalAction)
 
-    parser.add_argument('--duration', dest='duration', type=int,
-                        help='when subscribed, watch for DURATION seconds')
-    parser.add_argument('--sleep', dest='duration', type=int,
-                        help='alias for duration')
-    parser.add_argument('--subscribe', dest='ntf', type=str)
-    parser.add_argument('--replace', dest='flags', action='append_const',
-                        const=Netlink.NLM_F_REPLACE)
-    parser.add_argument('--excl', dest='flags', action='append_const',
-                        const=Netlink.NLM_F_EXCL)
-    parser.add_argument('--create', dest='flags', action='append_const',
-                        const=Netlink.NLM_F_CREATE)
-    parser.add_argument('--append', dest='flags', action='append_const',
-                        const=Netlink.NLM_F_APPEND)
-    parser.add_argument('--process-unknown', action=argparse.BooleanOptionalAction)
-    parser.add_argument('--output-json', action='store_true')
-    parser.add_argument('--dbg-small-recv', default=0, const=4000,
-                        action='store', nargs='?', type=int)
     args = parser.parse_args()
 
     def output(msg):
-- 
2.52.0


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

* [PATCH net-next v2 4/7] tools: ynl: cli: add --doc as alias to --list-attrs
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (2 preceding siblings ...)
  2026-01-10 23:31 ` [PATCH net-next v2 3/7] tools: ynl: cli: improve --help Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 5/7] tools: ynl: cli: factor out --list-attrs / --doc handling Jakub Kicinski
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

--list-attrs also provides information about the operation itself.
So --doc seems more appropriate. Add an alias.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 3aa1f1e816bf..4147c498b479 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -179,7 +179,7 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
                      help="List available --do and --dump operations")
     ops.add_argument('--list-msgs', action='store_true',
                      help="List all messages of the family (incl. notifications)")
-    ops.add_argument('--list-attrs', dest='list_attrs', metavar='MSG',
+    ops.add_argument('--list-attrs', '--doc', dest='list_attrs', metavar='MSG',
                      type=str, help='List attributes for a message / operation')
     ops.add_argument('--validate', action='store_true',
                      help="Validate the spec against schema and exit")
-- 
2.52.0


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

* [PATCH net-next v2 5/7] tools: ynl: cli: factor out --list-attrs / --doc handling
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (3 preceding siblings ...)
  2026-01-10 23:31 ` [PATCH net-next v2 4/7] tools: ynl: cli: add --doc as alias to --list-attrs Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 6/7] tools: ynl: cli: extract the event/notify handling in --list-attrs Jakub Kicinski
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

We'll soon add more code to the --doc handling. Factor it out
to avoid making main() too long.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 4147c498b479..6975efa7874f 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -137,6 +137,25 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
         print_attr_list(ynl, mode_spec['attributes'], attr_set)
 
 
+def do_doc(ynl, op):
+    """Handle --list-attrs $op, print the attr information to stdout"""
+    print(f'Operation: {color(op.name, Colors.BOLD)}')
+    print(op.yaml['doc'])
+
+    for mode in ['do', 'dump', 'event']:
+        if mode in op.yaml:
+            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(ynl, 'notify', ref_spec, op.attr_set, False)
+
+    if 'mcgrp' in op.yaml:
+        print(f"\nMulticast group: {op.yaml['mcgrp']}")
+
+
 # pylint: disable=too-many-locals,too-many-branches,too-many-statements
 def main():
     """YNL cli tool"""
@@ -286,21 +305,7 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
             print(f'Operation {args.list_attrs} not found')
             sys.exit(1)
 
-        print(f'Operation: {color(op.name, Colors.BOLD)}')
-        print(op.yaml['doc'])
-
-        for mode in ['do', 'dump', 'event']:
-            if mode in op.yaml:
-                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(ynl, 'notify', ref_spec, op.attr_set, False)
-
-        if 'mcgrp' in op.yaml:
-            print(f"\nMulticast group: {op.yaml['mcgrp']}")
+        do_doc(ynl, op)
 
     try:
         if args.do:
-- 
2.52.0


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

* [PATCH net-next v2 6/7] tools: ynl: cli: extract the event/notify handling in --list-attrs
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (4 preceding siblings ...)
  2026-01-10 23:31 ` [PATCH net-next v2 5/7] tools: ynl: cli: factor out --list-attrs / --doc handling Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-10 23:31 ` [PATCH net-next v2 7/7] tools: ynl: cli: print reply in combined format if possible Jakub Kicinski
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

Event and notify handling is quite different from do / dump
handling. Forcing it into print_mode_attrs() doesn't really
buy us anything as events and notifications do not have requests.
Call print_attr_list() directly. Apart form subjective code
clarity this also removes the word "reply" from the output:

Before:

  Event reply attributes:

Now:

  Event attributes:

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 6975efa7874f..6d2f0412dde0 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -120,11 +120,11 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
                     print_attr_list(ynl, nested_names, nested_set, indent + 4)
 
 
-def print_mode_attrs(ynl, mode, mode_spec, attr_set, print_request=True):
+def print_mode_attrs(ynl, mode, mode_spec, attr_set):
     """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']:
+    if 'request' in mode_spec and 'attributes' in mode_spec['request']:
         print(f'\n{mode_title} request attributes:')
         print_attr_list(ynl, mode_spec['request']['attributes'], attr_set)
 
@@ -132,25 +132,28 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
         print(f'\n{mode_title} reply attributes:')
         print_attr_list(ynl, mode_spec['reply']['attributes'], attr_set)
 
-    if 'attributes' in mode_spec:
-        print(f'\n{mode_title} attributes:')
-        print_attr_list(ynl, mode_spec['attributes'], attr_set)
-
 
 def do_doc(ynl, op):
     """Handle --list-attrs $op, print the attr information to stdout"""
     print(f'Operation: {color(op.name, Colors.BOLD)}')
     print(op.yaml['doc'])
 
-    for mode in ['do', 'dump', 'event']:
+    for mode in ['do', 'dump']:
         if mode in op.yaml:
-            print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set, True)
+            print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set)
+
+    if 'attributes' in op.yaml.get('event', {}):
+        print('\nEvent attributes:')
+        print_attr_list(ynl, op.yaml['event']['attributes'], op.attr_set)
 
     if 'notify' in op.yaml:
         mode_spec = op.yaml['notify']
         ref_spec = ynl.msgs.get(mode_spec).yaml.get('do')
+        if not ref_spec:
+            ref_spec = ynl.msgs.get(mode_spec).yaml.get('dump')
         if ref_spec:
-            print_mode_attrs(ynl, 'notify', ref_spec, op.attr_set, False)
+            print('\nNotification attributes:')
+            print_attr_list(ynl, ref_spec['reply']['attributes'], op.attr_set)
 
     if 'mcgrp' in op.yaml:
         print(f"\nMulticast group: {op.yaml['mcgrp']}")
-- 
2.52.0


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

* [PATCH net-next v2 7/7] tools: ynl: cli: print reply in combined format if possible
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (5 preceding siblings ...)
  2026-01-10 23:31 ` [PATCH net-next v2 6/7] tools: ynl: cli: extract the event/notify handling in --list-attrs Jakub Kicinski
@ 2026-01-10 23:31 ` Jakub Kicinski
  2026-01-11  7:56 ` [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Gal Pressman
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2026-01-10 23:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal, Jakub Kicinski

As pointed out during review of the --list-attrs support the GET
ops very often return the same attrs from do and dump. Make the
output more readable by combining the reply information, from:

  Do request attributes:
    - ifindex: u32
      netdev ifindex

  Do reply attributes:
    - ifindex: u32
      netdev ifindex
    [ .. other attrs .. ]

  Dump reply attributes:
    - ifindex: u32
      netdev ifindex
    [ .. other attrs .. ]

To, after:

  Do request attributes:
    - ifindex: u32
      netdev ifindex

  Do and Dump reply attributes:
    - ifindex: u32
      netdev ifindex
    [ .. other attrs .. ]

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 tools/net/ynl/pyynl/cli.py | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 6d2f0412dde0..fdac1ab10a40 100755
--- a/tools/net/ynl/pyynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
@@ -120,7 +120,7 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
                     print_attr_list(ynl, nested_names, nested_set, indent + 4)
 
 
-def print_mode_attrs(ynl, mode, mode_spec, attr_set):
+def print_mode_attrs(ynl, mode, mode_spec, attr_set, consistent_dd_reply=None):
     """Print a given mode (do/dump/event/notify)."""
     mode_title = mode.capitalize()
 
@@ -129,8 +129,15 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
         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(ynl, mode_spec['reply']['attributes'], attr_set)
+        if consistent_dd_reply and mode == "do":
+            title = None  # Dump handling will print in combined format
+        elif consistent_dd_reply and mode == "dump":
+            title = 'Do and Dump'
+        else:
+            title = f'{mode_title}'
+        if title:
+            print(f'\n{title} reply attributes:')
+            print_attr_list(ynl, mode_spec['reply']['attributes'], attr_set)
 
 
 def do_doc(ynl, op):
@@ -138,9 +145,15 @@ RELATIVE_SCHEMA_DIR='../../../../Documentation/netlink'
     print(f'Operation: {color(op.name, Colors.BOLD)}')
     print(op.yaml['doc'])
 
+    consistent_dd_reply = False
+    if 'do' in op.yaml and 'dump' in op.yaml and 'reply' in op.yaml['do'] and \
+       op.yaml['do']['reply'] == op.yaml['dump'].get('reply'):
+        consistent_dd_reply = True
+
     for mode in ['do', 'dump']:
         if mode in op.yaml:
-            print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set)
+            print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set,
+                             consistent_dd_reply=consistent_dd_reply)
 
     if 'attributes' in op.yaml.get('event', {}):
         print('\nEvent attributes:')
-- 
2.52.0


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

* Re: [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (6 preceding siblings ...)
  2026-01-10 23:31 ` [PATCH net-next v2 7/7] tools: ynl: cli: print reply in combined format if possible Jakub Kicinski
@ 2026-01-11  7:56 ` Gal Pressman
  2026-01-11 20:19 ` Stanislav Fomichev
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Gal Pressman @ 2026-01-11  7:56 UTC (permalink / raw)
  To: Jakub Kicinski, davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter

On 11/01/2026 1:31, Jakub Kicinski wrote:
> I had some time on the plane to LPC, so here are improvements
> to the --help and --list-attrs handling of YNL CLI which seem
> in order given growing use of YNL as a real CLI tool.
> 
> v2:
>  - patch 2: remove unnecessary isatty() check
> v1: https://lore.kernel.org/20260109211756.3342477-1-kuba@kernel.org
> 
> Jakub Kicinski (7):
>   tools: ynl: cli: introduce formatting for attr names in --list-attrs
>   tools: ynl: cli: wrap the doc text if it's long
>   tools: ynl: cli: improve --help
>   tools: ynl: cli: add --doc as alias to --list-attrs
>   tools: ynl: cli: factor out --list-attrs / --doc handling
>   tools: ynl: cli: extract the event/notify handling in --list-attrs
>   tools: ynl: cli: print reply in combined format if possible
> 
>  tools/net/ynl/pyynl/cli.py | 207 ++++++++++++++++++++++++++-----------
>  1 file changed, 144 insertions(+), 63 deletions(-)
> 

Neat, productive flight!
Tested-by: Gal Pressman <gal@nvidia.com>

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

* Re: [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (7 preceding siblings ...)
  2026-01-11  7:56 ` [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Gal Pressman
@ 2026-01-11 20:19 ` Stanislav Fomichev
  2026-01-12  2:05 ` Donald Hunter
  2026-01-13  2:27 ` patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: Stanislav Fomichev @ 2026-01-11 20:19 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal

On 01/10, Jakub Kicinski wrote:
> I had some time on the plane to LPC, so here are improvements
> to the --help and --list-attrs handling of YNL CLI which seem
> in order given growing use of YNL as a real CLI tool.
> 
> v2:
>  - patch 2: remove unnecessary isatty() check
> v1: https://lore.kernel.org/20260109211756.3342477-1-kuba@kernel.org

Acked-by: Stanislav Fomichev <sdf@fomichev.me>

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

* Re: [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (8 preceding siblings ...)
  2026-01-11 20:19 ` Stanislav Fomichev
@ 2026-01-12  2:05 ` Donald Hunter
  2026-01-13  2:27 ` patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: Donald Hunter @ 2026-01-12  2:05 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, sdf, gal

Jakub Kicinski <kuba@kernel.org> writes:

> I had some time on the plane to LPC, so here are improvements
> to the --help and --list-attrs handling of YNL CLI which seem
> in order given growing use of YNL as a real CLI tool.
>
> v2:
>  - patch 2: remove unnecessary isatty() check
> v1: https://lore.kernel.org/20260109211756.3342477-1-kuba@kernel.org
>
> Jakub Kicinski (7):
>   tools: ynl: cli: introduce formatting for attr names in --list-attrs
>   tools: ynl: cli: wrap the doc text if it's long
>   tools: ynl: cli: improve --help
>   tools: ynl: cli: add --doc as alias to --list-attrs
>   tools: ynl: cli: factor out --list-attrs / --doc handling
>   tools: ynl: cli: extract the event/notify handling in --list-attrs
>   tools: ynl: cli: print reply in combined format if possible
>
>  tools/net/ynl/pyynl/cli.py | 207 ++++++++++++++++++++++++++-----------
>  1 file changed, 144 insertions(+), 63 deletions(-)

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>

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

* Re: [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc
  2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
                   ` (9 preceding siblings ...)
  2026-01-12  2:05 ` Donald Hunter
@ 2026-01-13  2:27 ` patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-01-13  2:27 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, sdf,
	donald.hunter, gal

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Sat, 10 Jan 2026 15:31:35 -0800 you wrote:
> I had some time on the plane to LPC, so here are improvements
> to the --help and --list-attrs handling of YNL CLI which seem
> in order given growing use of YNL as a real CLI tool.
> 
> v2:
>  - patch 2: remove unnecessary isatty() check
> v1: https://lore.kernel.org/20260109211756.3342477-1-kuba@kernel.org
> 
> [...]

Here is the summary with links:
  - [net-next,v2,1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs
    https://git.kernel.org/netdev/net-next/c/21eb90fb5fbc
  - [net-next,v2,2/7] tools: ynl: cli: wrap the doc text if it's long
    https://git.kernel.org/netdev/net-next/c/101a7d57d518
  - [net-next,v2,3/7] tools: ynl: cli: improve --help
    https://git.kernel.org/netdev/net-next/c/1b7fbf62ad8b
  - [net-next,v2,4/7] tools: ynl: cli: add --doc as alias to --list-attrs
    https://git.kernel.org/netdev/net-next/c/aca1fe235c10
  - [net-next,v2,5/7] tools: ynl: cli: factor out --list-attrs / --doc handling
    https://git.kernel.org/netdev/net-next/c/45b99bb464eb
  - [net-next,v2,6/7] tools: ynl: cli: extract the event/notify handling in --list-attrs
    https://git.kernel.org/netdev/net-next/c/6ccc421b1461
  - [net-next,v2,7/7] tools: ynl: cli: print reply in combined format if possible
    https://git.kernel.org/netdev/net-next/c/60411adedf70

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] 12+ messages in thread

end of thread, other threads:[~2026-01-13  2:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-10 23:31 [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 1/7] tools: ynl: cli: introduce formatting for attr names in --list-attrs Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 2/7] tools: ynl: cli: wrap the doc text if it's long Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 3/7] tools: ynl: cli: improve --help Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 4/7] tools: ynl: cli: add --doc as alias to --list-attrs Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 5/7] tools: ynl: cli: factor out --list-attrs / --doc handling Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 6/7] tools: ynl: cli: extract the event/notify handling in --list-attrs Jakub Kicinski
2026-01-10 23:31 ` [PATCH net-next v2 7/7] tools: ynl: cli: print reply in combined format if possible Jakub Kicinski
2026-01-11  7:56 ` [PATCH net-next v2 0/7] tools: ynl: cli: improve the help and doc Gal Pressman
2026-01-11 20:19 ` Stanislav Fomichev
2026-01-12  2:05 ` Donald Hunter
2026-01-13  2:27 ` 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