@@ -2,21 +2,59 @@ package nmlite
22
33import (
44 "fmt"
5+ "strings"
56 "time"
67
78 "github.com/jetkvm/kvm/internal/network/types"
89 "github.com/jetkvm/kvm/pkg/nmlite/link"
910 "github.com/vishvananda/netlink"
1011)
1112
13+ type IfStateChangeReason uint
14+
15+ const (
16+ IfStateOperStateChanged IfStateChangeReason = 1
17+ IfStateOnlineStateChanged IfStateChangeReason = 2
18+ IfStateMACAddressChanged IfStateChangeReason = 3
19+ IfStateIPAddressesChanged IfStateChangeReason = 4
20+ )
21+
22+ type IfStateChangeReasons []IfStateChangeReason
23+
24+ func (r IfStateChangeReason ) String () string {
25+ switch r {
26+ case IfStateOperStateChanged :
27+ return "oper state changed"
28+ case IfStateOnlineStateChanged :
29+ return "online state changed"
30+ case IfStateMACAddressChanged :
31+ return "MAC address changed"
32+ case IfStateIPAddressesChanged :
33+ return "IP addresses changed"
34+ default :
35+ return fmt .Sprintf ("unknown change reason %d" , r )
36+ }
37+ }
38+
39+ func (rs IfStateChangeReasons ) String () string {
40+ reasons := []string {}
41+ for _ , r := range rs {
42+ reasons = append (reasons , r .String ())
43+ }
44+ return strings .Join (reasons , ", " )
45+ }
46+
1247// updateInterfaceState updates the current interface state
1348func (im * InterfaceManager ) updateInterfaceState () error {
1449 nl , err := im .link ()
1550 if err != nil {
1651 return fmt .Errorf ("failed to get interface: %w" , err )
1752 }
1853
19- var stateChanged bool
54+ var (
55+ stateChanged bool
56+ changeReasons IfStateChangeReasons
57+ )
2058
2159 attrs := nl .Attrs ()
2260
@@ -29,34 +67,41 @@ func (im *InterfaceManager) updateInterfaceState() error {
2967 if im .state .Up != isUp {
3068 im .state .Up = isUp
3169 stateChanged = true
70+ changeReasons = append (changeReasons , IfStateOperStateChanged )
3271 }
3372
3473 // Check if the interface is online
3574 isOnline := isUp && nl .HasGlobalUnicastAddress ()
3675 if im .state .Online != isOnline {
3776 im .state .Online = isOnline
3877 stateChanged = true
78+ changeReasons = append (changeReasons , IfStateOnlineStateChanged )
3979 }
4080
4181 // Check if the MAC address has changed
4282 if im .state .MACAddress != attrs .HardwareAddr .String () {
4383 im .state .MACAddress = attrs .HardwareAddr .String ()
4484 stateChanged = true
85+ changeReasons = append (changeReasons , IfStateMACAddressChanged )
4586 }
4687
4788 // Update IP addresses
4889 if ipChanged , err := im .updateInterfaceStateAddresses (nl ); err != nil {
4990 im .logger .Error ().Err (err ).Msg ("failed to update IP addresses" )
5091 } else if ipChanged {
5192 stateChanged = true
93+ changeReasons = append (changeReasons , IfStateIPAddressesChanged )
5294 }
5395
5496 im .state .LastUpdated = time .Now ()
5597 im .stateMu .Unlock ()
5698
5799 // Notify callback if state changed
58100 if stateChanged && im .onStateChange != nil {
59- im .logger .Debug ().Interface ("state" , im .state ).Msg ("notifying state change" )
101+ im .logger .Debug ().
102+ Stringer ("changeReasons" , changeReasons ).
103+ Interface ("state" , im .state ).
104+ Msg ("notifying state change" )
60105 im .onStateChange (* im .state )
61106 }
62107
@@ -80,6 +125,7 @@ func (im *InterfaceManager) updateInterfaceStateAddresses(nl *link.Link) (bool,
80125 ipv6Gateway string
81126 ipv4Ready , ipv6Ready = false , false
82127 stateChanged = false
128+ stateChangeReason string
83129 )
84130
85131 routes , _ := mgr .ListDefaultRoutes (link .AfInet6 )
@@ -123,40 +169,55 @@ func (im *InterfaceManager) updateInterfaceStateAddresses(nl *link.Link) (bool,
123169 if ! sortAndCompareStringSlices (im .state .IPv4Addresses , ipv4Addresses ) {
124170 im .state .IPv4Addresses = ipv4Addresses
125171 stateChanged = true
172+ stateChangeReason = "IPv4 addresses changed"
126173 }
127174
128175 if ! sortAndCompareIPv6AddressSlices (im .state .IPv6Addresses , ipv6Addresses ) {
129176 im .state .IPv6Addresses = ipv6Addresses
130177 stateChanged = true
178+ stateChangeReason = "IPv6 addresses changed"
131179 }
132180
133181 if im .state .IPv4Address != ipv4Addr {
134182 im .state .IPv4Address = ipv4Addr
135183 stateChanged = true
184+ stateChangeReason = "IPv4 address changed"
136185 }
137186
138187 if im .state .IPv6Address != ipv6Addr {
139188 im .state .IPv6Address = ipv6Addr
140189 stateChanged = true
190+ stateChangeReason = "IPv6 address changed"
141191 }
142192 if im .state .IPv6LinkLocal != ipv6LinkLocal {
143193 im .state .IPv6LinkLocal = ipv6LinkLocal
144194 stateChanged = true
195+ stateChangeReason = "IPv6 link local address changed"
145196 }
146197
147198 if im .state .IPv6Gateway != ipv6Gateway {
148199 im .state .IPv6Gateway = ipv6Gateway
149200 stateChanged = true
201+ stateChangeReason = "IPv6 gateway changed"
150202 }
151203
152204 if im .state .IPv4Ready != ipv4Ready {
153205 im .state .IPv4Ready = ipv4Ready
154206 stateChanged = true
207+ stateChangeReason = "IPv4 ready state changed"
155208 }
156209
157210 if im .state .IPv6Ready != ipv6Ready {
158211 im .state .IPv6Ready = ipv6Ready
159212 stateChanged = true
213+ stateChangeReason = "IPv6 ready state changed"
214+ }
215+
216+ if stateChanged {
217+ im .logger .Trace ().
218+ Str ("changeReason" , stateChangeReason ).
219+ Interface ("state" , im .state ).
220+ Msg ("interface state changed" )
160221 }
161222
162223 return stateChanged , nil
0 commit comments