mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
tools: ynl-gen: support fixed headers in genetlink
Support genetlink families using simple fixed headers. Assume fixed header is identical for all ops of the family for now. Fixed headers are added to the request and reply structs as a _hdr member, and copied to/from netlink messages appropriately. Reviewed-by: Donald Hunter <donald.hunter@gmail.com> Link: https://lore.kernel.org/r/20231213231432.2944749-4-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
139c163b5b
commit
f6805072c2
|
@ -191,12 +191,12 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
|
|||
str ? " (" : "");
|
||||
|
||||
start = mnl_nlmsg_get_payload_offset(ys->nlh,
|
||||
sizeof(struct genlmsghdr));
|
||||
ys->family->hdr_len);
|
||||
end = mnl_nlmsg_get_payload_tail(ys->nlh);
|
||||
|
||||
off = ys->err.attr_offs;
|
||||
off -= sizeof(struct nlmsghdr);
|
||||
off -= sizeof(struct genlmsghdr);
|
||||
off -= ys->family->hdr_len;
|
||||
|
||||
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
|
||||
&bad_attr[n], sizeof(bad_attr) - n, NULL);
|
||||
|
@ -217,14 +217,14 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
|
|||
bad_attr[0] ? ", " : (str ? " (" : ""));
|
||||
|
||||
start = mnl_nlmsg_get_payload_offset(ys->nlh,
|
||||
sizeof(struct genlmsghdr));
|
||||
ys->family->hdr_len);
|
||||
end = mnl_nlmsg_get_payload_tail(ys->nlh);
|
||||
|
||||
nest_pol = ys->req_policy;
|
||||
if (tb[NLMSGERR_ATTR_MISS_NEST]) {
|
||||
off = mnl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
|
||||
off -= sizeof(struct nlmsghdr);
|
||||
off -= sizeof(struct genlmsghdr);
|
||||
off -= ys->family->hdr_len;
|
||||
|
||||
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
|
||||
&miss_attr[n], sizeof(miss_attr) - n,
|
||||
|
|
|
@ -44,6 +44,7 @@ struct ynl_error {
|
|||
struct ynl_family {
|
||||
/* private: */
|
||||
const char *name;
|
||||
size_t hdr_len;
|
||||
const struct ynl_ntf_info *ntf_info;
|
||||
unsigned int ntf_info_size;
|
||||
};
|
||||
|
|
|
@ -1124,6 +1124,10 @@ class RenderInfo:
|
|||
self.op_mode = op_mode
|
||||
self.op = op
|
||||
|
||||
self.fixed_hdr = None
|
||||
if op and op.fixed_header:
|
||||
self.fixed_hdr = 'struct ' + c_lower(op.fixed_header)
|
||||
|
||||
# 'do' and 'dump' response parsing is identical
|
||||
self.type_consistent = True
|
||||
if op_mode != 'do' and 'dump' in op:
|
||||
|
@ -1570,7 +1574,9 @@ def _multi_parse(ri, struct, init_lines, local_vars):
|
|||
if struct.nested:
|
||||
iter_line = "mnl_attr_for_each_nested(attr, nested)"
|
||||
else:
|
||||
iter_line = "mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr))"
|
||||
if ri.fixed_hdr:
|
||||
local_vars += ['void *hdr;']
|
||||
iter_line = "mnl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len)"
|
||||
|
||||
array_nests = set()
|
||||
multi_attrs = set()
|
||||
|
@ -1603,6 +1609,9 @@ def _multi_parse(ri, struct, init_lines, local_vars):
|
|||
for arg in struct.inherited:
|
||||
ri.cw.p(f'dst->{arg} = {arg};')
|
||||
|
||||
if ri.fixed_hdr:
|
||||
ri.cw.p('hdr = mnl_nlmsg_get_payload_offset(nlh, sizeof(struct genlmsghdr));')
|
||||
ri.cw.p(f"memcpy(&dst->_hdr, hdr, sizeof({ri.fixed_hdr}));")
|
||||
for anest in sorted(all_multi):
|
||||
aspec = struct[anest]
|
||||
ri.cw.p(f"if (dst->{aspec.c_name})")
|
||||
|
@ -1723,6 +1732,10 @@ def print_req(ri):
|
|||
ret_err = 'NULL'
|
||||
local_vars += [f'{type_name(ri, rdir(direction))} *rsp;']
|
||||
|
||||
if ri.fixed_hdr:
|
||||
local_vars += ['size_t hdr_len;',
|
||||
'void *hdr;']
|
||||
|
||||
print_prototype(ri, direction, terminate=False)
|
||||
ri.cw.block_start()
|
||||
ri.cw.write_func_lvar(local_vars)
|
||||
|
@ -1733,6 +1746,13 @@ def print_req(ri):
|
|||
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()
|
||||
|
||||
if ri.fixed_hdr:
|
||||
ri.cw.p("hdr_len = sizeof(req->_hdr);")
|
||||
ri.cw.p("hdr = mnl_nlmsg_put_extra_header(nlh, hdr_len);")
|
||||
ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);")
|
||||
ri.cw.nl()
|
||||
|
||||
for _, attr in ri.struct["request"].member_list():
|
||||
attr.attr_put(ri, "req")
|
||||
ri.cw.nl()
|
||||
|
@ -1773,9 +1793,11 @@ def print_dump(ri):
|
|||
'struct nlmsghdr *nlh;',
|
||||
'int err;']
|
||||
|
||||
for var in local_vars:
|
||||
ri.cw.p(f'{var}')
|
||||
ri.cw.nl()
|
||||
if ri.fixed_hdr:
|
||||
local_vars += ['size_t hdr_len;',
|
||||
'void *hdr;']
|
||||
|
||||
ri.cw.write_func_lvar(local_vars)
|
||||
|
||||
ri.cw.p('yds.ys = ys;')
|
||||
ri.cw.p(f"yds.alloc_sz = sizeof({type_name(ri, rdir(direction))});")
|
||||
|
@ -1788,6 +1810,12 @@ def print_dump(ri):
|
|||
ri.cw.nl()
|
||||
ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
|
||||
|
||||
if ri.fixed_hdr:
|
||||
ri.cw.p("hdr_len = sizeof(req->_hdr);")
|
||||
ri.cw.p("hdr = mnl_nlmsg_put_extra_header(nlh, hdr_len);")
|
||||
ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);")
|
||||
ri.cw.nl()
|
||||
|
||||
if "request" in ri.op[ri.op_mode]:
|
||||
ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;")
|
||||
ri.cw.nl()
|
||||
|
@ -1845,6 +1873,10 @@ def _print_type(ri, direction, struct):
|
|||
|
||||
ri.cw.block_start(line=f"struct {ri.family.c_name}{suffix}")
|
||||
|
||||
if ri.fixed_hdr:
|
||||
ri.cw.p(ri.fixed_hdr + ' _hdr;')
|
||||
ri.cw.nl()
|
||||
|
||||
meta_started = False
|
||||
for _, attr in struct.member_list():
|
||||
for type_filter in ['len', 'bit']:
|
||||
|
@ -2482,6 +2514,10 @@ def render_user_family(family, cw, prototype):
|
|||
|
||||
cw.block_start(f'{symbol} = ')
|
||||
cw.p(f'.name\t\t= "{family.c_name}",')
|
||||
if family.fixed_header:
|
||||
cw.p(f'.hdr_len\t= sizeof(struct genlmsghdr) + sizeof(struct {c_lower(family.fixed_header)}),')
|
||||
else:
|
||||
cw.p('.hdr_len\t= sizeof(struct genlmsghdr),')
|
||||
if family.ntfs:
|
||||
cw.p(f".ntf_info\t= {family['name']}_ntf_info,")
|
||||
cw.p(f".ntf_info_size\t= MNL_ARRAY_SIZE({family['name']}_ntf_info),")
|
||||
|
|
Loading…
Reference in a new issue