mirror of
https://github.com/netbirdio/netbird.git
synced 2025-05-21 00:40:57 +02:00
Improve windows network monitor (#2184)
* Allow other states for windows neighbor network monitor * Allow windows route network monitor to check for multiple default routes
This commit is contained in:
parent
6aae797baf
commit
f6ccf6b97a
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -33,12 +34,8 @@ func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop, ca
|
|||||||
return fmt.Errorf("get neighbors: %w", err)
|
return fmt.Errorf("get neighbors: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n, ok := initialNeighbors[nexthopv4.IP]; ok {
|
neighborv4 = assignNeighbor(nexthopv4, initialNeighbors)
|
||||||
neighborv4 = &n
|
neighborv6 = assignNeighbor(nexthopv6, initialNeighbors)
|
||||||
}
|
|
||||||
if n, ok := initialNeighbors[nexthopv6.IP]; ok {
|
|
||||||
neighborv6 = &n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.Debugf("Network monitor: initial IPv4 neighbor: %v, IPv6 neighbor: %v", neighborv4, neighborv6)
|
log.Debugf("Network monitor: initial IPv4 neighbor: %v, IPv6 neighbor: %v", neighborv4, neighborv6)
|
||||||
|
|
||||||
@ -58,6 +55,16 @@ func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop, ca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assignNeighbor(nexthop systemops.Nexthop, initialNeighbors map[netip.Addr]systemops.Neighbor) *systemops.Neighbor {
|
||||||
|
if n, ok := initialNeighbors[nexthop.IP]; ok &&
|
||||||
|
n.State != unreachable &&
|
||||||
|
n.State != incomplete &&
|
||||||
|
n.State != tbd {
|
||||||
|
return &n
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func changed(
|
func changed(
|
||||||
nexthopv4 systemops.Nexthop,
|
nexthopv4 systemops.Nexthop,
|
||||||
neighborv4 *systemops.Neighbor,
|
neighborv4 *systemops.Neighbor,
|
||||||
@ -87,37 +94,64 @@ func changed(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// routeChanged checks if the default routes still point to our nexthop/interface
|
// routeChanged checks if the default routes still point to our nexthop/interface
|
||||||
func routeChanged(nexthop systemops.Nexthop, intf *net.Interface, routes map[netip.Prefix]systemops.Route) bool {
|
func routeChanged(nexthop systemops.Nexthop, intf *net.Interface, routes []systemops.Route) bool {
|
||||||
if !nexthop.IP.IsValid() {
|
if !nexthop.IP.IsValid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var unspec netip.Prefix
|
unspec := getUnspecifiedPrefix(nexthop.IP)
|
||||||
if nexthop.IP.Is6() {
|
defaultRoutes, foundMatchingRoute := processRoutes(nexthop, intf, routes, unspec)
|
||||||
unspec = netip.PrefixFrom(netip.IPv6Unspecified(), 0)
|
|
||||||
} else {
|
|
||||||
unspec = netip.PrefixFrom(netip.IPv4Unspecified(), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := routes[unspec]; ok {
|
log.Tracef("network monitor: all default routes:\n%s", strings.Join(defaultRoutes, "\n"))
|
||||||
if r.Nexthop != nexthop.IP || compareIntf(r.Interface, intf) != 0 {
|
|
||||||
oldIntf, newIntf := "<nil>", "<nil>"
|
if !foundMatchingRoute {
|
||||||
if intf != nil {
|
logRouteChange(nexthop.IP, intf)
|
||||||
oldIntf = intf.Name
|
|
||||||
}
|
|
||||||
if r.Interface != nil {
|
|
||||||
newIntf = r.Interface.Name
|
|
||||||
}
|
|
||||||
log.Infof("network monitor: default route changed: %s from %s (%s) to %s (%s)", r.Destination, nexthop.IP, oldIntf, r.Nexthop, newIntf)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Infof("network monitor: default route is gone")
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUnspecifiedPrefix(ip netip.Addr) netip.Prefix {
|
||||||
|
if ip.Is6() {
|
||||||
|
return netip.PrefixFrom(netip.IPv6Unspecified(), 0)
|
||||||
|
}
|
||||||
|
return netip.PrefixFrom(netip.IPv4Unspecified(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processRoutes(nexthop systemops.Nexthop, intf *net.Interface, routes []systemops.Route, unspec netip.Prefix) ([]string, bool) {
|
||||||
|
var defaultRoutes []string
|
||||||
|
foundMatchingRoute := false
|
||||||
|
|
||||||
|
for _, r := range routes {
|
||||||
|
if r.Destination == unspec {
|
||||||
|
routeInfo := formatRouteInfo(r)
|
||||||
|
defaultRoutes = append(defaultRoutes, routeInfo)
|
||||||
|
|
||||||
|
if r.Nexthop == nexthop.IP && compareIntf(r.Interface, intf) == 0 {
|
||||||
|
foundMatchingRoute = true
|
||||||
|
log.Debugf("network monitor: found matching default route: %s", routeInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultRoutes, foundMatchingRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatRouteInfo(r systemops.Route) string {
|
||||||
|
newIntf := "<nil>"
|
||||||
|
if r.Interface != nil {
|
||||||
|
newIntf = r.Interface.Name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Nexthop: %s, Interface: %s", r.Nexthop, newIntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logRouteChange(ip netip.Addr, intf *net.Interface) {
|
||||||
|
oldIntf := "<nil>"
|
||||||
|
if intf != nil {
|
||||||
|
oldIntf = intf.Name
|
||||||
|
}
|
||||||
|
log.Infof("network monitor: default route for %s (%s) is gone or changed", ip, oldIntf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func neighborChanged(nexthop systemops.Nexthop, neighbor *systemops.Neighbor, neighbors map[netip.Addr]systemops.Neighbor) bool {
|
func neighborChanged(nexthop systemops.Nexthop, neighbor *systemops.Neighbor, neighbors map[netip.Addr]systemops.Neighbor) bool {
|
||||||
@ -127,7 +161,7 @@ func neighborChanged(nexthop systemops.Nexthop, neighbor *systemops.Neighbor, ne
|
|||||||
|
|
||||||
// TODO: consider non-local nexthops, e.g. on point-to-point interfaces
|
// TODO: consider non-local nexthops, e.g. on point-to-point interfaces
|
||||||
if n, ok := neighbors[nexthop.IP]; ok {
|
if n, ok := neighbors[nexthop.IP]; ok {
|
||||||
if n.State != reachable && n.State != permanent {
|
if n.State == unreachable || n.State == incomplete {
|
||||||
log.Infof("network monitor: neighbor %s (%s) is not reachable: %s", neighbor.IPAddress, neighbor.LinkLayerAddress, stateFromInt(n.State))
|
log.Infof("network monitor: neighbor %s (%s) is not reachable: %s", neighbor.IPAddress, neighbor.LinkLayerAddress, stateFromInt(n.State))
|
||||||
return true
|
return true
|
||||||
} else if n.InterfaceIndex != neighbor.InterfaceIndex {
|
} else if n.InterfaceIndex != neighbor.InterfaceIndex {
|
||||||
@ -165,18 +199,13 @@ func getNeighbors() (map[netip.Addr]systemops.Neighbor, error) {
|
|||||||
return neighbours, nil
|
return neighbours, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRoutes() (map[netip.Prefix]systemops.Route, error) {
|
func getRoutes() ([]systemops.Route, error) {
|
||||||
entries, err := systemops.GetRoutes()
|
entries, err := systemops.GetRoutes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get routes: %w", err)
|
return nil, fmt.Errorf("get routes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
routes := make(map[netip.Prefix]systemops.Route, len(entries))
|
return entries, nil
|
||||||
for _, entry := range entries {
|
|
||||||
routes[entry.Destination] = entry
|
|
||||||
}
|
|
||||||
|
|
||||||
return routes, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func stateFromInt(state uint8) string {
|
func stateFromInt(state uint8) string {
|
||||||
|
Loading…
Reference in New Issue
Block a user