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