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