diff --git a/control/control_plane_core.go b/control/control_plane_core.go index 5c3990b94f..f78a287a86 100644 --- a/control/control_plane_core.go +++ b/control/control_plane_core.go @@ -588,7 +588,9 @@ func (c *controlPlaneCore) setupSkPidMonitor() error { func (c *controlPlaneCore) bindWan(ifname string, autoConfigKernelParameter bool) error { if autoConfigKernelParameter { - SetAcceptLocal(ifname, "1") + if err := sysctl.Set(fmt.Sprintf("net.ipv4.conf.%v.accept_local", ifname), "1", false); err != nil { + return err + } } return c._bindWan(ifname) } diff --git a/control/netns_utils.go b/control/netns_utils.go index a33f5fbf8e..91877abe3e 100644 --- a/control/netns_utils.go +++ b/control/netns_utils.go @@ -140,27 +140,27 @@ func (ns *DaeNetns) setupVeth() (err error) { func (ns *DaeNetns) setupSysctl() (err error) { // sysctl net.ipv4.conf.dae0.rp_filter=0 - if err = SetRpFilter(HostVethName, "0"); err != nil { + if err = sysctl.Set(fmt.Sprintf("net.ipv4.conf.%s.rp_filter", HostVethName), "0", true); err != nil { return fmt.Errorf("failed to set rp_filter for dae0: %v", err) } // sysctl net.ipv4.conf.all.rp_filter=0 - if err = SetRpFilter("all", "0"); err != nil { + if err = sysctl.Set("net.ipv4.conf.all.rp_filter", "0", true); err != nil { return fmt.Errorf("failed to set rp_filter for all: %v", err) } // sysctl net.ipv4.conf.dae0.arp_filter=0 - if err = SetArpFilter(HostVethName, "0"); err != nil { + if err = sysctl.Set(fmt.Sprintf("net.ipv4.conf.%s.arp_filter", HostVethName), "0", true); err != nil { return fmt.Errorf("failed to set arp_filter for dae0: %v", err) } // sysctl net.ipv4.conf.all.arp_filter=0 - if err = SetArpFilter("all", "0"); err != nil { + if err = sysctl.Set("net.ipv4.conf.all.arp_filter", "0", true); err != nil { return fmt.Errorf("failed to set arp_filter for all: %v", err) } // sysctl net.ipv4.conf.dae0.accept_local=1 - if err = SetAcceptLocal(HostVethName, "1"); err != nil { + if err = sysctl.Set(fmt.Sprintf("net.ipv4.conf.%s.accept_local", HostVethName), "1", true); err != nil { return fmt.Errorf("failed to set accept_local for dae0: %v", err) } // sysctl net.ipv6.conf.dae0.disable_ipv6=0 - if err = SetDisableIpv6(HostVethName, "0"); err != nil { + if err = sysctl.Set(fmt.Sprintf("net.ipv6.conf.%s.disable_ipv6", HostVethName), "0", true); err != nil { return fmt.Errorf("failed to set disable_ipv6 for dae0: %v", err) } // sysctl net.ipv6.conf.dae0.forwarding=1 diff --git a/control/sysctl.go b/control/sysctl.go new file mode 100644 index 0000000000..ffd16ea494 --- /dev/null +++ b/control/sysctl.go @@ -0,0 +1,90 @@ +package control + +import ( + "os" + "strings" + "sync" + + "github.com/fsnotify/fsnotify" + "github.com/sirupsen/logrus" +) + +const SysctlPrefixPath = "/proc/sys/" + +var sysctl *SysctlManager + +type SysctlManager struct { + mux sync.Mutex + watcher *fsnotify.Watcher + expectations map[string]string +} + +func init() { + var err error + if sysctl, err = NewSysctlManager(); err != nil { + logrus.Fatalf("failed to create sysctl manager: %v", err) + } +} + +func NewSysctlManager() (*SysctlManager, error) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return nil, err + } + + manager := &SysctlManager{ + mux: sync.Mutex{}, + watcher: watcher, + expectations: map[string]string{}, + } + go manager.StartWatch() + return manager, nil +} + +func (s *SysctlManager) StartWatch() { + for { + select { + case event, ok := <-s.watcher.Events: + if !ok { + return + } + if event.Has(fsnotify.Write) { + logrus.Tracef("sysctl write event: %+v", event) + s.mux.Lock() + expected, ok := s.expectations[event.Name] + s.mux.Unlock() + if ok { + raw, err := os.ReadFile(event.Name) + if err != nil { + logrus.Errorf("failed to read sysctl file %s: %v", event.Name, err) + } + value := strings.TrimSpace(string(raw)) + if value != expected { + logrus.Infof("sysctl %s has unexpected value %s, expected %s", event.Name, value, expected) + if err := os.WriteFile(event.Name, []byte(expected), 0644); err != nil { + logrus.Errorf("failed to write sysctl file %s: %v", event.Name, err) + } + } + } + } + case err, ok := <-s.watcher.Errors: + if !ok { + return + } + logrus.Errorf("sysctl watcher error: %v", err) + } + } +} + +func (s *SysctlManager) Set(key string, value string, watch bool) (err error) { + path := SysctlPrefixPath + strings.Replace(key, ".", "/", -1) + if watch { + s.mux.Lock() + s.expectations[path] = value + s.mux.Unlock() + if err = s.watcher.Add(path); err != nil { + return + } + } + return os.WriteFile(path, []byte(value), 0644) +} diff --git a/control/utils.go b/control/utils.go index 98888454f4..f0b93d2c38 100644 --- a/control/utils.go +++ b/control/utils.go @@ -128,22 +128,6 @@ func SetForwarding(ifname string, val string) { _ = setForwarding(ifname, consts.IpVersionStr_6, val) } -func SetAcceptLocal(ifname, val string) error { - return os.WriteFile(fmt.Sprintf("/proc/sys/net/ipv4/conf/%s/accept_local", ifname), []byte(val), 0644) -} - -func SetRpFilter(ifname, val string) error { - return os.WriteFile(fmt.Sprintf("/proc/sys/net/ipv4/conf/%s/rp_filter", ifname), []byte(val), 0644) -} - -func SetArpFilter(ifname, val string) error { - return os.WriteFile(fmt.Sprintf("/proc/sys/net/ipv4/conf/%s/arp_filter", ifname), []byte(val), 0644) -} - -func SetDisableIpv6(ifname, val string) error { - return os.WriteFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname), []byte(val), 0644) -} - func checkSendRedirects(ifname string, ipversion consts.IpVersionStr) error { path := fmt.Sprintf("/proc/sys/net/ipv%v/conf/%v/send_redirects", ipversion, ifname) b, err := os.ReadFile(path) diff --git a/go.mod b/go.mod index 365956cabe..604fe8b6f1 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 // indirect github.com/eknkc/basex v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 85bc2952ca..3588dc5bf1 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=