allocator.go 4.8 KB

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