github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/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{ 19 {"172.17.0.0/16", 16}, 20 {"172.18.0.0/16", 16}, 21 {"172.19.0.0/16", 16}, 22 {"172.20.0.0/14", 16}, 23 {"172.24.0.0/14", 16}, 24 {"172.28.0.0/14", 16}, 25 {"192.168.0.0/16", 20}, 26 } 27 globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}} 28 ) 29 30 // NetworkToSplit represent a network that has to be split in chunks with mask length Size. 31 // Each subnet in the set is derived from the Base pool. Base is to be passed 32 // in CIDR format. 33 // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256 34 // 10.10.[0-255].0/24 address pools 35 type NetworkToSplit struct { 36 Base string `json:"base"` 37 Size int `json:"size"` 38 } 39 40 func init() { 41 var err error 42 if predefinedGlobalScopeDefaultNetworks, err = SplitNetworks(globalScopeDefaultNetworks); err != nil { 43 panic("failed to initialize the global scope default address pool: " + err.Error()) 44 } 45 46 if predefinedLocalScopeDefaultNetworks, err = SplitNetworks(localScopeDefaultNetworks); err != nil { 47 panic("failed to initialize the local scope default address pool: " + err.Error()) 48 } 49 } 50 51 // ConfigGlobalScopeDefaultNetworks configures global default pool. 52 // Ideally this will be called from SwarmKit as part of swarm init 53 func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { 54 if defaultAddressPool == nil { 55 return nil 56 } 57 mutex.Lock() 58 defer mutex.Unlock() 59 defaultNetworks, err := SplitNetworks(defaultAddressPool) 60 if err != nil { 61 return err 62 } 63 predefinedGlobalScopeDefaultNetworks = defaultNetworks 64 return nil 65 } 66 67 // GetGlobalScopeDefaultNetworks returns a copy of the global-sopce network list. 68 func GetGlobalScopeDefaultNetworks() []*net.IPNet { 69 mutex.Lock() 70 defer mutex.Unlock() 71 return append([]*net.IPNet(nil), predefinedGlobalScopeDefaultNetworks...) 72 } 73 74 // GetLocalScopeDefaultNetworks returns a copy of the default local-scope network list. 75 func GetLocalScopeDefaultNetworks() []*net.IPNet { 76 return append([]*net.IPNet(nil), predefinedLocalScopeDefaultNetworks...) 77 } 78 79 // SplitNetworks takes a slice of networks, split them accordingly and returns them 80 func SplitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { 81 localPools := make([]*net.IPNet, 0, len(list)) 82 83 for _, p := range list { 84 _, b, err := net.ParseCIDR(p.Base) 85 if err != nil { 86 return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) 87 } 88 ones, _ := b.Mask.Size() 89 if p.Size <= 0 || p.Size < ones { 90 return nil, fmt.Errorf("invalid pools size: %d", p.Size) 91 } 92 localPools = append(localPools, splitNetwork(p.Size, b)...) 93 } 94 return localPools, nil 95 } 96 97 func splitNetwork(size int, base *net.IPNet) []*net.IPNet { 98 one, bits := base.Mask.Size() 99 mask := net.CIDRMask(size, bits) 100 n := 1 << uint(size-one) 101 s := uint(bits - size) 102 list := make([]*net.IPNet, 0, n) 103 104 for i := 0; i < n; i++ { 105 ip := copyIP(base.IP) 106 addIntToIP(ip, uint(i<<s)) 107 list = append(list, &net.IPNet{IP: ip, Mask: mask}) 108 } 109 return list 110 } 111 112 func copyIP(from net.IP) net.IP { 113 ip := make([]byte, len(from)) 114 copy(ip, from) 115 return ip 116 } 117 118 func addIntToIP(array net.IP, ordinal uint) { 119 for i := len(array) - 1; i >= 0; i-- { 120 array[i] |= (byte)(ordinal & 0xff) 121 ordinal >>= 8 122 } 123 }