22package ipamutils
33
44import (
5+ "fmt"
56 "net"
67 "sync"
8+
9+ "github.com/sirupsen/logrus"
710)
811
912var (
@@ -13,18 +16,37 @@ var (
1316 // PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
1417 // (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
1518 PredefinedGranularNetworks []* net.IPNet
16-
17- initNetworksOnce sync.Once
19+ initNetworksOnce sync.Once
1820)
1921
20- // InitNetworks initializes the pre-defined networks used by the built-in IP allocator
21- func InitNetworks () {
22+ // PredefinedPools represent a set of address pools with prefix length Size.
23+ // Each pool in the set is derived from the Base pool. Base is to be passed
24+ // in CIDR format.Currently we support only local scope networks
25+ // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
26+ // 10.10.[0-255].0/24 address pools
27+ type PredefinedPools struct {
28+ Base string `json:"base"`
29+ Size int `json:"size"`
30+ }
31+
32+ // InitNetworks initializes the local predefined address pools
33+ // with the default values.
34+ func InitNetworks (defaultAddressPool []* PredefinedPools ) {
2235 initNetworksOnce .Do (func () {
23- PredefinedBroadNetworks = initBroadPredefinedNetworks ()
36+ isPredefinedPool := false
2437 PredefinedGranularNetworks = initGranularPredefinedNetworks ()
38+ if defaultAddressPool == nil {
39+ defaultAddressPool = []* PredefinedPools {{"172.17.0.0/12" , 16 }, {"192.168.0.0/16" , 20 }}
40+ isPredefinedPool = true
41+ }
42+ if err := InitAddressPools (defaultAddressPool ); err != nil {
43+ logrus .WithError (err ).Error ("InitAddressPools failed to initialize the default address pool" )
44+ }
45+ if isPredefinedPool {
46+ PredefinedBroadNetworks = append (PredefinedBroadNetworks [:0 ], PredefinedBroadNetworks [1 :]... )
47+ }
2548 })
2649}
27-
2850func initBroadPredefinedNetworks () []* net.IPNet {
2951 pl := make ([]* net.IPNet , 0 , 31 )
3052 mask := []byte {255 , 255 , 0 , 0 }
@@ -48,3 +70,55 @@ func initGranularPredefinedNetworks() []*net.IPNet {
4870 }
4971 return pl
5072}
73+
74+ // InitAddressPools allows to initialize the local scope predefined
75+ // address pools to the desired values. It fails is invalid input is passed
76+ // or if the predefined pools were already initialized.
77+ func InitAddressPools (list []* PredefinedPools ) error {
78+ localPools := make ([]* net.IPNet , 0 , len (list ))
79+
80+ for _ , p := range list {
81+ if p == nil {
82+ continue
83+ }
84+ _ , b , err := net .ParseCIDR (p .Base )
85+ if err != nil {
86+ return fmt .Errorf ("invalid base pool %q: %v" , p .Base , err )
87+ }
88+ ones , _ := b .Mask .Size ()
89+ if p .Size <= 0 || p .Size < ones {
90+ return fmt .Errorf ("invalid pools size: %d" , p .Size )
91+ }
92+ localPools = append (localPools , initPools (p .Size , b )... )
93+ }
94+ PredefinedBroadNetworks = localPools
95+ return nil
96+ }
97+
98+ func initPools (size int , base * net.IPNet ) []* net.IPNet {
99+ one , bits := base .Mask .Size ()
100+ mask := net .CIDRMask (size , bits )
101+ n := 1 << uint (size - one )
102+ s := uint (bits - size )
103+ list := make ([]* net.IPNet , 0 , n )
104+
105+ for i := 0 ; i < n ; i ++ {
106+ ip := copyIP (base .IP )
107+ addIntToIP (ip , uint (i << s ))
108+ list = append (list , & net.IPNet {IP : ip , Mask : mask })
109+ }
110+ return list
111+ }
112+
113+ func copyIP (from net.IP ) net.IP {
114+ ip := make ([]byte , len (from ))
115+ copy (ip , from )
116+ return ip
117+ }
118+
119+ func addIntToIP (array net.IP , ordinal uint ) {
120+ for i := len (array ) - 1 ; i >= 0 ; i -- {
121+ array [i ] |= (byte )(ordinal & 0xff )
122+ ordinal >>= 8
123+ }
124+ }
0 commit comments