mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-17 15:56:39 +00:00
138 lines
4.7 KiB
Go
138 lines
4.7 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.org/x/exp/maps"
|
|
|
|
nbdns "github.com/netbirdio/netbird/dns"
|
|
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
|
"github.com/netbirdio/netbird/management/server/types"
|
|
)
|
|
|
|
func (am *DefaultAccountManager) initNetworkMapBuilderIfNeeded(account *types.Account, validatedPeers map[string]struct{}) {
|
|
am.enrichAccountFromHolder(account)
|
|
account.InitNetworkMapBuilderIfNeeded(validatedPeers)
|
|
}
|
|
|
|
func (am *DefaultAccountManager) getPeerNetworkMapExp(
|
|
ctx context.Context,
|
|
accountId string,
|
|
peerId string,
|
|
validatedPeers map[string]struct{},
|
|
customZone nbdns.CustomZone,
|
|
metrics *telemetry.AccountManagerMetrics,
|
|
resourcePolicies map[string][]*types.Policy,
|
|
routers map[string]map[string]*routerTypes.NetworkRouter,
|
|
) *types.NetworkMap {
|
|
account := am.getAccountFromHolderOrInit(accountId)
|
|
if account == nil {
|
|
log.WithContext(ctx).Warnf("account %s not found in holder when getting peer network map", accountId)
|
|
return &types.NetworkMap{
|
|
Network: &types.Network{},
|
|
}
|
|
}
|
|
|
|
legacyMap := account.GetPeerNetworkMap(ctx, peerId, customZone, validatedPeers, resourcePolicies, routers, nil)
|
|
|
|
go func() {
|
|
expMap := account.GetPeerNetworkMapExp(ctx, peerId, customZone, validatedPeers, metrics)
|
|
am.compareAndSaveNetworkMaps(ctx, accountId, peerId, expMap, legacyMap)
|
|
}()
|
|
|
|
return legacyMap
|
|
}
|
|
|
|
func (am *DefaultAccountManager) compareAndSaveNetworkMaps(ctx context.Context, accountId, peerId string, expMap, legacyMap *types.NetworkMap) {
|
|
expBytes, err := json.Marshal(expMap)
|
|
if err != nil {
|
|
log.WithContext(ctx).Warnf("failed to marshal experimental network map: %v", err)
|
|
return
|
|
}
|
|
|
|
legacyBytes, err := json.Marshal(legacyMap)
|
|
if err != nil {
|
|
log.WithContext(ctx).Warnf("failed to marshal legacy network map: %v", err)
|
|
return
|
|
}
|
|
|
|
if len(expBytes) == len(legacyBytes) {
|
|
log.WithContext(ctx).Debugf("network maps are equal for peer %s in account %s (size: %d bytes)", peerId, accountId, len(expBytes))
|
|
return
|
|
}
|
|
|
|
timestamp := time.Now().UnixMicro()
|
|
baseDir := filepath.Join("debug_networkmaps", accountId, peerId)
|
|
|
|
if err := os.MkdirAll(baseDir, 0o755); err != nil {
|
|
log.WithContext(ctx).Warnf("failed to create debug directory %s: %v", baseDir, err)
|
|
return
|
|
}
|
|
|
|
expFile := filepath.Join(baseDir, fmt.Sprintf("exp_networkmap_%d.json", timestamp))
|
|
if err := os.WriteFile(expFile, expBytes, 0o644); err != nil {
|
|
log.WithContext(ctx).Warnf("failed to write experimental network map to %s: %v", expFile, err)
|
|
return
|
|
}
|
|
|
|
legacyFile := filepath.Join(baseDir, fmt.Sprintf("legacy_networkmap_%d.json", timestamp))
|
|
if err := os.WriteFile(legacyFile, legacyBytes, 0o644); err != nil {
|
|
log.WithContext(ctx).Warnf("failed to write legacy network map to %s: %v", legacyFile, err)
|
|
return
|
|
}
|
|
|
|
log.WithContext(ctx).Infof("network maps differ for peer %s in account %s - saved to %s (exp: %d bytes, legacy: %d bytes)", peerId, accountId, baseDir, len(expBytes), len(legacyBytes))
|
|
}
|
|
|
|
func (am *DefaultAccountManager) onPeerAddedUpdNetworkMapCache(account *types.Account, peerId string) error {
|
|
am.enrichAccountFromHolder(account)
|
|
return account.OnPeerAddedUpdNetworkMapCache(peerId)
|
|
}
|
|
|
|
func (am *DefaultAccountManager) onPeerDeletedUpdNetworkMapCache(account *types.Account, peerId string) error {
|
|
am.enrichAccountFromHolder(account)
|
|
return account.OnPeerDeletedUpdNetworkMapCache(peerId)
|
|
}
|
|
|
|
func (am *DefaultAccountManager) updatePeerInNetworkMapCache(accountId string, peer *nbpeer.Peer) {
|
|
account := am.getAccountFromHolder(accountId)
|
|
if account == nil {
|
|
return
|
|
}
|
|
account.UpdatePeerInNetworkMapCache(peer)
|
|
}
|
|
|
|
func (am *DefaultAccountManager) recalculateNetworkMapCache(account *types.Account, validatedPeers map[string]struct{}) {
|
|
account.RecalculateNetworkMapCache(validatedPeers)
|
|
am.updateAccountInHolder(account)
|
|
}
|
|
|
|
func (am *DefaultAccountManager) RecalculateNetworkMapCache(ctx context.Context, accountId string) error {
|
|
if am.experimentalNetworkMap(accountId) {
|
|
account, err := am.requestBuffer.GetAccountWithBackpressure(ctx, accountId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
validatedPeers, err := am.integratedPeerValidator.GetValidatedPeers(ctx, account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("failed to get validate peers: %v", err)
|
|
return err
|
|
}
|
|
am.recalculateNetworkMapCache(account, validatedPeers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (am *DefaultAccountManager) experimentalNetworkMap(accountId string) bool {
|
|
_, ok := am.expNewNetworkMapAIDs[accountId]
|
|
return am.expNewNetworkMap || ok
|
|
}
|