allocator.go 3.6 KB

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