Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl-gen: print setters for multi-val attrs

For basic types we "flatten" setters. If a request "a" has a simple
nest "b" with value "val" we print helpers like:

req_set_a_b(struct a *req, int val)
{
req->_present.a = 1;
req->b._present.val = 1;
req->b.val = ...
}

This is not possible for multi-attr because they have to be allocated
dynamically by the user. Print "object level" setters so that user
preparing the object doesn't have to futz with the presence bits
and other YNL internals.

Add the ability to pass in the variable name to generated setters.
Using "req" here doesn't feel right, while the attr is part of a request
it's not the request itself, so it seems cleaner to call it "obj".

Example:

static inline void
netdev_queue_id_set_id(struct netdev_queue_id *obj, __u32 id)
{
obj->_present.id = 1;
obj->id = id;
}

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250723171046.4027470-5-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+13 -6
+13 -6
tools/net/ynl/pyynl/ynl_gen_c.py
··· 275 275 def _setter_lines(self, ri, member, presence): 276 276 raise Exception(f"Setter not implemented for class type {self.type}") 277 277 278 - def setter(self, ri, space, direction, deref=False, ref=None): 278 + def setter(self, ri, space, direction, deref=False, ref=None, var="req"): 279 279 ref = (ref if ref else []) + [self.c_name] 280 - var = "req" 281 280 member = f"{var}->{'.'.join(ref)}" 282 281 283 282 local_vars = [] ··· 331 332 def attr_get(self, ri, var, first): 332 333 pass 333 334 334 - def setter(self, ri, space, direction, deref=False, ref=None): 335 + def setter(self, ri, space, direction, deref=False, ref=None, var=None): 335 336 pass 336 337 337 338 ··· 354 355 def attr_policy(self, cw): 355 356 pass 356 357 357 - def setter(self, ri, space, direction, deref=False, ref=None): 358 + def setter(self, ri, space, direction, deref=False, ref=None, var=None): 358 359 pass 359 360 360 361 ··· 694 695 f"parg.data = &{var}->{self.c_name};"] 695 696 return get_lines, init_lines, None 696 697 697 - def setter(self, ri, space, direction, deref=False, ref=None): 698 + def setter(self, ri, space, direction, deref=False, ref=None, var="req"): 698 699 ref = (ref if ref else []) + [self.c_name] 699 700 700 701 for _, attr in ri.family.pure_nested_structs[self.nested_attrs].member_list(): 701 702 if attr.is_recursive(): 702 703 continue 703 - attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref) 704 + attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref, 705 + var=var) 704 706 705 707 706 708 class TypeMultiAttr(Type): ··· 2561 2561 print_alloc_wrapper(ri, "", struct) 2562 2562 ri.cw.nl() 2563 2563 free_rsp_nested_prototype(ri) 2564 + ri.cw.nl() 2565 + 2566 + # Name conflicts are too hard to deal with with the current code base, 2567 + # they are very rare so don't bother printing setters in that case. 2568 + if ri.ku_space == 'user' and not ri.type_name_conflict: 2569 + for _, attr in struct.member_list(): 2570 + attr.setter(ri, ri.attr_set, "", var="obj") 2564 2571 ri.cw.nl() 2565 2572 2566 2573