Skip to content

Commit

Permalink
Fix captured packets file unrecognized issue on osx (antrea-io#6795)
Browse files Browse the repository at this point in the history
By default, gopacket will write snap length=0 in the pcapng file
header, means unlimited snaplen. tcpdump on osx(libpcap version 1.10.1)
cannot recognize this and will report error. This patch will set
a default value(524288) for it.

Signed-off-by: Hang Yan <[email protected]>
  • Loading branch information
hangyan committed Nov 12, 2024
1 parent b6d4238 commit 12e1973
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 1 deletion.
9 changes: 8 additions & 1 deletion pkg/agent/packetcapture/packetcapture_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,14 @@ func (c *Controller) performCapture(
if err != nil {
return false, err
}
pcapngWriter, err := pcapgo.NewNgWriter(file, layers.LinkTypeEthernet)

// set SnapLength here to make tcpdump on Mac OSX works. By default, its value is
// 0 and means unlimited, but tcpdump on Mac OSX will complain:
// 'tcpdump: pcap_loop: invalid packet capture length <len>, bigger than snaplen of 524288'
defaultNgInterface := pcapgo.DefaultNgInterface
defaultNgInterface.SnapLength = 524288
defaultNgInterface.LinkType = layers.LinkTypeEthernet
pcapngWriter, err := pcapgo.NewNgWriterInterface(file, defaultNgInterface, pcapgo.DefaultNgWriterOptions)
if err != nil {
return false, fmt.Errorf("couldn't initialize a pcap writer: %w", err)
}
Expand Down
103 changes: 103 additions & 0 deletions test/e2e/packetcapture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@ package e2e
import (
"context"
"fmt"
"io"
"net"
"os"
"path/filepath"
"sort"
"strings"
"testing"
"time"

"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
"github.com/gopacket/gopacket/pcapgo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -524,6 +531,19 @@ func runPacketCaptureTest(t *testing.T, data *TestData, tc pcTestCase) {
require.NoError(t, err)
}
}
var srcPodIPs *PodIPs
if tc.pc.Spec.Source.IP != nil {
ip := net.ParseIP(*tc.pc.Spec.Source.IP)
srcPodIPs = &PodIPs{IPv4: &ip}
} else if tc.pc.Spec.Source.Pod != nil {
pod, err := data.clientset.CoreV1().Pods(tc.pc.Spec.Source.Pod.Namespace).Get(context.TODO(), tc.pc.Spec.Source.Pod.Name, metav1.GetOptions{})
if err != nil {
require.True(t, errors.IsNotFound(err))
} else {
srcPodIPs, err = parsePodIPs(pod)
require.NoError(t, err)
}
}

if _, err := data.crdClient.CrdV1alpha1().PacketCaptures().Create(context.TODO(), tc.pc, metav1.CreateOptions{}); err != nil {
t.Fatalf("Error when creating PacketCapture: %v", err)
Expand Down Expand Up @@ -586,6 +606,25 @@ func runPacketCaptureTest(t *testing.T, data *TestData, tc pcTestCase) {
if !packetCaptureStatusEqual(pc.Status, tc.expectedStatus) {
t.Errorf("CR status not match, actual: %+v, expected: %+v", pc.Status, tc.expectedStatus)
}

if tc.pc.Spec.FileServer == nil || tc.expectedStatus.NumberCaptured == 0 {
return
}
// verify packets.
antreaPodName, err := data.getAntreaPodOnNode(nodeName(0))
require.NoError(t, err)
fileName := fmt.Sprintf("%s.pcapng", tc.pc.Name)
dstFileName := filepath.Join(os.TempDir(), fileName)
packetFile := filepath.Join("/tmp", "antrea", "packetcapture", "packets", fileName)
err = data.copyPodFiles(antreaPodName, "antrea-agent", "kube-system", packetFile, os.TempDir())
require.NoError(t, err)
file, err := os.Open(dstFileName)
require.NoError(t, err)
defer file.Close()
err = verifyPacketFile(t, tc.pc, file, tc.expectedStatus.NumberCaptured, *srcPodIPs.IPv4, *dstPodIPs.IPv4)
require.NoError(t, err)
err = os.Remove(dstFileName)
require.NoError(t, err)
}

func (data *TestData) waitForPacketCapture(t *testing.T, name string, specTimeout int, fn func(*crdv1alpha1.PacketCapture) bool) (*crdv1alpha1.PacketCapture, error) {
Expand Down Expand Up @@ -670,3 +709,67 @@ func conditionSliceEqualsIgnoreLastTransitionTime(as, bs []crdv1alpha1.PacketCap
}
return true
}

// verifyPacketFile will read the packets file and check if packet count and packet data match with CR.
func verifyPacketFile(t *testing.T, pc *crdv1alpha1.PacketCapture, reader io.Reader, targetNum int32, srcIP net.IP, dstIP net.IP) (err error) {
ngReader, err := pcapgo.NewNgReader(reader, pcapgo.DefaultNgReaderOptions)
if err != nil {
return err
}

for i := int32(0); i < targetNum; i++ {
data, _, err := ngReader.ReadPacketData()
if err != nil {
return err
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
ipLayer := packet.Layer(layers.LayerTypeIPv4)
assert.NotNil(t, ipLayer)
ip, _ := ipLayer.(*layers.IPv4)
assert.Equal(t, srcIP.String(), ip.SrcIP.String())
assert.Equal(t, dstIP.String(), ip.DstIP.String())

if pc.Spec.Packet == nil {
return nil
}

packetSpec := pc.Spec.Packet
proto := packetSpec.Protocol
if proto == nil {
return nil
}
if strings.ToUpper(proto.StrVal) == "TCP" || proto.IntVal == 6 {
tcpLayer := packet.Layer(layers.LayerTypeTCP)
assert.NotNil(t, tcpLayer)
tcp, _ := tcpLayer.(*layers.TCP)
if packetSpec.TransportHeader.TCP != nil {
ports := packetSpec.TransportHeader.TCP
if ports.DstPort != nil {
assert.Equal(t, *ports.DstPort, int32(tcp.DstPort))
}
if ports.SrcPort != nil {
assert.Equal(t, *ports.SrcPort, int32(tcp.SrcPort))
}
}
}
if strings.ToUpper(proto.StrVal) == "UDP" || proto.IntVal == 17 {
udpLayer := packet.Layer(layers.LayerTypeUDP)
assert.NotNil(t, udpLayer)
udp, _ := udpLayer.(*layers.UDP)
if packetSpec.TransportHeader.UDP != nil {
ports := packetSpec.TransportHeader.UDP
if ports.DstPort != nil {
assert.Equal(t, *ports.DstPort, int32(udp.DstPort))
}
if ports.SrcPort != nil {
assert.Equal(t, *ports.SrcPort, int32(udp.SrcPort))
}
}
}
if strings.ToUpper(proto.StrVal) == "ICMP" || proto.IntVal == 1 {
icmpLayer := packet.Layer(layers.LayerTypeICMPv4)
assert.NotNil(t, icmpLayer)
}
}
return nil
}

0 comments on commit 12e1973

Please sign in to comment.