Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / sflow.go
1 // Copyright 2014 Google, Inc. All rights reserved.
2 //
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
5 // tree.
6
7 /*
8 This layer decodes SFlow version 5 datagrams.
9
10 The specification can be found here: http://sflow.org/sflow_version_5.txt
11
12 Additional developer information about sflow can be found at:
13 http://sflow.org/developers/specifications.php
14
15 And SFlow in general:
16 http://sflow.org/index.php
17
18 Two forms of sample data are defined: compact and expanded. The
19 Specification has this to say:
20
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.
26
27 This decoder only supports the compact form, because that is the only
28 one for which data was avaialble.
29
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.
34
35 The following sample record types are supported:
36
37         Raw Packet Header
38         opaque = flow_data; enterprise = 0; format = 1
39
40         Extended Switch Data
41         opaque = flow_data; enterprise = 0; format = 1001
42
43         Extended Router Data
44         opaque = flow_data; enterprise = 0; format = 1002
45
46         Extended Gateway Data
47         opaque = flow_data; enterprise = 0; format = 1003
48
49         Extended User Data
50         opaque = flow_data; enterprise = 0; format = 1004
51
52         Extended URL Data
53         opaque = flow_data; enterprise = 0; format = 1005
54
55 The following types of counter records are supported:
56
57         Generic Interface Counters - see RFC 2233
58         opaque = counter_data; enterprise = 0; format = 1
59
60         Ethernet Interface Counters - see RFC 2358
61         opaque = counter_data; enterprise = 0; format = 2
62
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. */
71
72 package layers
73
74 import (
75         "encoding/binary"
76         "errors"
77         "fmt"
78         "net"
79
80         "github.com/google/gopacket"
81 )
82
83 // SFlowRecord holds both flow sample records and counter sample records.
84 // A Record is the structure that actually holds the sampled data
85 // and / or counters.
86 type SFlowRecord interface {
87 }
88
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
94
95 func (sdc SFlowDataSource) decode() (SFlowSourceFormat, SFlowSourceValue) {
96         leftField := sdc >> 30
97         rightField := uint32(0x3FFFFFFF) & uint32(sdc)
98         return SFlowSourceFormat(leftField), SFlowSourceValue(rightField)
99 }
100
101 type SFlowDataSourceExpanded struct {
102         SourceIDClass SFlowSourceFormat
103         SourceIDIndex SFlowSourceValue
104 }
105
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)
110 }
111
112 type SFlowSourceFormat uint32
113
114 type SFlowSourceValue uint32
115
116 const (
117         SFlowTypeSingleInterface      SFlowSourceFormat = 0
118         SFlowTypePacketDiscarded      SFlowSourceFormat = 1
119         SFlowTypeMultipleDestinations SFlowSourceFormat = 2
120 )
121
122 func (sdf SFlowSourceFormat) String() string {
123         switch sdf {
124         case SFlowTypeSingleInterface:
125                 return "Single Interface"
126         case SFlowTypePacketDiscarded:
127                 return "Packet Discarded"
128         case SFlowTypeMultipleDestinations:
129                 return "Multiple Destinations"
130         default:
131                 return "UNKNOWN"
132         }
133 }
134
135 func decodeSFlow(data []byte, p gopacket.PacketBuilder) error {
136         s := &SFlowDatagram{}
137         err := s.DecodeFromBytes(data, p)
138         if err != nil {
139                 return err
140         }
141         p.AddLayer(s)
142         p.SetApplicationLayer(s)
143         return nil
144 }
145
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 {
149         BaseLayer
150
151         DatagramVersion uint32
152         AgentAddress    net.IP
153         SubAgentID      uint32
154         SequenceNumber  uint32
155         AgentUptime     uint32
156         SampleCount     uint32
157         FlowSamples     []SFlowFlowSample
158         CounterSamples  []SFlowCounterSample
159 }
160
161 // An SFlow  datagram's outer container has the following
162 // structure:
163
164 //  0                      15                      31
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)      /
171 //  /                                               /
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 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
181 //  /                  n samples                    /
182 //  /                                               /
183 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
184
185 // SFlowDataFormat encodes the EnterpriseID in the most
186 // significant 12 bits, and the SampleType in the least significant
187 // 20 bits.
188 type SFlowDataFormat uint32
189
190 func (sdf SFlowDataFormat) decode() (SFlowEnterpriseID, SFlowSampleType) {
191         leftField := sdf >> 12
192         rightField := uint32(0xFFF) & uint32(sdf)
193         return SFlowEnterpriseID(leftField), SFlowSampleType(rightField)
194 }
195
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
200 // here.
201 type SFlowEnterpriseID uint32
202
203 const (
204         SFlowStandard SFlowEnterpriseID = 0
205 )
206
207 func (eid SFlowEnterpriseID) String() string {
208         switch eid {
209         case SFlowStandard:
210                 return "Standard SFlow"
211         default:
212                 return ""
213         }
214 }
215
216 func (eid SFlowEnterpriseID) GetType() SFlowEnterpriseID {
217         return SFlowStandard
218 }
219
220 // SFlowSampleType specifies the type of sample. Only flow samples
221 // and counter samples are supported
222 type SFlowSampleType uint32
223
224 const (
225         SFlowTypeFlowSample            SFlowSampleType = 1
226         SFlowTypeCounterSample         SFlowSampleType = 2
227         SFlowTypeExpandedFlowSample    SFlowSampleType = 3
228         SFlowTypeExpandedCounterSample SFlowSampleType = 4
229 )
230
231 func (st SFlowSampleType) GetType() SFlowSampleType {
232         switch st {
233         case SFlowTypeFlowSample:
234                 return SFlowTypeFlowSample
235         case SFlowTypeCounterSample:
236                 return SFlowTypeCounterSample
237         case SFlowTypeExpandedFlowSample:
238                 return SFlowTypeExpandedFlowSample
239         case SFlowTypeExpandedCounterSample:
240                 return SFlowTypeExpandedCounterSample
241         default:
242                 panic("Invalid Sample Type")
243         }
244 }
245
246 func (st SFlowSampleType) String() string {
247         switch st {
248         case SFlowTypeFlowSample:
249                 return "Flow Sample"
250         case SFlowTypeCounterSample:
251                 return "Counter Sample"
252         case SFlowTypeExpandedFlowSample:
253                 return "Expanded Flow Sample"
254         case SFlowTypeExpandedCounterSample:
255                 return "Expanded Counter Sample"
256         default:
257                 return ""
258         }
259 }
260
261 func (s *SFlowDatagram) LayerType() gopacket.LayerType { return LayerTypeSFlow }
262
263 func (d *SFlowDatagram) Payload() []byte { return nil }
264
265 func (d *SFlowDatagram) CanDecode() gopacket.LayerClass { return LayerTypeSFlow }
266
267 func (d *SFlowDatagram) NextLayerType() gopacket.LayerType { return gopacket.LayerTypePayload }
268
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
272
273 const (
274         SFlowIPv4 SFlowIPType = 1
275         SFlowIPv6 SFlowIPType = 2
276 )
277
278 func (s SFlowIPType) String() string {
279         switch s {
280         case SFlowIPv4:
281                 return "IPv4"
282         case SFlowIPv6:
283                 return "IPv6"
284         default:
285                 return ""
286         }
287 }
288
289 func (s SFlowIPType) Length() int {
290         switch s {
291         case SFlowIPv4:
292                 return 4
293         case SFlowIPv6:
294                 return 16
295         default:
296                 return 0
297         }
298 }
299
300 func (s *SFlowDatagram) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
301         var agentAddressType SFlowIPType
302
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])
310
311         if s.SampleCount < 1 {
312                 return fmt.Errorf("SFlow Datagram has invalid sample length: %d", s.SampleCount)
313         }
314         for i := uint32(0); i < s.SampleCount; i++ {
315                 sdf := SFlowDataFormat(binary.BigEndian.Uint32(data[:4]))
316                 _, sampleType := sdf.decode()
317                 switch sampleType {
318                 case SFlowTypeFlowSample:
319                         if flowSample, err := decodeFlowSample(&data, false); err == nil {
320                                 s.FlowSamples = append(s.FlowSamples, flowSample)
321                         } else {
322                                 return err
323                         }
324                 case SFlowTypeCounterSample:
325                         if counterSample, err := decodeCounterSample(&data, false); err == nil {
326                                 s.CounterSamples = append(s.CounterSamples, counterSample)
327                         } else {
328                                 return err
329                         }
330                 case SFlowTypeExpandedFlowSample:
331                         if flowSample, err := decodeFlowSample(&data, true); err == nil {
332                                 s.FlowSamples = append(s.FlowSamples, flowSample)
333                         } else {
334                                 return err
335                         }
336                 case SFlowTypeExpandedCounterSample:
337                         if counterSample, err := decodeCounterSample(&data, true); err == nil {
338                                 s.CounterSamples = append(s.CounterSamples, counterSample)
339                         } else {
340                                 return err
341                         }
342
343                 default:
344                         return fmt.Errorf("Unsupported SFlow sample type %d", sampleType)
345                 }
346         }
347         return nil
348 }
349
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
355         SampleLength          uint32
356         SequenceNumber        uint32
357         SourceIDClass         SFlowSourceFormat
358         SourceIDIndex         SFlowSourceValue
359         SamplingRate          uint32
360         SamplePool            uint32
361         Dropped               uint32
362         InputInterfaceFormat  uint32
363         InputInterface        uint32
364         OutputInterfaceFormat uint32
365         OutputInterface       uint32
366         RecordCount           uint32
367         Records               []SFlowRecord
368 }
369
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
373
374 //  0                      15                      31
375 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
376 //  |      20 bit Interprise (0)     |12 bit format |
377 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
378 //  |                  sample length                |
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 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
388 //  |                    int drops                  |
389 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
390 //  |                 int input ifIndex             |
391 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
392 //  |                int output ifIndex             |
393 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
394 //  |               int number of records           |
395 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
396 //  /                   flow records                /
397 //  /                                               /
398 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
399
400 // Flow samples have the following structure.
401 // Flow record format: type 3
402
403 //  0                      15                      31
404 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
405 //  |      20 bit Interprise (0)     |12 bit format |
406 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
407 //  |                  sample length                |
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 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
419 //  |                    int drops                  |
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 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
431 //  /                   flow records                /
432 //  /                                               /
433 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
434
435 type SFlowFlowDataFormat uint32
436
437 func (fdf SFlowFlowDataFormat) decode() (SFlowEnterpriseID, SFlowFlowRecordType) {
438         leftField := fdf >> 12
439         rightField := uint32(0xFFF) & uint32(fdf)
440         return SFlowEnterpriseID(leftField), SFlowFlowRecordType(rightField)
441 }
442
443 func (fs SFlowFlowSample) GetRecords() []SFlowRecord {
444         return fs.Records
445 }
446
447 func (fs SFlowFlowSample) GetType() SFlowSampleType {
448         return SFlowTypeFlowSample
449 }
450
451 func skipRecord(data *[]byte) {
452         recordLength := int(binary.BigEndian.Uint32((*data)[4:]))
453         *data = (*data)[(recordLength+((4-recordLength)%4))+8:]
454 }
455
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
461
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])
465         if expanded {
466                 *data, s.SourceIDClass = (*data)[4:], SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4]))
467                 *data, s.SourceIDIndex = (*data)[4:], SFlowSourceValue(binary.BigEndian.Uint32((*data)[:4]))
468         } else {
469                 *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
470                 s.SourceIDClass, s.SourceIDIndex = sdc.decode()
471         }
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])
475
476         if expanded {
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])
481         } else {
482                 *data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
483                 *data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
484         }
485         *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
486
487         for i := uint32(0); i < s.RecordCount; i++ {
488                 rdf := SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
489                 _, flowRecordType := rdf.decode()
490
491                 switch flowRecordType {
492                 case SFlowTypeRawPacketFlow:
493                         if record, err := decodeRawPacketFlowRecord(data); err == nil {
494                                 s.Records = append(s.Records, record)
495                         } else {
496                                 return s, err
497                         }
498                 case SFlowTypeExtendedUserFlow:
499                         if record, err := decodeExtendedUserFlow(data); err == nil {
500                                 s.Records = append(s.Records, record)
501                         } else {
502                                 return s, err
503                         }
504                 case SFlowTypeExtendedUrlFlow:
505                         if record, err := decodeExtendedURLRecord(data); err == nil {
506                                 s.Records = append(s.Records, record)
507                         } else {
508                                 return s, err
509                         }
510                 case SFlowTypeExtendedSwitchFlow:
511                         if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
512                                 s.Records = append(s.Records, record)
513                         } else {
514                                 return s, err
515                         }
516                 case SFlowTypeExtendedRouterFlow:
517                         if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
518                                 s.Records = append(s.Records, record)
519                         } else {
520                                 return s, err
521                         }
522                 case SFlowTypeExtendedGatewayFlow:
523                         if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
524                                 s.Records = append(s.Records, record)
525                         } else {
526                                 return s, err
527                         }
528                 case SFlowTypeEthernetFrameFlow:
529                         // TODO
530                         skipRecord(data)
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)
535                         } else {
536                                 return s, err
537                         }
538                 case SFlowTypeIpv6Flow:
539                         if record, err := decodeSFlowIpv6Record(data); err == nil {
540                                 s.Records = append(s.Records, record)
541                         } else {
542                                 return s, err
543                         }
544                 case SFlowTypeExtendedMlpsFlow:
545                         // TODO
546                         skipRecord(data)
547                         return s, errors.New("skipping TypeExtendedMlpsFlow")
548                 case SFlowTypeExtendedNatFlow:
549                         // TODO
550                         skipRecord(data)
551                         return s, errors.New("skipping TypeExtendedNatFlow")
552                 case SFlowTypeExtendedMlpsTunnelFlow:
553                         // TODO
554                         skipRecord(data)
555                         return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
556                 case SFlowTypeExtendedMlpsVcFlow:
557                         // TODO
558                         skipRecord(data)
559                         return s, errors.New("skipping TypeExtendedMlpsVcFlow")
560                 case SFlowTypeExtendedMlpsFecFlow:
561                         // TODO
562                         skipRecord(data)
563                         return s, errors.New("skipping TypeExtendedMlpsFecFlow")
564                 case SFlowTypeExtendedMlpsLvpFecFlow:
565                         // TODO
566                         skipRecord(data)
567                         return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
568                 case SFlowTypeExtendedVlanFlow:
569                         // TODO
570                         skipRecord(data)
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)
575                         } else {
576                                 return s, err
577                         }
578                 case SFlowTypeExtendedIpv4TunnelIngressFlow:
579                         if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
580                                 s.Records = append(s.Records, record)
581                         } else {
582                                 return s, err
583                         }
584                 case SFlowTypeExtendedIpv6TunnelEgressFlow:
585                         if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
586                                 s.Records = append(s.Records, record)
587                         } else {
588                                 return s, err
589                         }
590                 case SFlowTypeExtendedIpv6TunnelIngressFlow:
591                         if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
592                                 s.Records = append(s.Records, record)
593                         } else {
594                                 return s, err
595                         }
596                 case SFlowTypeExtendedDecapsulateEgressFlow:
597                         if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
598                                 s.Records = append(s.Records, record)
599                         } else {
600                                 return s, err
601                         }
602                 case SFlowTypeExtendedDecapsulateIngressFlow:
603                         if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
604                                 s.Records = append(s.Records, record)
605                         } else {
606                                 return s, err
607                         }
608                 case SFlowTypeExtendedVniEgressFlow:
609                         if record, err := decodeExtendedVniEgress(data); err == nil {
610                                 s.Records = append(s.Records, record)
611                         } else {
612                                 return s, err
613                         }
614                 case SFlowTypeExtendedVniIngressFlow:
615                         if record, err := decodeExtendedVniIngress(data); err == nil {
616                                 s.Records = append(s.Records, record)
617                         } else {
618                                 return s, err
619                         }
620                 default:
621                         return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
622                 }
623         }
624         return s, nil
625 }
626
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
636         SampleLength   uint32
637         SequenceNumber uint32
638         SourceIDClass  SFlowSourceFormat
639         SourceIDIndex  SFlowSourceValue
640         RecordCount    uint32
641         Records        []SFlowRecord
642 }
643
644 // Counter samples have the following structure:
645
646 //  0                      15                      31
647 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
648 //  |          int sample sequence number           |
649 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
650 //  |id type |       src id index value             |
651 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
652 //  |               int number of records           |
653 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
654 //  /                counter records                /
655 //  /                                               /
656 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
657
658 type SFlowCounterDataFormat uint32
659
660 func (cdf SFlowCounterDataFormat) decode() (SFlowEnterpriseID, SFlowCounterRecordType) {
661         leftField := cdf >> 12
662         rightField := uint32(0xFFF) & uint32(cdf)
663         return SFlowEnterpriseID(leftField), SFlowCounterRecordType(rightField)
664 }
665
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 {
670         return cs.Records
671 }
672
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
677 }
678
679 type SFlowCounterRecordType uint32
680
681 const (
682         SFlowTypeGenericInterfaceCounters   SFlowCounterRecordType = 1
683         SFlowTypeEthernetInterfaceCounters  SFlowCounterRecordType = 2
684         SFlowTypeTokenRingInterfaceCounters SFlowCounterRecordType = 3
685         SFlowType100BaseVGInterfaceCounters SFlowCounterRecordType = 4
686         SFlowTypeVLANCounters               SFlowCounterRecordType = 5
687         SFlowTypeProcessorCounters          SFlowCounterRecordType = 1001
688 )
689
690 func (cr SFlowCounterRecordType) String() string {
691         switch cr {
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"
704         default:
705                 return ""
706
707         }
708 }
709
710 func decodeCounterSample(data *[]byte, expanded bool) (SFlowCounterSample, error) {
711         s := SFlowCounterSample{}
712         var sdc SFlowDataSource
713         var sdce SFlowDataSourceExpanded
714         var sdf SFlowDataFormat
715
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])
720         if expanded {
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()
723         } else {
724                 *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
725                 s.SourceIDClass, s.SourceIDIndex = sdc.decode()
726         }
727         *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
728
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)
736                         } else {
737                                 return s, err
738                         }
739                 case SFlowTypeEthernetInterfaceCounters:
740                         if record, err := decodeEthernetCounters(data); err == nil {
741                                 s.Records = append(s.Records, record)
742                         } else {
743                                 return s, err
744                         }
745                 case SFlowTypeTokenRingInterfaceCounters:
746                         skipRecord(data)
747                         return s, errors.New("skipping TypeTokenRingInterfaceCounters")
748                 case SFlowType100BaseVGInterfaceCounters:
749                         skipRecord(data)
750                         return s, errors.New("skipping Type100BaseVGInterfaceCounters")
751                 case SFlowTypeVLANCounters:
752                         skipRecord(data)
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)
757                         } else {
758                                 return s, err
759                         }
760                 default:
761                         return s, fmt.Errorf("Invalid counter record type: %d", counterRecordType)
762                 }
763         }
764         return s, nil
765 }
766
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
773 }
774
775 func (bfr SFlowBaseFlowRecord) GetType() SFlowFlowRecordType {
776         return bfr.Format
777 }
778
779 // SFlowFlowRecordType denotes what kind of Flow Record is
780 // represented. See RFC 3176
781 type SFlowFlowRecordType uint32
782
783 const (
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
808 )
809
810 func (rt SFlowFlowRecordType) String() string {
811         switch rt {
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"
860         default:
861                 return ""
862         }
863 }
864
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.
871 //
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 {
876         SFlowBaseFlowRecord
877         HeaderProtocol SFlowRawHeaderProtocol
878         FrameLength    uint32
879         PayloadRemoved uint32
880         HeaderLength   uint32
881         Header         gopacket.Packet
882 }
883
884 // Raw packet record types have the following structure:
885
886 //  0                      15                      31
887 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
888 //  |      20 bit Interprise (0)     |12 bit format |
889 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
890 //  |                  record length                |
891 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
892 //  |                 Header Protocol               |
893 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
894 //  |                 Frame Length                  |
895 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
896 //  |                 Payload Removed               |
897 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
898 //  |                 Header Length                 |
899 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
900 //  \                     Header                    \
901 //  \                                               \
902 //  \                                               \
903 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
904
905 type SFlowRawHeaderProtocol uint32
906
907 const (
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 */
922 )
923
924 func (sfhp SFlowRawHeaderProtocol) String() string {
925         switch sfhp {
926         case SFlowProtoEthernet:
927                 return "ETHERNET-ISO88023"
928         case SFlowProtoISO88024:
929                 return "ISO88024-TOKENBUS"
930         case SFlowProtoISO88025:
931                 return "ISO88025-TOKENRING"
932         case SFlowProtoFDDI:
933                 return "FDDI"
934         case SFlowProtoFrameRelay:
935                 return "FRAME-RELAY"
936         case SFlowProtoX25:
937                 return "X25"
938         case SFlowProtoPPP:
939                 return "PPP"
940         case SFlowProtoSMDS:
941                 return "SMDS"
942         case SFlowProtoAAL5:
943                 return "AAL5"
944         case SFlowProtoAAL5_IP:
945                 return "AAL5-IP"
946         case SFlowProtoIPv4:
947                 return "IPv4"
948         case SFlowProtoIPv6:
949                 return "IPv6"
950         case SFlowProtoMPLS:
951                 return "MPLS"
952         case SFlowProtoPOS:
953                 return "POS"
954         }
955         return "UNKNOWN"
956 }
957
958 func decodeRawPacketFlowRecord(data *[]byte) (SFlowRawPacketFlowRecord, error) {
959         rec := SFlowRawPacketFlowRecord{}
960         header := []byte{}
961         var fdf SFlowFlowDataFormat
962
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)
973         return rec, nil
974 }
975
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 {
981         SFlowBaseFlowRecord
982         IncomingVLAN         uint32
983         IncomingVLANPriority uint32
984         OutgoingVLAN         uint32
985         OutgoingVLANPriority uint32
986 }
987
988 // Extended switch records have the following structure:
989
990 //  0                      15                      31
991 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
992 //  |      20 bit Interprise (0)     |12 bit format |
993 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
994 //  |                  record length                |
995 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
996 //  |                   Incoming VLAN               |
997 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
998 //  |                Incoming VLAN Priority         |
999 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1000 //  |                   Outgoing VLAN               |
1001 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1002 //  |                Outgoing VLAN Priority         |
1003 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1004
1005 func decodeExtendedSwitchFlowRecord(data *[]byte) (SFlowExtendedSwitchFlowRecord, error) {
1006         es := SFlowExtendedSwitchFlowRecord{}
1007         var fdf SFlowFlowDataFormat
1008
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])
1016         return es, nil
1017 }
1018
1019 // SFlowExtendedRouterFlowRecord gives additional information
1020 // about the layer 3 routing information used to forward
1021 // the packet
1022 type SFlowExtendedRouterFlowRecord struct {
1023         SFlowBaseFlowRecord
1024         NextHop                net.IP
1025         NextHopSourceMask      uint32
1026         NextHopDestinationMask uint32
1027 }
1028
1029 // Extended router records have the following structure:
1030
1031 //  0                      15                      31
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)     /
1040 //  /                                               /
1041 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1042 //  |              Next Hop Source Mask             |
1043 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1044 //  |              Next Hop Destination Mask        |
1045 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1046
1047 func decodeExtendedRouterFlowRecord(data *[]byte) (SFlowExtendedRouterFlowRecord, error) {
1048         er := SFlowExtendedRouterFlowRecord{}
1049         var fdf SFlowFlowDataFormat
1050         var extendedRouterAddressType SFlowIPType
1051
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])
1059         return er, nil
1060 }
1061
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.
1067
1068 // Extended gateway records have the following structure:
1069
1070 //  0                      15                      31
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)     /
1079 //  /                                               /
1080 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1081 //  |                       AS                      |
1082 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1083 //  |                  Source AS                    |
1084 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1085 //  |                    Peer AS                    |
1086 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1087 //  |                  AS Path Count                |
1088 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1089 //  /                AS Path / Sequence             /
1090 //  /                                               /
1091 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1092 //  /                   Communities                 /
1093 //  /                                               /
1094 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1095 //  |                    Local Pref                 |
1096 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1097
1098 // AS Path / Sequence:
1099
1100 //  0                      15                      31
1101 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1102 //  |     AS Source Type (Path=1 / Sequence=2)      |
1103 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1104 //  |              Path / Sequence length           |
1105 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1106 //  /              Path / Sequence Members          /
1107 //  /                                               /
1108 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1109
1110 // Communities:
1111
1112 //  0                      15                      31
1113 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1114 //  |                communitiy length              |
1115 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1116 //  /              communitiy Members               /
1117 //  /                                               /
1118 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1119
1120 type SFlowExtendedGatewayFlowRecord struct {
1121         SFlowBaseFlowRecord
1122         NextHop     net.IP
1123         AS          uint32
1124         SourceAS    uint32
1125         PeerAS      uint32
1126         ASPathCount uint32
1127         ASPath      []SFlowASDestination
1128         Communities []uint32
1129         LocalPref   uint32
1130 }
1131
1132 type SFlowASPathType uint32
1133
1134 const (
1135         SFlowASSet      SFlowASPathType = 1
1136         SFlowASSequence SFlowASPathType = 2
1137 )
1138
1139 func (apt SFlowASPathType) String() string {
1140         switch apt {
1141         case SFlowASSet:
1142                 return "AS Set"
1143         case SFlowASSequence:
1144                 return "AS Sequence"
1145         default:
1146                 return ""
1147         }
1148 }
1149
1150 type SFlowASDestination struct {
1151         Type    SFlowASPathType
1152         Count   uint32
1153         Members []uint32
1154 }
1155
1156 func (asd SFlowASDestination) String() string {
1157         switch asd.Type {
1158         case SFlowASSet:
1159                 return fmt.Sprint("AS Set:", asd.Members)
1160         case SFlowASSequence:
1161                 return fmt.Sprint("AS Sequence:", asd.Members)
1162         default:
1163                 return ""
1164         }
1165 }
1166
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++ {
1172                 var member uint32
1173                 *data, member = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1174                 ad.Members[i] = member
1175         }
1176 }
1177
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
1184
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)
1198         }
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
1204         }
1205         *data, eg.LocalPref = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
1206         return eg, nil
1207 }
1208
1209 // **************************************************
1210 //  Extended URL Flow Record
1211 // **************************************************
1212
1213 //  0                      15                      31
1214 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1215 //  |      20 bit Interprise (0)     |12 bit format |
1216 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1217 //  |                  record length                |
1218 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1219 //  |                   direction                   |
1220 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1221 //  |                      URL                      |
1222 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1223 //  |                      Host                     |
1224 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1225
1226 type SFlowURLDirection uint32
1227
1228 const (
1229         SFlowURLsrc SFlowURLDirection = 1
1230         SFlowURLdst SFlowURLDirection = 2
1231 )
1232
1233 func (urld SFlowURLDirection) String() string {
1234         switch urld {
1235         case SFlowURLsrc:
1236                 return "Source address is the server"
1237         case SFlowURLdst:
1238                 return "Destination address is the server"
1239         default:
1240                 return ""
1241         }
1242 }
1243
1244 type SFlowExtendedURLRecord struct {
1245         SFlowBaseFlowRecord
1246         Direction SFlowURLDirection
1247         URL       string
1248         Host      string
1249 }
1250
1251 func decodeExtendedURLRecord(data *[]byte) (SFlowExtendedURLRecord, error) {
1252         eur := SFlowExtendedURLRecord{}
1253         var fdf SFlowFlowDataFormat
1254         var urlLen uint32
1255         var urlLenWithPad int
1256         var hostLen uint32
1257         var hostLenWithPad int
1258         var urlBytes []byte
1259         var hostBytes []byte
1260
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])
1273         return eur, nil
1274 }
1275
1276 // **************************************************
1277 //  Extended User Flow Record
1278 // **************************************************
1279
1280 //  0                      15                      31
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 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1294
1295 type SFlowExtendedUserFlow struct {
1296         SFlowBaseFlowRecord
1297         SourceCharSet      SFlowCharSet
1298         SourceUserID       string
1299         DestinationCharSet SFlowCharSet
1300         DestinationUserID  string
1301 }
1302
1303 type SFlowCharSet uint32
1304
1305 const (
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
1565 )
1566
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
1576
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])
1590         return eu, nil
1591 }
1592
1593 // **************************************************
1594 //  Packet IP version 4 Record
1595 // **************************************************
1596
1597 //  0                      15                      31
1598 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1599 //  |                     Length                    |
1600 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1601 //  |                    Protocol                   |
1602 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1603 //  |                  Source IPv4                  |
1604 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1605 //  |                Destination IPv4               |
1606 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1607 //  |                   Source Port                 |
1608 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1609 //  |                Destionation Port              |
1610 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1611 //  |                   TCP Flags                   |
1612 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1613 //  |                      TOS                      |
1614 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1615 type SFlowIpv4Record struct {
1616         // The length of the IP packet excluding ower layer encapsulations
1617         Length uint32
1618         // IP Protocol type (for example, TCP = 6, UDP = 17)
1619         Protocol uint32
1620         // Source IP Address
1621         IPSrc net.IP
1622         // Destination IP Address
1623         IPDst net.IP
1624         // TCP/UDP source port number or equivalent
1625         PortSrc uint32
1626         // TCP/UDP destination port number or equivalent
1627         PortDst uint32
1628         // TCP flags
1629         TCPFlags uint32
1630         // IP type of service
1631         TOS uint32
1632 }
1633
1634 func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
1635         si := SFlowIpv4Record{}
1636
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])
1645
1646         return si, nil
1647 }
1648
1649 // **************************************************
1650 //  Packet IP version 6 Record
1651 // **************************************************
1652
1653 //  0                      15                      31
1654 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1655 //  |                     Length                    |
1656 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1657 //  |                    Protocol                   |
1658 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1659 //  |                  Source IPv4                  |
1660 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1661 //  |                Destination IPv4               |
1662 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1663 //  |                   Source Port                 |
1664 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1665 //  |                Destionation Port              |
1666 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1667 //  |                   TCP Flags                   |
1668 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1669 //  |                    Priority                   |
1670 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1671 type SFlowIpv6Record struct {
1672         // The length of the IP packet excluding ower layer encapsulations
1673         Length uint32
1674         // IP Protocol type (for example, TCP = 6, UDP = 17)
1675         Protocol uint32
1676         // Source IP Address
1677         IPSrc net.IP
1678         // Destination IP Address
1679         IPDst net.IP
1680         // TCP/UDP source port number or equivalent
1681         PortSrc uint32
1682         // TCP/UDP destination port number or equivalent
1683         PortDst uint32
1684         // TCP flags
1685         TCPFlags uint32
1686         // IP priority
1687         Priority uint32
1688 }
1689
1690 func decodeSFlowIpv6Record(data *[]byte) (SFlowIpv6Record, error) {
1691         si := SFlowIpv6Record{}
1692
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])
1701
1702         return si, nil
1703 }
1704
1705 // **************************************************
1706 //  Extended IPv4 Tunnel Egress
1707 // **************************************************
1708
1709 //  0                      15                      31
1710 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1711 //  |      20 bit Interprise (0)     |12 bit format |
1712 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1713 //  |                  record length                |
1714 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1715 //  /           Packet IP version 4 Record          /
1716 //  /                                               /
1717 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1718 type SFlowExtendedIpv4TunnelEgressRecord struct {
1719         SFlowBaseFlowRecord
1720         SFlowIpv4Record SFlowIpv4Record
1721 }
1722
1723 func decodeExtendedIpv4TunnelEgress(data *[]byte) (SFlowExtendedIpv4TunnelEgressRecord, error) {
1724         rec := SFlowExtendedIpv4TunnelEgressRecord{}
1725         var fdf SFlowFlowDataFormat
1726
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)
1731
1732         return rec, nil
1733 }
1734
1735 // **************************************************
1736 //  Extended IPv4 Tunnel Ingress
1737 // **************************************************
1738
1739 //  0                      15                      31
1740 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1741 //  |      20 bit Interprise (0)     |12 bit format |
1742 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1743 //  |                  record length                |
1744 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1745 //  /           Packet IP version 4 Record          /
1746 //  /                                               /
1747 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1748 type SFlowExtendedIpv4TunnelIngressRecord struct {
1749         SFlowBaseFlowRecord
1750         SFlowIpv4Record SFlowIpv4Record
1751 }
1752
1753 func decodeExtendedIpv4TunnelIngress(data *[]byte) (SFlowExtendedIpv4TunnelIngressRecord, error) {
1754         rec := SFlowExtendedIpv4TunnelIngressRecord{}
1755         var fdf SFlowFlowDataFormat
1756
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)
1761
1762         return rec, nil
1763 }
1764
1765 // **************************************************
1766 //  Extended IPv6 Tunnel Egress
1767 // **************************************************
1768
1769 //  0                      15                      31
1770 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1771 //  |      20 bit Interprise (0)     |12 bit format |
1772 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1773 //  |                  record length                |
1774 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1775 //  /           Packet IP version 6 Record          /
1776 //  /                                               /
1777 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1778 type SFlowExtendedIpv6TunnelEgressRecord struct {
1779         SFlowBaseFlowRecord
1780         SFlowIpv6Record
1781 }
1782
1783 func decodeExtendedIpv6TunnelEgress(data *[]byte) (SFlowExtendedIpv6TunnelEgressRecord, error) {
1784         rec := SFlowExtendedIpv6TunnelEgressRecord{}
1785         var fdf SFlowFlowDataFormat
1786
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)
1791
1792         return rec, nil
1793 }
1794
1795 // **************************************************
1796 //  Extended IPv6 Tunnel Ingress
1797 // **************************************************
1798
1799 //  0                      15                      31
1800 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1801 //  |      20 bit Interprise (0)     |12 bit format |
1802 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1803 //  |                  record length                |
1804 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1805 //  /           Packet IP version 6 Record          /
1806 //  /                                               /
1807 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1808 type SFlowExtendedIpv6TunnelIngressRecord struct {
1809         SFlowBaseFlowRecord
1810         SFlowIpv6Record
1811 }
1812
1813 func decodeExtendedIpv6TunnelIngress(data *[]byte) (SFlowExtendedIpv6TunnelIngressRecord, error) {
1814         rec := SFlowExtendedIpv6TunnelIngressRecord{}
1815         var fdf SFlowFlowDataFormat
1816
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)
1821
1822         return rec, nil
1823 }
1824
1825 // **************************************************
1826 //  Extended Decapsulate Egress
1827 // **************************************************
1828
1829 //  0                      15                      31
1830 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1831 //  |      20 bit Interprise (0)     |12 bit format |
1832 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1833 //  |                  record length                |
1834 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1835 //  |               Inner Header Offset             |
1836 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1837 type SFlowExtendedDecapsulateEgressRecord struct {
1838         SFlowBaseFlowRecord
1839         InnerHeaderOffset uint32
1840 }
1841
1842 func decodeExtendedDecapsulateEgress(data *[]byte) (SFlowExtendedDecapsulateEgressRecord, error) {
1843         rec := SFlowExtendedDecapsulateEgressRecord{}
1844         var fdf SFlowFlowDataFormat
1845
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])
1850
1851         return rec, nil
1852 }
1853
1854 // **************************************************
1855 //  Extended Decapsulate Ingress
1856 // **************************************************
1857
1858 //  0                      15                      31
1859 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1860 //  |      20 bit Interprise (0)     |12 bit format |
1861 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1862 //  |                  record length                |
1863 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1864 //  |               Inner Header Offset             |
1865 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1866 type SFlowExtendedDecapsulateIngressRecord struct {
1867         SFlowBaseFlowRecord
1868         InnerHeaderOffset uint32
1869 }
1870
1871 func decodeExtendedDecapsulateIngress(data *[]byte) (SFlowExtendedDecapsulateIngressRecord, error) {
1872         rec := SFlowExtendedDecapsulateIngressRecord{}
1873         var fdf SFlowFlowDataFormat
1874
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])
1879
1880         return rec, nil
1881 }
1882
1883 // **************************************************
1884 //  Extended VNI Egress
1885 // **************************************************
1886
1887 //  0                      15                      31
1888 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1889 //  |      20 bit Interprise (0)     |12 bit format |
1890 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1891 //  |                  record length                |
1892 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1893 //  |                       VNI                     |
1894 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1895 type SFlowExtendedVniEgressRecord struct {
1896         SFlowBaseFlowRecord
1897         VNI uint32
1898 }
1899
1900 func decodeExtendedVniEgress(data *[]byte) (SFlowExtendedVniEgressRecord, error) {
1901         rec := SFlowExtendedVniEgressRecord{}
1902         var fdf SFlowFlowDataFormat
1903
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])
1908
1909         return rec, nil
1910 }
1911
1912 // **************************************************
1913 //  Extended VNI Ingress
1914 // **************************************************
1915
1916 //  0                      15                      31
1917 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1918 //  |      20 bit Interprise (0)     |12 bit format |
1919 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1920 //  |                  record length                |
1921 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1922 //  |                       VNI                     |
1923 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1924 type SFlowExtendedVniIngressRecord struct {
1925         SFlowBaseFlowRecord
1926         VNI uint32
1927 }
1928
1929 func decodeExtendedVniIngress(data *[]byte) (SFlowExtendedVniIngressRecord, error) {
1930         rec := SFlowExtendedVniIngressRecord{}
1931         var fdf SFlowFlowDataFormat
1932
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])
1937
1938         return rec, nil
1939 }
1940
1941 // **************************************************
1942 //  Counter Record
1943 // **************************************************
1944
1945 //  0                      15                      31
1946 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1947 //  |      20 bit Interprise (0)     |12 bit format |
1948 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1949 //  |                  counter length               |
1950 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1951 //  /                   counter data                /
1952 //  /                                               /
1953 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1954
1955 type SFlowBaseCounterRecord struct {
1956         EnterpriseID   SFlowEnterpriseID
1957         Format         SFlowCounterRecordType
1958         FlowDataLength uint32
1959 }
1960
1961 func (bcr SFlowBaseCounterRecord) GetType() SFlowCounterRecordType {
1962         switch bcr.Format {
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
1975
1976         }
1977         unrecognized := fmt.Sprint("Unrecognized counter record type:", bcr.Format)
1978         panic(unrecognized)
1979 }
1980
1981 // **************************************************
1982 //  Counter Record
1983 // **************************************************
1984
1985 //  0                      15                      31
1986 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1987 //  |      20 bit Interprise (0)     |12 bit format |
1988 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1989 //  |                  counter length               |
1990 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1991 //  |                    IfIndex                    |
1992 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1993 //  |                    IfType                     |
1994 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1995 //  |                   IfSpeed                     |
1996 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1997 //  |                   IfDirection                 |
1998 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1999 //  |                    IfStatus                   |
2000 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2001 //  |                   IFInOctets                  |
2002 //  |                                               |
2003 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2004 //  |                   IfInUcastPkts               |
2005 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2006 //  |                  IfInMulticastPkts            |
2007 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2008 //  |                  IfInBroadcastPkts            |
2009 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2010 //  |                    IfInDiscards               |
2011 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2012 //  |                    InInErrors                 |
2013 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2014 //  |                  IfInUnknownProtos            |
2015 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2016 //  |                   IfOutOctets                 |
2017 //  |                                               |
2018 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2019 //  |                   IfOutUcastPkts              |
2020 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2021 //  |                  IfOutMulticastPkts           |
2022 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2023 //  |                  IfOutBroadcastPkts           |
2024 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2025 //  |                   IfOutDiscards               |
2026 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2027 //  |                    IfOUtErrors                |
2028 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2029 //  |                 IfPromiscouousMode            |
2030 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2031
2032 type SFlowGenericInterfaceCounters struct {
2033         SFlowBaseCounterRecord
2034         IfIndex            uint32
2035         IfType             uint32
2036         IfSpeed            uint64
2037         IfDirection        uint32
2038         IfStatus           uint32
2039         IfInOctets         uint64
2040         IfInUcastPkts      uint32
2041         IfInMulticastPkts  uint32
2042         IfInBroadcastPkts  uint32
2043         IfInDiscards       uint32
2044         IfInErrors         uint32
2045         IfInUnknownProtos  uint32
2046         IfOutOctets        uint64
2047         IfOutUcastPkts     uint32
2048         IfOutMulticastPkts uint32
2049         IfOutBroadcastPkts uint32
2050         IfOutDiscards      uint32
2051         IfOutErrors        uint32
2052         IfPromiscuousMode  uint32
2053 }
2054
2055 func decodeGenericInterfaceCounters(data *[]byte) (SFlowGenericInterfaceCounters, error) {
2056         gic := SFlowGenericInterfaceCounters{}
2057         var cdf SFlowCounterDataFormat
2058
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])
2081         return gic, nil
2082 }
2083
2084 // **************************************************
2085 //  Counter Record
2086 // **************************************************
2087
2088 //  0                      15                      31
2089 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2090 //  |      20 bit Interprise (0)     |12 bit format |
2091 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2092 //  |                  counter length               |
2093 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2094 //  /                   counter data                /
2095 //  /                                               /
2096 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2097
2098 type SFlowEthernetCounters struct {
2099         SFlowBaseCounterRecord
2100         AlignmentErrors           uint32
2101         FCSErrors                 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
2112         SymbolErrors              uint32
2113 }
2114
2115 func decodeEthernetCounters(data *[]byte) (SFlowEthernetCounters, error) {
2116         ec := SFlowEthernetCounters{}
2117         var cdf SFlowCounterDataFormat
2118
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])
2135         return ec, nil
2136 }
2137
2138 // **************************************************
2139 //  Processor Counter Record
2140 // **************************************************
2141 //  0                      15                      31
2142 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2143 //  |      20 bit Interprise (0)     |12 bit format |
2144 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2145 //  |                  counter length               |
2146 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2147 //  |                    FiveSecCpu                 |
2148 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2149 //  |                    OneMinCpu                  |
2150 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2151 //  |                    GiveMinCpu                 |
2152 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2153 //  |                   TotalMemory                 |
2154 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2155 //  |                    FreeMemory                 |
2156 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2157
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)
2165 }
2166
2167 func decodeProcessorCounters(data *[]byte) (SFlowProcessorCounters, error) {
2168         pc := SFlowProcessorCounters{}
2169         var cdf SFlowCounterDataFormat
2170         var high32, low32 uint32
2171
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])
2175
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)
2185
2186         return pc, nil
2187 }