From 5e7f0099869dc8a18da163fdc82c0e7662e7c9aa Mon Sep 17 00:00:00 2001 From: Ale Paredes <1709578+ale7714@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:32:51 -0500 Subject: [PATCH 1/3] Add disabale wifi power save option --- subsystems/provisioning/definitions.go | 3 ++ subsystems/provisioning/provisioning.go | 39 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/subsystems/provisioning/definitions.go b/subsystems/provisioning/definitions.go index 4141f720..87923453 100644 --- a/subsystems/provisioning/definitions.go +++ b/subsystems/provisioning/definitions.go @@ -365,6 +365,9 @@ type Config struct { // Computed from HotspotPrefix and Manufacturer hotspotSSID string + + // When true, it will disable power save for all wifi connections managed by NetworkManager. + DisableWifiPowerSave *bool `json:"disable_wifi_power_save"` } // Timeout allows parsing golang-style durations (1h20m30s) OR seconds-as-float from/to json. diff --git a/subsystems/provisioning/provisioning.go b/subsystems/provisioning/provisioning.go index 7d7367f7..029257a3 100644 --- a/subsystems/provisioning/provisioning.go +++ b/subsystems/provisioning/provisioning.go @@ -21,6 +21,14 @@ import ( "google.golang.org/grpc" ) +const ( + wifiPowerSaveFilepath = "/etc/NetworkManager/conf.d/wifi-powersave.conf" + + wifiPowerSaveContentsDefault = "[connection]\n# Do not modify existing setting\nwifi.powersave = 1" + wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2" + wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3" +) + func init() { registry.Register(SubsysName, NewProvisioning) } @@ -230,6 +238,10 @@ func (w *Provisioning) Start(ctx context.Context) error { } } + if err := w.writeWifiPowerSave(); err != nil { + w.logger.Error(errw.Wrap(err, "error applying wifi power save configuration")) + } + w.processAdditionalnetworks(ctx) if err := w.checkOnline(true); err != nil { @@ -375,3 +387,30 @@ func (w *Provisioning) updateHotspotSSID(cfg *Config) { cfg.hotspotSSID = cfg.hotspotSSID[:32] } } + +func (w *Provisioning) writeWifiPowerSave() error { + contents := wifiPowerSaveContentsDefault + + if w.cfg.DisableWifiPowerSave != nil && *w.cfg.DisableWifiPowerSave { + contents = wifiPowerSaveContentsDisable + } + + if w.cfg.DisableWifiPowerSave != nil && !*w.cfg.DisableWifiPowerSave { + contents = wifiPowerSaveContentsEnable + } + + isNew, err := agent.WriteFileIfNew(wifiPowerSaveFilepath, []byte(contents)) + if err != nil { + return errw.Wrap(err, "error writing wifi-powersave.conf") + } + + if isNew { + w.logger.Infof("Updated %s to: %q", wifiPowerSaveFilepath, contents) + // Reload NetworkManager to apply changes + if err := w.nm.Reload(0); err != nil { + return errw.Wrap(err, "error reloading NetworkManager after wifi-powersave.conf update") + } + } + + return nil +} From 16c1aba5019c545d89914e72aee525d8afa0cceb Mon Sep 17 00:00:00 2001 From: James Otting Date: Wed, 20 Nov 2024 15:49:30 -0500 Subject: [PATCH 2/3] Reactivate connection on powersave change, misc cleanup. (#45) --- subsystems/provisioning/definitions.go | 8 +++-- subsystems/provisioning/grpc.go | 2 +- subsystems/provisioning/networkmanager.go | 4 +-- subsystems/provisioning/portal.go | 6 ++-- subsystems/provisioning/provisioning.go | 43 +++++++++++------------ subsystems/provisioning/scanning.go | 2 +- subsystems/provisioning/setup.go | 14 ++++---- 7 files changed, 41 insertions(+), 38 deletions(-) diff --git a/subsystems/provisioning/definitions.go b/subsystems/provisioning/definitions.go index 87923453..67bafb44 100644 --- a/subsystems/provisioning/definitions.go +++ b/subsystems/provisioning/definitions.go @@ -29,6 +29,10 @@ const ( ConnCheckFilepath = "/etc/NetworkManager/conf.d/80-viam.conf" ConnCheckContents = "[connectivity]\nuri=http://packages.viam.com/check_network_status.txt\ninterval=300\n" + wifiPowerSaveFilepath = "/etc/NetworkManager/conf.d/81-viam-wifi-powersave.conf" + wifiPowerSaveContentsDefault = "# This file intentionally left blank.\n" + wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2\n" + wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3\n" NetworkTypeWifi = "wifi" NetworkTypeWired = "wired" NetworkTypeHotspot = "hotspot" @@ -366,8 +370,8 @@ type Config struct { // Computed from HotspotPrefix and Manufacturer hotspotSSID string - // When true, it will disable power save for all wifi connections managed by NetworkManager. - DisableWifiPowerSave *bool `json:"disable_wifi_power_save"` + // If set, will explicitly enable or disable power save for all wifi connections managed by NetworkManager. + WifiPowerSave *bool `json:"wifi_power_save"` } // Timeout allows parsing golang-style durations (1h20m30s) OR seconds-as-float from/to json. diff --git a/subsystems/provisioning/grpc.go b/subsystems/provisioning/grpc.go index d408cb17..5aee5ef3 100644 --- a/subsystems/provisioning/grpc.go +++ b/subsystems/provisioning/grpc.go @@ -16,7 +16,7 @@ func (w *Provisioning) startGRPC() error { bind := PortalBindAddr + ":4772" lis, err := net.Listen("tcp", bind) if err != nil { - return errw.Wrapf(err, "error listening on: %s", bind) + return errw.Wrapf(err, "listening on: %s", bind) } w.grpcServer = grpc.NewServer(grpc.WaitForHandlers(true)) diff --git a/subsystems/provisioning/networkmanager.go b/subsystems/provisioning/networkmanager.go index 82f95f85..81683b86 100644 --- a/subsystems/provisioning/networkmanager.go +++ b/subsystems/provisioning/networkmanager.go @@ -175,13 +175,13 @@ func (w *Provisioning) StartProvisioning(ctx context.Context, inputChan chan<- u return err } if err := w.activateConnection(ctx, w.Config().HotspotInterface, w.Config().hotspotSSID); err != nil { - return errw.Wrap(err, "error starting provisioning mode hotspot") + return errw.Wrap(err, "starting provisioning mode hotspot") } // start portal with ssid list and known connections if err := w.startPortal(inputChan); err != nil { err = errors.Join(err, w.deactivateConnection(w.Config().HotspotInterface, w.Config().hotspotSSID)) - return errw.Wrap(err, "could not start web/grpc portal") + return errw.Wrap(err, "starting web/grpc portal") } w.connState.setProvisioning(true) diff --git a/subsystems/provisioning/portal.go b/subsystems/provisioning/portal.go index 996b5525..086a9445 100644 --- a/subsystems/provisioning/portal.go +++ b/subsystems/provisioning/portal.go @@ -35,11 +35,11 @@ func (w *Provisioning) startPortal(inputChan chan<- userInput) error { w.portalData = &portalData{input: &userInput{}, inputChan: inputChan} if err := w.startGRPC(); err != nil { - return errw.Wrap(err, "error starting GRPC service") + return errw.Wrap(err, "starting GRPC service") } if err := w.startWeb(); err != nil { - return errw.Wrap(err, "error starting web portal service") + return errw.Wrap(err, "starting web portal service") } return nil @@ -56,7 +56,7 @@ func (w *Provisioning) startWeb() error { bind := PortalBindAddr + ":80" lis, err := net.Listen("tcp", bind) if err != nil { - return errw.Wrapf(err, "error listening on: %s", bind) + return errw.Wrapf(err, "listening on: %s", bind) } w.portalData.workers.Add(1) diff --git a/subsystems/provisioning/provisioning.go b/subsystems/provisioning/provisioning.go index 029257a3..0e21218b 100644 --- a/subsystems/provisioning/provisioning.go +++ b/subsystems/provisioning/provisioning.go @@ -21,14 +21,6 @@ import ( "google.golang.org/grpc" ) -const ( - wifiPowerSaveFilepath = "/etc/NetworkManager/conf.d/wifi-powersave.conf" - - wifiPowerSaveContentsDefault = "[connection]\n# Do not modify existing setting\nwifi.powersave = 1" - wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2" - wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3" -) - func init() { registry.Register(SubsysName, NewProvisioning) } @@ -172,7 +164,7 @@ func (w *Provisioning) init(ctx context.Context) error { w.updateHotspotSSID(w.cfg) if err := w.writeDNSMasq(); err != nil { - return errw.Wrap(err, "error writing dnsmasq configuration") + return errw.Wrap(err, "writing dnsmasq configuration") } if err := w.testConnCheck(); err != nil { @@ -238,8 +230,8 @@ func (w *Provisioning) Start(ctx context.Context) error { } } - if err := w.writeWifiPowerSave(); err != nil { - w.logger.Error(errw.Wrap(err, "error applying wifi power save configuration")) + if err := w.writeWifiPowerSave(ctx); err != nil { + w.logger.Error(errw.Wrap(err, "applying wifi power save configuration")) } w.processAdditionalnetworks(ctx) @@ -369,7 +361,7 @@ func (w *Provisioning) processAdditionalnetworks(ctx context.Context) { for _, network := range w.cfg.Networks { _, err := w.addOrUpdateConnection(network) if err != nil { - w.logger.Error(errw.Wrapf(err, "error adding network %s", network.SSID)) + w.logger.Error(errw.Wrapf(err, "adding network %s", network.SSID)) continue } if network.Interface != "" { @@ -388,27 +380,34 @@ func (w *Provisioning) updateHotspotSSID(cfg *Config) { } } -func (w *Provisioning) writeWifiPowerSave() error { +// must be run inside dataMu lock. +func (w *Provisioning) writeWifiPowerSave(ctx context.Context) error { contents := wifiPowerSaveContentsDefault - - if w.cfg.DisableWifiPowerSave != nil && *w.cfg.DisableWifiPowerSave { - contents = wifiPowerSaveContentsDisable - } - - if w.cfg.DisableWifiPowerSave != nil && !*w.cfg.DisableWifiPowerSave { - contents = wifiPowerSaveContentsEnable + if w.cfg.WifiPowerSave != nil { + if *w.cfg.WifiPowerSave { + contents = wifiPowerSaveContentsEnable + } else { + contents = wifiPowerSaveContentsDisable + } } isNew, err := agent.WriteFileIfNew(wifiPowerSaveFilepath, []byte(contents)) if err != nil { - return errw.Wrap(err, "error writing wifi-powersave.conf") + return errw.Wrap(err, "writing wifi-powersave.conf") } if isNew { w.logger.Infof("Updated %s to: %q", wifiPowerSaveFilepath, contents) // Reload NetworkManager to apply changes if err := w.nm.Reload(0); err != nil { - return errw.Wrap(err, "error reloading NetworkManager after wifi-powersave.conf update") + return errw.Wrap(err, "reloading NetworkManager after wifi-powersave.conf update") + } + + ssid := w.netState.ActiveSSID(w.cfg.HotspotInterface) + if w.connState.getConnected() && ssid != "" { + if err := w.activateConnection(ctx, w.cfg.HotspotInterface, ssid); err != nil { + return errw.Wrapf(err, "reactivating %s to enforce powersave setting", ssid) + } } } diff --git a/subsystems/provisioning/scanning.go b/subsystems/provisioning/scanning.go index 91226157..c3eaa8ad 100644 --- a/subsystems/provisioning/scanning.go +++ b/subsystems/provisioning/scanning.go @@ -19,7 +19,7 @@ func (w *Provisioning) networkScan(ctx context.Context) error { prevScan, err := wifiDev.GetPropertyLastScan() if err != nil { - return errw.Wrap(err, "error scanning wifi") + return errw.Wrap(err, "scanning wifi") } err = wifiDev.RequestScan() diff --git a/subsystems/provisioning/setup.go b/subsystems/provisioning/setup.go index dda0785a..4fef08a9 100644 --- a/subsystems/provisioning/setup.go +++ b/subsystems/provisioning/setup.go @@ -35,35 +35,35 @@ func (w *Provisioning) writeDNSMasq() error { func (w *Provisioning) testConnCheck() error { connCheckEnabled, err := w.nm.GetPropertyConnectivityCheckEnabled() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check state") + return errw.Wrap(err, "getting NetworkManager connectivity check state") } if !connCheckEnabled { hasConnCheck, err := w.nm.GetPropertyConnectivityCheckAvailable() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check configuration") + return errw.Wrap(err, "getting NetworkManager connectivity check configuration") } if !hasConnCheck { if err := w.writeConnCheck(); err != nil { - return (errw.Wrap(err, "error writing NetworkManager connectivity check configuration")) + return (errw.Wrap(err, "writing NetworkManager connectivity check configuration")) } if err := w.nm.Reload(0); err != nil { - return (errw.Wrap(err, "error reloading NetworkManager")) + return (errw.Wrap(err, "reloading NetworkManager")) } hasConnCheck, err = w.nm.GetPropertyConnectivityCheckAvailable() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check configuration") + return errw.Wrap(err, "getting NetworkManager connectivity check configuration") } if !hasConnCheck { - return errors.New("error configuring NetworkManager connectivity check") + return errors.New("configuring NetworkManager connectivity check") } } connCheckEnabled, err = w.nm.GetPropertyConnectivityCheckEnabled() if err != nil { - return errw.Wrap(err, "error getting NetworkManager connectivity check state") + return errw.Wrap(err, "getting NetworkManager connectivity check state") } if !connCheckEnabled { From ea3299c6d4bf2d9640b00b7b97335aedfbbc58bb Mon Sep 17 00:00:00 2001 From: James Otting Date: Wed, 20 Nov 2024 17:01:14 -0500 Subject: [PATCH 3/3] Lint --- subsystems/provisioning/definitions.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subsystems/provisioning/definitions.go b/subsystems/provisioning/definitions.go index 67bafb44..152d0d2d 100644 --- a/subsystems/provisioning/definitions.go +++ b/subsystems/provisioning/definitions.go @@ -33,9 +33,9 @@ const ( wifiPowerSaveContentsDefault = "# This file intentionally left blank.\n" wifiPowerSaveContentsDisable = "[connection]\n# Explicitly disable\nwifi.powersave = 2\n" wifiPowerSaveContentsEnable = "[connection]\n# Explicitly enable\nwifi.powersave = 3\n" - NetworkTypeWifi = "wifi" - NetworkTypeWired = "wired" - NetworkTypeHotspot = "hotspot" + NetworkTypeWifi = "wifi" + NetworkTypeWired = "wired" + NetworkTypeHotspot = "hotspot" IfNameAny = "any"