22package ipamutils
33
44import (
5+ "fmt"
56 "net"
67 "sync"
78)
@@ -13,11 +14,22 @@ var (
1314 // PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
1415 // (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
1516 PredefinedGranularNetworks []* net.IPNet
16-
17- initNetworksOnce sync.Once
17+ initNetworksOnce sync.Once
1818)
1919
20- // InitNetworks initializes the pre-defined networks used by the built-in IP allocator
20+ // PredefinedPools represent a set of address pools with prefix length Size.
21+ // Each pool in the set is derived from the Base pool. Base is to be passed
22+ // in CIDR format. The Scope field can be "local" or "global", and says
23+ // whether the address pool is to be used for local or global scope networks.
24+ // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
25+ // 10.10.[0-255].0/24 address pools
26+ type PredefinedPools struct {
27+ Base string `json:"base"`
28+ Size int `json:"size"`
29+ }
30+
31+ // InitNetworks initializes the local predefined address pools
32+ // with the default values.
2133func InitNetworks () {
2234 initNetworksOnce .Do (func () {
2335 PredefinedBroadNetworks = initBroadPredefinedNetworks ()
@@ -48,3 +60,68 @@ func initGranularPredefinedNetworks() []*net.IPNet {
4860 }
4961 return pl
5062}
63+
64+ // InitAddressPools allows to initialize the local and global scope predefined
65+ // address pools to the desired values. It fails is invalid input is passed
66+ // or if the predefined pools were already initialized.
67+ func InitAddressPools (list []* PredefinedPools ) error {
68+ localPools := make ([]* net.IPNet , 0 , len (list ))
69+ done := false
70+
71+ for _ , p := range list {
72+ if p == nil {
73+ continue
74+ }
75+ _ , b , err := net .ParseCIDR (p .Base )
76+ if err != nil {
77+ return fmt .Errorf ("invalid base pool %q: %v" , p .Base , err )
78+ }
79+ ones , _ := b .Mask .Size ()
80+ if p .Size <= 0 || p .Size < ones {
81+ return fmt .Errorf ("invalid pools size: %d" , p .Size )
82+ }
83+ localPools = append (localPools , initPools (p .Size , b )... )
84+ }
85+ if localPools == nil {
86+ localPools = initBroadPredefinedNetworks ()
87+ }
88+ initNetworksOnce .Do (func () {
89+ PredefinedBroadNetworks = localPools
90+ done = true
91+ })
92+ if ! done {
93+ return fmt .Errorf ("predefined address pools are already initialized" )
94+ }
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+
111+ return list
112+ }
113+
114+ func copyIP (from net.IP ) net.IP {
115+ ip := make ([]byte , len (from ))
116+ for i := 0 ; i < len (ip ); i ++ {
117+ ip [i ] = from [i ]
118+ }
119+ return ip
120+ }
121+
122+ func addIntToIP (array []byte , ordinal uint ) {
123+ for i := len (array ) - 1 ; i >= 0 ; i -- {
124+ array [i ] |= (byte )(ordinal & 0xff )
125+ ordinal >>= 8
126+ }
127+ }
0 commit comments