github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/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/libnetwork/datastore"
    11  	"github.com/docker/libnetwork/ipamapi"
    12  	"github.com/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": string(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 == string(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  func (aSpace *addrSpace) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange, pdf bool) (func() error, error) {
   261  	aSpace.Lock()
   262  	defer aSpace.Unlock()
   263  
   264  	// Check if already allocated
   265  	if p, ok := aSpace.subnets[k]; ok {
   266  		if pdf {
   267  			return nil, types.InternalMaskableErrorf("predefined pool %s is already reserved", nw)
   268  		}
   269  		aSpace.incRefCount(p, 1)
   270  		return func() error { return nil }, nil
   271  	}
   272  
   273  	// If master pool, check for overlap
   274  	if ipr == nil {
   275  		if aSpace.contains(k.AddressSpace, nw) {
   276  			return nil, ipamapi.ErrPoolOverlap
   277  		}
   278  		// This is a new master pool, add it along with corresponding bitmask
   279  		aSpace.subnets[k] = &PoolData{Pool: nw, RefCount: 1}
   280  		return func() error { return aSpace.alloc.insertBitMask(k, nw) }, nil
   281  	}
   282  
   283  	// This is a new non-master pool
   284  	p := &PoolData{
   285  		ParentKey: SubnetKey{AddressSpace: k.AddressSpace, Subnet: k.Subnet},
   286  		Pool:      nw,
   287  		Range:     ipr,
   288  		RefCount:  1,
   289  	}
   290  	aSpace.subnets[k] = p
   291  
   292  	// Look for parent pool
   293  	pp, ok := aSpace.subnets[p.ParentKey]
   294  	if ok {
   295  		aSpace.incRefCount(pp, 1)
   296  		return func() error { return nil }, nil
   297  	}
   298  
   299  	// Parent pool does not exist, add it along with corresponding bitmask
   300  	aSpace.subnets[p.ParentKey] = &PoolData{Pool: nw, RefCount: 1}
   301  	return func() error { return aSpace.alloc.insertBitMask(p.ParentKey, nw) }, nil
   302  }
   303  
   304  func (aSpace *addrSpace) updatePoolDBOnRemoval(k SubnetKey) (func() error, error) {
   305  	aSpace.Lock()
   306  	defer aSpace.Unlock()
   307  
   308  	p, ok := aSpace.subnets[k]
   309  	if !ok {
   310  		return nil, ipamapi.ErrBadPool
   311  	}
   312  
   313  	aSpace.incRefCount(p, -1)
   314  
   315  	c := p
   316  	for ok {
   317  		if c.RefCount == 0 {
   318  			delete(aSpace.subnets, k)
   319  			if c.Range == nil {
   320  				return func() error {
   321  					bm, err := aSpace.alloc.retrieveBitmask(k, c.Pool)
   322  					if err != nil {
   323  						return types.InternalErrorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err)
   324  					}
   325  					return bm.Destroy()
   326  				}, nil
   327  			}
   328  		}
   329  		k = c.ParentKey
   330  		c, ok = aSpace.subnets[k]
   331  	}
   332  
   333  	return func() error { return nil }, nil
   334  }
   335  
   336  func (aSpace *addrSpace) incRefCount(p *PoolData, delta int) {
   337  	c := p
   338  	ok := true
   339  	for ok {
   340  		c.RefCount += delta
   341  		c, ok = aSpace.subnets[c.ParentKey]
   342  	}
   343  }
   344  
   345  // Checks whether the passed subnet is a superset or subset of any of the subset in this config db
   346  func (aSpace *addrSpace) contains(space string, nw *net.IPNet) bool {
   347  	for k, v := range aSpace.subnets {
   348  		if space == k.AddressSpace && k.ChildSubnet == "" {
   349  			if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) {
   350  				return true
   351  			}
   352  		}
   353  	}
   354  	return false
   355  }
   356  
   357  func (aSpace *addrSpace) store() datastore.DataStore {
   358  	aSpace.Lock()
   359  	defer aSpace.Unlock()
   360  
   361  	return aSpace.ds
   362  }