utils.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // Package ipamutils provides utility functions for ipam management
  2. package ipamutils
  3. import (
  4. "fmt"
  5. "net"
  6. "sync"
  7. "github.com/sirupsen/logrus"
  8. )
  9. var (
  10. // PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
  11. // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks`
  12. PredefinedBroadNetworks []*net.IPNet
  13. // PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
  14. // (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
  15. PredefinedGranularNetworks []*net.IPNet
  16. initNetworksOnce sync.Once
  17. defaultBroadNetwork = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
  18. {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
  19. {"192.168.0.0/16", 20}}
  20. defaultGranularNetwork = []*NetworkToSplit{{"10.0.0.0/8", 24}}
  21. )
  22. // NetworkToSplit represent a network that has to be split in chunks with mask length Size.
  23. // Each subnet in the set is derived from the Base pool. Base is to be passed
  24. // in CIDR format.
  25. // Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
  26. // 10.10.[0-255].0/24 address pools
  27. type NetworkToSplit struct {
  28. Base string `json:"base"`
  29. Size int `json:"size"`
  30. }
  31. // InitNetworks initializes the broad network pool and the granular network pool
  32. func InitNetworks(defaultAddressPool []*NetworkToSplit) {
  33. initNetworksOnce.Do(func() {
  34. // error ingnored should never fail
  35. PredefinedGranularNetworks, _ = splitNetworks(defaultGranularNetwork)
  36. if defaultAddressPool == nil {
  37. defaultAddressPool = defaultBroadNetwork
  38. }
  39. var err error
  40. if PredefinedBroadNetworks, err = splitNetworks(defaultAddressPool); err != nil {
  41. logrus.WithError(err).Error("InitAddressPools failed to initialize the default address pool")
  42. }
  43. })
  44. }
  45. // splitNetworks takes a slice of networks, split them accordingly and returns them
  46. func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
  47. localPools := make([]*net.IPNet, 0, len(list))
  48. for _, p := range list {
  49. _, b, err := net.ParseCIDR(p.Base)
  50. if err != nil {
  51. return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err)
  52. }
  53. ones, _ := b.Mask.Size()
  54. if p.Size <= 0 || p.Size < ones {
  55. return nil, fmt.Errorf("invalid pools size: %d", p.Size)
  56. }
  57. localPools = append(localPools, splitNetwork(p.Size, b)...)
  58. }
  59. return localPools, nil
  60. }
  61. func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
  62. one, bits := base.Mask.Size()
  63. mask := net.CIDRMask(size, bits)
  64. n := 1 << uint(size-one)
  65. s := uint(bits - size)
  66. list := make([]*net.IPNet, 0, n)
  67. for i := 0; i < n; i++ {
  68. ip := copyIP(base.IP)
  69. addIntToIP(ip, uint(i<<s))
  70. list = append(list, &net.IPNet{IP: ip, Mask: mask})
  71. }
  72. return list
  73. }
  74. func copyIP(from net.IP) net.IP {
  75. ip := make([]byte, len(from))
  76. copy(ip, from)
  77. return ip
  78. }
  79. func addIntToIP(array net.IP, ordinal uint) {
  80. for i := len(array) - 1; i >= 0; i-- {
  81. array[i] |= (byte)(ordinal & 0xff)
  82. ordinal >>= 8
  83. }
  84. }