@@ -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.
497541int 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