From 6280b8a8f3e261c5f0fcfbb69f4485fd78cb158e Mon Sep 17 00:00:00 2001 From: Marco Iorio Date: Fri, 13 Oct 2023 12:38:37 +0200 Subject: [PATCH] connectivity: fix encryption validation when running in ENI mode When running in ENI mode, the outgoing interface of pod originating traffic is different from the one that would be used by host originating traffic towards the same destination. This breaks the current pod-to-pod encryption validation, as the source interface for the tcpdump filter is determined based on the routes towards the given destination only. Let's update the source interface determination to additionally consider the source address. This approach had been initially suggested by Paul Chaignon in #1241, but then reverted in [1] because `ip route get` returns and error in case the `from` address is not assigned to any local interface. We can work around this by specifying an input interface: let's use lo as it should be always present. [1]: 2fc0835ff158 ("connectivity: Fix iface derivation in encrypt tests") Signed-off-by: Marco Iorio --- connectivity/tests/encryption.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/connectivity/tests/encryption.go b/connectivity/tests/encryption.go index a024781640..7fe0a97b04 100644 --- a/connectivity/tests/encryption.go +++ b/connectivity/tests/encryption.go @@ -31,11 +31,19 @@ const ( // which interface the traffic is routed to. Additionally, we translate // the interface name to the tunneling interface name, if the route goes // through "cilium_host" and tunneling is enabled. -func getInterNodeIface(ctx context.Context, t *check.Test, clientHost *check.Pod, dstIP string) string { +func getInterNodeIface(ctx context.Context, t *check.Test, clientHost *check.Pod, ipFam features.IPFamily, srcIP, dstIP string) string { + ipRouteGetCmd := fmt.Sprintf("ip -o route get %s from %s", dstIP, srcIP) + if srcIP != clientHost.Address(ipFam) { + // The "iif lo" part is required when the source address is not one + // of the addresses of the host. If an interface is not specified + // "ip route" returns "RTNETLINK answers: Network is unreachable" in + // case the "from" address is not assigned to any local interface. + ipRouteGetCmd = fmt.Sprintf("%s iif lo", ipRouteGetCmd) + } + cmd := []string{ "/bin/sh", "-c", - fmt.Sprintf("ip -o route get %s | grep -oE 'dev [^ ]*' | cut -d' ' -f2", - dstIP), + fmt.Sprintf("%s | grep -oE 'dev [^ ]*' | cut -d' ' -f2", ipRouteGetCmd), } t.Debugf("Running %s", strings.Join(cmd, " ")) dev, err := clientHost.K8sClient.ExecInPod(ctx, clientHost.Pod.Namespace, @@ -130,7 +138,7 @@ func testNoTrafficLeak(ctx context.Context, t *check.Test, s check.Scenario, client, server, clientHost *check.Pod, reqType requestType, ipFam features.IPFamily, ) { dstAddr := server.Address(ipFam) - iface := getInterNodeIface(ctx, t, clientHost, dstAddr) + iface := getInterNodeIface(ctx, t, clientHost, ipFam, client.Address(ipFam), dstAddr) srcFilter := getSourceAddressFilter(ctx, t, client, clientHost, ipFam, dstAddr) bgStdout := &safeBuffer{}