github.com/rumpl/bof@v23.0.0-rc.2+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 panic("failed to initialize the global scope default address pool: " + err.Error()) 38 } 39 40 if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil { 41 panic("failed to initialize the local scope default address pool: " + err.Error()) 42 } 43 } 44 45 // configDefaultNetworks configures local as well global default pool based on input 46 func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error { 47 mutex.Lock() 48 defer mutex.Unlock() 49 defaultNetworks, err := splitNetworks(defaultAddressPool) 50 if err != nil { 51 return err 52 } 53 *result = defaultNetworks 54 return nil 55 } 56 57 // GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks 58 func GetGlobalScopeDefaultNetworks() []*net.IPNet { 59 mutex.Lock() 60 defer mutex.Unlock() 61 return PredefinedGlobalScopeDefaultNetworks 62 } 63 64 // GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks 65 func GetLocalScopeDefaultNetworks() []*net.IPNet { 66 mutex.Lock() 67 defer mutex.Unlock() 68 return PredefinedLocalScopeDefaultNetworks 69 } 70 71 // ConfigGlobalScopeDefaultNetworks configures global default pool. 72 // Ideally this will be called from SwarmKit as part of swarm init 73 func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { 74 if defaultAddressPool == nil { 75 defaultAddressPool = globalScopeDefaultNetworks 76 } 77 return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks) 78 } 79 80 // ConfigLocalScopeDefaultNetworks configures local default pool. 81 // Ideally this will be called during libnetwork init 82 func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { 83 if defaultAddressPool == nil { 84 return nil 85 } 86 return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks) 87 } 88 89 // splitNetworks takes a slice of networks, split them accordingly and returns them 90 func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { 91 localPools := make([]*net.IPNet, 0, len(list)) 92 93 for _, p := range list { 94 _, b, err := net.ParseCIDR(p.Base) 95 if err != nil { 96 return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) 97 } 98 ones, _ := b.Mask.Size() 99 if p.Size <= 0 || p.Size < ones { 100 return nil, fmt.Errorf("invalid pools size: %d", p.Size) 101 } 102 localPools = append(localPools, splitNetwork(p.Size, b)...) 103 } 104 return localPools, nil 105 } 106 107 func splitNetwork(size int, base *net.IPNet) []*net.IPNet { 108 one, bits := base.Mask.Size() 109 mask := net.CIDRMask(size, bits) 110 n := 1 << uint(size-one) 111 s := uint(bits - size) 112 list := make([]*net.IPNet, 0, n) 113 114 for i := 0; i < n; i++ { 115 ip := copyIP(base.IP) 116 addIntToIP(ip, uint(i<<s)) 117 list = append(list, &net.IPNet{IP: ip, Mask: mask}) 118 } 119 return list 120 } 121 122 func copyIP(from net.IP) net.IP { 123 ip := make([]byte, len(from)) 124 copy(ip, from) 125 return ip 126 } 127 128 func addIntToIP(array net.IP, ordinal uint) { 129 for i := len(array) - 1; i >= 0; i-- { 130 array[i] |= (byte)(ordinal & 0xff) 131 ordinal >>= 8 132 } 133 }