diff mbox series

[net-next] tools: ynl: introduce option to ignore unknown attributes or types

Message ID 20231012140438.306857-1-jiri@resnulli.us (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net-next] tools: ynl: introduce option to ignore unknown attributes or types | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
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/cc_maintainers warning 1 maintainers not CCed: donald.hunter@gmail.com
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 success Errors and warnings before: 9 this patch: 9
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 43 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jiri Pirko Oct. 12, 2023, 2:04 p.m. UTC
From: Jiri Pirko <jiri@nvidia.com>

In case the kernel sends message back containing attribute not defined
in family spec, following exception is raised to the user:

$ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}'
Traceback (most recent call last):
  File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 521, in _decode
    attr_spec = attr_space.attrs_by_val[attr.type]
                ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 132

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/jiri/work/linux/./tools/net/ynl/cli.py", line 61, in <module>
    main()
  File "/home/jiri/work/linux/./tools/net/ynl/cli.py", line 49, in main
    reply = ynl.do(args.do, attrs, args.flags)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 731, in do
    return self._op(method, vals, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 719, in _op
    rsp_msg = self._decode(decoded.raw_attrs, op.attr_set.name)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jiri/work/linux/tools/net/ynl/lib/ynl.py", line 525, in _decode
    raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
Exception: Space 'devlink' has no attribute with value '132'

Introduce a command line option "ignore-unknown" and pass it down to
YnlFamily class constructor to allow user to get at least the part
of the message containing known attributes.

$ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}' --ignore-unknown
{'bus-name': 'netdevsim',
 'dev-name': 'netdevsim1',
 'trap-action': 'drop',
 'trap-group-name': 'l2_drops',
 'trap-name': 'source_mac_is_multicast'}

Do the same for unknown attribute types.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 tools/net/ynl/cli.py     | 3 ++-
 tools/net/ynl/lib/ynl.py | 7 ++++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

Comments

Jakub Kicinski Oct. 12, 2023, 2:32 p.m. UTC | #1
On Thu, 12 Oct 2023 16:04:38 +0200 Jiri Pirko wrote:
> $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}' --ignore-unknown
> {'bus-name': 'netdevsim',
>  'dev-name': 'netdevsim1',
>  'trap-action': 'drop',
>  'trap-group-name': 'l2_drops',
>  'trap-name': 'source_mac_is_multicast'}

Wouldn't it be better to put the unknown attr in as raw binary?
We can key it by attribute type (integer) and put the NlAttr object
in as the value.

That way at least the user still sees that the unknown attrs are
present.
Jiri Pirko Oct. 13, 2023, 7:49 a.m. UTC | #2
Thu, Oct 12, 2023 at 04:32:23PM CEST, kuba@kernel.org wrote:
>On Thu, 12 Oct 2023 16:04:38 +0200 Jiri Pirko wrote:
>> $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do trap-get --json '{"bus-name": "netdevsim", "dev-name": "netdevsim1", "trap-name": "source_mac_is_multicast"}' --ignore-unknown
>> {'bus-name': 'netdevsim',
>>  'dev-name': 'netdevsim1',
>>  'trap-action': 'drop',
>>  'trap-group-name': 'l2_drops',
>>  'trap-name': 'source_mac_is_multicast'}
>
>Wouldn't it be better to put the unknown attr in as raw binary?
>We can key it by attribute type (integer) and put the NlAttr object
>in as the value.
>
>That way at least the user still sees that the unknown attrs are
>present.

Okay, will check that out.
diff mbox series

Patch

diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/cli.py
index 564ecf07cd2c..36fa0b2a8944 100755
--- a/tools/net/ynl/cli.py
+++ b/tools/net/ynl/cli.py
@@ -27,6 +27,7 @@  def main():
                         const=Netlink.NLM_F_CREATE)
     parser.add_argument('--append', dest='flags', action='append_const',
                         const=Netlink.NLM_F_APPEND)
+    parser.add_argument('--ignore-unknown', action=argparse.BooleanOptionalAction)
     args = parser.parse_args()
 
     if args.no_schema:
@@ -36,7 +37,7 @@  def main():
     if args.json_text:
         attrs = json.loads(args.json_text)
 
-    ynl = YnlFamily(args.spec, args.schema)
+    ynl = YnlFamily(args.spec, args.schema, args.ignore_unknown)
 
     if args.ntf:
         ynl.ntf_subscribe(args.ntf)
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index 13c4b019a881..fdec6e4f8061 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -404,10 +404,11 @@  class GenlProtocol(NetlinkProtocol):
 
 
 class YnlFamily(SpecFamily):
-    def __init__(self, def_path, schema=None):
+    def __init__(self, def_path, schema=None, ignore_unknown=False):
         super().__init__(def_path, schema)
 
         self.include_raw = False
+        self.ignore_unknown = ignore_unknown
 
         try:
             if self.proto == "netlink-raw":
@@ -519,6 +520,8 @@  class YnlFamily(SpecFamily):
             try:
                 attr_spec = attr_space.attrs_by_val[attr.type]
             except KeyError:
+                if self.ignore_unknown:
+                    continue
                 raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
             if attr_spec["type"] == 'nest':
                 subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'])
@@ -534,6 +537,8 @@  class YnlFamily(SpecFamily):
             elif attr_spec["type"] == 'array-nest':
                 decoded = self._decode_array_nest(attr, attr_spec)
             else:
+                if self.ignore_unknown:
+                    continue
                 raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
 
             if 'enum' in attr_spec: