Skip to content

Commit 3456084

Browse files
kuba-mooPaolo Abeni
authored andcommitted
tools: ynl-gen: mutli-attr: support binary types with struct
Binary types with struct are fixed size, relatively easy to handle for multi attr. Declare the member as a pointer. Count the members, allocate an array, copy in the data. Allow the netlink attr to be smaller or larger than our view of the struct in case the build headers are newer or older than the running kernel. 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-9-kuba@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 0ea8cf5 commit 3456084

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

tools/net/ynl/pyynl/ynl_gen_c.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,8 @@ def presence_type(self):
640640
def _complex_member_type(self, ri):
641641
if 'type' not in self.attr or self.attr['type'] == 'nest':
642642
return self.nested_struct_type
643+
elif self.attr['type'] == 'binary' and 'struct' in self.attr:
644+
return None # use arg_member()
643645
elif self.attr['type'] == 'string':
644646
return 'struct ynl_string *'
645647
elif self.attr['type'] in scalars:
@@ -648,13 +650,21 @@ def _complex_member_type(self, ri):
648650
else:
649651
raise Exception(f"Sub-type {self.attr['type']} not supported yet")
650652

653+
def arg_member(self, ri):
654+
if self.type == 'binary' and 'struct' in self.attr:
655+
return [f'struct {c_lower(self.attr["struct"])} *{self.c_name}',
656+
f'unsigned int n_{self.c_name}']
657+
return super().arg_member(ri)
658+
651659
def free_needs_iter(self):
652660
return self.attr['type'] in {'nest', 'string'}
653661

654662
def _free_lines(self, ri, var, ref):
655663
lines = []
656664
if self.attr['type'] in scalars:
657665
lines += [f"free({var}->{ref}{self.c_name});"]
666+
elif self.attr['type'] == 'binary' and 'struct' in self.attr:
667+
lines += [f"free({var}->{ref}{self.c_name});"]
658668
elif self.attr['type'] == 'string':
659669
lines += [
660670
f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)",
@@ -685,6 +695,9 @@ def attr_put(self, ri, var):
685695
put_type = self.type
686696
ri.cw.p(f"for (i = 0; i < {var}->n_{self.c_name}; i++)")
687697
ri.cw.p(f"ynl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
698+
elif self.attr['type'] == 'binary' and 'struct' in self.attr:
699+
ri.cw.p(f"for (i = 0; i < {var}->n_{self.c_name}; i++)")
700+
ri.cw.p(f"ynl_attr_put(nlh, {self.enum_name}, &{var}->{self.c_name}[i], sizeof(struct {c_lower(self.attr['struct'])}));")
688701
elif self.attr['type'] == 'string':
689702
ri.cw.p(f"for (i = 0; i < {var}->n_{self.c_name}; i++)")
690703
ri.cw.p(f"ynl_attr_put_str(nlh, {self.enum_name}, {var}->{self.c_name}[i]->str);")
@@ -1847,6 +1860,12 @@ def _multi_parse(ri, struct, init_lines, local_vars):
18471860
ri.cw.p('return YNL_PARSE_CB_ERROR;')
18481861
elif aspec.type in scalars:
18491862
ri.cw.p(f"dst->{aspec.c_name}[i] = ynl_attr_get_{aspec.type}(attr);")
1863+
elif aspec.type == 'binary' and 'struct' in aspec:
1864+
ri.cw.p('size_t len = ynl_attr_data_len(attr);')
1865+
ri.cw.nl()
1866+
ri.cw.p(f'if (len > sizeof(dst->{aspec.c_name}[0]))')
1867+
ri.cw.p(f'len = sizeof(dst->{aspec.c_name}[0]);')
1868+
ri.cw.p(f"memcpy(&dst->{aspec.c_name}[i], ynl_attr_data(attr), len);")
18501869
elif aspec.type == 'string':
18511870
ri.cw.p('unsigned int len;')
18521871
ri.cw.nl()

0 commit comments

Comments
 (0)