summaryrefslogtreecommitdiff
path: root/tools/net/ynl
diff options
context:
space:
mode:
authorJiri Pirko <jiri@nvidia.com>2024-02-22 16:43:51 +0300
committerJakub Kicinski <kuba@kernel.org>2024-02-24 05:16:44 +0300
commite8a6c515ff5f52e1ee24397116a05cd4fc1bae99 (patch)
treea57efa065dd9a76276dc4778746327aba5f9b93b /tools/net/ynl
parentffe10a4546feaae085a269f6e99680b9eda7d5a6 (diff)
downloadlinux-e8a6c515ff5f52e1ee24397116a05cd4fc1bae99.tar.xz
tools: ynl: allow user to pass enum string instead of scalar value
During decoding of messages coming from kernel, attribute values are converted to enum names in case the attribute type is enum of bitfield32. However, when user constructs json message, he has to pass plain scalar values. See "state" "selector" and "value" attributes in following examples: $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/dpll.yaml --do pin-set --json '{"id": 0, "parent-device": {"parent-id": 0, "state": 1}}' $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do port-set --json '{"bus-name": "pci", "dev-name": "0000:08:00.1", "port-index": 98304, "port-function": {"caps": {"selector": 1, "value": 1 }}}' Allow user to pass strings containing enum names, convert them to scalar values to be encoded into Netlink message: $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/dpll.yaml --do pin-set --json '{"id": 0, "parent-device": {"parent-id": 0, "state": "connected"}}' $ sudo ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml --do port-set --json '{"bus-name": "pci", "dev-name": "0000:08:00.1", "port-index": 98304, "port-function": {"caps": {"selector": ["roce-bit"], "value": ["roce-bit"] }}}' Signed-off-by: Jiri Pirko <jiri@nvidia.com> Reviewed-by: Donald Hunter <donald.hunter@gmail.com> Link: https://lore.kernel.org/r/20240222134351.224704-4-jiri@resnulli.us Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/net/ynl')
-rw-r--r--tools/net/ynl/lib/ynl.py26
1 files changed, 24 insertions, 2 deletions
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index e459a130170b..ac55aa5a3083 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -438,6 +438,26 @@ class YnlFamily(SpecFamily):
self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_ADD_MEMBERSHIP,
mcast_id)
+ def _encode_enum(self, attr_spec, value):
+ enum = self.consts[attr_spec['enum']]
+ if enum.type == 'flags' or attr_spec.get('enum-as-flags', False):
+ scalar = 0
+ if isinstance(value, str):
+ value = [value]
+ for single_value in value:
+ scalar += enum.entries[single_value].user_value(as_flags = True)
+ return scalar
+ else:
+ return enum.entries[value].user_value()
+
+ def _get_scalar(self, attr_spec, value):
+ try:
+ return int(value)
+ except (ValueError, TypeError) as e:
+ if 'enum' not in attr_spec:
+ raise e
+ return self._encode_enum(attr_spec, value);
+
def _add_attr(self, space, name, value, search_attrs):
try:
attr = self.attr_sets[space][name]
@@ -475,7 +495,7 @@ class YnlFamily(SpecFamily):
else:
raise Exception(f'Unknown type for binary attribute, value: {value}')
elif attr['type'] in NlAttr.type_formats or attr.is_auto_scalar:
- scalar = int(value)
+ scalar = self._get_scalar(attr, value)
if attr.is_auto_scalar:
attr_type = attr["type"][0] + ('32' if scalar.bit_length() <= 32 else '64')
else:
@@ -483,7 +503,9 @@ class YnlFamily(SpecFamily):
format = NlAttr.get_format(attr_type, attr.byte_order)
attr_payload = format.pack(scalar)
elif attr['type'] in "bitfield32":
- attr_payload = struct.pack("II", int(value["value"]), int(value["selector"]))
+ scalar_value = self._get_scalar(attr, value["value"])
+ scalar_selector = self._get_scalar(attr, value["selector"])
+ attr_payload = struct.pack("II", scalar_value, scalar_selector)
elif attr['type'] == 'sub-message':
msg_format = self._resolve_selector(attr, search_attrs)
attr_payload = b''