allocator.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package ipallocator
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "github.com/dotcloud/docker/pkg/netlink"
  6. "net"
  7. "sync"
  8. )
  9. type networkSet map[iPNet]iPSet
  10. type iPNet struct {
  11. IP string
  12. Mask string
  13. }
  14. var (
  15. ErrNetworkAlreadyAllocated = errors.New("requested network overlaps with existing network")
  16. ErrNetworkAlreadyRegisterd = errors.New("requested network is already registered")
  17. ErrNoAvailableIps = errors.New("no available ips on network")
  18. ErrIPAlreadyAllocated = errors.New("ip already allocated")
  19. lock = sync.Mutex{}
  20. allocatedIPs = networkSet{}
  21. availableIPS = networkSet{}
  22. )
  23. func RegisterNetwork(network *net.IPNet) error {
  24. lock.Lock()
  25. defer lock.Unlock()
  26. routes, err := netlink.NetworkGetRoutes()
  27. if err != nil {
  28. return err
  29. }
  30. if err := checkRouteOverlaps(routes, network); err != nil {
  31. return err
  32. }
  33. if err := checkExistingNetworkOverlaps(network); err != nil {
  34. return err
  35. }
  36. n := newIPNet(network)
  37. allocatedIPs[n] = iPSet{}
  38. availableIPS[n] = iPSet{}
  39. return nil
  40. }
  41. func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
  42. lock.Lock()
  43. defer lock.Unlock()
  44. if ip == nil {
  45. next, err := getNextIp(network)
  46. if err != nil {
  47. return nil, err
  48. }
  49. return next, nil
  50. }
  51. if err := registerIP(network, ip); err != nil {
  52. return nil, err
  53. }
  54. return ip, nil
  55. }
  56. func ReleaseIP(network *net.IPNet, ip *net.IP) error {
  57. lock.Lock()
  58. defer lock.Unlock()
  59. n := newIPNet(network)
  60. existing := allocatedIPs[n]
  61. i := ipToInt(ip)
  62. existing.Remove(int(i))
  63. available := availableIPS[n]
  64. available.Push(int(i))
  65. return nil
  66. }
  67. func getNextIp(network *net.IPNet) (*net.IP, error) {
  68. var (
  69. n = newIPNet(network)
  70. available = availableIPS[n]
  71. next = available.Pop()
  72. allocated = allocatedIPs[n]
  73. ownIP = int(ipToInt(&network.IP))
  74. )
  75. if next != 0 {
  76. ip := intToIP(int32(next))
  77. allocated.Push(int(next))
  78. return ip, nil
  79. }
  80. size := int(networkSize(network.Mask))
  81. next = allocated.PullBack() + 1
  82. // size -1 for the broadcast address, -1 for the gateway address
  83. for i := 0; i < size-2; i++ {
  84. if next == ownIP {
  85. next++
  86. continue
  87. }
  88. ip := intToIP(int32(next))
  89. allocated.Push(next)
  90. return ip, nil
  91. }
  92. return nil, ErrNoAvailableIps
  93. }
  94. func registerIP(network *net.IPNet, ip *net.IP) error {
  95. existing := allocatedIPs[newIPNet(network)]
  96. if existing.Exists(int(ipToInt(ip))) {
  97. return ErrIPAlreadyAllocated
  98. }
  99. return nil
  100. }
  101. func checkRouteOverlaps(networks []netlink.Route, toCheck *net.IPNet) error {
  102. for _, network := range networks {
  103. if network.IPNet != nil && networkOverlaps(toCheck, network.IPNet) {
  104. return ErrNetworkAlreadyAllocated
  105. }
  106. }
  107. return nil
  108. }
  109. // Detects overlap between one IPNet and another
  110. func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
  111. if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
  112. return true
  113. }
  114. if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
  115. return true
  116. }
  117. return false
  118. }
  119. func checkExistingNetworkOverlaps(network *net.IPNet) error {
  120. for existing := range allocatedIPs {
  121. if newIPNet(network) == existing {
  122. return ErrNetworkAlreadyRegisterd
  123. }
  124. ex := newNetIPNet(existing)
  125. if networkOverlaps(network, ex) {
  126. return ErrNetworkAlreadyAllocated
  127. }
  128. }
  129. return nil
  130. }
  131. // Calculates the first and last IP addresses in an IPNet
  132. func networkRange(network *net.IPNet) (net.IP, net.IP) {
  133. var (
  134. netIP = network.IP.To4()
  135. firstIP = netIP.Mask(network.Mask)
  136. lastIP = net.IPv4(0, 0, 0, 0).To4()
  137. )
  138. for i := 0; i < len(lastIP); i++ {
  139. lastIP[i] = netIP[i] | ^network.Mask[i]
  140. }
  141. return firstIP, lastIP
  142. }
  143. func newIPNet(network *net.IPNet) iPNet {
  144. return iPNet{
  145. IP: string(network.IP),
  146. Mask: string(network.Mask),
  147. }
  148. }
  149. func newNetIPNet(network iPNet) *net.IPNet {
  150. return &net.IPNet{
  151. IP: []byte(network.IP),
  152. Mask: []byte(network.Mask),
  153. }
  154. }
  155. // Converts a 4 bytes IP into a 32 bit integer
  156. func ipToInt(ip *net.IP) int32 {
  157. return int32(binary.BigEndian.Uint32(ip.To4()))
  158. }
  159. // Converts 32 bit integer into a 4 bytes IP address
  160. func intToIP(n int32) *net.IP {
  161. b := make([]byte, 4)
  162. binary.BigEndian.PutUint32(b, uint32(n))
  163. ip := net.IP(b)
  164. return &ip
  165. }
  166. // Given a netmask, calculates the number of available hosts
  167. func networkSize(mask net.IPMask) int32 {
  168. m := net.IPv4Mask(0, 0, 0, 0)
  169. for i := 0; i < net.IPv4len; i++ {
  170. m[i] = ^mask[i]
  171. }
  172. return int32(binary.BigEndian.Uint32(m)) + 1
  173. }