Skip to content

Commit 09d7ff0

Browse files
donaldhkuba-moo
authored andcommitted
tools: ynl: parse extack for sub-messages
Extend the Python YNL extack decoding to handle sub-messages in the same way that YNL C does. This involves retaining the input values so that they are available during extack decoding. ./tools/net/ynl/pyynl/cli.py --family rt-link --do newlink --create \ --json '{ "linkinfo": {"kind": "netkit", "data": {"policy": 10} } }' Netlink error: Invalid argument nl_len = 92 (76) nl_flags = 0x300 nl_type = 2 error: -22 extack: {'msg': 'Provided default xmit policy not supported', 'bad-attr': '.linkinfo.data(netkit).policy'} Signed-off-by: Donald Hunter <donald.hunter@gmail.com> Link: https://patch.msgid.link/20250523103031.80236-1-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 8bc3c23 commit 09d7ff0

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

tools/net/ynl/pyynl/lib/ynl.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ def _add_attr(self, space, name, value, search_attrs):
594594
scalar_selector = self._get_scalar(attr, value["selector"])
595595
attr_payload = struct.pack("II", scalar_value, scalar_selector)
596596
elif attr['type'] == 'sub-message':
597-
msg_format = self._resolve_selector(attr, search_attrs)
597+
msg_format, _ = self._resolve_selector(attr, search_attrs)
598598
attr_payload = b''
599599
if msg_format.fixed_header:
600600
attr_payload += self._encode_struct(msg_format.fixed_header, value)
@@ -712,10 +712,10 @@ def _resolve_selector(self, attr_spec, search_attrs):
712712
raise Exception(f"No message format for '{value}' in sub-message spec '{sub_msg}'")
713713

714714
spec = sub_msg_spec.formats[value]
715-
return spec
715+
return spec, value
716716

717717
def _decode_sub_msg(self, attr, attr_spec, search_attrs):
718-
msg_format = self._resolve_selector(attr_spec, search_attrs)
718+
msg_format, _ = self._resolve_selector(attr_spec, search_attrs)
719719
decoded = {}
720720
offset = 0
721721
if msg_format.fixed_header:
@@ -787,7 +787,7 @@ def _decode(self, attrs, space, outer_attrs = None):
787787

788788
return rsp
789789

790-
def _decode_extack_path(self, attrs, attr_set, offset, target):
790+
def _decode_extack_path(self, attrs, attr_set, offset, target, search_attrs):
791791
for attr in attrs:
792792
try:
793793
attr_spec = attr_set.attrs_by_val[attr.type]
@@ -801,26 +801,37 @@ def _decode_extack_path(self, attrs, attr_set, offset, target):
801801
if offset + attr.full_len <= target:
802802
offset += attr.full_len
803803
continue
804-
if attr_spec['type'] != 'nest':
804+
805+
pathname = attr_spec.name
806+
if attr_spec['type'] == 'nest':
807+
sub_attrs = self.attr_sets[attr_spec['nested-attributes']]
808+
search_attrs = SpaceAttrs(sub_attrs, search_attrs.lookup(attr_spec['name']))
809+
elif attr_spec['type'] == 'sub-message':
810+
msg_format, value = self._resolve_selector(attr_spec, search_attrs)
811+
if msg_format is None:
812+
raise Exception(f"Can't resolve sub-message of {attr_spec['name']} for extack")
813+
sub_attrs = self.attr_sets[msg_format.attr_set]
814+
pathname += f"({value})"
815+
else:
805816
raise Exception(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack")
806817
offset += 4
807-
subpath = self._decode_extack_path(NlAttrs(attr.raw),
808-
self.attr_sets[attr_spec['nested-attributes']],
809-
offset, target)
818+
subpath = self._decode_extack_path(NlAttrs(attr.raw), sub_attrs,
819+
offset, target, search_attrs)
810820
if subpath is None:
811821
return None
812-
return '.' + attr_spec.name + subpath
822+
return '.' + pathname + subpath
813823

814824
return None
815825

816-
def _decode_extack(self, request, op, extack):
826+
def _decode_extack(self, request, op, extack, vals):
817827
if 'bad-attr-offs' not in extack:
818828
return
819829

820830
msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set), op)
821831
offset = self.nlproto.msghdr_size() + self._struct_size(op.fixed_header)
832+
search_attrs = SpaceAttrs(op.attr_set, vals)
822833
path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset,
823-
extack['bad-attr-offs'])
834+
extack['bad-attr-offs'], search_attrs)
824835
if path:
825836
del extack['bad-attr-offs']
826837
extack['bad-attr'] = path
@@ -1012,7 +1023,7 @@ def _ops(self, ops):
10121023
for (method, vals, flags) in ops:
10131024
op = self.ops[method]
10141025
msg = self._encode_message(op, vals, flags, req_seq)
1015-
reqs_by_seq[req_seq] = (op, msg, flags)
1026+
reqs_by_seq[req_seq] = (op, vals, msg, flags)
10161027
payload += msg
10171028
req_seq += 1
10181029

@@ -1027,9 +1038,9 @@ def _ops(self, ops):
10271038
self._recv_dbg_print(reply, nms)
10281039
for nl_msg in nms:
10291040
if nl_msg.nl_seq in reqs_by_seq:
1030-
(op, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq]
1041+
(op, vals, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq]
10311042
if nl_msg.extack:
1032-
self._decode_extack(req_msg, op, nl_msg.extack)
1043+
self._decode_extack(req_msg, op, nl_msg.extack, vals)
10331044
else:
10341045
op = None
10351046
req_flags = []

0 commit comments

Comments
 (0)