浏览代码

update ip allocation logic

Max Ma 1 年之前
父节点
当前提交
849b51deed
共有 5 个文件被更改,包括 132 次插入14 次删除
  1. 4 4
      controllers/network.go
  2. 17 0
      logic/extpeers.go
  3. 97 4
      logic/networks.go
  4. 12 4
      logic/nodes.go
  5. 2 2
      main.go

+ 4 - 4
controllers/network.go

@@ -392,8 +392,8 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
 		return
 	}
-	//delete network from ip pool
-	go logic.RemoveNetworkFromIpPool(network)
+	//delete network from allocated ip map
+	go logic.RemoveNetworkFromAllocatedIpMap(network)
 
 	logger.Log(1, r.Header.Get("user"), "deleted network", network)
 	w.WriteHeader(http.StatusOK)
@@ -470,8 +470,8 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	//add new network to ip pool
-	go logic.AddNetworkToIpPool(network.NetID)
+	//add new network to allocated ip map
+	go logic.AddNetworkToAllocatedIpMap(network.NetID)
 
 	go func() {
 		defaultHosts := logic.GetDefaultHosts()

+ 17 - 0
logic/extpeers.go

@@ -90,6 +90,15 @@ func DeleteExtClient(network string, clientid string) error {
 	if err != nil {
 		return err
 	}
+	if extClient, ok := getExtClientFromCache(key); ok {
+		//recycle ip address
+		if extClient.Address != "" {
+			RemoveIpFromAllocatedIpMap(network, extClient.Address)
+		}
+		if extClient.Address6 != "" {
+			RemoveIpFromAllocatedIpMap(network, extClient.Address6)
+		}
+	}
 	if servercfg.CacheEnabled() {
 		deleteExtClientFromCache(key)
 	}
@@ -287,6 +296,14 @@ func SaveExtClient(extclient *models.ExtClient) error {
 	if servercfg.CacheEnabled() {
 		storeExtClientInCache(key, *extclient)
 	}
+	if _, ok := allocatedIpMap[extclient.Network]; ok {
+		if extclient.Address != "" {
+			AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address))
+		}
+		if extclient.Address6 != "" {
+			AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address6))
+		}
+	}
 	return SetNetworkNodesLastModified(extclient.Network)
 }
 

+ 97 - 4
logic/networks.go

@@ -17,13 +17,88 @@ import (
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/validation"
+	"golang.org/x/exp/slog"
 )
 
 var (
 	networkCacheMutex = &sync.RWMutex{}
 	networkCacheMap   = make(map[string]models.Network)
+	allocatedIpMap    = make(map[string]map[string]net.IP)
 )
 
+const (
+	ipAddrCap = 5000
+)
+
+// SetAllocatedIpMap - set allocated ip map for networks
+func SetAllocatedIpMap() error {
+	logger.Log(0, "start setting up allocated ip map")
+	if allocatedIpMap == nil {
+		allocatedIpMap = map[string]map[string]net.IP{}
+	}
+
+	currentNetworks, err := GetNetworks()
+	if err != nil {
+		return err
+	}
+
+	for _, v := range currentNetworks {
+		pMap := map[string]net.IP{}
+		netName := v.NetID
+
+		nodes, err := GetNetworkNodes(netName)
+		if err != nil {
+			slog.Error("could not load node for network", netName, "error", err.Error())
+			continue
+		}
+
+		for _, n := range nodes {
+
+			if n.Address.IP != nil {
+				pMap[n.Address.IP.String()] = n.Address.IP
+			}
+			if n.Address6.IP != nil {
+				pMap[n.Address6.IP.String()] = n.Address6.IP
+			}
+		}
+
+		allocatedIpMap[netName] = pMap
+	}
+	logger.Log(0, "setting up allocated ip map done")
+	return nil
+}
+
+// ClearAllocatedIpMap - set allocatedIpMap to nil
+func ClearAllocatedIpMap() {
+	allocatedIpMap = nil
+}
+
+func AddIpToAllocatedIpMap(networkName string, ip net.IP) {
+	networkCacheMutex.Lock()
+	allocatedIpMap[networkName][ip.String()] = ip
+	networkCacheMutex.Unlock()
+}
+
+func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
+	networkCacheMutex.Lock()
+	delete(allocatedIpMap[networkName], ip)
+	networkCacheMutex.Unlock()
+}
+
+// AddNetworkToAllocatedIpMap - add network to allocated ip map when network is added
+func AddNetworkToAllocatedIpMap(networkName string) {
+	networkCacheMutex.Lock()
+	allocatedIpMap[networkName] = map[string]net.IP{}
+	networkCacheMutex.Unlock()
+}
+
+// RemoveNetworkFromAllocatedIpMap - remove network from allocated ip map when network is deleted
+func RemoveNetworkFromAllocatedIpMap(networkName string) {
+	networkCacheMutex.Lock()
+	delete(allocatedIpMap, networkName)
+	networkCacheMutex.Unlock()
+}
+
 func getNetworksFromCache() (networks []models.Network) {
 	networkCacheMutex.RLock()
 	for _, network := range networkCacheMap {
@@ -239,9 +314,17 @@ func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
 		newAddrs = net4.LastAddress()
 	}
 
+	ipAllocated := allocatedIpMap[networkName]
+	i := 0
 	for {
-		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&
-			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {
+		if i >= ipAddrCap {
+			break
+		}
+		// if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&
+		// 	IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {
+		// 	return newAddrs, nil
+		// }
+		if _, ok := ipAllocated[newAddrs.String()]; !ok {
 			return newAddrs, nil
 		}
 		if reverse {
@@ -252,6 +335,7 @@ func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
 		if err != nil {
 			break
 		}
+		i++
 	}
 
 	return add, errors.New("ERROR: No unique addresses available. Check network subnet")
@@ -328,9 +412,17 @@ func UniqueAddress6(networkName string, reverse bool) (net.IP, error) {
 		return add, err
 	}
 
+	ipAllocated := allocatedIpMap[networkName]
+	i := 0
 	for {
-		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&
-			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {
+		if i >= ipAddrCap {
+			break
+		}
+		// if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&
+		// 	IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {
+		// 	return newAddrs, nil
+		// }
+		if _, ok := ipAllocated[newAddrs.String()]; !ok {
 			return newAddrs, nil
 		}
 		if reverse {
@@ -341,6 +433,7 @@ func UniqueAddress6(networkName string, reverse bool) (net.IP, error) {
 		if err != nil {
 			break
 		}
+		i++
 	}
 
 	return add, errors.New("ERROR: No unique IPv6 addresses available. Check network subnet")

+ 12 - 4
logic/nodes.go

@@ -303,10 +303,10 @@ func DeleteNodeByID(node *models.Node) error {
 	}
 	//recycle ip address
 	if node.Address.IP != nil {
-		ReleaseV4IpForNetwork(node.Network, node.Address.IP)
+		RemoveIpFromAllocatedIpMap(node.Network, node.Address.IP.String())
 	}
 	if node.Address6.IP != nil {
-		ReleaseV6IpForNetwork(node.Network, node.Address6.IP)
+		RemoveIpFromAllocatedIpMap(node.Network, node.Address6.IP.String())
 	}
 	return nil
 }
@@ -543,7 +543,7 @@ func createNode(node *models.Node) error {
 
 	if node.Address.IP == nil {
 		if parentNetwork.IsIPv4 == "yes" {
-			if node.Address.IP, err = GetUniqueAddress(node.Network); err != nil {
+			if node.Address.IP, err = UniqueAddress(node.Network, false); err != nil {
 				return err
 			}
 			_, cidr, err := net.ParseCIDR(parentNetwork.AddressRange)
@@ -557,7 +557,7 @@ func createNode(node *models.Node) error {
 	}
 	if node.Address6.IP == nil {
 		if parentNetwork.IsIPv6 == "yes" {
-			if node.Address6.IP, err = GetUniqueAddress6(node.Network); err != nil {
+			if node.Address6.IP, err = UniqueAddress6(node.Network, false); err != nil {
 				return err
 			}
 			_, cidr, err := net.ParseCIDR(parentNetwork.AddressRange6)
@@ -593,6 +593,14 @@ func createNode(node *models.Node) error {
 	if servercfg.CacheEnabled() {
 		storeNodeInCache(*node)
 	}
+	if _, ok := allocatedIpMap[node.Network]; ok {
+		if node.Address.IP != nil {
+			AddIpToAllocatedIpMap(node.Network, node.Address.IP)
+		}
+		if node.Address6.IP != nil {
+			AddIpToAllocatedIpMap(node.Network, node.Address6.IP)
+		}
+	}
 	_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), defaultACLVal)
 	if err != nil {
 		logger.Log(1, "failed to create node ACL for node,", node.ID.String(), "err:", err.Error())

+ 2 - 2
main.go

@@ -37,8 +37,8 @@ func main() {
 	servercfg.SetVersion(version)
 	fmt.Println(models.RetrieveLogo()) // print the logo
 	initialize()                       // initial db and acls
-	logic.SetIpPool()
-	defer logic.ClearIpPool()
+	logic.SetAllocatedIpMap()
+	defer logic.ClearAllocatedIpMap()
 	setGarbageCollection()
 	setVerbosity()
 	if servercfg.DeployedByOperator() && !servercfg.IsPro {