Skip to content

Commit

Permalink
Add pod information into captures
Browse files Browse the repository at this point in the history
Signed-off-by: Chance Zibolski <chance.zibolski@gmail.com>
  • Loading branch information
chancez committed Jul 22, 2024
1 parent e7c144e commit 1f3c102
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 92 deletions.
28 changes: 16 additions & 12 deletions cmd/output_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,14 @@ func (h *outputFileHandler) HandlePacket(p gopacket.Packet) error {
// for the first interface automatically as part of capture.NewPcapNgWriter.
if h.outputFormat == capperpb.PcapOutputFormat_OUTPUT_FORMAT_PCAPNG {
captureIface := capture.CaptureInterface{
Name: ad.IfaceName,
Index: p.Metadata().InterfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
Name: ad.IfaceName,
Index: p.Metadata().InterfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
K8sPod: ad.K8SPodName,
K8sPodNamespace: ad.K8SPodNamespace,
}
if _, configured := h.interfaceConfigured[captureIface]; !configured {
ngWriter := packetWriter.(*capture.PcapNgWriter)
Expand Down Expand Up @@ -141,12 +143,14 @@ func (h *outputFileHandler) newPacketWriter(identifier string, interfaceIndex in
case capperpb.PcapOutputFormat_OUTPUT_FORMAT_PCAPNG:
var err error
captureIface := capture.CaptureInterface{
Name: ad.IfaceName,
Index: interfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
Name: ad.IfaceName,
Index: interfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
K8sPod: ad.K8SPodName,
K8sPodNamespace: ad.K8SPodNamespace,
}
packetWriter, err = capture.NewPcapNgWriter(w, captureIface, h.snaplen, ad.GetHardware(), ad.GetOperatingSystem())
if err != nil {
Expand Down
20 changes: 14 additions & 6 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,16 +262,16 @@ func (s *server) getPod(ctx context.Context, podName, namespace string) (*contai

func (s *server) Capture(req *capperpb.CaptureRequest, stream capperpb.Capper_CaptureServer) error {
ctx := stream.Context()
var netns string
var pod *containerdutil.Pod
if req.GetK8SPodFilter() != nil {
podName := req.GetK8SPodFilter().GetName()
namespace := req.GetK8SPodFilter().GetNamespace()
pod, err := s.getPod(ctx, podName, namespace)
var err error
pod, err = s.getPod(ctx, podName, namespace)
if err != nil {
// don't wrap the error, getPod returns a grpc status error with codes set.
return err
}
netns = pod.Netns
}

conf := capture.Config{
Expand All @@ -282,7 +282,7 @@ func (s *server) Capture(req *capperpb.CaptureRequest, stream capperpb.Capper_Ca
CaptureDuration: req.GetDuration().AsDuration(),
}

return s.capture(ctx, req.GetInterface(), netns, conf, stream)
return s.capture(ctx, req.GetInterface(), pod, conf, stream)
}

func (s *server) NodeMetadata(req *capperpb.NodeMetadataRequest, stream capperpb.Capper_NodeMetadataServer) error {
Expand Down Expand Up @@ -340,15 +340,23 @@ func (s *server) NodeMetadata(req *capperpb.NodeMetadataRequest, stream capperpb
}
}

func (s *server) capture(ctx context.Context, ifaces []string, netns string, conf capture.Config, stream capperpb.Capper_CaptureServer) error {
func (s *server) capture(ctx context.Context, ifaces []string, pod *containerdutil.Pod, conf capture.Config, stream capperpb.Capper_CaptureServer) error {
eg, ctx := errgroup.WithContext(ctx)
if len(ifaces) == 0 {
ifaces = []string{""}
}
for _, iface := range ifaces {
iface := iface
eg.Go(func() error {
handle, err := capture.NewBasic(ctx, s.log, iface, netns, conf)
var (
err error
handle capture.Capture
)
if pod == nil {
handle, err = capture.NewBasic(ctx, s.log, iface, "", conf)
} else {
handle, err = capture.NewContainer(ctx, s.log, iface, pod, conf)
}
if err != nil {
return fmt.Errorf("error creating packet capture: %w", err)
}
Expand Down
34 changes: 27 additions & 7 deletions pkg/capture/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"runtime"
"time"

containerdutil "github.com/chancez/capper/pkg/containerd"
"github.com/chancez/capper/pkg/namespaces"
capperpb "github.com/chancez/capper/proto/capper"
"github.com/gopacket/gopacket"
Expand Down Expand Up @@ -93,12 +94,14 @@ type Config struct {
}

type CaptureInterface struct {
Name string
Index int
Hostname string
NetnsInode uint64
Netns string
LinkType layers.LinkType
Name string
Index int
Hostname string
NetnsInode uint64
Netns string
LinkType layers.LinkType
K8sPod string
K8sPodNamespace string
}

func getInterface(ifaceName string, netns string) (CaptureInterface, error) {
Expand Down Expand Up @@ -173,13 +176,28 @@ type BasicCapture struct {
handle *pcap.Handle
}

func NewBasic(ctx context.Context, log *slog.Logger, ifaceName, netns string, conf Config) (*BasicCapture, error) {
func NewBasic(ctx context.Context, log *slog.Logger, ifaceName string, netns string, conf Config) (*BasicCapture, error) {
pod := &containerdutil.Pod{Netns: netns}
return newCapture(ctx, log, ifaceName, pod, conf)
}

func NewContainer(ctx context.Context, log *slog.Logger, ifaceName string, pod *containerdutil.Pod, conf Config) (*BasicCapture, error) {
return newCapture(ctx, log, ifaceName, pod, conf)
}

func newCapture(ctx context.Context, log *slog.Logger, ifaceName string, pod *containerdutil.Pod, conf Config) (*BasicCapture, error) {
clock := clockwork.NewRealClock()

netns := ""
if pod != nil {
netns = pod.Netns
}
iface, err := getInterface(ifaceName, netns)
if err != nil {
return nil, fmt.Errorf("error getting interface: %w", err)
}
iface.K8sPod = pod.Name
iface.K8sPodNamespace = pod.Namespace

handle, err := NewLiveHandle(iface.Name, netns, conf.Filter, conf.Snaplen, conf.Promisc, conf.BufferSize)
if err != nil {
Expand Down Expand Up @@ -242,6 +260,8 @@ func (c *BasicCapture) Start(ctx context.Context, handler PacketHandler) error {
IfaceName: c.iface.Name,
Hardware: runtime.GOARCH,
OperatingSystem: runtime.GOOS,
K8SPodName: c.iface.K8sPod,
K8SPodNamespace: c.iface.K8sPodNamespace,
})
err := handler.HandlePacket(packet)
if err != nil {
Expand Down
41 changes: 33 additions & 8 deletions pkg/capture/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package capture
import (
"fmt"
"io"
"strconv"
"strings"

"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
Expand Down Expand Up @@ -58,7 +60,7 @@ func NewPcapNgWriter(w io.Writer, iface CaptureInterface, snaplen uint32, hardwa
LinkType: iface.LinkType,
SnapLength: snaplen,
OS: os,
Description: fmt.Sprintf("iface: %s hostname: %q", iface.Name, iface.Hostname),
Description: interfaceDescription(iface),
}
interfaceToID[iface] = 0

Expand All @@ -74,12 +76,14 @@ func NewPcapNgWriter(w io.Writer, iface CaptureInterface, snaplen uint32, hardwa
return -1, false
}
iface := CaptureInterface{
Name: ad.IfaceName,
Index: ci.InterfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
Name: ad.IfaceName,
Index: ci.InterfaceIndex,
Hostname: ad.NodeName,
Netns: ad.Netns,
NetnsInode: ad.NetnsInode,
LinkType: layers.LinkType(ad.LinkType),
K8sPod: ad.K8SPodName,
K8sPodNamespace: ad.K8SPodNamespace,
}
id, ok = interfaceToID[iface]
return id, ok
Expand Down Expand Up @@ -112,10 +116,31 @@ func (w *PcapNgWriter) AddInterface(iface CaptureInterface) (int, error) {
LinkType: iface.LinkType,
SnapLength: w.snaplen,
OS: w.os,
Description: fmt.Sprintf("iface: %s hostname: %q", iface.Name, iface.Hostname),
Description: interfaceDescription(iface),
})
if err == nil {
w.interfaceToID[iface] = id
}
return id, err
}

func interfaceDescription(i CaptureInterface) string {
var b strings.Builder
b.WriteString("interface: ")
b.WriteString(i.Name)
b.WriteString(" index: ")
b.WriteString(strconv.Itoa(i.Index))
b.WriteString(" hostname: ")
b.WriteString(i.Hostname)
if i.K8sPod != "" {
b.WriteString(" pod: ")
b.WriteString(i.K8sPodNamespace)
b.WriteString("/")
b.WriteString(i.K8sPod)
} else if i.Netns != "" {
b.WriteString(" netns: ")
b.WriteString(i.Netns)
}

return b.String()
}
Loading

0 comments on commit 1f3c102

Please sign in to comment.