github.com/gopacket/gopacket@v1.1.0/layers/sflow.go (about)

     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 available.
    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/gopacket/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  // SFlowDataFormat
   165  //
   166  //	  0                      15                      31
   167  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   168  //	  |           int sFlow version (2|4|5)           |
   169  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   170  //	  |   int IP version of the Agent (1=v4|2=v6)     |
   171  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   172  //	  /    Agent IP address (v4=4byte|v6=16byte)      /
   173  //	  /                                               /
   174  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   175  //	  |               int sub agent id                |
   176  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   177  //	  |         int datagram sequence number          |
   178  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   179  //	  |            int switch uptime in ms            |
   180  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   181  //	  |          int n samples in datagram            |
   182  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   183  //	  /                  n samples                    /
   184  //	  /                                               /
   185  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   186  
   187  // SFlowDataFormat encodes the EnterpriseID in the most
   188  // significant 12 bits, and the SampleType in the least significant
   189  // 20 bits.
   190  type SFlowDataFormat uint32
   191  
   192  func (sdf SFlowDataFormat) decode() (SFlowEnterpriseID, SFlowSampleType) {
   193  	leftField := sdf >> 12
   194  	rightField := uint32(0xFFF) & uint32(sdf)
   195  	return SFlowEnterpriseID(leftField), SFlowSampleType(rightField)
   196  }
   197  
   198  // SFlowEnterpriseID is used to differentiate between the
   199  // official SFlow standard, and other, vendor-specific
   200  // types of flow data. (Similiar to SNMP's enterprise MIB
   201  // OIDs) Only the office SFlow Enterprise ID is decoded
   202  // here.
   203  type SFlowEnterpriseID uint32
   204  
   205  const (
   206  	SFlowStandard SFlowEnterpriseID = 0
   207  )
   208  
   209  func (eid SFlowEnterpriseID) String() string {
   210  	switch eid {
   211  	case SFlowStandard:
   212  		return "Standard SFlow"
   213  	default:
   214  		return ""
   215  	}
   216  }
   217  
   218  func (eid SFlowEnterpriseID) GetType() SFlowEnterpriseID {
   219  	return SFlowStandard
   220  }
   221  
   222  // SFlowSampleType specifies the type of sample. Only flow samples
   223  // and counter samples are supported
   224  type SFlowSampleType uint32
   225  
   226  const (
   227  	SFlowTypeFlowSample            SFlowSampleType = 1
   228  	SFlowTypeCounterSample         SFlowSampleType = 2
   229  	SFlowTypeExpandedFlowSample    SFlowSampleType = 3
   230  	SFlowTypeExpandedCounterSample SFlowSampleType = 4
   231  )
   232  
   233  func (st SFlowSampleType) GetType() SFlowSampleType {
   234  	switch st {
   235  	case SFlowTypeFlowSample:
   236  		return SFlowTypeFlowSample
   237  	case SFlowTypeCounterSample:
   238  		return SFlowTypeCounterSample
   239  	case SFlowTypeExpandedFlowSample:
   240  		return SFlowTypeExpandedFlowSample
   241  	case SFlowTypeExpandedCounterSample:
   242  		return SFlowTypeExpandedCounterSample
   243  	default:
   244  		panic("Invalid Sample Type")
   245  	}
   246  }
   247  
   248  func (st SFlowSampleType) String() string {
   249  	switch st {
   250  	case SFlowTypeFlowSample:
   251  		return "Flow Sample"
   252  	case SFlowTypeCounterSample:
   253  		return "Counter Sample"
   254  	case SFlowTypeExpandedFlowSample:
   255  		return "Expanded Flow Sample"
   256  	case SFlowTypeExpandedCounterSample:
   257  		return "Expanded Counter Sample"
   258  	default:
   259  		return ""
   260  	}
   261  }
   262  
   263  func (s *SFlowDatagram) LayerType() gopacket.LayerType { return LayerTypeSFlow }
   264  
   265  func (d *SFlowDatagram) Payload() []byte { return nil }
   266  
   267  func (d *SFlowDatagram) CanDecode() gopacket.LayerClass { return LayerTypeSFlow }
   268  
   269  func (d *SFlowDatagram) NextLayerType() gopacket.LayerType { return gopacket.LayerTypePayload }
   270  
   271  // SFlowIPType determines what form the IP address being decoded will
   272  // take. This is an XDR union type allowing for both IPv4 and IPv6
   273  type SFlowIPType uint32
   274  
   275  const (
   276  	SFlowIPv4 SFlowIPType = 1
   277  	SFlowIPv6 SFlowIPType = 2
   278  )
   279  
   280  func (s SFlowIPType) String() string {
   281  	switch s {
   282  	case SFlowIPv4:
   283  		return "IPv4"
   284  	case SFlowIPv6:
   285  		return "IPv6"
   286  	default:
   287  		return ""
   288  	}
   289  }
   290  
   291  func (s SFlowIPType) Length() int {
   292  	switch s {
   293  	case SFlowIPv4:
   294  		return 4
   295  	case SFlowIPv6:
   296  		return 16
   297  	default:
   298  		return 0
   299  	}
   300  }
   301  
   302  func (s *SFlowDatagram) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   303  	var agentAddressType SFlowIPType
   304  
   305  	data, s.DatagramVersion = data[4:], binary.BigEndian.Uint32(data[:4])
   306  	data, agentAddressType = data[4:], SFlowIPType(binary.BigEndian.Uint32(data[:4]))
   307  	data, s.AgentAddress = data[agentAddressType.Length():], data[:agentAddressType.Length()]
   308  	data, s.SubAgentID = data[4:], binary.BigEndian.Uint32(data[:4])
   309  	data, s.SequenceNumber = data[4:], binary.BigEndian.Uint32(data[:4])
   310  	data, s.AgentUptime = data[4:], binary.BigEndian.Uint32(data[:4])
   311  	data, s.SampleCount = data[4:], binary.BigEndian.Uint32(data[:4])
   312  
   313  	if s.SampleCount < 1 {
   314  		return fmt.Errorf("SFlow Datagram has invalid sample length: %d", s.SampleCount)
   315  	}
   316  	for i := uint32(0); i < s.SampleCount; i++ {
   317  		sdf := SFlowDataFormat(binary.BigEndian.Uint32(data[:4]))
   318  		_, sampleType := sdf.decode()
   319  		switch sampleType {
   320  		case SFlowTypeFlowSample:
   321  			if flowSample, err := decodeFlowSample(&data, false); err == nil {
   322  				s.FlowSamples = append(s.FlowSamples, flowSample)
   323  			} else {
   324  				return err
   325  			}
   326  		case SFlowTypeCounterSample:
   327  			if counterSample, err := decodeCounterSample(&data, false); err == nil {
   328  				s.CounterSamples = append(s.CounterSamples, counterSample)
   329  			} else {
   330  				return err
   331  			}
   332  		case SFlowTypeExpandedFlowSample:
   333  			if flowSample, err := decodeFlowSample(&data, true); err == nil {
   334  				s.FlowSamples = append(s.FlowSamples, flowSample)
   335  			} else {
   336  				return err
   337  			}
   338  		case SFlowTypeExpandedCounterSample:
   339  			if counterSample, err := decodeCounterSample(&data, true); err == nil {
   340  				s.CounterSamples = append(s.CounterSamples, counterSample)
   341  			} else {
   342  				return err
   343  			}
   344  
   345  		default:
   346  			return fmt.Errorf("Unsupported SFlow sample type %d", sampleType)
   347  		}
   348  	}
   349  	return nil
   350  }
   351  
   352  // SFlowFlowSample represents a sampled packet and contains
   353  // one or more records describing the packet
   354  type SFlowFlowSample struct {
   355  	EnterpriseID          SFlowEnterpriseID
   356  	Format                SFlowSampleType
   357  	SampleLength          uint32
   358  	SequenceNumber        uint32
   359  	SourceIDClass         SFlowSourceFormat
   360  	SourceIDIndex         SFlowSourceValue
   361  	SamplingRate          uint32
   362  	SamplePool            uint32
   363  	Dropped               uint32
   364  	InputInterfaceFormat  uint32
   365  	InputInterface        uint32
   366  	OutputInterfaceFormat uint32
   367  	OutputInterface       uint32
   368  	RecordCount           uint32
   369  	Records               []SFlowRecord
   370  }
   371  
   372  // Flow samples have the following structure. Note
   373  // the bit fields to encode the Enterprise ID and the
   374  // Flow record format: type 1
   375  
   376  //	  0                      15                      31
   377  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   378  //	  |      20 bit Interprise (0)     |12 bit format |
   379  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   380  //	  |                  sample length                |
   381  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   382  //	  |          int sample sequence number           |
   383  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   384  //	  |id type |       src id index value             |
   385  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   386  //	  |               int sampling rate               |
   387  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   388  //	  |                int sample pool                |
   389  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   390  //	  |                    int drops                  |
   391  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   392  //	  |                 int input ifIndex             |
   393  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   394  //	  |                int output ifIndex             |
   395  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   396  //	  |               int number of records           |
   397  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   398  //	  /                   flow records                /
   399  //	  /                                               /
   400  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   401  
   402  // Flow samples have the following structure.
   403  // Flow record format: type 3
   404  
   405  //	  0                      15                      31
   406  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   407  //	  |      20 bit Interprise (0)     |12 bit format |
   408  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   409  //	  |                  sample length                |
   410  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   411  //	  |          int sample sequence number           |
   412  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   413  //	  |               int src id type                 |
   414  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   415  //	  |             int src id index value            |
   416  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   417  //	  |               int sampling rate               |
   418  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   419  //	  |                int sample pool                |
   420  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   421  //	  |                    int drops                  |
   422  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   423  //	  |           int input interface format          |
   424  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   425  //	  |           int input interface value           |
   426  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   427  //	  |           int output interface format         |
   428  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   429  //	  |           int output interface value          |
   430  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   431  //	  |               int number of records           |
   432  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   433  //	  /                   flow records                /
   434  //	  /                                               /
   435  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   436  
   437  type SFlowFlowDataFormat uint32
   438  
   439  func (fdf SFlowFlowDataFormat) decode() (SFlowEnterpriseID, SFlowFlowRecordType) {
   440  	leftField := fdf >> 12
   441  	rightField := uint32(0xFFF) & uint32(fdf)
   442  	return SFlowEnterpriseID(leftField), SFlowFlowRecordType(rightField)
   443  }
   444  
   445  func (fs SFlowFlowSample) GetRecords() []SFlowRecord {
   446  	return fs.Records
   447  }
   448  
   449  func (fs SFlowFlowSample) GetType() SFlowSampleType {
   450  	return SFlowTypeFlowSample
   451  }
   452  
   453  func skipRecord(data *[]byte) {
   454  	recordLength := int(binary.BigEndian.Uint32((*data)[4:]))
   455  	*data = (*data)[(recordLength+((4-recordLength)%4))+8:]
   456  }
   457  
   458  func decodeFlowSample(data *[]byte, expanded bool) (SFlowFlowSample, error) {
   459  	s := SFlowFlowSample{}
   460  	var sdf SFlowDataFormat
   461  	*data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
   462  	var sdc SFlowDataSource
   463  
   464  	s.EnterpriseID, s.Format = sdf.decode()
   465  	if len(*data) < 4 {
   466  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   467  	}
   468  	*data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   469  	if len(*data) < 4 {
   470  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   471  	}
   472  	*data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   473  	if expanded {
   474  		if len(*data) < 4 {
   475  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   476  		}
   477  		*data, s.SourceIDClass = (*data)[4:], SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4]))
   478  		if len(*data) < 4 {
   479  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   480  		}
   481  		*data, s.SourceIDIndex = (*data)[4:], SFlowSourceValue(binary.BigEndian.Uint32((*data)[:4]))
   482  	} else {
   483  		if len(*data) < 4 {
   484  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   485  		}
   486  		*data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
   487  		s.SourceIDClass, s.SourceIDIndex = sdc.decode()
   488  	}
   489  	if len(*data) < 4 {
   490  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   491  	}
   492  	*data, s.SamplingRate = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   493  	if len(*data) < 4 {
   494  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   495  	}
   496  	*data, s.SamplePool = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   497  	if len(*data) < 4 {
   498  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   499  	}
   500  	*data, s.Dropped = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   501  
   502  	if expanded {
   503  		if len(*data) < 4 {
   504  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   505  		}
   506  		*data, s.InputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   507  		if len(*data) < 4 {
   508  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   509  		}
   510  		*data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   511  		if len(*data) < 4 {
   512  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   513  		}
   514  		*data, s.OutputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   515  		if len(*data) < 4 {
   516  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   517  		}
   518  		*data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   519  	} else {
   520  		if len(*data) < 4 {
   521  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   522  		}
   523  		*data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   524  		if len(*data) < 4 {
   525  			return SFlowFlowSample{}, errors.New("ethernet counters too small")
   526  		}
   527  		*data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   528  	}
   529  	if len(*data) < 4 {
   530  		return SFlowFlowSample{}, errors.New("ethernet counters too small")
   531  	}
   532  	*data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   533  
   534  	for i := uint32(0); i < s.RecordCount; i++ {
   535  		rdf := SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
   536  		enterpriseID, flowRecordType := rdf.decode()
   537  
   538  		// Try to decode when EnterpriseID is 0 signaling
   539  		// default sflow structs are used according specification
   540  		// Unexpected behavior detected for e.g. with pmacct
   541  		if enterpriseID == 0 {
   542  			switch flowRecordType {
   543  			case SFlowTypeRawPacketFlow:
   544  				if record, err := decodeRawPacketFlowRecord(data); err == nil {
   545  					s.Records = append(s.Records, record)
   546  				} else {
   547  					return s, err
   548  				}
   549  			case SFlowTypeExtendedUserFlow:
   550  				if record, err := decodeExtendedUserFlow(data); err == nil {
   551  					s.Records = append(s.Records, record)
   552  				} else {
   553  					return s, err
   554  				}
   555  			case SFlowTypeExtendedUrlFlow:
   556  				if record, err := decodeExtendedURLRecord(data); err == nil {
   557  					s.Records = append(s.Records, record)
   558  				} else {
   559  					return s, err
   560  				}
   561  			case SFlowTypeExtendedSwitchFlow:
   562  				if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
   563  					s.Records = append(s.Records, record)
   564  				} else {
   565  					return s, err
   566  				}
   567  			case SFlowTypeExtendedRouterFlow:
   568  				if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
   569  					s.Records = append(s.Records, record)
   570  				} else {
   571  					return s, err
   572  				}
   573  			case SFlowTypeExtendedGatewayFlow:
   574  				if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
   575  					s.Records = append(s.Records, record)
   576  				} else {
   577  					return s, err
   578  				}
   579  			case SFlowTypeEthernetFrameFlow:
   580  				if record, err := decodeEthernetFrameFlowRecord(data); err == nil {
   581  					s.Records = append(s.Records, record)
   582  				} else {
   583  					return s, err
   584  				}
   585  			case SFlowTypeIpv4Flow:
   586  				if record, err := decodeSFlowIpv4Record(data); err == nil {
   587  					s.Records = append(s.Records, record)
   588  				} else {
   589  					return s, err
   590  				}
   591  			case SFlowTypeIpv6Flow:
   592  				if record, err := decodeSFlowIpv6Record(data); err == nil {
   593  					s.Records = append(s.Records, record)
   594  				} else {
   595  					return s, err
   596  				}
   597  			case SFlowTypeExtendedMlpsFlow:
   598  				// TODO
   599  				skipRecord(data)
   600  				return s, errors.New("skipping TypeExtendedMlpsFlow")
   601  			case SFlowTypeExtendedNatFlow:
   602  				// TODO
   603  				skipRecord(data)
   604  				return s, errors.New("skipping TypeExtendedNatFlow")
   605  			case SFlowTypeExtendedMlpsTunnelFlow:
   606  				// TODO
   607  				skipRecord(data)
   608  				return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
   609  			case SFlowTypeExtendedMlpsVcFlow:
   610  				// TODO
   611  				skipRecord(data)
   612  				return s, errors.New("skipping TypeExtendedMlpsVcFlow")
   613  			case SFlowTypeExtendedMlpsFecFlow:
   614  				// TODO
   615  				skipRecord(data)
   616  				return s, errors.New("skipping TypeExtendedMlpsFecFlow")
   617  			case SFlowTypeExtendedMlpsLvpFecFlow:
   618  				// TODO
   619  				skipRecord(data)
   620  				return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
   621  			case SFlowTypeExtendedVlanFlow:
   622  				// TODO
   623  				skipRecord(data)
   624  				return s, errors.New("skipping TypeExtendedVlanFlow")
   625  			case SFlowTypeExtendedIpv4TunnelEgressFlow:
   626  				if record, err := decodeExtendedIpv4TunnelEgress(data); err == nil {
   627  					s.Records = append(s.Records, record)
   628  				} else {
   629  					return s, err
   630  				}
   631  			case SFlowTypeExtendedIpv4TunnelIngressFlow:
   632  				if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
   633  					s.Records = append(s.Records, record)
   634  				} else {
   635  					return s, err
   636  				}
   637  			case SFlowTypeExtendedIpv6TunnelEgressFlow:
   638  				if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
   639  					s.Records = append(s.Records, record)
   640  				} else {
   641  					return s, err
   642  				}
   643  			case SFlowTypeExtendedIpv6TunnelIngressFlow:
   644  				if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
   645  					s.Records = append(s.Records, record)
   646  				} else {
   647  					return s, err
   648  				}
   649  			case SFlowTypeExtendedDecapsulateEgressFlow:
   650  				if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
   651  					s.Records = append(s.Records, record)
   652  				} else {
   653  					return s, err
   654  				}
   655  			case SFlowTypeExtendedDecapsulateIngressFlow:
   656  				if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
   657  					s.Records = append(s.Records, record)
   658  				} else {
   659  					return s, err
   660  				}
   661  			case SFlowTypeExtendedVniEgressFlow:
   662  				if record, err := decodeExtendedVniEgress(data); err == nil {
   663  					s.Records = append(s.Records, record)
   664  				} else {
   665  					return s, err
   666  				}
   667  			case SFlowTypeExtendedVniIngressFlow:
   668  				if record, err := decodeExtendedVniIngress(data); err == nil {
   669  					s.Records = append(s.Records, record)
   670  				} else {
   671  					return s, err
   672  				}
   673  			default:
   674  				return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
   675  			}
   676  		} else {
   677  			skipRecord(data)
   678  		}
   679  	}
   680  	return s, nil
   681  }
   682  
   683  // Counter samples report information about various counter
   684  // objects. Typically these are items like IfInOctets, or
   685  // CPU / Memory stats, etc. SFlow will report these at regular
   686  // intervals as configured on the agent. If one were sufficiently
   687  // industrious, this could be used to replace the typical
   688  // SNMP polling used for such things.
   689  type SFlowCounterSample struct {
   690  	EnterpriseID   SFlowEnterpriseID
   691  	Format         SFlowSampleType
   692  	SampleLength   uint32
   693  	SequenceNumber uint32
   694  	SourceIDClass  SFlowSourceFormat
   695  	SourceIDIndex  SFlowSourceValue
   696  	RecordCount    uint32
   697  	Records        []SFlowRecord
   698  }
   699  
   700  // Counter samples have the following structure:
   701  
   702  // SFlowCounterDataFormat
   703  //
   704  //	  0                      15                      31
   705  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   706  //	  |          int sample sequence number           |
   707  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   708  //	  |id type |       src id index value             |
   709  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   710  //	  |               int number of records           |
   711  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   712  //	  /                counter records                /
   713  //	  /                                               /
   714  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   715  
   716  type SFlowCounterDataFormat uint32
   717  
   718  func (cdf SFlowCounterDataFormat) decode() (SFlowEnterpriseID, SFlowCounterRecordType) {
   719  	leftField := cdf >> 12
   720  	rightField := uint32(0xFFF) & uint32(cdf)
   721  	return SFlowEnterpriseID(leftField), SFlowCounterRecordType(rightField)
   722  }
   723  
   724  // GetRecords will return a slice of interface types
   725  // representing records. A type switch can be used to
   726  // get at the underlying SFlowCounterRecordType.
   727  func (cs SFlowCounterSample) GetRecords() []SFlowRecord {
   728  	return cs.Records
   729  }
   730  
   731  // GetType will report the type of sample. Only the
   732  // compact form of counter samples is supported
   733  func (cs SFlowCounterSample) GetType() SFlowSampleType {
   734  	return SFlowTypeCounterSample
   735  }
   736  
   737  type SFlowCounterRecordType uint32
   738  
   739  const (
   740  	SFlowTypeGenericInterfaceCounters   SFlowCounterRecordType = 1
   741  	SFlowTypeEthernetInterfaceCounters  SFlowCounterRecordType = 2
   742  	SFlowTypeTokenRingInterfaceCounters SFlowCounterRecordType = 3
   743  	SFlowType100BaseVGInterfaceCounters SFlowCounterRecordType = 4
   744  	SFlowTypeVLANCounters               SFlowCounterRecordType = 5
   745  	SFlowTypeLACPCounters               SFlowCounterRecordType = 7
   746  	SFlowTypeProcessorCounters          SFlowCounterRecordType = 1001
   747  	SFlowTypeOpenflowPortCounters       SFlowCounterRecordType = 1004
   748  	SFlowTypePORTNAMECounters           SFlowCounterRecordType = 1005
   749  	SFLowTypeAPPRESOURCESCounters       SFlowCounterRecordType = 2203
   750  	SFlowTypeOVSDPCounters              SFlowCounterRecordType = 2207
   751  )
   752  
   753  func (cr SFlowCounterRecordType) String() string {
   754  	switch cr {
   755  	case SFlowTypeGenericInterfaceCounters:
   756  		return "Generic Interface Counters"
   757  	case SFlowTypeEthernetInterfaceCounters:
   758  		return "Ethernet Interface Counters"
   759  	case SFlowTypeTokenRingInterfaceCounters:
   760  		return "Token Ring Interface Counters"
   761  	case SFlowType100BaseVGInterfaceCounters:
   762  		return "100BaseVG Interface Counters"
   763  	case SFlowTypeVLANCounters:
   764  		return "VLAN Counters"
   765  	case SFlowTypeLACPCounters:
   766  		return "LACP Counters"
   767  	case SFlowTypeProcessorCounters:
   768  		return "Processor Counters"
   769  	case SFlowTypeOpenflowPortCounters:
   770  		return "Openflow Port Counters"
   771  	case SFlowTypePORTNAMECounters:
   772  		return "PORT NAME Counters"
   773  	case SFLowTypeAPPRESOURCESCounters:
   774  		return "App Resources Counters"
   775  	case SFlowTypeOVSDPCounters:
   776  		return "OVSDP Counters"
   777  	default:
   778  		return ""
   779  
   780  	}
   781  }
   782  
   783  func decodeCounterSample(data *[]byte, expanded bool) (SFlowCounterSample, error) {
   784  	s := SFlowCounterSample{}
   785  	var sdc SFlowDataSource
   786  	var sdce SFlowDataSourceExpanded
   787  	var sdf SFlowDataFormat
   788  
   789  	*data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
   790  	s.EnterpriseID, s.Format = sdf.decode()
   791  	*data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   792  	*data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   793  	if expanded {
   794  		*data, sdce = (*data)[8:], SFlowDataSourceExpanded{SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4])), SFlowSourceValue(binary.BigEndian.Uint32((*data)[4:8]))}
   795  		s.SourceIDClass, s.SourceIDIndex = sdce.decode()
   796  	} else {
   797  		*data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
   798  		s.SourceIDClass, s.SourceIDIndex = sdc.decode()
   799  	}
   800  	*data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
   801  
   802  	for i := uint32(0); i < s.RecordCount; i++ {
   803  		cdf := SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
   804  		_, counterRecordType := cdf.decode()
   805  		switch counterRecordType {
   806  		case SFlowTypeGenericInterfaceCounters:
   807  			if record, err := decodeGenericInterfaceCounters(data); err == nil {
   808  				s.Records = append(s.Records, record)
   809  			} else {
   810  				return s, err
   811  			}
   812  		case SFlowTypeEthernetInterfaceCounters:
   813  			if record, err := decodeEthernetCounters(data); err == nil {
   814  				s.Records = append(s.Records, record)
   815  			} else {
   816  				return s, err
   817  			}
   818  		case SFlowTypeTokenRingInterfaceCounters:
   819  			skipRecord(data)
   820  			return s, errors.New("skipping TypeTokenRingInterfaceCounters")
   821  		case SFlowType100BaseVGInterfaceCounters:
   822  			skipRecord(data)
   823  			return s, errors.New("skipping Type100BaseVGInterfaceCounters")
   824  		case SFlowTypeVLANCounters:
   825  			if record, err := decodeVLANCounters(data); err == nil {
   826  				s.Records = append(s.Records, record)
   827  			} else {
   828  				return s, err
   829  			}
   830  		case SFlowTypeLACPCounters:
   831  			if record, err := decodeLACPCounters(data); err == nil {
   832  				s.Records = append(s.Records, record)
   833  			} else {
   834  				return s, err
   835  			}
   836  		case SFlowTypeProcessorCounters:
   837  			if record, err := decodeProcessorCounters(data); err == nil {
   838  				s.Records = append(s.Records, record)
   839  			} else {
   840  				return s, err
   841  			}
   842  		case SFlowTypeOpenflowPortCounters:
   843  			if record, err := decodeOpenflowportCounters(data); err == nil {
   844  				s.Records = append(s.Records, record)
   845  			} else {
   846  				return s, err
   847  			}
   848  		case SFlowTypePORTNAMECounters:
   849  			if record, err := decodePortnameCounters(data); err == nil {
   850  				s.Records = append(s.Records, record)
   851  			} else {
   852  				return s, err
   853  			}
   854  		case SFLowTypeAPPRESOURCESCounters:
   855  			if record, err := decodeAppresourcesCounters(data); err == nil {
   856  				s.Records = append(s.Records, record)
   857  			} else {
   858  				return s, err
   859  			}
   860  		case SFlowTypeOVSDPCounters:
   861  			if record, err := decodeOVSDPCounters(data); err == nil {
   862  				s.Records = append(s.Records, record)
   863  			} else {
   864  				return s, err
   865  			}
   866  		default:
   867  			return s, fmt.Errorf("Invalid counter record type: %d", counterRecordType)
   868  		}
   869  	}
   870  	return s, nil
   871  }
   872  
   873  // SFlowBaseFlowRecord holds the fields common to all records
   874  // of type SFlowFlowRecordType
   875  type SFlowBaseFlowRecord struct {
   876  	EnterpriseID   SFlowEnterpriseID
   877  	Format         SFlowFlowRecordType
   878  	FlowDataLength uint32
   879  }
   880  
   881  func (bfr SFlowBaseFlowRecord) GetType() SFlowFlowRecordType {
   882  	return bfr.Format
   883  }
   884  
   885  // SFlowFlowRecordType denotes what kind of Flow Record is
   886  // represented. See RFC 3176
   887  type SFlowFlowRecordType uint32
   888  
   889  const (
   890  	SFlowTypeRawPacketFlow                  SFlowFlowRecordType = 1
   891  	SFlowTypeEthernetFrameFlow              SFlowFlowRecordType = 2
   892  	SFlowTypeIpv4Flow                       SFlowFlowRecordType = 3
   893  	SFlowTypeIpv6Flow                       SFlowFlowRecordType = 4
   894  	SFlowTypeExtendedSwitchFlow             SFlowFlowRecordType = 1001
   895  	SFlowTypeExtendedRouterFlow             SFlowFlowRecordType = 1002
   896  	SFlowTypeExtendedGatewayFlow            SFlowFlowRecordType = 1003
   897  	SFlowTypeExtendedUserFlow               SFlowFlowRecordType = 1004
   898  	SFlowTypeExtendedUrlFlow                SFlowFlowRecordType = 1005
   899  	SFlowTypeExtendedMlpsFlow               SFlowFlowRecordType = 1006
   900  	SFlowTypeExtendedNatFlow                SFlowFlowRecordType = 1007
   901  	SFlowTypeExtendedMlpsTunnelFlow         SFlowFlowRecordType = 1008
   902  	SFlowTypeExtendedMlpsVcFlow             SFlowFlowRecordType = 1009
   903  	SFlowTypeExtendedMlpsFecFlow            SFlowFlowRecordType = 1010
   904  	SFlowTypeExtendedMlpsLvpFecFlow         SFlowFlowRecordType = 1011
   905  	SFlowTypeExtendedVlanFlow               SFlowFlowRecordType = 1012
   906  	SFlowTypeExtendedIpv4TunnelEgressFlow   SFlowFlowRecordType = 1023
   907  	SFlowTypeExtendedIpv4TunnelIngressFlow  SFlowFlowRecordType = 1024
   908  	SFlowTypeExtendedIpv6TunnelEgressFlow   SFlowFlowRecordType = 1025
   909  	SFlowTypeExtendedIpv6TunnelIngressFlow  SFlowFlowRecordType = 1026
   910  	SFlowTypeExtendedDecapsulateEgressFlow  SFlowFlowRecordType = 1027
   911  	SFlowTypeExtendedDecapsulateIngressFlow SFlowFlowRecordType = 1028
   912  	SFlowTypeExtendedVniEgressFlow          SFlowFlowRecordType = 1029
   913  	SFlowTypeExtendedVniIngressFlow         SFlowFlowRecordType = 1030
   914  )
   915  
   916  func (rt SFlowFlowRecordType) String() string {
   917  	switch rt {
   918  	case SFlowTypeRawPacketFlow:
   919  		return "Raw Packet Flow Record"
   920  	case SFlowTypeEthernetFrameFlow:
   921  		return "Ethernet Frame Flow Record"
   922  	case SFlowTypeIpv4Flow:
   923  		return "IPv4 Flow Record"
   924  	case SFlowTypeIpv6Flow:
   925  		return "IPv6 Flow Record"
   926  	case SFlowTypeExtendedSwitchFlow:
   927  		return "Extended Switch Flow Record"
   928  	case SFlowTypeExtendedRouterFlow:
   929  		return "Extended Router Flow Record"
   930  	case SFlowTypeExtendedGatewayFlow:
   931  		return "Extended Gateway Flow Record"
   932  	case SFlowTypeExtendedUserFlow:
   933  		return "Extended User Flow Record"
   934  	case SFlowTypeExtendedUrlFlow:
   935  		return "Extended URL Flow Record"
   936  	case SFlowTypeExtendedMlpsFlow:
   937  		return "Extended MPLS Flow Record"
   938  	case SFlowTypeExtendedNatFlow:
   939  		return "Extended NAT Flow Record"
   940  	case SFlowTypeExtendedMlpsTunnelFlow:
   941  		return "Extended MPLS Tunnel Flow Record"
   942  	case SFlowTypeExtendedMlpsVcFlow:
   943  		return "Extended MPLS VC Flow Record"
   944  	case SFlowTypeExtendedMlpsFecFlow:
   945  		return "Extended MPLS FEC Flow Record"
   946  	case SFlowTypeExtendedMlpsLvpFecFlow:
   947  		return "Extended MPLS LVP FEC Flow Record"
   948  	case SFlowTypeExtendedVlanFlow:
   949  		return "Extended VLAN Flow Record"
   950  	case SFlowTypeExtendedIpv4TunnelEgressFlow:
   951  		return "Extended IPv4 Tunnel Egress Record"
   952  	case SFlowTypeExtendedIpv4TunnelIngressFlow:
   953  		return "Extended IPv4 Tunnel Ingress Record"
   954  	case SFlowTypeExtendedIpv6TunnelEgressFlow:
   955  		return "Extended IPv6 Tunnel Egress Record"
   956  	case SFlowTypeExtendedIpv6TunnelIngressFlow:
   957  		return "Extended IPv6 Tunnel Ingress Record"
   958  	case SFlowTypeExtendedDecapsulateEgressFlow:
   959  		return "Extended Decapsulate Egress Record"
   960  	case SFlowTypeExtendedDecapsulateIngressFlow:
   961  		return "Extended Decapsulate Ingress Record"
   962  	case SFlowTypeExtendedVniEgressFlow:
   963  		return "Extended VNI Ingress Record"
   964  	case SFlowTypeExtendedVniIngressFlow:
   965  		return "Extended VNI Ingress Record"
   966  	default:
   967  		return ""
   968  	}
   969  }
   970  
   971  // SFlowRawPacketFlowRecords hold information about a sampled
   972  // packet grabbed as it transited the agent. This is
   973  // perhaps the most useful and interesting record type,
   974  // as it holds the headers of the sampled packet and
   975  // can be used to build up a complete picture of the
   976  // traffic patterns on a network.
   977  //
   978  // The raw packet header is sent back into gopacket for
   979  // decoding, and the resulting gopackt.Packet is stored
   980  // in the Header member
   981  type SFlowRawPacketFlowRecord struct {
   982  	SFlowBaseFlowRecord
   983  	HeaderProtocol SFlowRawHeaderProtocol
   984  	FrameLength    uint32
   985  	PayloadRemoved uint32
   986  	HeaderLength   uint32
   987  	Header         gopacket.Packet
   988  }
   989  
   990  // Raw packet record types have the following structure:
   991  //
   992  //	  0                      15                      31
   993  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   994  //	  |      20 bit Interprise (0)     |12 bit format |
   995  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   996  //	  |                  record length                |
   997  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   998  //	  |                 Header Protocol               |
   999  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1000  //	  |                 Frame Length                  |
  1001  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1002  //	  |                 Payload Removed               |
  1003  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1004  //	  |                 Header Length                 |
  1005  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1006  //	  \                     Header                    \
  1007  //	  \                                               \
  1008  //	  \                                               \
  1009  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1010  
  1011  type SFlowRawHeaderProtocol uint32
  1012  
  1013  const (
  1014  	SFlowProtoEthernet   SFlowRawHeaderProtocol = 1
  1015  	SFlowProtoISO88024   SFlowRawHeaderProtocol = 2
  1016  	SFlowProtoISO88025   SFlowRawHeaderProtocol = 3
  1017  	SFlowProtoFDDI       SFlowRawHeaderProtocol = 4
  1018  	SFlowProtoFrameRelay SFlowRawHeaderProtocol = 5
  1019  	SFlowProtoX25        SFlowRawHeaderProtocol = 6
  1020  	SFlowProtoPPP        SFlowRawHeaderProtocol = 7
  1021  	SFlowProtoSMDS       SFlowRawHeaderProtocol = 8
  1022  	SFlowProtoAAL5       SFlowRawHeaderProtocol = 9
  1023  	SFlowProtoAAL5_IP    SFlowRawHeaderProtocol = 10 /* e.g. Cisco AAL5 mux */
  1024  	SFlowProtoIPv4       SFlowRawHeaderProtocol = 11
  1025  	SFlowProtoIPv6       SFlowRawHeaderProtocol = 12
  1026  	SFlowProtoMPLS       SFlowRawHeaderProtocol = 13
  1027  	SFlowProtoPOS        SFlowRawHeaderProtocol = 14 /* RFC 1662, 2615 */
  1028  )
  1029  
  1030  func (sfhp SFlowRawHeaderProtocol) String() string {
  1031  	switch sfhp {
  1032  	case SFlowProtoEthernet:
  1033  		return "ETHERNET-ISO88023"
  1034  	case SFlowProtoISO88024:
  1035  		return "ISO88024-TOKENBUS"
  1036  	case SFlowProtoISO88025:
  1037  		return "ISO88025-TOKENRING"
  1038  	case SFlowProtoFDDI:
  1039  		return "FDDI"
  1040  	case SFlowProtoFrameRelay:
  1041  		return "FRAME-RELAY"
  1042  	case SFlowProtoX25:
  1043  		return "X25"
  1044  	case SFlowProtoPPP:
  1045  		return "PPP"
  1046  	case SFlowProtoSMDS:
  1047  		return "SMDS"
  1048  	case SFlowProtoAAL5:
  1049  		return "AAL5"
  1050  	case SFlowProtoAAL5_IP:
  1051  		return "AAL5-IP"
  1052  	case SFlowProtoIPv4:
  1053  		return "IPv4"
  1054  	case SFlowProtoIPv6:
  1055  		return "IPv6"
  1056  	case SFlowProtoMPLS:
  1057  		return "MPLS"
  1058  	case SFlowProtoPOS:
  1059  		return "POS"
  1060  	}
  1061  	return "UNKNOWN"
  1062  }
  1063  
  1064  func decodeRawPacketFlowRecord(data *[]byte) (SFlowRawPacketFlowRecord, error) {
  1065  	rec := SFlowRawPacketFlowRecord{}
  1066  	header := []byte{}
  1067  	var fdf SFlowFlowDataFormat
  1068  
  1069  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1070  	rec.EnterpriseID, rec.Format = fdf.decode()
  1071  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1072  	*data, rec.HeaderProtocol = (*data)[4:], SFlowRawHeaderProtocol(binary.BigEndian.Uint32((*data)[:4]))
  1073  	*data, rec.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1074  	*data, rec.PayloadRemoved = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1075  	*data, rec.HeaderLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1076  	headerLenWithPadding := int(rec.HeaderLength + ((4 - rec.HeaderLength) % 4))
  1077  	*data, header = (*data)[headerLenWithPadding:], (*data)[:headerLenWithPadding]
  1078  	rec.Header = gopacket.NewPacket(header, LayerTypeEthernet, gopacket.Default)
  1079  	return rec, nil
  1080  }
  1081  
  1082  // SFlowExtendedSwitchFlowRecord give additional information
  1083  // about the sampled packet if it's available. It's mainly
  1084  // useful for getting at the incoming and outgoing VLANs
  1085  // An agent may or may not provide this information.
  1086  type SFlowExtendedSwitchFlowRecord struct {
  1087  	SFlowBaseFlowRecord
  1088  	IncomingVLAN         uint32
  1089  	IncomingVLANPriority uint32
  1090  	OutgoingVLAN         uint32
  1091  	OutgoingVLANPriority uint32
  1092  }
  1093  
  1094  // Extended switch records have the following structure:
  1095  //
  1096  //	  0                      15                      31
  1097  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1098  //	  |      20 bit Interprise (0)     |12 bit format |
  1099  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1100  //	  |                  record length                |
  1101  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1102  //	  |                   Incoming VLAN               |
  1103  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1104  //	  |                Incoming VLAN Priority         |
  1105  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1106  //	  |                   Outgoing VLAN               |
  1107  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1108  //	  |                Outgoing VLAN Priority         |
  1109  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1110  
  1111  func decodeExtendedSwitchFlowRecord(data *[]byte) (SFlowExtendedSwitchFlowRecord, error) {
  1112  	es := SFlowExtendedSwitchFlowRecord{}
  1113  	var fdf SFlowFlowDataFormat
  1114  
  1115  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1116  	es.EnterpriseID, es.Format = fdf.decode()
  1117  	*data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1118  	*data, es.IncomingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1119  	*data, es.IncomingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1120  	*data, es.OutgoingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1121  	*data, es.OutgoingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1122  	return es, nil
  1123  }
  1124  
  1125  // SFlowExtendedRouterFlowRecord gives additional information
  1126  // about the layer 3 routing information used to forward
  1127  // the packet
  1128  type SFlowExtendedRouterFlowRecord struct {
  1129  	SFlowBaseFlowRecord
  1130  	NextHop                net.IP
  1131  	NextHopSourceMask      uint32
  1132  	NextHopDestinationMask uint32
  1133  }
  1134  
  1135  // Extended router records have the following structure:
  1136  //
  1137  //	  0                      15                      31
  1138  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1139  //	  |      20 bit Interprise (0)     |12 bit format |
  1140  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1141  //	  |                  record length                |
  1142  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1143  //	  |   IP version of next hop router (1=v4|2=v6)   |
  1144  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1145  //	  /     Next Hop address (v4=4byte|v6=16byte)     /
  1146  //	  /                                               /
  1147  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1148  //	  |              Next Hop Source Mask             |
  1149  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1150  //	  |              Next Hop Destination Mask        |
  1151  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1152  
  1153  func decodeExtendedRouterFlowRecord(data *[]byte) (SFlowExtendedRouterFlowRecord, error) {
  1154  	er := SFlowExtendedRouterFlowRecord{}
  1155  	var fdf SFlowFlowDataFormat
  1156  	var extendedRouterAddressType SFlowIPType
  1157  
  1158  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1159  	er.EnterpriseID, er.Format = fdf.decode()
  1160  	*data, er.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1161  	*data, extendedRouterAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
  1162  	*data, er.NextHop = (*data)[extendedRouterAddressType.Length():], (*data)[:extendedRouterAddressType.Length()]
  1163  	*data, er.NextHopSourceMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1164  	*data, er.NextHopDestinationMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1165  	return er, nil
  1166  }
  1167  
  1168  // SFlowExtendedGatewayFlowRecord describes information treasured by
  1169  // nework engineers everywhere: AS path information listing which
  1170  // BGP peer sent the packet, and various other BGP related info.
  1171  // This information is vital because it gives a picture of how much
  1172  // traffic is being sent from / received by various BGP peers.
  1173  
  1174  // Extended gateway records have the following structure:
  1175  //
  1176  //	  0                      15                      31
  1177  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1178  //	  |      20 bit Interprise (0)     |12 bit format |
  1179  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1180  //	  |                  record length                |
  1181  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1182  //	  |   IP version of next hop router (1=v4|2=v6)   |
  1183  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1184  //	  /     Next Hop address (v4=4byte|v6=16byte)     /
  1185  //	  /                                               /
  1186  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1187  //	  |                       AS                      |
  1188  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1189  //	  |                  Source AS                    |
  1190  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1191  //	  |                    Peer AS                    |
  1192  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1193  //	  |                  AS Path Count                |
  1194  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1195  //	  /                AS Path / Sequence             /
  1196  //	  /                                               /
  1197  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1198  //	  /                   Communities                 /
  1199  //	  /                                               /
  1200  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1201  //	  |                    Local Pref                 |
  1202  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1203  
  1204  // AS Path / Sequence:
  1205  
  1206  //	  0                      15                      31
  1207  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1208  //	  |     AS Source Type (Path=1 / Sequence=2)      |
  1209  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1210  //	  |              Path / Sequence length           |
  1211  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1212  //	  /              Path / Sequence Members          /
  1213  //	  /                                               /
  1214  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1215  
  1216  // Communities:
  1217  
  1218  //	  0                      15                      31
  1219  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1220  //	  |                communitiy length              |
  1221  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1222  //	  /              communitiy Members               /
  1223  //	  /                                               /
  1224  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1225  
  1226  type SFlowExtendedGatewayFlowRecord struct {
  1227  	SFlowBaseFlowRecord
  1228  	NextHop     net.IP
  1229  	AS          uint32
  1230  	SourceAS    uint32
  1231  	PeerAS      uint32
  1232  	ASPathCount uint32
  1233  	ASPath      []SFlowASDestination
  1234  	Communities []uint32
  1235  	LocalPref   uint32
  1236  }
  1237  
  1238  type SFlowASPathType uint32
  1239  
  1240  const (
  1241  	SFlowASSet      SFlowASPathType = 1
  1242  	SFlowASSequence SFlowASPathType = 2
  1243  )
  1244  
  1245  func (apt SFlowASPathType) String() string {
  1246  	switch apt {
  1247  	case SFlowASSet:
  1248  		return "AS Set"
  1249  	case SFlowASSequence:
  1250  		return "AS Sequence"
  1251  	default:
  1252  		return ""
  1253  	}
  1254  }
  1255  
  1256  type SFlowASDestination struct {
  1257  	Type    SFlowASPathType
  1258  	Count   uint32
  1259  	Members []uint32
  1260  }
  1261  
  1262  func (asd SFlowASDestination) String() string {
  1263  	switch asd.Type {
  1264  	case SFlowASSet:
  1265  		return fmt.Sprint("AS Set:", asd.Members)
  1266  	case SFlowASSequence:
  1267  		return fmt.Sprint("AS Sequence:", asd.Members)
  1268  	default:
  1269  		return ""
  1270  	}
  1271  }
  1272  
  1273  func (ad *SFlowASDestination) decodePath(data *[]byte) {
  1274  	*data, ad.Type = (*data)[4:], SFlowASPathType(binary.BigEndian.Uint32((*data)[:4]))
  1275  	*data, ad.Count = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1276  	ad.Members = make([]uint32, ad.Count)
  1277  	for i := uint32(0); i < ad.Count; i++ {
  1278  		var member uint32
  1279  		*data, member = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1280  		ad.Members[i] = member
  1281  	}
  1282  }
  1283  
  1284  func decodeExtendedGatewayFlowRecord(data *[]byte) (SFlowExtendedGatewayFlowRecord, error) {
  1285  	eg := SFlowExtendedGatewayFlowRecord{}
  1286  	var fdf SFlowFlowDataFormat
  1287  	var extendedGatewayAddressType SFlowIPType
  1288  	var communitiesLength uint32
  1289  	var community uint32
  1290  
  1291  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1292  	eg.EnterpriseID, eg.Format = fdf.decode()
  1293  	*data, eg.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1294  	*data, extendedGatewayAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
  1295  	*data, eg.NextHop = (*data)[extendedGatewayAddressType.Length():], (*data)[:extendedGatewayAddressType.Length()]
  1296  	*data, eg.AS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1297  	*data, eg.SourceAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1298  	*data, eg.PeerAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1299  	*data, eg.ASPathCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1300  	for i := uint32(0); i < eg.ASPathCount; i++ {
  1301  		asPath := SFlowASDestination{}
  1302  		asPath.decodePath(data)
  1303  		eg.ASPath = append(eg.ASPath, asPath)
  1304  	}
  1305  	*data, communitiesLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1306  	eg.Communities = make([]uint32, communitiesLength)
  1307  	for j := uint32(0); j < communitiesLength; j++ {
  1308  		*data, community = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1309  		eg.Communities[j] = community
  1310  	}
  1311  	*data, eg.LocalPref = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1312  	return eg, nil
  1313  }
  1314  
  1315  // **************************************************
  1316  //  Extended URL Flow Record
  1317  // **************************************************
  1318  //
  1319  //	  0                      15                      31
  1320  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1321  //	  |      20 bit Interprise (0)     |12 bit format |
  1322  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1323  //	  |                  record length                |
  1324  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1325  //	  |                   direction                   |
  1326  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1327  //	  |                      URL                      |
  1328  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1329  //	  |                      Host                     |
  1330  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1331  
  1332  type SFlowURLDirection uint32
  1333  
  1334  const (
  1335  	SFlowURLsrc SFlowURLDirection = 1
  1336  	SFlowURLdst SFlowURLDirection = 2
  1337  )
  1338  
  1339  func (urld SFlowURLDirection) String() string {
  1340  	switch urld {
  1341  	case SFlowURLsrc:
  1342  		return "Source address is the server"
  1343  	case SFlowURLdst:
  1344  		return "Destination address is the server"
  1345  	default:
  1346  		return ""
  1347  	}
  1348  }
  1349  
  1350  type SFlowExtendedURLRecord struct {
  1351  	SFlowBaseFlowRecord
  1352  	Direction SFlowURLDirection
  1353  	URL       string
  1354  	Host      string
  1355  }
  1356  
  1357  func decodeExtendedURLRecord(data *[]byte) (SFlowExtendedURLRecord, error) {
  1358  	eur := SFlowExtendedURLRecord{}
  1359  	var fdf SFlowFlowDataFormat
  1360  	var urlLen uint32
  1361  	var urlLenWithPad int
  1362  	var hostLen uint32
  1363  	var hostLenWithPad int
  1364  	var urlBytes []byte
  1365  	var hostBytes []byte
  1366  
  1367  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1368  	eur.EnterpriseID, eur.Format = fdf.decode()
  1369  	*data, eur.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1370  	*data, eur.Direction = (*data)[4:], SFlowURLDirection(binary.BigEndian.Uint32((*data)[:4]))
  1371  	*data, urlLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1372  	urlLenWithPad = int(urlLen + ((4 - urlLen) % 4))
  1373  	*data, urlBytes = (*data)[urlLenWithPad:], (*data)[:urlLenWithPad]
  1374  	eur.URL = string(urlBytes[:urlLen])
  1375  	*data, hostLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1376  	hostLenWithPad = int(hostLen + ((4 - hostLen) % 4))
  1377  	*data, hostBytes = (*data)[hostLenWithPad:], (*data)[:hostLenWithPad]
  1378  	eur.Host = string(hostBytes[:hostLen])
  1379  	return eur, nil
  1380  }
  1381  
  1382  // **************************************************
  1383  //  Extended User Flow Record
  1384  // **************************************************
  1385  //
  1386  //	  0                      15                      31
  1387  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1388  //	  |      20 bit Interprise (0)     |12 bit format |
  1389  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1390  //	  |                  record length                |
  1391  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1392  //	  |                Source Character Set           |
  1393  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1394  //	  |                 Source User Id                |
  1395  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1396  //	  |              Destination Character Set        |
  1397  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1398  //	  |               Destination User ID             |
  1399  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1400  
  1401  type SFlowExtendedUserFlow struct {
  1402  	SFlowBaseFlowRecord
  1403  	SourceCharSet      SFlowCharSet
  1404  	SourceUserID       string
  1405  	DestinationCharSet SFlowCharSet
  1406  	DestinationUserID  string
  1407  }
  1408  
  1409  type SFlowCharSet uint32
  1410  
  1411  const (
  1412  	SFlowCSunknown                 SFlowCharSet = 2
  1413  	SFlowCSASCII                   SFlowCharSet = 3
  1414  	SFlowCSISOLatin1               SFlowCharSet = 4
  1415  	SFlowCSISOLatin2               SFlowCharSet = 5
  1416  	SFlowCSISOLatin3               SFlowCharSet = 6
  1417  	SFlowCSISOLatin4               SFlowCharSet = 7
  1418  	SFlowCSISOLatinCyrillic        SFlowCharSet = 8
  1419  	SFlowCSISOLatinArabic          SFlowCharSet = 9
  1420  	SFlowCSISOLatinGreek           SFlowCharSet = 10
  1421  	SFlowCSISOLatinHebrew          SFlowCharSet = 11
  1422  	SFlowCSISOLatin5               SFlowCharSet = 12
  1423  	SFlowCSISOLatin6               SFlowCharSet = 13
  1424  	SFlowCSISOTextComm             SFlowCharSet = 14
  1425  	SFlowCSHalfWidthKatakana       SFlowCharSet = 15
  1426  	SFlowCSJISEncoding             SFlowCharSet = 16
  1427  	SFlowCSShiftJIS                SFlowCharSet = 17
  1428  	SFlowCSEUCPkdFmtJapanese       SFlowCharSet = 18
  1429  	SFlowCSEUCFixWidJapanese       SFlowCharSet = 19
  1430  	SFlowCSISO4UnitedKingdom       SFlowCharSet = 20
  1431  	SFlowCSISO11SwedishForNames    SFlowCharSet = 21
  1432  	SFlowCSISO15Italian            SFlowCharSet = 22
  1433  	SFlowCSISO17Spanish            SFlowCharSet = 23
  1434  	SFlowCSISO21German             SFlowCharSet = 24
  1435  	SFlowCSISO60DanishNorwegian    SFlowCharSet = 25
  1436  	SFlowCSISO69French             SFlowCharSet = 26
  1437  	SFlowCSISO10646UTF1            SFlowCharSet = 27
  1438  	SFlowCSISO646basic1983         SFlowCharSet = 28
  1439  	SFlowCSINVARIANT               SFlowCharSet = 29
  1440  	SFlowCSISO2IntlRefVersion      SFlowCharSet = 30
  1441  	SFlowCSNATSSEFI                SFlowCharSet = 31
  1442  	SFlowCSNATSSEFIADD             SFlowCharSet = 32
  1443  	SFlowCSNATSDANO                SFlowCharSet = 33
  1444  	SFlowCSNATSDANOADD             SFlowCharSet = 34
  1445  	SFlowCSISO10Swedish            SFlowCharSet = 35
  1446  	SFlowCSKSC56011987             SFlowCharSet = 36
  1447  	SFlowCSISO2022KR               SFlowCharSet = 37
  1448  	SFlowCSEUCKR                   SFlowCharSet = 38
  1449  	SFlowCSISO2022JP               SFlowCharSet = 39
  1450  	SFlowCSISO2022JP2              SFlowCharSet = 40
  1451  	SFlowCSISO13JISC6220jp         SFlowCharSet = 41
  1452  	SFlowCSISO14JISC6220ro         SFlowCharSet = 42
  1453  	SFlowCSISO16Portuguese         SFlowCharSet = 43
  1454  	SFlowCSISO18Greek7Old          SFlowCharSet = 44
  1455  	SFlowCSISO19LatinGreek         SFlowCharSet = 45
  1456  	SFlowCSISO25French             SFlowCharSet = 46
  1457  	SFlowCSISO27LatinGreek1        SFlowCharSet = 47
  1458  	SFlowCSISO5427Cyrillic         SFlowCharSet = 48
  1459  	SFlowCSISO42JISC62261978       SFlowCharSet = 49
  1460  	SFlowCSISO47BSViewdata         SFlowCharSet = 50
  1461  	SFlowCSISO49INIS               SFlowCharSet = 51
  1462  	SFlowCSISO50INIS8              SFlowCharSet = 52
  1463  	SFlowCSISO51INISCyrillic       SFlowCharSet = 53
  1464  	SFlowCSISO54271981             SFlowCharSet = 54
  1465  	SFlowCSISO5428Greek            SFlowCharSet = 55
  1466  	SFlowCSISO57GB1988             SFlowCharSet = 56
  1467  	SFlowCSISO58GB231280           SFlowCharSet = 57
  1468  	SFlowCSISO61Norwegian2         SFlowCharSet = 58
  1469  	SFlowCSISO70VideotexSupp1      SFlowCharSet = 59
  1470  	SFlowCSISO84Portuguese2        SFlowCharSet = 60
  1471  	SFlowCSISO85Spanish2           SFlowCharSet = 61
  1472  	SFlowCSISO86Hungarian          SFlowCharSet = 62
  1473  	SFlowCSISO87JISX0208           SFlowCharSet = 63
  1474  	SFlowCSISO88Greek7             SFlowCharSet = 64
  1475  	SFlowCSISO89ASMO449            SFlowCharSet = 65
  1476  	SFlowCSISO90                   SFlowCharSet = 66
  1477  	SFlowCSISO91JISC62291984a      SFlowCharSet = 67
  1478  	SFlowCSISO92JISC62991984b      SFlowCharSet = 68
  1479  	SFlowCSISO93JIS62291984badd    SFlowCharSet = 69
  1480  	SFlowCSISO94JIS62291984hand    SFlowCharSet = 70
  1481  	SFlowCSISO95JIS62291984handadd SFlowCharSet = 71
  1482  	SFlowCSISO96JISC62291984kana   SFlowCharSet = 72
  1483  	SFlowCSISO2033                 SFlowCharSet = 73
  1484  	SFlowCSISO99NAPLPS             SFlowCharSet = 74
  1485  	SFlowCSISO102T617bit           SFlowCharSet = 75
  1486  	SFlowCSISO103T618bit           SFlowCharSet = 76
  1487  	SFlowCSISO111ECMACyrillic      SFlowCharSet = 77
  1488  	SFlowCSa71                     SFlowCharSet = 78
  1489  	SFlowCSa72                     SFlowCharSet = 79
  1490  	SFlowCSISO123CSAZ24341985gr    SFlowCharSet = 80
  1491  	SFlowCSISO88596E               SFlowCharSet = 81
  1492  	SFlowCSISO88596I               SFlowCharSet = 82
  1493  	SFlowCSISO128T101G2            SFlowCharSet = 83
  1494  	SFlowCSISO88598E               SFlowCharSet = 84
  1495  	SFlowCSISO88598I               SFlowCharSet = 85
  1496  	SFlowCSISO139CSN369103         SFlowCharSet = 86
  1497  	SFlowCSISO141JUSIB1002         SFlowCharSet = 87
  1498  	SFlowCSISO143IECP271           SFlowCharSet = 88
  1499  	SFlowCSISO146Serbian           SFlowCharSet = 89
  1500  	SFlowCSISO147Macedonian        SFlowCharSet = 90
  1501  	SFlowCSISO150                  SFlowCharSet = 91
  1502  	SFlowCSISO151Cuba              SFlowCharSet = 92
  1503  	SFlowCSISO6937Add              SFlowCharSet = 93
  1504  	SFlowCSISO153GOST1976874       SFlowCharSet = 94
  1505  	SFlowCSISO8859Supp             SFlowCharSet = 95
  1506  	SFlowCSISO10367Box             SFlowCharSet = 96
  1507  	SFlowCSISO158Lap               SFlowCharSet = 97
  1508  	SFlowCSISO159JISX02121990      SFlowCharSet = 98
  1509  	SFlowCSISO646Danish            SFlowCharSet = 99
  1510  	SFlowCSUSDK                    SFlowCharSet = 100
  1511  	SFlowCSDKUS                    SFlowCharSet = 101
  1512  	SFlowCSKSC5636                 SFlowCharSet = 102
  1513  	SFlowCSUnicode11UTF7           SFlowCharSet = 103
  1514  	SFlowCSISO2022CN               SFlowCharSet = 104
  1515  	SFlowCSISO2022CNEXT            SFlowCharSet = 105
  1516  	SFlowCSUTF8                    SFlowCharSet = 106
  1517  	SFlowCSISO885913               SFlowCharSet = 109
  1518  	SFlowCSISO885914               SFlowCharSet = 110
  1519  	SFlowCSISO885915               SFlowCharSet = 111
  1520  	SFlowCSISO885916               SFlowCharSet = 112
  1521  	SFlowCSGBK                     SFlowCharSet = 113
  1522  	SFlowCSGB18030                 SFlowCharSet = 114
  1523  	SFlowCSOSDEBCDICDF0415         SFlowCharSet = 115
  1524  	SFlowCSOSDEBCDICDF03IRV        SFlowCharSet = 116
  1525  	SFlowCSOSDEBCDICDF041          SFlowCharSet = 117
  1526  	SFlowCSISO115481               SFlowCharSet = 118
  1527  	SFlowCSKZ1048                  SFlowCharSet = 119
  1528  	SFlowCSUnicode                 SFlowCharSet = 1000
  1529  	SFlowCSUCS4                    SFlowCharSet = 1001
  1530  	SFlowCSUnicodeASCII            SFlowCharSet = 1002
  1531  	SFlowCSUnicodeLatin1           SFlowCharSet = 1003
  1532  	SFlowCSUnicodeJapanese         SFlowCharSet = 1004
  1533  	SFlowCSUnicodeIBM1261          SFlowCharSet = 1005
  1534  	SFlowCSUnicodeIBM1268          SFlowCharSet = 1006
  1535  	SFlowCSUnicodeIBM1276          SFlowCharSet = 1007
  1536  	SFlowCSUnicodeIBM1264          SFlowCharSet = 1008
  1537  	SFlowCSUnicodeIBM1265          SFlowCharSet = 1009
  1538  	SFlowCSUnicode11               SFlowCharSet = 1010
  1539  	SFlowCSSCSU                    SFlowCharSet = 1011
  1540  	SFlowCSUTF7                    SFlowCharSet = 1012
  1541  	SFlowCSUTF16BE                 SFlowCharSet = 1013
  1542  	SFlowCSUTF16LE                 SFlowCharSet = 1014
  1543  	SFlowCSUTF16                   SFlowCharSet = 1015
  1544  	SFlowCSCESU8                   SFlowCharSet = 1016
  1545  	SFlowCSUTF32                   SFlowCharSet = 1017
  1546  	SFlowCSUTF32BE                 SFlowCharSet = 1018
  1547  	SFlowCSUTF32LE                 SFlowCharSet = 1019
  1548  	SFlowCSBOCU1                   SFlowCharSet = 1020
  1549  	SFlowCSWindows30Latin1         SFlowCharSet = 2000
  1550  	SFlowCSWindows31Latin1         SFlowCharSet = 2001
  1551  	SFlowCSWindows31Latin2         SFlowCharSet = 2002
  1552  	SFlowCSWindows31Latin5         SFlowCharSet = 2003
  1553  	SFlowCSHPRoman8                SFlowCharSet = 2004
  1554  	SFlowCSAdobeStandardEncoding   SFlowCharSet = 2005
  1555  	SFlowCSVenturaUS               SFlowCharSet = 2006
  1556  	SFlowCSVenturaInternational    SFlowCharSet = 2007
  1557  	SFlowCSDECMCS                  SFlowCharSet = 2008
  1558  	SFlowCSPC850Multilingual       SFlowCharSet = 2009
  1559  	SFlowCSPCp852                  SFlowCharSet = 2010
  1560  	SFlowCSPC8CodePage437          SFlowCharSet = 2011
  1561  	SFlowCSPC8DanishNorwegian      SFlowCharSet = 2012
  1562  	SFlowCSPC862LatinHebrew        SFlowCharSet = 2013
  1563  	SFlowCSPC8Turkish              SFlowCharSet = 2014
  1564  	SFlowCSIBMSymbols              SFlowCharSet = 2015
  1565  	SFlowCSIBMThai                 SFlowCharSet = 2016
  1566  	SFlowCSHPLegal                 SFlowCharSet = 2017
  1567  	SFlowCSHPPiFont                SFlowCharSet = 2018
  1568  	SFlowCSHPMath8                 SFlowCharSet = 2019
  1569  	SFlowCSHPPSMath                SFlowCharSet = 2020
  1570  	SFlowCSHPDesktop               SFlowCharSet = 2021
  1571  	SFlowCSVenturaMath             SFlowCharSet = 2022
  1572  	SFlowCSMicrosoftPublishing     SFlowCharSet = 2023
  1573  	SFlowCSWindows31J              SFlowCharSet = 2024
  1574  	SFlowCSGB2312                  SFlowCharSet = 2025
  1575  	SFlowCSBig5                    SFlowCharSet = 2026
  1576  	SFlowCSMacintosh               SFlowCharSet = 2027
  1577  	SFlowCSIBM037                  SFlowCharSet = 2028
  1578  	SFlowCSIBM038                  SFlowCharSet = 2029
  1579  	SFlowCSIBM273                  SFlowCharSet = 2030
  1580  	SFlowCSIBM274                  SFlowCharSet = 2031
  1581  	SFlowCSIBM275                  SFlowCharSet = 2032
  1582  	SFlowCSIBM277                  SFlowCharSet = 2033
  1583  	SFlowCSIBM278                  SFlowCharSet = 2034
  1584  	SFlowCSIBM280                  SFlowCharSet = 2035
  1585  	SFlowCSIBM281                  SFlowCharSet = 2036
  1586  	SFlowCSIBM284                  SFlowCharSet = 2037
  1587  	SFlowCSIBM285                  SFlowCharSet = 2038
  1588  	SFlowCSIBM290                  SFlowCharSet = 2039
  1589  	SFlowCSIBM297                  SFlowCharSet = 2040
  1590  	SFlowCSIBM420                  SFlowCharSet = 2041
  1591  	SFlowCSIBM423                  SFlowCharSet = 2042
  1592  	SFlowCSIBM424                  SFlowCharSet = 2043
  1593  	SFlowCSIBM500                  SFlowCharSet = 2044
  1594  	SFlowCSIBM851                  SFlowCharSet = 2045
  1595  	SFlowCSIBM855                  SFlowCharSet = 2046
  1596  	SFlowCSIBM857                  SFlowCharSet = 2047
  1597  	SFlowCSIBM860                  SFlowCharSet = 2048
  1598  	SFlowCSIBM861                  SFlowCharSet = 2049
  1599  	SFlowCSIBM863                  SFlowCharSet = 2050
  1600  	SFlowCSIBM864                  SFlowCharSet = 2051
  1601  	SFlowCSIBM865                  SFlowCharSet = 2052
  1602  	SFlowCSIBM868                  SFlowCharSet = 2053
  1603  	SFlowCSIBM869                  SFlowCharSet = 2054
  1604  	SFlowCSIBM870                  SFlowCharSet = 2055
  1605  	SFlowCSIBM871                  SFlowCharSet = 2056
  1606  	SFlowCSIBM880                  SFlowCharSet = 2057
  1607  	SFlowCSIBM891                  SFlowCharSet = 2058
  1608  	SFlowCSIBM903                  SFlowCharSet = 2059
  1609  	SFlowCSIBBM904                 SFlowCharSet = 2060
  1610  	SFlowCSIBM905                  SFlowCharSet = 2061
  1611  	SFlowCSIBM918                  SFlowCharSet = 2062
  1612  	SFlowCSIBM1026                 SFlowCharSet = 2063
  1613  	SFlowCSIBMEBCDICATDE           SFlowCharSet = 2064
  1614  	SFlowCSEBCDICATDEA             SFlowCharSet = 2065
  1615  	SFlowCSEBCDICCAFR              SFlowCharSet = 2066
  1616  	SFlowCSEBCDICDKNO              SFlowCharSet = 2067
  1617  	SFlowCSEBCDICDKNOA             SFlowCharSet = 2068
  1618  	SFlowCSEBCDICFISE              SFlowCharSet = 2069
  1619  	SFlowCSEBCDICFISEA             SFlowCharSet = 2070
  1620  	SFlowCSEBCDICFR                SFlowCharSet = 2071
  1621  	SFlowCSEBCDICIT                SFlowCharSet = 2072
  1622  	SFlowCSEBCDICPT                SFlowCharSet = 2073
  1623  	SFlowCSEBCDICES                SFlowCharSet = 2074
  1624  	SFlowCSEBCDICESA               SFlowCharSet = 2075
  1625  	SFlowCSEBCDICESS               SFlowCharSet = 2076
  1626  	SFlowCSEBCDICUK                SFlowCharSet = 2077
  1627  	SFlowCSEBCDICUS                SFlowCharSet = 2078
  1628  	SFlowCSUnknown8BiT             SFlowCharSet = 2079
  1629  	SFlowCSMnemonic                SFlowCharSet = 2080
  1630  	SFlowCSMnem                    SFlowCharSet = 2081
  1631  	SFlowCSVISCII                  SFlowCharSet = 2082
  1632  	SFlowCSVIQR                    SFlowCharSet = 2083
  1633  	SFlowCSKOI8R                   SFlowCharSet = 2084
  1634  	SFlowCSHZGB2312                SFlowCharSet = 2085
  1635  	SFlowCSIBM866                  SFlowCharSet = 2086
  1636  	SFlowCSPC775Baltic             SFlowCharSet = 2087
  1637  	SFlowCSKOI8U                   SFlowCharSet = 2088
  1638  	SFlowCSIBM00858                SFlowCharSet = 2089
  1639  	SFlowCSIBM00924                SFlowCharSet = 2090
  1640  	SFlowCSIBM01140                SFlowCharSet = 2091
  1641  	SFlowCSIBM01141                SFlowCharSet = 2092
  1642  	SFlowCSIBM01142                SFlowCharSet = 2093
  1643  	SFlowCSIBM01143                SFlowCharSet = 2094
  1644  	SFlowCSIBM01144                SFlowCharSet = 2095
  1645  	SFlowCSIBM01145                SFlowCharSet = 2096
  1646  	SFlowCSIBM01146                SFlowCharSet = 2097
  1647  	SFlowCSIBM01147                SFlowCharSet = 2098
  1648  	SFlowCSIBM01148                SFlowCharSet = 2099
  1649  	SFlowCSIBM01149                SFlowCharSet = 2100
  1650  	SFlowCSBig5HKSCS               SFlowCharSet = 2101
  1651  	SFlowCSIBM1047                 SFlowCharSet = 2102
  1652  	SFlowCSPTCP154                 SFlowCharSet = 2103
  1653  	SFlowCSAmiga1251               SFlowCharSet = 2104
  1654  	SFlowCSKOI7switched            SFlowCharSet = 2105
  1655  	SFlowCSBRF                     SFlowCharSet = 2106
  1656  	SFlowCSTSCII                   SFlowCharSet = 2107
  1657  	SFlowCSCP51932                 SFlowCharSet = 2108
  1658  	SFlowCSWindows874              SFlowCharSet = 2109
  1659  	SFlowCSWindows1250             SFlowCharSet = 2250
  1660  	SFlowCSWindows1251             SFlowCharSet = 2251
  1661  	SFlowCSWindows1252             SFlowCharSet = 2252
  1662  	SFlowCSWindows1253             SFlowCharSet = 2253
  1663  	SFlowCSWindows1254             SFlowCharSet = 2254
  1664  	SFlowCSWindows1255             SFlowCharSet = 2255
  1665  	SFlowCSWindows1256             SFlowCharSet = 2256
  1666  	SFlowCSWindows1257             SFlowCharSet = 2257
  1667  	SFlowCSWindows1258             SFlowCharSet = 2258
  1668  	SFlowCSTIS620                  SFlowCharSet = 2259
  1669  	SFlowCS50220                   SFlowCharSet = 2260
  1670  	SFlowCSreserved                SFlowCharSet = 3000
  1671  )
  1672  
  1673  func decodeExtendedUserFlow(data *[]byte) (SFlowExtendedUserFlow, error) {
  1674  	eu := SFlowExtendedUserFlow{}
  1675  	var fdf SFlowFlowDataFormat
  1676  	var srcUserLen uint32
  1677  	var srcUserLenWithPad int
  1678  	var srcUserBytes []byte
  1679  	var dstUserLen uint32
  1680  	var dstUserLenWithPad int
  1681  	var dstUserBytes []byte
  1682  
  1683  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1684  	eu.EnterpriseID, eu.Format = fdf.decode()
  1685  	*data, eu.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1686  	*data, eu.SourceCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
  1687  	*data, srcUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1688  	srcUserLenWithPad = int(srcUserLen + ((4 - srcUserLen) % 4))
  1689  	*data, srcUserBytes = (*data)[srcUserLenWithPad:], (*data)[:srcUserLenWithPad]
  1690  	eu.SourceUserID = string(srcUserBytes[:srcUserLen])
  1691  	*data, eu.DestinationCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
  1692  	*data, dstUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1693  	dstUserLenWithPad = int(dstUserLen + ((4 - dstUserLen) % 4))
  1694  	*data, dstUserBytes = (*data)[dstUserLenWithPad:], (*data)[:dstUserLenWithPad]
  1695  	eu.DestinationUserID = string(dstUserBytes[:dstUserLen])
  1696  	return eu, nil
  1697  }
  1698  
  1699  // **************************************************
  1700  //  Packet IP version 4 Record
  1701  // **************************************************
  1702  
  1703  // SFlowIpv4Record
  1704  //
  1705  //	0                      15                      31
  1706  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1707  //	|                     Length                    |
  1708  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1709  //	|                    Protocol                   |
  1710  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1711  //	|                  Source IPv4                  |
  1712  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1713  //	|                Destination IPv4               |
  1714  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1715  //	|                   Source Port                 |
  1716  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1717  //	|                Destionation Port              |
  1718  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1719  //	|                   TCP Flags                   |
  1720  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1721  //	|                      TOS                      |
  1722  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1723  type SFlowIpv4Record struct {
  1724  	// The length of the IP packet excluding ower layer encapsulations
  1725  	Length uint32
  1726  	// IP Protocol type (for example, TCP = 6, UDP = 17)
  1727  	Protocol uint32
  1728  	// Source IP Address
  1729  	IPSrc net.IP
  1730  	// Destination IP Address
  1731  	IPDst net.IP
  1732  	// TCP/UDP source port number or equivalent
  1733  	PortSrc uint32
  1734  	// TCP/UDP destination port number or equivalent
  1735  	PortDst uint32
  1736  	// TCP flags
  1737  	TCPFlags uint32
  1738  	// IP type of service
  1739  	TOS uint32
  1740  }
  1741  
  1742  func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
  1743  	si := SFlowIpv4Record{}
  1744  
  1745  	*data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1746  	*data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1747  	*data, si.IPSrc = (*data)[4:], net.IP((*data)[:4])
  1748  	*data, si.IPDst = (*data)[4:], net.IP((*data)[:4])
  1749  	*data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1750  	*data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1751  	*data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1752  	*data, si.TOS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1753  
  1754  	return si, nil
  1755  }
  1756  
  1757  // **************************************************
  1758  //
  1759  //	Packet IP version 6 Record
  1760  //
  1761  // **************************************************
  1762  //
  1763  //	0                      15                      31
  1764  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1765  //	|                     Length                    |
  1766  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1767  //	|                    Protocol                   |
  1768  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1769  //	|                  Source IPv4                  |
  1770  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1771  //	|                Destination IPv4               |
  1772  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1773  //	|                   Source Port                 |
  1774  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1775  //	|                Destionation Port              |
  1776  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1777  //	|                   TCP Flags                   |
  1778  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1779  //	|                    Priority                   |
  1780  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1781  type SFlowIpv6Record struct {
  1782  	// The length of the IP packet excluding ower layer encapsulations
  1783  	Length uint32
  1784  	// IP Protocol type (for example, TCP = 6, UDP = 17)
  1785  	Protocol uint32
  1786  	// Source IP Address
  1787  	IPSrc net.IP
  1788  	// Destination IP Address
  1789  	IPDst net.IP
  1790  	// TCP/UDP source port number or equivalent
  1791  	PortSrc uint32
  1792  	// TCP/UDP destination port number or equivalent
  1793  	PortDst uint32
  1794  	// TCP flags
  1795  	TCPFlags uint32
  1796  	// IP priority
  1797  	Priority uint32
  1798  }
  1799  
  1800  func decodeSFlowIpv6Record(data *[]byte) (SFlowIpv6Record, error) {
  1801  	si := SFlowIpv6Record{}
  1802  
  1803  	*data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1804  	*data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1805  	*data, si.IPSrc = (*data)[16:], net.IP((*data)[:16])
  1806  	*data, si.IPDst = (*data)[16:], net.IP((*data)[:16])
  1807  	*data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1808  	*data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1809  	*data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1810  	*data, si.Priority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1811  
  1812  	return si, nil
  1813  }
  1814  
  1815  // **************************************************
  1816  //
  1817  //	Extended IPv4 Tunnel Egress
  1818  //
  1819  // **************************************************
  1820  //
  1821  //	0                      15                      31
  1822  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1823  //	|      20 bit Interprise (0)     |12 bit format |
  1824  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1825  //	|                  record length                |
  1826  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1827  //	/           Packet IP version 4 Record          /
  1828  //	/                                               /
  1829  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1830  type SFlowExtendedIpv4TunnelEgressRecord struct {
  1831  	SFlowBaseFlowRecord
  1832  	SFlowIpv4Record SFlowIpv4Record
  1833  }
  1834  
  1835  func decodeExtendedIpv4TunnelEgress(data *[]byte) (SFlowExtendedIpv4TunnelEgressRecord, error) {
  1836  	rec := SFlowExtendedIpv4TunnelEgressRecord{}
  1837  	var fdf SFlowFlowDataFormat
  1838  
  1839  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1840  	rec.EnterpriseID, rec.Format = fdf.decode()
  1841  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1842  	rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
  1843  
  1844  	return rec, nil
  1845  }
  1846  
  1847  // **************************************************
  1848  //
  1849  //	Extended IPv4 Tunnel Ingress
  1850  //
  1851  // **************************************************
  1852  //
  1853  //	0                      15                      31
  1854  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1855  //	|      20 bit Interprise (0)     |12 bit format |
  1856  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1857  //	|                  record length                |
  1858  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1859  //	/           Packet IP version 4 Record          /
  1860  //	/                                               /
  1861  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1862  type SFlowExtendedIpv4TunnelIngressRecord struct {
  1863  	SFlowBaseFlowRecord
  1864  	SFlowIpv4Record SFlowIpv4Record
  1865  }
  1866  
  1867  func decodeExtendedIpv4TunnelIngress(data *[]byte) (SFlowExtendedIpv4TunnelIngressRecord, error) {
  1868  	rec := SFlowExtendedIpv4TunnelIngressRecord{}
  1869  	var fdf SFlowFlowDataFormat
  1870  
  1871  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1872  	rec.EnterpriseID, rec.Format = fdf.decode()
  1873  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1874  	rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
  1875  
  1876  	return rec, nil
  1877  }
  1878  
  1879  // **************************************************
  1880  //
  1881  //	Extended IPv6 Tunnel Egress
  1882  //
  1883  // **************************************************
  1884  //
  1885  //	0                      15                      31
  1886  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1887  //	|      20 bit Interprise (0)     |12 bit format |
  1888  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1889  //	|                  record length                |
  1890  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1891  //	/           Packet IP version 6 Record          /
  1892  //	/                                               /
  1893  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1894  type SFlowExtendedIpv6TunnelEgressRecord struct {
  1895  	SFlowBaseFlowRecord
  1896  	SFlowIpv6Record
  1897  }
  1898  
  1899  func decodeExtendedIpv6TunnelEgress(data *[]byte) (SFlowExtendedIpv6TunnelEgressRecord, error) {
  1900  	rec := SFlowExtendedIpv6TunnelEgressRecord{}
  1901  	var fdf SFlowFlowDataFormat
  1902  
  1903  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1904  	rec.EnterpriseID, rec.Format = fdf.decode()
  1905  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1906  	rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
  1907  
  1908  	return rec, nil
  1909  }
  1910  
  1911  // **************************************************
  1912  //
  1913  //	Extended IPv6 Tunnel Ingress
  1914  //
  1915  // **************************************************
  1916  //
  1917  //	0                      15                      31
  1918  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1919  //	|      20 bit Interprise (0)     |12 bit format |
  1920  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1921  //	|                  record length                |
  1922  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1923  //	/           Packet IP version 6 Record          /
  1924  //	/                                               /
  1925  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1926  type SFlowExtendedIpv6TunnelIngressRecord struct {
  1927  	SFlowBaseFlowRecord
  1928  	SFlowIpv6Record
  1929  }
  1930  
  1931  func decodeExtendedIpv6TunnelIngress(data *[]byte) (SFlowExtendedIpv6TunnelIngressRecord, error) {
  1932  	rec := SFlowExtendedIpv6TunnelIngressRecord{}
  1933  	var fdf SFlowFlowDataFormat
  1934  
  1935  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1936  	rec.EnterpriseID, rec.Format = fdf.decode()
  1937  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1938  	rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
  1939  
  1940  	return rec, nil
  1941  }
  1942  
  1943  // **************************************************
  1944  //
  1945  //	Extended Decapsulate Egress
  1946  //
  1947  // **************************************************
  1948  //
  1949  //	0                      15                      31
  1950  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1951  //	|      20 bit Interprise (0)     |12 bit format |
  1952  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1953  //	|                  record length                |
  1954  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1955  //	|               Inner Header Offset             |
  1956  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1957  type SFlowExtendedDecapsulateEgressRecord struct {
  1958  	SFlowBaseFlowRecord
  1959  	InnerHeaderOffset uint32
  1960  }
  1961  
  1962  func decodeExtendedDecapsulateEgress(data *[]byte) (SFlowExtendedDecapsulateEgressRecord, error) {
  1963  	rec := SFlowExtendedDecapsulateEgressRecord{}
  1964  	var fdf SFlowFlowDataFormat
  1965  
  1966  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  1967  	rec.EnterpriseID, rec.Format = fdf.decode()
  1968  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1969  	*data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  1970  
  1971  	return rec, nil
  1972  }
  1973  
  1974  // **************************************************
  1975  //
  1976  //	Extended Decapsulate Ingress
  1977  //
  1978  // **************************************************
  1979  
  1980  // SFlowExtendedDecapsulateIngressRecord
  1981  //
  1982  //	0                      15                      31
  1983  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1984  //	|      20 bit Interprise (0)     |12 bit format |
  1985  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1986  //	|                  record length                |
  1987  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1988  //	|               Inner Header Offset             |
  1989  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1990  type SFlowExtendedDecapsulateIngressRecord struct {
  1991  	SFlowBaseFlowRecord
  1992  	InnerHeaderOffset uint32
  1993  }
  1994  
  1995  func decodeExtendedDecapsulateIngress(data *[]byte) (SFlowExtendedDecapsulateIngressRecord, error) {
  1996  	rec := SFlowExtendedDecapsulateIngressRecord{}
  1997  	var fdf SFlowFlowDataFormat
  1998  
  1999  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2000  	rec.EnterpriseID, rec.Format = fdf.decode()
  2001  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2002  	*data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2003  
  2004  	return rec, nil
  2005  }
  2006  
  2007  // **************************************************
  2008  //
  2009  //	Extended VNI Egress
  2010  //
  2011  // **************************************************
  2012  
  2013  // SFlowExtendedVniEgressRecord
  2014  //
  2015  //	0                      15                      31
  2016  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2017  //	|      20 bit Interprise (0)     |12 bit format |
  2018  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2019  //	|                  record length                |
  2020  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2021  //	|                       VNI                     |
  2022  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2023  type SFlowExtendedVniEgressRecord struct {
  2024  	SFlowBaseFlowRecord
  2025  	VNI uint32
  2026  }
  2027  
  2028  func decodeExtendedVniEgress(data *[]byte) (SFlowExtendedVniEgressRecord, error) {
  2029  	rec := SFlowExtendedVniEgressRecord{}
  2030  	var fdf SFlowFlowDataFormat
  2031  
  2032  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2033  	rec.EnterpriseID, rec.Format = fdf.decode()
  2034  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2035  	*data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2036  
  2037  	return rec, nil
  2038  }
  2039  
  2040  // **************************************************
  2041  //
  2042  //	Extended VNI Ingress
  2043  //
  2044  // **************************************************
  2045  
  2046  // SFlowExtendedVniIngressRecord
  2047  //
  2048  //	0                      15                      31
  2049  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2050  //	|      20 bit Interprise (0)     |12 bit format |
  2051  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2052  //	|                  record length                |
  2053  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2054  //	|                       VNI                     |
  2055  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2056  type SFlowExtendedVniIngressRecord struct {
  2057  	SFlowBaseFlowRecord
  2058  	VNI uint32
  2059  }
  2060  
  2061  func decodeExtendedVniIngress(data *[]byte) (SFlowExtendedVniIngressRecord, error) {
  2062  	rec := SFlowExtendedVniIngressRecord{}
  2063  	var fdf SFlowFlowDataFormat
  2064  
  2065  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2066  	rec.EnterpriseID, rec.Format = fdf.decode()
  2067  	*data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2068  	*data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2069  
  2070  	return rec, nil
  2071  }
  2072  
  2073  // **************************************************
  2074  //  Counter Record
  2075  // **************************************************
  2076  
  2077  // SFlowBaseCounterRecord
  2078  //
  2079  //	0                      15                      31
  2080  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2081  //	|      20 bit Interprise (0)     |12 bit format |
  2082  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2083  //	|                  counter length               |
  2084  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2085  //	|                   counter data                |
  2086  //	|                                               |
  2087  //	+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2088  type SFlowBaseCounterRecord struct {
  2089  	EnterpriseID   SFlowEnterpriseID
  2090  	Format         SFlowCounterRecordType
  2091  	FlowDataLength uint32
  2092  }
  2093  
  2094  func (bcr SFlowBaseCounterRecord) GetType() SFlowCounterRecordType {
  2095  	switch bcr.Format {
  2096  	case SFlowTypeGenericInterfaceCounters:
  2097  		return SFlowTypeGenericInterfaceCounters
  2098  	case SFlowTypeEthernetInterfaceCounters:
  2099  		return SFlowTypeEthernetInterfaceCounters
  2100  	case SFlowTypeTokenRingInterfaceCounters:
  2101  		return SFlowTypeTokenRingInterfaceCounters
  2102  	case SFlowType100BaseVGInterfaceCounters:
  2103  		return SFlowType100BaseVGInterfaceCounters
  2104  	case SFlowTypeVLANCounters:
  2105  		return SFlowTypeVLANCounters
  2106  	case SFlowTypeLACPCounters:
  2107  		return SFlowTypeLACPCounters
  2108  	case SFlowTypeProcessorCounters:
  2109  		return SFlowTypeProcessorCounters
  2110  	case SFlowTypeOpenflowPortCounters:
  2111  		return SFlowTypeOpenflowPortCounters
  2112  	case SFlowTypePORTNAMECounters:
  2113  		return SFlowTypePORTNAMECounters
  2114  	case SFLowTypeAPPRESOURCESCounters:
  2115  		return SFLowTypeAPPRESOURCESCounters
  2116  	case SFlowTypeOVSDPCounters:
  2117  		return SFlowTypeOVSDPCounters
  2118  	}
  2119  	unrecognized := fmt.Sprint("Unrecognized counter record type:", bcr.Format)
  2120  	panic(unrecognized)
  2121  }
  2122  
  2123  // **************************************************
  2124  //  Counter Record
  2125  // **************************************************
  2126  //
  2127  //	  0                      15                      31
  2128  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2129  //	  |      20 bit Interprise (0)     |12 bit format |
  2130  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2131  //	  |                  counter length               |
  2132  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2133  //	  |                    IfIndex                    |
  2134  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2135  //	  |                    IfType                     |
  2136  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2137  //	  |                   IfSpeed                     |
  2138  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2139  //	  |                   IfDirection                 |
  2140  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2141  //	  |                    IfStatus                   |
  2142  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2143  //	  |                   IFInOctets                  |
  2144  //	  |                                               |
  2145  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2146  //	  |                   IfInUcastPkts               |
  2147  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2148  //	  |                  IfInMulticastPkts            |
  2149  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2150  //	  |                  IfInBroadcastPkts            |
  2151  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2152  //	  |                    IfInDiscards               |
  2153  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2154  //	  |                    InInErrors                 |
  2155  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2156  //	  |                  IfInUnknownProtos            |
  2157  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2158  //	  |                   IfOutOctets                 |
  2159  //	  |                                               |
  2160  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2161  //	  |                   IfOutUcastPkts              |
  2162  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2163  //	  |                  IfOutMulticastPkts           |
  2164  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2165  //	  |                  IfOutBroadcastPkts           |
  2166  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2167  //	  |                   IfOutDiscards               |
  2168  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2169  //	  |                    IfOUtErrors                |
  2170  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2171  //	  |                 IfPromiscouousMode            |
  2172  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2173  
  2174  type SFlowGenericInterfaceCounters struct {
  2175  	SFlowBaseCounterRecord
  2176  	IfIndex            uint32
  2177  	IfType             uint32
  2178  	IfSpeed            uint64
  2179  	IfDirection        uint32
  2180  	IfStatus           uint32
  2181  	IfInOctets         uint64
  2182  	IfInUcastPkts      uint32
  2183  	IfInMulticastPkts  uint32
  2184  	IfInBroadcastPkts  uint32
  2185  	IfInDiscards       uint32
  2186  	IfInErrors         uint32
  2187  	IfInUnknownProtos  uint32
  2188  	IfOutOctets        uint64
  2189  	IfOutUcastPkts     uint32
  2190  	IfOutMulticastPkts uint32
  2191  	IfOutBroadcastPkts uint32
  2192  	IfOutDiscards      uint32
  2193  	IfOutErrors        uint32
  2194  	IfPromiscuousMode  uint32
  2195  }
  2196  
  2197  func decodeGenericInterfaceCounters(data *[]byte) (SFlowGenericInterfaceCounters, error) {
  2198  	gic := SFlowGenericInterfaceCounters{}
  2199  	var cdf SFlowCounterDataFormat
  2200  
  2201  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2202  	gic.EnterpriseID, gic.Format = cdf.decode()
  2203  	*data, gic.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2204  	*data, gic.IfIndex = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2205  	*data, gic.IfType = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2206  	*data, gic.IfSpeed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2207  	*data, gic.IfDirection = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2208  	*data, gic.IfStatus = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2209  	*data, gic.IfInOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2210  	*data, gic.IfInUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2211  	*data, gic.IfInMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2212  	*data, gic.IfInBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2213  	*data, gic.IfInDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2214  	*data, gic.IfInErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2215  	*data, gic.IfInUnknownProtos = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2216  	*data, gic.IfOutOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2217  	*data, gic.IfOutUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2218  	*data, gic.IfOutMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2219  	*data, gic.IfOutBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2220  	*data, gic.IfOutDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2221  	*data, gic.IfOutErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2222  	*data, gic.IfPromiscuousMode = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2223  	return gic, nil
  2224  }
  2225  
  2226  // **************************************************
  2227  //  Counter Record
  2228  // **************************************************
  2229  //
  2230  //	  0                      15                      31
  2231  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2232  //	  |      20 bit Interprise (0)     |12 bit format |
  2233  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2234  //	  |                  counter length               |
  2235  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2236  //	  /                   counter data                /
  2237  //	  /                                               /
  2238  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2239  
  2240  type SFlowEthernetCounters struct {
  2241  	SFlowBaseCounterRecord
  2242  	AlignmentErrors           uint32
  2243  	FCSErrors                 uint32
  2244  	SingleCollisionFrames     uint32
  2245  	MultipleCollisionFrames   uint32
  2246  	SQETestErrors             uint32
  2247  	DeferredTransmissions     uint32
  2248  	LateCollisions            uint32
  2249  	ExcessiveCollisions       uint32
  2250  	InternalMacTransmitErrors uint32
  2251  	CarrierSenseErrors        uint32
  2252  	FrameTooLongs             uint32
  2253  	InternalMacReceiveErrors  uint32
  2254  	SymbolErrors              uint32
  2255  }
  2256  
  2257  func decodeEthernetCounters(data *[]byte) (SFlowEthernetCounters, error) {
  2258  	ec := SFlowEthernetCounters{}
  2259  	var cdf SFlowCounterDataFormat
  2260  
  2261  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2262  	ec.EnterpriseID, ec.Format = cdf.decode()
  2263  	if len(*data) < 4 {
  2264  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2265  	}
  2266  	*data, ec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2267  	if len(*data) < 4 {
  2268  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2269  	}
  2270  	*data, ec.AlignmentErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2271  	if len(*data) < 4 {
  2272  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2273  	}
  2274  	*data, ec.FCSErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2275  	if len(*data) < 4 {
  2276  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2277  	}
  2278  	*data, ec.SingleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2279  	if len(*data) < 4 {
  2280  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2281  	}
  2282  	*data, ec.MultipleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2283  	if len(*data) < 4 {
  2284  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2285  	}
  2286  	*data, ec.SQETestErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2287  	if len(*data) < 4 {
  2288  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2289  	}
  2290  	*data, ec.DeferredTransmissions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2291  	if len(*data) < 4 {
  2292  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2293  	}
  2294  	*data, ec.LateCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2295  	if len(*data) < 4 {
  2296  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2297  	}
  2298  	*data, ec.ExcessiveCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2299  	if len(*data) < 4 {
  2300  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2301  	}
  2302  	*data, ec.InternalMacTransmitErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2303  	if len(*data) < 4 {
  2304  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2305  	}
  2306  	*data, ec.CarrierSenseErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2307  	if len(*data) < 4 {
  2308  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2309  	}
  2310  	*data, ec.FrameTooLongs = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2311  	if len(*data) < 4 {
  2312  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2313  	}
  2314  	*data, ec.InternalMacReceiveErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2315  	if len(*data) < 4 {
  2316  		return SFlowEthernetCounters{}, errors.New("ethernet counters too small")
  2317  	}
  2318  	*data, ec.SymbolErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2319  	return ec, nil
  2320  }
  2321  
  2322  // VLAN Counter
  2323  
  2324  type SFlowVLANCounters struct {
  2325  	SFlowBaseCounterRecord
  2326  	VlanID        uint32
  2327  	Octets        uint64
  2328  	UcastPkts     uint32
  2329  	MulticastPkts uint32
  2330  	BroadcastPkts uint32
  2331  	Discards      uint32
  2332  }
  2333  
  2334  func decodeVLANCounters(data *[]byte) (SFlowVLANCounters, error) {
  2335  	vc := SFlowVLANCounters{}
  2336  	var cdf SFlowCounterDataFormat
  2337  
  2338  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2339  	vc.EnterpriseID, vc.Format = cdf.decode()
  2340  	vc.EnterpriseID, vc.Format = cdf.decode()
  2341  	*data, vc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2342  	*data, vc.VlanID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2343  	*data, vc.Octets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2344  	*data, vc.UcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2345  	*data, vc.MulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2346  	*data, vc.BroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2347  	*data, vc.Discards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2348  	return vc, nil
  2349  }
  2350  
  2351  // SFLLACPportState  :  SFlow LACP Port State (All(4) - 32 bit)
  2352  type SFLLACPPortState struct {
  2353  	PortStateAll uint32
  2354  }
  2355  
  2356  // LACPcounters  :  LACP SFlow Counters  ( 64 Bytes )
  2357  type SFlowLACPCounters struct {
  2358  	SFlowBaseCounterRecord
  2359  	ActorSystemID        net.HardwareAddr
  2360  	PartnerSystemID      net.HardwareAddr
  2361  	AttachedAggID        uint32
  2362  	LacpPortState        SFLLACPPortState
  2363  	LACPDUsRx            uint32
  2364  	MarkerPDUsRx         uint32
  2365  	MarkerResponsePDUsRx uint32
  2366  	UnknownRx            uint32
  2367  	IllegalRx            uint32
  2368  	LACPDUsTx            uint32
  2369  	MarkerPDUsTx         uint32
  2370  	MarkerResponsePDUsTx uint32
  2371  }
  2372  
  2373  func decodeLACPCounters(data *[]byte) (SFlowLACPCounters, error) {
  2374  	la := SFlowLACPCounters{}
  2375  	var cdf SFlowCounterDataFormat
  2376  
  2377  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2378  	la.EnterpriseID, la.Format = cdf.decode()
  2379  	*data, la.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2380  	*data, la.ActorSystemID = (*data)[6:], (*data)[:6]
  2381  	*data = (*data)[2:] // remove padding
  2382  	*data, la.PartnerSystemID = (*data)[6:], (*data)[:6]
  2383  	*data = (*data)[2:] //remove padding
  2384  	*data, la.AttachedAggID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2385  	*data, la.LacpPortState.PortStateAll = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2386  	*data, la.LACPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2387  	*data, la.MarkerPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2388  	*data, la.MarkerResponsePDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2389  	*data, la.UnknownRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2390  	*data, la.IllegalRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2391  	*data, la.LACPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2392  	*data, la.MarkerPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2393  	*data, la.MarkerResponsePDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2394  
  2395  	return la, nil
  2396  
  2397  }
  2398  
  2399  // **************************************************
  2400  //  Processor Counter Record
  2401  // **************************************************
  2402  //
  2403  //	  0                      15                      31
  2404  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2405  //	  |      20 bit Interprise (0)     |12 bit format |
  2406  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2407  //	  |                  counter length               |
  2408  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2409  //	  |                    FiveSecCpu                 |
  2410  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2411  //	  |                    OneMinCpu                  |
  2412  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2413  //	  |                    GiveMinCpu                 |
  2414  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2415  //	  |                   TotalMemory                 |
  2416  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2417  //	  |                    FreeMemory                 |
  2418  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2419  
  2420  type SFlowProcessorCounters struct {
  2421  	SFlowBaseCounterRecord
  2422  	FiveSecCpu  uint32 // 5 second average CPU utilization
  2423  	OneMinCpu   uint32 // 1 minute average CPU utilization
  2424  	FiveMinCpu  uint32 // 5 minute average CPU utilization
  2425  	TotalMemory uint64 // total memory (in bytes)
  2426  	FreeMemory  uint64 // free memory (in bytes)
  2427  }
  2428  
  2429  func decodeProcessorCounters(data *[]byte) (SFlowProcessorCounters, error) {
  2430  	pc := SFlowProcessorCounters{}
  2431  	var cdf SFlowCounterDataFormat
  2432  	var high32, low32 uint32
  2433  
  2434  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2435  	pc.EnterpriseID, pc.Format = cdf.decode()
  2436  	*data, pc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2437  
  2438  	*data, pc.FiveSecCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2439  	*data, pc.OneMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2440  	*data, pc.FiveMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2441  	*data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2442  	*data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2443  	pc.TotalMemory = (uint64(high32) << 32) + uint64(low32)
  2444  	*data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2445  	*data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2446  	pc.FreeMemory = (uint64(high32)) + uint64(low32)
  2447  
  2448  	return pc, nil
  2449  }
  2450  
  2451  // SFlowEthernetFrameFlowRecord give additional information
  2452  // about the sampled packet if it's available.
  2453  // An agent may or may not provide this information.
  2454  type SFlowEthernetFrameFlowRecord struct {
  2455  	SFlowBaseFlowRecord
  2456  	FrameLength uint32
  2457  	SrcMac      net.HardwareAddr
  2458  	DstMac      net.HardwareAddr
  2459  	Type        uint32
  2460  }
  2461  
  2462  // Ethernet frame flow records have the following structure:
  2463  //
  2464  //	  0                      15                      31
  2465  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2466  //	  |      20 bit Interprise (0)     |12 bit format |
  2467  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2468  //	  |                  record length                |
  2469  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2470  //	  |                Source Mac Address             |
  2471  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2472  //	  |             Destination Mac Address           |
  2473  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2474  //	  |               Ethernet Packet Type            |
  2475  //	  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2476  
  2477  func decodeEthernetFrameFlowRecord(data *[]byte) (SFlowEthernetFrameFlowRecord, error) {
  2478  	es := SFlowEthernetFrameFlowRecord{}
  2479  	var fdf SFlowFlowDataFormat
  2480  
  2481  	*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2482  	es.EnterpriseID, es.Format = fdf.decode()
  2483  	*data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2484  
  2485  	*data, es.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2486  	*data, es.SrcMac = (*data)[8:], net.HardwareAddr((*data)[:6])
  2487  	*data, es.DstMac = (*data)[8:], net.HardwareAddr((*data)[:6])
  2488  	*data, es.Type = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2489  	return es, nil
  2490  }
  2491  
  2492  // SFlowOpenflowPortCounters  :  OVS-Sflow OpenFlow Port Counter  ( 20 Bytes )
  2493  type SFlowOpenflowPortCounters struct {
  2494  	SFlowBaseCounterRecord
  2495  	DatapathID uint64
  2496  	PortNo     uint32
  2497  }
  2498  
  2499  func decodeOpenflowportCounters(data *[]byte) (SFlowOpenflowPortCounters, error) {
  2500  	ofp := SFlowOpenflowPortCounters{}
  2501  	var cdf SFlowCounterDataFormat
  2502  
  2503  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2504  	ofp.EnterpriseID, ofp.Format = cdf.decode()
  2505  	*data, ofp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2506  	*data, ofp.DatapathID = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2507  	*data, ofp.PortNo = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2508  
  2509  	return ofp, nil
  2510  }
  2511  
  2512  // SFlowAppresourcesCounters  :  OVS_Sflow App Resources Counter ( 48 Bytes )
  2513  type SFlowAppresourcesCounters struct {
  2514  	SFlowBaseCounterRecord
  2515  	UserTime   uint32
  2516  	SystemTime uint32
  2517  	MemUsed    uint64
  2518  	MemMax     uint64
  2519  	FdOpen     uint32
  2520  	FdMax      uint32
  2521  	ConnOpen   uint32
  2522  	ConnMax    uint32
  2523  }
  2524  
  2525  func decodeAppresourcesCounters(data *[]byte) (SFlowAppresourcesCounters, error) {
  2526  	app := SFlowAppresourcesCounters{}
  2527  	var cdf SFlowCounterDataFormat
  2528  
  2529  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2530  	app.EnterpriseID, app.Format = cdf.decode()
  2531  	*data, app.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2532  	*data, app.UserTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2533  	*data, app.SystemTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2534  	*data, app.MemUsed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2535  	*data, app.MemMax = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
  2536  	*data, app.FdOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2537  	*data, app.FdMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2538  	*data, app.ConnOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2539  	*data, app.ConnMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2540  
  2541  	return app, nil
  2542  }
  2543  
  2544  // SFlowOVSDPCounters  :  OVS-Sflow DataPath Counter  ( 32 Bytes )
  2545  type SFlowOVSDPCounters struct {
  2546  	SFlowBaseCounterRecord
  2547  	NHit     uint32
  2548  	NMissed  uint32
  2549  	NLost    uint32
  2550  	NMaskHit uint32
  2551  	NFlows   uint32
  2552  	NMasks   uint32
  2553  }
  2554  
  2555  func decodeOVSDPCounters(data *[]byte) (SFlowOVSDPCounters, error) {
  2556  	dp := SFlowOVSDPCounters{}
  2557  	var cdf SFlowCounterDataFormat
  2558  
  2559  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2560  	dp.EnterpriseID, dp.Format = cdf.decode()
  2561  	*data, dp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2562  	*data, dp.NHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2563  	*data, dp.NMissed = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2564  	*data, dp.NLost = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2565  	*data, dp.NMaskHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2566  	*data, dp.NFlows = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2567  	*data, dp.NMasks = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2568  
  2569  	return dp, nil
  2570  }
  2571  
  2572  // SFlowPORTNAME  :  OVS-Sflow PORTNAME Counter Sampletype ( 20 Bytes )
  2573  type SFlowPORTNAME struct {
  2574  	SFlowBaseCounterRecord
  2575  	Len uint32
  2576  	Str string
  2577  }
  2578  
  2579  func decodeString(data *[]byte) (len uint32, str string) {
  2580  	*data, len = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2581  	str = string((*data)[:len])
  2582  	if (len % 4) != 0 {
  2583  		len += 4 - len%4
  2584  	}
  2585  	*data = (*data)[len:]
  2586  	return
  2587  }
  2588  
  2589  func decodePortnameCounters(data *[]byte) (SFlowPORTNAME, error) {
  2590  	pn := SFlowPORTNAME{}
  2591  	var cdf SFlowCounterDataFormat
  2592  
  2593  	*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
  2594  	pn.EnterpriseID, pn.Format = cdf.decode()
  2595  	*data, pn.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
  2596  	pn.Len, pn.Str = decodeString(data)
  2597  
  2598  	return pn, nil
  2599  }