-
Notifications
You must be signed in to change notification settings - Fork 0
/
ip_allocator.go
75 lines (63 loc) · 1.71 KB
/
ip_allocator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package netutils
import (
"fmt"
"net"
)
type IPAllocator struct {
network *net.IPNet
allocMap map[string]bool
}
func NewIPAllocator(network string, inUse []string) (*IPAllocator, error) {
_, netIP, err := net.ParseCIDR(network)
if err != nil {
return nil, fmt.Errorf("Failed to parse network address: %q", network)
}
amap := make(map[string]bool)
for _, netStr := range inUse {
_, nIp, err := net.ParseCIDR(netStr)
if err != nil {
fmt.Println("Failed to parse network address: ", netStr)
continue
}
if !netIP.Contains(nIp.IP) {
fmt.Println("Provided subnet doesn't belong to network: ", nIp)
continue
}
amap[netStr] = true
}
// Add the network address to the map
amap[netIP.String()] = true
return &IPAllocator{network: netIP, allocMap: amap}, nil
}
func (ipa *IPAllocator) GetIP() (*net.IPNet, error) {
var (
numIPs uint32
numIPBits uint
)
baseipu := IPToUint32(ipa.network.IP)
netMaskSize, _ := ipa.network.Mask.Size()
numIPBits = 32 - uint(netMaskSize)
numIPs = 1 << numIPBits
var i uint32
// We exclude the last address as it is reserved for broadcast
for i = 0; i < numIPs-1; i++ {
ipu := baseipu | i
genIP := &net.IPNet{IP: Uint32ToIP(ipu), Mask: net.CIDRMask(netMaskSize, 32)}
if !ipa.allocMap[genIP.String()] {
ipa.allocMap[genIP.String()] = true
return genIP, nil
}
}
return nil, fmt.Errorf("No IPs available.")
}
func (ipa *IPAllocator) ReleaseIP(ip *net.IPNet) error {
if !ipa.network.Contains(ip.IP) {
return fmt.Errorf("Provided IP %v doesn't belong to the network %v.", ip, ipa.network)
}
ipStr := ip.String()
if !ipa.allocMap[ipStr] {
return fmt.Errorf("Provided IP %v is already available.", ip)
}
ipa.allocMap[ipStr] = false
return nil
}