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