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