Skip to content

Commit 6ab6e66

Browse files
committed
init: preload networking modules for Ubuntu support
On Ubuntu, hv_netvsc, hv_sock, bridge, and other networking modules are loadable (=m) rather than built-in (=y). The existing ftw()-based load_all_modules() may not resolve them reliably by path alone. Add preload_networking_modules() to load critical modules by name before the general module scan. Also enable KMOD=1 in the default Makefile and improve module load logging with structured messages. Without hv_netvsc: hot-added NICs timeout waiting for sysfs net interface. Without hv_sock: vsock-based entropy and GCS communication fail. Signed-off-by: Jie Chen <jiechen3@microsoft.com>
1 parent 7df9037 commit 6ab6e66

1 file changed

Lines changed: 61 additions & 3 deletions

File tree

init/init.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,50 @@ int reap_until(pid_t until_pid) {
492492
}
493493

494494
#ifdef MODULES
495+
// Preload networking modules that may not be built-in on all distros (e.g., Ubuntu).
496+
// On kernels where these are built-in (=y), the probe call is a harmless no-op.
497+
void preload_networking_modules() {
498+
const char* modules[] = {
499+
"hv_netvsc", // Hyper-V network driver
500+
"hv_sock", // Hyper-V vsocket support
501+
"bridge", // Linux bridge support
502+
"veth", // Virtual ethernet pairs
503+
"nf_conntrack", // Connection tracking for NAT/masquerading
504+
"br_netfilter", // Bridge netfilter for iptables
505+
NULL
506+
};
507+
508+
if (k_ctx == NULL) {
509+
k_ctx = kmod_new(NULL, NULL);
510+
if (k_ctx == NULL) {
511+
dmesgWarn("preload_networking_modules: failed to create kmod context\n");
512+
return;
513+
}
514+
}
515+
516+
kmod_load_resources(k_ctx);
517+
518+
for (int i = 0; modules[i] != NULL; i++) {
519+
struct kmod_module* mod = NULL;
520+
int err = kmod_module_new_from_name(k_ctx, modules[i], &mod);
521+
if (err < 0)
522+
continue;
523+
524+
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_IGNORE_LOADED, NULL, NULL, NULL, NULL);
525+
char msg[256];
526+
const char* status = (err == 0 || err == -EEXIST) ? "ok"
527+
: (err == -ENOENT) ? "not found (may be built-in)"
528+
: "failed";
529+
snprintf(msg, sizeof(msg), "preload module %s: %s (err=%d)\n", modules[i], status, err);
530+
if (err == 0 || err == -EEXIST || err == -ENOENT)
531+
dmesgInfo(msg);
532+
else
533+
dmesgWarn(msg);
534+
535+
kmod_module_unref(mod);
536+
}
537+
}
538+
495539
// load_module gets the module from the absolute path to the module and then
496540
// inserts into the kernel.
497541
int load_module(struct kmod_ctx* ctx, const char* module_path) {
@@ -507,7 +551,8 @@ int load_module(struct kmod_ctx* ctx, const char* module_path) {
507551
return err;
508552
}
509553

510-
err = kmod_module_probe_insert_module(mod, 0, NULL, NULL, NULL, NULL);
554+
// Use probe_insert_module for automatic dependency resolution
555+
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST | KMOD_PROBE_IGNORE_LOADED, NULL, NULL, NULL, NULL);
511556
if (err < 0) {
512557
kmod_module_unref(mod);
513558
return err;
@@ -549,10 +594,14 @@ int parse_tree_entry(const char* fpath, const struct stat* sb, int typeflag) {
549594
// print warning if we fail to load the module, but don't fail fn so
550595
// we keep trying to load the rest of the modules.
551596
result = load_module(k_ctx, fpath);
597+
char msg[512];
552598
if (result != 0) {
553-
warn2("failed to load module", fpath);
599+
snprintf(msg, sizeof(msg), "failed to load module %s (error %d)\n", fpath, result);
600+
dmesgWarn(msg);
601+
} else {
602+
snprintf(msg, sizeof(msg), "loaded module: %s\n", fpath);
603+
dmesgInfo(msg);
554604
}
555-
dmesgInfo(fpath);
556605
return 0;
557606
}
558607

@@ -777,12 +826,21 @@ int main(int argc, char** argv) {
777826
init_network("lo", AF_INET6);
778827

779828
#ifdef MODULES
829+
// Preload networking modules by name before the general ftw()-based scan.
830+
// On Ubuntu, hv_netvsc and hv_sock are loadable (=m) not built-in (=y),
831+
// and load_all_modules() may not resolve them reliably by path alone.
832+
// Without hv_netvsc: hot-added NICs timeout. Without hv_sock: vsock fails.
833+
preload_networking_modules();
834+
780835
#ifdef DEBUG
781836
printf("loading modules\n");
782837
#endif
783838
load_all_modules();
784839
#endif
785840

841+
// Initialize entropy after module loading: on distros where hv_sock is a
842+
// loadable module (e.g., Ubuntu), the vsock transport used by init_entropy
843+
// is not available until the module is loaded above.
786844
if (entropy_port != 0) {
787845
init_entropy(entropy_port);
788846
}

0 commit comments

Comments
 (0)