diff --git a/pkg/ip/addr_linux.go b/pkg/ip/addr_linux.go index aefa100c..53383de8 100644 --- a/pkg/ip/addr_linux.go +++ b/pkg/ip/addr_linux.go @@ -31,15 +31,15 @@ const SETTLE_INTERVAL = 50 * time.Millisecond // There is no easy way to wait for this as an event, so just loop until the // addresses are no longer tentative. // If any addresses are still tentative after timeout seconds, then error. -func SettleAddresses(ifName string, timeout int) error { +func SettleAddresses(ifName string, timeout time.Duration) error { link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to retrieve link: %v", err) } - deadline := time.Now().Add(time.Duration(timeout) * time.Second) + deadline := time.Now().Add(timeout) for { - addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V6) if err != nil { return fmt.Errorf("could not list addresses: %v", err) } @@ -50,7 +50,13 @@ func SettleAddresses(ifName string, timeout int) error { ok := true for _, addr := range addrs { - if addr.Flags&(syscall.IFA_F_TENTATIVE|syscall.IFA_F_DADFAILED) > 0 { + if addr.Flags&(syscall.IFA_F_DADFAILED) != 0 { + return fmt.Errorf("link %s has address %s in DADFAILED state", + ifName, + addr.IP.String()) + } + + if addr.Flags&(syscall.IFA_F_TENTATIVE) != 0 { ok = false break // Break out of the `range addrs`, not the `for` } diff --git a/pkg/ipam/ipam_linux.go b/pkg/ipam/ipam_linux.go index b1814667..39a9d808 100644 --- a/pkg/ipam/ipam_linux.go +++ b/pkg/ipam/ipam_linux.go @@ -18,6 +18,7 @@ import ( "fmt" "net" "os" + "time" "github.com/vishvananda/netlink" @@ -31,6 +32,8 @@ const ( // Note: use slash as separator so we can have dots in interface name (VLANs) DisableIPv6SysctlTemplate = "net/ipv6/conf/%s/disable_ipv6" KeepAddrOnDownSysctlTemplate = "net/ipv6/conf/%s/keep_addr_on_down" + + dadSettleTimeout = 5 * time.Second ) // ConfigureIface takes the result of IPAM plugin and @@ -111,7 +114,10 @@ func ConfigureIface(ifName string, res *current.Result) error { } if v6gw != nil { - ip.SettleAddresses(ifName, 10) + err = ip.SettleAddresses(ifName, dadSettleTimeout) + if err != nil { + return fmt.Errorf("failed to settle addresses for %q: %v", ifName, err) + } } for _, r := range res.Routes {