Skip to content

Commit

Permalink
[Windows] Bugfix for MTU configuration on nonexistent interface
Browse files Browse the repository at this point in the history
Configure MTU in a separate goroutine after the host interface is
created.

Signed-off-by: wenyingd <wenyingd@vmware.com>
  • Loading branch information
wenyingd committed Sep 16, 2021
1 parent 4cdd0b2 commit 73d9e22
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 43 deletions.
1 change: 1 addition & 0 deletions pkg/agent/cniserver/interface_configuration_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ func (ic *ifConfigurator) configureContainerLink(
brSriovVFDeviceID string,
podSriovVFDeviceID string,
result *current.Result,
containerAccess *containerAccessArbitrator,
) error {
if brSriovVFDeviceID != "" {
if !ic.isOvsHardwareOffloadEnabled {
Expand Down
59 changes: 56 additions & 3 deletions pkg/agent/cniserver/interface_configuration_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"

"antrea.io/antrea/pkg/agent/interfacestore"
Expand All @@ -43,6 +44,8 @@ const (
notFoundHNSEndpoint = "The endpoint was not found"
)

type postInterfaceCreateHook func() error

type ifConfigurator struct {
hnsNetwork *hcsshim.HNSNetwork
epCache *sync.Map
Expand Down Expand Up @@ -106,6 +109,7 @@ func (ic *ifConfigurator) configureContainerLink(
brSriovVFDeviceID string,
podSriovVFDeviceID string,
result *current.Result,
containerAccess *containerAccessArbitrator,
) error {
if brSriovVFDeviceID != "" {
return fmt.Errorf("OVS hardware offload is not supported on windows")
Expand Down Expand Up @@ -152,9 +156,19 @@ func (ic *ifConfigurator) configureContainerLink(
ifaceIdx := 1
containerIP.Interface = &ifaceIdx

ifaceName := fmt.Sprintf("vEthernet (%s)", endpoint.Name)
if err := util.SetInterfaceMTU(ifaceName, mtu); err != nil {
return fmt.Errorf("failed to configure MTU on container interface '%s': %v", ifaceName, err)
// MTU is configured only when the infrastructure container is created.
if containerID == infraContainerID {
// Configure MTU in another separate goroutine to ensure it is executed after the host interface is created.
// The reasons include, 1) for containerd runtime, the interface is created by containerd after the CNI
// CmdAdd request is returned; 2) for docker runtime, the interface is created after hcsshim.HotAttachEndpoint,
// and the hcsshim call is not synchronized from the observation.
return ic.addPostInterfaceCreateHook(infraContainerID, epName, containerAccess, func() error {
ifaceName := fmt.Sprintf("%s (%s)", util.ContainerVNICPrefix, epName)
if err := util.SetInterfaceMTU(ifaceName, mtu); err != nil {
return fmt.Errorf("failed to configure MTU on container interface '%s': %v", ifaceName, err)
}
return nil
})
}
return nil
}
Expand Down Expand Up @@ -504,3 +518,42 @@ func (ic *ifConfigurator) getInterceptedInterfaces(
func (ic *ifConfigurator) getOVSInterfaceType() int {
return internalOVSInterfaceType
}

func (ic *ifConfigurator) addPostInterfaceCreateHook(containerID, endpointName string, containerAccess *containerAccessArbitrator, hook postInterfaceCreateHook) error {
if containerAccess == nil {
return fmt.Errorf("container lock cannot be null")
}
expectedEP, ok := ic.getEndpoint(endpointName)
if !ok {
return fmt.Errorf("failed to find HNSEndpoint %s", endpointName)
}
go func() {
ifaceName := fmt.Sprintf("vEthernet (%s)", endpointName)
err := wait.PollImmediate(time.Second, 60*time.Second, func() (done bool, err error) {
containerAccess.lockContainer(containerID)
defer containerAccess.unlockContainer(containerID)
currentEP, ok := ic.getEndpoint(endpointName)
if !ok {
klog.InfoS("HNSEndpoint doesn't exist in cache, exit current goroutine", "HNSEndpoint Name", endpointName)
return true, nil
}
if currentEP.Id != expectedEP.Id {
klog.InfoS("Detected HNSEndpoint change, exit current goroutine", "HNSEndpoint Name", endpointName)
return true, nil
}
if !util.HostInterfaceExists(ifaceName) {
klog.InfoS("Waiting for interface to be created", "interface name", ifaceName)
return false, nil
}
if err := hook(); err != nil {
return false, err
}
return true, nil
})

if err != nil {
klog.Errorf("Failed to configure host interface %s: %v", ifaceName, err)
}
}()
return nil
}
2 changes: 1 addition & 1 deletion pkg/agent/cniserver/pod_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func (pc *podConfigurator) configureInterfaces(
createOVSPort bool,
containerAccess *containerAccessArbitrator,
) error {
err := pc.ifConfigurator.configureContainerLink(podName, podNameSpace, containerID, containerNetNS, containerIFDev, mtu, sriovVFDeviceID, "", result)
err := pc.ifConfigurator.configureContainerLink(podName, podNameSpace, containerID, containerNetNS, containerIFDev, mtu, sriovVFDeviceID, "", result, containerAccess)
if err != nil {
return err
}
Expand Down
41 changes: 3 additions & 38 deletions pkg/agent/cniserver/pod_configuration_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ package cniserver

import (
"fmt"
"time"

"github.com/containernetworking/cni/pkg/types/current"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"

"antrea.io/antrea/pkg/agent/interfacestore"
Expand All @@ -34,43 +32,10 @@ import (
// in another goroutine. The function is for Containerd runtime. The host interface is created after
// CNI call completes.
func (pc *podConfigurator) connectInterfaceToOVSAsync(ifConfig *interfacestore.InterfaceConfig, containerAccess *containerAccessArbitrator) error {
if containerAccess == nil {
return fmt.Errorf("container lock cannot be null")
}
ovsPortName := ifConfig.InterfaceName
expectedEp, ok := pc.ifConfigurator.getEndpoint(ovsPortName)
if !ok {
return fmt.Errorf("failed to find HNSEndpoint %s", ovsPortName)
}
hostIfAlias := fmt.Sprintf("%s (%s)", util.ContainerVNICPrefix, ovsPortName)
containerID := ifConfig.ContainerID
go func() {
klog.Infof("Waiting for interface %s to be created", hostIfAlias)
err := wait.PollImmediate(time.Second, 60*time.Second, func() (bool, error) {
containerAccess.lockContainer(containerID)
defer containerAccess.unlockContainer(containerID)
curEp, ok := pc.ifConfigurator.getEndpoint(ovsPortName)
if !ok {
return true, fmt.Errorf("failed to find HNSEndpoint %s", ovsPortName)
}
if curEp.Id != expectedEp.Id {
klog.Warningf("Detected HNSEndpoint change for port %s, exiting current goroutine", ovsPortName)
return true, nil
}
if !util.HostInterfaceExists(hostIfAlias) {
klog.Infof("Waiting for interface %s to be created", hostIfAlias)
return false, nil
}
if err := pc.connectInterfaceToOVSCommon(ovsPortName, ifConfig); err != nil {
return true, fmt.Errorf("failed to connect to OVS for container %s: %v", containerID, err)
}
return true, nil
})
if err != nil {
klog.Errorf("Failed to create OVS port for container %s: %v", containerID, err)
}
}()
return nil
return pc.ifConfigurator.addPostInterfaceCreateHook(ifConfig.ContainerID, ovsPortName, containerAccess, func() error {
return pc.connectInterfaceToOVSCommon(ovsPortName, ifConfig)
})
}

// connectInterfaceToOVS connects an existing interface to OVS br-int.
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/cniserver/sriov.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (pc *podConfigurator) configureSecondaryInterface(
return fmt.Errorf("error getting the Pod SR-IOV VF device ID")
}

err := pc.ifConfigurator.configureContainerLink(podName, podNameSpace, containerID, containerNetNS, containerIFDev, mtu, "", podSriovVFDeviceID, result)
err := pc.ifConfigurator.configureContainerLink(podName, podNameSpace, containerID, containerNetNS, containerIFDev, mtu, "", podSriovVFDeviceID, result, nil)
if err != nil {
return err
}
Expand Down

0 comments on commit 73d9e22

Please sign in to comment.