1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-27 15:02:50 -05:00

network: listen to NM Wired interface + use nmcli for route metrics

- Some other misc floating window change, too lazy to separate the
  commit
This commit is contained in:
bbedward
2026-01-06 16:01:28 -05:00
parent c45eb2cccf
commit c1fbeb3f5e
16 changed files with 285 additions and 188 deletions

View File

@@ -13,6 +13,7 @@ const (
dbusNMPath = "/org/freedesktop/NetworkManager"
dbusNMInterface = "org.freedesktop.NetworkManager"
dbusNMDeviceInterface = "org.freedesktop.NetworkManager.Device"
dbusNMWiredInterface = "org.freedesktop.NetworkManager.Device.Wired"
dbusNMWirelessInterface = "org.freedesktop.NetworkManager.Device.Wireless"
dbusNMAccessPointInterface = "org.freedesktop.NetworkManager.AccessPoint"
dbusPropsInterface = "org.freedesktop.DBus.Properties"

View File

@@ -81,44 +81,24 @@ func (b *NetworkManagerBackend) startSignalPump() error {
return err
}
if b.wifiDevice != nil {
dev := b.wifiDevice.(gonetworkmanager.Device)
for _, info := range b.wifiDevices {
if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
); err != nil {
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
conn.RemoveSignal(signals)
conn.Close()
return err
}
}
if b.ethernetDevice != nil {
dev := b.ethernetDevice.(gonetworkmanager.Device)
for _, info := range b.ethernetDevices {
if err := conn.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
); err != nil {
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
if b.wifiDevice != nil {
dev := b.wifiDevice.(gonetworkmanager.Device)
conn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
}
conn.RemoveSignal(signals)
conn.Close()
return err
@@ -157,19 +137,17 @@ func (b *NetworkManagerBackend) stopSignalPump() {
dbus.WithMatchMember("PropertiesChanged"),
)
if b.wifiDevice != nil {
dev := b.wifiDevice.(gonetworkmanager.Device)
for _, info := range b.wifiDevices {
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
}
if b.ethernetDevice != nil {
dev := b.ethernetDevice.(gonetworkmanager.Device)
for _, info := range b.ethernetDevices {
b.dbusConn.RemoveMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
dbus.WithMatchObjectPath(dbus.ObjectPath(info.device.GetPath())),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
@@ -232,7 +210,10 @@ func (b *NetworkManagerBackend) handleDBusSignal(sig *dbus.Signal) {
b.handleNetworkManagerChange(changes)
case dbusNMDeviceInterface:
b.handleDeviceChange(changes)
b.handleDeviceChange(sig.Path, changes)
case dbusNMWiredInterface:
b.handleWiredChange(changes)
case dbusNMWirelessInterface:
b.handleWiFiChange(changes)
@@ -278,9 +259,10 @@ func (b *NetworkManagerBackend) handleNetworkManagerChange(changes map[string]db
}
}
func (b *NetworkManagerBackend) handleDeviceChange(changes map[string]dbus.Variant) {
func (b *NetworkManagerBackend) handleDeviceChange(devicePath dbus.ObjectPath, changes map[string]dbus.Variant) {
var needsUpdate bool
var stateChanged bool
var managedChanged bool
for key := range changes {
switch key {
@@ -289,21 +271,61 @@ func (b *NetworkManagerBackend) handleDeviceChange(changes map[string]dbus.Varia
needsUpdate = true
case "Ip4Config":
needsUpdate = true
case "Managed":
managedChanged = true
default:
continue
}
}
if needsUpdate {
b.updateEthernetState()
b.updateWiFiState()
if stateChanged {
b.updatePrimaryConnection()
if managedChanged {
if managedVariant, ok := changes["Managed"]; ok {
if managed, ok := managedVariant.Value().(bool); ok && managed {
b.handleDeviceAdded(devicePath)
return
}
}
if b.onStateChange != nil {
b.onStateChange()
}
if !needsUpdate {
return
}
b.updateAllEthernetDevices()
b.updateEthernetState()
b.updateAllWiFiDevices()
b.updateWiFiState()
if stateChanged {
b.listEthernetConnections()
b.updatePrimaryConnection()
}
if b.onStateChange != nil {
b.onStateChange()
}
}
func (b *NetworkManagerBackend) handleWiredChange(changes map[string]dbus.Variant) {
var needsUpdate bool
for key := range changes {
switch key {
case "Carrier", "Speed", "HwAddress":
needsUpdate = true
default:
continue
}
}
if !needsUpdate {
return
}
b.updateAllEthernetDevices()
b.updateEthernetState()
b.updatePrimaryConnection()
if b.onStateChange != nil {
b.onStateChange()
}
}
func (b *NetworkManagerBackend) handleWiFiChange(changes map[string]dbus.Variant) {
@@ -369,6 +391,18 @@ func (b *NetworkManagerBackend) handleDeviceAdded(devicePath dbus.ObjectPath) {
return
}
if devType != gonetworkmanager.NmDeviceTypeEthernet && devType != gonetworkmanager.NmDeviceTypeWifi {
return
}
if b.dbusConn != nil {
b.dbusConn.AddMatchSignal(
dbus.WithMatchObjectPath(devicePath),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
}
managed, _ := dev.GetPropertyManaged()
if !managed {
return
@@ -398,14 +432,6 @@ func (b *NetworkManagerBackend) handleDeviceAdded(devicePath dbus.ObjectPath) {
b.ethernetDevice = dev
}
if b.dbusConn != nil {
b.dbusConn.AddMatchSignal(
dbus.WithMatchObjectPath(devicePath),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
}
b.updateAllEthernetDevices()
b.updateEthernetState()
b.listEthernetConnections()
@@ -430,14 +456,6 @@ func (b *NetworkManagerBackend) handleDeviceAdded(devicePath dbus.ObjectPath) {
b.wifiDev = w
}
if b.dbusConn != nil {
b.dbusConn.AddMatchSignal(
dbus.WithMatchObjectPath(devicePath),
dbus.WithMatchInterface(dbusPropsInterface),
dbus.WithMatchMember("PropertiesChanged"),
)
}
b.updateAllWiFiDevices()
b.updateWiFiState()
}

View File

@@ -159,7 +159,7 @@ func TestNetworkManagerBackend_HandleDeviceChange(t *testing.T) {
}
assert.NotPanics(t, func() {
backend.handleDeviceChange(changes)
backend.handleDeviceChange("/org/freedesktop/NetworkManager/Devices/1", changes)
})
}
@@ -174,7 +174,7 @@ func TestNetworkManagerBackend_HandleDeviceChange_Ip4Config(t *testing.T) {
}
assert.NotPanics(t, func() {
backend.handleDeviceChange(changes)
backend.handleDeviceChange("/org/freedesktop/NetworkManager/Devices/1", changes)
})
}

View File

@@ -2,9 +2,21 @@ package network
import (
"fmt"
"os/exec"
"time"
"github.com/Wifx/gonetworkmanager/v2"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/godbus/dbus/v5"
)
const (
priorityHigh = int32(100)
priorityLow = int32(10)
priorityDefault = int32(0)
metricPreferred = int64(100)
metricNonPreferred = int64(300)
metricDefault = int64(100)
)
func (m *Manager) SetConnectionPreference(pref ConnectionPreference) error {
@@ -36,83 +48,124 @@ func (m *Manager) SetConnectionPreference(pref ConnectionPreference) error {
}
func (m *Manager) prioritizeWiFi() error {
if err := m.setConnectionMetrics("802-11-wireless", 50); err != nil {
return err
if err := m.setConnectionPriority("802-11-wireless", priorityHigh, metricPreferred); err != nil {
log.Warnf("Failed to set WiFi priority: %v", err)
}
if err := m.setConnectionMetrics("802-3-ethernet", 100); err != nil {
return err
if err := m.setConnectionPriority("802-3-ethernet", priorityLow, metricNonPreferred); err != nil {
log.Warnf("Failed to set Ethernet priority: %v", err)
}
m.reapplyActiveConnections()
m.notifySubscribers()
return nil
}
func (m *Manager) prioritizeEthernet() error {
if err := m.setConnectionMetrics("802-3-ethernet", 50); err != nil {
return err
if err := m.setConnectionPriority("802-3-ethernet", priorityHigh, metricPreferred); err != nil {
log.Warnf("Failed to set Ethernet priority: %v", err)
}
if err := m.setConnectionMetrics("802-11-wireless", 100); err != nil {
return err
if err := m.setConnectionPriority("802-11-wireless", priorityLow, metricNonPreferred); err != nil {
log.Warnf("Failed to set WiFi priority: %v", err)
}
m.reapplyActiveConnections()
m.notifySubscribers()
return nil
}
func (m *Manager) balancePriorities() error {
if err := m.setConnectionMetrics("802-3-ethernet", 50); err != nil {
return err
if err := m.setConnectionPriority("802-3-ethernet", priorityDefault, metricDefault); err != nil {
log.Warnf("Failed to reset Ethernet priority: %v", err)
}
if err := m.setConnectionMetrics("802-11-wireless", 50); err != nil {
return err
if err := m.setConnectionPriority("802-11-wireless", priorityDefault, metricDefault); err != nil {
log.Warnf("Failed to reset WiFi priority: %v", err)
}
m.reapplyActiveConnections()
m.notifySubscribers()
return nil
}
func (m *Manager) setConnectionMetrics(connType string, metric uint32) error {
settingsMgr, err := gonetworkmanager.NewSettings()
func (m *Manager) reapplyActiveConnections() {
m.stateMutex.RLock()
ethDev := m.state.EthernetDevice
wifiDev := m.state.WiFiDevice
m.stateMutex.RUnlock()
if ethDev != "" {
exec.Command("nmcli", "dev", "reapply", ethDev).Run()
}
if wifiDev != "" {
exec.Command("nmcli", "dev", "reapply", wifiDev).Run()
}
}
func (m *Manager) setConnectionPriority(connType string, autoconnectPriority int32, routeMetric int64) error {
conn, err := dbus.ConnectSystemBus()
if err != nil {
return fmt.Errorf("failed to get settings: %w", err)
return fmt.Errorf("failed to connect to system bus: %w", err)
}
defer conn.Close()
settingsObj := conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings")
var connPaths []dbus.ObjectPath
if err := settingsObj.Call("org.freedesktop.NetworkManager.Settings.ListConnections", 0).Store(&connPaths); err != nil {
return fmt.Errorf("failed to list connections: %w", err)
}
connections, err := settingsMgr.ListConnections()
if err != nil {
return fmt.Errorf("failed to get connections: %w", err)
}
for _, connPath := range connPaths {
connObj := conn.Object("org.freedesktop.NetworkManager", connPath)
for _, conn := range connections {
connSettings, err := conn.GetSettings()
if err != nil {
var settings map[string]map[string]dbus.Variant
if err := connObj.Call("org.freedesktop.NetworkManager.Settings.Connection.GetSettings", 0).Store(&settings); err != nil {
continue
}
if connMeta, ok := connSettings["connection"]; ok {
if cType, ok := connMeta["type"].(string); ok && cType == connType {
if connSettings["ipv4"] == nil {
connSettings["ipv4"] = make(map[string]any)
}
if ipv4Map := connSettings["ipv4"]; ipv4Map != nil {
ipv4Map["route-metric"] = int64(metric)
}
if connSettings["ipv6"] == nil {
connSettings["ipv6"] = make(map[string]any)
}
if ipv6Map := connSettings["ipv6"]; ipv6Map != nil {
ipv6Map["route-metric"] = int64(metric)
}
err = conn.Update(connSettings)
if err != nil {
continue
}
}
connSection, ok := settings["connection"]
if !ok {
continue
}
typeVariant, ok := connSection["type"]
if !ok {
continue
}
cType, ok := typeVariant.Value().(string)
if !ok || cType != connType {
continue
}
connName := ""
if idVariant, ok := connSection["id"]; ok {
connName, _ = idVariant.Value().(string)
}
if connName == "" {
continue
}
if err := exec.Command("nmcli", "con", "mod", connName,
"connection.autoconnect-priority", fmt.Sprintf("%d", autoconnectPriority)).Run(); err != nil {
log.Warnf("Failed to set autoconnect-priority for %v: %v", connName, err)
continue
}
if err := exec.Command("nmcli", "con", "mod", connName,
"ipv4.route-metric", fmt.Sprintf("%d", routeMetric)).Run(); err != nil {
log.Warnf("Failed to set ipv4.route-metric for %v: %v", connName, err)
}
if err := exec.Command("nmcli", "con", "mod", connName,
"ipv6.route-metric", fmt.Sprintf("%d", routeMetric)).Run(); err != nil {
log.Warnf("Failed to set ipv6.route-metric for %v: %v", connName, err)
}
log.Infof("Updated %v: autoconnect-priority=%d, route-metric=%d", connName, autoconnectPriority, routeMetric)
}
return nil
@@ -125,14 +178,18 @@ func (m *Manager) GetConnectionPreference() ConnectionPreference {
}
func (m *Manager) WasRecentlyFailed(ssid string) bool {
if nm, ok := m.backend.(*NetworkManagerBackend); ok {
nm.failedMutex.RLock()
defer nm.failedMutex.RUnlock()
if nm.lastFailedSSID == ssid {
elapsed := time.Now().Unix() - nm.lastFailedTime
return elapsed < 10
}
nm, ok := m.backend.(*NetworkManagerBackend)
if !ok {
return false
}
return false
nm.failedMutex.RLock()
defer nm.failedMutex.RUnlock()
if nm.lastFailedSSID != ssid {
return false
}
elapsed := time.Now().Unix() - nm.lastFailedTime
return elapsed < 10
}