* [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