sandboxdata.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package libnetwork
  2. import (
  3. "container/heap"
  4. "fmt"
  5. "sync"
  6. "github.com/Sirupsen/logrus"
  7. "github.com/docker/libnetwork/sandbox"
  8. )
  9. type epHeap []*endpoint
  10. type sandboxData struct {
  11. sbox sandbox.Sandbox
  12. refCnt int
  13. endpoints epHeap
  14. sync.Mutex
  15. }
  16. func (eh epHeap) Len() int { return len(eh) }
  17. func (eh epHeap) Less(i, j int) bool {
  18. eh[i].Lock()
  19. eh[j].Lock()
  20. defer eh[j].Unlock()
  21. defer eh[i].Unlock()
  22. if eh[i].container.config.prio == eh[j].container.config.prio {
  23. return eh[i].network.Name() < eh[j].network.Name()
  24. }
  25. return eh[i].container.config.prio > eh[j].container.config.prio
  26. }
  27. func (eh epHeap) Swap(i, j int) { eh[i], eh[j] = eh[j], eh[i] }
  28. func (eh *epHeap) Push(x interface{}) {
  29. *eh = append(*eh, x.(*endpoint))
  30. }
  31. func (eh *epHeap) Pop() interface{} {
  32. old := *eh
  33. n := len(old)
  34. x := old[n-1]
  35. *eh = old[0 : n-1]
  36. return x
  37. }
  38. func (s *sandboxData) updateGateway(ep *endpoint) error {
  39. sb := s.sandbox()
  40. sb.UnsetGateway()
  41. sb.UnsetGatewayIPv6()
  42. if ep == nil {
  43. return nil
  44. }
  45. ep.Lock()
  46. joinInfo := ep.joinInfo
  47. ep.Unlock()
  48. if err := sb.SetGateway(joinInfo.gw); err != nil {
  49. return fmt.Errorf("failed to set gateway while updating gateway: %v", err)
  50. }
  51. if err := sb.SetGatewayIPv6(joinInfo.gw6); err != nil {
  52. return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err)
  53. }
  54. return nil
  55. }
  56. func (s *sandboxData) addEndpoint(ep *endpoint) error {
  57. ep.Lock()
  58. joinInfo := ep.joinInfo
  59. ifaces := ep.iFaces
  60. ep.Unlock()
  61. sb := s.sandbox()
  62. for _, i := range ifaces {
  63. var ifaceOptions []sandbox.IfaceOption
  64. ifaceOptions = append(ifaceOptions, sb.InterfaceOptions().Address(&i.addr),
  65. sb.InterfaceOptions().Routes(i.routes))
  66. if i.addrv6.IP.To16() != nil {
  67. ifaceOptions = append(ifaceOptions,
  68. sb.InterfaceOptions().AddressIPv6(&i.addrv6))
  69. }
  70. if err := sb.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
  71. return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
  72. }
  73. }
  74. if joinInfo != nil {
  75. // Set up non-interface routes.
  76. for _, r := range ep.joinInfo.StaticRoutes {
  77. if err := sb.AddStaticRoute(r); err != nil {
  78. return fmt.Errorf("failed to add static route %s: %v", r.Destination.String(), err)
  79. }
  80. }
  81. }
  82. s.Lock()
  83. heap.Push(&s.endpoints, ep)
  84. highEp := s.endpoints[0]
  85. s.Unlock()
  86. if ep == highEp {
  87. if err := s.updateGateway(ep); err != nil {
  88. return err
  89. }
  90. }
  91. return nil
  92. }
  93. func (s *sandboxData) rmEndpoint(ep *endpoint) {
  94. ep.Lock()
  95. joinInfo := ep.joinInfo
  96. ep.Unlock()
  97. sb := s.sandbox()
  98. for _, i := range sb.Info().Interfaces() {
  99. // Only remove the interfaces owned by this endpoint from the sandbox.
  100. if ep.hasInterface(i.SrcName()) {
  101. if err := i.Remove(); err != nil {
  102. logrus.Debugf("Remove interface failed: %v", err)
  103. }
  104. }
  105. }
  106. // Remove non-interface routes.
  107. for _, r := range joinInfo.StaticRoutes {
  108. if err := sb.RemoveStaticRoute(r); err != nil {
  109. logrus.Debugf("Remove route failed: %v", err)
  110. }
  111. }
  112. // We don't check if s.endpoints is empty here because
  113. // it should never be empty during a rmEndpoint call and
  114. // if it is we will rightfully panic here
  115. s.Lock()
  116. highEpBefore := s.endpoints[0]
  117. var (
  118. i int
  119. e *endpoint
  120. )
  121. for i, e = range s.endpoints {
  122. if e == ep {
  123. break
  124. }
  125. }
  126. heap.Remove(&s.endpoints, i)
  127. var highEpAfter *endpoint
  128. if len(s.endpoints) > 0 {
  129. highEpAfter = s.endpoints[0]
  130. }
  131. s.Unlock()
  132. if highEpBefore != highEpAfter {
  133. s.updateGateway(highEpAfter)
  134. }
  135. }
  136. func (s *sandboxData) sandbox() sandbox.Sandbox {
  137. s.Lock()
  138. defer s.Unlock()
  139. return s.sbox
  140. }
  141. func (c *controller) sandboxAdd(key string, create bool, ep *endpoint) (sandbox.Sandbox, error) {
  142. c.Lock()
  143. sData, ok := c.sandboxes[key]
  144. c.Unlock()
  145. if !ok {
  146. sb, err := sandbox.NewSandbox(key, create)
  147. if err != nil {
  148. return nil, fmt.Errorf("failed to create new sandbox: %v", err)
  149. }
  150. sData = &sandboxData{
  151. sbox: sb,
  152. endpoints: epHeap{},
  153. }
  154. heap.Init(&sData.endpoints)
  155. c.Lock()
  156. c.sandboxes[key] = sData
  157. c.Unlock()
  158. }
  159. if err := sData.addEndpoint(ep); err != nil {
  160. return nil, err
  161. }
  162. return sData.sandbox(), nil
  163. }
  164. func (c *controller) sandboxRm(key string, ep *endpoint) {
  165. c.Lock()
  166. sData := c.sandboxes[key]
  167. c.Unlock()
  168. sData.rmEndpoint(ep)
  169. }
  170. func (c *controller) sandboxGet(key string) sandbox.Sandbox {
  171. c.Lock()
  172. sData, ok := c.sandboxes[key]
  173. c.Unlock()
  174. if !ok {
  175. return nil
  176. }
  177. return sData.sandbox()
  178. }
  179. func (c *controller) LeaveAll(id string) error {
  180. c.Lock()
  181. sData, ok := c.sandboxes[sandbox.GenerateKey(id)]
  182. c.Unlock()
  183. if !ok {
  184. c.Unlock()
  185. return fmt.Errorf("could not find sandbox for container id %s", id)
  186. }
  187. sData.Lock()
  188. eps := make([]*endpoint, len(sData.endpoints))
  189. for i, ep := range sData.endpoints {
  190. eps[i] = ep
  191. }
  192. sData.Unlock()
  193. for _, ep := range eps {
  194. if err := ep.Leave(id); err != nil {
  195. logrus.Warnf("Failed leaving endpoint id %s: %v\n", ep.ID(), err)
  196. }
  197. }
  198. sData.sandbox().Destroy()
  199. delete(c.sandboxes, sandbox.GenerateKey(id))
  200. return nil
  201. }