From 0b93bf14cefac61cf925a3a405f569085dfa889d Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 14 Oct 2026 12:14:02 +0200 Subject: [PATCH 1/2] ns: remove obsolete conntrack module loading The modprobe logic was inherited from libnetwork, where it was added for conntrack support in [moby/libnetwork@ac1e2ea]. IPVS does not use this functionality, and loading kernel modules is not necessary for detecting supported netlink families. Remove the module loading and retain socket-based capability detection for NETLINK_XFRM and NETLINK_NETFILTER. Also remove the associated warnings for unavailable optional features. [moby/libnetwork@ac1e2ea]: https://github.com/moby/libnetwork/commit/ac1e2ea6b8e2b3ead93f9a77f5bd292ac8494e8d Signed-off-by: Sebastiaan van Stijn --- ns/init_linux.go | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/ns/init_linux.go b/ns/init_linux.go index 1296c1f..2e4dcf9 100644 --- a/ns/init_linux.go +++ b/ns/init_linux.go @@ -3,8 +3,6 @@ package ns import ( "fmt" "os" - "os/exec" - "strings" "sync" "time" @@ -76,20 +74,11 @@ func NlHandle() *netlink.Handle { func getSupportedNlFamilies() []int { fams := []int{unix.NETLINK_ROUTE} - // NETLINK_XFRM test - if err := checkXfrmSocket(); err != nil { - logrus.Warnf("Could not load necessary modules for IPSEC rules: %v", err) - } else { + + if err := checkXfrmSocket(); err == nil { fams = append(fams, unix.NETLINK_XFRM) } - // NETLINK_NETFILTER test - if err := loadNfConntrackModules(); err != nil { - if checkNfSocket() != nil { - logrus.Warnf("Could not load necessary modules for Conntrack: %v", err) - } else { - fams = append(fams, unix.NETLINK_NETFILTER) - } - } else { + if err := checkNfSocket(); err == nil { fams = append(fams, unix.NETLINK_NETFILTER) } @@ -105,16 +94,6 @@ func checkXfrmSocket() error { return unix.Close(fd) } -func loadNfConntrackModules() error { - if out, err := exec.Command("modprobe", "-va", "nf_conntrack").CombinedOutput(); err != nil { - return fmt.Errorf("running modprobe nf_conntrack failed with message: `%s`, error: %w", strings.TrimSpace(string(out)), err) - } - if out, err := exec.Command("modprobe", "-va", "nf_conntrack_netlink").CombinedOutput(); err != nil { - return fmt.Errorf("running modprobe nf_conntrack_netlink failed with message: `%s`, error: %w", strings.TrimSpace(string(out)), err) - } - return nil -} - // API check on required nf_conntrack* modules (nf_conntrack, nf_conntrack_netlink) func checkNfSocket() error { fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_NETFILTER) From fe1271f6684c7e0f598fa1ff3f9d6d6627b6ff33 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 14 Oct 2026 12:23:17 +0200 Subject: [PATCH 2/2] ns: simplify initialization and remove logging Replace the manually managed sync.Once and global handles with sync.OnceValue to ensure initialization only happens once, including when Init is called directly. Preserve initialization errors internally so SetNamespace can return them, while keeping the existing exported API unchanged. Avoid using partially initialized handles, clean up on failure, and remove the logrus dependency from the package. Signed-off-by: Sebastiaan van Stijn --- ns/init_linux.go | 64 ++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/ns/init_linux.go b/ns/init_linux.go index 2e4dcf9..731d415 100644 --- a/ns/init_linux.go +++ b/ns/init_linux.go @@ -6,60 +6,66 @@ import ( "sync" "time" - "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" "golang.org/x/sys/unix" ) -var ( - initNs netns.NsHandle - initNl *netlink.Handle - initOnce sync.Once -) - // NetlinkSocketsTimeout represents the default timeout duration for the sockets const NetlinkSocketsTimeout = 3 * time.Second -// Init initializes a new network namespace +// Init initializes the initial network namespace handles. func Init() { - var err error - initNs, err = netns.Get() + _, _ = initHandles() +} + +type handles struct { + ns netns.NsHandle + nl *netlink.Handle +} + +var initHandles = sync.OnceValues(func() (handles, error) { + ns, err := netns.Get() if err != nil { - logrus.Errorf("could not get initial namespace: %v", err) + return handles{}, fmt.Errorf("get initial namespace: %w", err) } - initNl, err = netlink.NewHandle(getSupportedNlFamilies()...) + + nl, err := netlink.NewHandle(getSupportedNlFamilies()...) if err != nil { - logrus.Errorf("could not create netlink handle on initial namespace: %v", err) + _ = ns.Close() + return handles{}, fmt.Errorf("create netlink handle: %w", err) } - err = initNl.SetSocketTimeout(NetlinkSocketsTimeout) - if err != nil { - logrus.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err) + + if err := nl.SetSocketTimeout(NetlinkSocketsTimeout); err != nil { + nl.Close() + _ = ns.Close() + return handles{}, fmt.Errorf("set netlink socket timeout: %w", err) } -} + + return handles{ns: ns, nl: nl}, nil +}) // SetNamespace sets the initial namespace handler func SetNamespace() error { - initOnce.Do(Init) - if err := netns.Set(initNs); err != nil { + h, err := initHandles() + if err != nil { + return fmt.Errorf("initialize namespace: %w", err) + } + + if err := netns.Set(h.ns); err != nil { linkInfo, linkErr := getLink() if linkErr != nil { linkInfo = linkErr.Error() } - return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %w", linkInfo, initNs, err) + return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %w", linkInfo, h.ns, err) } return nil } // ParseHandlerInt transforms the namespace handler into an integer func ParseHandlerInt() int { - return int(getHandler()) -} - -// GetHandler returns the namespace handler -func getHandler() netns.NsHandle { - initOnce.Do(Init) - return initNs + h, _ := initHandles() + return int(h.ns) } func getLink() (string, error) { @@ -68,8 +74,8 @@ func getLink() (string, error) { // NlHandle returns the netlink handler func NlHandle() *netlink.Handle { - initOnce.Do(Init) - return initNl + h, _ := initHandles() + return h.nl } func getSupportedNlFamilies() []int {