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 () {
23- 		PredefinedBroadNetworks  =  initBroadPredefinedNetworks ()
36+ 		if  defaultAddressPool  !=  nil  {
37+ 			if  err  :=  InitAddressPools (defaultAddressPool ); err  !=  nil  {
38+ 				logrus .Error ("InitAddressPools failed to initialize default address pool %v" , err )
39+ 			}
40+ 
41+ 		} else  {
42+ 			PredefinedBroadNetworks  =  initBroadPredefinedNetworks ()
43+ 		}
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 and global 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