diff --git a/test/e2e/framework.go b/test/e2e/framework.go index 82374921712..7fa95d15c19 100644 --- a/test/e2e/framework.go +++ b/test/e2e/framework.go @@ -1537,6 +1537,17 @@ func (data *TestData) createNginxPodOnNode(name string, ns string, nodeName stri }).WithHostNetwork(hostNetwork).Create(data) } +func (data *TestData) createUDPAndTCPServerPod(name string, ns string, portNum int32, serverNode string) error { + cmd := []string{"/bin/bash", "-c"} + args := []string{ + fmt.Sprintf("/agnhost serve-hostname --udp --http=false --port %d & /agnhost serve-hostname --tcp --http=false --port %d", portNum, portNum), + } + port := corev1.ContainerPort{ContainerPort: 8080} + containerName := fmt.Sprintf("c%v", 8080) + return NewPodBuilder(name, ns, agnhostImage).OnNode(serverNode).WithContainerName(containerName).WithCommand(cmd).WithArgs(args).WithPorts([]corev1.ContainerPort{port}).Create(testData) + +} + // createServerPod creates a Pod that can listen to specified port and have named port set. func (data *TestData) createServerPod(name string, ns string, portName string, portNum int32, setHostPort bool, hostNetwork bool) error { // See https://github.com/kubernetes/kubernetes/blob/master/test/images/agnhost/porter/porter.go#L17 for the image's detail. diff --git a/test/e2e/packetsampling_test.go b/test/e2e/packetsampling_test.go index 7d969ea5747..8e8080ce602 100644 --- a/test/e2e/packetsampling_test.go +++ b/test/e2e/packetsampling_test.go @@ -17,10 +17,12 @@ import ( ) var ( - psNamespace = "default" - psSecretName = "ps-secret" - psNginxPodName = "test-nginx" - psBusyboxPodName = "busybox" + psNamespace = "default" + psSecretName = "ps-secret" + psNginxPodName = "test-nginx" + psBusyboxPodName = "busybox" + mixProtoServerPodName = "mix-proto-server" + serverPort int32 = 8080 ) type psTestCase struct { @@ -104,6 +106,10 @@ func testPacketSamplingIntraNode(t *testing.T, data *TestData) { require.NoError(t, err) defer deletePodWrapper(t, data, data.testNamespace, psNginxPodName) + err = data.createUDPAndTCPServerPod(mixProtoServerPodName, data.testNamespace, serverPodPort, node1) + require.NoError(t, err) + defer deletePodWrapper(t, data, data.testNamespace, mixProtoServerPodName) + err = data.createBusyboxPodOnNode(psBusyboxPodName, data.testNamespace, node1, false) require.NoError(t, err) defer deletePodWrapper(t, data, data.testNamespace, psNginxPodName) @@ -159,6 +165,53 @@ func testPacketSamplingIntraNode(t *testing.T, data *TestData) { expectedPhase: crdv1alpha1.PacketSamplingSucceeded, expectedNum: 5, }, + { + name: "intraNodeUDPPacketSamplingIPv4", + ipVersion: 4, + srcPod: psBusyboxPodName, + ps: &crdv1alpha1.PacketSampling{ + ObjectMeta: metav1.ObjectMeta{ + Name: randName(fmt.Sprintf("%s-%s-to-%s-%s-", data.testNamespace, node1Pods[0], data.testNamespace, node1Pods[1])), + }, + Spec: crdv1alpha1.PacketSamplingSpec{ + Source: crdv1alpha1.Source{ + Namespace: data.testNamespace, + Pod: psBusyboxPodName, + }, + Destination: crdv1alpha1.Destination{ + Namespace: data.testNamespace, + Pod: mixProtoServerPodName, + }, + + Type: crdv1alpha1.FirstNSampling, + FirstNSamplingConfig: &crdv1alpha1.FirstNSamplingConfig{ + Number: 5, + }, + FileServer: crdv1alpha1.BundleFileServer{ + URL: fmt.Sprintf("%s:30010/upload", controlPlaneNodeIPv4()), + }, + Authentication: crdv1alpha1.BundleServerAuthConfiguration{ + AuthType: "BasicAuthentication", + AuthSecret: &v1.SecretReference{ + Name: psSecretName, + Namespace: psNamespace, + }, + }, + Packet: crdv1alpha1.Packet{ + IPHeader: crdv1alpha1.IPHeader{ + Protocol: protocolUDP, + }, + TransportHeader: crdv1alpha1.TransportHeader{ + UDP: &crdv1alpha1.UDPHeader{ + DstPort: serverPort, + }, + }, + }, + }, + }, + expectedPhase: crdv1alpha1.PacketSamplingSucceeded, + expectedNum: 5, + }, } t.Run("testPacketSamplingIntraNode", func(t *testing.T) { for _, tc := range testcases { @@ -212,21 +265,28 @@ func runPacketSamplingTest(t *testing.T, data *TestData, tc psTestCase) { } // Give a little time for Nodes to install OVS flows. time.Sleep(time.Second * 2) + protocol := tc.ps.Spec.Packet.IPHeader.Protocol + server := dstPodIPs.IPv4.String() + if tc.ipVersion == 6 { + server = dstPodIPs.IPv6.String() + } // Send an ICMP echo packet from the source Pod to the destination. - if tc.ps.Spec.Packet.IPHeader.Protocol == protocolICMP { + if protocol == protocolICMP { if err := data.RunPingCommandFromTestPod(PodInfo{srcPod, osString, "", ""}, data.testNamespace, dstPodIPs, agnhostContainerName, 10, 0, false); err != nil { t.Logf("Ping '%s' -> '%v' failed: ERROR (%v)", srcPod, *dstPodIPs, err) } - } else if tc.ps.Spec.Packet.IPHeader.Protocol == protocolTCP { - server := dstPodIPs.IPv4.String() - if tc.ipVersion == 6 { - server = dstPodIPs.IPv6.String() - } + } else if protocol == protocolTCP { url := fmt.Sprintf("%s:%v", server, tc.ps.Spec.Packet.TransportHeader.TCP.DstPort) if _, _, err := data.runWgetCommandOnBusyboxWithRetry(tc.srcPod, data.testNamespace, url, 3); err != nil { t.Logf("wget '%s' -> '%v' failed: ERROR (%v)", srcPod, url, err) } + } else if protocol == protocolUDP { + for i := 1; i <= 5; i++ { + if err := data.runNetcatCommandFromTestPodWithProtocol(tc.srcPod, data.testNamespace, busyboxContainerName, server, serverPort, "udp"); err != nil { + t.Logf("Netcat(UDP) '%s' -> '%v' failed: ERROR (%v)", srcPod, server, err) + } + } } ps, err := data.waitForPacketSampling(t, tc.ps.Name, tc.expectedPhase)