Exemple #1
0
func releaseVF(conf *NetConf, ifName string, initns ns.NetNS) error {
	// get VF device
	vfDev, err := netlink.LinkByName(ifName)
	if err != nil {
		return fmt.Errorf("failed to lookup vf %d device %q: %v", conf.VF, ifName, err)
	}

	// device name in init netns
	index := vfDev.Attrs().Index
	devName := fmt.Sprintf("dev%d", index)

	// shutdown VF device
	if err = netlink.LinkSetDown(vfDev); err != nil {
		return fmt.Errorf("failed to down vf % device: %v", conf.VF, err)
	}

	// rename VF device
	err = renameLink(ifName, devName)
	if err != nil {
		return fmt.Errorf("failed to rename vf %d evice %q to %q: %v", conf.VF, ifName, devName, err)
	}

	// move VF device to init netns
	if err = netlink.LinkSetNsFd(vfDev, int(initns.Fd())); err != nil {
		return fmt.Errorf("failed to move vf %d to init netns: %v", conf.VF, err)
	}

	return nil
}
Exemple #2
0
// SetupVeth sets up a virtual ethernet link.
// Should be in container netns.
func SetupVeth(contVethName string, mtu int, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) {
	var hostVethName string
	hostVethName, contVeth, err = makeVeth(contVethName, mtu)
	if err != nil {
		return
	}

	if err = netlink.LinkSetUp(contVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	hostVeth, err = netlink.LinkByName(hostVethName)
	if err != nil {
		err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
		return
	}

	if err = netlink.LinkSetUp(hostVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
		err = fmt.Errorf("failed to move veth to host netns: %v", err)
		return
	}

	return
}
Exemple #3
0
func (n *networkNamespace) AddInterface(i *Interface) error {
	n.Lock()
	i.DstName = fmt.Sprintf("%s%d", i.DstName, n.nextIfIndex)
	n.nextIfIndex++
	n.Unlock()

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	origns, err := netns.Get()
	if err != nil {
		return err
	}
	defer origns.Close()

	f, err := os.OpenFile(n.path, os.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("failed get network namespace %q: %v", n.path, err)
	}
	defer f.Close()

	// Find the network interface identified by the SrcName attribute.
	iface, err := netlink.LinkByName(i.SrcName)
	if err != nil {
		return err
	}

	// Move the network interface to the destination namespace.
	nsFD := f.Fd()
	if err := netlink.LinkSetNsFd(iface, int(nsFD)); err != nil {
		return err
	}

	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
		return err
	}
	defer netns.Set(origns)

	// Down the interface before configuring
	if err := netlink.LinkSetDown(iface); err != nil {
		return err
	}

	// Configure the interface now this is moved in the proper namespace.
	if err := configureInterface(iface, i); err != nil {
		return err
	}

	// Up the interface.
	if err := netlink.LinkSetUp(iface); err != nil {
		return err
	}

	n.Lock()
	n.sinfo.Interfaces = append(n.sinfo.Interfaces, i)
	n.Unlock()

	return nil
}
func (n *networkNamespace) RemoveInterface(i *Interface) error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	origns, err := netns.Get()
	if err != nil {
		return err
	}
	defer origns.Close()

	f, err := os.OpenFile(n.path, os.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("failed get network namespace %q: %v", n.path, err)
	}
	defer f.Close()

	nsFD := f.Fd()
	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
		return err
	}
	defer netns.Set(origns)

	// Find the network inteerface identified by the DstName attribute.
	iface, err := netlink.LinkByName(i.DstName)
	if err != nil {
		return err
	}

	// Down the interface before configuring
	if err := netlink.LinkSetDown(iface); err != nil {
		return err
	}

	err = netlink.LinkSetName(iface, i.SrcName)
	if err != nil {
		fmt.Println("LinkSetName failed: ", err)
		return err
	}

	// Move the network interface to caller namespace.
	if err := netlink.LinkSetNsFd(iface, int(origns)); err != nil {
		fmt.Println("LinkSetNsPid failed: ", err)
		return err
	}

	n.Lock()
	for index, intf := range n.sinfo.Interfaces {
		if intf == i {
			n.sinfo.Interfaces = append(n.sinfo.Interfaces[:index], n.sinfo.Interfaces[index+1:]...)
			break
		}
	}
	n.Unlock()

	return nil
}
Exemple #5
0
func endpointSetNs(nsfd int) {
	veth, err := netlink.LinkByName("myveth1")
	if err != nil {
		panic(err)
	}

	err = netlink.LinkSetNsFd(veth, nsfd)
	if err != nil {
		panic(err)
	}
}
Exemple #6
0
func (Link) SetNs(intf *net.Interface, ns int) error {
	netlinkMu.Lock()
	defer netlinkMu.Unlock()

	link, err := netlink.LinkByName(intf.Name)
	if err != nil {
		return errF(err)
	}

	return errF(netlink.LinkSetNsFd(link, ns))
}
Exemple #7
0
func (i *nwIface) Remove() error {
	i.Lock()
	n := i.ns
	i.Unlock()

	n.Lock()
	path := n.path
	isDefault := n.isDefault
	n.Unlock()

	return nsInvoke(path, func(nsFD int) error { return nil }, func(callerFD int) error {
		// Find the network inteerface identified by the DstName attribute.
		iface, err := netlink.LinkByName(i.DstName())
		if err != nil {
			return err
		}

		// Down the interface before configuring
		if err := netlink.LinkSetDown(iface); err != nil {
			return err
		}

		err = netlink.LinkSetName(iface, i.SrcName())
		if err != nil {
			fmt.Println("LinkSetName failed: ", err)
			return err
		}

		// if it is a bridge just delete it.
		if i.Bridge() {
			if err := netlink.LinkDel(iface); err != nil {
				return fmt.Errorf("failed deleting bridge %q: %v", i.SrcName(), err)
			}
		} else if !isDefault {
			// Move the network interface to caller namespace.
			if err := netlink.LinkSetNsFd(iface, callerFD); err != nil {
				fmt.Println("LinkSetNsPid failed: ", err)
				return err
			}
		}

		n.Lock()
		for index, intf := range n.iFaces {
			if intf == i {
				n.iFaces = append(n.iFaces[:index], n.iFaces[index+1:]...)
				break
			}
		}
		n.Unlock()

		return nil
	})
}
Exemple #8
0
func setHostMode() {
	if os.Getenv("_OVERLAY_HOST_MODE") != "" {
		hostMode = true
		return
	}

	err := createVxlan("testvxlan", 1)
	if err != nil {
		logrus.Errorf("Failed to create testvxlan interface: %v", err)
		return
	}

	defer deleteInterface("testvxlan")

	path := "/proc/self/ns/net"
	f, err := os.OpenFile(path, os.O_RDONLY, 0)
	if err != nil {
		logrus.Errorf("Failed to open path %s for network namespace for setting host mode: %v", path, err)
		return
	}
	defer f.Close()

	nsFD := f.Fd()

	iface, err := netlink.LinkByName("testvxlan")
	if err != nil {
		logrus.Errorf("Failed to get link testvxlan: %v", err)
		return
	}

	// If we are not able to move the vxlan interface to a namespace
	// then fallback to host mode
	if err := netlink.LinkSetNsFd(iface, int(nsFD)); err != nil {
		hostMode = true
	}
}
Exemple #9
0
// SetupVeth sets up a virtual ethernet link.
// Should be in container netns, and will switch back to hostNS to set the host
// veth end up.
func SetupVeth(contVethName string, mtu int, hostNS ns.NetNS) (hostVeth, contVeth netlink.Link, err error) {
	var hostVethName string
	hostVethName, contVeth, err = makeVeth(contVethName, mtu)
	if err != nil {
		return
	}

	if err = netlink.LinkSetUp(contVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	hostVeth, err = netlink.LinkByName(hostVethName)
	if err != nil {
		err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
		return
	}

	if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
		err = fmt.Errorf("failed to move veth to host netns: %v", err)
		return
	}

	err = hostNS.Do(func(_ ns.NetNS) error {
		hostVeth, err := netlink.LinkByName(hostVethName)
		if err != nil {
			return fmt.Errorf("failed to lookup %q in %q: %v", hostVethName, hostNS.Path(), err)
		}

		if err = netlink.LinkSetUp(hostVeth); err != nil {
			return fmt.Errorf("failed to set %q up: %v", hostVethName, err)
		}
		return nil
	})
	return
}
func (*nl) LinkSetNsFd(link netlink.Link, fd int) error {
	return netlink.LinkSetNsFd(link, fd)
}
Exemple #11
0
func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
	i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n}
	i.processInterfaceOptions(options...)

	if i.master != "" {
		i.dstMaster = n.findDst(i.master, true)
		if i.dstMaster == "" {
			return fmt.Errorf("could not find an appropriate master %q for %q",
				i.master, i.srcName)
		}
	}

	n.Lock()
	if n.isDefault {
		i.dstName = i.srcName
	} else {
		i.dstName = fmt.Sprintf("%s%d", i.dstName, n.nextIfIndex)
		n.nextIfIndex++
	}

	path := n.path
	isDefault := n.isDefault
	n.Unlock()

	return nsInvoke(path, func(nsFD int) error {
		// If it is a bridge interface we have to create the bridge inside
		// the namespace so don't try to lookup the interface using srcName
		if i.bridge {
			return nil
		}

		// Find the network interface identified by the SrcName attribute.
		iface, err := netlink.LinkByName(i.srcName)
		if err != nil {
			return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
		}

		// Move the network interface to the destination
		// namespace only if the namespace is not a default
		// type
		if !isDefault {
			if err := netlink.LinkSetNsFd(iface, nsFD); err != nil {
				return fmt.Errorf("failed to set namespace on link %q: %v", i.srcName, err)
			}
		}

		return nil
	}, func(callerFD int) error {
		if i.bridge {
			link := &netlink.Bridge{
				LinkAttrs: netlink.LinkAttrs{
					Name: i.srcName,
				},
			}

			if err := netlink.LinkAdd(link); err != nil {
				return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err)
			}
		}

		// Find the network interface identified by the SrcName attribute.
		iface, err := netlink.LinkByName(i.srcName)
		if err != nil {
			return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
		}

		// Down the interface before configuring
		if err := netlink.LinkSetDown(iface); err != nil {
			return fmt.Errorf("failed to set link down: %v", err)
		}

		// Configure the interface now this is moved in the proper namespace.
		if err := configureInterface(iface, i); err != nil {
			return err
		}

		// Up the interface.
		if err := netlink.LinkSetUp(iface); err != nil {
			return fmt.Errorf("failed to set link up: %v", err)
		}

		// Set the routes on the interface. This can only be done when the interface is up.
		if err := setInterfaceRoutes(iface, i); err != nil {
			return fmt.Errorf("error setting interface %q routes to %q: %v", iface.Attrs().Name, i.Routes(), err)
		}

		n.Lock()
		n.iFaces = append(n.iFaces, i)
		n.Unlock()

		return nil
	})
}
Exemple #12
0
// DoNetworking performs the networking for the given config and IPAM result
func DoNetworking(args *skel.CmdArgs, conf NetConf, res *types.Result, logger *log.Entry, desiredVethName string) (hostVethName, contVethMAC string, err error) {
	// Select the first 11 characters of the containerID for the host veth.
	hostVethName = "cali" + args.ContainerID[:min(11, len(args.ContainerID))]
	contVethName := args.IfName

	// If a desired veth name was passed in, use that instead.
	if desiredVethName != "" {
		hostVethName = desiredVethName
	}

	err = ns.WithNetNSPath(args.Netns, func(hostNS ns.NetNS) error {
		veth := &netlink.Veth{
			LinkAttrs: netlink.LinkAttrs{
				Name:  contVethName,
				Flags: net.FlagUp,
				MTU:   conf.MTU,
			},
			PeerName: hostVethName,
		}

		if err := netlink.LinkAdd(veth); err != nil {
			logger.Errorf("Error adding veth %+v: %s", veth, err)
			return err
		}

		hostVeth, err := netlink.LinkByName(hostVethName)
		if err != nil {
			err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
			return err
		}

		contVeth, err := netlink.LinkByName(contVethName)
		if err != nil {
			err = fmt.Errorf("failed to lookup %q: %v", contVethName, err)
			return err
		}

		// Fetch the MAC from the container Veth. This is needed by Calico.
		contVethMAC = contVeth.Attrs().HardwareAddr.String()
		logger.WithField("MAC", contVethMAC).Debug("Found MAC for container veth")

		// At this point, the virtual ethernet pair has been created, and both ends have the right names.
		// Both ends of the veth are still in the container's network namespace.

		// Before returning, create the routes inside the namespace, first for IPv4 then IPv6.
		if res.IP4 != nil {
			// Add a connected route to a dummy next hop so that a default route can be set
			gw := net.IPv4(169, 254, 1, 1)
			gwNet := &net.IPNet{IP: gw, Mask: net.CIDRMask(32, 32)}
			if err = netlink.RouteAdd(&netlink.Route{
				LinkIndex: contVeth.Attrs().Index,
				Scope:     netlink.SCOPE_LINK,
				Dst:       gwNet}); err != nil {
				return fmt.Errorf("failed to add route %v", err)
			}

			if err = ip.AddDefaultRoute(gw, contVeth); err != nil {
				return fmt.Errorf("failed to add route %v", err)
			}

			if err = netlink.AddrAdd(contVeth, &netlink.Addr{IPNet: &res.IP4.IP}); err != nil {
				return fmt.Errorf("failed to add IP addr to %q: %v", contVethName, err)
			}
		}

		// Handle IPv6 routes
		if res.IP6 != nil {
			// No need to add a dummy next hop route as the host veth device will already have an IPv6
			// link local address that can be used as a next hop.
			// Just fetch the address of the host end of the veth and use it as the next hop.
			var hostIPv6Addr net.IP
			if err := hostNS.Do(func(_ ns.NetNS) error {
				addresses, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6)
				if err != nil {
					logger.Errorf("Error listing IPv6 addresses: %s", err)
					return err
				}

				if len(addresses) < 1 {
					// If the hostVeth doesn't have an IPv6 address then this host probably doesn't
					// support IPv6. Since a IPv6 address has been allocated that can't be used,
					// return an error.
					return fmt.Errorf("Failed to get IPv6 addresses for container veth")
				}

				hostIPv6Addr = addresses[0].IP
				return nil
			}); err != nil {
				logger.Errorf("Error getting IPv6 address: %s", err)
				return err
			}

			_, defNet, _ := net.ParseCIDR("::/0")
			if err = ip.AddRoute(defNet, hostIPv6Addr, contVeth); err != nil {
				return fmt.Errorf("failed to add default gateway to %v %v", hostIPv6Addr, err)
			}

			if err = netlink.AddrAdd(contVeth, &netlink.Addr{IPNet: &res.IP6.IP}); err != nil {
				return fmt.Errorf("failed to add IP addr to %q: %v", contVeth, err)
			}
		}

		// Now that the everything has been successfully set up in the container, move the "host" end of the
		// veth into the host namespace.
		if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
			return fmt.Errorf("failed to move veth to host netns: %v", err)
		}

		return nil
	})

	if err != nil {
		logger.Errorf("Error creating veth: %s", err)
		return "", "", err
	}

	// Moving a veth between namespaces always leaves it in the "DOWN" state. Set it back to "UP" now that we're
	// back in the host namespace.
	hostVeth, err := netlink.LinkByName(hostVethName)
	if err != nil {
		return "", "", fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
	}

	if err = netlink.LinkSetUp(hostVeth); err != nil {
		return "", "", fmt.Errorf("failed to set %q up: %v", hostVethName, err)
	}

	return hostVethName, contVethMAC, err
}
Exemple #13
0
func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	if !interfaceExistsInNamespace(ns, ifName) {
		maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
		if len(id) > maxIDLen {
			id = id[:maxIDLen] // trim passed ID if too long
		}
		name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
		_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
			if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
				return fmt.Errorf("failed to move veth to container netns: %s", err)
			}
			if err := WithNetNSUnsafe(ns, func() error {
				if err := netlink.LinkSetName(veth, ifName); err != nil {
					return err
				}
				if err := ConfigureARPCache(ifName); err != nil {
					return err
				}
				if err := ipt.Append("filter", "INPUT", "-i", ifName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
					return err
				}
				return nil
			}); err != nil {
				return fmt.Errorf("error setting up interface: %s", err)
			}
			return nil
		})
		if err != nil {
			return err
		}
	}

	if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
		newAddresses, err := AddAddresses(veth, cidrs)
		if err != nil {
			return err
		}

		// Add multicast ACCEPT rules for new subnets
		for _, ipnet := range newAddresses {
			acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
			exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
			if err != nil {
				return err
			}
			if !exists {
				if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
					return err
				}
			}
		}

		if err := netlink.LinkSetUp(veth); err != nil {
			return err
		}
		for _, ipnet := range newAddresses {
			// If we don't wait for a bit here, we see the arp fail to reach the bridge.
			time.Sleep(1 * time.Millisecond)
			arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName)
		}
		if withMulticastRoute {
			/* Route multicast packets across the weave network.
			This must come last in 'attach'. If you change this, change weavewait to match.

			TODO: Add the MTU lock to prevent PMTU discovery for multicast
			destinations. Without that, the kernel sets the DF flag on
			multicast packets. Since RFC1122 prohibits sending of ICMP
			errors for packets with multicast destinations, that causes
			packets larger than the PMTU to be dropped silently.  */

			_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
			if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
				return err
			}
		}
		return nil
	}); err != nil {
		return err
	}

	return nil
}
Exemple #14
0
// NewVeth creates a veth pair with the given name, moves the peer into the
// namespace n, then renames the peer to dstName and assigns the provided ip.
// If insideFn is not nil, also executes that function in the context of the
// given namespace.
func NewVeth(n netns.NsHandle, name, dstName, ip string, insideFn func(netlink.Link) error) (link *netlink.Veth, err error) {
	l := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name: name,
		},
		PeerName: name + "_",
	}
	if err = netlink.LinkAdd(l); err != nil {
		return
	}
	defer func() {
		if err != nil {
			netlink.LinkDel(l)
		}
	}()

	otherL, err := netlink.LinkByName(l.PeerName)
	if err != nil {
		return
	}
	if err = netlink.LinkSetNsFd(otherL, int(n)); err != nil {
		return
	}
	err = RunInNs(n, func() error {
		lo, err := netlink.LinkByName("lo")
		if err != nil {
			return err
		}
		err = netlink.LinkSetUp(lo)
		if err != nil {
			return err
		}
		l, err := netlink.LinkByName(name + "_")
		if err != nil {
			return err
		}
		if err = netlink.LinkSetName(l, dstName); err != nil {
			return err
		}
		l.Attrs().Name = dstName
		a, err := netlink.ParseIPNet(ip)
		if err != nil {
			return err
		}
		if err := netlink.AddrAdd(l, &netlink.Addr{IPNet: a}); err != nil {
			return err
		}
		if insideFn != nil {
			if err := insideFn(l); err != nil {
				return err
			}
		}
		if err = netlink.LinkSetUp(l); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return
	}
	if err = netlink.LinkSetUp(l); err != nil {
		return
	}
	link = l
	return
}
Exemple #15
0
func setupVF(conf *NetConf, ifName string, netns ns.NetNS) error {

	masterName := conf.Master
	vfIdx := conf.VF

	m, err := netlink.LinkByName(masterName)
	if err != nil {
		return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
	}

	vfDir := fmt.Sprintf("/sys/class/net/%s/device/virtfn%d/net", masterName, vfIdx)
	if _, err := os.Lstat(vfDir); err != nil {
		return err
	}

	infos, err := ioutil.ReadDir(vfDir)
	if err != nil {
		return err
	}

	if len(infos) != 1 {
		return fmt.Errorf("Mutiple network devices in directory %s", vfDir)
	}

	// VF NIC name
	vfDevName := infos[0].Name()
	vfDev, err := netlink.LinkByName(vfDevName)
	if err != nil {
		return fmt.Errorf("failed to lookup vf device %q: %v", vfDevName, err)
	}

	// set hardware address
	if conf.MAC != "" {
		macAddr, err := net.ParseMAC(conf.MAC)
		if err != nil {
			return err
		}
		if err = netlink.LinkSetVfHardwareAddr(m, conf.VF, macAddr); err != nil {
			return fmt.Errorf("failed to set vf %d macaddress: %v", conf.VF, err)
		}
	}

	if conf.Vlan != 0 {
		if err = netlink.LinkSetVfVlan(m, conf.VF, conf.Vlan); err != nil {
			return fmt.Errorf("failed to set vf %d vlan: %v", conf.VF, err)
		}
	}

	if err = netlink.LinkSetUp(vfDev); err != nil {
		return fmt.Errorf("failed to setup vf %d device: %v", conf.VF, err)
	}

	// move VF device to ns
	if err = netlink.LinkSetNsFd(vfDev, int(netns.Fd())); err != nil {
		return fmt.Errorf("failed to move vf %d to netns: %v", conf.VF, err)
	}

	return netns.Do(func(_ ns.NetNS) error {
		err := renameLink(vfDevName, ifName)
		if err != nil {
			return fmt.Errorf("failed to rename vf %d device %q to %q: %v", conf.VF, vfDevName, ifName, err)
		}
		return nil
	})
}
Exemple #16
0
func cmdAdd(args *skel.CmdArgs) error {
	n, err := loadNetConf(args.StdinData)
	if err != nil {
		return err
	}

	log.Debugf("Args %s", args)

	c, err := cnc.NewDefaultClient()
	if err != nil {
		return fmt.Errorf("error while starting cilium-client: %s", err)
	}

	netNs, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %s", args.Netns, err)
	}
	defer netNs.Close()

	if err := removeIfFromNSIfExists(netNs, args.IfName); err != nil {
		return fmt.Errorf("failed removing interface %q from namespace %q: %s",
			args.IfName, args.Netns, err)
	}

	var ep endpoint.Endpoint
	veth, peer, tmpIfName, err := plugins.SetupVeth(args.ContainerID, n.MTU, &ep)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			if err = netlink.LinkDel(veth); err != nil {
				log.Warningf("failed to clean up veth %q: %s", veth.Name, err)
			}
		}
	}()

	if err = netlink.LinkSetNsFd(*peer, int(netNs.Fd())); err != nil {
		return fmt.Errorf("unable to move veth pair %q to netns: %s", peer, err)
	}

	err = netNs.Do(func(_ ns.NetNS) error {
		err := renameLink(tmpIfName, args.IfName)
		if err != nil {
			return fmt.Errorf("failed to rename %q to %q: %s", tmpIfName, args.IfName, err)
		}
		return nil
	})

	req := ipam.IPAMReq{}
	ipamConf, err := c.AllocateIP(ipam.CNIIPAMType, req)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil && ipamConf != nil {
			if ipamConf.IP6 != nil {
				req := ipam.IPAMReq{IP: &ipamConf.IP6.IP.IP}
				if err = c.ReleaseIP(ipam.CNIIPAMType, req); err != nil {
					log.Warningf("failed to release allocated IPv6 of container ID %q: %s", args.ContainerID, err)
				}
			}
			if ipamConf.IP4 != nil {
				req := ipam.IPAMReq{IP: &ipamConf.IP4.IP.IP}
				if err = c.ReleaseIP(ipam.CNIIPAMType, req); err != nil {
					log.Warningf("failed to release allocated IPv4 of container ID %q: %s", args.ContainerID, err)
				}
			}
		}
	}()

	if err = netNs.Do(func(_ ns.NetNS) error {
		return configureIface(args.IfName, ipamConf)
	}); err != nil {
		return err
	}

	ep.IPv6 = addressing.DeriveCiliumIPv6(ipamConf.IP6.IP.IP)
	if ipamConf.IP4 != nil {
		ep.IPv4 = addressing.DeriveCiliumIPv4(ipamConf.IP4.IP.IP)
	}
	ep.NodeIP = ipamConf.IP6.Gateway
	ep.DockerID = args.ContainerID
	ep.SetID()
	if err = c.EndpointJoin(ep); err != nil {
		return fmt.Errorf("unable to create eBPF map: %s", err)
	}

	return createCNIReply(ipamConf)
}