allocator.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
  18. ErrNoAvailableIps = errors.New("no available ips on network")
  19. ErrIPAlreadyAllocated = errors.New("ip already allocated")
  20. lock = sync.Mutex{}
  21. allocatedIPs = networkSet{}
  22. availableIPS = networkSet{}
  23. )
  24. func RegisterNetwork(network *net.IPNet, nameservers []string) error {
  25. lock.Lock()
  26. defer lock.Unlock()
  27. if err := checkExistingNetworkOverlaps(network); err != nil {
  28. return err
  29. }
  30. routes, err := netlink.NetworkGetRoutes()
  31. if err != nil {
  32. return err
  33. }
  34. if err := checkRouteOverlaps(routes, network); err != nil {
  35. return err
  36. }
  37. if err := checkNameserverOverlaps(nameservers, network); err != nil {
  38. return err
  39. }
  40. n := newIPNet(network)
  41. allocatedIPs[n] = &iPSet{}
  42. availableIPS[n] = &iPSet{}
  43. return nil
  44. }
  45. func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
  46. lock.Lock()
  47. defer lock.Unlock()
  48. if ip == nil {
  49. next, err := getNextIp(network)
  50. if err != nil {
  51. return nil, err
  52. }
  53. return next, nil
  54. }
  55. if err := registerIP(network, ip); err != nil {
  56. return nil, err
  57. }
  58. return ip, nil
  59. }
  60. func ReleaseIP(network *net.IPNet, ip *net.IP) error {
  61. lock.Lock()
  62. defer lock.Unlock()
  63. var (
  64. first, _ = networkRange(network)
  65. base = ipToInt(&first)
  66. n = newIPNet(network)
  67. existing = allocatedIPs[n]
  68. available = availableIPS[n]
  69. i = ipToInt(ip)
  70. pos = i - base
  71. )
  72. existing.Remove(int(pos))
  73. available.Push(int(pos))
  74. return nil
  75. }
  76. func getNextIp(network *net.IPNet) (*net.IP, error) {
  77. var (
  78. n = newIPNet(network)
  79. ownIP = ipToInt(&network.IP)
  80. available = availableIPS[n]
  81. allocated = allocatedIPs[n]
  82. first, _ = networkRange(network)
  83. base = ipToInt(&first)
  84. pos = int32(available.Pop())
  85. )
  86. // We pop and push the position not the ip
  87. if pos != 0 {
  88. ip := intToIP(int32(base + pos))
  89. allocated.Push(int(pos))
  90. return ip, nil
  91. }
  92. var (
  93. size = int(networkSize(network.Mask))
  94. max = int32(size - 2) // size -1 for the broadcast address, -1 for the gateway address
  95. )
  96. if pos = int32(allocated.PullBack()); pos == 0 {
  97. pos = 1
  98. }
  99. for i := int32(0); i < max; i++ {
  100. next := int32(base + pos)
  101. pos = pos%max + 1
  102. if next == ownIP {
  103. continue
  104. }
  105. ip := intToIP(next)
  106. allocated.Push(int(pos))
  107. return ip, nil
  108. }
  109. return nil, ErrNoAvailableIps
  110. }
  111. func registerIP(network *net.IPNet, ip *net.IP) error {
  112. existing := allocatedIPs[newIPNet(network)]
  113. // checking position not ip
  114. if existing.Exists(int(ipToInt(ip))) {
  115. return ErrIPAlreadyAllocated
  116. }
  117. return nil
  118. }
  119. func checkRouteOverlaps(networks []netlink.Route, toCheck *net.IPNet) error {
  120. for _, network := range networks {
  121. if network.IPNet != nil && networkOverlaps(toCheck, network.IPNet) {
  122. return ErrNetworkAlreadyAllocated
  123. }
  124. }
  125. return nil
  126. }
  127. // Detects overlap between one IPNet and another
  128. func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
  129. if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
  130. return true
  131. }
  132. if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
  133. return true
  134. }
  135. return false
  136. }
  137. func checkExistingNetworkOverlaps(network *net.IPNet) error {
  138. for existing := range allocatedIPs {
  139. if newIPNet(network) == existing {
  140. return ErrNetworkAlreadyRegisterd
  141. }
  142. ex := newNetIPNet(existing)
  143. if networkOverlaps(network, ex) {
  144. return ErrNetworkAlreadyAllocated
  145. }
  146. }
  147. return nil
  148. }
  149. // Calculates the first and last IP addresses in an IPNet
  150. func networkRange(network *net.IPNet) (net.IP, net.IP) {
  151. var (
  152. netIP = network.IP.To4()
  153. firstIP = netIP.Mask(network.Mask)
  154. lastIP = net.IPv4(0, 0, 0, 0).To4()
  155. )
  156. for i := 0; i < len(lastIP); i++ {
  157. lastIP[i] = netIP[i] | ^network.Mask[i]
  158. }
  159. return firstIP, lastIP
  160. }
  161. func newIPNet(network *net.IPNet) iPNet {
  162. return iPNet{
  163. IP: string(network.IP),
  164. Mask: string(network.Mask),
  165. }
  166. }
  167. func newNetIPNet(network iPNet) *net.IPNet {
  168. return &net.IPNet{
  169. IP: []byte(network.IP),
  170. Mask: []byte(network.Mask),
  171. }
  172. }
  173. // Converts a 4 bytes IP into a 32 bit integer
  174. func ipToInt(ip *net.IP) int32 {
  175. return int32(binary.BigEndian.Uint32(ip.To4()))
  176. }
  177. // Converts 32 bit integer into a 4 bytes IP address
  178. func intToIP(n int32) *net.IP {
  179. b := make([]byte, 4)
  180. binary.BigEndian.PutUint32(b, uint32(n))
  181. ip := net.IP(b)
  182. return &ip
  183. }
  184. // Given a netmask, calculates the number of available hosts
  185. func networkSize(mask net.IPMask) int32 {
  186. m := net.IPv4Mask(0, 0, 0, 0)
  187. for i := 0; i < net.IPv4len; i++ {
  188. m[i] = ^mask[i]
  189. }
  190. return int32(binary.BigEndian.Uint32(m)) + 1
  191. }
  192. func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
  193. if len(nameservers) > 0 {
  194. for _, ns := range nameservers {
  195. _, nsNetwork, err := net.ParseCIDR(ns)
  196. if err != nil {
  197. return err
  198. }
  199. if networkOverlaps(toCheck, nsNetwork) {
  200. return ErrNetworkOverlapsWithNameservers
  201. }
  202. }
  203. }
  204. return nil
  205. }