func WaitForAddressesToBeStable(ifName string, timeout time.Duration) error {
	link, err := netlink.LinkByName(ifName)
	if err != nil {
		return fmt.Errorf("failed to retrieve link: %v", err)
	}
	deadline := time.Now().Add(timeout)
	for {
		addrs, err := netlink.AddrList(link, netlink.FAMILY_V6)
		if err != nil {
			return fmt.Errorf("could not list addresses: %v", err)
		}
		ok := true
		for _, addr := range addrs {
			if addr.Flags&(syscall.IFA_F_TENTATIVE|syscall.IFA_F_DADFAILED) > 0 {
				ok = false
				break
			}
		}
		if ok {
			return nil
		}
		if time.Now().After(deadline) {
			return fmt.Errorf("link %s still has tentative addresses after %d seconds",
				ifName,
				timeout)
		}
		time.Sleep(WAIT_INTERVAL)
	}
}
Implements `SettleAddresses` functionality of the `ip` package.
WaitForAddressesToBeStable waits for all addresses on a link to leave tentative state.
Will be particularly useful for ipv6, where all addresses need to do DAD.
If any addresses are still tentative after timeout seconds, then error.
package driver
import (
	"fmt"
	"net"
	"os"
	"syscall"
	"time"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
	"github.com/containernetworking/plugins/pkg/ns"
	"github.com/vishvananda/netlink"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/ipwrapper"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/netlinkwrapper"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/networkutils"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/nswrapper"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/procsyswrapper"
	"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/logger"
)
const (
	vlanRulePriority = 10
	toContainerRulePriority = 512
	fromContainerRulePriority = 1536
	mainRouteTable = unix.RT_TABLE_MAIN
	WAIT_INTERVAL = 50 * time.Millisecond
	v6DADTimeout = 10 * time.Second
)
type NetworkAPIs interface {
	SetupNS(hostVethName string, contVethName string, netnsPath string, v4Addr *net.IPNet, v6Addr *net.IPNet, deviceNumber int, vpcCIDRs []string, useExternalSNAT bool, mtu int, log logger.Logger) error
	TeardownNS(addr *net.IPNet, deviceNumber int, log logger.Logger) error
	SetupPodENINetwork(hostVethName string, contVethName string, netnsPath string, v4Addr *net.IPNet, v6Addr *net.IPNet, vlanID int, eniMAC string,
		subnetGW string, parentIfIndex int, mtu int, log logger.Logger) error
	TeardownPodENINetwork(vlanID int, log logger.Logger) error
}
type linuxNetwork struct {
	netLink netlinkwrapper.NetLink
	ns      nswrapper.NS
	procSys procsyswrapper.ProcSys
}
func New() NetworkAPIs {
	return &linuxNetwork{
		netLink: netlinkwrapper.NewNetLink(),
		ns:      nswrapper.NewNS(),
		procSys: procsyswrapper.NewProcSys(),
	}
}
type createVethPairContext struct {
	contVethName string
	hostVethName string
	v4Addr       *net.IPNet
	v6Addr       *net.IPNet
	netLink      netlinkwrapper.NetLink
	ip           ipwrapper.IP
	mtu          int
	procSys      procsyswrapper.ProcSys
}
func newCreateVethPairContext(contVethName string, hostVethName string, v4Addr *net.IPNet, v6Addr *net.IPNet, mtu int) *createVethPairContext {
	return &createVethPairContext{
		contVethName: contVethName,
		hostVethName: hostVethName,
		v4Addr:       v4Addr,
		v6Addr:       v6Addr,
		netLink:      netlinkwrapper.NewNetLink(),
		ip:           ipwrapper.NewIP(),
		mtu:          mtu,
		procSys:      procsyswrapper.NewProcSys(),
	}
}
func (createVethContext *createVethPairContext) run(hostNS ns.NetNS) error {
	veth := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name:  createVethContext.contVethName,
			Flags: net.FlagUp,
			MTU:   createVethContext.mtu,
		},
		PeerName: createVethContext.hostVethName,
	}
	if err := createVethContext.netLink.LinkAdd(veth); err != nil {
		return err
	}
	hostVeth, err := createVethContext.netLink.LinkByName(createVethContext.hostVethName)
	if err != nil {
		return errors.Wrapf(err, "setup NS network: failed to find link %q", createVethContext.hostVethName)
	}
	if err = createVethContext.netLink.LinkSetUp(hostVeth); err != nil {
		return errors.Wrapf(err, "setup NS network: failed to set link %q up", createVethContext.hostVethName)
	}
	contVeth, err := createVethContext.netLink.LinkByName(createVethContext.contVethName)
	if err != nil {
		return errors.Wrapf(err, "setup NS network: failed to find link %q", createVethContext.contVethName)
	}
	if err = createVethContext.netLink.LinkSetUp(contVeth); err != nil {
		return errors.Wrapf(err, "setup NS network: failed to set link %q up", createVethContext.contVethName)
	}
	if createVethContext.v6Addr != nil && createVethContext.v6Addr.IP.To16() != nil {
		if err = createVethContext.procSys.Set(fmt.Sprintf("net/ipv6/conf/%s/disable_ipv6", createVethContext.contVethName), "0"); err != nil {
			if !os.IsNotExist(err) {
				return errors.Wrapf(err, "setupVeth network: failed to enable IPv6 on container veth interface")
			}
		}
		if err = createVethContext.procSys.Set(fmt.Sprintf("net/ipv6/conf/lo/disable_ipv6"), "0"); err != nil {
			if !os.IsNotExist(err) {
				return errors.Wrapf(err, "setupVeth network: failed to enable IPv6 on container's lo interface")
			}
		}
	}
	var gw net.IP
	var maskLen int
	var addr *netlink.Addr
	var defNet *net.IPNet
	if createVethContext.v4Addr != nil {
		gw = net.IPv4(169, 254, 1, 1)
		maskLen = 32
		addr = &netlink.Addr{IPNet: createVethContext.v4Addr}
		defNet = &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, maskLen)}
	} else if createVethContext.v6Addr != nil {
		gw = net.IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
		maskLen = 128
		addr = &netlink.Addr{IPNet: createVethContext.v6Addr}
		defNet = &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, maskLen)}
	}
	gwNet := &net.IPNet{IP: gw, Mask: net.CIDRMask(maskLen, maskLen)}
	if err = createVethContext.netLink.RouteReplace(&netlink.Route{
		LinkIndex: contVeth.Attrs().Index,
		Scope:     netlink.SCOPE_LINK,
		Dst:       gwNet}); err != nil {
		return errors.Wrap(err, "setup NS network: failed to add default gateway")
	}
	if err = createVethContext.netLink.RouteAdd(&netlink.Route{
		LinkIndex: contVeth.Attrs().Index,
		Scope:     netlink.SCOPE_UNIVERSE,
		Dst:       defNet,
		Gw:        gw,
	}); err != nil {
		return errors.Wrap(err, "setup NS network: failed to add default route")
	}
	if err = createVethContext.netLink.AddrAdd(contVeth, addr); err != nil {
		return errors.Wrapf(err, "setup NS network: failed to add IP addr to %q", createVethContext.contVethName)
	}
	neigh := &netlink.Neigh{
		LinkIndex:    contVeth.Attrs().Index,
		State:        netlink.NUD_PERMANENT,
		IP:           gwNet.IP,
		HardwareAddr: hostVeth.Attrs().HardwareAddr,
	}
	if err = createVethContext.netLink.NeighAdd(neigh); err != nil {
		return errors.Wrap(err, "setup NS network: failed to add static ARP")
	}
	if createVethContext.v6Addr != nil && createVethContext.v6Addr.IP.To16() != nil {
		if err := WaitForAddressesToBeStable(createVethContext.contVethName, v6DADTimeout); err != nil {
			return errors.Wrap(err, "setup NS network: failed while waiting for v6 addresses to be stable")
		}
	}
	if err = createVethContext.netLink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
		return errors.Wrap(err, "setup NS network: failed to move veth to host netns")
	}
	return nil
}