package defaultipam import ( "fmt" "net/netip" "strings" "github.com/moby/moby/v2/daemon/libnetwork/internal/addrset" "github.com/moby/moby/v2/daemon/libnetwork/types" ) // PoolID is the pointer to the configured pools in each address space type PoolID struct { AddressSpace string SubnetKey } // PoolData contains the configured pool data type PoolData struct { addrs *addrset.AddrSet children map[netip.Prefix]struct{} // Whether to implicitly release the pool once it no longer has any children. autoRelease bool } // SubnetKey is the composite key to an address pool within an address space. type SubnetKey struct { Subnet, ChildSubnet netip.Prefix } func (k SubnetKey) Is6() bool { return k.Subnet.Addr().Is6() } // PoolIDFromString creates a new PoolID and populates the SubnetKey object // reading it from the given string. func PoolIDFromString(str string) (pID PoolID, err error) { if str == "" { return pID, types.InvalidParameterErrorf("invalid string form for subnetkey: %s", str) } p := strings.Split(str, "/") if len(p) != 3 && len(p) != 5 { return pID, types.InvalidParameterErrorf("invalid string form for subnetkey: %s", str) } pID.AddressSpace = p[0] pID.Subnet, err = netip.ParsePrefix(p[1] + "/" + p[2]) if err != nil { return pID, types.InvalidParameterErrorf("invalid string form for subnetkey: %s", str) } if len(p) == 5 { pID.ChildSubnet, err = netip.ParsePrefix(p[3] + "/" + p[4]) if err != nil { return pID, types.InvalidParameterErrorf("invalid string form for subnetkey: %s", str) } } return pID, nil } // String returns the string form of the SubnetKey object func (s *PoolID) String() string { if s.ChildSubnet == (netip.Prefix{}) { return s.AddressSpace + "/" + s.Subnet.String() } else { return s.AddressSpace + "/" + s.Subnet.String() + "/" + s.ChildSubnet.String() } } // String returns the string form of the PoolData object func (p *PoolData) String() string { return fmt.Sprintf("PoolData[Children: %d]", len(p.children)) } // mergeIter is used to iterate on both 'a' and 'b' at the same time while // maintaining the total order that would arise if both were merged and then // sorted. Both 'a' and 'b' have to be sorted beforehand. type mergeIter struct { a, b []netip.Prefix ia, ib int cmp func(a, b netip.Prefix) int lastA bool } func newMergeIter(a, b []netip.Prefix, cmp func(a, b netip.Prefix) int) *mergeIter { iter := &mergeIter{ a: a, b: b, cmp: cmp, } iter.lastA = iter.nextA() return iter } func (it *mergeIter) Get() netip.Prefix { if it.ia+it.ib >= len(it.a)+len(it.b) { return netip.Prefix{} } if it.lastA { return it.a[it.ia] } return it.b[it.ib] } func (it *mergeIter) Inc() { if it.lastA { it.ia++ } else { it.ib++ } it.lastA = it.nextA() } func (it *mergeIter) nextA() bool { if it.ia < len(it.a) && it.ib < len(it.b) && it.cmp(it.a[it.ia], it.b[it.ib]) <= 0 { return true } else if it.ia < len(it.a) && it.ib >= len(it.b) { return true } return false }