mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-13 12:19:54 +00:00
[management, client] Add IPv6 overlay support (#5631)
This commit is contained in:
@@ -50,10 +50,11 @@ type CustomLogger interface {
|
||||
}
|
||||
|
||||
type selectRoute struct {
|
||||
NetID string
|
||||
Network netip.Prefix
|
||||
Domains domain.List
|
||||
Selected bool
|
||||
NetID string
|
||||
Network netip.Prefix
|
||||
Domains domain.List
|
||||
Selected bool
|
||||
extraNetworks []netip.Prefix
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -198,6 +199,7 @@ func (c *Client) GetStatusDetails() *StatusDetails {
|
||||
}
|
||||
pi := PeerInfo{
|
||||
IP: p.IP,
|
||||
IPv6: p.IPv6,
|
||||
FQDN: p.FQDN,
|
||||
LocalIceCandidateEndpoint: p.LocalIceCandidateEndpoint,
|
||||
RemoteIceCandidateEndpoint: p.RemoteIceCandidateEndpoint,
|
||||
@@ -216,7 +218,7 @@ func (c *Client) GetStatusDetails() *StatusDetails {
|
||||
}
|
||||
peerInfos[n] = pi
|
||||
}
|
||||
return &StatusDetails{items: peerInfos, fqdn: fullStatus.LocalPeerState.FQDN, ip: fullStatus.LocalPeerState.IP}
|
||||
return &StatusDetails{items: peerInfos, fqdn: fullStatus.LocalPeerState.FQDN, ip: fullStatus.LocalPeerState.IP, ipv6: fullStatus.LocalPeerState.IPv6}
|
||||
}
|
||||
|
||||
// SetConnectionListener set the network connection listener
|
||||
@@ -366,48 +368,60 @@ func (c *Client) GetRoutesSelectionDetails() (*RoutesSelectionDetails, error) {
|
||||
}
|
||||
|
||||
routeManager := engine.GetRouteManager()
|
||||
routesMap := routeManager.GetClientRoutesWithNetID()
|
||||
if routeManager == nil {
|
||||
return nil, fmt.Errorf("could not get route manager")
|
||||
}
|
||||
routesMap := routeManager.GetClientRoutesWithNetID()
|
||||
routeSelector := routeManager.GetRouteSelector()
|
||||
if routeSelector == nil {
|
||||
return nil, fmt.Errorf("could not get route selector")
|
||||
}
|
||||
|
||||
v6ExitMerged := route.V6ExitMergeSet(routesMap)
|
||||
routes := buildSelectRoutes(routesMap, routeSelector.IsSelected, v6ExitMerged)
|
||||
resolvedDomains := c.recorder.GetResolvedDomainsStates()
|
||||
|
||||
return prepareRouteSelectionDetails(routes, resolvedDomains), nil
|
||||
}
|
||||
|
||||
func buildSelectRoutes(routesMap map[route.NetID][]*route.Route, isSelected func(route.NetID) bool, v6Merged map[route.NetID]struct{}) []*selectRoute {
|
||||
var routes []*selectRoute
|
||||
for id, rt := range routesMap {
|
||||
if len(rt) == 0 {
|
||||
continue
|
||||
}
|
||||
route := &selectRoute{
|
||||
if _, ok := v6Merged[id]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
r := &selectRoute{
|
||||
NetID: string(id),
|
||||
Network: rt[0].Network,
|
||||
Domains: rt[0].Domains,
|
||||
Selected: routeSelector.IsSelected(id),
|
||||
Selected: isSelected(id),
|
||||
}
|
||||
routes = append(routes, route)
|
||||
|
||||
v6ID := route.NetID(string(id) + route.V6ExitSuffix)
|
||||
if _, ok := v6Merged[v6ID]; ok {
|
||||
r.extraNetworks = []netip.Prefix{routesMap[v6ID][0].Network}
|
||||
}
|
||||
|
||||
routes = append(routes, r)
|
||||
}
|
||||
|
||||
sort.Slice(routes, func(i, j int) bool {
|
||||
iPrefix := routes[i].Network.Bits()
|
||||
jPrefix := routes[j].Network.Bits()
|
||||
|
||||
if iPrefix == jPrefix {
|
||||
iAddr := routes[i].Network.Addr()
|
||||
jAddr := routes[j].Network.Addr()
|
||||
if iAddr == jAddr {
|
||||
return routes[i].NetID < routes[j].NetID
|
||||
}
|
||||
return iAddr.String() < jAddr.String()
|
||||
iBits, jBits := routes[i].Network.Bits(), routes[j].Network.Bits()
|
||||
if iBits != jBits {
|
||||
return iBits < jBits
|
||||
}
|
||||
return iPrefix < jPrefix
|
||||
iAddr, jAddr := routes[i].Network.Addr(), routes[j].Network.Addr()
|
||||
if iAddr != jAddr {
|
||||
return iAddr.Less(jAddr)
|
||||
}
|
||||
return routes[i].NetID < routes[j].NetID
|
||||
})
|
||||
|
||||
resolvedDomains := c.recorder.GetResolvedDomainsStates()
|
||||
|
||||
return prepareRouteSelectionDetails(routes, resolvedDomains), nil
|
||||
|
||||
return routes
|
||||
}
|
||||
|
||||
func prepareRouteSelectionDetails(routes []*selectRoute, resolvedDomains map[domain.Domain]peer.ResolvedDomainInfo) *RoutesSelectionDetails {
|
||||
@@ -443,6 +457,9 @@ func prepareRouteSelectionDetails(routes []*selectRoute, resolvedDomains map[dom
|
||||
if len(r.Domains) > 0 {
|
||||
netStr = r.Domains.SafeString()
|
||||
}
|
||||
for _, extra := range r.extraNetworks {
|
||||
netStr += ", " + extra.String()
|
||||
}
|
||||
|
||||
routeSelection = append(routeSelection, RoutesSelectionInfo{
|
||||
ID: r.NetID,
|
||||
@@ -474,7 +491,9 @@ func (c *Client) SelectRoute(id string) error {
|
||||
} else {
|
||||
log.Debugf("select route with id: %s", id)
|
||||
routes := toNetIDs([]string{id})
|
||||
if err := routeSelector.SelectRoutes(routes, true, maps.Keys(routeManager.GetClientRoutesWithNetID())); err != nil {
|
||||
routesMap := routeManager.GetClientRoutesWithNetID()
|
||||
routes = route.ExpandV6ExitPairs(routes, routesMap)
|
||||
if err := routeSelector.SelectRoutes(routes, true, maps.Keys(routesMap)); err != nil {
|
||||
log.Debugf("error when selecting routes: %s", err)
|
||||
return fmt.Errorf("select routes: %w", err)
|
||||
}
|
||||
@@ -501,7 +520,9 @@ func (c *Client) DeselectRoute(id string) error {
|
||||
} else {
|
||||
log.Debugf("deselect route with id: %s", id)
|
||||
routes := toNetIDs([]string{id})
|
||||
if err := routeSelector.DeselectRoutes(routes, maps.Keys(routeManager.GetClientRoutesWithNetID())); err != nil {
|
||||
routesMap := routeManager.GetClientRoutesWithNetID()
|
||||
routes = route.ExpandV6ExitPairs(routes, routesMap)
|
||||
if err := routeSelector.DeselectRoutes(routes, maps.Keys(routesMap)); err != nil {
|
||||
log.Debugf("error when deselecting routes: %s", err)
|
||||
return fmt.Errorf("deselect routes: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package NetBirdSDK
|
||||
// PeerInfo describe information about the peers. It designed for the UI usage
|
||||
type PeerInfo struct {
|
||||
IP string
|
||||
IPv6 string
|
||||
FQDN string
|
||||
LocalIceCandidateEndpoint string
|
||||
RemoteIceCandidateEndpoint string
|
||||
@@ -23,6 +24,11 @@ type PeerInfo struct {
|
||||
Routes RoutesDetails
|
||||
}
|
||||
|
||||
// GetIPv6 returns the IPv6 address of the peer
|
||||
func (p PeerInfo) GetIPv6() string {
|
||||
return p.IPv6
|
||||
}
|
||||
|
||||
// GetRoutes return with RouteDetails
|
||||
func (p PeerInfo) GetRouteDetails() *RoutesDetails {
|
||||
return &p.Routes
|
||||
@@ -57,6 +63,7 @@ type StatusDetails struct {
|
||||
items []PeerInfo
|
||||
fqdn string
|
||||
ip string
|
||||
ipv6 string
|
||||
}
|
||||
|
||||
// Add new PeerInfo to the collection
|
||||
@@ -100,3 +107,8 @@ func (array StatusDetails) GetFQDN() string {
|
||||
func (array StatusDetails) GetIP() string {
|
||||
return array.ip
|
||||
}
|
||||
|
||||
// GetIPv6 return with the IPv6 of the local peer
|
||||
func (array StatusDetails) GetIPv6() string {
|
||||
return array.ipv6
|
||||
}
|
||||
|
||||
@@ -110,6 +110,24 @@ func (p *Preferences) GetRosenpassPermissive() (bool, error) {
|
||||
return cfg.RosenpassPermissive, err
|
||||
}
|
||||
|
||||
// GetDisableIPv6 reads disable IPv6 setting from config file
|
||||
func (p *Preferences) GetDisableIPv6() (bool, error) {
|
||||
if p.configInput.DisableIPv6 != nil {
|
||||
return *p.configInput.DisableIPv6, nil
|
||||
}
|
||||
|
||||
cfg, err := profilemanager.ReadConfig(p.configInput.ConfigPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return cfg.DisableIPv6, err
|
||||
}
|
||||
|
||||
// SetDisableIPv6 stores the given value and waits for commit
|
||||
func (p *Preferences) SetDisableIPv6(disable bool) {
|
||||
p.configInput.DisableIPv6 = &disable
|
||||
}
|
||||
|
||||
// Commit write out the changes into config file
|
||||
func (p *Preferences) Commit() error {
|
||||
// Use DirectUpdateOrCreateConfig to avoid atomic file operations (temp file + rename)
|
||||
|
||||
Reference in New Issue
Block a user