allocator.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package ipallocator
  2. import (
  3. "errors"
  4. "math/big"
  5. "net"
  6. "sync"
  7. log "github.com/Sirupsen/logrus"
  8. "github.com/docker/docker/daemon/networkdriver"
  9. )
  10. // allocatedMap is thread-unsafe set of allocated IP
  11. type allocatedMap struct {
  12. p map[string]struct{}
  13. last *big.Int
  14. begin *big.Int
  15. end *big.Int
  16. }
  17. func newAllocatedMap(network *net.IPNet) *allocatedMap {
  18. firstIP, lastIP := networkdriver.NetworkRange(network)
  19. begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
  20. end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1))
  21. return &allocatedMap{
  22. p: make(map[string]struct{}),
  23. begin: begin,
  24. end: end,
  25. last: big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin
  26. }
  27. }
  28. type networkSet map[string]*allocatedMap
  29. var (
  30. ErrNoAvailableIPs = errors.New("no available ip addresses on network")
  31. ErrIPAlreadyAllocated = errors.New("ip already allocated")
  32. ErrIPOutOfRange = errors.New("requested ip is out of range")
  33. ErrNetworkAlreadyRegistered = errors.New("network already registered")
  34. ErrBadSubnet = errors.New("network does not contain specified subnet")
  35. )
  36. var (
  37. lock = sync.Mutex{}
  38. allocatedIPs = networkSet{}
  39. )
  40. // RegisterSubnet registers network in global allocator with bounds
  41. // defined by subnet. If you want to use network range you must call
  42. // this method before first RequestIP, otherwise full network range will be used
  43. func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
  44. lock.Lock()
  45. defer lock.Unlock()
  46. key := network.String()
  47. if _, ok := allocatedIPs[key]; ok {
  48. return ErrNetworkAlreadyRegistered
  49. }
  50. n := newAllocatedMap(network)
  51. beginIP, endIP := networkdriver.NetworkRange(subnet)
  52. begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1))
  53. end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1))
  54. // Check that subnet is within network
  55. if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) {
  56. return ErrBadSubnet
  57. }
  58. n.begin.Set(begin)
  59. n.end.Set(end)
  60. n.last.Sub(begin, big.NewInt(1))
  61. allocatedIPs[key] = n
  62. return nil
  63. }
  64. // RequestIP requests an available ip from the given network. It
  65. // will return the next available ip if the ip provided is nil. If the
  66. // ip provided is not nil it will validate that the provided ip is available
  67. // for use or return an error
  68. func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
  69. lock.Lock()
  70. defer lock.Unlock()
  71. key := network.String()
  72. allocated, ok := allocatedIPs[key]
  73. if !ok {
  74. allocated = newAllocatedMap(network)
  75. allocatedIPs[key] = allocated
  76. }
  77. if ip == nil {
  78. return allocated.getNextIP()
  79. }
  80. return allocated.checkIP(ip)
  81. }
  82. // ReleaseIP adds the provided ip back into the pool of
  83. // available ips to be returned for use.
  84. func ReleaseIP(network *net.IPNet, ip net.IP) error {
  85. lock.Lock()
  86. defer lock.Unlock()
  87. if allocated, exists := allocatedIPs[network.String()]; exists {
  88. delete(allocated.p, ip.String())
  89. }
  90. return nil
  91. }
  92. func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
  93. if _, ok := allocated.p[ip.String()]; ok {
  94. return nil, ErrIPAlreadyAllocated
  95. }
  96. pos := ipToBigInt(ip)
  97. // Verify that the IP address is within our network range.
  98. if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
  99. return nil, ErrIPOutOfRange
  100. }
  101. // Register the IP.
  102. allocated.p[ip.String()] = struct{}{}
  103. return ip, nil
  104. }
  105. // return an available ip if one is currently available. If not,
  106. // return the next available ip for the nextwork
  107. func (allocated *allocatedMap) getNextIP() (net.IP, error) {
  108. pos := big.NewInt(0).Set(allocated.last)
  109. allRange := big.NewInt(0).Sub(allocated.end, allocated.begin)
  110. for i := big.NewInt(0); i.Cmp(allRange) <= 0; i.Add(i, big.NewInt(1)) {
  111. pos.Add(pos, big.NewInt(1))
  112. if pos.Cmp(allocated.end) == 1 {
  113. pos.Set(allocated.begin)
  114. }
  115. if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
  116. continue
  117. }
  118. allocated.p[bigIntToIP(pos).String()] = struct{}{}
  119. allocated.last.Set(pos)
  120. return bigIntToIP(pos), nil
  121. }
  122. return nil, ErrNoAvailableIPs
  123. }
  124. // Converts a 4 bytes IP into a 128 bit integer
  125. func ipToBigInt(ip net.IP) *big.Int {
  126. x := big.NewInt(0)
  127. if ip4 := ip.To4(); ip4 != nil {
  128. return x.SetBytes(ip4)
  129. }
  130. if ip6 := ip.To16(); ip6 != nil {
  131. return x.SetBytes(ip6)
  132. }
  133. log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
  134. return nil
  135. }
  136. // Converts 128 bit integer into a 4 bytes IP address
  137. func bigIntToIP(v *big.Int) net.IP {
  138. return net.IP(v.Bytes())
  139. }