Skip to content

Commit

Permalink
Fix NodeNetworkPolicy e2e test failure (#6172)
Browse files Browse the repository at this point in the history
In NodeNetworkPolicy e2e tests, we have the following cases:

- Node to Node. We deploy two hostNetwork Pods on different Nodes.
- Node to Pods. We deploy a hostNetwork Pod on a Node and two
  non-hostNetwork Pods on different Nodes.

For the case of Node to Pods, after creating test Pods, a full mesh
probing is run to ensure that all Pods can be reachable from each
other. However, the UDP or SCTP probing from a non-hostNetwork Pod, using
the Node external IP (the IP in the hostNetwork Pod object) as destination
IP, to the hostNetwork Pod within on the same Node will get a failure. The
reason is that due to UDP's connectionless nature, the reply traffic
may use a source IP address determined by routing decisions or outgoing
interfaces, which means that the local Antrea gateway IPs will be chosen
as source IP address, rather than the destination IP address used in
request traffic. As a result, the probing will get a failure because the
source IP address of reply traffic is unexpected.

To resolve the issue, when the target Pod is a hostNetwork Pod, we use the
local Antrea gateway IPs as the destination IP, rather than the hostNetwork
Pod IP (the Node external IP).

Signed-off-by: Hongliang Liu <lhongliang@vmware.com>
  • Loading branch information
hongliangl authored Apr 23, 2024
1 parent 142a9e7 commit 7acc1c2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
10 changes: 10 additions & 0 deletions test/e2e/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ func skipIfEncapModeIsNot(tb testing.TB, data *TestData, encapMode config.Traffi
}
}

func skipIfEncapModeIs(tb testing.TB, data *TestData, encapMode config.TrafficEncapModeType) {
currentEncapMode, err := data.GetEncapMode()
if err != nil {
tb.Fatalf("Failed to get encap mode: %v", err)
}
if currentEncapMode == encapMode {
tb.Skipf("Skipping test for encap mode '%s'", encapMode.String())
}
}

func skipIfHasWindowsNodes(tb testing.TB) {
if len(clusterInfo.windowsNodes) != 0 {
tb.Skipf("Skipping test as the cluster has Windows Nodes")
Expand Down
36 changes: 31 additions & 5 deletions test/e2e/k8s_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,12 +430,38 @@ func (k *KubernetesUtils) probeAndDecideConnectivity(fromPod, toPod v1.Pod,
fromPodName, toPodName string, port int32, protocol utils.AntreaPolicyProtocol, expectedResult *PodConnectivityMark) (PodConnectivityMark, error) {
// Both IPv4 and IPv6 address should be tested.
connectivity := Unknown
for _, eachIP := range toPod.Status.PodIPs {
toIP := eachIP.IP
// If it's an IPv6 address, add "[]" around it.
if strings.Contains(toIP, ":") {
toIP = fmt.Sprintf("[%s]", toIP)
var toIPs []string
if toPod.Spec.HostNetwork {
// When probing UDP or SCTP from a non-hostNetwork Pod to a hostNetwork Pod within the same Node, the local
// Antrea gateway IPs should be used as the destination IP, rather than the Node external IPs. If using the Node
// external IPs as destination IPs when probing, the UDP or SCTP reply traffic from hostNetwork Pod will choose
// a source IP address based on the routing decision or outgoing interface, which means that the local Antrea
// gateway IPs will be chosen as the source IP address. As a result, the probing will get a failure because the
// source IP address of reply traffic is unexpected. To accommodate with this case, when the target Pod is a
// hostNetwork Pod, the local Antrea gateway IPs are used.
nodeInfo := getNodeByName(toPod.Spec.NodeName)
if nodeInfo == nil {
return connectivity, fmt.Errorf("failed to get Node information by name %s", toPod.Spec.NodeName)
}
gwIPv4, gwIPv6 := nodeGatewayIPs(nodeInfo.idx)
if gwIPv4 != "" {
toIPs = append(toIPs, gwIPv4)
}
if gwIPv6 != "" {
toIPs = append(toIPs, fmt.Sprintf("[%s]", gwIPv6))
}
} else {
for _, eachIP := range toPod.Status.PodIPs {
toIP := eachIP.IP
// If it's an IPv6 address, add "[]" around it.
if strings.Contains(toIP, ":") {
toIP = fmt.Sprintf("[%s]", toIP)
}
toIPs = append(toIPs, toIP)
}
}

for _, toIP := range toIPs {
// HACK: inferring container name as c80, c81 etc., for simplicity.
containerName := fmt.Sprintf("c%v", port)
curConnectivity := k.probe(&fromPod, fromPodName, containerName, toIP, toPodName, port, protocol, expectedResult)
Expand Down
10 changes: 6 additions & 4 deletions test/e2e/nodenetworkpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"antrea.io/antrea/pkg/agent/config"
crdv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1"
"antrea.io/antrea/pkg/features"
. "antrea.io/antrea/test/e2e/utils"
Expand All @@ -45,17 +46,17 @@ func initializeAntreaNodeNetworkPolicy(t *testing.T, data *TestData, toHostNetwo
}
}
nodes = make(map[string]string)
nodes["x"] = controlPlaneNodeName()
nodes["y"] = workerNodeName(1)
nodes["x"] = nodeName(0)
nodes["y"] = nodeName(1)
nodes["z"] = nodeName(0)
hostNetworks := make(map[string]bool)
hostNetworks["x"] = true
if toHostNetworkPod {
hostNetworks["y"] = true
} else {
hostNetworks["y"] = false
nodes["z"] = workerNodeName(1)
hostNetworks["z"] = false
}
hostNetworks["z"] = false
allPods = []Pod{}

for _, podName := range podsPerNamespace {
Expand Down Expand Up @@ -88,6 +89,7 @@ func TestAntreaNodeNetworkPolicy(t *testing.T) {
t.Fatalf("Error when setting up test: %v", err)
}
defer teardownTest(t, data)
skipIfEncapModeIs(t, data, config.TrafficEncapModeNetworkPolicyOnly)

initializeAntreaNodeNetworkPolicy(t, data, true)

Expand Down

0 comments on commit 7acc1c2

Please sign in to comment.