Commit fb0a06d4 authored by Donald Hunter's avatar Donald Hunter Committed by Jakub Kicinski
Browse files

tools/net/ynl: Fix extack parsing with fixed header genlmsg



Move decode_fixed_header into YnlFamily and add a _fixed_header_size
method to allow extack decoding to skip the fixed header.

Signed-off-by: default avatarDonald Hunter <donald.hunter@gmail.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Link: https://lore.kernel.org/r/20230825122756.7603-7-donald.hunter@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 88901b96
Loading
Loading
Loading
Loading
+40 −25
Original line number Diff line number Diff line
@@ -293,7 +293,7 @@ def _genl_load_families():

                gm = GenlMsg(nl_msg)
                fam = dict()
                for attr in gm.raw_attrs:
                for attr in NlAttrs(gm.raw):
                    if attr.type == Netlink.CTRL_ATTR_FAMILY_ID:
                        fam['id'] = attr.as_scalar('u16')
                    elif attr.type == Netlink.CTRL_ATTR_FAMILY_NAME:
@@ -317,23 +317,10 @@ def _genl_load_families():


class GenlMsg:
    def __init__(self, nl_msg, fixed_header_members=[]):
    def __init__(self, nl_msg):
        self.nl = nl_msg

        self.hdr = nl_msg.raw[0:4]
        offset = 4

        self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr)

        self.fixed_header_attrs = dict()
        for m in fixed_header_members:
            format = NlAttr.get_format(m.type, m.byte_order)
            decoded = format.unpack_from(nl_msg.raw, offset)
            offset += format.size
            self.fixed_header_attrs[m.name] = decoded[0]

        self.raw = nl_msg.raw[offset:]
        self.raw_attrs = NlAttrs(self.raw)
        self.genl_cmd, self.genl_version, _ = struct.unpack_from("BBH", nl_msg.raw, 0)
        self.raw = nl_msg.raw[4:]

    def __repr__(self):
        msg = repr(self.nl)
@@ -514,17 +501,44 @@ class YnlFamily(SpecFamily):

        return None

    def _decode_extack(self, request, attr_space, extack):
    def _decode_extack(self, request, op, extack):
        if 'bad-attr-offs' not in extack:
            return

        genl_req = GenlMsg(NlMsg(request, 0, attr_space=attr_space))
        path = self._decode_extack_path(genl_req.raw_attrs, attr_space,
                                        20, extack['bad-attr-offs'])
        genl_req = GenlMsg(NlMsg(request, 0, op.attr_set))
        fixed_header_size = self._fixed_header_size(op)
        offset = 20 + fixed_header_size
        path = self._decode_extack_path(NlAttrs(genl_req.raw[fixed_header_size:]),
                                        op.attr_set, offset,
                                        extack['bad-attr-offs'])
        if path:
            del extack['bad-attr-offs']
            extack['bad-attr'] = path

    def _fixed_header_size(self, op):
        if op.fixed_header:
            fixed_header_members = self.consts[op.fixed_header].members
            size = 0
            for m in fixed_header_members:
                format = NlAttr.get_format(m.type, m.byte_order)
                size += format.size
            return size
        else:
            return 0

    def _decode_fixed_header(self, msg, name):
        fixed_header_members = self.consts[name].members
        fixed_header_attrs = dict()
        offset = 0
        for m in fixed_header_members:
            format = NlAttr.get_format(m.type, m.byte_order)
            [ value ] = format.unpack_from(msg.raw, offset)
            offset += format.size
            if m.enum:
                value = self._decode_enum(value, m)
            fixed_header_attrs[m.name] = value
        return fixed_header_attrs

    def handle_ntf(self, nl_msg, genl_msg):
        msg = dict()
        if self.include_raw:
@@ -599,7 +613,7 @@ class YnlFamily(SpecFamily):
            nms = NlMsgs(reply, attr_space=op.attr_set)
            for nl_msg in nms:
                if nl_msg.extack:
                    self._decode_extack(msg, op.attr_set, nl_msg.extack)
                    self._decode_extack(msg, op, nl_msg.extack)

                if nl_msg.error:
                    raise NlError(nl_msg)
@@ -610,7 +624,7 @@ class YnlFamily(SpecFamily):
                    done = True
                    break

                gm = GenlMsg(nl_msg, fixed_header_members)
                gm = GenlMsg(nl_msg)
                # Check if this is a reply to our request
                if nl_msg.nl_seq != req_seq or gm.genl_cmd != op.rsp_value:
                    if gm.genl_cmd in self.async_msg_ids:
@@ -620,8 +634,9 @@ class YnlFamily(SpecFamily):
                        print('Unexpected message: ' + repr(gm))
                        continue

                rsp_msg = self._decode(gm.raw_attrs, op.attr_set.name)
                rsp_msg.update(gm.fixed_header_attrs)
                rsp_msg = self._decode(NlAttrs(gm.raw), op.attr_set.name)
                if op.fixed_header:
                    rsp_msg.update(self._decode_fixed_header(gm, op.fixed_header))
                rsp.append(rsp_msg)

        if not rsp: