Commit 6878eb59 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'tools-ynl-generate-code-for-the-handshake-family'

Jakub Kicinski says:

====================
tools: ynl: generate code for the handshake family

Add necessary features and generate user space C code for serializing
/ deserializing messages of the handshake family.

In addition to basics already present in netdev and fou, handshake
has nested attrs and multi-attr u32.
====================

Link: https://lore.kernel.org/r/20230606194302.919343-1-kuba@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e7214663 7a11f70c
......@@ -9,7 +9,7 @@ endif
TOOL:=../ynl-gen-c.py
GENS:=fou netdev
GENS:=handshake fou netdev
SRCS=$(patsubst %,%-user.c,${GENS})
HDRS=$(patsubst %,%-user.h,${GENS})
OBJS=$(patsubst %,%-user.o,${GENS})
......
This diff is collapsed.
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/handshake.yaml */
/* YNL-GEN user header */
#ifndef _LINUX_HANDSHAKE_GEN_H
#define _LINUX_HANDSHAKE_GEN_H
#include <stdlib.h>
#include <string.h>
#include <linux/types.h>
#include <linux/handshake.h>
struct ynl_sock;
extern const struct ynl_family ynl_handshake_family;
/* Enums */
const char *handshake_op_str(int op);
const char *handshake_handler_class_str(enum handshake_handler_class value);
const char *handshake_msg_type_str(enum handshake_msg_type value);
const char *handshake_auth_str(enum handshake_auth value);
/* Common nested types */
struct handshake_x509 {
struct {
__u32 cert:1;
__u32 privkey:1;
} _present;
__u32 cert;
__u32 privkey;
};
/* ============== HANDSHAKE_CMD_ACCEPT ============== */
/* HANDSHAKE_CMD_ACCEPT - do */
struct handshake_accept_req {
struct {
__u32 handler_class:1;
} _present;
enum handshake_handler_class handler_class;
};
static inline struct handshake_accept_req *handshake_accept_req_alloc(void)
{
return calloc(1, sizeof(struct handshake_accept_req));
}
void handshake_accept_req_free(struct handshake_accept_req *req);
static inline void
handshake_accept_req_set_handler_class(struct handshake_accept_req *req,
enum handshake_handler_class handler_class)
{
req->_present.handler_class = 1;
req->handler_class = handler_class;
}
struct handshake_accept_rsp {
struct {
__u32 sockfd:1;
__u32 message_type:1;
__u32 timeout:1;
__u32 auth_mode:1;
__u32 peername_len;
} _present;
__u32 sockfd;
enum handshake_msg_type message_type;
__u32 timeout;
enum handshake_auth auth_mode;
unsigned int n_peer_identity;
__u32 *peer_identity;
unsigned int n_certificate;
struct handshake_x509 *certificate;
char *peername;
};
void handshake_accept_rsp_free(struct handshake_accept_rsp *rsp);
/*
* Handler retrieves next queued handshake request
*/
struct handshake_accept_rsp *
handshake_accept(struct ynl_sock *ys, struct handshake_accept_req *req);
/* HANDSHAKE_CMD_ACCEPT - notify */
struct handshake_accept_ntf {
__u16 family;
__u8 cmd;
struct ynl_ntf_base_type *next;
void (*free)(struct handshake_accept_ntf *ntf);
struct handshake_accept_rsp obj __attribute__ ((aligned (8)));
};
void handshake_accept_ntf_free(struct handshake_accept_ntf *rsp);
/* ============== HANDSHAKE_CMD_DONE ============== */
/* HANDSHAKE_CMD_DONE - do */
struct handshake_done_req {
struct {
__u32 status:1;
__u32 sockfd:1;
} _present;
__u32 status;
__u32 sockfd;
unsigned int n_remote_auth;
__u32 *remote_auth;
};
static inline struct handshake_done_req *handshake_done_req_alloc(void)
{
return calloc(1, sizeof(struct handshake_done_req));
}
void handshake_done_req_free(struct handshake_done_req *req);
static inline void
handshake_done_req_set_status(struct handshake_done_req *req, __u32 status)
{
req->_present.status = 1;
req->status = status;
}
static inline void
handshake_done_req_set_sockfd(struct handshake_done_req *req, __u32 sockfd)
{
req->_present.sockfd = 1;
req->sockfd = sockfd;
}
static inline void
__handshake_done_req_set_remote_auth(struct handshake_done_req *req,
__u32 *remote_auth,
unsigned int n_remote_auth)
{
free(req->remote_auth);
req->remote_auth = remote_auth;
req->n_remote_auth = n_remote_auth;
}
/*
* Handler reports handshake completion
*/
int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req);
/* --------------- Common notification parsing --------------- */
struct ynl_ntf_base_type *handshake_ntf_parse(struct ynl_sock *ys);
#endif /* _LINUX_HANDSHAKE_GEN_H */
......@@ -94,7 +94,10 @@ class Type(SpecAttr):
def arg_member(self, ri):
member = self._complex_member_type(ri)
if member:
return [member + ' *' + self.c_name]
arg = [member + ' *' + self.c_name]
if self.presence_type() == 'count':
arg += ['unsigned int n_' + self.c_name]
return arg
raise Exception(f"Struct member not implemented for class type {self.type}")
def struct_member(self, ri):
......@@ -188,9 +191,12 @@ class Type(SpecAttr):
code.append(presence + ' = 1;')
code += self._setter_lines(ri, member, presence)
ri.cw.write_func('static inline void',
f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}",
body=code,
func_name = f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}"
free = bool([x for x in code if 'free(' in x])
alloc = bool([x for x in code if 'alloc(' in x])
if free and not alloc:
func_name = '__' + func_name
ri.cw.write_func('static inline void', func_name, body=code,
args=[f'{type_name(ri, direction, deref=deref)} *{var}'] + self.arg_member(ri))
......@@ -444,6 +450,13 @@ class TypeMultiAttr(Type):
def presence_type(self):
return 'count'
def _mnl_type(self):
t = self.type
# mnl does not have a helper for signed types
if t[0] == 's':
t = 'u' + t[1:]
return t
def _complex_member_type(self, ri):
if 'type' not in self.attr or self.attr['type'] == 'nest':
return f"struct {self.nested_render_name}"
......@@ -457,9 +470,14 @@ class TypeMultiAttr(Type):
return 'type' not in self.attr or self.attr['type'] == 'nest'
def free(self, ri, var, ref):
if 'type' not in self.attr or self.attr['type'] == 'nest':
if self.attr['type'] in scalars:
ri.cw.p(f"free({var}->{ref}{self.c_name});")
elif 'type' not in self.attr or self.attr['type'] == 'nest':
ri.cw.p(f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)")
ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);')
ri.cw.p(f"free({var}->{ref}{self.c_name});")
else:
raise Exception(f"Free of MultiAttr sub-type {self.attr['type']} not supported yet")
def _attr_typol(self):
if 'type' not in self.attr or self.attr['type'] == 'nest':
......@@ -470,7 +488,26 @@ class TypeMultiAttr(Type):
raise Exception(f"Sub-type {self.attr['type']} not supported yet")
def _attr_get(self, ri, var):
return f'{var}->n_{self.c_name}++;', None, None
return f'n_{self.c_name}++;', None, None
def attr_put(self, ri, var):
if self.attr['type'] in scalars:
put_type = self._mnl_type()
ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
ri.cw.p(f"mnl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
elif 'type' not in self.attr or self.attr['type'] == 'nest':
ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
self._attr_put_line(ri, var, f"{self.nested_render_name}_put(nlh, " +
f"{self.enum_name}, &{var}->{self.c_name}[i])")
else:
raise Exception(f"Put of MultiAttr sub-type {self.attr['type']} not supported yet")
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
return [f"free({member});",
f"{member} = {self.c_name};",
f"{presence} = n_{self.c_name};"]
class TypeArrayNest(Type):
......@@ -1269,6 +1306,11 @@ def _multi_parse(ri, struct, init_lines, local_vars):
local_vars.append('struct ynl_parse_arg parg;')
init_lines.append('parg.ys = yarg->ys;')
all_multi = array_nests | multi_attrs
for anest in sorted(all_multi):
local_vars.append(f"unsigned int n_{struct[anest].c_name} = 0;")
ri.cw.block_start()
ri.cw.write_func_lvar(local_vars)
......@@ -1279,6 +1321,11 @@ def _multi_parse(ri, struct, init_lines, local_vars):
for arg in struct.inherited:
ri.cw.p(f'dst->{arg} = {arg};')
for anest in sorted(all_multi):
aspec = struct[anest]
ri.cw.p(f"if (dst->{aspec.c_name})")
ri.cw.p(f'return ynl_error_parse(yarg, "attribute already present ({struct.attr_set.name}.{aspec.name})");')
ri.cw.nl()
ri.cw.block_start(line=iter_line)
......@@ -1294,8 +1341,9 @@ def _multi_parse(ri, struct, init_lines, local_vars):
for anest in sorted(array_nests):
aspec = struct[anest]
ri.cw.block_start(line=f"if (dst->n_{aspec.c_name})")
ri.cw.p(f"dst->{aspec.c_name} = calloc(dst->n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
ri.cw.block_start(line=f"if (n_{aspec.c_name})")
ri.cw.p(f"dst->{aspec.c_name} = calloc({aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
ri.cw.p(f"dst->n_{aspec.c_name} = n_{aspec.c_name};")
ri.cw.p('i = 0;')
ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;")
ri.cw.block_start(line=f"mnl_attr_for_each_nested(attr, attr_{aspec.c_name})")
......@@ -1309,8 +1357,9 @@ def _multi_parse(ri, struct, init_lines, local_vars):
for anest in sorted(multi_attrs):
aspec = struct[anest]
ri.cw.block_start(line=f"if (dst->n_{aspec.c_name})")
ri.cw.p(f"dst->{aspec.c_name} = calloc(dst->n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
ri.cw.block_start(line=f"if (n_{aspec.c_name})")
ri.cw.p(f"dst->{aspec.c_name} = calloc(n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
ri.cw.p(f"dst->n_{aspec.c_name} = n_{aspec.c_name};")
ri.cw.p('i = 0;')
if 'nested-attributes' in aspec:
ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment