Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 93 additions & 3 deletions pkg/plugin/ebpfwindows/datapath_drop_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ const (

const (
// dropNotifyV1Len is the amount of packet data provided in a v0/v1 drop notification.
dropNotifyV1Len = 36
dropNotifyV1Len = 36
dropPktmonNotifyV1Len = 57
)

var dropNotifyLengthFromVersion = map[uint16]uint{
DropNotifyVersion0: dropNotifyV1Len, // retain backwards compatibility for testing.
DropNotifyVersion1: dropNotifyV1Len,
}

var pktmonDropNotifyLengthFromVersion = map[uint16]uint{
DropNotifyVersion1: dropPktmonNotifyV1Len,
}

var (
errUnexpectedDropNotifyLength = errors.New("unexpected DropNotify data length")
errInvalidDropNotifyVersion = errors.New("invalid DropNotify version")
errUnexpectedDropNotifyLength = errors.New("unexpected DropNotify data length")
errInvalidDropNotifyVersion = errors.New("invalid DropNotify version")
errInvalidPktmonDropNotifyVersion = errors.New("invalid Pktmon DropNotify version")
)

// DropNotify is the message format of a drop notification in the BPF ring buffer
Expand All @@ -50,6 +56,90 @@ type DropNotify struct {
Ifindex uint32
}

type NetEventDataHeader struct {
Type uint8
Version uint16
}

type PktmonEvtStreamPacketDescriptor struct {
PacketOriginalLength uint32
PacketLoggedLength uint32
PacketMetadataLength uint32
}

type PktmonEvtStreamMetadata struct {
PktGroupID uint64
PktCount uint16
AppearanceCount uint16
DirectionName uint16
PacketType uint16
ComponentID uint16
EdgeID uint16
FilterID uint16
DropReason uint32
DropLocation uint32
ProcNum uint16
Timestamp uint64
}

type PktmonEvtStreamPacketHeader struct {
EventID uint8
PacketDescriptor PktmonEvtStreamPacketDescriptor
Metadata PktmonEvtStreamMetadata
}

type PktmonDropNotify struct {
VersionHeader NetEventDataHeader
PktmonHeader PktmonEvtStreamPacketHeader
}

// DecodePktmonDrop will decode 'data' into the provided DropNotify structure
func DecodePktmonDrop(data []byte, pdn *PktmonDropNotify) error {
if err := pdn.decodePktmonDrop(data); err != nil {
return err
}
return nil
}

// DataOffset returns the offset from the beginning of PktmonDropNotify where the
// notification data begins.
func (n *PktmonDropNotify) DataOffset() uint {
return pktmonDropNotifyLengthFromVersion[n.VersionHeader.Version]
}

func (n *PktmonDropNotify) decodePktmonDrop(data []byte) error {
if l := len(data); l < dropPktmonNotifyV1Len {
return fmt.Errorf("%w: expected at least %d but got %d", errUnexpectedDropNotifyLength, dropPktmonNotifyV1Len, l)
}
version := byteorder.Native.Uint16(data[2:4])

// Check against max version.
if version > DropNotifyVersion1 {
return fmt.Errorf("%w: Unrecognized drop event version %d", errInvalidPktmonDropNotifyVersion, version)
}

// Decode logic for version = v1.
n.VersionHeader.Type = data[0]
n.VersionHeader.Version = version
n.PktmonHeader.EventID = data[4]
n.PktmonHeader.PacketDescriptor.PacketOriginalLength = byteorder.Native.Uint32(data[5:9])
n.PktmonHeader.PacketDescriptor.PacketLoggedLength = byteorder.Native.Uint32(data[9:13])
n.PktmonHeader.PacketDescriptor.PacketMetadataLength = byteorder.Native.Uint32(data[13:17])
n.PktmonHeader.Metadata.PktGroupID = byteorder.Native.Uint64(data[17:25])
n.PktmonHeader.Metadata.PktCount = byteorder.Native.Uint16(data[25:27])
n.PktmonHeader.Metadata.AppearanceCount = byteorder.Native.Uint16(data[27:29])
n.PktmonHeader.Metadata.DirectionName = byteorder.Native.Uint16(data[29:31])
n.PktmonHeader.Metadata.PacketType = byteorder.Native.Uint16(data[31:33])
n.PktmonHeader.Metadata.ComponentID = byteorder.Native.Uint16(data[33:35])
n.PktmonHeader.Metadata.EdgeID = byteorder.Native.Uint16(data[35:37])
n.PktmonHeader.Metadata.FilterID = byteorder.Native.Uint16(data[37:39])
n.PktmonHeader.Metadata.DropReason = byteorder.Native.Uint32(data[39:43])
n.PktmonHeader.Metadata.DropLocation = byteorder.Native.Uint32(data[43:47])
n.PktmonHeader.Metadata.ProcNum = byteorder.Native.Uint16(data[47:49])
n.PktmonHeader.Metadata.Timestamp = byteorder.Native.Uint64(data[49:57])
return nil
}

// DecodeDropNotify will decode 'data' into the provided DropNotify structure
func DecodeDropNotify(data []byte, dn *DropNotify) error {
return dn.decodeDropNotify(data)
Expand Down
28 changes: 28 additions & 0 deletions pkg/plugin/ebpfwindows/ebpf_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,34 @@ func (p *Plugin) handleTraceEvent(data unsafe.Pointer, size uint32) error {
}
utils.AddRetinaMetadata(fl, meta)
p.enricher.Write(e)

case MessageTypePktmonDrop:
if size <= uint32(unsafe.Sizeof(PktmonDropNotify{})) {
return fmt.Errorf("%w: %d", errInvalidDropNotifySize, size)
}

e, err := p.parser.Decode(&observer.MonitorEvent{
Payload: &observer.PerfEvent{
Data: perfData,
},
})
if err != nil {
return fmt.Errorf("could not convert pktmon dropnotify event to flow: %w", err)
}
meta := &utils.RetinaMetadata{}
utils.AddPacketSize(meta, size-uint32(unsafe.Sizeof(DropNotify{})))
fl := e.GetFlow()
if fl == nil {
return fmt.Errorf("%w", errNilDropNotifyFlow)
}
if fl.GetEventType() == nil {
return fmt.Errorf("%w", errNilDropNotifyEvent)
}
// Set the drop reason.
eventType := fl.GetEventType().GetSubType()
meta.DropReason = utils.DropReason(eventType)
utils.AddRetinaMetadata(fl, meta)
p.enricher.Write(e)
}
return nil
}
Loading
Loading