Skip to content

Commit 316c2e6

Browse files
authored
fix(network): IPv6 addresses sorting was using wrong references (jetkvm#997)
1 parent 79cb2aa commit 316c2e6

2 files changed

Lines changed: 71 additions & 8 deletions

File tree

pkg/nmlite/interface_state.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,59 @@ package nmlite
22

33
import (
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
1348
func (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

pkg/nmlite/utils.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,19 @@ func sortAndCompareStringSlices(a, b []string) bool {
4242
return true
4343
}
4444

45+
func sortIPv6AddressSlicesStable(a []types.IPv6Address) {
46+
sort.SliceStable(a, func(i, j int) bool {
47+
return a[i].Address.String() < a[j].Address.String()
48+
})
49+
}
50+
4551
func sortAndCompareIPv6AddressSlices(a, b []types.IPv6Address) bool {
4652
if len(a) != len(b) {
4753
return false
4854
}
4955

50-
sort.SliceStable(a, func(i, j int) bool {
51-
return a[i].Address.String() < b[j].Address.String()
52-
})
53-
sort.SliceStable(b, func(i, j int) bool {
54-
return b[i].Address.String() < a[j].Address.String()
55-
})
56+
sortIPv6AddressSlicesStable(a)
57+
sortIPv6AddressSlicesStable(b)
5658

5759
for i := range a {
5860
if a[i].Address.String() != b[i].Address.String() {

0 commit comments

Comments
 (0)