github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/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/Prakhar-Agarwal-byte/moby/libnetwork/driverapi" 12 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/netutils" 13 "github.com/Prakhar-Agarwal-byte/moby/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 } 87 iNames := jinfo.InterfaceName() 88 err = iNames.SetNames(vethName, containerVethPrefix) 89 if err != nil { 90 return err 91 } 92 if err := d.storeUpdate(ep); err != nil { 93 return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err) 94 } 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 network, err := d.getNetwork(nid) 102 if err != nil { 103 return err 104 } 105 endpoint, err := network.getEndpoint(eid) 106 if err != nil { 107 return err 108 } 109 if endpoint == nil { 110 return fmt.Errorf("could not find endpoint with id %s", eid) 111 } 112 113 return nil 114 } 115 116 // getSubnetforIPv4 returns the ipv4 subnet to which the given IP belongs 117 func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipSubnet { 118 return getSubnetForIP(ip, n.config.Ipv4Subnets) 119 } 120 121 // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs 122 func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipSubnet { 123 return getSubnetForIP(ip, n.config.Ipv6Subnets) 124 } 125 126 func getSubnetForIP(ip *net.IPNet, subnets []*ipSubnet) *ipSubnet { 127 for _, s := range subnets { 128 _, snet, err := net.ParseCIDR(s.SubnetIP) 129 if err != nil { 130 return nil 131 } 132 // first check if the mask lengths are the same 133 i, _ := snet.Mask.Size() 134 j, _ := ip.Mask.Size() 135 if i != j { 136 continue 137 } 138 if snet.Contains(ip.IP) { 139 return s 140 } 141 } 142 143 return nil 144 }