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 }