From 29029bb78f513876665a64072e066db9a18d2241 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Wed, 14 Jan 2026 15:58:22 -0500 Subject: [PATCH] netlink: enumerate existing interfaces at startup The netlink plugin only receives RTM_NEWLINK events for interfaces that appear after the plugin starts. Interfaces that already exist at boot (e.g., virtio-net in QEMU) never generate events, so their conditions like net/eth0/exist were never set. Moving enumeration to PLUGIN_INIT doesn't work because it runs before cond_init(), so the condition filesystem isn't ready yet. Fix by registering an HOOK_SVC_PLUGIN callback that queries existing interfaces and routes. This hook runs during conf_init(), after the condition system is initialized. --- plugins/netlink.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/plugins/netlink.c b/plugins/netlink.c index e647c858..a70b01e8 100644 --- a/plugins/netlink.c +++ b/plugins/netlink.c @@ -406,9 +406,29 @@ static void nl_reconf(void *arg) cond_reassert("net/"); } +/* + * Initial enumeration of existing interfaces and routes. Called from + * HOOK_SVC_PLUGIN which runs after the condition system is initialized. + * Interfaces that exist before finit starts (e.g., virtio-net in QEMU) + * won't generate RTM_NEWLINK events, so we must query for them. + */ +static void nl_enumerate(void *arg) +{ + int sd; + + sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (sd < 0) + return; + + nl_resync_ifaces(sd, 0); + nl_resync_routes(sd, 1); + close(sd); +} + static plugin_t plugin = { .name = __FILE__, - .hook[HOOK_SVC_RECONF] = { .cb = nl_reconf }, + .hook[HOOK_SVC_RECONF] = { .cb = nl_reconf }, + .hook[HOOK_SVC_PLUGIN] = { .cb = nl_enumerate }, .io = { .cb = nl_callback, .flags = PLUGIN_IO_READ,