diff options
Diffstat (limited to 'tools/net/ynl/pyynl/lib/ynl.py')
-rw-r--r-- | tools/net/ynl/pyynl/lib/ynl.py | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index dcc2c6b298d6..55b59f6c79b8 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -594,7 +594,7 @@ class YnlFamily(SpecFamily): 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) + msg_format, _ = self._resolve_selector(attr, search_attrs) attr_payload = b'' if msg_format.fixed_header: attr_payload += self._encode_struct(msg_format.fixed_header, value) @@ -712,10 +712,10 @@ class YnlFamily(SpecFamily): raise Exception(f"No message format for '{value}' in sub-message spec '{sub_msg}'") spec = sub_msg_spec.formats[value] - return spec + return spec, value def _decode_sub_msg(self, attr, attr_spec, search_attrs): - msg_format = self._resolve_selector(attr_spec, search_attrs) + msg_format, _ = self._resolve_selector(attr_spec, search_attrs) decoded = {} offset = 0 if msg_format.fixed_header: @@ -787,7 +787,7 @@ class YnlFamily(SpecFamily): return rsp - def _decode_extack_path(self, attrs, attr_set, offset, target): + def _decode_extack_path(self, attrs, attr_set, offset, target, search_attrs): for attr in attrs: try: attr_spec = attr_set.attrs_by_val[attr.type] @@ -801,26 +801,37 @@ class YnlFamily(SpecFamily): if offset + attr.full_len <= target: offset += attr.full_len continue - if attr_spec['type'] != 'nest': + + pathname = attr_spec.name + if attr_spec['type'] == 'nest': + sub_attrs = self.attr_sets[attr_spec['nested-attributes']] + search_attrs = SpaceAttrs(sub_attrs, search_attrs.lookup(attr_spec['name'])) + elif attr_spec['type'] == 'sub-message': + msg_format, value = self._resolve_selector(attr_spec, search_attrs) + if msg_format is None: + raise Exception(f"Can't resolve sub-message of {attr_spec['name']} for extack") + sub_attrs = self.attr_sets[msg_format.attr_set] + pathname += f"({value})" + else: raise Exception(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack") offset += 4 - subpath = self._decode_extack_path(NlAttrs(attr.raw), - self.attr_sets[attr_spec['nested-attributes']], - offset, target) + subpath = self._decode_extack_path(NlAttrs(attr.raw), sub_attrs, + offset, target, search_attrs) if subpath is None: return None - return '.' + attr_spec.name + subpath + return '.' + pathname + subpath return None - def _decode_extack(self, request, op, extack): + def _decode_extack(self, request, op, extack, vals): if 'bad-attr-offs' not in extack: return msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set), op) offset = self.nlproto.msghdr_size() + self._struct_size(op.fixed_header) + search_attrs = SpaceAttrs(op.attr_set, vals) path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset, - extack['bad-attr-offs']) + extack['bad-attr-offs'], search_attrs) if path: del extack['bad-attr-offs'] extack['bad-attr'] = path @@ -1012,7 +1023,7 @@ class YnlFamily(SpecFamily): for (method, vals, flags) in ops: op = self.ops[method] msg = self._encode_message(op, vals, flags, req_seq) - reqs_by_seq[req_seq] = (op, msg, flags) + reqs_by_seq[req_seq] = (op, vals, msg, flags) payload += msg req_seq += 1 @@ -1027,9 +1038,9 @@ class YnlFamily(SpecFamily): self._recv_dbg_print(reply, nms) for nl_msg in nms: if nl_msg.nl_seq in reqs_by_seq: - (op, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq] + (op, vals, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq] if nl_msg.extack: - self._decode_extack(req_msg, op, nl_msg.extack) + self._decode_extack(req_msg, op, nl_msg.extack, vals) else: op = None req_flags = [] |