22package ipamutils
33
44import (
5+ "fmt"
56 "net"
67 "sync"
8+
9+ "github.com/sirupsen/logrus"
710)
811
912var (
@@ -13,18 +16,34 @@ 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 () {
36+ if defaultAddressPool != nil {
37+ if err := InitAddressPools (defaultAddressPool ); err != nil {
38+ logrus .WithError (err ).Error ("InitAddressPools failed to initialize the default address pool" )
39+ }
40+ PredefinedGranularNetworks = initGranularPredefinedNetworks ()
41+ return
42+ }
2343 PredefinedBroadNetworks = initBroadPredefinedNetworks ()
2444 PredefinedGranularNetworks = initGranularPredefinedNetworks ()
2545 })
2646}
27-
2847func initBroadPredefinedNetworks () []* net.IPNet {
2948 pl := make ([]* net.IPNet , 0 , 31 )
3049 mask := []byte {255 , 255 , 0 , 0 }
@@ -48,3 +67,55 @@ func initGranularPredefinedNetworks() []*net.IPNet {
4867 }
4968 return pl
5069}
70+
71+ // InitAddressPools allows to initialize the local scope predefined
72+ // address pools to the desired values. It fails is invalid input is passed
73+ // or if the predefined pools were already initialized.
74+ func InitAddressPools (list []* PredefinedPools ) error {
75+ localPools := make ([]* net.IPNet , 0 , len (list ))
76+
77+ for _ , p := range list {
78+ if p == nil {
79+ continue
80+ }
81+ _ , b , err := net .ParseCIDR (p .Base )
82+ if err != nil {
83+ return fmt .Errorf ("invalid base pool %q: %v" , p .Base , err )
84+ }
85+ ones , _ := b .Mask .Size ()
86+ if p .Size <= 0 || p .Size < ones {
87+ return fmt .Errorf ("invalid pools size: %d" , p .Size )
88+ }
89+ localPools = append (localPools , initPools (p .Size , b )... )
90+ }
91+ PredefinedBroadNetworks = localPools
92+ return nil
93+ }
94+
95+ func initPools (size int , base * net.IPNet ) []* net.IPNet {
96+ one , bits := base .Mask .Size ()
97+ mask := net .CIDRMask (size , bits )
98+ n := 1 << uint (size - one )
99+ s := uint (bits - size )
100+ list := make ([]* net.IPNet , 0 , n )
101+
102+ for i := 0 ; i < n ; i ++ {
103+ ip := copyIP (base .IP )
104+ addIntToIP (ip , uint (i << s ))
105+ list = append (list , & net.IPNet {IP : ip , Mask : mask })
106+ }
107+ return list
108+ }
109+
110+ func copyIP (from net.IP ) net.IP {
111+ ip := make ([]byte , len (from ))
112+ copy (ip , from )
113+ return ip
114+ }
115+
116+ func addIntToIP (array net.IP , ordinal uint ) {
117+ for i := len (array ) - 1 ; i >= 0 ; i -- {
118+ array [i ] |= (byte )(ordinal & 0xff )
119+ ordinal >>= 8
120+ }
121+ }
0 commit comments