telegraf/plugins/inputs/sflow/decoder.go

307 lines
11 KiB
Go

package sflow
import (
"fmt"
"math"
"net"
"github.com/influxdata/telegraf/plugins/inputs/sflow/decoder"
)
const (
addressTypeIPv4 = uint32(1) // line: 1383
addressTypeIPv6 = uint32(2) // line: 1384
sampleTypeFlowSample = uint32(1) // line: 1614
sampleTypeFlowSampleExpanded = uint32(3) // line: 1698
flowDataRawPacketHeaderFormat = uint32(1) // line: 1938
headerProtocolEthernetIso88023 = uint32(1) // line: 1920
ipProtocolTCP = byte(6)
ipProtocolUDP = byte(17)
metricName = "sflow"
)
var headerProtocolMap = map[uint32]string{
headerProtocolEthernetIso88023: "ETHERNET-ISO88023", // line: 1920
}
var etypeMap = map[uint16]string{
0x0800: "IPv4",
0x86DD: "IPv6",
}
func bytesToIPStr(b []byte) string {
return net.IP(b).String()
}
func bytesToMACStr(b []byte) string {
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4], b[5])
}
var ipvMap = map[uint32]string{
1: "IPV4", // line: 1383
2: "IPV6", // line: 1384
}
// V5FormatOptions captures configuration for controlling the processing of an SFlow V5 packet.
type V5FormatOptions struct {
MaxFlowsPerSample uint32
MaxSamplesPerPacket uint32
MaxFlowHeaderLength uint32
MaxSampleLength uint32
}
// NewDefaultV5FormatOptions answers a new V5FormatOptions with default values initialised
func NewDefaultV5FormatOptions() V5FormatOptions {
return V5FormatOptions{
MaxFlowsPerSample: math.MaxUint32,
MaxSamplesPerPacket: math.MaxUint32,
MaxFlowHeaderLength: math.MaxUint32,
MaxSampleLength: math.MaxUint32,
}
}
// V5Format answers and decoder.Directive capable of decoding sFlow v5 packets in accordance
// with SFlow v5 specification at https://sflow.org/sflow_version_5.txt
func V5Format(options V5FormatOptions) decoder.Directive {
return decoder.Seq( // line: 1823
decoder.U32().Do(decoder.U32Assert(func(v uint32) bool { return v == 5 }, "Version %d not supported, only version 5")),
decoder.U32().Switch( // agent_address line: 1787
decoder.Case(addressTypeIPv4, decoder.Bytes(4).Do(decoder.BytesToStr(4, bytesToIPStr).AsT("agent_address"))), // line: 1390
decoder.Case(addressTypeIPv6, decoder.Bytes(16).Do(decoder.BytesToStr(16, bytesToIPStr).AsT("agent_address"))), // line: 1393
),
decoder.U32(), // sub_agent_id line: 1790
decoder.U32(), // sequence_number line: 1801
decoder.U32(), // uptime line: 1804
decoder.U32().Iter(options.MaxSamplesPerPacket, sampleRecord(options)), // samples line: 1812
)
}
func sampleRecord(options V5FormatOptions) decoder.Directive {
var sampleType interface{}
return decoder.Seq( // line: 1760
decoder.U32().Ref(&sampleType), // sample_type line: 1761
decoder.U32().Encapsulated(options.MaxSampleLength, // sample_data line: 1762
decoder.Ref(sampleType).Switch(
decoder.Case(sampleTypeFlowSample, flowSample(sampleType, options)), // line: 1614
decoder.Case(sampleTypeFlowSampleExpanded, flowSampleExpanded(sampleType, options)), // line: 1698
decoder.DefaultCase(nil), // this allows other cases to just be ignored rather than cause an error
),
),
)
}
func flowSample(sampleType interface{}, options V5FormatOptions) decoder.Directive {
var samplingRate = new(uint32)
var sourceIDIndex = new(uint32)
return decoder.Seq( // line: 1616
decoder.U32(), // sequence_number line: 1617
decoder.U32(). // source_id line: 1622
Do(decoder.U32ToU32(func(v uint32) uint32 { return v >> 24 }).AsT("source_id_type")). // source_id_type Line 1465
Do(decoder.U32ToU32(func(v uint32) uint32 { return v & 0x00ffffff }).Set(sourceIDIndex).AsT("source_id_index")), // line: 1468
decoder.U32().Do(decoder.Set(samplingRate).AsF("sampling_rate")), // line: 1631
decoder.U32(), // samplePool: Line 1632
decoder.U32().Do(decoder.AsF("drops")), // Line 1636
decoder.U32(). // line: 1651
Do(decoder.U32ToU32(func(v uint32) uint32 { return v & 0x3fffffff }).AsT("input_ifindex")). // line: 1477
Do(decoder.U32ToU32(func(v uint32) uint32 { return v & 0x3fffffff }).
ToString(func(v uint32) string {
if v == *sourceIDIndex {
return "ingress"
}
return ""
}).
BreakIf("").
AsT("sample_direction")),
decoder.U32(). // line: 1652
Do(decoder.U32ToU32(func(v uint32) uint32 { return v & 0x3fffffff }).AsT("output_ifindex")). // line: 1477
Do(decoder.U32ToU32(func(v uint32) uint32 { return v & 0x3fffffff }).
ToString(func(v uint32) string {
if v == *sourceIDIndex {
return "egress"
}
return ""
}).
BreakIf("").
AsT("sample_direction")),
decoder.U32().Iter(options.MaxFlowsPerSample, flowRecord(samplingRate, options)), // line: 1654
)
}
func flowSampleExpanded(sampleType interface{}, options V5FormatOptions) decoder.Directive {
var samplingRate = new(uint32)
var sourceIDIndex = new(uint32)
return decoder.Seq( // line: 1700
decoder.U32(), // sequence_number line: 1701
decoder.U32().Do(decoder.AsT("source_id_type")), // line: 1706 + 16878
decoder.U32().Do(decoder.Set(sourceIDIndex).AsT("source_id_index")), // line 1689
decoder.U32().Do(decoder.Set(samplingRate).AsF("sampling_rate")), // sample_rate line: 1707
decoder.U32(), // saple_pool line: 1708
decoder.U32().Do(decoder.AsF("drops")), // line: 1712
decoder.U32(), // inputt line: 1727
decoder.U32(). // input line: 1727
Do(decoder.AsT("input_ifindex")). // line: 1728
Do(decoder.U32ToStr(func(v uint32) string {
if v == *sourceIDIndex {
return "ingress"
}
return ""
}).
BreakIf("").
AsT("sample_direction")),
decoder.U32(), // output line: 1728
decoder.U32(). // outpuit line: 1728
Do(decoder.AsT("output_ifindex")). // line: 1729 CHANFE AS FOR NON EXPANDED
Do(decoder.U32ToStr(func(v uint32) string {
if v == *sourceIDIndex {
return "egress"
}
return ""
}).
BreakIf("").
AsT("sample_direction")),
decoder.U32().Iter(options.MaxFlowsPerSample, flowRecord(samplingRate, options)), // line: 1730
)
}
func flowRecord(samplingRate *uint32, options V5FormatOptions) decoder.Directive {
var flowFormat interface{}
return decoder.Seq( // line: 1597
decoder.U32().Ref(&flowFormat), // line 1598
decoder.U32().Encapsulated(options.MaxFlowHeaderLength, // line 1599
decoder.Ref(flowFormat).Switch(
decoder.Case(flowDataRawPacketHeaderFormat, rawPacketHeaderFlowData(samplingRate, options)), // line: 1938
decoder.DefaultCase(nil),
),
),
)
}
func rawPacketHeaderFlowData(samplingRate *uint32, options V5FormatOptions) decoder.Directive {
var protocol interface{}
var headerLength interface{}
return decoder.Seq( // line: 1940
decoder.U32().Ref(&protocol).Do(decoder.MapU32ToStr(headerProtocolMap).AsT("header_protocol")), // line: 1941
decoder.U32(). // line: 1942
Do(decoder.AsF("frame_length")).
Do(decoder.U32ToU32(func(in uint32) uint32 {
return in * (*samplingRate)
}).AsF("bytes")),
decoder.U32(), // stripped line: 1967
decoder.U32().Ref(&headerLength).Do(decoder.AsF("header_length")),
decoder.Ref(headerLength).Encapsulated(options.MaxFlowHeaderLength,
decoder.Ref(protocol).Switch(
decoder.Case(headerProtocolEthernetIso88023, ethHeader(options)),
decoder.DefaultCase(nil),
)),
)
}
// ethHeader answers a decode Directive that will decode an ethernet frame header
// according to https://en.wikipedia.org/wiki/Ethernet_frame
func ethHeader(options V5FormatOptions) decoder.Directive {
var tagOrEType interface{}
etype := new(uint16)
return decoder.Seq(
decoder.OpenMetric(metricName),
decoder.Bytes(6).Do(decoder.BytesToStr(6, bytesToMACStr).AsT("dst_mac")),
decoder.Bytes(6).Do(decoder.BytesToStr(6, bytesToMACStr).AsT("src_mac")),
decoder.U16().Ref(&tagOrEType).Switch(
decoder.Case(uint16(0x8100),
decoder.Seq(
decoder.U16(),
decoder.U16().Do(decoder.Set(etype)), // just follows on from vlan id
),
),
decoder.DefaultCase( // Not an 802.1Q VLAN Tag, just treat as an ether type
decoder.Ref(tagOrEType).Do(decoder.Set(etype)),
),
),
decoder.U16Value(etype).Do(decoder.MapU16ToStr(etypeMap).AsT("ether_type")),
decoder.U16Value(etype).Switch(
decoder.Case(uint16(0x0800), ipv4Header(options)),
decoder.Case(uint16(0x86DD), ipv6Header(options)),
decoder.DefaultCase(nil),
),
decoder.CloseMetric(),
)
}
// ipv4Header answers a decode Directive that decode an IPv4 header according to
// https://en.wikipedia.org/wiki/IPv4
func ipv4Header(options V5FormatOptions) decoder.Directive {
var proto interface{}
return decoder.Seq(
decoder.U16().
Do(decoder.U16ToU16(func(in uint16) uint16 { return (in & 0xFC) >> 2 }).AsT("ip_dscp")).
Do(decoder.U16ToU16(func(in uint16) uint16 { return in & 0x3 }).AsT("ip_ecn")),
decoder.U16().Do(decoder.AsF("ip_total_length")),
decoder.U16(),
decoder.U16().
Do(decoder.U16ToU16(func(v uint16) uint16 { return (v & 0xE000) >> 13 }).AsF("ip_flags")).
Do(decoder.U16ToU16(func(v uint16) uint16 { return v & 0x1FFF }).AsF("ip_fragment_offset")),
decoder.Bytes(1).Do(decoder.BytesTo(1, func(b []byte) interface{} { return uint8(b[0]) }).AsF("ip_ttl")),
decoder.Bytes(1).Ref(&proto),
decoder.U16(),
decoder.Bytes(4).Do(decoder.BytesToStr(4, bytesToIPStr).AsT("src_ip")),
decoder.Bytes(4).Do(decoder.BytesToStr(4, bytesToIPStr).AsT("dst_ip")),
decoder.Ref(proto).Switch( // Does not consider IHL and Options
decoder.Case(ipProtocolTCP, tcpHeader(options)),
decoder.Case(ipProtocolUDP, udpHeader(options)),
decoder.DefaultCase(nil),
),
)
}
// ipv6Header answers a decode Directive that decode an IPv6 header according to
// https://en.wikipedia.org/wiki/IPv6_packet
func ipv6Header(options V5FormatOptions) decoder.Directive {
nextHeader := new(uint16)
return decoder.Seq(
decoder.U32().
Do(decoder.U32ToU32(func(in uint32) uint32 { return (in & 0xFC00000) >> 22 }).AsF("ip_dscp")).
Do(decoder.U32ToU32(func(in uint32) uint32 { return (in & 0x300000) >> 20 }).AsF("ip_ecn")),
decoder.U16(),
decoder.U16().
Do(decoder.U16ToU16(func(in uint16) uint16 { return (in & 0xFF00) >> 8 }).Set(nextHeader)),
decoder.Bytes(16).Do(decoder.BytesToStr(16, bytesToIPStr).AsT("src_ip")),
decoder.Bytes(16).Do(decoder.BytesToStr(16, bytesToIPStr).AsT("dst_ip")),
decoder.U16Value(nextHeader).Switch(
decoder.Case(uint16(ipProtocolTCP), tcpHeader(options)),
decoder.Case(uint16(ipProtocolUDP), udpHeader(options)),
decoder.DefaultCase(nil),
),
)
}
func tcpHeader(options V5FormatOptions) decoder.Directive {
return decoder.Seq(
decoder.U16().
Do(decoder.AsT("src_port")),
decoder.U16().
Do(decoder.AsT("dst_port")),
decoder.U32(), //"sequence"),
decoder.U32(), //"ack_number"),
decoder.Bytes(2).
Do(decoder.BytesToU32(2, func(b []byte) uint32 { return uint32((b[0] & 0xF0) * 4) }).AsF("tcp_header_length")),
decoder.U16().Do(decoder.AsF("tcp_window_size")),
decoder.U16(), // "checksum"),
decoder.U16().Do(decoder.AsF("tcp_urgent_pointer")),
)
}
func udpHeader(options V5FormatOptions) decoder.Directive {
return decoder.Seq(
decoder.U16().
Do(decoder.AsT("src_port")),
decoder.U16().
Do(decoder.AsT("dst_port")),
decoder.U16().Do(decoder.AsF("udp_length")),
)
}