diff --git a/Makefile b/Makefile index 6ef7823fcf..d4d038b9d6 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ else endif # Go version to use for builds -GO_VERSION=1.20 +GO_VERSION=1.21 # K8s version used for Makefile helpers K8S_VERSION=1.24.6 diff --git a/pkg/backend/vxlan/device_windows.go b/pkg/backend/vxlan/device_windows.go index 332fca3a3f..08d6b29006 100644 --- a/pkg/backend/vxlan/device_windows.go +++ b/pkg/backend/vxlan/device_windows.go @@ -146,20 +146,9 @@ func ensureNetwork(expectedNetwork *hcn.HostComputeNetwork, expectedAddressPrefi return nil, errors.Wrapf(lastErr, "timeout, failed to get management IP from HostComputeNetwork %s", networkName) } - managementIP := getManagementIP(newNetwork) - // Wait for the interface with the management IP - log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP) - managementIPv4, err := ip.ParseIP4(managementIP) + err = checkHostNetworkReady(newNetwork) if err != nil { - return nil, errors.Wrapf(err, "Failed to parse management ip (%s)", managementIP) - } - - waitErr = wait.Poll(2000*time.Millisecond, 20*time.Second, func() (done bool, err error) { - _, lastErr = ip.GetInterfaceByIP(managementIPv4.ToIP()) - return lastErr == nil, nil - }) - if waitErr == wait.ErrWaitTimeout { - return nil, errors.Wrapf(lastErr, "timeout, failed to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP) + return nil, errors.Wrapf(err, "Interface bound to %s took too long to get ready. Please check your network host configuration", networkName) } log.Infof("Created HostComputeNetwork %s", networkName) @@ -236,3 +225,28 @@ func addNetAdapterName(network *hcn.HostComputeNetwork, netAdapterName string) e return nil } + +// checkHostNetworkReady waits for the host network to be ready: the main interface must be up and have an IP address +func checkHostNetworkReady(network *hcn.HostComputeNetwork) error { + managementIP := getManagementIP(network) + // Wait for the interface with the management IP + log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", network.Name, managementIP) + managementIPv4, err := ip.ParseIP4(managementIP) + if err != nil { + return errors.Wrapf(err, "Failed to parse management ip (%s)", managementIP) + } + + waitErr := wait.Poll(3*time.Second, 25*time.Second, func() (done bool, err error) { + iface, lastErr := ip.GetInterfaceByIP(managementIPv4.ToIP()) + if lastErr == nil { + log.V(2).Infof("Host interface: %s bound by %s ready", iface.Name, network.Name) + return true, nil + } + log.V(2).Infof("Host interface bound by %s not ready", network.Name) + return false, nil + }) + if waitErr == wait.ErrWaitTimeout { + return errors.Wrapf(waitErr, "timeout, failed to get net interface for HostComputeNetwork %s (%s)", network.Name, managementIP) + } + return nil +} diff --git a/pkg/backend/vxlan/vxlan_windows.go b/pkg/backend/vxlan/vxlan_windows.go index 763e6d9883..81cbdb5fe7 100644 --- a/pkg/backend/vxlan/vxlan_windows.go +++ b/pkg/backend/vxlan/vxlan_windows.go @@ -73,7 +73,7 @@ func newSubnetAttrs(publicIP net.IP, vnid uint16, mac net.HardwareAddr) (*lease. } data, err := json.Marshal(&leaseAttrs) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to marshal vxlanLeaseAttrs: %w", err) } return &lease.LeaseAttrs{ @@ -153,7 +153,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, dev, err := newVXLANDevice(&devAttrs) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create VXLAN network: %w", err) } dev.directRouting = cfg.DirectRouting dev.macPrefix = cfg.MacPrefix @@ -165,7 +165,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, hcnNetwork, err := hcn.GetNetworkByName(cfg.Name) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get HNS network: %w", err) } var newDrMac string @@ -174,7 +174,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, policySettings := hcn.DrMacAddressNetworkPolicySetting{} err = json.Unmarshal(policy.Settings, &policySettings) if err != nil { - return nil, fmt.Errorf("Failed to unmarshal settings") + return nil, fmt.Errorf("failed to unmarshal settings") } newDrMac = policySettings.Address } @@ -182,7 +182,7 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, mac, err := net.ParseMAC(string(newDrMac)) if err != nil { - return nil, fmt.Errorf("Cannot parse DR MAC %v: %+v", newDrMac, err) + return nil, fmt.Errorf("cannot parse DR MAC %v: %+v", newDrMac, err) } subnetAttrs, err = newSubnetAttrs(be.extIface.ExtAddr, uint16(cfg.VNI), mac) @@ -190,9 +190,15 @@ func (be *VXLANBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGroup, return nil, err } + // Before contacting the lease server (e.g. kube-api), we verify that the physical interface is ready + err = checkHostNetworkReady(hcnNetwork) + if err != nil { + return nil, fmt.Errorf("interface bound to %s took too long to get ready. Please check your network host configuration", hcnNetwork.Name) + } + lease, err = be.subnetMgr.AcquireLease(ctx, subnetAttrs) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to acquire lease: %w", err) } network.SubnetLease = lease return network, nil diff --git a/pkg/lease/lease.go b/pkg/lease/lease.go index c7503eaf6f..f429525fbe 100644 --- a/pkg/lease/lease.go +++ b/pkg/lease/lease.go @@ -45,7 +45,7 @@ type LeaseAttrs struct { BackendV6Data json.RawMessage `json:",omitempty"` } -// Lease includes information about the lease +// Lease includes information about the lease type Lease struct { EnableIPv4 bool EnableIPv6 bool @@ -67,7 +67,7 @@ type LeaseWatchResult struct { } type LeaseWatcher struct { - OwnLease *Lease //Lease with the subnet of the local node + OwnLease *Lease //Lease with the subnet of the local node Leases []Lease //Leases with subnets from other nodes }