Skip to content

Commit f01e642

Browse files
committed
Allow user to specify default address pools for docker networks
This is separate commit on libnetwork to address PR 36054 Signed-off-by: selansen <elango.siva@docker.com>
1 parent 20dd462 commit f01e642

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

ipamutils/utils.go

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package ipamutils
33

44
import (
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.
2133
func 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+
}

ipamutils/utils_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"testing"
55

66
_ "github.com/docker/libnetwork/testutils"
7+
"github.com/stretchr/testify/assert"
8+
"sync"
79
)
810

911
func init() {
@@ -24,3 +26,26 @@ func TestGranularPredefined(t *testing.T) {
2426
}
2527

2628
}
29+
30+
func TestInitAddressPools(t *testing.T) {
31+
prePool1 := &PredefinedPools{"172.80.0.0/16", 24}
32+
prePool2 := &PredefinedPools{"172.90.0.0/16", 24}
33+
DefaultAddressPools := []*PredefinedPools{prePool1, prePool2}
34+
initNetworksOnce = sync.Once{}
35+
if err := InitAddressPools(DefaultAddressPools); err != nil {
36+
assert.NoError(t, err)
37+
}
38+
// Check for Random IPAddresses in PredefinedBroadNetworks ex: first , last and middle
39+
40+
if len(PredefinedBroadNetworks) == 512 {
41+
assert.Equal(t, PredefinedBroadNetworks[0].String(), "172.80.0.0/24")
42+
assert.Equal(t, PredefinedBroadNetworks[127].String(), "172.80.127.0/24")
43+
assert.Equal(t, PredefinedBroadNetworks[255].String(), "172.80.255.0/24")
44+
assert.Equal(t, PredefinedBroadNetworks[256].String(), "172.90.0.0/24")
45+
assert.Equal(t, PredefinedBroadNetworks[383].String(), "172.90.127.0/24")
46+
assert.Equal(t, PredefinedBroadNetworks[511].String(), "172.90.255.0/24")
47+
48+
} else {
49+
t.Fatalf(" Error IPAddress is missing in PredefinedBroadNetworks")
50+
}
51+
}

0 commit comments

Comments
 (0)