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

tools: ynl-gen: split presence metadata

Each YNL struct contains the data and a sub-struct indicating which
fields are valid. Something like:

struct family_op_req {
struct {
u32 a:1;
u32 b:1;
u32 bin_len;
} _present;

u32 a;
u64 b;
const unsigned char *bin;
};

Note that the bin object 'bin' has a length stored, and that length
has a _len suffix added to the field name. This breaks if there
is a explicit field called bin_len, which is the case for some
TC actions. Move the length fields out of the _present struct,
create a new struct called _len:

struct family_op_req {
struct {
u32 a:1;
u32 b:1;
} _present;
struct {
u32 bin;
} _len;

u32 a;
u64 b;
const unsigned char *bin;
};

This should prevent name collisions and help with the packing
of the struct.

Unfortunately this is a breaking change, but hopefully the migration
isn't too painful.

Link: https://patch.msgid.link/20250505165208.248049-3-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+28 -28
+23 -23
tools/net/ynl/pyynl/ynl_gen_c.py
··· 154 154 155 155 if self.presence_type() == 'len': 156 156 pfx = '__' if space == 'user' else '' 157 - return f"{pfx}u32 {self.c_name}_len;" 157 + return f"{pfx}u32 {self.c_name};" 158 158 159 159 def _complex_member_type(self, ri): 160 160 return None ··· 217 217 cw.p(f'[{self.enum_name}] = {"{"} .name = "{self.name}", {typol}{"}"},') 218 218 219 219 def _attr_put_line(self, ri, var, line): 220 - if self.presence_type() == 'present': 221 - ri.cw.p(f"if ({var}->_present.{self.c_name})") 222 - elif self.presence_type() == 'len': 223 - ri.cw.p(f"if ({var}->_present.{self.c_name}_len)") 220 + presence = self.presence_type() 221 + if presence in {'present', 'len'}: 222 + ri.cw.p(f"if ({var}->_{presence}.{self.c_name})") 224 223 ri.cw.p(f"{line};") 225 224 226 225 def _attr_put_simple(self, ri, var, put_type): ··· 281 282 # Every layer below last is a nest, so we know it uses bit presence 282 283 # last layer is "self" and may be a complex type 283 284 if i == len(ref) - 1 and self.presence_type() != 'present': 285 + presence = f"{var}->{'.'.join(ref[:i] + [''])}_{self.presence_type()}.{ref[i]}" 284 286 continue 285 287 code.append(presence + ' = 1;') 286 288 ref_path = '.'.join(ref[:-1]) ··· 501 501 self._attr_put_simple(ri, var, 'str') 502 502 503 503 def _attr_get(self, ri, var): 504 - len_mem = var + '->_present.' + self.c_name + '_len' 504 + len_mem = var + '->_len.' + self.c_name 505 505 return [f"{len_mem} = len;", 506 506 f"{var}->{self.c_name} = malloc(len + 1);", 507 507 f"memcpy({var}->{self.c_name}, ynl_attr_get_str(attr), len);", ··· 510 510 ['unsigned int len;'] 511 511 512 512 def _setter_lines(self, ri, member, presence): 513 - return [f"{presence}_len = strlen({self.c_name});", 514 - f"{member} = malloc({presence}_len + 1);", 515 - f'memcpy({member}, {self.c_name}, {presence}_len);', 516 - f'{member}[{presence}_len] = 0;'] 513 + return [f"{presence} = strlen({self.c_name});", 514 + f"{member} = malloc({presence} + 1);", 515 + f'memcpy({member}, {self.c_name}, {presence});', 516 + f'{member}[{presence}] = 0;'] 517 517 518 518 519 519 class TypeBinary(Type): ··· 552 552 553 553 def attr_put(self, ri, var): 554 554 self._attr_put_line(ri, var, f"ynl_attr_put(nlh, {self.enum_name}, " + 555 - f"{var}->{self.c_name}, {var}->_present.{self.c_name}_len)") 555 + f"{var}->{self.c_name}, {var}->_len.{self.c_name})") 556 556 557 557 def _attr_get(self, ri, var): 558 - len_mem = var + '->_present.' + self.c_name + '_len' 558 + len_mem = var + '->_len.' + self.c_name 559 559 return [f"{len_mem} = len;", 560 560 f"{var}->{self.c_name} = malloc(len);", 561 561 f"memcpy({var}->{self.c_name}, ynl_attr_data(attr), len);"], \ ··· 563 563 ['unsigned int len;'] 564 564 565 565 def _setter_lines(self, ri, member, presence): 566 - return [f"{presence}_len = len;", 567 - f"{member} = malloc({presence}_len);", 568 - f'memcpy({member}, {self.c_name}, {presence}_len);'] 566 + return [f"{presence} = len;", 567 + f"{member} = malloc({presence});", 568 + f'memcpy({member}, {self.c_name}, {presence});'] 569 569 570 570 571 571 class TypeBitfield32(Type): ··· 721 721 722 722 def _setter_lines(self, ri, member, presence): 723 723 # For multi-attr we have a count, not presence, hack up the presence 724 - presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name 724 + presence = presence[:-(len('_count.') + len(self.c_name))] + "n_" + self.c_name 725 725 return [f"{member} = {self.c_name};", 726 726 f"{presence} = n_{self.c_name};"] 727 727 ··· 784 784 785 785 def _setter_lines(self, ri, member, presence): 786 786 # For multi-attr we have a count, not presence, hack up the presence 787 - presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name 787 + presence = presence[:-(len('_count.') + len(self.c_name))] + "n_" + self.c_name 788 788 return [f"{member} = {self.c_name};", 789 789 f"{presence} = n_{self.c_name};"] 790 790 ··· 2186 2186 ri.cw.p(ri.fixed_hdr + ' _hdr;') 2187 2187 ri.cw.nl() 2188 2188 2189 - meta_started = False 2190 - for _, attr in struct.member_list(): 2191 - for type_filter in ['len', 'present']: 2189 + for type_filter in ['present', 'len']: 2190 + meta_started = False 2191 + for _, attr in struct.member_list(): 2192 2192 line = attr.presence_member(ri.ku_space, type_filter) 2193 2193 if line: 2194 2194 if not meta_started: 2195 2195 ri.cw.block_start(line=f"struct") 2196 2196 meta_started = True 2197 2197 ri.cw.p(line) 2198 - if meta_started: 2199 - ri.cw.block_end(line='_present;') 2200 - ri.cw.nl() 2198 + if meta_started: 2199 + ri.cw.block_end(line=f'_{type_filter};') 2200 + ri.cw.nl() 2201 2201 2202 2202 for arg in struct.inherited: 2203 2203 ri.cw.p(f"__u32 {arg};")
+1 -1
tools/net/ynl/samples/devlink.c
··· 34 34 if (!info_rsp) 35 35 goto err_free_devs; 36 36 37 - if (info_rsp->_present.info_driver_name_len) 37 + if (info_rsp->_len.info_driver_name) 38 38 printf(" driver: %s\n", info_rsp->info_driver_name); 39 39 if (info_rsp->n_info_version_running) 40 40 printf(" running fw:\n");
+2 -2
tools/net/ynl/samples/rt-addr.c
··· 20 20 if (name) 21 21 printf("%16s: ", name); 22 22 23 - switch (a->_present.address_len) { 23 + switch (a->_len.address) { 24 24 case 4: 25 25 addr = inet_ntop(AF_INET, a->address, 26 26 addr_str, sizeof(addr_str)); ··· 36 36 if (addr) 37 37 printf("%s", addr); 38 38 else 39 - printf("[%d]", a->_present.address_len); 39 + printf("[%d]", a->_len.address); 40 40 41 41 printf("\n"); 42 42 }
+2 -2
tools/net/ynl/samples/rt-route.c
··· 26 26 printf("oif: %-16s ", name); 27 27 } 28 28 29 - if (r->_present.dst_len) { 29 + if (r->_len.dst) { 30 30 route = inet_ntop(r->_hdr.rtm_family, r->dst, 31 31 route_str, sizeof(route_str)); 32 32 printf("dst: %s/%d", route, r->_hdr.rtm_dst_len); 33 33 } 34 34 35 - if (r->_present.gateway_len) { 35 + if (r->_len.gateway) { 36 36 route = inet_ntop(r->_hdr.rtm_family, r->gateway, 37 37 route_str, sizeof(route_str)); 38 38 printf("gateway: %s ", route);