github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/drivers/macvlan/macvlan_joinleave.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package macvlan
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  
    10  	"github.com/docker/docker/libnetwork/driverapi"
    11  	"github.com/docker/docker/libnetwork/netutils"
    12  	"github.com/docker/docker/libnetwork/ns"
    13  	"github.com/docker/docker/libnetwork/osl"
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  // Join method is invoked when a Sandbox is attached to an endpoint.
    18  func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
    19  	defer osl.InitOSContext()()
    20  	n, err := d.getNetwork(nid)
    21  	if err != nil {
    22  		return err
    23  	}
    24  	endpoint := n.endpoint(eid)
    25  	if endpoint == nil {
    26  		return fmt.Errorf("could not find endpoint with id %s", eid)
    27  	}
    28  	// generate a name for the iface that will be renamed to eth0 in the sbox
    29  	containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
    30  	if err != nil {
    31  		return fmt.Errorf("error generating an interface name: %s", err)
    32  	}
    33  	// create the netlink macvlan interface
    34  	vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode)
    35  	if err != nil {
    36  		return err
    37  	}
    38  	// bind the generated iface name to the endpoint
    39  	endpoint.srcName = vethName
    40  	ep := n.endpoint(eid)
    41  	if ep == nil {
    42  		return fmt.Errorf("could not find endpoint with id %s", eid)
    43  	}
    44  	// parse and match the endpoint address with the available v4 subnets
    45  	if !n.config.Internal {
    46  		if len(n.config.Ipv4Subnets) > 0 {
    47  			s := n.getSubnetforIPv4(ep.addr)
    48  			if s == nil {
    49  				return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
    50  			}
    51  			v4gw, _, err := net.ParseCIDR(s.GwIP)
    52  			if err != nil {
    53  				return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
    54  			}
    55  			err = jinfo.SetGateway(v4gw)
    56  			if err != nil {
    57  				return err
    58  			}
    59  			logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, MacVlan_Mode: %s, Parent: %s",
    60  				ep.addr.IP.String(), v4gw.String(), n.config.MacvlanMode, n.config.Parent)
    61  		}
    62  		// parse and match the endpoint address with the available v6 subnets
    63  		if len(n.config.Ipv6Subnets) > 0 {
    64  			s := n.getSubnetforIPv6(ep.addrv6)
    65  			if s == nil {
    66  				return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
    67  			}
    68  			v6gw, _, err := net.ParseCIDR(s.GwIP)
    69  			if err != nil {
    70  				return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
    71  			}
    72  			err = jinfo.SetGatewayIPv6(v6gw)
    73  			if err != nil {
    74  				return err
    75  			}
    76  			logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s Gateway: %s MacVlan_Mode: %s, Parent: %s",
    77  				ep.addrv6.IP.String(), v6gw.String(), n.config.MacvlanMode, n.config.Parent)
    78  		}
    79  	} else {
    80  		if len(n.config.Ipv4Subnets) > 0 {
    81  			logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, MacVlan_Mode: %s, Parent: %s",
    82  				ep.addr.IP.String(), n.config.MacvlanMode, n.config.Parent)
    83  		}
    84  		if len(n.config.Ipv6Subnets) > 0 {
    85  			logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s MacVlan_Mode: %s, Parent: %s",
    86  				ep.addrv6.IP.String(), n.config.MacvlanMode, n.config.Parent)
    87  		}
    88  	}
    89  	iNames := jinfo.InterfaceName()
    90  	err = iNames.SetNames(vethName, containerVethPrefix)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	if err := d.storeUpdate(ep); err != nil {
    95  		return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err)
    96  	}
    97  	return nil
    98  }
    99  
   100  // Leave method is invoked when a Sandbox detaches from an endpoint.
   101  func (d *driver) Leave(nid, eid string) error {
   102  	defer osl.InitOSContext()()
   103  	network, err := d.getNetwork(nid)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	endpoint, err := network.getEndpoint(eid)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	if endpoint == nil {
   112  		return fmt.Errorf("could not find endpoint with id %s", eid)
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  // getSubnetforIP returns the ipv4 subnet to which the given IP belongs
   119  func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet {
   120  	for _, s := range n.config.Ipv4Subnets {
   121  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   122  		if err != nil {
   123  			return nil
   124  		}
   125  		// first check if the mask lengths are the same
   126  		i, _ := snet.Mask.Size()
   127  		j, _ := ip.Mask.Size()
   128  		if i != j {
   129  			continue
   130  		}
   131  		if snet.Contains(ip.IP) {
   132  			return s
   133  		}
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs
   140  func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet {
   141  	for _, s := range n.config.Ipv6Subnets {
   142  		_, snet, err := net.ParseCIDR(s.SubnetIP)
   143  		if err != nil {
   144  			return nil
   145  		}
   146  		// first check if the mask lengths are the same
   147  		i, _ := snet.Mask.Size()
   148  		j, _ := ip.Mask.Size()
   149  		if i != j {
   150  			continue
   151  		}
   152  		if snet.Contains(ip.IP) {
   153  			return s
   154  		}
   155  	}
   156  
   157  	return nil
   158  }