This patch adopts netlink policy and command definitions as
generated by ynl-gen, thus completing the conversion to YNL.
Given that the old and new policy is functionally identical, and
just moved to a new file, then it serves to verify that the policy
in the spec in identical to the previous policy code.
The new files are covered by drivers/net/wireguard/ pattern in
MAINTAINERS.
No behavioural changes intended.
Signed-off-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
---
drivers/net/wireguard/Makefile | 1 +
drivers/net/wireguard/netlink.c | 64 +++---------------------
drivers/net/wireguard/netlink_gen.c | 77 +++++++++++++++++++++++++++++
drivers/net/wireguard/netlink_gen.h | 29 +++++++++++
4 files changed, 114 insertions(+), 57 deletions(-)
create mode 100644 drivers/net/wireguard/netlink_gen.c
create mode 100644 drivers/net/wireguard/netlink_gen.h
diff --git a/drivers/net/wireguard/Makefile b/drivers/net/wireguard/Makefile
index dbe1f8514efc..ae4b479cddbd 100644
--- a/drivers/net/wireguard/Makefile
+++ b/drivers/net/wireguard/Makefile
@@ -14,4 +14,5 @@ wireguard-y += allowedips.o
wireguard-y += ratelimiter.o
wireguard-y += cookie.o
wireguard-y += netlink.o
+wireguard-y += netlink_gen.o
obj-$(CONFIG_WIREGUARD) := wireguard.o
diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c
index ff1549fe55e2..6a7e522e3a78 100644
--- a/drivers/net/wireguard/netlink.c
+++ b/drivers/net/wireguard/netlink.c
@@ -9,6 +9,7 @@
#include "socket.h"
#include "queueing.h"
#include "messages.h"
+#include "netlink_gen.h"
#include <uapi/linux/wireguard.h>
@@ -18,39 +19,6 @@
#include <crypto/utils.h>
static struct genl_family genl_family;
-static const struct nla_policy peer_policy[WGPEER_A_MAX + 1];
-static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1];
-
-static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = {
- [WGDEVICE_A_IFINDEX] = { .type = NLA_U32 },
- [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
- [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
- [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
- [WGDEVICE_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
- [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 },
- [WGDEVICE_A_FWMARK] = { .type = NLA_U32 },
- [WGDEVICE_A_PEERS] = NLA_POLICY_NESTED_ARRAY(peer_policy),
-};
-
-static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
- [WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
- [WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
- [WGPEER_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x7),
- [WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(sizeof(struct sockaddr)),
- [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 },
- [WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(sizeof(struct __kernel_timespec)),
- [WGPEER_A_RX_BYTES] = { .type = NLA_U64 },
- [WGPEER_A_TX_BYTES] = { .type = NLA_U64 },
- [WGPEER_A_ALLOWEDIPS] = NLA_POLICY_NESTED_ARRAY(allowedip_policy),
- [WGPEER_A_PROTOCOL_VERSION] = { .type = NLA_U32 }
-};
-
-static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = {
- [WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 },
- [WGALLOWEDIP_A_IPADDR] = NLA_POLICY_MIN_LEN(sizeof(struct in_addr)),
- [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 },
- [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
-};
static struct wg_device *lookup_interface(struct nlattr **attrs,
struct sk_buff *skb)
@@ -199,7 +167,7 @@ get_peer(struct wg_peer *peer, struct sk_buff *skb, struct dump_ctx *ctx)
return -EMSGSIZE;
}
-static int wireguard_nl_get_device_start(struct netlink_callback *cb)
+int wireguard_nl_get_device_start(struct netlink_callback *cb)
{
struct wg_device *wg;
@@ -210,8 +178,8 @@ static int wireguard_nl_get_device_start(struct netlink_callback *cb)
return 0;
}
-static int wireguard_nl_get_device_dumpit(struct sk_buff *skb,
- struct netlink_callback *cb)
+int wireguard_nl_get_device_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb)
{
struct wg_peer *peer, *next_peer_cursor;
struct dump_ctx *ctx = DUMP_CTX(cb);
@@ -305,7 +273,7 @@ static int wireguard_nl_get_device_dumpit(struct sk_buff *skb,
*/
}
-static int wireguard_nl_get_device_done(struct netlink_callback *cb)
+int wireguard_nl_get_device_done(struct netlink_callback *cb)
{
struct dump_ctx *ctx = DUMP_CTX(cb);
@@ -503,8 +471,8 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs)
return ret;
}
-static int wireguard_nl_set_device_doit(struct sk_buff *skb,
- struct genl_info *info)
+int wireguard_nl_set_device_doit(struct sk_buff *skb,
+ struct genl_info *info)
{
struct wg_device *wg = lookup_interface(info->attrs, skb);
u32 flags = 0;
@@ -618,24 +586,6 @@ static int wireguard_nl_set_device_doit(struct sk_buff *skb,
return ret;
}
-static const struct genl_split_ops wireguard_nl_ops[] = {
- {
- .cmd = WG_CMD_GET_DEVICE,
- .start = wireguard_nl_get_device_start,
- .dumpit = wireguard_nl_get_device_dumpit,
- .done = wireguard_nl_get_device_done,
- .policy = device_policy,
- .maxattr = WGDEVICE_A_PEERS,
- .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DUMP,
- }, {
- .cmd = WG_CMD_SET_DEVICE,
- .doit = wireguard_nl_set_device_doit,
- .policy = device_policy,
- .maxattr = WGDEVICE_A_PEERS,
- .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO,
- }
-};
-
static struct genl_family genl_family __ro_after_init = {
.split_ops = wireguard_nl_ops,
.n_split_ops = ARRAY_SIZE(wireguard_nl_ops),
diff --git a/drivers/net/wireguard/netlink_gen.c b/drivers/net/wireguard/netlink_gen.c
new file mode 100644
index 000000000000..f95fa133778f
--- /dev/null
+++ b/drivers/net/wireguard/netlink_gen.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/wireguard.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "netlink_gen.h"
+
+#include <uapi/linux/wireguard.h>
+#include <linux/time_types.h>
+
+/* Common nested types */
+const struct nla_policy wireguard_wgallowedip_nl_policy[WGALLOWEDIP_A_FLAGS + 1] = {
+ [WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16, },
+ [WGALLOWEDIP_A_IPADDR] = NLA_POLICY_MIN_LEN(4),
+ [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8, },
+ [WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
+};
+
+const struct nla_policy wireguard_wgpeer_nl_policy[WGPEER_A_PROTOCOL_VERSION + 1] = {
+ [WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGPEER_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x7),
+ [WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(16),
+ [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16, },
+ [WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(16),
+ [WGPEER_A_RX_BYTES] = { .type = NLA_U64, },
+ [WGPEER_A_TX_BYTES] = { .type = NLA_U64, },
+ [WGPEER_A_ALLOWEDIPS] = NLA_POLICY_NESTED_ARRAY(wireguard_wgallowedip_nl_policy),
+ [WGPEER_A_PROTOCOL_VERSION] = { .type = NLA_U32, },
+};
+
+/* WG_CMD_GET_DEVICE - dump */
+static const struct nla_policy wireguard_get_device_nl_policy[WGDEVICE_A_PEERS + 1] = {
+ [WGDEVICE_A_IFINDEX] = { .type = NLA_U32, },
+ [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = 15, },
+ [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGDEVICE_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
+ [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16, },
+ [WGDEVICE_A_FWMARK] = { .type = NLA_U32, },
+ [WGDEVICE_A_PEERS] = NLA_POLICY_NESTED_ARRAY(wireguard_wgpeer_nl_policy),
+};
+
+/* WG_CMD_SET_DEVICE - do */
+static const struct nla_policy wireguard_set_device_nl_policy[WGDEVICE_A_PEERS + 1] = {
+ [WGDEVICE_A_IFINDEX] = { .type = NLA_U32, },
+ [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = 15, },
+ [WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
+ [WGDEVICE_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
+ [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16, },
+ [WGDEVICE_A_FWMARK] = { .type = NLA_U32, },
+ [WGDEVICE_A_PEERS] = NLA_POLICY_NESTED_ARRAY(wireguard_wgpeer_nl_policy),
+};
+
+/* Ops table for wireguard */
+const struct genl_split_ops wireguard_nl_ops[2] = {
+ {
+ .cmd = WG_CMD_GET_DEVICE,
+ .start = wireguard_nl_get_device_start,
+ .dumpit = wireguard_nl_get_device_dumpit,
+ .done = wireguard_nl_get_device_done,
+ .policy = wireguard_get_device_nl_policy,
+ .maxattr = WGDEVICE_A_PEERS,
+ .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DUMP,
+ },
+ {
+ .cmd = WG_CMD_SET_DEVICE,
+ .doit = wireguard_nl_set_device_doit,
+ .policy = wireguard_set_device_nl_policy,
+ .maxattr = WGDEVICE_A_PEERS,
+ .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+};
diff --git a/drivers/net/wireguard/netlink_gen.h b/drivers/net/wireguard/netlink_gen.h
new file mode 100644
index 000000000000..e635b1f5f0df
--- /dev/null
+++ b/drivers/net/wireguard/netlink_gen.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/wireguard.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_WIREGUARD_GEN_H
+#define _LINUX_WIREGUARD_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/wireguard.h>
+#include <linux/time_types.h>
+
+/* Common nested types */
+extern const struct nla_policy wireguard_wgallowedip_nl_policy[WGALLOWEDIP_A_FLAGS + 1];
+extern const struct nla_policy wireguard_wgpeer_nl_policy[WGPEER_A_PROTOCOL_VERSION + 1];
+
+/* Ops table for wireguard */
+extern const struct genl_split_ops wireguard_nl_ops[2];
+
+int wireguard_nl_get_device_start(struct netlink_callback *cb);
+int wireguard_nl_get_device_done(struct netlink_callback *cb);
+
+int wireguard_nl_get_device_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb);
+int wireguard_nl_set_device_doit(struct sk_buff *skb, struct genl_info *info);
+
+#endif /* _LINUX_WIREGUARD_GEN_H */
--
2.51.0
On Wed, Nov 05, 2025 at 06:32:20PM +0000, Asbjørn Sloth Tønnesen wrote: > drivers/net/wireguard/netlink_gen.c | 77 +++++++++++++++++++++++++++++ > drivers/net/wireguard/netlink_gen.h | 29 +++++++++++ > create mode 100644 drivers/net/wireguard/netlink_gen.c > create mode 100644 drivers/net/wireguard/netlink_gen.h > +#include "netlink_gen.h" > +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) > +/* Do not edit directly, auto-generated from: */ > +/* Documentation/netlink/specs/wireguard.yaml */ > +/* YNL-GEN kernel source */ Similar to what's happening in the tools/ynl/samples build system, instead of statically generating this, can you have this be generated at build time, and placed into a generated/ folder that doesn't get checked into git? I don't see the purpose of having to manually keep this in check? (And if for some reason, you refuse to do that, it'd be very nice if the DO NOT EDIT header of the file also had the command that generated it, in case I need to regenerate it later and can't remember how it was done, because I didn't do it the first time, etc. Go's generated files usually follow this pattern. But anyway, I think I'd prefer, if it's possible, to just have this generated at compile time.) Jason
On 11/18/25 3:15 PM, Jason A. Donenfeld wrote: > On Wed, Nov 05, 2025 at 06:32:20PM +0000, Asbjørn Sloth Tønnesen wrote: >> drivers/net/wireguard/netlink_gen.c | 77 +++++++++++++++++++++++++++++ >> drivers/net/wireguard/netlink_gen.h | 29 +++++++++++ >> create mode 100644 drivers/net/wireguard/netlink_gen.c >> create mode 100644 drivers/net/wireguard/netlink_gen.h >> +#include "netlink_gen.h" >> +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) >> +/* Do not edit directly, auto-generated from: */ >> +/* Documentation/netlink/specs/wireguard.yaml */ >> +/* YNL-GEN kernel source */ > > Similar to what's happening in the tools/ynl/samples build system, > instead of statically generating this, can you have this be generated at > build time, and placed into a generated/ folder that doesn't get checked > into git? I don't see the purpose of having to manually keep this in > check? > > (And if for some reason, you refuse to do that, it'd be very nice if the > DO NOT EDIT header of the file also had the command that generated it, > in case I need to regenerate it later and can't remember how it was > done, because I didn't do it the first time, etc. Go's generated files > usually follow this pattern. > > But anyway, I think I'd prefer, if it's possible, to just have this > generated at compile time.) The main value in having the generated kernel code in git, is that it can't change accidentally, which makes it easy for patchwork to catch if output changes without being a part of the commit. I will leave it up to Donald and Jakub, if they want to allow these files to be generated on-the-fly. Alternatively, the generated files could be put under YNL in MAINTAINERS, so you only maintain the spec, but not the generated output files. I agree that there could be a note in the header about how to re-generate the files, or just a link to the doc: https://docs.kernel.org/userspace-api/netlink/intro-specs.html#generating-kernel-code The easy to use regeneration tool is ynl-regen: ./tools/net/ynl/ynl-regen.sh # skip if output is newer than yaml ./tools/net/ynl/ynl-regen.sh -f # force, when working on ynl ./tools/net/ynl/ynl-regen.sh -p drivers/net/wireguard # run on a subdir
On Tue, Nov 18, 2025 at 10:23:12PM +0000, Asbjørn Sloth Tønnesen wrote: > On 11/18/25 3:15 PM, Jason A. Donenfeld wrote: > > On Wed, Nov 05, 2025 at 06:32:20PM +0000, Asbjørn Sloth Tønnesen wrote: > >> drivers/net/wireguard/netlink_gen.c | 77 +++++++++++++++++++++++++++++ > >> drivers/net/wireguard/netlink_gen.h | 29 +++++++++++ > >> create mode 100644 drivers/net/wireguard/netlink_gen.c > >> create mode 100644 drivers/net/wireguard/netlink_gen.h > >> +#include "netlink_gen.h" > >> +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) > >> +/* Do not edit directly, auto-generated from: */ > >> +/* Documentation/netlink/specs/wireguard.yaml */ > >> +/* YNL-GEN kernel source */ > > > > Similar to what's happening in the tools/ynl/samples build system, > > instead of statically generating this, can you have this be generated at > > build time, and placed into a generated/ folder that doesn't get checked > > into git? I don't see the purpose of having to manually keep this in > > check? > > > > (And if for some reason, you refuse to do that, it'd be very nice if the > > DO NOT EDIT header of the file also had the command that generated it, > > in case I need to regenerate it later and can't remember how it was > > done, because I didn't do it the first time, etc. Go's generated files > > usually follow this pattern. > > > > But anyway, I think I'd prefer, if it's possible, to just have this > > generated at compile time.) > > The main value in having the generated kernel code in git, is that it can't > change accidentally, which makes it easy for patchwork to catch if output > changes without being a part of the commit. > > I will leave it up to Donald and Jakub, if they want to allow these files to > be generated on-the-fly. I mean, there is *tons* of generated code in the kernel. This is how it works. And you *want the output to change when the tool changes*. That's literally the point. It would be like if you wanted to check in all the .o files, in case the compiler started generating different output, or if you wanted the objtool output or anything else to be checked in. And sheerly from a git perspective, it seems outrageous to touch a zillion files every time the ynl code changes. Rather, the fact that it's generated on the fly ensures that the ynl generator stays correctly implemented. It's the best way to keep that code from rotting. Jason
On Tue, 18 Nov 2025 23:51:37 +0100 Jason A. Donenfeld wrote: > I mean, there is *tons* of generated code in the kernel. This is how it > works. And you *want the output to change when the tool changes*. That's > literally the point. It would be like if you wanted to check in all the > .o files, in case the compiler started generating different output, or > if you wanted the objtool output or anything else to be checked in. And > sheerly from a git perspective, it seems outrageous to touch a zillion > files every time the ynl code changes. Rather, the fact that it's > generated on the fly ensures that the ynl generator stays correctly > implemented. It's the best way to keep that code from rotting. CI checks validate that the files are up to date. There has been no churn to the kernel side of the generated code. Let's be practical.
On Tue, Nov 18, 2025 at 05:00:45PM -0800, Jakub Kicinski wrote:
> On Tue, 18 Nov 2025 23:51:37 +0100 Jason A. Donenfeld wrote:
> > I mean, there is *tons* of generated code in the kernel. This is how it
> > works. And you *want the output to change when the tool changes*. That's
> > literally the point. It would be like if you wanted to check in all the
> > .o files, in case the compiler started generating different output, or
> > if you wanted the objtool output or anything else to be checked in. And
> > sheerly from a git perspective, it seems outrageous to touch a zillion
> > files every time the ynl code changes. Rather, the fact that it's
> > generated on the fly ensures that the ynl generator stays correctly
> > implemented. It's the best way to keep that code from rotting.
>
> CI checks validate that the files are up to date.
> There has been no churn to the kernel side of the generated code.
> Let's be practical.
Okay, it sounds like neither of you want to do this. Darn. I really hate
having generated artifacts laying around that can be created efficiently
at compile time. But okay, so it goes. I guess we'll do that.
I would like to ask two things, then, which may or may not be possible:
1) Can we put this in drivers/net/wireguard/generated/netlink.{c.h}
And then in the Makefile, do `wireguard-y += netlink.o generated/netlink.o`
on one line like that. I prefer this to keeping it in the same
directory with the awkward -gen suffix.
2) In the header of each generated file, automatically write out the
command that was used to generate it. Here's an example of this good
habit from Go: https://github.com/golang/go/blob/master/src/syscall/zsyscall_linux_amd64.go
Jason
On 11/20/25 12:54 AM, Jason A. Donenfeld wrote:
> On Tue, Nov 18, 2025 at 05:00:45PM -0800, Jakub Kicinski wrote:
>> On Tue, 18 Nov 2025 23:51:37 +0100 Jason A. Donenfeld wrote:
>>> I mean, there is *tons* of generated code in the kernel. This is how it
>>> works. And you *want the output to change when the tool changes*. That's
>>> literally the point. It would be like if you wanted to check in all the
>>> .o files, in case the compiler started generating different output, or
>>> if you wanted the objtool output or anything else to be checked in. And
>>> sheerly from a git perspective, it seems outrageous to touch a zillion
>>> files every time the ynl code changes. Rather, the fact that it's
>>> generated on the fly ensures that the ynl generator stays correctly
>>> implemented. It's the best way to keep that code from rotting.
>>
>> CI checks validate that the files are up to date.
>> There has been no churn to the kernel side of the generated code.
>> Let's be practical.
>
> Okay, it sounds like neither of you want to do this. Darn. I really hate
> having generated artifacts laying around that can be created efficiently
> at compile time. But okay, so it goes. I guess we'll do that.
I generally agree, but given this generates code across the tree, then I
prefer this, as side-effects are more obvious.
To complete Jakub's earlier argument of not complicating everyone's life,
then this code generator is Python-based and depends on yaml and jsonschema.
Even doing compile-time generation for a single family, would elevate those
packages from developer-dependencies to build-dependencies.
> I would like to ask two things, then, which may or may not be possible:
>
> 1) Can we put this in drivers/net/wireguard/generated/netlink.{c.h}
> And then in the Makefile, do `wireguard-y += netlink.o generated/netlink.o`
> on one line like that. I prefer this to keeping it in the same
> directory with the awkward -gen suffix.
Sure, there isn't much consistency across families anyway.
On Thu, 20 Nov 2025 01:54:47 +0100 Jason A. Donenfeld wrote:
> On Tue, Nov 18, 2025 at 05:00:45PM -0800, Jakub Kicinski wrote:
> > On Tue, 18 Nov 2025 23:51:37 +0100 Jason A. Donenfeld wrote:
> > > I mean, there is *tons* of generated code in the kernel. This is how it
> > > works. And you *want the output to change when the tool changes*. That's
> > > literally the point. It would be like if you wanted to check in all the
> > > .o files, in case the compiler started generating different output, or
> > > if you wanted the objtool output or anything else to be checked in. And
> > > sheerly from a git perspective, it seems outrageous to touch a zillion
> > > files every time the ynl code changes. Rather, the fact that it's
> > > generated on the fly ensures that the ynl generator stays correctly
> > > implemented. It's the best way to keep that code from rotting.
> >
> > CI checks validate that the files are up to date.
> > There has been no churn to the kernel side of the generated code.
> > Let's be practical.
>
> Okay, it sounds like neither of you want to do this. Darn. I really hate
> having generated artifacts laying around that can be created efficiently
> at compile time. But okay, so it goes. I guess we'll do that.
>
> I would like to ask two things, then, which may or may not be possible:
>
> 1) Can we put this in drivers/net/wireguard/generated/netlink.{c.h}
> And then in the Makefile, do `wireguard-y += netlink.o generated/netlink.o`
> on one line like that. I prefer this to keeping it in the same
> directory with the awkward -gen suffix.
That should work, I think.
> 2) In the header of each generated file, automatically write out the
> command that was used to generate it. Here's an example of this good
> habit from Go: https://github.com/golang/go/blob/master/src/syscall/zsyscall_linux_amd64.go
You don't like the runes? :)
/* Do not edit directly, auto-generated from: */
/* $YAML-path */
/* YNL-GEN [kernel|user|uapi] [source|header] */
/* YNL-ARG $extra-args */
Do you care about the exact cmdline of the python tool, or can we just
append:
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
On Thu, Nov 20, 2025 at 3:44 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Thu, 20 Nov 2025 01:54:47 +0100 Jason A. Donenfeld wrote:
> > On Tue, Nov 18, 2025 at 05:00:45PM -0800, Jakub Kicinski wrote:
> > > On Tue, 18 Nov 2025 23:51:37 +0100 Jason A. Donenfeld wrote:
> > > > I mean, there is *tons* of generated code in the kernel. This is how it
> > > > works. And you *want the output to change when the tool changes*. That's
> > > > literally the point. It would be like if you wanted to check in all the
> > > > .o files, in case the compiler started generating different output, or
> > > > if you wanted the objtool output or anything else to be checked in. And
> > > > sheerly from a git perspective, it seems outrageous to touch a zillion
> > > > files every time the ynl code changes. Rather, the fact that it's
> > > > generated on the fly ensures that the ynl generator stays correctly
> > > > implemented. It's the best way to keep that code from rotting.
> > >
> > > CI checks validate that the files are up to date.
> > > There has been no churn to the kernel side of the generated code.
> > > Let's be practical.
> >
> > Okay, it sounds like neither of you want to do this. Darn. I really hate
> > having generated artifacts laying around that can be created efficiently
> > at compile time. But okay, so it goes. I guess we'll do that.
> >
> > I would like to ask two things, then, which may or may not be possible:
> >
> > 1) Can we put this in drivers/net/wireguard/generated/netlink.{c.h}
> > And then in the Makefile, do `wireguard-y += netlink.o generated/netlink.o`
> > on one line like that. I prefer this to keeping it in the same
> > directory with the awkward -gen suffix.
>
> That should work, I think.
>
> > 2) In the header of each generated file, automatically write out the
> > command that was used to generate it. Here's an example of this good
> > habit from Go: https://github.com/golang/go/blob/master/src/syscall/zsyscall_linux_amd64.go
>
> You don't like the runes? :)
>
> /* Do not edit directly, auto-generated from: */
> /* $YAML-path */
> /* YNL-GEN [kernel|user|uapi] [source|header] */
> /* YNL-ARG $extra-args */
>
> Do you care about the exact cmdline of the python tool, or can we just
> append:
>
> /* To regenerate run: tools/net/ynl/ynl-regen.sh */
The args are non-trivial, right? The idea is so that these files can
be regenerated in a few years when the ynl project has widely
succeeded and we've all paged this out of our minds and forgotten how
it all worked.
On Thu, 20 Nov 2025 03:46:39 +0100 Jason A. Donenfeld wrote:
> > Do you care about the exact cmdline of the python tool, or can we just
> > append:
> >
> > /* To regenerate run: tools/net/ynl/ynl-regen.sh */
>
> The args are non-trivial, right?
They aren't all that complicated TBH, quoting slightly modified from
tools/net/ynl/ynl-regen.sh:
$TOOL --mode $mode --$type --spec $KDIR/$yaml_spec $extra_args -o $output
The line just gets quote long for my taste with all the paths in place.
Somewhere along the line we added --cmp-out to make sure output isn't
modified on every regen attempt (for the benefit of incremental builds).
> The idea is so that these files can be regenerated in a few years
> when the ynl project has widely succeeded and we've all paged this
> out of our minds and forgotten how it all worked.
We run ./tools/net/ynl/ynl-regen.sh in our CI, checking if anything
diverged. Primarily because in early days, when codegen was modified
more often, I was worried we'll break the generation for some of the
specs.
The documentation also basically says "create the fake header where
you want the file to be and run ./tools/net/ynl/ynl-regen.sh".
https://docs.kernel.org/userspace-api/netlink/intro-specs.html#generating-kernel-code
Admittedly most of this comes down to "what Jakub found convenient
when developing the specs" :S
On Tue, Nov 18, 2025 at 04:15:20PM +0100, Jason A. Donenfeld wrote: > On Wed, Nov 05, 2025 at 06:32:20PM +0000, Asbjørn Sloth Tønnesen wrote: > > drivers/net/wireguard/netlink_gen.c | 77 +++++++++++++++++++++++++++++ > > drivers/net/wireguard/netlink_gen.h | 29 +++++++++++ > > create mode 100644 drivers/net/wireguard/netlink_gen.c > > create mode 100644 drivers/net/wireguard/netlink_gen.h > > +#include "netlink_gen.h" > > +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) > > +/* Do not edit directly, auto-generated from: */ > > +/* Documentation/netlink/specs/wireguard.yaml */ > > +/* YNL-GEN kernel source */ > > Similar to what's happening in the tools/ynl/samples build system, > instead of statically generating this, can you have this be generated at > build time, and placed into a generated/ folder that doesn't get checked > into git? I don't see the purpose of having to manually keep this in > check? Grep, for example, for PERLASM in the lib/crypto code. There's certainly precedent for doing this.
© 2016 - 2025 Red Hat, Inc.