tools: ynl: let classic netlink requests specify extra nlflags

Classic netlink makes extensive use of flags. Support specifying
them the same way as attributes are specified (using a helper),
for example:

     rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);

Wrap the code up in a RenderInfo predicate. I think that some
genetlink families may want this, too. It should be easy to
add a spec property later.

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20250429154704.2613851-5-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Jakub Kicinski
2025-04-29 08:46:56 -07:00
committed by Paolo Abeni
parent d12a7be025
commit fe7d57e040
3 changed files with 23 additions and 4 deletions

View File

@@ -94,7 +94,7 @@ struct ynl_ntf_base_type {
unsigned char data[] __attribute__((aligned(8)));
};
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id);
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags);
struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id);
struct nlmsghdr *

View File

@@ -451,9 +451,9 @@ ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
return nlh;
}
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id)
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags)
{
return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK);
return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | flags);
}
struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)

View File

@@ -1294,6 +1294,9 @@ class RenderInfo:
def type_empty(self, key):
return len(self.struct[key].attr_list) == 0 and self.fixed_hdr is None
def needs_nlflags(self, direction):
return self.op_mode == 'do' and direction == 'request' and self.family.is_classic()
class CodeWriter:
def __init__(self, nlib, out_file=None, overwrite=True):
@@ -1924,7 +1927,7 @@ def print_req(ri):
ri.cw.write_func_lvar(local_vars)
if ri.family.is_classic():
ri.cw.p(f"nlh = ynl_msg_start_req(ys, {ri.op.enum_name});")
ri.cw.p(f"nlh = ynl_msg_start_req(ys, {ri.op.enum_name}, req->_nlmsg_flags);")
else:
ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
@@ -2053,6 +2056,16 @@ def print_free_prototype(ri, direction, suffix=';'):
ri.cw.write_func_prot('void', f"{name}_free", [f"struct {struct_name} *{arg}"], suffix=suffix)
def print_nlflags_set(ri, direction):
name = op_prefix(ri, direction)
ri.cw.write_func_prot(f'static inline void', f"{name}_set_nlflags",
[f"struct {name} *req", "__u16 nl_flags"])
ri.cw.block_start()
ri.cw.p('req->_nlmsg_flags = nl_flags;')
ri.cw.block_end()
ri.cw.nl()
def _print_type(ri, direction, struct):
suffix = f'_{ri.type_name}{direction_to_suffix[direction]}'
if not direction and ri.type_name_conflict:
@@ -2063,6 +2076,9 @@ def _print_type(ri, direction, struct):
ri.cw.block_start(line=f"struct {ri.family.c_name}{suffix}")
if ri.needs_nlflags(direction):
ri.cw.p('__u16 _nlmsg_flags;')
ri.cw.nl()
if ri.fixed_hdr:
ri.cw.p(ri.fixed_hdr + ' _hdr;')
ri.cw.nl()
@@ -2102,6 +2118,9 @@ def print_type_helpers(ri, direction, deref=False):
print_free_prototype(ri, direction)
ri.cw.nl()
if ri.needs_nlflags(direction):
print_nlflags_set(ri, direction)
if ri.ku_space == 'user' and direction == 'request':
for _, attr in ri.struct[direction].member_list():
attr.setter(ri, ri.attr_set, direction, deref=deref)