Skip to content

Commit

Permalink
connectivity: Add pod-to-pod-no-frag
Browse files Browse the repository at this point in the history
The new test case is intended to check whether MTU is properly set in
pod netns.

The check sends an ICMP Echo with DF set and payload. The payload size
is derived from pod MTU. No reply means that MTU is misconfigured
somewhere in the packet path.

Signed-off-by: Martynas Pumputis <[email protected]>
  • Loading branch information
brb committed Jun 25, 2024
1 parent c4d9fd8 commit 9636a3e
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
1 change: 1 addition & 0 deletions connectivity/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ func concurrentTests(connTests []*check.ConnectivityTest) error {
podToControlplaneHostCidr{},
podToK8sOnControlplaneCidr{},
localRedirectPolicy{},
noFragmentation{},
}
return injectTests(tests, connTests...)
}
Expand Down
20 changes: 20 additions & 0 deletions connectivity/builder/no_fragmentation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package builder

import (
"github.com/cilium/cilium-cli/connectivity/check"
"github.com/cilium/cilium-cli/connectivity/tests"
)

type noFragmentation struct{}

func (t noFragmentation) build(ct *check.ConnectivityTest, _ map[string]string) {
newTest("pod-to-pod-no-frag", ct).
WithCondition(func() bool { return !ct.Params().SingleNode }).
WithScenarios(
tests.PodToPodNoFrag(),
)

}
1 change: 0 additions & 1 deletion connectivity/builder/pod_to_pod_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,4 @@ func (t podToPodEncryption) build(ct *check.ConnectivityTest, _ map[string]strin
WithScenarios(
tests.PodToPodEncryption(features.RequireEnabled(features.EncryptionPod)),
)

}
90 changes: 90 additions & 0 deletions connectivity/tests/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ package tests
import (
"context"
"fmt"
"strconv"
"strings"

"github.com/cilium/cilium-cli/connectivity/check"
"github.com/cilium/cilium-cli/utils/features"
)

const (
HdrSizeICMPEcho = 8
HdrSizeIPv4 = 20
HdrSizeIPv6 = 40
)

// PodToPod generates one HTTP request from each client pod
// to each echo (server) pod in the test context. The remote Pod is contacted
// directly, no DNS is involved.
Expand Down Expand Up @@ -165,3 +173,85 @@ func (s *podToPodWithEndpoints) curlEndpoints(ctx context.Context, t *check.Test
}
}
}

// PodToPodNoFrag is a test to check whether a correct MTU is set
// for pods. The check is performed by sending an ICMP Echo request with DF
// set ("do not fragment"). The ICMP payload size of the request:
//
// - For IPv4: $POD_MTU - 20 (IPv4 hdr) - 8 (ICMP Echo hdr)
// - For IPv6: $POD_MTU - 40 (IPv6 hdr) - 8 (ICMP Echo hdr)
func PodToPodNoFrag() check.Scenario {
return &podToPodNoFrag{}
}

type podToPodNoFrag struct{}

func (s *podToPodNoFrag) Name() string {
return "pod-to-pod-no-frag"
}

func (s *podToPodNoFrag) Run(ctx context.Context, t *check.Test) {
ct := t.Context()
client := ct.RandomClientPod()
var mtu int

cmd := []string{
"/bin/sh", "-c",
"ip route show default | grep -oE 'mtu [^ ]*' | cut -d' ' -f2",
}
t.Debugf("Running %s", strings.Join(cmd, " "))
mtuBytes, err := client.K8sClient.ExecInPod(ctx, client.Pod.Namespace,
client.Pod.Name, "", cmd)
if err != nil {
t.Fatalf("Failed to get route MTU in pod %s: %s", client, err)
}
mtuStr := strings.TrimSpace(mtuBytes.String())

// Derive MTU from pod iface instead
if mtuStr == "" {
cmd := []string{
"/bin/sh", "-c",
"cat /sys/class/net/eth0/mtu",
}
t.Debugf("Running %s", strings.Join(cmd, " "))
mtuBytes, err = client.K8sClient.ExecInPod(ctx, client.Pod.Namespace,
client.Pod.Name, "", cmd)
if err != nil {
t.Fatalf("Failed to get eth0 MTU in pod %s: %s", client, err)
}

mtuStr = strings.TrimSpace(mtuBytes.String())
}

mtu, err = strconv.Atoi(mtuStr)
if err != nil {
t.Fatalf("Failed to parse MTU %s: %s", mtuStr, err)
}
t.Debugf("Derived MTU: %d", mtu)

var server check.Pod
for _, pod := range ct.EchoPods() {
// Make sure that the server pod is on another node than client
if pod.Pod.Status.HostIP != client.Pod.Status.HostIP {
server = pod
break
}
}

t.ForEachIPFamily(func(ipFam features.IPFamily) {
t.NewAction(s, fmt.Sprintf("ping-%s", ipFam), client, server, ipFam).Run(func(a *check.Action) {
payloadSize := mtu - HdrSizeICMPEcho
switch ipFam {
case features.IPFamilyV4:
payloadSize -= HdrSizeIPv4
case features.IPFamilyV6:
payloadSize -= HdrSizeIPv6
}
a.ExecInPod(ctx, t.Context().PingCommand(server, ipFam,
"-M", "do", // DF
"-s", strconv.Itoa(payloadSize), // payload size
))
})

})
}

0 comments on commit 9636a3e

Please sign in to comment.