sandbox_linux.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package libnetwork
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "time"
  7. "github.com/containerd/log"
  8. "github.com/docker/docker/libnetwork/osl"
  9. "github.com/docker/docker/libnetwork/types"
  10. )
  11. func releaseOSSboxResources(ns *osl.Namespace, ep *Endpoint) {
  12. for _, i := range ns.Interfaces() {
  13. // Only remove the interfaces owned by this endpoint from the sandbox.
  14. if ep.hasInterface(i.SrcName()) {
  15. if err := i.Remove(); err != nil {
  16. log.G(context.TODO()).Debugf("Remove interface %s failed: %v", i.SrcName(), err)
  17. }
  18. }
  19. }
  20. ep.mu.Lock()
  21. joinInfo := ep.joinInfo
  22. vip := ep.virtualIP
  23. lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR
  24. ep.mu.Unlock()
  25. if len(vip) > 0 && lbModeIsDSR {
  26. ipNet := &net.IPNet{IP: vip, Mask: net.CIDRMask(32, 32)}
  27. if err := ns.RemoveAliasIP(ns.GetLoopbackIfaceName(), ipNet); err != nil {
  28. log.G(context.TODO()).WithError(err).Debugf("failed to remove virtual ip %v to loopback", ipNet)
  29. }
  30. }
  31. if joinInfo == nil {
  32. return
  33. }
  34. // Remove non-interface routes.
  35. for _, r := range joinInfo.StaticRoutes {
  36. if err := ns.RemoveStaticRoute(r); err != nil {
  37. log.G(context.TODO()).Debugf("Remove route failed: %v", err)
  38. }
  39. }
  40. }
  41. // Statistics retrieves the interfaces' statistics for the sandbox.
  42. func (sb *Sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) {
  43. m := make(map[string]*types.InterfaceStatistics)
  44. sb.mu.Lock()
  45. osb := sb.osSbox
  46. sb.mu.Unlock()
  47. if osb == nil {
  48. return m, nil
  49. }
  50. var err error
  51. for _, i := range osb.Interfaces() {
  52. if m[i.DstName()], err = i.Statistics(); err != nil {
  53. return m, err
  54. }
  55. }
  56. return m, nil
  57. }
  58. func (sb *Sandbox) updateGateway(ep *Endpoint) error {
  59. sb.mu.Lock()
  60. osSbox := sb.osSbox
  61. sb.mu.Unlock()
  62. if osSbox == nil {
  63. return nil
  64. }
  65. osSbox.UnsetGateway() //nolint:errcheck
  66. osSbox.UnsetGatewayIPv6() //nolint:errcheck
  67. if ep == nil {
  68. return nil
  69. }
  70. ep.mu.Lock()
  71. joinInfo := ep.joinInfo
  72. ep.mu.Unlock()
  73. if err := osSbox.SetGateway(joinInfo.gw); err != nil {
  74. return fmt.Errorf("failed to set gateway while updating gateway: %v", err)
  75. }
  76. if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil {
  77. return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err)
  78. }
  79. return nil
  80. }
  81. func (sb *Sandbox) ExecFunc(f func()) error {
  82. sb.mu.Lock()
  83. osSbox := sb.osSbox
  84. sb.mu.Unlock()
  85. if osSbox != nil {
  86. return osSbox.InvokeFunc(f)
  87. }
  88. return fmt.Errorf("osl sandbox unavailable in ExecFunc for %v", sb.ContainerID())
  89. }
  90. // SetKey updates the Sandbox Key.
  91. func (sb *Sandbox) SetKey(basePath string) error {
  92. start := time.Now()
  93. defer func() {
  94. log.G(context.TODO()).Debugf("sandbox set key processing took %s for container %s", time.Since(start), sb.ContainerID())
  95. }()
  96. if basePath == "" {
  97. return types.InvalidParameterErrorf("invalid sandbox key")
  98. }
  99. sb.mu.Lock()
  100. if sb.inDelete {
  101. sb.mu.Unlock()
  102. return types.ForbiddenErrorf("failed to SetKey: sandbox %q delete in progress", sb.id)
  103. }
  104. oldosSbox := sb.osSbox
  105. sb.mu.Unlock()
  106. if oldosSbox != nil {
  107. // If we already have an OS sandbox, release the network resources from that
  108. // and destroy the OS snab. We are moving into a new home further down. Note that none
  109. // of the network resources gets destroyed during the move.
  110. if err := sb.releaseOSSbox(); err != nil {
  111. log.G(context.TODO()).WithError(err).Error("Error destroying os sandbox")
  112. }
  113. }
  114. osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key())
  115. if err != nil {
  116. return err
  117. }
  118. sb.mu.Lock()
  119. sb.osSbox = osSbox
  120. sb.mu.Unlock()
  121. // If the resolver was setup before stop it and set it up in the
  122. // new osl sandbox.
  123. if oldosSbox != nil && sb.resolver != nil {
  124. sb.resolver.Stop()
  125. if err := sb.osSbox.InvokeFunc(sb.resolver.SetupFunc(0)); err == nil {
  126. if err := sb.resolver.Start(); err != nil {
  127. log.G(context.TODO()).Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
  128. }
  129. } else {
  130. log.G(context.TODO()).Errorf("Resolver Setup Function failed for container %s, %q", sb.ContainerID(), err)
  131. }
  132. }
  133. for _, ep := range sb.Endpoints() {
  134. if err = sb.populateNetworkResources(ep); err != nil {
  135. return err
  136. }
  137. }
  138. return nil
  139. }
  140. func (sb *Sandbox) releaseOSSbox() error {
  141. sb.mu.Lock()
  142. osSbox := sb.osSbox
  143. sb.osSbox = nil
  144. sb.mu.Unlock()
  145. if osSbox == nil {
  146. return nil
  147. }
  148. for _, ep := range sb.Endpoints() {
  149. releaseOSSboxResources(osSbox, ep)
  150. }
  151. return osSbox.Destroy()
  152. }
  153. func (sb *Sandbox) restoreOslSandbox() error {
  154. var routes []*types.StaticRoute
  155. // restore osl sandbox
  156. interfaces := make(map[osl.Iface][]osl.IfaceOption)
  157. for _, ep := range sb.endpoints {
  158. ep.mu.Lock()
  159. joinInfo := ep.joinInfo
  160. i := ep.iface
  161. ep.mu.Unlock()
  162. if i == nil {
  163. log.G(context.TODO()).Errorf("error restoring endpoint %s for container %s", ep.Name(), sb.ContainerID())
  164. continue
  165. }
  166. ifaceOptions := []osl.IfaceOption{
  167. osl.WithIPv4Address(i.addr),
  168. osl.WithRoutes(i.routes),
  169. }
  170. if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
  171. ifaceOptions = append(ifaceOptions, osl.WithIPv6Address(i.addrv6))
  172. }
  173. if i.mac != nil {
  174. ifaceOptions = append(ifaceOptions, osl.WithMACAddress(i.mac))
  175. }
  176. if len(i.llAddrs) != 0 {
  177. ifaceOptions = append(ifaceOptions, osl.WithLinkLocalAddresses(i.llAddrs))
  178. }
  179. interfaces[osl.Iface{SrcName: i.srcName, DstPrefix: i.dstPrefix}] = ifaceOptions
  180. if joinInfo != nil {
  181. routes = append(routes, joinInfo.StaticRoutes...)
  182. }
  183. if ep.needResolver() {
  184. sb.startResolver(true)
  185. }
  186. }
  187. gwep := sb.getGatewayEndpoint()
  188. if gwep == nil {
  189. return nil
  190. }
  191. // restore osl sandbox
  192. return sb.osSbox.Restore(interfaces, routes, gwep.joinInfo.gw, gwep.joinInfo.gw6)
  193. }
  194. func (sb *Sandbox) populateNetworkResources(ep *Endpoint) error {
  195. sb.mu.Lock()
  196. if sb.osSbox == nil {
  197. sb.mu.Unlock()
  198. return nil
  199. }
  200. inDelete := sb.inDelete
  201. sb.mu.Unlock()
  202. ep.mu.Lock()
  203. joinInfo := ep.joinInfo
  204. i := ep.iface
  205. lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR
  206. ep.mu.Unlock()
  207. if ep.needResolver() {
  208. sb.startResolver(false)
  209. }
  210. if i != nil && i.srcName != "" {
  211. var ifaceOptions []osl.IfaceOption
  212. ifaceOptions = append(ifaceOptions, osl.WithIPv4Address(i.addr), osl.WithRoutes(i.routes))
  213. if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
  214. ifaceOptions = append(ifaceOptions, osl.WithIPv6Address(i.addrv6))
  215. }
  216. if len(i.llAddrs) != 0 {
  217. ifaceOptions = append(ifaceOptions, osl.WithLinkLocalAddresses(i.llAddrs))
  218. }
  219. if i.mac != nil {
  220. ifaceOptions = append(ifaceOptions, osl.WithMACAddress(i.mac))
  221. }
  222. if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
  223. return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
  224. }
  225. if len(ep.virtualIP) > 0 && lbModeIsDSR {
  226. if sb.loadBalancerNID == "" {
  227. if err := sb.osSbox.DisableARPForVIP(i.srcName); err != nil {
  228. return fmt.Errorf("failed disable ARP for VIP: %v", err)
  229. }
  230. }
  231. ipNet := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
  232. if err := sb.osSbox.AddAliasIP(sb.osSbox.GetLoopbackIfaceName(), ipNet); err != nil {
  233. return fmt.Errorf("failed to add virtual ip %v to loopback: %v", ipNet, err)
  234. }
  235. }
  236. }
  237. if joinInfo != nil {
  238. // Set up non-interface routes.
  239. for _, r := range joinInfo.StaticRoutes {
  240. if err := sb.osSbox.AddStaticRoute(r); err != nil {
  241. return fmt.Errorf("failed to add static route %s: %v", r.Destination.String(), err)
  242. }
  243. }
  244. }
  245. if ep == sb.getGatewayEndpoint() {
  246. if err := sb.updateGateway(ep); err != nil {
  247. return err
  248. }
  249. }
  250. // Make sure to add the endpoint to the populated endpoint set
  251. // before populating loadbalancers.
  252. sb.mu.Lock()
  253. sb.populatedEndpoints[ep.ID()] = struct{}{}
  254. sb.mu.Unlock()
  255. // Populate load balancer only after updating all the other
  256. // information including gateway and other routes so that
  257. // loadbalancers are populated all the network state is in
  258. // place in the sandbox.
  259. sb.populateLoadBalancers(ep)
  260. // Only update the store if we did not come here as part of
  261. // sandbox delete. If we came here as part of delete then do
  262. // not bother updating the store. The sandbox object will be
  263. // deleted anyway
  264. if !inDelete {
  265. return sb.storeUpdate()
  266. }
  267. return nil
  268. }