1 // Copyright 2014 Google, Inc. All rights reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
8 This layer decodes SFlow version 5 datagrams.
10 The specification can be found here: http://sflow.org/sflow_version_5.txt
12 Additional developer information about sflow can be found at:
13 http://sflow.org/developers/specifications.php
16 http://sflow.org/index.php
18 Two forms of sample data are defined: compact and expanded. The
19 Specification has this to say:
21 Compact and expand forms of counter and flow samples are defined.
22 An agent must not mix compact/expanded encodings. If an agent
23 will never use ifIndex numbers >= 2^24 then it must use compact
24 encodings for all interfaces. Otherwise the expanded formats must
25 be used for all interfaces.
27 This decoder only supports the compact form, because that is the only
28 one for which data was avaialble.
30 The datagram is composed of one or more samples of type flow or counter,
31 and each sample is composed of one or more records describing the sample.
32 A sample is a single instance of sampled inforamtion, and each record in
33 the sample gives additional / supplimentary information about the sample.
35 The following sample record types are supported:
38 opaque = flow_data; enterprise = 0; format = 1
41 opaque = flow_data; enterprise = 0; format = 1001
44 opaque = flow_data; enterprise = 0; format = 1002
47 opaque = flow_data; enterprise = 0; format = 1003
50 opaque = flow_data; enterprise = 0; format = 1004
53 opaque = flow_data; enterprise = 0; format = 1005
55 The following types of counter records are supported:
57 Generic Interface Counters - see RFC 2233
58 opaque = counter_data; enterprise = 0; format = 1
60 Ethernet Interface Counters - see RFC 2358
61 opaque = counter_data; enterprise = 0; format = 2
63 SFlow is encoded using XDR (RFC4506). There are a few places
64 where the standard 4-byte fields are partitioned into two
65 bitfields of different lengths. I'm not sure why the designers
66 chose to pack together two values like this in some places, and
67 in others they use the entire 4-byte value to store a number that
68 will never be more than a few bits. In any case, there are a couple
69 of types defined to handle the decoding of these bitfields, and
70 that's why they're there. */
80 "github.com/google/gopacket"
83 // SFlowRecord holds both flow sample records and counter sample records.
84 // A Record is the structure that actually holds the sampled data
86 type SFlowRecord interface {
89 // SFlowDataSource encodes a 2-bit SFlowSourceFormat in its most significant
90 // 2 bits, and an SFlowSourceValue in its least significant 30 bits.
91 // These types and values define the meaning of the inteface information
92 // presented in the sample metadata.
93 type SFlowDataSource int32
95 func (sdc SFlowDataSource) decode() (SFlowSourceFormat, SFlowSourceValue) {
96 leftField := sdc >> 30
97 rightField := uint32(0x3FFFFFFF) & uint32(sdc)
98 return SFlowSourceFormat(leftField), SFlowSourceValue(rightField)
101 type SFlowDataSourceExpanded struct {
102 SourceIDClass SFlowSourceFormat
103 SourceIDIndex SFlowSourceValue
106 func (sdce SFlowDataSourceExpanded) decode() (SFlowSourceFormat, SFlowSourceValue) {
107 leftField := sdce.SourceIDClass >> 30
108 rightField := uint32(0x3FFFFFFF) & uint32(sdce.SourceIDIndex)
109 return SFlowSourceFormat(leftField), SFlowSourceValue(rightField)
112 type SFlowSourceFormat uint32
114 type SFlowSourceValue uint32
117 SFlowTypeSingleInterface SFlowSourceFormat = 0
118 SFlowTypePacketDiscarded SFlowSourceFormat = 1
119 SFlowTypeMultipleDestinations SFlowSourceFormat = 2
122 func (sdf SFlowSourceFormat) String() string {
124 case SFlowTypeSingleInterface:
125 return "Single Interface"
126 case SFlowTypePacketDiscarded:
127 return "Packet Discarded"
128 case SFlowTypeMultipleDestinations:
129 return "Multiple Destinations"
135 func decodeSFlow(data []byte, p gopacket.PacketBuilder) error {
136 s := &SFlowDatagram{}
137 err := s.DecodeFromBytes(data, p)
142 p.SetApplicationLayer(s)
146 // SFlowDatagram is the outermost container which holds some basic information
147 // about the reporting agent, and holds at least one sample record
148 type SFlowDatagram struct {
151 DatagramVersion uint32
154 SequenceNumber uint32
157 FlowSamples []SFlowFlowSample
158 CounterSamples []SFlowCounterSample
161 // An SFlow datagram's outer container has the following
165 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
166 // | int sFlow version (2|4|5) |
167 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
168 // | int IP version of the Agent (1=v4|2=v6) |
169 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
170 // / Agent IP address (v4=4byte|v6=16byte) /
172 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
173 // | int sub agent id |
174 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
175 // | int datagram sequence number |
176 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
177 // | int switch uptime in ms |
178 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
179 // | int n samples in datagram |
180 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
183 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
185 // SFlowDataFormat encodes the EnterpriseID in the most
186 // significant 12 bits, and the SampleType in the least significant
188 type SFlowDataFormat uint32
190 func (sdf SFlowDataFormat) decode() (SFlowEnterpriseID, SFlowSampleType) {
191 leftField := sdf >> 12
192 rightField := uint32(0xFFF) & uint32(sdf)
193 return SFlowEnterpriseID(leftField), SFlowSampleType(rightField)
196 // SFlowEnterpriseID is used to differentiate between the
197 // official SFlow standard, and other, vendor-specific
198 // types of flow data. (Similiar to SNMP's enterprise MIB
199 // OIDs) Only the office SFlow Enterprise ID is decoded
201 type SFlowEnterpriseID uint32
204 SFlowStandard SFlowEnterpriseID = 0
207 func (eid SFlowEnterpriseID) String() string {
210 return "Standard SFlow"
216 func (eid SFlowEnterpriseID) GetType() SFlowEnterpriseID {
220 // SFlowSampleType specifies the type of sample. Only flow samples
221 // and counter samples are supported
222 type SFlowSampleType uint32
225 SFlowTypeFlowSample SFlowSampleType = 1
226 SFlowTypeCounterSample SFlowSampleType = 2
227 SFlowTypeExpandedFlowSample SFlowSampleType = 3
228 SFlowTypeExpandedCounterSample SFlowSampleType = 4
231 func (st SFlowSampleType) GetType() SFlowSampleType {
233 case SFlowTypeFlowSample:
234 return SFlowTypeFlowSample
235 case SFlowTypeCounterSample:
236 return SFlowTypeCounterSample
237 case SFlowTypeExpandedFlowSample:
238 return SFlowTypeExpandedFlowSample
239 case SFlowTypeExpandedCounterSample:
240 return SFlowTypeExpandedCounterSample
242 panic("Invalid Sample Type")
246 func (st SFlowSampleType) String() string {
248 case SFlowTypeFlowSample:
250 case SFlowTypeCounterSample:
251 return "Counter Sample"
252 case SFlowTypeExpandedFlowSample:
253 return "Expanded Flow Sample"
254 case SFlowTypeExpandedCounterSample:
255 return "Expanded Counter Sample"
261 func (s *SFlowDatagram) LayerType() gopacket.LayerType { return LayerTypeSFlow }
263 func (d *SFlowDatagram) Payload() []byte { return nil }
265 func (d *SFlowDatagram) CanDecode() gopacket.LayerClass { return LayerTypeSFlow }
267 func (d *SFlowDatagram) NextLayerType() gopacket.LayerType { return gopacket.LayerTypePayload }
269 // SFlowIPType determines what form the IP address being decoded will
270 // take. This is an XDR union type allowing for both IPv4 and IPv6
271 type SFlowIPType uint32
274 SFlowIPv4 SFlowIPType = 1
275 SFlowIPv6 SFlowIPType = 2
278 func (s SFlowIPType) String() string {
289 func (s SFlowIPType) Length() int {
300 func (s *SFlowDatagram) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
301 var agentAddressType SFlowIPType
303 data, s.DatagramVersion = data[4:], binary.BigEndian.Uint32(data[:4])
304 data, agentAddressType = data[4:], SFlowIPType(binary.BigEndian.Uint32(data[:4]))
305 data, s.AgentAddress = data[agentAddressType.Length():], data[:agentAddressType.Length()]
306 data, s.SubAgentID = data[4:], binary.BigEndian.Uint32(data[:4])
307 data, s.SequenceNumber = data[4:], binary.BigEndian.Uint32(data[:4])
308 data, s.AgentUptime = data[4:], binary.BigEndian.Uint32(data[:4])
309 data, s.SampleCount = data[4:], binary.BigEndian.Uint32(data[:4])
311 if s.SampleCount < 1 {
312 return fmt.Errorf("SFlow Datagram has invalid sample length: %d", s.SampleCount)
314 for i := uint32(0); i < s.SampleCount; i++ {
315 sdf := SFlowDataFormat(binary.BigEndian.Uint32(data[:4]))
316 _, sampleType := sdf.decode()
318 case SFlowTypeFlowSample:
319 if flowSample, err := decodeFlowSample(&data, false); err == nil {
320 s.FlowSamples = append(s.FlowSamples, flowSample)
324 case SFlowTypeCounterSample:
325 if counterSample, err := decodeCounterSample(&data, false); err == nil {
326 s.CounterSamples = append(s.CounterSamples, counterSample)
330 case SFlowTypeExpandedFlowSample:
331 if flowSample, err := decodeFlowSample(&data, true); err == nil {
332 s.FlowSamples = append(s.FlowSamples, flowSample)
336 case SFlowTypeExpandedCounterSample:
337 if counterSample, err := decodeCounterSample(&data, true); err == nil {
338 s.CounterSamples = append(s.CounterSamples, counterSample)
344 return fmt.Errorf("Unsupported SFlow sample type %d", sampleType)
350 // SFlowFlowSample represents a sampled packet and contains
351 // one or more records describing the packet
352 type SFlowFlowSample struct {
353 EnterpriseID SFlowEnterpriseID
354 Format SFlowSampleType
356 SequenceNumber uint32
357 SourceIDClass SFlowSourceFormat
358 SourceIDIndex SFlowSourceValue
362 InputInterfaceFormat uint32
363 InputInterface uint32
364 OutputInterfaceFormat uint32
365 OutputInterface uint32
367 Records []SFlowRecord
370 // Flow samples have the following structure. Note
371 // the bit fields to encode the Enterprise ID and the
372 // Flow record format: type 1
375 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
376 // | 20 bit Interprise (0) |12 bit format |
377 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
379 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
380 // | int sample sequence number |
381 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
382 // |id type | src id index value |
383 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
384 // | int sampling rate |
385 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
386 // | int sample pool |
387 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
389 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
390 // | int input ifIndex |
391 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
392 // | int output ifIndex |
393 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
394 // | int number of records |
395 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
398 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
400 // Flow samples have the following structure.
401 // Flow record format: type 3
404 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
405 // | 20 bit Interprise (0) |12 bit format |
406 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
408 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
409 // | int sample sequence number |
410 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
411 // | int src id type |
412 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
413 // | int src id index value |
414 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
415 // | int sampling rate |
416 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
417 // | int sample pool |
418 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
420 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
421 // | int input interface format |
422 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
423 // | int input interface value |
424 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
425 // | int output interface format |
426 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
427 // | int output interface value |
428 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
429 // | int number of records |
430 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
433 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
435 type SFlowFlowDataFormat uint32
437 func (fdf SFlowFlowDataFormat) decode() (SFlowEnterpriseID, SFlowFlowRecordType) {
438 leftField := fdf >> 12
439 rightField := uint32(0xFFF) & uint32(fdf)
440 return SFlowEnterpriseID(leftField), SFlowFlowRecordType(rightField)
443 func (fs SFlowFlowSample) GetRecords() []SFlowRecord {
447 func (fs SFlowFlowSample) GetType() SFlowSampleType {
448 return SFlowTypeFlowSample
451 func skipRecord(data *[]byte) {
452 recordLength := int(binary.BigEndian.Uint32((*data)[4:]))
453 *data = (*data)[(recordLength+((4-recordLength)%4))+8:]
456 func decodeFlowSample(data *[]byte, expanded bool) (SFlowFlowSample, error) {
457 s := SFlowFlowSample{}
458 var sdf SFlowDataFormat
459 *data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
460 var sdc SFlowDataSource
462 s.EnterpriseID, s.Format = sdf.decode()
463 *data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
464 *data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
466 *data, s.SourceIDClass = (*data)[4:], SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4]))
467 *data, s.SourceIDIndex = (*data)[4:], SFlowSourceValue(binary.BigEndian.Uint32((*data)[:4]))
469 *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
470 s.SourceIDClass, s.SourceIDIndex = sdc.decode()
472 *data, s.SamplingRate = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
473 *data, s.SamplePool = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
474 *data, s.Dropped = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
477 *data, s.InputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
478 *data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
479 *data, s.OutputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
480 *data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
482 *data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
483 *data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
485 *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
487 for i := uint32(0); i < s.RecordCount; i++ {
488 rdf := SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
489 _, flowRecordType := rdf.decode()
491 switch flowRecordType {
492 case SFlowTypeRawPacketFlow:
493 if record, err := decodeRawPacketFlowRecord(data); err == nil {
494 s.Records = append(s.Records, record)
498 case SFlowTypeExtendedUserFlow:
499 if record, err := decodeExtendedUserFlow(data); err == nil {
500 s.Records = append(s.Records, record)
504 case SFlowTypeExtendedUrlFlow:
505 if record, err := decodeExtendedURLRecord(data); err == nil {
506 s.Records = append(s.Records, record)
510 case SFlowTypeExtendedSwitchFlow:
511 if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
512 s.Records = append(s.Records, record)
516 case SFlowTypeExtendedRouterFlow:
517 if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
518 s.Records = append(s.Records, record)
522 case SFlowTypeExtendedGatewayFlow:
523 if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
524 s.Records = append(s.Records, record)
528 case SFlowTypeEthernetFrameFlow:
531 return s, errors.New("skipping TypeEthernetFrameFlow")
532 case SFlowTypeIpv4Flow:
533 if record, err := decodeSFlowIpv4Record(data); err == nil {
534 s.Records = append(s.Records, record)
538 case SFlowTypeIpv6Flow:
539 if record, err := decodeSFlowIpv6Record(data); err == nil {
540 s.Records = append(s.Records, record)
544 case SFlowTypeExtendedMlpsFlow:
547 return s, errors.New("skipping TypeExtendedMlpsFlow")
548 case SFlowTypeExtendedNatFlow:
551 return s, errors.New("skipping TypeExtendedNatFlow")
552 case SFlowTypeExtendedMlpsTunnelFlow:
555 return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
556 case SFlowTypeExtendedMlpsVcFlow:
559 return s, errors.New("skipping TypeExtendedMlpsVcFlow")
560 case SFlowTypeExtendedMlpsFecFlow:
563 return s, errors.New("skipping TypeExtendedMlpsFecFlow")
564 case SFlowTypeExtendedMlpsLvpFecFlow:
567 return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
568 case SFlowTypeExtendedVlanFlow:
571 return s, errors.New("skipping TypeExtendedVlanFlow")
572 case SFlowTypeExtendedIpv4TunnelEgressFlow:
573 if record, err := decodeExtendedIpv4TunnelEgress(data); err == nil {
574 s.Records = append(s.Records, record)
578 case SFlowTypeExtendedIpv4TunnelIngressFlow:
579 if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
580 s.Records = append(s.Records, record)
584 case SFlowTypeExtendedIpv6TunnelEgressFlow:
585 if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
586 s.Records = append(s.Records, record)
590 case SFlowTypeExtendedIpv6TunnelIngressFlow:
591 if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
592 s.Records = append(s.Records, record)
596 case SFlowTypeExtendedDecapsulateEgressFlow:
597 if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
598 s.Records = append(s.Records, record)
602 case SFlowTypeExtendedDecapsulateIngressFlow:
603 if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
604 s.Records = append(s.Records, record)
608 case SFlowTypeExtendedVniEgressFlow:
609 if record, err := decodeExtendedVniEgress(data); err == nil {
610 s.Records = append(s.Records, record)
614 case SFlowTypeExtendedVniIngressFlow:
615 if record, err := decodeExtendedVniIngress(data); err == nil {
616 s.Records = append(s.Records, record)
621 return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
627 // Counter samples report information about various counter
628 // objects. Typically these are items like IfInOctets, or
629 // CPU / Memory stats, etc. SFlow will report these at regular
630 // intervals as configured on the agent. If one were sufficiently
631 // industrious, this could be used to replace the typical
632 // SNMP polling used for such things.
633 type SFlowCounterSample struct {
634 EnterpriseID SFlowEnterpriseID
635 Format SFlowSampleType
637 SequenceNumber uint32
638 SourceIDClass SFlowSourceFormat
639 SourceIDIndex SFlowSourceValue
641 Records []SFlowRecord
644 // Counter samples have the following structure:
647 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
648 // | int sample sequence number |
649 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
650 // |id type | src id index value |
651 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
652 // | int number of records |
653 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
654 // / counter records /
656 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
658 type SFlowCounterDataFormat uint32
660 func (cdf SFlowCounterDataFormat) decode() (SFlowEnterpriseID, SFlowCounterRecordType) {
661 leftField := cdf >> 12
662 rightField := uint32(0xFFF) & uint32(cdf)
663 return SFlowEnterpriseID(leftField), SFlowCounterRecordType(rightField)
666 // GetRecords will return a slice of interface types
667 // representing records. A type switch can be used to
668 // get at the underlying SFlowCounterRecordType.
669 func (cs SFlowCounterSample) GetRecords() []SFlowRecord {
673 // GetType will report the type of sample. Only the
674 // compact form of counter samples is supported
675 func (cs SFlowCounterSample) GetType() SFlowSampleType {
676 return SFlowTypeCounterSample
679 type SFlowCounterRecordType uint32
682 SFlowTypeGenericInterfaceCounters SFlowCounterRecordType = 1
683 SFlowTypeEthernetInterfaceCounters SFlowCounterRecordType = 2
684 SFlowTypeTokenRingInterfaceCounters SFlowCounterRecordType = 3
685 SFlowType100BaseVGInterfaceCounters SFlowCounterRecordType = 4
686 SFlowTypeVLANCounters SFlowCounterRecordType = 5
687 SFlowTypeProcessorCounters SFlowCounterRecordType = 1001
690 func (cr SFlowCounterRecordType) String() string {
692 case SFlowTypeGenericInterfaceCounters:
693 return "Generic Interface Counters"
694 case SFlowTypeEthernetInterfaceCounters:
695 return "Ethernet Interface Counters"
696 case SFlowTypeTokenRingInterfaceCounters:
697 return "Token Ring Interface Counters"
698 case SFlowType100BaseVGInterfaceCounters:
699 return "100BaseVG Interface Counters"
700 case SFlowTypeVLANCounters:
701 return "VLAN Counters"
702 case SFlowTypeProcessorCounters:
703 return "Processor Counters"
710 func decodeCounterSample(data *[]byte, expanded bool) (SFlowCounterSample, error) {
711 s := SFlowCounterSample{}
712 var sdc SFlowDataSource
713 var sdce SFlowDataSourceExpanded
714 var sdf SFlowDataFormat
716 *data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
717 s.EnterpriseID, s.Format = sdf.decode()
718 *data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
719 *data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
721 *data, sdce = (*data)[8:], SFlowDataSourceExpanded{SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4])), SFlowSourceValue(binary.BigEndian.Uint32((*data)[4:8]))}
722 s.SourceIDClass, s.SourceIDIndex = sdce.decode()
724 *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
725 s.SourceIDClass, s.SourceIDIndex = sdc.decode()
727 *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
729 for i := uint32(0); i < s.RecordCount; i++ {
730 cdf := SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
731 _, counterRecordType := cdf.decode()
732 switch counterRecordType {
733 case SFlowTypeGenericInterfaceCounters:
734 if record, err := decodeGenericInterfaceCounters(data); err == nil {
735 s.Records = append(s.Records, record)
739 case SFlowTypeEthernetInterfaceCounters:
740 if record, err := decodeEthernetCounters(data); err == nil {
741 s.Records = append(s.Records, record)
745 case SFlowTypeTokenRingInterfaceCounters:
747 return s, errors.New("skipping TypeTokenRingInterfaceCounters")
748 case SFlowType100BaseVGInterfaceCounters:
750 return s, errors.New("skipping Type100BaseVGInterfaceCounters")
751 case SFlowTypeVLANCounters:
753 return s, errors.New("skipping TypeVLANCounters")
754 case SFlowTypeProcessorCounters:
755 if record, err := decodeProcessorCounters(data); err == nil {
756 s.Records = append(s.Records, record)
761 return s, fmt.Errorf("Invalid counter record type: %d", counterRecordType)
767 // SFlowBaseFlowRecord holds the fields common to all records
768 // of type SFlowFlowRecordType
769 type SFlowBaseFlowRecord struct {
770 EnterpriseID SFlowEnterpriseID
771 Format SFlowFlowRecordType
772 FlowDataLength uint32
775 func (bfr SFlowBaseFlowRecord) GetType() SFlowFlowRecordType {
779 // SFlowFlowRecordType denotes what kind of Flow Record is
780 // represented. See RFC 3176
781 type SFlowFlowRecordType uint32
784 SFlowTypeRawPacketFlow SFlowFlowRecordType = 1
785 SFlowTypeEthernetFrameFlow SFlowFlowRecordType = 2
786 SFlowTypeIpv4Flow SFlowFlowRecordType = 3
787 SFlowTypeIpv6Flow SFlowFlowRecordType = 4
788 SFlowTypeExtendedSwitchFlow SFlowFlowRecordType = 1001
789 SFlowTypeExtendedRouterFlow SFlowFlowRecordType = 1002
790 SFlowTypeExtendedGatewayFlow SFlowFlowRecordType = 1003
791 SFlowTypeExtendedUserFlow SFlowFlowRecordType = 1004
792 SFlowTypeExtendedUrlFlow SFlowFlowRecordType = 1005
793 SFlowTypeExtendedMlpsFlow SFlowFlowRecordType = 1006
794 SFlowTypeExtendedNatFlow SFlowFlowRecordType = 1007
795 SFlowTypeExtendedMlpsTunnelFlow SFlowFlowRecordType = 1008
796 SFlowTypeExtendedMlpsVcFlow SFlowFlowRecordType = 1009
797 SFlowTypeExtendedMlpsFecFlow SFlowFlowRecordType = 1010
798 SFlowTypeExtendedMlpsLvpFecFlow SFlowFlowRecordType = 1011
799 SFlowTypeExtendedVlanFlow SFlowFlowRecordType = 1012
800 SFlowTypeExtendedIpv4TunnelEgressFlow SFlowFlowRecordType = 1023
801 SFlowTypeExtendedIpv4TunnelIngressFlow SFlowFlowRecordType = 1024
802 SFlowTypeExtendedIpv6TunnelEgressFlow SFlowFlowRecordType = 1025
803 SFlowTypeExtendedIpv6TunnelIngressFlow SFlowFlowRecordType = 1026
804 SFlowTypeExtendedDecapsulateEgressFlow SFlowFlowRecordType = 1027
805 SFlowTypeExtendedDecapsulateIngressFlow SFlowFlowRecordType = 1028
806 SFlowTypeExtendedVniEgressFlow SFlowFlowRecordType = 1029
807 SFlowTypeExtendedVniIngressFlow SFlowFlowRecordType = 1030
810 func (rt SFlowFlowRecordType) String() string {
812 case SFlowTypeRawPacketFlow:
813 return "Raw Packet Flow Record"
814 case SFlowTypeEthernetFrameFlow:
815 return "Ethernet Frame Flow Record"
816 case SFlowTypeIpv4Flow:
817 return "IPv4 Flow Record"
818 case SFlowTypeIpv6Flow:
819 return "IPv6 Flow Record"
820 case SFlowTypeExtendedSwitchFlow:
821 return "Extended Switch Flow Record"
822 case SFlowTypeExtendedRouterFlow:
823 return "Extended Router Flow Record"
824 case SFlowTypeExtendedGatewayFlow:
825 return "Extended Gateway Flow Record"
826 case SFlowTypeExtendedUserFlow:
827 return "Extended User Flow Record"
828 case SFlowTypeExtendedUrlFlow:
829 return "Extended URL Flow Record"
830 case SFlowTypeExtendedMlpsFlow:
831 return "Extended MPLS Flow Record"
832 case SFlowTypeExtendedNatFlow:
833 return "Extended NAT Flow Record"
834 case SFlowTypeExtendedMlpsTunnelFlow:
835 return "Extended MPLS Tunnel Flow Record"
836 case SFlowTypeExtendedMlpsVcFlow:
837 return "Extended MPLS VC Flow Record"
838 case SFlowTypeExtendedMlpsFecFlow:
839 return "Extended MPLS FEC Flow Record"
840 case SFlowTypeExtendedMlpsLvpFecFlow:
841 return "Extended MPLS LVP FEC Flow Record"
842 case SFlowTypeExtendedVlanFlow:
843 return "Extended VLAN Flow Record"
844 case SFlowTypeExtendedIpv4TunnelEgressFlow:
845 return "Extended IPv4 Tunnel Egress Record"
846 case SFlowTypeExtendedIpv4TunnelIngressFlow:
847 return "Extended IPv4 Tunnel Ingress Record"
848 case SFlowTypeExtendedIpv6TunnelEgressFlow:
849 return "Extended IPv6 Tunnel Egress Record"
850 case SFlowTypeExtendedIpv6TunnelIngressFlow:
851 return "Extended IPv6 Tunnel Ingress Record"
852 case SFlowTypeExtendedDecapsulateEgressFlow:
853 return "Extended Decapsulate Egress Record"
854 case SFlowTypeExtendedDecapsulateIngressFlow:
855 return "Extended Decapsulate Ingress Record"
856 case SFlowTypeExtendedVniEgressFlow:
857 return "Extended VNI Ingress Record"
858 case SFlowTypeExtendedVniIngressFlow:
859 return "Extended VNI Ingress Record"
865 // SFlowRawPacketFlowRecords hold information about a sampled
866 // packet grabbed as it transited the agent. This is
867 // perhaps the most useful and interesting record type,
868 // as it holds the headers of the sampled packet and
869 // can be used to build up a complete picture of the
870 // traffic patterns on a network.
872 // The raw packet header is sent back into gopacket for
873 // decoding, and the resulting gopackt.Packet is stored
874 // in the Header member
875 type SFlowRawPacketFlowRecord struct {
877 HeaderProtocol SFlowRawHeaderProtocol
879 PayloadRemoved uint32
881 Header gopacket.Packet
884 // Raw packet record types have the following structure:
887 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
888 // | 20 bit Interprise (0) |12 bit format |
889 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
891 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
892 // | Header Protocol |
893 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
895 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
896 // | Payload Removed |
897 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
899 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
903 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
905 type SFlowRawHeaderProtocol uint32
908 SFlowProtoEthernet SFlowRawHeaderProtocol = 1
909 SFlowProtoISO88024 SFlowRawHeaderProtocol = 2
910 SFlowProtoISO88025 SFlowRawHeaderProtocol = 3
911 SFlowProtoFDDI SFlowRawHeaderProtocol = 4
912 SFlowProtoFrameRelay SFlowRawHeaderProtocol = 5
913 SFlowProtoX25 SFlowRawHeaderProtocol = 6
914 SFlowProtoPPP SFlowRawHeaderProtocol = 7
915 SFlowProtoSMDS SFlowRawHeaderProtocol = 8
916 SFlowProtoAAL5 SFlowRawHeaderProtocol = 9
917 SFlowProtoAAL5_IP SFlowRawHeaderProtocol = 10 /* e.g. Cisco AAL5 mux */
918 SFlowProtoIPv4 SFlowRawHeaderProtocol = 11
919 SFlowProtoIPv6 SFlowRawHeaderProtocol = 12
920 SFlowProtoMPLS SFlowRawHeaderProtocol = 13
921 SFlowProtoPOS SFlowRawHeaderProtocol = 14 /* RFC 1662, 2615 */
924 func (sfhp SFlowRawHeaderProtocol) String() string {
926 case SFlowProtoEthernet:
927 return "ETHERNET-ISO88023"
928 case SFlowProtoISO88024:
929 return "ISO88024-TOKENBUS"
930 case SFlowProtoISO88025:
931 return "ISO88025-TOKENRING"
934 case SFlowProtoFrameRelay:
944 case SFlowProtoAAL5_IP:
958 func decodeRawPacketFlowRecord(data *[]byte) (SFlowRawPacketFlowRecord, error) {
959 rec := SFlowRawPacketFlowRecord{}
961 var fdf SFlowFlowDataFormat
963 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
964 rec.EnterpriseID, rec.Format = fdf.decode()
965 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
966 *data, rec.HeaderProtocol = (*data)[4:], SFlowRawHeaderProtocol(binary.BigEndian.Uint32((*data)[:4]))
967 *data, rec.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
968 *data, rec.PayloadRemoved = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
969 *data, rec.HeaderLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
970 headerLenWithPadding := int(rec.HeaderLength + ((4 - rec.HeaderLength) % 4))
971 *data, header = (*data)[headerLenWithPadding:], (*data)[:headerLenWithPadding]
972 rec.Header = gopacket.NewPacket(header, LayerTypeEthernet, gopacket.Default)
976 // SFlowExtendedSwitchFlowRecord give additional information
977 // about the sampled packet if it's available. It's mainly
978 // useful for getting at the incoming and outgoing VLANs
979 // An agent may or may not provide this information.
980 type SFlowExtendedSwitchFlowRecord struct {
983 IncomingVLANPriority uint32
985 OutgoingVLANPriority uint32
988 // Extended switch records have the following structure:
991 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
992 // | 20 bit Interprise (0) |12 bit format |
993 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
995 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
997 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
998 // | Incoming VLAN Priority |
999 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1000 // | Outgoing VLAN |
1001 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1002 // | Outgoing VLAN Priority |
1003 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1005 func decodeExtendedSwitchFlowRecord(data *[]byte) (SFlowExtendedSwitchFlowRecord, error) {
1006 es := SFlowExtendedSwitchFlowRecord{}
1007 var fdf SFlowFlowDataFormat
1009 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1010 es.EnterpriseID, es.Format = fdf.decode()
1011 *data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1012 *data, es.IncomingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1013 *data, es.IncomingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1014 *data, es.OutgoingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1015 *data, es.OutgoingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1019 // SFlowExtendedRouterFlowRecord gives additional information
1020 // about the layer 3 routing information used to forward
1022 type SFlowExtendedRouterFlowRecord struct {
1025 NextHopSourceMask uint32
1026 NextHopDestinationMask uint32
1029 // Extended router records have the following structure:
1032 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1033 // | 20 bit Interprise (0) |12 bit format |
1034 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1035 // | record length |
1036 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1037 // | IP version of next hop router (1=v4|2=v6) |
1038 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1039 // / Next Hop address (v4=4byte|v6=16byte) /
1041 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1042 // | Next Hop Source Mask |
1043 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1044 // | Next Hop Destination Mask |
1045 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1047 func decodeExtendedRouterFlowRecord(data *[]byte) (SFlowExtendedRouterFlowRecord, error) {
1048 er := SFlowExtendedRouterFlowRecord{}
1049 var fdf SFlowFlowDataFormat
1050 var extendedRouterAddressType SFlowIPType
1052 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1053 er.EnterpriseID, er.Format = fdf.decode()
1054 *data, er.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1055 *data, extendedRouterAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
1056 *data, er.NextHop = (*data)[extendedRouterAddressType.Length():], (*data)[:extendedRouterAddressType.Length()]
1057 *data, er.NextHopSourceMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1058 *data, er.NextHopDestinationMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1062 // SFlowExtendedGatewayFlowRecord describes information treasured by
1063 // nework engineers everywhere: AS path information listing which
1064 // BGP peer sent the packet, and various other BGP related info.
1065 // This information is vital because it gives a picture of how much
1066 // traffic is being sent from / received by various BGP peers.
1068 // Extended gateway records have the following structure:
1071 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1072 // | 20 bit Interprise (0) |12 bit format |
1073 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1074 // | record length |
1075 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1076 // | IP version of next hop router (1=v4|2=v6) |
1077 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1078 // / Next Hop address (v4=4byte|v6=16byte) /
1080 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1082 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1084 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1086 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1087 // | AS Path Count |
1088 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1089 // / AS Path / Sequence /
1091 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1094 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1096 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1098 // AS Path / Sequence:
1101 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1102 // | AS Source Type (Path=1 / Sequence=2) |
1103 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1104 // | Path / Sequence length |
1105 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1106 // / Path / Sequence Members /
1108 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1113 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1114 // | communitiy length |
1115 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1116 // / communitiy Members /
1118 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1120 type SFlowExtendedGatewayFlowRecord struct {
1127 ASPath []SFlowASDestination
1128 Communities []uint32
1132 type SFlowASPathType uint32
1135 SFlowASSet SFlowASPathType = 1
1136 SFlowASSequence SFlowASPathType = 2
1139 func (apt SFlowASPathType) String() string {
1143 case SFlowASSequence:
1144 return "AS Sequence"
1150 type SFlowASDestination struct {
1151 Type SFlowASPathType
1156 func (asd SFlowASDestination) String() string {
1159 return fmt.Sprint("AS Set:", asd.Members)
1160 case SFlowASSequence:
1161 return fmt.Sprint("AS Sequence:", asd.Members)
1167 func (ad *SFlowASDestination) decodePath(data *[]byte) {
1168 *data, ad.Type = (*data)[4:], SFlowASPathType(binary.BigEndian.Uint32((*data)[:4]))
1169 *data, ad.Count = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1170 ad.Members = make([]uint32, ad.Count)
1171 for i := uint32(0); i < ad.Count; i++ {
1173 *data, member = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1174 ad.Members[i] = member
1178 func decodeExtendedGatewayFlowRecord(data *[]byte) (SFlowExtendedGatewayFlowRecord, error) {
1179 eg := SFlowExtendedGatewayFlowRecord{}
1180 var fdf SFlowFlowDataFormat
1181 var extendedGatewayAddressType SFlowIPType
1182 var communitiesLength uint32
1183 var community uint32
1185 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1186 eg.EnterpriseID, eg.Format = fdf.decode()
1187 *data, eg.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1188 *data, extendedGatewayAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
1189 *data, eg.NextHop = (*data)[extendedGatewayAddressType.Length():], (*data)[:extendedGatewayAddressType.Length()]
1190 *data, eg.AS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1191 *data, eg.SourceAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1192 *data, eg.PeerAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1193 *data, eg.ASPathCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1194 for i := uint32(0); i < eg.ASPathCount; i++ {
1195 asPath := SFlowASDestination{}
1196 asPath.decodePath(data)
1197 eg.ASPath = append(eg.ASPath, asPath)
1199 *data, communitiesLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1200 eg.Communities = make([]uint32, communitiesLength)
1201 for j := uint32(0); j < communitiesLength; j++ {
1202 *data, community = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1203 eg.Communities[j] = community
1205 *data, eg.LocalPref = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1209 // **************************************************
1210 // Extended URL Flow Record
1211 // **************************************************
1214 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1215 // | 20 bit Interprise (0) |12 bit format |
1216 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1217 // | record length |
1218 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1220 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1222 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1224 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1226 type SFlowURLDirection uint32
1229 SFlowURLsrc SFlowURLDirection = 1
1230 SFlowURLdst SFlowURLDirection = 2
1233 func (urld SFlowURLDirection) String() string {
1236 return "Source address is the server"
1238 return "Destination address is the server"
1244 type SFlowExtendedURLRecord struct {
1246 Direction SFlowURLDirection
1251 func decodeExtendedURLRecord(data *[]byte) (SFlowExtendedURLRecord, error) {
1252 eur := SFlowExtendedURLRecord{}
1253 var fdf SFlowFlowDataFormat
1255 var urlLenWithPad int
1257 var hostLenWithPad int
1259 var hostBytes []byte
1261 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1262 eur.EnterpriseID, eur.Format = fdf.decode()
1263 *data, eur.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1264 *data, eur.Direction = (*data)[4:], SFlowURLDirection(binary.BigEndian.Uint32((*data)[:4]))
1265 *data, urlLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1266 urlLenWithPad = int(urlLen + ((4 - urlLen) % 4))
1267 *data, urlBytes = (*data)[urlLenWithPad:], (*data)[:urlLenWithPad]
1268 eur.URL = string(urlBytes[:urlLen])
1269 *data, hostLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1270 hostLenWithPad = int(hostLen + ((4 - hostLen) % 4))
1271 *data, hostBytes = (*data)[hostLenWithPad:], (*data)[:hostLenWithPad]
1272 eur.Host = string(hostBytes[:hostLen])
1276 // **************************************************
1277 // Extended User Flow Record
1278 // **************************************************
1281 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1282 // | 20 bit Interprise (0) |12 bit format |
1283 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1284 // | record length |
1285 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1286 // | Source Character Set |
1287 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1288 // | Source User Id |
1289 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1290 // | Destination Character Set |
1291 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1292 // | Destination User ID |
1293 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1295 type SFlowExtendedUserFlow struct {
1297 SourceCharSet SFlowCharSet
1299 DestinationCharSet SFlowCharSet
1300 DestinationUserID string
1303 type SFlowCharSet uint32
1306 SFlowCSunknown SFlowCharSet = 2
1307 SFlowCSASCII SFlowCharSet = 3
1308 SFlowCSISOLatin1 SFlowCharSet = 4
1309 SFlowCSISOLatin2 SFlowCharSet = 5
1310 SFlowCSISOLatin3 SFlowCharSet = 6
1311 SFlowCSISOLatin4 SFlowCharSet = 7
1312 SFlowCSISOLatinCyrillic SFlowCharSet = 8
1313 SFlowCSISOLatinArabic SFlowCharSet = 9
1314 SFlowCSISOLatinGreek SFlowCharSet = 10
1315 SFlowCSISOLatinHebrew SFlowCharSet = 11
1316 SFlowCSISOLatin5 SFlowCharSet = 12
1317 SFlowCSISOLatin6 SFlowCharSet = 13
1318 SFlowCSISOTextComm SFlowCharSet = 14
1319 SFlowCSHalfWidthKatakana SFlowCharSet = 15
1320 SFlowCSJISEncoding SFlowCharSet = 16
1321 SFlowCSShiftJIS SFlowCharSet = 17
1322 SFlowCSEUCPkdFmtJapanese SFlowCharSet = 18
1323 SFlowCSEUCFixWidJapanese SFlowCharSet = 19
1324 SFlowCSISO4UnitedKingdom SFlowCharSet = 20
1325 SFlowCSISO11SwedishForNames SFlowCharSet = 21
1326 SFlowCSISO15Italian SFlowCharSet = 22
1327 SFlowCSISO17Spanish SFlowCharSet = 23
1328 SFlowCSISO21German SFlowCharSet = 24
1329 SFlowCSISO60DanishNorwegian SFlowCharSet = 25
1330 SFlowCSISO69French SFlowCharSet = 26
1331 SFlowCSISO10646UTF1 SFlowCharSet = 27
1332 SFlowCSISO646basic1983 SFlowCharSet = 28
1333 SFlowCSINVARIANT SFlowCharSet = 29
1334 SFlowCSISO2IntlRefVersion SFlowCharSet = 30
1335 SFlowCSNATSSEFI SFlowCharSet = 31
1336 SFlowCSNATSSEFIADD SFlowCharSet = 32
1337 SFlowCSNATSDANO SFlowCharSet = 33
1338 SFlowCSNATSDANOADD SFlowCharSet = 34
1339 SFlowCSISO10Swedish SFlowCharSet = 35
1340 SFlowCSKSC56011987 SFlowCharSet = 36
1341 SFlowCSISO2022KR SFlowCharSet = 37
1342 SFlowCSEUCKR SFlowCharSet = 38
1343 SFlowCSISO2022JP SFlowCharSet = 39
1344 SFlowCSISO2022JP2 SFlowCharSet = 40
1345 SFlowCSISO13JISC6220jp SFlowCharSet = 41
1346 SFlowCSISO14JISC6220ro SFlowCharSet = 42
1347 SFlowCSISO16Portuguese SFlowCharSet = 43
1348 SFlowCSISO18Greek7Old SFlowCharSet = 44
1349 SFlowCSISO19LatinGreek SFlowCharSet = 45
1350 SFlowCSISO25French SFlowCharSet = 46
1351 SFlowCSISO27LatinGreek1 SFlowCharSet = 47
1352 SFlowCSISO5427Cyrillic SFlowCharSet = 48
1353 SFlowCSISO42JISC62261978 SFlowCharSet = 49
1354 SFlowCSISO47BSViewdata SFlowCharSet = 50
1355 SFlowCSISO49INIS SFlowCharSet = 51
1356 SFlowCSISO50INIS8 SFlowCharSet = 52
1357 SFlowCSISO51INISCyrillic SFlowCharSet = 53
1358 SFlowCSISO54271981 SFlowCharSet = 54
1359 SFlowCSISO5428Greek SFlowCharSet = 55
1360 SFlowCSISO57GB1988 SFlowCharSet = 56
1361 SFlowCSISO58GB231280 SFlowCharSet = 57
1362 SFlowCSISO61Norwegian2 SFlowCharSet = 58
1363 SFlowCSISO70VideotexSupp1 SFlowCharSet = 59
1364 SFlowCSISO84Portuguese2 SFlowCharSet = 60
1365 SFlowCSISO85Spanish2 SFlowCharSet = 61
1366 SFlowCSISO86Hungarian SFlowCharSet = 62
1367 SFlowCSISO87JISX0208 SFlowCharSet = 63
1368 SFlowCSISO88Greek7 SFlowCharSet = 64
1369 SFlowCSISO89ASMO449 SFlowCharSet = 65
1370 SFlowCSISO90 SFlowCharSet = 66
1371 SFlowCSISO91JISC62291984a SFlowCharSet = 67
1372 SFlowCSISO92JISC62991984b SFlowCharSet = 68
1373 SFlowCSISO93JIS62291984badd SFlowCharSet = 69
1374 SFlowCSISO94JIS62291984hand SFlowCharSet = 70
1375 SFlowCSISO95JIS62291984handadd SFlowCharSet = 71
1376 SFlowCSISO96JISC62291984kana SFlowCharSet = 72
1377 SFlowCSISO2033 SFlowCharSet = 73
1378 SFlowCSISO99NAPLPS SFlowCharSet = 74
1379 SFlowCSISO102T617bit SFlowCharSet = 75
1380 SFlowCSISO103T618bit SFlowCharSet = 76
1381 SFlowCSISO111ECMACyrillic SFlowCharSet = 77
1382 SFlowCSa71 SFlowCharSet = 78
1383 SFlowCSa72 SFlowCharSet = 79
1384 SFlowCSISO123CSAZ24341985gr SFlowCharSet = 80
1385 SFlowCSISO88596E SFlowCharSet = 81
1386 SFlowCSISO88596I SFlowCharSet = 82
1387 SFlowCSISO128T101G2 SFlowCharSet = 83
1388 SFlowCSISO88598E SFlowCharSet = 84
1389 SFlowCSISO88598I SFlowCharSet = 85
1390 SFlowCSISO139CSN369103 SFlowCharSet = 86
1391 SFlowCSISO141JUSIB1002 SFlowCharSet = 87
1392 SFlowCSISO143IECP271 SFlowCharSet = 88
1393 SFlowCSISO146Serbian SFlowCharSet = 89
1394 SFlowCSISO147Macedonian SFlowCharSet = 90
1395 SFlowCSISO150 SFlowCharSet = 91
1396 SFlowCSISO151Cuba SFlowCharSet = 92
1397 SFlowCSISO6937Add SFlowCharSet = 93
1398 SFlowCSISO153GOST1976874 SFlowCharSet = 94
1399 SFlowCSISO8859Supp SFlowCharSet = 95
1400 SFlowCSISO10367Box SFlowCharSet = 96
1401 SFlowCSISO158Lap SFlowCharSet = 97
1402 SFlowCSISO159JISX02121990 SFlowCharSet = 98
1403 SFlowCSISO646Danish SFlowCharSet = 99
1404 SFlowCSUSDK SFlowCharSet = 100
1405 SFlowCSDKUS SFlowCharSet = 101
1406 SFlowCSKSC5636 SFlowCharSet = 102
1407 SFlowCSUnicode11UTF7 SFlowCharSet = 103
1408 SFlowCSISO2022CN SFlowCharSet = 104
1409 SFlowCSISO2022CNEXT SFlowCharSet = 105
1410 SFlowCSUTF8 SFlowCharSet = 106
1411 SFlowCSISO885913 SFlowCharSet = 109
1412 SFlowCSISO885914 SFlowCharSet = 110
1413 SFlowCSISO885915 SFlowCharSet = 111
1414 SFlowCSISO885916 SFlowCharSet = 112
1415 SFlowCSGBK SFlowCharSet = 113
1416 SFlowCSGB18030 SFlowCharSet = 114
1417 SFlowCSOSDEBCDICDF0415 SFlowCharSet = 115
1418 SFlowCSOSDEBCDICDF03IRV SFlowCharSet = 116
1419 SFlowCSOSDEBCDICDF041 SFlowCharSet = 117
1420 SFlowCSISO115481 SFlowCharSet = 118
1421 SFlowCSKZ1048 SFlowCharSet = 119
1422 SFlowCSUnicode SFlowCharSet = 1000
1423 SFlowCSUCS4 SFlowCharSet = 1001
1424 SFlowCSUnicodeASCII SFlowCharSet = 1002
1425 SFlowCSUnicodeLatin1 SFlowCharSet = 1003
1426 SFlowCSUnicodeJapanese SFlowCharSet = 1004
1427 SFlowCSUnicodeIBM1261 SFlowCharSet = 1005
1428 SFlowCSUnicodeIBM1268 SFlowCharSet = 1006
1429 SFlowCSUnicodeIBM1276 SFlowCharSet = 1007
1430 SFlowCSUnicodeIBM1264 SFlowCharSet = 1008
1431 SFlowCSUnicodeIBM1265 SFlowCharSet = 1009
1432 SFlowCSUnicode11 SFlowCharSet = 1010
1433 SFlowCSSCSU SFlowCharSet = 1011
1434 SFlowCSUTF7 SFlowCharSet = 1012
1435 SFlowCSUTF16BE SFlowCharSet = 1013
1436 SFlowCSUTF16LE SFlowCharSet = 1014
1437 SFlowCSUTF16 SFlowCharSet = 1015
1438 SFlowCSCESU8 SFlowCharSet = 1016
1439 SFlowCSUTF32 SFlowCharSet = 1017
1440 SFlowCSUTF32BE SFlowCharSet = 1018
1441 SFlowCSUTF32LE SFlowCharSet = 1019
1442 SFlowCSBOCU1 SFlowCharSet = 1020
1443 SFlowCSWindows30Latin1 SFlowCharSet = 2000
1444 SFlowCSWindows31Latin1 SFlowCharSet = 2001
1445 SFlowCSWindows31Latin2 SFlowCharSet = 2002
1446 SFlowCSWindows31Latin5 SFlowCharSet = 2003
1447 SFlowCSHPRoman8 SFlowCharSet = 2004
1448 SFlowCSAdobeStandardEncoding SFlowCharSet = 2005
1449 SFlowCSVenturaUS SFlowCharSet = 2006
1450 SFlowCSVenturaInternational SFlowCharSet = 2007
1451 SFlowCSDECMCS SFlowCharSet = 2008
1452 SFlowCSPC850Multilingual SFlowCharSet = 2009
1453 SFlowCSPCp852 SFlowCharSet = 2010
1454 SFlowCSPC8CodePage437 SFlowCharSet = 2011
1455 SFlowCSPC8DanishNorwegian SFlowCharSet = 2012
1456 SFlowCSPC862LatinHebrew SFlowCharSet = 2013
1457 SFlowCSPC8Turkish SFlowCharSet = 2014
1458 SFlowCSIBMSymbols SFlowCharSet = 2015
1459 SFlowCSIBMThai SFlowCharSet = 2016
1460 SFlowCSHPLegal SFlowCharSet = 2017
1461 SFlowCSHPPiFont SFlowCharSet = 2018
1462 SFlowCSHPMath8 SFlowCharSet = 2019
1463 SFlowCSHPPSMath SFlowCharSet = 2020
1464 SFlowCSHPDesktop SFlowCharSet = 2021
1465 SFlowCSVenturaMath SFlowCharSet = 2022
1466 SFlowCSMicrosoftPublishing SFlowCharSet = 2023
1467 SFlowCSWindows31J SFlowCharSet = 2024
1468 SFlowCSGB2312 SFlowCharSet = 2025
1469 SFlowCSBig5 SFlowCharSet = 2026
1470 SFlowCSMacintosh SFlowCharSet = 2027
1471 SFlowCSIBM037 SFlowCharSet = 2028
1472 SFlowCSIBM038 SFlowCharSet = 2029
1473 SFlowCSIBM273 SFlowCharSet = 2030
1474 SFlowCSIBM274 SFlowCharSet = 2031
1475 SFlowCSIBM275 SFlowCharSet = 2032
1476 SFlowCSIBM277 SFlowCharSet = 2033
1477 SFlowCSIBM278 SFlowCharSet = 2034
1478 SFlowCSIBM280 SFlowCharSet = 2035
1479 SFlowCSIBM281 SFlowCharSet = 2036
1480 SFlowCSIBM284 SFlowCharSet = 2037
1481 SFlowCSIBM285 SFlowCharSet = 2038
1482 SFlowCSIBM290 SFlowCharSet = 2039
1483 SFlowCSIBM297 SFlowCharSet = 2040
1484 SFlowCSIBM420 SFlowCharSet = 2041
1485 SFlowCSIBM423 SFlowCharSet = 2042
1486 SFlowCSIBM424 SFlowCharSet = 2043
1487 SFlowCSIBM500 SFlowCharSet = 2044
1488 SFlowCSIBM851 SFlowCharSet = 2045
1489 SFlowCSIBM855 SFlowCharSet = 2046
1490 SFlowCSIBM857 SFlowCharSet = 2047
1491 SFlowCSIBM860 SFlowCharSet = 2048
1492 SFlowCSIBM861 SFlowCharSet = 2049
1493 SFlowCSIBM863 SFlowCharSet = 2050
1494 SFlowCSIBM864 SFlowCharSet = 2051
1495 SFlowCSIBM865 SFlowCharSet = 2052
1496 SFlowCSIBM868 SFlowCharSet = 2053
1497 SFlowCSIBM869 SFlowCharSet = 2054
1498 SFlowCSIBM870 SFlowCharSet = 2055
1499 SFlowCSIBM871 SFlowCharSet = 2056
1500 SFlowCSIBM880 SFlowCharSet = 2057
1501 SFlowCSIBM891 SFlowCharSet = 2058
1502 SFlowCSIBM903 SFlowCharSet = 2059
1503 SFlowCSIBBM904 SFlowCharSet = 2060
1504 SFlowCSIBM905 SFlowCharSet = 2061
1505 SFlowCSIBM918 SFlowCharSet = 2062
1506 SFlowCSIBM1026 SFlowCharSet = 2063
1507 SFlowCSIBMEBCDICATDE SFlowCharSet = 2064
1508 SFlowCSEBCDICATDEA SFlowCharSet = 2065
1509 SFlowCSEBCDICCAFR SFlowCharSet = 2066
1510 SFlowCSEBCDICDKNO SFlowCharSet = 2067
1511 SFlowCSEBCDICDKNOA SFlowCharSet = 2068
1512 SFlowCSEBCDICFISE SFlowCharSet = 2069
1513 SFlowCSEBCDICFISEA SFlowCharSet = 2070
1514 SFlowCSEBCDICFR SFlowCharSet = 2071
1515 SFlowCSEBCDICIT SFlowCharSet = 2072
1516 SFlowCSEBCDICPT SFlowCharSet = 2073
1517 SFlowCSEBCDICES SFlowCharSet = 2074
1518 SFlowCSEBCDICESA SFlowCharSet = 2075
1519 SFlowCSEBCDICESS SFlowCharSet = 2076
1520 SFlowCSEBCDICUK SFlowCharSet = 2077
1521 SFlowCSEBCDICUS SFlowCharSet = 2078
1522 SFlowCSUnknown8BiT SFlowCharSet = 2079
1523 SFlowCSMnemonic SFlowCharSet = 2080
1524 SFlowCSMnem SFlowCharSet = 2081
1525 SFlowCSVISCII SFlowCharSet = 2082
1526 SFlowCSVIQR SFlowCharSet = 2083
1527 SFlowCSKOI8R SFlowCharSet = 2084
1528 SFlowCSHZGB2312 SFlowCharSet = 2085
1529 SFlowCSIBM866 SFlowCharSet = 2086
1530 SFlowCSPC775Baltic SFlowCharSet = 2087
1531 SFlowCSKOI8U SFlowCharSet = 2088
1532 SFlowCSIBM00858 SFlowCharSet = 2089
1533 SFlowCSIBM00924 SFlowCharSet = 2090
1534 SFlowCSIBM01140 SFlowCharSet = 2091
1535 SFlowCSIBM01141 SFlowCharSet = 2092
1536 SFlowCSIBM01142 SFlowCharSet = 2093
1537 SFlowCSIBM01143 SFlowCharSet = 2094
1538 SFlowCSIBM01144 SFlowCharSet = 2095
1539 SFlowCSIBM01145 SFlowCharSet = 2096
1540 SFlowCSIBM01146 SFlowCharSet = 2097
1541 SFlowCSIBM01147 SFlowCharSet = 2098
1542 SFlowCSIBM01148 SFlowCharSet = 2099
1543 SFlowCSIBM01149 SFlowCharSet = 2100
1544 SFlowCSBig5HKSCS SFlowCharSet = 2101
1545 SFlowCSIBM1047 SFlowCharSet = 2102
1546 SFlowCSPTCP154 SFlowCharSet = 2103
1547 SFlowCSAmiga1251 SFlowCharSet = 2104
1548 SFlowCSKOI7switched SFlowCharSet = 2105
1549 SFlowCSBRF SFlowCharSet = 2106
1550 SFlowCSTSCII SFlowCharSet = 2107
1551 SFlowCSCP51932 SFlowCharSet = 2108
1552 SFlowCSWindows874 SFlowCharSet = 2109
1553 SFlowCSWindows1250 SFlowCharSet = 2250
1554 SFlowCSWindows1251 SFlowCharSet = 2251
1555 SFlowCSWindows1252 SFlowCharSet = 2252
1556 SFlowCSWindows1253 SFlowCharSet = 2253
1557 SFlowCSWindows1254 SFlowCharSet = 2254
1558 SFlowCSWindows1255 SFlowCharSet = 2255
1559 SFlowCSWindows1256 SFlowCharSet = 2256
1560 SFlowCSWindows1257 SFlowCharSet = 2257
1561 SFlowCSWindows1258 SFlowCharSet = 2258
1562 SFlowCSTIS620 SFlowCharSet = 2259
1563 SFlowCS50220 SFlowCharSet = 2260
1564 SFlowCSreserved SFlowCharSet = 3000
1567 func decodeExtendedUserFlow(data *[]byte) (SFlowExtendedUserFlow, error) {
1568 eu := SFlowExtendedUserFlow{}
1569 var fdf SFlowFlowDataFormat
1570 var srcUserLen uint32
1571 var srcUserLenWithPad int
1572 var srcUserBytes []byte
1573 var dstUserLen uint32
1574 var dstUserLenWithPad int
1575 var dstUserBytes []byte
1577 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1578 eu.EnterpriseID, eu.Format = fdf.decode()
1579 *data, eu.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1580 *data, eu.SourceCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
1581 *data, srcUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1582 srcUserLenWithPad = int(srcUserLen + ((4 - srcUserLen) % 4))
1583 *data, srcUserBytes = (*data)[srcUserLenWithPad:], (*data)[:srcUserLenWithPad]
1584 eu.SourceUserID = string(srcUserBytes[:srcUserLen])
1585 *data, eu.DestinationCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
1586 *data, dstUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1587 dstUserLenWithPad = int(dstUserLen + ((4 - dstUserLen) % 4))
1588 *data, dstUserBytes = (*data)[dstUserLenWithPad:], (*data)[:dstUserLenWithPad]
1589 eu.DestinationUserID = string(dstUserBytes[:dstUserLen])
1593 // **************************************************
1594 // Packet IP version 4 Record
1595 // **************************************************
1598 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1600 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1602 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1604 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1605 // | Destination IPv4 |
1606 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1608 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1609 // | Destionation Port |
1610 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1612 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1614 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1615 type SFlowIpv4Record struct {
1616 // The length of the IP packet excluding ower layer encapsulations
1618 // IP Protocol type (for example, TCP = 6, UDP = 17)
1620 // Source IP Address
1622 // Destination IP Address
1624 // TCP/UDP source port number or equivalent
1626 // TCP/UDP destination port number or equivalent
1630 // IP type of service
1634 func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
1635 si := SFlowIpv4Record{}
1637 *data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1638 *data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1639 *data, si.IPSrc = (*data)[4:], net.IP((*data)[:4])
1640 *data, si.IPDst = (*data)[4:], net.IP((*data)[:4])
1641 *data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1642 *data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1643 *data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1644 *data, si.TOS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1649 // **************************************************
1650 // Packet IP version 6 Record
1651 // **************************************************
1654 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1656 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1658 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1660 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1661 // | Destination IPv4 |
1662 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1664 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1665 // | Destionation Port |
1666 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1668 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1670 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1671 type SFlowIpv6Record struct {
1672 // The length of the IP packet excluding ower layer encapsulations
1674 // IP Protocol type (for example, TCP = 6, UDP = 17)
1676 // Source IP Address
1678 // Destination IP Address
1680 // TCP/UDP source port number or equivalent
1682 // TCP/UDP destination port number or equivalent
1690 func decodeSFlowIpv6Record(data *[]byte) (SFlowIpv6Record, error) {
1691 si := SFlowIpv6Record{}
1693 *data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1694 *data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1695 *data, si.IPSrc = (*data)[16:], net.IP((*data)[:16])
1696 *data, si.IPDst = (*data)[16:], net.IP((*data)[:16])
1697 *data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1698 *data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1699 *data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1700 *data, si.Priority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1705 // **************************************************
1706 // Extended IPv4 Tunnel Egress
1707 // **************************************************
1710 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1711 // | 20 bit Interprise (0) |12 bit format |
1712 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1713 // | record length |
1714 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1715 // / Packet IP version 4 Record /
1717 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1718 type SFlowExtendedIpv4TunnelEgressRecord struct {
1720 SFlowIpv4Record SFlowIpv4Record
1723 func decodeExtendedIpv4TunnelEgress(data *[]byte) (SFlowExtendedIpv4TunnelEgressRecord, error) {
1724 rec := SFlowExtendedIpv4TunnelEgressRecord{}
1725 var fdf SFlowFlowDataFormat
1727 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1728 rec.EnterpriseID, rec.Format = fdf.decode()
1729 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1730 rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
1735 // **************************************************
1736 // Extended IPv4 Tunnel Ingress
1737 // **************************************************
1740 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1741 // | 20 bit Interprise (0) |12 bit format |
1742 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1743 // | record length |
1744 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1745 // / Packet IP version 4 Record /
1747 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1748 type SFlowExtendedIpv4TunnelIngressRecord struct {
1750 SFlowIpv4Record SFlowIpv4Record
1753 func decodeExtendedIpv4TunnelIngress(data *[]byte) (SFlowExtendedIpv4TunnelIngressRecord, error) {
1754 rec := SFlowExtendedIpv4TunnelIngressRecord{}
1755 var fdf SFlowFlowDataFormat
1757 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1758 rec.EnterpriseID, rec.Format = fdf.decode()
1759 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1760 rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
1765 // **************************************************
1766 // Extended IPv6 Tunnel Egress
1767 // **************************************************
1770 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1771 // | 20 bit Interprise (0) |12 bit format |
1772 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1773 // | record length |
1774 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1775 // / Packet IP version 6 Record /
1777 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1778 type SFlowExtendedIpv6TunnelEgressRecord struct {
1783 func decodeExtendedIpv6TunnelEgress(data *[]byte) (SFlowExtendedIpv6TunnelEgressRecord, error) {
1784 rec := SFlowExtendedIpv6TunnelEgressRecord{}
1785 var fdf SFlowFlowDataFormat
1787 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1788 rec.EnterpriseID, rec.Format = fdf.decode()
1789 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1790 rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
1795 // **************************************************
1796 // Extended IPv6 Tunnel Ingress
1797 // **************************************************
1800 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1801 // | 20 bit Interprise (0) |12 bit format |
1802 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1803 // | record length |
1804 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1805 // / Packet IP version 6 Record /
1807 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1808 type SFlowExtendedIpv6TunnelIngressRecord struct {
1813 func decodeExtendedIpv6TunnelIngress(data *[]byte) (SFlowExtendedIpv6TunnelIngressRecord, error) {
1814 rec := SFlowExtendedIpv6TunnelIngressRecord{}
1815 var fdf SFlowFlowDataFormat
1817 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1818 rec.EnterpriseID, rec.Format = fdf.decode()
1819 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1820 rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
1825 // **************************************************
1826 // Extended Decapsulate Egress
1827 // **************************************************
1830 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1831 // | 20 bit Interprise (0) |12 bit format |
1832 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1833 // | record length |
1834 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1835 // | Inner Header Offset |
1836 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1837 type SFlowExtendedDecapsulateEgressRecord struct {
1839 InnerHeaderOffset uint32
1842 func decodeExtendedDecapsulateEgress(data *[]byte) (SFlowExtendedDecapsulateEgressRecord, error) {
1843 rec := SFlowExtendedDecapsulateEgressRecord{}
1844 var fdf SFlowFlowDataFormat
1846 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1847 rec.EnterpriseID, rec.Format = fdf.decode()
1848 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1849 *data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1854 // **************************************************
1855 // Extended Decapsulate Ingress
1856 // **************************************************
1859 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1860 // | 20 bit Interprise (0) |12 bit format |
1861 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1862 // | record length |
1863 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1864 // | Inner Header Offset |
1865 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1866 type SFlowExtendedDecapsulateIngressRecord struct {
1868 InnerHeaderOffset uint32
1871 func decodeExtendedDecapsulateIngress(data *[]byte) (SFlowExtendedDecapsulateIngressRecord, error) {
1872 rec := SFlowExtendedDecapsulateIngressRecord{}
1873 var fdf SFlowFlowDataFormat
1875 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1876 rec.EnterpriseID, rec.Format = fdf.decode()
1877 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1878 *data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1883 // **************************************************
1884 // Extended VNI Egress
1885 // **************************************************
1888 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1889 // | 20 bit Interprise (0) |12 bit format |
1890 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1891 // | record length |
1892 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1894 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1895 type SFlowExtendedVniEgressRecord struct {
1900 func decodeExtendedVniEgress(data *[]byte) (SFlowExtendedVniEgressRecord, error) {
1901 rec := SFlowExtendedVniEgressRecord{}
1902 var fdf SFlowFlowDataFormat
1904 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1905 rec.EnterpriseID, rec.Format = fdf.decode()
1906 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1907 *data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1912 // **************************************************
1913 // Extended VNI Ingress
1914 // **************************************************
1917 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1918 // | 20 bit Interprise (0) |12 bit format |
1919 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1920 // | record length |
1921 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1923 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1924 type SFlowExtendedVniIngressRecord struct {
1929 func decodeExtendedVniIngress(data *[]byte) (SFlowExtendedVniIngressRecord, error) {
1930 rec := SFlowExtendedVniIngressRecord{}
1931 var fdf SFlowFlowDataFormat
1933 *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
1934 rec.EnterpriseID, rec.Format = fdf.decode()
1935 *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1936 *data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1941 // **************************************************
1943 // **************************************************
1946 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1947 // | 20 bit Interprise (0) |12 bit format |
1948 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1949 // | counter length |
1950 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1953 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1955 type SFlowBaseCounterRecord struct {
1956 EnterpriseID SFlowEnterpriseID
1957 Format SFlowCounterRecordType
1958 FlowDataLength uint32
1961 func (bcr SFlowBaseCounterRecord) GetType() SFlowCounterRecordType {
1963 case SFlowTypeGenericInterfaceCounters:
1964 return SFlowTypeGenericInterfaceCounters
1965 case SFlowTypeEthernetInterfaceCounters:
1966 return SFlowTypeEthernetInterfaceCounters
1967 case SFlowTypeTokenRingInterfaceCounters:
1968 return SFlowTypeTokenRingInterfaceCounters
1969 case SFlowType100BaseVGInterfaceCounters:
1970 return SFlowType100BaseVGInterfaceCounters
1971 case SFlowTypeVLANCounters:
1972 return SFlowTypeVLANCounters
1973 case SFlowTypeProcessorCounters:
1974 return SFlowTypeProcessorCounters
1977 unrecognized := fmt.Sprint("Unrecognized counter record type:", bcr.Format)
1981 // **************************************************
1983 // **************************************************
1986 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1987 // | 20 bit Interprise (0) |12 bit format |
1988 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1989 // | counter length |
1990 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1992 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1994 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1996 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1998 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2000 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2003 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2004 // | IfInUcastPkts |
2005 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2006 // | IfInMulticastPkts |
2007 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2008 // | IfInBroadcastPkts |
2009 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2011 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2013 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2014 // | IfInUnknownProtos |
2015 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2018 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2019 // | IfOutUcastPkts |
2020 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2021 // | IfOutMulticastPkts |
2022 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2023 // | IfOutBroadcastPkts |
2024 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2025 // | IfOutDiscards |
2026 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2028 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2029 // | IfPromiscouousMode |
2030 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2032 type SFlowGenericInterfaceCounters struct {
2033 SFlowBaseCounterRecord
2040 IfInUcastPkts uint32
2041 IfInMulticastPkts uint32
2042 IfInBroadcastPkts uint32
2045 IfInUnknownProtos uint32
2047 IfOutUcastPkts uint32
2048 IfOutMulticastPkts uint32
2049 IfOutBroadcastPkts uint32
2050 IfOutDiscards uint32
2052 IfPromiscuousMode uint32
2055 func decodeGenericInterfaceCounters(data *[]byte) (SFlowGenericInterfaceCounters, error) {
2056 gic := SFlowGenericInterfaceCounters{}
2057 var cdf SFlowCounterDataFormat
2059 *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
2060 gic.EnterpriseID, gic.Format = cdf.decode()
2061 *data, gic.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2062 *data, gic.IfIndex = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2063 *data, gic.IfType = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2064 *data, gic.IfSpeed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
2065 *data, gic.IfDirection = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2066 *data, gic.IfStatus = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2067 *data, gic.IfInOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
2068 *data, gic.IfInUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2069 *data, gic.IfInMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2070 *data, gic.IfInBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2071 *data, gic.IfInDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2072 *data, gic.IfInErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2073 *data, gic.IfInUnknownProtos = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2074 *data, gic.IfOutOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
2075 *data, gic.IfOutUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2076 *data, gic.IfOutMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2077 *data, gic.IfOutBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2078 *data, gic.IfOutDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2079 *data, gic.IfOutErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2080 *data, gic.IfPromiscuousMode = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2084 // **************************************************
2086 // **************************************************
2089 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2090 // | 20 bit Interprise (0) |12 bit format |
2091 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2092 // | counter length |
2093 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2096 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2098 type SFlowEthernetCounters struct {
2099 SFlowBaseCounterRecord
2100 AlignmentErrors uint32
2102 SingleCollisionFrames uint32
2103 MultipleCollisionFrames uint32
2104 SQETestErrors uint32
2105 DeferredTransmissions uint32
2106 LateCollisions uint32
2107 ExcessiveCollisions uint32
2108 InternalMacTransmitErrors uint32
2109 CarrierSenseErrors uint32
2110 FrameTooLongs uint32
2111 InternalMacReceiveErrors uint32
2115 func decodeEthernetCounters(data *[]byte) (SFlowEthernetCounters, error) {
2116 ec := SFlowEthernetCounters{}
2117 var cdf SFlowCounterDataFormat
2119 *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
2120 ec.EnterpriseID, ec.Format = cdf.decode()
2121 *data, ec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2122 *data, ec.AlignmentErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2123 *data, ec.FCSErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2124 *data, ec.SingleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2125 *data, ec.MultipleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2126 *data, ec.SQETestErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2127 *data, ec.DeferredTransmissions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2128 *data, ec.LateCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2129 *data, ec.ExcessiveCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2130 *data, ec.InternalMacTransmitErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2131 *data, ec.CarrierSenseErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2132 *data, ec.FrameTooLongs = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2133 *data, ec.InternalMacReceiveErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2134 *data, ec.SymbolErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2138 // **************************************************
2139 // Processor Counter Record
2140 // **************************************************
2142 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2143 // | 20 bit Interprise (0) |12 bit format |
2144 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2145 // | counter length |
2146 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2148 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2150 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2152 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2154 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2156 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2158 type SFlowProcessorCounters struct {
2159 SFlowBaseCounterRecord
2160 FiveSecCpu uint32 // 5 second average CPU utilization
2161 OneMinCpu uint32 // 1 minute average CPU utilization
2162 FiveMinCpu uint32 // 5 minute average CPU utilization
2163 TotalMemory uint64 // total memory (in bytes)
2164 FreeMemory uint64 // free memory (in bytes)
2167 func decodeProcessorCounters(data *[]byte) (SFlowProcessorCounters, error) {
2168 pc := SFlowProcessorCounters{}
2169 var cdf SFlowCounterDataFormat
2170 var high32, low32 uint32
2172 *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
2173 pc.EnterpriseID, pc.Format = cdf.decode()
2174 *data, pc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2176 *data, pc.FiveSecCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2177 *data, pc.OneMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2178 *data, pc.FiveMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2179 *data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2180 *data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2181 pc.TotalMemory = (uint64(high32) << 32) + uint64(low32)
2182 *data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2183 *data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
2184 pc.FreeMemory = (uint64(high32)) + uint64(low32)