Commit 777c8029 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Paolo Abeni
Browse files

tools: ynl: allow fixed-header to be specified per op



rtnetlink has variety of ops with different fixed headers.
Detect that op fixed header is not the same as family one,
and use sizeof() directly. For reverse parsing we need to
pass the fixed header len along the policy (in the socket
state).

Reviewed-by: default avatarDonald Hunter <donald.hunter@gmail.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20250429154704.2613851-13-kuba@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 18d574c8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -191,12 +191,12 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
		n = snprintf(bad_attr, sizeof(bad_attr), "%sbad attribute: ",
			     str ? " (" : "");

		start = ynl_nlmsg_data_offset(ys->nlh, ys->family->hdr_len);
		start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
		end = ynl_nlmsg_end_addr(ys->nlh);

		off = ys->err.attr_offs;
		off -= sizeof(struct nlmsghdr);
		off -= ys->family->hdr_len;
		off -= ys->req_hdr_len;

		n += ynl_err_walk(ys, start, end, off, ys->req_policy,
				  &bad_attr[n], sizeof(bad_attr) - n, NULL);
@@ -216,14 +216,14 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
		n = snprintf(miss_attr, sizeof(miss_attr), "%smissing attribute: ",
			     bad_attr[0] ? ", " : (str ? " (" : ""));

		start = ynl_nlmsg_data_offset(ys->nlh, ys->family->hdr_len);
		start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
		end = ynl_nlmsg_end_addr(ys->nlh);

		nest_pol = ys->req_policy;
		if (tb[NLMSGERR_ATTR_MISS_NEST]) {
			off = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
			off -= sizeof(struct nlmsghdr);
			off -= ys->family->hdr_len;
			off -= ys->req_hdr_len;

			n += ynl_err_walk(ys, start, end, off, ys->req_policy,
					  &miss_attr[n], sizeof(miss_attr) - n,
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ struct ynl_sock {

	struct nlmsghdr *nlh;
	const struct ynl_policy_nest *req_policy;
	size_t req_hdr_len;
	unsigned char *tx_buf;
	unsigned char *rx_buf;
	unsigned char raw_buf[];
+16 −1
Original line number Diff line number Diff line
@@ -1311,8 +1311,15 @@ class RenderInfo:
        self.op = op

        self.fixed_hdr = None
        self.fixed_hdr_len = 'ys->family->hdr_len'
        if op and op.fixed_header:
            self.fixed_hdr = 'struct ' + c_lower(op.fixed_header)
            if op.fixed_header != family.fixed_header:
                if family.is_classic():
                    self.fixed_hdr_len = f"sizeof({self.fixed_hdr})"
                else:
                    raise Exception(f"Per-op fixed header not supported, yet")


        # 'do' and 'dump' response parsing is identical
        self.type_consistent = True
@@ -1799,6 +1806,11 @@ def _multi_parse(ri, struct, init_lines, local_vars):
        if ri.fixed_hdr:
            local_vars += ['void *hdr;']
        iter_line = "ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len)"
        if ri.op.fixed_header != ri.family.fixed_header:
            if ri.family.is_classic():
                iter_line = f"ynl_attr_for_each(attr, nlh, sizeof({ri.fixed_hdr}))"
            else:
                raise Exception(f"Per-op fixed header not supported, yet")

    array_nests = set()
    multi_attrs = set()
@@ -2016,6 +2028,7 @@ def print_req(ri):
        ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")

    ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;")
    ri.cw.p(f"ys->req_hdr_len = {ri.fixed_hdr_len};")
    if 'reply' in ri.op[ri.op_mode]:
        ri.cw.p(f"yrs.yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;")
    ri.cw.nl()
@@ -2095,6 +2108,7 @@ def print_dump(ri):

    if "request" in ri.op[ri.op_mode]:
        ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;")
        ri.cw.p(f"ys->req_hdr_len = {ri.fixed_hdr_len};")
        ri.cw.nl()
        for _, attr in ri.struct["request"].member_list():
            attr.attr_put(ri, "req")
@@ -2914,6 +2928,7 @@ def render_user_family(family, cw, prototype):
        cw.p(f'.is_classic\t= true,')
        cw.p(f'.classic_id\t= {family.get("protonum")},')
    if family.is_classic():
        if family.fixed_header:
            cw.p(f'.hdr_len\t= sizeof(struct {c_lower(family.fixed_header)}),')
    elif family.fixed_header:
        cw.p(f'.hdr_len\t= sizeof(struct genlmsghdr) + sizeof(struct {c_lower(family.fixed_header)}),')