Global Default Address Pool support
This change brings global default address pool feature into libnetwork. Idea is to reuse same code flow and functions that were implemented for local scope default address pool. Function InitNetworks carries most of the changes. local scope default address pool init should always happen only once. But Global scope default address pool can be initialized multiple times. Signed-off-by: selansen <elango.siva@docker.com>
This commit is contained in:
parent
3321709a62
commit
52e85b4b9a
|
@ -10,7 +10,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
"github.com/docker/libnetwork/ipamutils"
|
|
||||||
"github.com/docker/libnetwork/iptables"
|
"github.com/docker/libnetwork/iptables"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
"github.com/docker/libnetwork/netutils"
|
"github.com/docker/libnetwork/netutils"
|
||||||
|
@ -20,10 +19,6 @@ import (
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
ipamutils.InitNetworks(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndpointMarshalling(t *testing.T) {
|
func TestEndpointMarshalling(t *testing.T) {
|
||||||
ip1, _ := types.ParseCIDR("172.22.0.9/16")
|
ip1, _ := types.ParseCIDR("172.22.0.9/16")
|
||||||
ip2, _ := types.ParseCIDR("2001:db8::9")
|
ip2, _ := types.ParseCIDR("2001:db8::9")
|
||||||
|
|
|
@ -46,8 +46,8 @@ func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
|
||||||
|
|
||||||
// Load predefined subnet pools
|
// Load predefined subnet pools
|
||||||
a.predefined = map[string][]*net.IPNet{
|
a.predefined = map[string][]*net.IPNet{
|
||||||
localAddressSpace: ipamutils.PredefinedBroadNetworks,
|
localAddressSpace: ipamutils.PredefinedLocalScopeDefaultNetworks,
|
||||||
globalAddressSpace: ipamutils.PredefinedGranularNetworks,
|
globalAddressSpace: ipamutils.PredefinedGlobalScopeDefaultNetworks,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize asIndices map
|
// Initialize asIndices map
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/docker/libnetwork/bitseq"
|
"github.com/docker/libnetwork/bitseq"
|
||||||
"github.com/docker/libnetwork/datastore"
|
"github.com/docker/libnetwork/datastore"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
"github.com/docker/libnetwork/ipamutils"
|
|
||||||
_ "github.com/docker/libnetwork/testutils"
|
_ "github.com/docker/libnetwork/testutils"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
@ -57,7 +56,6 @@ func randomLocalStore(needStore bool) (datastore.DataStore, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllocator(store bool) (*Allocator, error) {
|
func getAllocator(store bool) (*Allocator, error) {
|
||||||
ipamutils.InitNetworks(nil)
|
|
||||||
ds, err := randomLocalStore(store)
|
ds, err := randomLocalStore(store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -35,7 +35,7 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipamutils.InitNetworks(GetDefaultIPAddressPool())
|
ipamutils.ConfigLocalScopeDefaultNetworks(GetDefaultIPAddressPool())
|
||||||
|
|
||||||
a, err := ipam.NewAllocator(localDs, globalDs)
|
a, err := ipam.NewAllocator(localDs, globalDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -37,7 +37,7 @@ func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipamutils.InitNetworks(nil)
|
ipamutils.ConfigLocalScopeDefaultNetworks(nil)
|
||||||
|
|
||||||
a, err := ipam.NewAllocator(localDs, globalDs)
|
a, err := ipam.NewAllocator(localDs, globalDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,23 +5,20 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
|
// PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
|
||||||
// (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks`
|
// (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks`
|
||||||
PredefinedBroadNetworks []*net.IPNet
|
PredefinedLocalScopeDefaultNetworks []*net.IPNet
|
||||||
// PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
|
// PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8
|
||||||
// (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
|
// (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks`
|
||||||
PredefinedGranularNetworks []*net.IPNet
|
PredefinedGlobalScopeDefaultNetworks []*net.IPNet
|
||||||
initNetworksOnce sync.Once
|
mutex sync.Mutex
|
||||||
|
localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
|
||||||
defaultBroadNetwork = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
|
|
||||||
{"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
|
{"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
|
||||||
{"192.168.0.0/16", 20}}
|
{"192.168.0.0/16", 20}}
|
||||||
defaultGranularNetwork = []*NetworkToSplit{{"10.0.0.0/8", 24}}
|
globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetworkToSplit represent a network that has to be split in chunks with mask length Size.
|
// NetworkToSplit represent a network that has to be split in chunks with mask length Size.
|
||||||
|
@ -34,19 +31,47 @@ type NetworkToSplit struct {
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitNetworks initializes the broad network pool and the granular network pool
|
func init() {
|
||||||
func InitNetworks(defaultAddressPool []*NetworkToSplit) {
|
|
||||||
initNetworksOnce.Do(func() {
|
|
||||||
// error ingnored should never fail
|
|
||||||
PredefinedGranularNetworks, _ = splitNetworks(defaultGranularNetwork)
|
|
||||||
if defaultAddressPool == nil {
|
|
||||||
defaultAddressPool = defaultBroadNetwork
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
if PredefinedBroadNetworks, err = splitNetworks(defaultAddressPool); err != nil {
|
if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil {
|
||||||
logrus.WithError(err).Error("InitAddressPools failed to initialize the default address pool")
|
//we are going to panic in case of error as we should never get into this state
|
||||||
|
panic("InitAddressPools failed to initialize the global scope default address pool")
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil {
|
||||||
|
//we are going to panic in case of error as we should never get into this state
|
||||||
|
panic("InitAddressPools failed to initialize the local scope default address pool")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configDefaultNetworks configures local as well global default pool based on input
|
||||||
|
func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
defaultNetworks, err := splitNetworks(defaultAddressPool)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*result = defaultNetworks
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigGlobalScopeDefaultNetworks configures global default pool.
|
||||||
|
// Ideally this will be called from SwarmKit as part of swarm init
|
||||||
|
func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
|
||||||
|
if defaultAddressPool == nil {
|
||||||
|
defaultAddressPool = globalScopeDefaultNetworks
|
||||||
|
}
|
||||||
|
return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigLocalScopeDefaultNetworks configures local default pool.
|
||||||
|
// Ideally this will be called during libnetwork init
|
||||||
|
func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
|
||||||
|
if defaultAddressPool == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// splitNetworks takes a slice of networks, split them accordingly and returns them
|
// splitNetworks takes a slice of networks, split them accordingly and returns them
|
||||||
|
|
|
@ -2,7 +2,6 @@ package ipamutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
_ "github.com/docker/libnetwork/testutils"
|
_ "github.com/docker/libnetwork/testutils"
|
||||||
|
@ -34,15 +33,25 @@ func initGranularPredefinedNetworks() []*net.IPNet {
|
||||||
return pl
|
return pl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initGlobalScopeNetworks() []*net.IPNet {
|
||||||
|
pl := make([]*net.IPNet, 0, 256*256)
|
||||||
|
mask := []byte{255, 255, 255, 0}
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
for j := 0; j < 256; j++ {
|
||||||
|
pl = append(pl, &net.IPNet{IP: []byte{30, byte(i), byte(j), 0}, Mask: mask})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pl
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefaultNetwork(t *testing.T) {
|
func TestDefaultNetwork(t *testing.T) {
|
||||||
InitNetworks(nil)
|
for _, nw := range PredefinedGlobalScopeDefaultNetworks {
|
||||||
for _, nw := range PredefinedGranularNetworks {
|
|
||||||
if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 {
|
if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 {
|
||||||
t.Fatalf("Unexpected size for network in granular list: %v", nw)
|
t.Fatalf("Unexpected size for network in granular list: %v", nw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nw := range PredefinedBroadNetworks {
|
for _, nw := range PredefinedLocalScopeDefaultNetworks {
|
||||||
if ones, bits := nw.Mask.Size(); bits != 32 || (ones != 20 && ones != 16) {
|
if ones, bits := nw.Mask.Size(); bits != 32 || (ones != 20 && ones != 16) {
|
||||||
t.Fatalf("Unexpected size for network in broad list: %v", nw)
|
t.Fatalf("Unexpected size for network in broad list: %v", nw)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +62,7 @@ func TestDefaultNetwork(t *testing.T) {
|
||||||
for _, v := range originalBroadNets {
|
for _, v := range originalBroadNets {
|
||||||
m[v.String()] = true
|
m[v.String()] = true
|
||||||
}
|
}
|
||||||
for _, nw := range PredefinedBroadNetworks {
|
for _, nw := range PredefinedLocalScopeDefaultNetworks {
|
||||||
_, ok := m[nw.String()]
|
_, ok := m[nw.String()]
|
||||||
assert.Check(t, ok)
|
assert.Check(t, ok)
|
||||||
delete(m, nw.String())
|
delete(m, nw.String())
|
||||||
|
@ -67,7 +76,25 @@ func TestDefaultNetwork(t *testing.T) {
|
||||||
for _, v := range originalGranularNets {
|
for _, v := range originalGranularNets {
|
||||||
m[v.String()] = true
|
m[v.String()] = true
|
||||||
}
|
}
|
||||||
for _, nw := range PredefinedGranularNetworks {
|
for _, nw := range PredefinedGlobalScopeDefaultNetworks {
|
||||||
|
_, ok := m[nw.String()]
|
||||||
|
assert.Check(t, ok)
|
||||||
|
delete(m, nw.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Check(t, is.Len(m, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigGlobalScopeDefaultNetworks(t *testing.T) {
|
||||||
|
err := ConfigGlobalScopeDefaultNetworks([]*NetworkToSplit{{"30.0.0.0/8", 24}})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
originalGlobalScopeNetworks := initGlobalScopeNetworks()
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for _, v := range originalGlobalScopeNetworks {
|
||||||
|
m[v.String()] = true
|
||||||
|
}
|
||||||
|
for _, nw := range PredefinedGlobalScopeDefaultNetworks {
|
||||||
_, ok := m[nw.String()]
|
_, ok := m[nw.String()]
|
||||||
assert.Check(t, ok)
|
assert.Check(t, ok)
|
||||||
delete(m, nw.String())
|
delete(m, nw.String())
|
||||||
|
@ -77,15 +104,15 @@ func TestDefaultNetwork(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitAddressPools(t *testing.T) {
|
func TestInitAddressPools(t *testing.T) {
|
||||||
initNetworksOnce = sync.Once{}
|
err := ConfigLocalScopeDefaultNetworks([]*NetworkToSplit{{"172.80.0.0/16", 24}, {"172.90.0.0/16", 24}})
|
||||||
InitNetworks([]*NetworkToSplit{{"172.80.0.0/16", 24}, {"172.90.0.0/16", 24}})
|
assert.NilError(t, err)
|
||||||
|
|
||||||
// Check for Random IPAddresses in PredefinedBroadNetworks ex: first , last and middle
|
// Check for Random IPAddresses in PredefinedLocalScopeDefaultNetworks ex: first , last and middle
|
||||||
assert.Check(t, is.Len(PredefinedBroadNetworks, 512), "Failed to find PredefinedBroadNetworks")
|
assert.Check(t, is.Len(PredefinedLocalScopeDefaultNetworks, 512), "Failed to find PredefinedLocalScopeDefaultNetworks")
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[0].String(), "172.80.0.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[0].String(), "172.80.0.0/24"))
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[127].String(), "172.80.127.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[127].String(), "172.80.127.0/24"))
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[255].String(), "172.80.255.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[255].String(), "172.80.255.0/24"))
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[256].String(), "172.90.0.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[256].String(), "172.90.0.0/24"))
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[383].String(), "172.90.127.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[383].String(), "172.90.127.0/24"))
|
||||||
assert.Check(t, is.Equal(PredefinedBroadNetworks[511].String(), "172.90.255.0/24"))
|
assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[511].String(), "172.90.255.0/24"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,8 @@ func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if link == nil || len(v4Nets) == 0 {
|
if link == nil || len(v4Nets) == 0 {
|
||||||
// Choose from predefined broad networks
|
// Choose from predefined local scope networks
|
||||||
v4Net, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
v4Net, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,15 +212,14 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
|
||||||
|
|
||||||
func TestNetworkRequest(t *testing.T) {
|
func TestNetworkRequest(t *testing.T) {
|
||||||
defer testutils.SetupTestOSContext(t)()
|
defer testutils.SetupTestOSContext(t)()
|
||||||
ipamutils.InitNetworks(nil)
|
|
||||||
|
|
||||||
nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
nw, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var found bool
|
var found bool
|
||||||
for _, exp := range ipamutils.PredefinedBroadNetworks {
|
for _, exp := range ipamutils.PredefinedLocalScopeDefaultNetworks {
|
||||||
if types.CompareIPNet(exp, nw) {
|
if types.CompareIPNet(exp, nw) {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
@ -231,13 +230,13 @@ func TestNetworkRequest(t *testing.T) {
|
||||||
t.Fatalf("Found unexpected broad network %s", nw)
|
t.Fatalf("Found unexpected broad network %s", nw)
|
||||||
}
|
}
|
||||||
|
|
||||||
nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks)
|
nw, err = FindAvailableNetwork(ipamutils.PredefinedGlobalScopeDefaultNetworks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
found = false
|
found = false
|
||||||
for _, exp := range ipamutils.PredefinedGranularNetworks {
|
for _, exp := range ipamutils.PredefinedGlobalScopeDefaultNetworks {
|
||||||
if types.CompareIPNet(exp, nw) {
|
if types.CompareIPNet(exp, nw) {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
@ -255,7 +254,7 @@ func TestNetworkRequest(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
nw, err = FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -266,7 +265,6 @@ func TestNetworkRequest(t *testing.T) {
|
||||||
|
|
||||||
func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
|
func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
|
||||||
defer testutils.SetupTestOSContext(t)()
|
defer testutils.SetupTestOSContext(t)()
|
||||||
ipamutils.InitNetworks(nil)
|
|
||||||
|
|
||||||
nws := []string{"172.101.202.254/16", "172.102.202.254/16"}
|
nws := []string{"172.101.202.254/16", "172.102.202.254/16"}
|
||||||
createInterface(t, "test", nws...)
|
createInterface(t, "test", nws...)
|
||||||
|
@ -303,7 +301,6 @@ func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
|
||||||
|
|
||||||
func TestElectInterfaceAddress(t *testing.T) {
|
func TestElectInterfaceAddress(t *testing.T) {
|
||||||
defer testutils.SetupTestOSContext(t)()
|
defer testutils.SetupTestOSContext(t)()
|
||||||
ipamutils.InitNetworks(nil)
|
|
||||||
|
|
||||||
nws := "172.101.202.254/16"
|
nws := "172.101.202.254/16"
|
||||||
createInterface(t, "test", nws)
|
createInterface(t, "test", nws)
|
||||||
|
|
Loading…
Reference in New Issue