sflow

package
v0.331.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 21, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package sflow decodes sFlow v5 datagrams per the InMon publicly-published sFlow v5 specification (sflow.org). sFlow is the packet-sampling counterpart to NetFlow (covered by `netflow_v5_decode`): instead of summarising per-flow state, sFlow exports a configurable 1-in-N sample of the packets transiting a device, plus periodic interface counters.

Operationally, sFlow is the dominant monitoring telemetry on every modern datacenter switch — Arista, Cisco Nexus, HP, Juniper QFX, Mellanox, Cumulus — because it scales linearly with link speed regardless of flow churn (whereas NetFlow's per-flow state grows with churn). DDoS-detection, capacity planning, and security-NDR platforms all consume sFlow.

Wrap-vs-native judgement

Native. The sFlow v5 spec is fully public; the wire
format is XDR-encoded (network-byte-order, 4-byte
aligned). A 32-byte datagram header is followed by N
(Sample Type + Length + Data) records, each carrying
either a Flow Sample (per-packet) or a Counter Sample
(per-interface periodic). No crypto, no compression.
Operators paste sFlow bytes (UDP destination port 6343)
from a `tcpdump -X udp port 6343` line or a Wireshark
Follow-UDP-Stream view and get the documented header +
sample breakdown.

What this package covers

  • **Datagram common header** (variable; 28 or 40 bytes):

  • bytes 0-3: Version (uint32 BE; must be 5).

  • bytes 4-7: Agent Address Type (uint32 BE; 1 IPv4, 2 IPv6).

  • then 4 bytes IPv4 or 16 bytes IPv6 Agent Address.

  • next 4 bytes: Sub-Agent ID (uint32 BE).

  • next 4 bytes: Sequence Number (uint32 BE; per-Agent monotonic — gaps signal datagram loss).

  • next 4 bytes: System Uptime (uint32 BE; ms since agent boot).

  • next 4 bytes: Sample Count (uint32 BE; number of samples in this datagram).

  • **Sample walker** — repeated 8-byte header (Sample Type uint32 BE + Sample Length uint32 BE) + sample body. The Sample Type is split into top 12 bits (Enterprise; 0 for standard sFlow) + bottom 20 bits (Format). **4-entry standard sample format table**: 1 Flow Sample, 2 Counter Sample, 3 Expanded Flow Sample, 4 Expanded Counter Sample (Expanded uses uint64 ifIndex fields for bonded interfaces above 2^32 — same body otherwise).

  • **Flow Sample body** (Format 1):

  • Sequence Number (uint32 BE).

  • Source ID: top 8 bits **Source Class** (0 ifIndex, 1 smonVlanDataSource, 2 entPhysicalEntry) + low 24 bits **Source Index** (typically ifIndex of the sampler).

  • **Sampling Rate** (uint32 BE; 1-in-N).

  • Sample Pool (uint32 BE; total packets seen so far on this source).

  • Drops (uint32 BE; cumulative buffer drops).

  • Input Interface Index (uint32 BE).

  • Output Interface Index (uint32 BE; high bits encode special meanings — Discarded, Multiple, Unknown — surfaced as a Note when set).

  • Number of Flow Records (uint32 BE) + N Flow Records.

  • **Flow Record types** (most common):

  • **1 Raw Packet Header** — Header Protocol (uint32 BE; **6-entry name table**: 1 Ethernet / 11 802.11 / 12 IPv4 / 13 IPv6 / 21 PPP / 22 PPPoE) + Frame Length on wire (uint32 BE) + Stripped octets (uint32 BE; bytes trimmed from start, typically the L2 framing) + Original Sampled Header Length (uint32 BE) + Header Bytes (capped hex preview).

  • **2 Ethernet Frame Data** — Length + 6-byte src MAC + 6-byte dst MAC + EtherType.

  • **3 IPv4 Data** — Length + Protocol (IP proto number) + 4-byte src + 4-byte dst + uint32 src port + uint32 dst port + uint32 TCP flags + uint32 ToS.

  • **4 IPv6 Data** — same shape but with 16-byte addresses and an IPv6 priority.

  • **Counter Sample body** (Format 2):

  • Sequence Number (uint32 BE).

  • Source ID (same split as Flow Sample).

  • Number of Counter Records (uint32 BE) + N records.

  • **Counter Record type 1 (Generic Interface Counters)** — full 88-byte body: ifIndex / ifType / ifSpeed (uint64) / ifDirection / ifStatus / ifInOctets (uint64) / ifInUcastPkts / ifInMulticastPkts / ifInBroadcastPkts / ifInDiscards / ifInErrors / ifInUnknownProtos / ifOutOctets (uint64) / ifOutUcastPkts / ifOutMulticastPkts / ifOutBroadcastPkts / ifOutDiscards / ifOutErrors / ifPromiscuousMode.

What this package does NOT cover (deliberately out of scope)

  • UDP framing — feed sFlow bytes after the UDP header strip. sFlow runs on UDP destination port 6343.

  • sFlow v4 and earlier — the wire format changed significantly; v5 has been the standard since 2003.

  • Per-Counter-Record dissection beyond Generic Interface Counters (Ethernet / Token Ring / 802.11 / VG / VLAN / Processor / Radio counters) — surfaced as raw hex; a future iteration could add them.

  • Raw Packet Header inner dissection — the captured header bytes are surfaced as hex; the operator feeds them into the appropriate `*_decode` Spec (e.g. `ip_packet_decode`) based on the Header Protocol.

  • sFlow agent state-machine reasoning (sampling-rate drift, polling-interval skew) — higher-level analysis.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CounterRecord

type CounterRecord struct {
	RecordType   uint32 `json:"record_type"`
	Enterprise   uint32 `json:"enterprise"`
	Format       uint32 `json:"format"`
	FormatName   string `json:"format_name"`
	RecordLength uint32 `json:"record_length"`
	DataHex      string `json:"data_hex,omitempty"`

	// Decoded forms populated for known record formats.
	GenericInterface *GenericInterfaceCounters `json:"generic_interface_counters,omitempty"`
}

CounterRecord is one (Record Type, Length, Data) entry from a Counter Sample's counters array.

type CounterSampleBody

type CounterSampleBody struct {
	SequenceNumber  uint32          `json:"sequence_number"`
	SourceID        uint32          `json:"source_id"`
	SourceClass     int             `json:"source_class"`
	SourceClassName string          `json:"source_class_name"`
	SourceIndex     uint32          `json:"source_index"`
	NumberOfRecords uint32          `json:"number_of_counter_records"`
	CounterRecords  []CounterRecord `json:"counter_records,omitempty"`
}

CounterSampleBody is the decoded body of a Counter Sample (Format 2).

type DecodeOpts

type DecodeOpts struct {
	// MaxHeaderBytes caps the per-Raw-Packet-Header hex
	// preview. Zero shows full header (up to typical
	// sampled length of 128 bytes).
	MaxHeaderBytes int
}

DecodeOpts tunes the walker for output size.

func DefaultDecodeOpts

func DefaultDecodeOpts() DecodeOpts

DefaultDecodeOpts returns a 128-byte header preview cap.

type EthernetFrame

type EthernetFrame struct {
	Length       uint32 `json:"length"`
	SrcMAC       string `json:"src_mac"`
	DstMAC       string `json:"dst_mac"`
	EtherType    uint32 `json:"ether_type"`
	EtherTypeHex string `json:"ether_type_hex"`
}

EthernetFrame is the decoded body of Flow Record Format 2.

type FlowRecord

type FlowRecord struct {
	RecordType   uint32 `json:"record_type"`
	Enterprise   uint32 `json:"enterprise"`
	Format       uint32 `json:"format"`
	FormatName   string `json:"format_name"`
	RecordLength uint32 `json:"record_length"`
	DataHex      string `json:"data_hex,omitempty"`

	// Decoded forms populated for known record formats.
	RawPacketHeader *RawPacketHeader `json:"raw_packet_header,omitempty"`
	EthernetFrame   *EthernetFrame   `json:"ethernet_frame,omitempty"`
	IPv4Data        *IPv4FlowData    `json:"ipv4_data,omitempty"`
}

FlowRecord is one (Record Type, Length, Data) entry from a Flow Sample's flow_records array.

type FlowSampleBody

type FlowSampleBody struct {
	SequenceNumber      uint32       `json:"sequence_number"`
	SourceID            uint32       `json:"source_id"`
	SourceClass         int          `json:"source_class"`
	SourceClassName     string       `json:"source_class_name"`
	SourceIndex         uint32       `json:"source_index"`
	SamplingRate        uint32       `json:"sampling_rate"`
	SamplePool          uint32       `json:"sample_pool"`
	Drops               uint32       `json:"drops"`
	InputInterface      uint32       `json:"input_interface"`
	OutputInterface     uint32       `json:"output_interface"`
	OutputInterfaceNote string       `json:"output_interface_note,omitempty"`
	NumberOfRecords     uint32       `json:"number_of_flow_records"`
	FlowRecords         []FlowRecord `json:"flow_records,omitempty"`
}

FlowSampleBody is the decoded body of a Flow Sample (Format 1).

type GenericInterfaceCounters

type GenericInterfaceCounters struct {
	IfIndex            uint32 `json:"if_index"`
	IfType             uint32 `json:"if_type"`
	IfSpeed            uint64 `json:"if_speed"`
	IfDirection        uint32 `json:"if_direction"`
	IfStatus           uint32 `json:"if_status"`
	IfInOctets         uint64 `json:"if_in_octets"`
	IfInUcastPkts      uint32 `json:"if_in_ucast_pkts"`
	IfInMulticastPkts  uint32 `json:"if_in_multicast_pkts"`
	IfInBroadcastPkts  uint32 `json:"if_in_broadcast_pkts"`
	IfInDiscards       uint32 `json:"if_in_discards"`
	IfInErrors         uint32 `json:"if_in_errors"`
	IfInUnknownProtos  uint32 `json:"if_in_unknown_protos"`
	IfOutOctets        uint64 `json:"if_out_octets"`
	IfOutUcastPkts     uint32 `json:"if_out_ucast_pkts"`
	IfOutMulticastPkts uint32 `json:"if_out_multicast_pkts"`
	IfOutBroadcastPkts uint32 `json:"if_out_broadcast_pkts"`
	IfOutDiscards      uint32 `json:"if_out_discards"`
	IfOutErrors        uint32 `json:"if_out_errors"`
	IfPromiscuousMode  uint32 `json:"if_promiscuous_mode"`
}

GenericInterfaceCounters is the decoded body of Counter Record Format 1 (88-byte ifEntry-equivalent body).

type IPv4FlowData

type IPv4FlowData struct {
	Length        uint32 `json:"length"`
	Protocol      uint32 `json:"protocol"`
	SrcAddress    string `json:"src_address"`
	DstAddress    string `json:"dst_address"`
	SrcPort       uint32 `json:"src_port"`
	DstPort       uint32 `json:"dst_port"`
	TCPFlags      uint32 `json:"tcp_flags"`
	TypeOfService uint32 `json:"type_of_service"`
}

IPv4FlowData is the decoded body of Flow Record Format 3.

type RawPacketHeader

type RawPacketHeader struct {
	HeaderProtocol      uint32 `json:"header_protocol"`
	HeaderProtocolName  string `json:"header_protocol_name"`
	FrameLengthOnWire   uint32 `json:"frame_length_on_wire"`
	StrippedBytes       uint32 `json:"stripped_bytes"`
	SampledHeaderLength uint32 `json:"sampled_header_length"`
	HeaderBytesShown    int    `json:"header_bytes_shown,omitempty"`
	HeaderHex           string `json:"header_hex,omitempty"`
}

RawPacketHeader is the decoded body of Flow Record Format 1.

type Result

type Result struct {
	Version          uint32   `json:"version"`
	AgentAddressType int      `json:"agent_address_type"`
	AgentAddress     string   `json:"agent_address"`
	SubAgentID       uint32   `json:"sub_agent_id"`
	SequenceNumber   uint32   `json:"sequence_number"`
	SystemUptimeMs   uint32   `json:"system_uptime_ms"`
	SampleCount      uint32   `json:"sample_count"`
	Samples          []Sample `json:"samples"`
	TotalBytes       int      `json:"total_bytes"`
	Notes            []string `json:"notes,omitempty"`
}

Result is the top-level decoded view of an sFlow v5 datagram.

func Decode

func Decode(hexStr string, opts DecodeOpts) (*Result, error)

Decode parses a single sFlow v5 datagram from hex.

type Sample

type Sample struct {
	SampleType   uint32 `json:"sample_type"`
	Enterprise   uint32 `json:"enterprise"`
	Format       uint32 `json:"format"`
	FormatName   string `json:"format_name"`
	SampleLength uint32 `json:"sample_length"`
	BodyHex      string `json:"body_hex,omitempty"`

	// Decoded forms populated for known sample formats.
	FlowSample    *FlowSampleBody    `json:"flow_sample,omitempty"`
	CounterSample *CounterSampleBody `json:"counter_sample,omitempty"`
}

Sample is one (Sample Type, Length, Data) record from the sample walker.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL