utils.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Package ipamutils provides utility functions for ipam management
  2. package ipamutils
  3. import (
  4. "fmt"
  5. "net"
  6. "sync"
  7. )
  8. var (
  9. // PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
  10. // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks`
  11. PredefinedLocalScopeDefaultNetworks []*net.IPNet
  12. // PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8
  13. // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks`
  14. PredefinedGlobalScopeDefaultNetworks []*net.IPNet
  15. mutex sync.Mutex
  16. localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
  17. {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
  18. {"192.168.0.0/16", 20}}
  19. globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
  20. )
  21. // NetworkToSplit represent a network that has to be split in chunks with mask length Size.
  22. // Each subnet in the set is derived from the Base pool. Base is to be passed
  23. // in CIDR format.
  24. // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
  25. // 10.10.[0-255].0/24 address pools
  26. type NetworkToSplit struct {
  27. Base string `json:"base"`
  28. Size int `json:"size"`
  29. }
  30. func init() {
  31. var err error
  32. if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil {
  33. //we are going to panic in case of error as we should never get into this state
  34. panic("InitAddressPools failed to initialize the global scope default address pool")
  35. }
  36. if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); 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 local scope default address pool")
  39. }
  40. }
  41. // configDefaultNetworks configures local as well global default pool based on input
  42. func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error {
  43. mutex.Lock()
  44. defer mutex.Unlock()
  45. defaultNetworks, err := splitNetworks(defaultAddressPool)
  46. if err != nil {
  47. return err
  48. }
  49. *result = defaultNetworks
  50. return nil
  51. }
  52. // GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks
  53. func GetGlobalScopeDefaultNetworks() []*net.IPNet {
  54. mutex.Lock()
  55. defer mutex.Unlock()
  56. return PredefinedGlobalScopeDefaultNetworks
  57. }
  58. // GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks
  59. func GetLocalScopeDefaultNetworks() []*net.IPNet {
  60. mutex.Lock()
  61. defer mutex.Unlock()
  62. return PredefinedLocalScopeDefaultNetworks
  63. }
  64. // ConfigGlobalScopeDefaultNetworks configures global default pool.
  65. // Ideally this will be called from SwarmKit as part of swarm init
  66. func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
  67. if defaultAddressPool == nil {
  68. defaultAddressPool = globalScopeDefaultNetworks
  69. }
  70. return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks)
  71. }
  72. // ConfigLocalScopeDefaultNetworks configures local default pool.
  73. // Ideally this will be called during libnetwork init
  74. func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
  75. if defaultAddressPool == nil {
  76. return nil
  77. }
  78. return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks)
  79. }
  80. // splitNetworks takes a slice of networks, split them accordingly and returns them
  81. func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
  82. localPools := make([]*net.IPNet, 0, len(list))
  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. func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
  97. one, bits := base.Mask.Size()
  98. mask := net.CIDRMask(size, bits)
  99. n := 1 << uint(size-one)
  100. s := uint(bits - size)
  101. list := make([]*net.IPNet, 0, n)
  102. for i := 0; i < n; i++ {
  103. ip := copyIP(base.IP)
  104. addIntToIP(ip, uint(i<<s))
  105. list = append(list, &net.IPNet{IP: ip, Mask: mask})
  106. }
  107. return list
  108. }
  109. func copyIP(from net.IP) net.IP {
  110. ip := make([]byte, len(from))
  111. copy(ip, from)
  112. return ip
  113. }
  114. func addIntToIP(array net.IP, ordinal uint) {
  115. for i := len(array) - 1; i >= 0; i-- {
  116. array[i] |= (byte)(ordinal & 0xff)
  117. ordinal >>= 8
  118. }
  119. }