github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/ipam/structures.go (about) 1 package ipam 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "strings" 8 "sync" 9 10 "github.com/docker/docker/libnetwork/datastore" 11 "github.com/docker/docker/libnetwork/ipamapi" 12 "github.com/docker/docker/libnetwork/types" 13 ) 14 15 // SubnetKey is the pointer to the configured pools in each address space 16 type SubnetKey struct { 17 AddressSpace string 18 Subnet string 19 ChildSubnet string 20 } 21 22 // PoolData contains the configured pool data 23 type PoolData struct { 24 ParentKey SubnetKey 25 Pool *net.IPNet 26 Range *AddressRange `json:",omitempty"` 27 RefCount int 28 } 29 30 // addrSpace contains the pool configurations for the address space 31 type addrSpace struct { 32 subnets map[SubnetKey]*PoolData 33 dbIndex uint64 34 dbExists bool 35 id string 36 scope string 37 ds datastore.DataStore 38 alloc *Allocator 39 sync.Mutex 40 } 41 42 // AddressRange specifies first and last ip ordinal which 43 // identifies a range in a pool of addresses 44 type AddressRange struct { 45 Sub *net.IPNet 46 Start, End uint64 47 } 48 49 // String returns the string form of the AddressRange object 50 func (r *AddressRange) String() string { 51 return fmt.Sprintf("Sub: %s, range [%d, %d]", r.Sub, r.Start, r.End) 52 } 53 54 // MarshalJSON returns the JSON encoding of the Range object 55 func (r *AddressRange) MarshalJSON() ([]byte, error) { 56 m := map[string]interface{}{ 57 "Sub": r.Sub.String(), 58 "Start": r.Start, 59 "End": r.End, 60 } 61 return json.Marshal(m) 62 } 63 64 // UnmarshalJSON decodes data into the Range object 65 func (r *AddressRange) UnmarshalJSON(data []byte) error { 66 m := map[string]interface{}{} 67 err := json.Unmarshal(data, &m) 68 if err != nil { 69 return err 70 } 71 if r.Sub, err = types.ParseCIDR(m["Sub"].(string)); err != nil { 72 return err 73 } 74 r.Start = uint64(m["Start"].(float64)) 75 r.End = uint64(m["End"].(float64)) 76 return nil 77 } 78 79 // String returns the string form of the SubnetKey object 80 func (s *SubnetKey) String() string { 81 k := fmt.Sprintf("%s/%s", s.AddressSpace, s.Subnet) 82 if s.ChildSubnet != "" { 83 k = fmt.Sprintf("%s/%s", k, s.ChildSubnet) 84 } 85 return k 86 } 87 88 // FromString populates the SubnetKey object reading it from string 89 func (s *SubnetKey) FromString(str string) error { 90 if str == "" || !strings.Contains(str, "/") { 91 return types.BadRequestErrorf("invalid string form for subnetkey: %s", str) 92 } 93 94 p := strings.Split(str, "/") 95 if len(p) != 3 && len(p) != 5 { 96 return types.BadRequestErrorf("invalid string form for subnetkey: %s", str) 97 } 98 s.AddressSpace = p[0] 99 s.Subnet = fmt.Sprintf("%s/%s", p[1], p[2]) 100 if len(p) == 5 { 101 s.ChildSubnet = fmt.Sprintf("%s/%s", p[3], p[4]) 102 } 103 104 return nil 105 } 106 107 // String returns the string form of the PoolData object 108 func (p *PoolData) String() string { 109 return fmt.Sprintf("ParentKey: %s, Pool: %s, Range: %s, RefCount: %d", 110 p.ParentKey.String(), p.Pool.String(), p.Range, p.RefCount) 111 } 112 113 // MarshalJSON returns the JSON encoding of the PoolData object 114 func (p *PoolData) MarshalJSON() ([]byte, error) { 115 m := map[string]interface{}{ 116 "ParentKey": p.ParentKey, 117 "RefCount": p.RefCount, 118 } 119 if p.Pool != nil { 120 m["Pool"] = p.Pool.String() 121 } 122 if p.Range != nil { 123 m["Range"] = p.Range 124 } 125 return json.Marshal(m) 126 } 127 128 // UnmarshalJSON decodes data into the PoolData object 129 func (p *PoolData) UnmarshalJSON(data []byte) error { 130 var ( 131 err error 132 t struct { 133 ParentKey SubnetKey 134 Pool string 135 Range *AddressRange `json:",omitempty"` 136 RefCount int 137 } 138 ) 139 140 if err = json.Unmarshal(data, &t); err != nil { 141 return err 142 } 143 144 p.ParentKey = t.ParentKey 145 p.Range = t.Range 146 p.RefCount = t.RefCount 147 if t.Pool != "" { 148 if p.Pool, err = types.ParseCIDR(t.Pool); err != nil { 149 return err 150 } 151 } 152 153 return nil 154 } 155 156 // MarshalJSON returns the JSON encoding of the addrSpace object 157 func (aSpace *addrSpace) MarshalJSON() ([]byte, error) { 158 aSpace.Lock() 159 defer aSpace.Unlock() 160 161 m := map[string]interface{}{ 162 "Scope": aSpace.scope, 163 } 164 165 if aSpace.subnets != nil { 166 s := map[string]*PoolData{} 167 for k, v := range aSpace.subnets { 168 s[k.String()] = v 169 } 170 m["Subnets"] = s 171 } 172 173 return json.Marshal(m) 174 } 175 176 // UnmarshalJSON decodes data into the addrSpace object 177 func (aSpace *addrSpace) UnmarshalJSON(data []byte) error { 178 aSpace.Lock() 179 defer aSpace.Unlock() 180 181 m := map[string]interface{}{} 182 err := json.Unmarshal(data, &m) 183 if err != nil { 184 return err 185 } 186 187 aSpace.scope = datastore.LocalScope 188 s := m["Scope"].(string) 189 if s == datastore.GlobalScope { 190 aSpace.scope = datastore.GlobalScope 191 } 192 193 if v, ok := m["Subnets"]; ok { 194 sb, _ := json.Marshal(v) 195 var s map[string]*PoolData 196 err := json.Unmarshal(sb, &s) 197 if err != nil { 198 return err 199 } 200 for ks, v := range s { 201 k := SubnetKey{} 202 k.FromString(ks) 203 aSpace.subnets[k] = v 204 } 205 } 206 207 return nil 208 } 209 210 // CopyTo deep copies the pool data to the destination pooldata 211 func (p *PoolData) CopyTo(dstP *PoolData) error { 212 dstP.ParentKey = p.ParentKey 213 dstP.Pool = types.GetIPNetCopy(p.Pool) 214 215 if p.Range != nil { 216 dstP.Range = &AddressRange{} 217 dstP.Range.Sub = types.GetIPNetCopy(p.Range.Sub) 218 dstP.Range.Start = p.Range.Start 219 dstP.Range.End = p.Range.End 220 } 221 222 dstP.RefCount = p.RefCount 223 return nil 224 } 225 226 func (aSpace *addrSpace) CopyTo(o datastore.KVObject) error { 227 aSpace.Lock() 228 defer aSpace.Unlock() 229 230 dstAspace := o.(*addrSpace) 231 232 dstAspace.id = aSpace.id 233 dstAspace.ds = aSpace.ds 234 dstAspace.alloc = aSpace.alloc 235 dstAspace.scope = aSpace.scope 236 dstAspace.dbIndex = aSpace.dbIndex 237 dstAspace.dbExists = aSpace.dbExists 238 239 dstAspace.subnets = make(map[SubnetKey]*PoolData) 240 for k, v := range aSpace.subnets { 241 dstAspace.subnets[k] = &PoolData{} 242 v.CopyTo(dstAspace.subnets[k]) 243 } 244 245 return nil 246 } 247 248 func (aSpace *addrSpace) New() datastore.KVObject { 249 aSpace.Lock() 250 defer aSpace.Unlock() 251 252 return &addrSpace{ 253 id: aSpace.id, 254 ds: aSpace.ds, 255 alloc: aSpace.alloc, 256 scope: aSpace.scope, 257 } 258 } 259 260 // updatePoolDBOnAdd returns a closure which will add the subnet k to the address space when executed. 261 func (aSpace *addrSpace) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange, pdf bool) (func() error, error) { 262 aSpace.Lock() 263 defer aSpace.Unlock() 264 265 // Check if already allocated 266 if _, ok := aSpace.subnets[k]; ok { 267 if pdf { 268 return nil, types.InternalMaskableErrorf("predefined pool %s is already reserved", nw) 269 } 270 // This means the same pool is already allocated. updatePoolDBOnAdd is called when there 271 // is request for a pool/subpool. It should ensure there is no overlap with existing pools 272 return nil, ipamapi.ErrPoolOverlap 273 } 274 275 // If master pool, check for overlap 276 if ipr == nil { 277 if aSpace.contains(k.AddressSpace, nw) { 278 return nil, ipamapi.ErrPoolOverlap 279 } 280 // This is a new master pool, add it along with corresponding bitmask 281 aSpace.subnets[k] = &PoolData{Pool: nw, RefCount: 1} 282 return func() error { return aSpace.alloc.insertBitMask(k, nw) }, nil 283 } 284 285 // This is a new non-master pool (subPool) 286 p := &PoolData{ 287 ParentKey: SubnetKey{AddressSpace: k.AddressSpace, Subnet: k.Subnet}, 288 Pool: nw, 289 Range: ipr, 290 RefCount: 1, 291 } 292 aSpace.subnets[k] = p 293 294 // Look for parent pool 295 pp, ok := aSpace.subnets[p.ParentKey] 296 if ok { 297 aSpace.incRefCount(pp, 1) 298 return func() error { return nil }, nil 299 } 300 301 // Parent pool does not exist, add it along with corresponding bitmask 302 aSpace.subnets[p.ParentKey] = &PoolData{Pool: nw, RefCount: 1} 303 return func() error { return aSpace.alloc.insertBitMask(p.ParentKey, nw) }, nil 304 } 305 306 func (aSpace *addrSpace) updatePoolDBOnRemoval(k SubnetKey) (func() error, error) { 307 aSpace.Lock() 308 defer aSpace.Unlock() 309 310 p, ok := aSpace.subnets[k] 311 if !ok { 312 return nil, ipamapi.ErrBadPool 313 } 314 315 aSpace.incRefCount(p, -1) 316 317 c := p 318 for ok { 319 if c.RefCount == 0 { 320 delete(aSpace.subnets, k) 321 if c.Range == nil { 322 return func() error { 323 bm, err := aSpace.alloc.retrieveBitmask(k, c.Pool) 324 if err != nil { 325 return types.InternalErrorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err) 326 } 327 return bm.Destroy() 328 }, nil 329 } 330 } 331 k = c.ParentKey 332 c, ok = aSpace.subnets[k] 333 } 334 335 return func() error { return nil }, nil 336 } 337 338 func (aSpace *addrSpace) incRefCount(p *PoolData, delta int) { 339 c := p 340 ok := true 341 for ok { 342 c.RefCount += delta 343 c, ok = aSpace.subnets[c.ParentKey] 344 } 345 } 346 347 // Checks whether the passed subnet is a superset or subset of any of the subset in this config db 348 func (aSpace *addrSpace) contains(space string, nw *net.IPNet) bool { 349 for k, v := range aSpace.subnets { 350 if space == k.AddressSpace && k.ChildSubnet == "" { 351 if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) { 352 return true 353 } 354 } 355 } 356 return false 357 } 358 359 func (aSpace *addrSpace) store() datastore.DataStore { 360 aSpace.Lock() 361 defer aSpace.Unlock() 362 363 return aSpace.ds 364 }