github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/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{
    19  		{"172.17.0.0/16", 16},
    20  		{"172.18.0.0/16", 16},
    21  		{"172.19.0.0/16", 16},
    22  		{"172.20.0.0/14", 16},
    23  		{"172.24.0.0/14", 16},
    24  		{"172.28.0.0/14", 16},
    25  		{"192.168.0.0/16", 20},
    26  	}
    27  	globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
    28  )
    29  
    30  // NetworkToSplit represent a network that has to be split in chunks with mask length Size.
    31  // Each subnet in the set is derived from the Base pool. Base is to be passed
    32  // in CIDR format.
    33  // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
    34  // 10.10.[0-255].0/24 address pools
    35  type NetworkToSplit struct {
    36  	Base string `json:"base"`
    37  	Size int    `json:"size"`
    38  }
    39  
    40  func init() {
    41  	var err error
    42  	if predefinedGlobalScopeDefaultNetworks, err = SplitNetworks(globalScopeDefaultNetworks); err != nil {
    43  		panic("failed to initialize the global scope default address pool: " + err.Error())
    44  	}
    45  
    46  	if predefinedLocalScopeDefaultNetworks, err = SplitNetworks(localScopeDefaultNetworks); err != nil {
    47  		panic("failed to initialize the local scope default address pool: " + err.Error())
    48  	}
    49  }
    50  
    51  // ConfigGlobalScopeDefaultNetworks configures global default pool.
    52  // Ideally this will be called from SwarmKit as part of swarm init
    53  func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
    54  	if defaultAddressPool == nil {
    55  		return nil
    56  	}
    57  	mutex.Lock()
    58  	defer mutex.Unlock()
    59  	defaultNetworks, err := SplitNetworks(defaultAddressPool)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	predefinedGlobalScopeDefaultNetworks = defaultNetworks
    64  	return nil
    65  }
    66  
    67  // GetGlobalScopeDefaultNetworks returns a copy of the global-sopce network list.
    68  func GetGlobalScopeDefaultNetworks() []*net.IPNet {
    69  	mutex.Lock()
    70  	defer mutex.Unlock()
    71  	return append([]*net.IPNet(nil), predefinedGlobalScopeDefaultNetworks...)
    72  }
    73  
    74  // GetLocalScopeDefaultNetworks returns a copy of the default local-scope network list.
    75  func GetLocalScopeDefaultNetworks() []*net.IPNet {
    76  	return append([]*net.IPNet(nil), predefinedLocalScopeDefaultNetworks...)
    77  }
    78  
    79  // SplitNetworks takes a slice of networks, split them accordingly and returns them
    80  func SplitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
    81  	localPools := make([]*net.IPNet, 0, len(list))
    82  
    83  	for _, p := range list {
    84  		_, b, err := net.ParseCIDR(p.Base)
    85  		if err != nil {
    86  			return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err)
    87  		}
    88  		ones, _ := b.Mask.Size()
    89  		if p.Size <= 0 || p.Size < ones {
    90  			return nil, fmt.Errorf("invalid pools size: %d", p.Size)
    91  		}
    92  		localPools = append(localPools, splitNetwork(p.Size, b)...)
    93  	}
    94  	return localPools, nil
    95  }
    96  
    97  func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
    98  	one, bits := base.Mask.Size()
    99  	mask := net.CIDRMask(size, bits)
   100  	n := 1 << uint(size-one)
   101  	s := uint(bits - size)
   102  	list := make([]*net.IPNet, 0, n)
   103  
   104  	for i := 0; i < n; i++ {
   105  		ip := copyIP(base.IP)
   106  		addIntToIP(ip, uint(i<<s))
   107  		list = append(list, &net.IPNet{IP: ip, Mask: mask})
   108  	}
   109  	return list
   110  }
   111  
   112  func copyIP(from net.IP) net.IP {
   113  	ip := make([]byte, len(from))
   114  	copy(ip, from)
   115  	return ip
   116  }
   117  
   118  func addIntToIP(array net.IP, ordinal uint) {
   119  	for i := len(array) - 1; i >= 0; i-- {
   120  		array[i] |= (byte)(ordinal & 0xff)
   121  		ordinal >>= 8
   122  	}
   123  }