github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/drivers/ipvlan/ipvlan_joinleave.go (about)

     1  package ipvlan
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  
     7  	"github.com/Sirupsen/logrus"
     8  	"github.com/docker/libnetwork/driverapi"
     9  	"github.com/docker/libnetwork/netutils"
    10  	"github.com/docker/libnetwork/ns"
    11  	"github.com/docker/libnetwork/osl"
    12  	"github.com/docker/libnetwork/types"
    13  )
    14  
    15  type staticRoute struct {
    16  	Destination *net.IPNet
    17  	RouteType   int
    18  	NextHop     net.IP
    19  }
    20  
    21  const (
    22  	defaultV4RouteCidr = "0.0.0.0/0"
    23  	defaultV6RouteCidr = "::/0"
    24  )
    25  
    26  // Join method is invoked when a Sandbox is attached to an endpoint.
    27  func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
    28  	defer osl.InitOSContext()()
    29  	n, err := d.getNetwork(nid)
    30  	if err != nil {
    31  		return err
    32  	}
    33  	endpoint := n.endpoint(eid)
    34  	if endpoint == nil {
    35  		return fmt.Errorf("could not find endpoint with id %s", eid)
    36  	}
    37  	// generate a name for the iface that will be renamed to eth0 in the sbox
    38  	containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
    39  	if err != nil {
    40  		return fmt.Errorf("error generating an interface name: %v", err)
    41  	}
    42  	// create the netlink ipvlan interface
    43  	vethName, err := createIPVlan(containerIfName, n.config.Parent, n.config.IpvlanMode)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	// bind the generated iface name to the endpoint
    48  	endpoint.srcName = vethName
    49  	ep := n.endpoint(eid)
    50  	if ep == nil {
    51  		return fmt.Errorf("could not find endpoint with id %s", eid)
    52  	}
    53  	if n.config.IpvlanMode == modeL3 {
    54  		// disable gateway services to add a default gw using dev eth0 only
    55  		jinfo.DisableGatewayService()
    56  		defaultRoute, err := ifaceGateway(defaultV4RouteCidr)
    57  		if err != nil {
    58  			return err
    59  		}
    60  		if err := jinfo.AddStaticRoute(defaultRoute.Destination, defaultRoute.RouteType, defaultRoute.NextHop); err != nil {
    61  			return fmt.Errorf("failed to set an ipvlan l3 mode ipv4 default gateway: %v", err)
    62  		}
    63  		logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Ipvlan_Mode: %s, Parent: %s",
    64  			ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent)
    65  		// If the endpoint has a v6 address, set a v6 default route
    66  		if ep.addrv6 != nil {
    67  			default6Route, err := ifaceGateway(defaultV6RouteCidr)
    68  			if err != nil {
    69  				return err
    70  			}
    71  			if err = jinfo.AddStaticRoute(default6Route.Destination, default6Route.RouteType, default6Route.NextHop); err != nil {
    72  				return fmt.Errorf("failed to set an ipvlan l3 mode ipv6 default gateway: %v", err)
    73  			}
    74  			logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Ipvlan_Mode: %s, Parent: %s",
    75  				ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent)
    76  		}
    77  	}
    78  	if n.config.IpvlanMode == modeL2 {
    79  		// parse and correlate the endpoint v4 address with the available v4 subnets
    80  		if len(n.config.Ipv4Subnets) > 0 {
    81  			s := n.getSubnetforIPv4(ep.addr)
    82  			if s == nil {
    83  				return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
    84  			}
    85  			v4gw, _, err := net.ParseCIDR(s.GwIP)
    86  			if err != nil {
    87  				return fmt.Errorf("gatway %s is not a valid ipv4 address: %v", s.GwIP, err)
    88  			}
    89  			err = jinfo.SetGateway(v4gw)
    90  			if err != nil {
    91  				return err
    92  			}
    93  			logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s",
    94  				ep.addr.IP.String(), v4gw.String(), n.config.IpvlanMode, n.config.Parent)
    95  		}
    96  		// parse and correlate the endpoint v6 address with the available v6 subnets
    97  		if len(n.config.Ipv6Subnets) > 0 {
    98  			s := n.getSubnetforIPv6(ep.addrv6)
    99  			if s == nil {
   100  				return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
   101  			}
   102  			v6gw, _, err := net.ParseCIDR(s.GwIP)
   103  			if err != nil {
   104  				return fmt.Errorf("gatway %s is not a valid ipv6 address: %v", s.GwIP, err)
   105  			}
   106  			err = jinfo.SetGatewayIPv6(v6gw)
   107  			if err != nil {
   108  				return err
   109  			}
   110  			logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s",
   111  				ep.addrv6.IP.String(), v6gw.String(), n.config.IpvlanMode, n.config.Parent)
   112  		}
   113  	}
   114  	iNames := jinfo.InterfaceName()
   115  	err = iNames.SetNames(vethName, containerVethPrefix)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	if err = d.storeUpdate(ep); err != nil {
   120  		return fmt.Errorf("failed to save ipvlan endpoint %s to store: %v", ep.id[0:7], err)
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  // Leave method is invoked when a Sandbox detaches from an endpoint.
   127  func (d *driver) Leave(nid, eid string) error {
   128  	defer osl.InitOSContext()()
   129  	network, err := d.getNetwork(nid)
   130  	if err != nil {
   131  		return err
   132  	}
   133  	endpoint, err := network.getEndpoint(eid)
   134  	if err != nil {
   135  		return err
   136  	}
   137  	if endpoint == nil {
   138  		return fmt.Errorf("could not find endpoint with id %s", eid)
   139  	}
   140  
   141  	return nil
   142  }
   143  
   144  // ifaceGateway returns a static route for either v4/v6 to be set to the container eth0
   145  func ifaceGateway(dfNet string) (*staticRoute, error) {
   146  	nh, dst, err := net.ParseCIDR(dfNet)
   147  	if err != nil {
   148  		return nil, fmt.Errorf("unable to parse default route %v", err)
   149  	}
   150  	defaultRoute := &staticRoute{
   151  		Destination: dst,
   152  		RouteType:   types.CONNECTED,
   153  		NextHop:     nh,
   154  	}
   155  
   156  	return defaultRoute, nil
   157  }
   158  
   159  // getSubnetforIPv4 returns the ipv4 subnet to which the given IP belongs
   160  func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet {
   161  	for _, s := range n.config.Ipv4Subnets {
   162  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   163  		if err != nil {
   164  			return nil
   165  		}
   166  		// first check if the mask lengths are the same
   167  		i, _ := snet.Mask.Size()
   168  		j, _ := ip.Mask.Size()
   169  		if i != j {
   170  			continue
   171  		}
   172  		if snet.Contains(ip.IP) {
   173  			return s
   174  		}
   175  	}
   176  
   177  	return nil
   178  }
   179  
   180  // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs
   181  func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet {
   182  	for _, s := range n.config.Ipv6Subnets {
   183  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   184  		if err != nil {
   185  			return nil
   186  		}
   187  		// first check if the mask lengths are the same
   188  		i, _ := snet.Mask.Size()
   189  		j, _ := ip.Mask.Size()
   190  		if i != j {
   191  			continue
   192  		}
   193  		if snet.Contains(ip.IP) {
   194  			return s
   195  		}
   196  	}
   197  
   198  	return nil
   199  }