tools: ynl-gen: split presence metadata
authorJakub Kicinski <kuba@kernel.org>
Mon, 5 May 2025 16:52:06 +0000 (09:52 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 8 May 2025 01:21:25 +0000 (18:21 -0700)
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>
tools/net/ynl/pyynl/ynl_gen_c.py
tools/net/ynl/samples/devlink.c
tools/net/ynl/samples/rt-addr.c
tools/net/ynl/samples/rt-route.c

index 19d8a46895f68a6d69bdf2552497ea8fefb05eaf..e761a20cc53fd0d0c3d44757eba0876add87186b 100755 (executable)
@@ -154,7 +154,7 @@ class Type(SpecAttr):
 
         if self.presence_type() == 'len':
             pfx = '__' if space == 'user' else ''
-            return f"{pfx}u32 {self.c_name}_len;"
+            return f"{pfx}u32 {self.c_name};"
 
     def _complex_member_type(self, ri):
         return None
@@ -217,10 +217,9 @@ class Type(SpecAttr):
         cw.p(f'[{self.enum_name}] = {"{"} .name = "{self.name}", {typol}{"}"},')
 
     def _attr_put_line(self, ri, var, line):
-        if self.presence_type() == 'present':
-            ri.cw.p(f"if ({var}->_present.{self.c_name})")
-        elif self.presence_type() == 'len':
-            ri.cw.p(f"if ({var}->_present.{self.c_name}_len)")
+        presence = self.presence_type()
+        if presence in {'present', 'len'}:
+            ri.cw.p(f"if ({var}->_{presence}.{self.c_name})")
         ri.cw.p(f"{line};")
 
     def _attr_put_simple(self, ri, var, put_type):
@@ -282,6 +281,7 @@ class Type(SpecAttr):
             # Every layer below last is a nest, so we know it uses bit presence
             # last layer is "self" and may be a complex type
             if i == len(ref) - 1 and self.presence_type() != 'present':
+                presence = f"{var}->{'.'.join(ref[:i] + [''])}_{self.presence_type()}.{ref[i]}"
                 continue
             code.append(presence + ' = 1;')
         ref_path = '.'.join(ref[:-1])
@@ -501,7 +501,7 @@ class TypeString(Type):
         self._attr_put_simple(ri, var, 'str')
 
     def _attr_get(self, ri, var):
-        len_mem = var + '->_present.' + self.c_name + '_len'
+        len_mem = var + '->_len.' + self.c_name
         return [f"{len_mem} = len;",
                 f"{var}->{self.c_name} = malloc(len + 1);",
                 f"memcpy({var}->{self.c_name}, ynl_attr_get_str(attr), len);",
@@ -510,10 +510,10 @@ class TypeString(Type):
                ['unsigned int len;']
 
     def _setter_lines(self, ri, member, presence):
-        return [f"{presence}_len = strlen({self.c_name});",
-                f"{member} = malloc({presence}_len + 1);",
-                f'memcpy({member}, {self.c_name}, {presence}_len);',
-                f'{member}[{presence}_len] = 0;']
+        return [f"{presence} = strlen({self.c_name});",
+                f"{member} = malloc({presence} + 1);",
+                f'memcpy({member}, {self.c_name}, {presence});',
+                f'{member}[{presence}] = 0;']
 
 
 class TypeBinary(Type):
@@ -552,10 +552,10 @@ class TypeBinary(Type):
 
     def attr_put(self, ri, var):
         self._attr_put_line(ri, var, f"ynl_attr_put(nlh, {self.enum_name}, " +
-                            f"{var}->{self.c_name}, {var}->_present.{self.c_name}_len)")
+                            f"{var}->{self.c_name}, {var}->_len.{self.c_name})")
 
     def _attr_get(self, ri, var):
-        len_mem = var + '->_present.' + self.c_name + '_len'
+        len_mem = var + '->_len.' + self.c_name
         return [f"{len_mem} = len;",
                 f"{var}->{self.c_name} = malloc(len);",
                 f"memcpy({var}->{self.c_name}, ynl_attr_data(attr), len);"], \
@@ -563,9 +563,9 @@ class TypeBinary(Type):
                ['unsigned int len;']
 
     def _setter_lines(self, ri, member, presence):
-        return [f"{presence}_len = len;",
-                f"{member} = malloc({presence}_len);",
-                f'memcpy({member}, {self.c_name}, {presence}_len);']
+        return [f"{presence} = len;",
+                f"{member} = malloc({presence});",
+                f'memcpy({member}, {self.c_name}, {presence});']
 
 
 class TypeBitfield32(Type):
@@ -721,7 +721,7 @@ class TypeMultiAttr(Type):
 
     def _setter_lines(self, ri, member, presence):
         # For multi-attr we have a count, not presence, hack up the presence
-        presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name
+        presence = presence[:-(len('_count.') + len(self.c_name))] + "n_" + self.c_name
         return [f"{member} = {self.c_name};",
                 f"{presence} = n_{self.c_name};"]
 
@@ -784,7 +784,7 @@ class TypeArrayNest(Type):
 
     def _setter_lines(self, ri, member, presence):
         # For multi-attr we have a count, not presence, hack up the presence
-        presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name
+        presence = presence[:-(len('_count.') + len(self.c_name))] + "n_" + self.c_name
         return [f"{member} = {self.c_name};",
                 f"{presence} = n_{self.c_name};"]
 
@@ -2186,18 +2186,18 @@ def _print_type(ri, direction, struct):
         ri.cw.p(ri.fixed_hdr + ' _hdr;')
         ri.cw.nl()
 
-    meta_started = False
-    for _, attr in struct.member_list():
-        for type_filter in ['len', 'present']:
+    for type_filter in ['present', 'len']:
+        meta_started = False
+        for _, attr in struct.member_list():
             line = attr.presence_member(ri.ku_space, type_filter)
             if line:
                 if not meta_started:
                     ri.cw.block_start(line=f"struct")
                     meta_started = True
                 ri.cw.p(line)
-    if meta_started:
-        ri.cw.block_end(line='_present;')
-        ri.cw.nl()
+        if meta_started:
+            ri.cw.block_end(line=f'_{type_filter};')
+    ri.cw.nl()
 
     for arg in struct.inherited:
         ri.cw.p(f"__u32 {arg};")
index d2611d7ebab45cb7a81bfbe8e75b393184483b3d..3d32a6335044336985f16a8fc660a2855b908933 100644 (file)
@@ -34,7 +34,7 @@ int main(int argc, char **argv)
                if (!info_rsp)
                        goto err_free_devs;
 
-               if (info_rsp->_present.info_driver_name_len)
+               if (info_rsp->_len.info_driver_name)
                        printf("    driver: %s\n", info_rsp->info_driver_name);
                if (info_rsp->n_info_version_running)
                        printf("    running fw:\n");
index 0f4851b4ec57bfef40a7be3c8973f734d3c3506f..2edde5c36b185936114d950e3f9af001f1878fe6 100644 (file)
@@ -20,7 +20,7 @@ static void rt_addr_print(struct rt_addr_getaddr_rsp *a)
        if (name)
                printf("%16s: ", name);
 
-       switch (a->_present.address_len) {
+       switch (a->_len.address) {
        case 4:
                addr = inet_ntop(AF_INET, a->address,
                                 addr_str, sizeof(addr_str));
@@ -36,7 +36,7 @@ static void rt_addr_print(struct rt_addr_getaddr_rsp *a)
        if (addr)
                printf("%s", addr);
        else
-               printf("[%d]", a->_present.address_len);
+               printf("[%d]", a->_len.address);
 
        printf("\n");
 }
index 9d9c868f88733ece11e3745e2ea9f057f96a0aa9..7427104a96df689aeca2d88d9f5a929825668316 100644 (file)
@@ -26,13 +26,13 @@ static void rt_route_print(struct rt_route_getroute_rsp *r)
                        printf("oif: %-16s ", name);
        }
 
-       if (r->_present.dst_len) {
+       if (r->_len.dst) {
                route = inet_ntop(r->_hdr.rtm_family, r->dst,
                                  route_str, sizeof(route_str));
                printf("dst: %s/%d", route, r->_hdr.rtm_dst_len);
        }
 
-       if (r->_present.gateway_len) {
+       if (r->_len.gateway) {
                route = inet_ntop(r->_hdr.rtm_family, r->gateway,
                                  route_str, sizeof(route_str));
                printf("gateway: %s ", route);