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  }