github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/libnetwork/ipamutils/utils.go (about) 1 // Package ipamutils provides utility functions for ipam management 2 package ipamutils 3 4 import ( 5 "fmt" 6 "net" 7 "sync" 8 ) 9 10 var ( 11 // PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12 12 // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks` 13 PredefinedLocalScopeDefaultNetworks []*net.IPNet 14 // PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8 15 // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks` 16 PredefinedGlobalScopeDefaultNetworks []*net.IPNet 17 mutex sync.Mutex 18 localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16}, 19 {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16}, 20 {"192.168.0.0/16", 20}} 21 globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}} 22 ) 23 24 // NetworkToSplit represent a network that has to be split in chunks with mask length Size. 25 // Each subnet in the set is derived from the Base pool. Base is to be passed 26 // in CIDR format. 27 // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256 28 // 10.10.[0-255].0/24 address pools 29 type NetworkToSplit struct { 30 Base string `json:"base"` 31 Size int `json:"size"` 32 } 33 34 func init() { 35 var err error 36 if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil { 37 //we are going to panic in case of error as we should never get into this state 38 panic("InitAddressPools failed to initialize the global scope default address pool") 39 } 40 41 if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil { 42 //we are going to panic in case of error as we should never get into this state 43 panic("InitAddressPools failed to initialize the local scope default address pool") 44 } 45 } 46 47 // configDefaultNetworks configures local as well global default pool based on input 48 func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error { 49 mutex.Lock() 50 defer mutex.Unlock() 51 defaultNetworks, err := splitNetworks(defaultAddressPool) 52 if err != nil { 53 return err 54 } 55 *result = defaultNetworks 56 return nil 57 } 58 59 // GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks 60 func GetGlobalScopeDefaultNetworks() []*net.IPNet { 61 mutex.Lock() 62 defer mutex.Unlock() 63 return PredefinedGlobalScopeDefaultNetworks 64 } 65 66 // GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks 67 func GetLocalScopeDefaultNetworks() []*net.IPNet { 68 mutex.Lock() 69 defer mutex.Unlock() 70 return PredefinedLocalScopeDefaultNetworks 71 } 72 73 // ConfigGlobalScopeDefaultNetworks configures global default pool. 74 // Ideally this will be called from SwarmKit as part of swarm init 75 func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { 76 if defaultAddressPool == nil { 77 defaultAddressPool = globalScopeDefaultNetworks 78 } 79 return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks) 80 } 81 82 // ConfigLocalScopeDefaultNetworks configures local default pool. 83 // Ideally this will be called during libnetwork init 84 func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { 85 if defaultAddressPool == nil { 86 return nil 87 } 88 return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks) 89 } 90 91 // splitNetworks takes a slice of networks, split them accordingly and returns them 92 func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { 93 localPools := make([]*net.IPNet, 0, len(list)) 94 95 for _, p := range list { 96 _, b, err := net.ParseCIDR(p.Base) 97 if err != nil { 98 return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) 99 } 100 ones, _ := b.Mask.Size() 101 if p.Size <= 0 || p.Size < ones { 102 return nil, fmt.Errorf("invalid pools size: %d", p.Size) 103 } 104 localPools = append(localPools, splitNetwork(p.Size, b)...) 105 } 106 return localPools, nil 107 } 108 109 func splitNetwork(size int, base *net.IPNet) []*net.IPNet { 110 one, bits := base.Mask.Size() 111 mask := net.CIDRMask(size, bits) 112 n := 1 << uint(size-one) 113 s := uint(bits - size) 114 list := make([]*net.IPNet, 0, n) 115 116 for i := 0; i < n; i++ { 117 ip := copyIP(base.IP) 118 addIntToIP(ip, uint(i<<s)) 119 list = append(list, &net.IPNet{IP: ip, Mask: mask}) 120 } 121 return list 122 } 123 124 func copyIP(from net.IP) net.IP { 125 ip := make([]byte, len(from)) 126 copy(ip, from) 127 return ip 128 } 129 130 func addIntToIP(array net.IP, ordinal uint) { 131 for i := len(array) - 1; i >= 0; i-- { 132 array[i] |= (byte)(ordinal & 0xff) 133 ordinal >>= 8 134 } 135 }