mirror of
https://github.com/moby/moby.git
synced 2026-08-06 08:01:35 +00:00
These drivers did not do anything meaningful in the `Leave` method; they would check if the network and/or endpoint were missing, in which case they produced an error, but the network and endpoint (if present) would not be used, so it was only validation. Such validation could still be relevant elsewhere, but looking at where this method is called; the `Driver.Leave()` is called in two places, both of which don't handle the error, other than logging it as a warning / error; It's called by `Endpoint.sbJoin()`, as part of the rollback;d5c838dc5e/daemon/libnetwork/endpoint.go (L539-L545)And `Endpoint.sbLeave()`, which also discards the error;d5c838dc5e/daemon/libnetwork/endpoint.go (L772-L776)Based on he above, this code looks to be redundant, so replacing it with a stub; returning `nil`. As replacing the code removed the use of network.getEndpoint, which was effectively a copy of network.endpoint (which didn't have error handling), I merged the two methods, and removed custom error-handling elsewhere. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
150 lines
4.9 KiB
Go
150 lines
4.9 KiB
Go
//go:build linux
|
|
|
|
package macvlan
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/containerd/log"
|
|
"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
|
|
"github.com/moby/moby/v2/daemon/libnetwork/netlabel"
|
|
"github.com/moby/moby/v2/daemon/libnetwork/netutils"
|
|
"github.com/moby/moby/v2/daemon/libnetwork/ns"
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
// Join method is invoked when a Sandbox is attached to an endpoint.
|
|
func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, epOpts, _ map[string]any) error {
|
|
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.macvlan.Join", trace.WithAttributes(
|
|
attribute.String("nid", nid),
|
|
attribute.String("eid", eid),
|
|
attribute.String("sboxKey", sboxKey)))
|
|
defer span.End()
|
|
|
|
n, err := d.getNetwork(nid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// generate a name for the iface that will be renamed to eth0 in the sbox
|
|
containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
|
|
if err != nil {
|
|
return fmt.Errorf("error generating an interface name: %w", err)
|
|
}
|
|
// create the netlink macvlan interface
|
|
vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ep, err := n.endpoint(eid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// bind the generated iface name to the endpoint
|
|
//
|
|
// TODO(thaJeztah): this should really be done under a lock.
|
|
ep.srcName = vethName
|
|
|
|
if !n.config.Internal {
|
|
// parse and correlate the endpoint v4 address with the available v4 subnets
|
|
if ep.addr != nil && len(n.config.Ipv4Subnets) > 0 {
|
|
s := getSubnetForIP(ep.addr, n.config.Ipv4Subnets)
|
|
if s == nil {
|
|
return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
|
|
}
|
|
if s.GwIP == "" {
|
|
// Can't set up a default gateway, but the network is not internal, so it should
|
|
// be treated as having external connectivity. (This preserves old behavior,
|
|
// where a gateway address was assigned from IPAM that did not necessarily
|
|
// correspond with a working gateway.)
|
|
jinfo.ForceGw4()
|
|
} else {
|
|
v4gw, _, err := net.ParseCIDR(s.GwIP)
|
|
if err != nil {
|
|
return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
|
}
|
|
err = jinfo.SetGateway(v4gw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
log.G(ctx).Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, MacVlan_Mode: %s, Parent: %s",
|
|
ep.addr.IP.String(), s.GwIP, n.config.MacvlanMode, n.config.Parent)
|
|
}
|
|
// parse and correlate the endpoint v6 address with the available v6 subnets
|
|
if ep.addrv6 != nil && len(n.config.Ipv6Subnets) > 0 {
|
|
s := getSubnetForIP(ep.addrv6, n.config.Ipv6Subnets)
|
|
if s == nil {
|
|
return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
|
|
}
|
|
if s.GwIP == "" {
|
|
// Can't set up a default gateway, but the network is not internal, so it should
|
|
// be treated as having external connectivity. (This preserves old behavior,
|
|
// where a gateway address was assigned from IPAM that did not necessarily
|
|
// correspond with a working gateway.)
|
|
jinfo.ForceGw6()
|
|
} else {
|
|
v6gw, _, err := net.ParseCIDR(s.GwIP)
|
|
if err != nil {
|
|
return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
|
}
|
|
err = jinfo.SetGatewayIPv6(v6gw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
log.G(ctx).Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s Gateway: %s MacVlan_Mode: %s, Parent: %s",
|
|
ep.addrv6.IP.String(), s.GwIP, n.config.MacvlanMode, n.config.Parent)
|
|
}
|
|
} else {
|
|
if len(n.config.Ipv4Subnets) > 0 {
|
|
log.G(ctx).Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, MacVlan_Mode: %s, Parent: %s",
|
|
ep.addr.IP.String(), n.config.MacvlanMode, n.config.Parent)
|
|
}
|
|
if len(n.config.Ipv6Subnets) > 0 {
|
|
log.G(ctx).Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s MacVlan_Mode: %s, Parent: %s",
|
|
ep.addrv6.IP.String(), n.config.MacvlanMode, n.config.Parent)
|
|
}
|
|
}
|
|
jinfo.DisableGatewayService()
|
|
iNames := jinfo.InterfaceName()
|
|
err = iNames.SetNames(vethName, containerVethPrefix, netlabel.GetIfname(epOpts))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := d.storeUpdate(ep); err != nil {
|
|
return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
|
func (d *driver) Leave(nid, eid string) error {
|
|
return nil
|
|
}
|
|
|
|
// getSubnetForIP returns the (IPv4 or IPv6) subnet to which the given IP belongs.
|
|
func getSubnetForIP(ip *net.IPNet, subnets []*ipSubnet) *ipSubnet {
|
|
for _, s := range subnets {
|
|
_, snet, err := net.ParseCIDR(s.SubnetIP)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
// first check if the mask lengths are the same
|
|
i, _ := snet.Mask.Size()
|
|
j, _ := ip.Mask.Size()
|
|
if i != j {
|
|
continue
|
|
}
|
|
if snet.Contains(ip.IP) {
|
|
return s
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|