12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471 |
- // Copyright 2014 Google, Inc. All rights reserved.
- //
- // Use of this source code is governed by a BSD-style license
- // that can be found in the LICENSE file in the root of the source
- // tree.
- /*
- This layer decodes SFlow version 5 datagrams.
- The specification can be found here: http://sflow.org/sflow_version_5.txt
- Additional developer information about sflow can be found at:
- http://sflow.org/developers/specifications.php
- And SFlow in general:
- http://sflow.org/index.php
- Two forms of sample data are defined: compact and expanded. The
- Specification has this to say:
- Compact and expand forms of counter and flow samples are defined.
- An agent must not mix compact/expanded encodings. If an agent
- will never use ifIndex numbers >= 2^24 then it must use compact
- encodings for all interfaces. Otherwise the expanded formats must
- be used for all interfaces.
- This decoder only supports the compact form, because that is the only
- one for which data was avaialble.
- The datagram is composed of one or more samples of type flow or counter,
- and each sample is composed of one or more records describing the sample.
- A sample is a single instance of sampled inforamtion, and each record in
- the sample gives additional / supplimentary information about the sample.
- The following sample record types are supported:
- Raw Packet Header
- opaque = flow_data; enterprise = 0; format = 1
- Extended Switch Data
- opaque = flow_data; enterprise = 0; format = 1001
- Extended Router Data
- opaque = flow_data; enterprise = 0; format = 1002
- Extended Gateway Data
- opaque = flow_data; enterprise = 0; format = 1003
- Extended User Data
- opaque = flow_data; enterprise = 0; format = 1004
- Extended URL Data
- opaque = flow_data; enterprise = 0; format = 1005
- The following types of counter records are supported:
- Generic Interface Counters - see RFC 2233
- opaque = counter_data; enterprise = 0; format = 1
- Ethernet Interface Counters - see RFC 2358
- opaque = counter_data; enterprise = 0; format = 2
- SFlow is encoded using XDR (RFC4506). There are a few places
- where the standard 4-byte fields are partitioned into two
- bitfields of different lengths. I'm not sure why the designers
- chose to pack together two values like this in some places, and
- in others they use the entire 4-byte value to store a number that
- will never be more than a few bits. In any case, there are a couple
- of types defined to handle the decoding of these bitfields, and
- that's why they're there. */
- package layers
- import (
- "encoding/binary"
- "errors"
- "fmt"
- "net"
- "github.com/google/gopacket"
- )
- // SFlowRecord holds both flow sample records and counter sample records.
- // A Record is the structure that actually holds the sampled data
- // and / or counters.
- type SFlowRecord interface {
- }
- // SFlowDataSource encodes a 2-bit SFlowSourceFormat in its most significant
- // 2 bits, and an SFlowSourceValue in its least significant 30 bits.
- // These types and values define the meaning of the inteface information
- // presented in the sample metadata.
- type SFlowDataSource int32
- func (sdc SFlowDataSource) decode() (SFlowSourceFormat, SFlowSourceValue) {
- leftField := sdc >> 30
- rightField := uint32(0x3FFFFFFF) & uint32(sdc)
- return SFlowSourceFormat(leftField), SFlowSourceValue(rightField)
- }
- type SFlowDataSourceExpanded struct {
- SourceIDClass SFlowSourceFormat
- SourceIDIndex SFlowSourceValue
- }
- func (sdce SFlowDataSourceExpanded) decode() (SFlowSourceFormat, SFlowSourceValue) {
- leftField := sdce.SourceIDClass >> 30
- rightField := uint32(0x3FFFFFFF) & uint32(sdce.SourceIDIndex)
- return SFlowSourceFormat(leftField), SFlowSourceValue(rightField)
- }
- type SFlowSourceFormat uint32
- type SFlowSourceValue uint32
- const (
- SFlowTypeSingleInterface SFlowSourceFormat = 0
- SFlowTypePacketDiscarded SFlowSourceFormat = 1
- SFlowTypeMultipleDestinations SFlowSourceFormat = 2
- )
- func (sdf SFlowSourceFormat) String() string {
- switch sdf {
- case SFlowTypeSingleInterface:
- return "Single Interface"
- case SFlowTypePacketDiscarded:
- return "Packet Discarded"
- case SFlowTypeMultipleDestinations:
- return "Multiple Destinations"
- default:
- return "UNKNOWN"
- }
- }
- func decodeSFlow(data []byte, p gopacket.PacketBuilder) error {
- s := &SFlowDatagram{}
- err := s.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
- p.AddLayer(s)
- p.SetApplicationLayer(s)
- return nil
- }
- // SFlowDatagram is the outermost container which holds some basic information
- // about the reporting agent, and holds at least one sample record
- type SFlowDatagram struct {
- BaseLayer
- DatagramVersion uint32
- AgentAddress net.IP
- SubAgentID uint32
- SequenceNumber uint32
- AgentUptime uint32
- SampleCount uint32
- FlowSamples []SFlowFlowSample
- CounterSamples []SFlowCounterSample
- }
- // An SFlow datagram's outer container has the following
- // structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sFlow version (2|4|5) |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int IP version of the Agent (1=v4|2=v6) |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Agent IP address (v4=4byte|v6=16byte) /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sub agent id |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int datagram sequence number |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int switch uptime in ms |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int n samples in datagram |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / n samples /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // SFlowDataFormat encodes the EnterpriseID in the most
- // significant 12 bits, and the SampleType in the least significant
- // 20 bits.
- type SFlowDataFormat uint32
- func (sdf SFlowDataFormat) decode() (SFlowEnterpriseID, SFlowSampleType) {
- leftField := sdf >> 12
- rightField := uint32(0xFFF) & uint32(sdf)
- return SFlowEnterpriseID(leftField), SFlowSampleType(rightField)
- }
- // SFlowEnterpriseID is used to differentiate between the
- // official SFlow standard, and other, vendor-specific
- // types of flow data. (Similiar to SNMP's enterprise MIB
- // OIDs) Only the office SFlow Enterprise ID is decoded
- // here.
- type SFlowEnterpriseID uint32
- const (
- SFlowStandard SFlowEnterpriseID = 0
- )
- func (eid SFlowEnterpriseID) String() string {
- switch eid {
- case SFlowStandard:
- return "Standard SFlow"
- default:
- return ""
- }
- }
- func (eid SFlowEnterpriseID) GetType() SFlowEnterpriseID {
- return SFlowStandard
- }
- // SFlowSampleType specifies the type of sample. Only flow samples
- // and counter samples are supported
- type SFlowSampleType uint32
- const (
- SFlowTypeFlowSample SFlowSampleType = 1
- SFlowTypeCounterSample SFlowSampleType = 2
- SFlowTypeExpandedFlowSample SFlowSampleType = 3
- SFlowTypeExpandedCounterSample SFlowSampleType = 4
- )
- func (st SFlowSampleType) GetType() SFlowSampleType {
- switch st {
- case SFlowTypeFlowSample:
- return SFlowTypeFlowSample
- case SFlowTypeCounterSample:
- return SFlowTypeCounterSample
- case SFlowTypeExpandedFlowSample:
- return SFlowTypeExpandedFlowSample
- case SFlowTypeExpandedCounterSample:
- return SFlowTypeExpandedCounterSample
- default:
- panic("Invalid Sample Type")
- }
- }
- func (st SFlowSampleType) String() string {
- switch st {
- case SFlowTypeFlowSample:
- return "Flow Sample"
- case SFlowTypeCounterSample:
- return "Counter Sample"
- case SFlowTypeExpandedFlowSample:
- return "Expanded Flow Sample"
- case SFlowTypeExpandedCounterSample:
- return "Expanded Counter Sample"
- default:
- return ""
- }
- }
- func (s *SFlowDatagram) LayerType() gopacket.LayerType { return LayerTypeSFlow }
- func (d *SFlowDatagram) Payload() []byte { return nil }
- func (d *SFlowDatagram) CanDecode() gopacket.LayerClass { return LayerTypeSFlow }
- func (d *SFlowDatagram) NextLayerType() gopacket.LayerType { return gopacket.LayerTypePayload }
- // SFlowIPType determines what form the IP address being decoded will
- // take. This is an XDR union type allowing for both IPv4 and IPv6
- type SFlowIPType uint32
- const (
- SFlowIPv4 SFlowIPType = 1
- SFlowIPv6 SFlowIPType = 2
- )
- func (s SFlowIPType) String() string {
- switch s {
- case SFlowIPv4:
- return "IPv4"
- case SFlowIPv6:
- return "IPv6"
- default:
- return ""
- }
- }
- func (s SFlowIPType) Length() int {
- switch s {
- case SFlowIPv4:
- return 4
- case SFlowIPv6:
- return 16
- default:
- return 0
- }
- }
- func (s *SFlowDatagram) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
- var agentAddressType SFlowIPType
- data, s.DatagramVersion = data[4:], binary.BigEndian.Uint32(data[:4])
- data, agentAddressType = data[4:], SFlowIPType(binary.BigEndian.Uint32(data[:4]))
- data, s.AgentAddress = data[agentAddressType.Length():], data[:agentAddressType.Length()]
- data, s.SubAgentID = data[4:], binary.BigEndian.Uint32(data[:4])
- data, s.SequenceNumber = data[4:], binary.BigEndian.Uint32(data[:4])
- data, s.AgentUptime = data[4:], binary.BigEndian.Uint32(data[:4])
- data, s.SampleCount = data[4:], binary.BigEndian.Uint32(data[:4])
- if s.SampleCount < 1 {
- return fmt.Errorf("SFlow Datagram has invalid sample length: %d", s.SampleCount)
- }
- for i := uint32(0); i < s.SampleCount; i++ {
- sdf := SFlowDataFormat(binary.BigEndian.Uint32(data[:4]))
- _, sampleType := sdf.decode()
- switch sampleType {
- case SFlowTypeFlowSample:
- if flowSample, err := decodeFlowSample(&data, false); err == nil {
- s.FlowSamples = append(s.FlowSamples, flowSample)
- } else {
- return err
- }
- case SFlowTypeCounterSample:
- if counterSample, err := decodeCounterSample(&data, false); err == nil {
- s.CounterSamples = append(s.CounterSamples, counterSample)
- } else {
- return err
- }
- case SFlowTypeExpandedFlowSample:
- if flowSample, err := decodeFlowSample(&data, true); err == nil {
- s.FlowSamples = append(s.FlowSamples, flowSample)
- } else {
- return err
- }
- case SFlowTypeExpandedCounterSample:
- if counterSample, err := decodeCounterSample(&data, true); err == nil {
- s.CounterSamples = append(s.CounterSamples, counterSample)
- } else {
- return err
- }
- default:
- return fmt.Errorf("Unsupported SFlow sample type %d", sampleType)
- }
- }
- return nil
- }
- // SFlowFlowSample represents a sampled packet and contains
- // one or more records describing the packet
- type SFlowFlowSample struct {
- EnterpriseID SFlowEnterpriseID
- Format SFlowSampleType
- SampleLength uint32
- SequenceNumber uint32
- SourceIDClass SFlowSourceFormat
- SourceIDIndex SFlowSourceValue
- SamplingRate uint32
- SamplePool uint32
- Dropped uint32
- InputInterfaceFormat uint32
- InputInterface uint32
- OutputInterfaceFormat uint32
- OutputInterface uint32
- RecordCount uint32
- Records []SFlowRecord
- }
- // Flow samples have the following structure. Note
- // the bit fields to encode the Enterprise ID and the
- // Flow record format: type 1
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | sample length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sample sequence number |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // |id type | src id index value |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sampling rate |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sample pool |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int drops |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int input ifIndex |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int output ifIndex |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int number of records |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / flow records /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // Flow samples have the following structure.
- // Flow record format: type 3
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | sample length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sample sequence number |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int src id type |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int src id index value |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sampling rate |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sample pool |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int drops |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int input interface format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int input interface value |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int output interface format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int output interface value |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int number of records |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / flow records /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowFlowDataFormat uint32
- func (fdf SFlowFlowDataFormat) decode() (SFlowEnterpriseID, SFlowFlowRecordType) {
- leftField := fdf >> 12
- rightField := uint32(0xFFF) & uint32(fdf)
- return SFlowEnterpriseID(leftField), SFlowFlowRecordType(rightField)
- }
- func (fs SFlowFlowSample) GetRecords() []SFlowRecord {
- return fs.Records
- }
- func (fs SFlowFlowSample) GetType() SFlowSampleType {
- return SFlowTypeFlowSample
- }
- func skipRecord(data *[]byte) {
- recordLength := int(binary.BigEndian.Uint32((*data)[4:]))
- *data = (*data)[(recordLength+((4-recordLength)%4))+8:]
- }
- func decodeFlowSample(data *[]byte, expanded bool) (SFlowFlowSample, error) {
- s := SFlowFlowSample{}
- var sdf SFlowDataFormat
- *data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- var sdc SFlowDataSource
- s.EnterpriseID, s.Format = sdf.decode()
- *data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- if expanded {
- *data, s.SourceIDClass = (*data)[4:], SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4]))
- *data, s.SourceIDIndex = (*data)[4:], SFlowSourceValue(binary.BigEndian.Uint32((*data)[:4]))
- } else {
- *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
- s.SourceIDClass, s.SourceIDIndex = sdc.decode()
- }
- *data, s.SamplingRate = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.SamplePool = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.Dropped = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- if expanded {
- *data, s.InputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.OutputInterfaceFormat = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- } else {
- *data, s.InputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.OutputInterface = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- }
- *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- for i := uint32(0); i < s.RecordCount; i++ {
- rdf := SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- enterpriseID, flowRecordType := rdf.decode()
- // Try to decode when EnterpriseID is 0 signaling
- // default sflow structs are used according specification
- // Unexpected behavior detected for e.g. with pmacct
- if enterpriseID == 0 {
- switch flowRecordType {
- case SFlowTypeRawPacketFlow:
- if record, err := decodeRawPacketFlowRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedUserFlow:
- if record, err := decodeExtendedUserFlow(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedUrlFlow:
- if record, err := decodeExtendedURLRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedSwitchFlow:
- if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedRouterFlow:
- if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedGatewayFlow:
- if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeEthernetFrameFlow:
- if record, err := decodeEthernetFrameFlowRecord(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeIpv4Flow:
- if record, err := decodeSFlowIpv4Record(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeIpv6Flow:
- if record, err := decodeSFlowIpv6Record(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedMlpsFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedMlpsFlow")
- case SFlowTypeExtendedNatFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedNatFlow")
- case SFlowTypeExtendedMlpsTunnelFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
- case SFlowTypeExtendedMlpsVcFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedMlpsVcFlow")
- case SFlowTypeExtendedMlpsFecFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedMlpsFecFlow")
- case SFlowTypeExtendedMlpsLvpFecFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
- case SFlowTypeExtendedVlanFlow:
- // TODO
- skipRecord(data)
- return s, errors.New("skipping TypeExtendedVlanFlow")
- case SFlowTypeExtendedIpv4TunnelEgressFlow:
- if record, err := decodeExtendedIpv4TunnelEgress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedIpv4TunnelIngressFlow:
- if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedIpv6TunnelEgressFlow:
- if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedIpv6TunnelIngressFlow:
- if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedDecapsulateEgressFlow:
- if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedDecapsulateIngressFlow:
- if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedVniEgressFlow:
- if record, err := decodeExtendedVniEgress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeExtendedVniIngressFlow:
- if record, err := decodeExtendedVniIngress(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- default:
- return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
- }
- } else {
- skipRecord(data)
- }
- }
- return s, nil
- }
- // Counter samples report information about various counter
- // objects. Typically these are items like IfInOctets, or
- // CPU / Memory stats, etc. SFlow will report these at regular
- // intervals as configured on the agent. If one were sufficiently
- // industrious, this could be used to replace the typical
- // SNMP polling used for such things.
- type SFlowCounterSample struct {
- EnterpriseID SFlowEnterpriseID
- Format SFlowSampleType
- SampleLength uint32
- SequenceNumber uint32
- SourceIDClass SFlowSourceFormat
- SourceIDIndex SFlowSourceValue
- RecordCount uint32
- Records []SFlowRecord
- }
- // Counter samples have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int sample sequence number |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // |id type | src id index value |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | int number of records |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / counter records /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowCounterDataFormat uint32
- func (cdf SFlowCounterDataFormat) decode() (SFlowEnterpriseID, SFlowCounterRecordType) {
- leftField := cdf >> 12
- rightField := uint32(0xFFF) & uint32(cdf)
- return SFlowEnterpriseID(leftField), SFlowCounterRecordType(rightField)
- }
- // GetRecords will return a slice of interface types
- // representing records. A type switch can be used to
- // get at the underlying SFlowCounterRecordType.
- func (cs SFlowCounterSample) GetRecords() []SFlowRecord {
- return cs.Records
- }
- // GetType will report the type of sample. Only the
- // compact form of counter samples is supported
- func (cs SFlowCounterSample) GetType() SFlowSampleType {
- return SFlowTypeCounterSample
- }
- type SFlowCounterRecordType uint32
- const (
- SFlowTypeGenericInterfaceCounters SFlowCounterRecordType = 1
- SFlowTypeEthernetInterfaceCounters SFlowCounterRecordType = 2
- SFlowTypeTokenRingInterfaceCounters SFlowCounterRecordType = 3
- SFlowType100BaseVGInterfaceCounters SFlowCounterRecordType = 4
- SFlowTypeVLANCounters SFlowCounterRecordType = 5
- SFlowTypeLACPCounters SFlowCounterRecordType = 7
- SFlowTypeProcessorCounters SFlowCounterRecordType = 1001
- SFlowTypeOpenflowPortCounters SFlowCounterRecordType = 1004
- SFlowTypePORTNAMECounters SFlowCounterRecordType = 1005
- SFLowTypeAPPRESOURCESCounters SFlowCounterRecordType = 2203
- SFlowTypeOVSDPCounters SFlowCounterRecordType = 2207
- )
- func (cr SFlowCounterRecordType) String() string {
- switch cr {
- case SFlowTypeGenericInterfaceCounters:
- return "Generic Interface Counters"
- case SFlowTypeEthernetInterfaceCounters:
- return "Ethernet Interface Counters"
- case SFlowTypeTokenRingInterfaceCounters:
- return "Token Ring Interface Counters"
- case SFlowType100BaseVGInterfaceCounters:
- return "100BaseVG Interface Counters"
- case SFlowTypeVLANCounters:
- return "VLAN Counters"
- case SFlowTypeLACPCounters:
- return "LACP Counters"
- case SFlowTypeProcessorCounters:
- return "Processor Counters"
- case SFlowTypeOpenflowPortCounters:
- return "Openflow Port Counters"
- case SFlowTypePORTNAMECounters:
- return "PORT NAME Counters"
- case SFLowTypeAPPRESOURCESCounters:
- return "App Resources Counters"
- case SFlowTypeOVSDPCounters:
- return "OVSDP Counters"
- default:
- return ""
- }
- }
- func decodeCounterSample(data *[]byte, expanded bool) (SFlowCounterSample, error) {
- s := SFlowCounterSample{}
- var sdc SFlowDataSource
- var sdce SFlowDataSourceExpanded
- var sdf SFlowDataFormat
- *data, sdf = (*data)[4:], SFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- s.EnterpriseID, s.Format = sdf.decode()
- *data, s.SampleLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, s.SequenceNumber = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- if expanded {
- *data, sdce = (*data)[8:], SFlowDataSourceExpanded{SFlowSourceFormat(binary.BigEndian.Uint32((*data)[:4])), SFlowSourceValue(binary.BigEndian.Uint32((*data)[4:8]))}
- s.SourceIDClass, s.SourceIDIndex = sdce.decode()
- } else {
- *data, sdc = (*data)[4:], SFlowDataSource(binary.BigEndian.Uint32((*data)[:4]))
- s.SourceIDClass, s.SourceIDIndex = sdc.decode()
- }
- *data, s.RecordCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- for i := uint32(0); i < s.RecordCount; i++ {
- cdf := SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- _, counterRecordType := cdf.decode()
- switch counterRecordType {
- case SFlowTypeGenericInterfaceCounters:
- if record, err := decodeGenericInterfaceCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeEthernetInterfaceCounters:
- if record, err := decodeEthernetCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeTokenRingInterfaceCounters:
- skipRecord(data)
- return s, errors.New("skipping TypeTokenRingInterfaceCounters")
- case SFlowType100BaseVGInterfaceCounters:
- skipRecord(data)
- return s, errors.New("skipping Type100BaseVGInterfaceCounters")
- case SFlowTypeVLANCounters:
- if record, err := decodeVLANCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeLACPCounters:
- if record, err := decodeLACPCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeProcessorCounters:
- if record, err := decodeProcessorCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeOpenflowPortCounters:
- if record, err := decodeOpenflowportCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypePORTNAMECounters:
- if record, err := decodePortnameCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFLowTypeAPPRESOURCESCounters:
- if record, err := decodeAppresourcesCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- case SFlowTypeOVSDPCounters:
- if record, err := decodeOVSDPCounters(data); err == nil {
- s.Records = append(s.Records, record)
- } else {
- return s, err
- }
- default:
- return s, fmt.Errorf("Invalid counter record type: %d", counterRecordType)
- }
- }
- return s, nil
- }
- // SFlowBaseFlowRecord holds the fields common to all records
- // of type SFlowFlowRecordType
- type SFlowBaseFlowRecord struct {
- EnterpriseID SFlowEnterpriseID
- Format SFlowFlowRecordType
- FlowDataLength uint32
- }
- func (bfr SFlowBaseFlowRecord) GetType() SFlowFlowRecordType {
- return bfr.Format
- }
- // SFlowFlowRecordType denotes what kind of Flow Record is
- // represented. See RFC 3176
- type SFlowFlowRecordType uint32
- const (
- SFlowTypeRawPacketFlow SFlowFlowRecordType = 1
- SFlowTypeEthernetFrameFlow SFlowFlowRecordType = 2
- SFlowTypeIpv4Flow SFlowFlowRecordType = 3
- SFlowTypeIpv6Flow SFlowFlowRecordType = 4
- SFlowTypeExtendedSwitchFlow SFlowFlowRecordType = 1001
- SFlowTypeExtendedRouterFlow SFlowFlowRecordType = 1002
- SFlowTypeExtendedGatewayFlow SFlowFlowRecordType = 1003
- SFlowTypeExtendedUserFlow SFlowFlowRecordType = 1004
- SFlowTypeExtendedUrlFlow SFlowFlowRecordType = 1005
- SFlowTypeExtendedMlpsFlow SFlowFlowRecordType = 1006
- SFlowTypeExtendedNatFlow SFlowFlowRecordType = 1007
- SFlowTypeExtendedMlpsTunnelFlow SFlowFlowRecordType = 1008
- SFlowTypeExtendedMlpsVcFlow SFlowFlowRecordType = 1009
- SFlowTypeExtendedMlpsFecFlow SFlowFlowRecordType = 1010
- SFlowTypeExtendedMlpsLvpFecFlow SFlowFlowRecordType = 1011
- SFlowTypeExtendedVlanFlow SFlowFlowRecordType = 1012
- SFlowTypeExtendedIpv4TunnelEgressFlow SFlowFlowRecordType = 1023
- SFlowTypeExtendedIpv4TunnelIngressFlow SFlowFlowRecordType = 1024
- SFlowTypeExtendedIpv6TunnelEgressFlow SFlowFlowRecordType = 1025
- SFlowTypeExtendedIpv6TunnelIngressFlow SFlowFlowRecordType = 1026
- SFlowTypeExtendedDecapsulateEgressFlow SFlowFlowRecordType = 1027
- SFlowTypeExtendedDecapsulateIngressFlow SFlowFlowRecordType = 1028
- SFlowTypeExtendedVniEgressFlow SFlowFlowRecordType = 1029
- SFlowTypeExtendedVniIngressFlow SFlowFlowRecordType = 1030
- )
- func (rt SFlowFlowRecordType) String() string {
- switch rt {
- case SFlowTypeRawPacketFlow:
- return "Raw Packet Flow Record"
- case SFlowTypeEthernetFrameFlow:
- return "Ethernet Frame Flow Record"
- case SFlowTypeIpv4Flow:
- return "IPv4 Flow Record"
- case SFlowTypeIpv6Flow:
- return "IPv6 Flow Record"
- case SFlowTypeExtendedSwitchFlow:
- return "Extended Switch Flow Record"
- case SFlowTypeExtendedRouterFlow:
- return "Extended Router Flow Record"
- case SFlowTypeExtendedGatewayFlow:
- return "Extended Gateway Flow Record"
- case SFlowTypeExtendedUserFlow:
- return "Extended User Flow Record"
- case SFlowTypeExtendedUrlFlow:
- return "Extended URL Flow Record"
- case SFlowTypeExtendedMlpsFlow:
- return "Extended MPLS Flow Record"
- case SFlowTypeExtendedNatFlow:
- return "Extended NAT Flow Record"
- case SFlowTypeExtendedMlpsTunnelFlow:
- return "Extended MPLS Tunnel Flow Record"
- case SFlowTypeExtendedMlpsVcFlow:
- return "Extended MPLS VC Flow Record"
- case SFlowTypeExtendedMlpsFecFlow:
- return "Extended MPLS FEC Flow Record"
- case SFlowTypeExtendedMlpsLvpFecFlow:
- return "Extended MPLS LVP FEC Flow Record"
- case SFlowTypeExtendedVlanFlow:
- return "Extended VLAN Flow Record"
- case SFlowTypeExtendedIpv4TunnelEgressFlow:
- return "Extended IPv4 Tunnel Egress Record"
- case SFlowTypeExtendedIpv4TunnelIngressFlow:
- return "Extended IPv4 Tunnel Ingress Record"
- case SFlowTypeExtendedIpv6TunnelEgressFlow:
- return "Extended IPv6 Tunnel Egress Record"
- case SFlowTypeExtendedIpv6TunnelIngressFlow:
- return "Extended IPv6 Tunnel Ingress Record"
- case SFlowTypeExtendedDecapsulateEgressFlow:
- return "Extended Decapsulate Egress Record"
- case SFlowTypeExtendedDecapsulateIngressFlow:
- return "Extended Decapsulate Ingress Record"
- case SFlowTypeExtendedVniEgressFlow:
- return "Extended VNI Ingress Record"
- case SFlowTypeExtendedVniIngressFlow:
- return "Extended VNI Ingress Record"
- default:
- return ""
- }
- }
- // SFlowRawPacketFlowRecords hold information about a sampled
- // packet grabbed as it transited the agent. This is
- // perhaps the most useful and interesting record type,
- // as it holds the headers of the sampled packet and
- // can be used to build up a complete picture of the
- // traffic patterns on a network.
- //
- // The raw packet header is sent back into gopacket for
- // decoding, and the resulting gopackt.Packet is stored
- // in the Header member
- type SFlowRawPacketFlowRecord struct {
- SFlowBaseFlowRecord
- HeaderProtocol SFlowRawHeaderProtocol
- FrameLength uint32
- PayloadRemoved uint32
- HeaderLength uint32
- Header gopacket.Packet
- }
- // Raw packet record types have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Header Protocol |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Frame Length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Payload Removed |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Header Length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // \ Header \
- // \ \
- // \ \
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowRawHeaderProtocol uint32
- const (
- SFlowProtoEthernet SFlowRawHeaderProtocol = 1
- SFlowProtoISO88024 SFlowRawHeaderProtocol = 2
- SFlowProtoISO88025 SFlowRawHeaderProtocol = 3
- SFlowProtoFDDI SFlowRawHeaderProtocol = 4
- SFlowProtoFrameRelay SFlowRawHeaderProtocol = 5
- SFlowProtoX25 SFlowRawHeaderProtocol = 6
- SFlowProtoPPP SFlowRawHeaderProtocol = 7
- SFlowProtoSMDS SFlowRawHeaderProtocol = 8
- SFlowProtoAAL5 SFlowRawHeaderProtocol = 9
- SFlowProtoAAL5_IP SFlowRawHeaderProtocol = 10 /* e.g. Cisco AAL5 mux */
- SFlowProtoIPv4 SFlowRawHeaderProtocol = 11
- SFlowProtoIPv6 SFlowRawHeaderProtocol = 12
- SFlowProtoMPLS SFlowRawHeaderProtocol = 13
- SFlowProtoPOS SFlowRawHeaderProtocol = 14 /* RFC 1662, 2615 */
- )
- func (sfhp SFlowRawHeaderProtocol) String() string {
- switch sfhp {
- case SFlowProtoEthernet:
- return "ETHERNET-ISO88023"
- case SFlowProtoISO88024:
- return "ISO88024-TOKENBUS"
- case SFlowProtoISO88025:
- return "ISO88025-TOKENRING"
- case SFlowProtoFDDI:
- return "FDDI"
- case SFlowProtoFrameRelay:
- return "FRAME-RELAY"
- case SFlowProtoX25:
- return "X25"
- case SFlowProtoPPP:
- return "PPP"
- case SFlowProtoSMDS:
- return "SMDS"
- case SFlowProtoAAL5:
- return "AAL5"
- case SFlowProtoAAL5_IP:
- return "AAL5-IP"
- case SFlowProtoIPv4:
- return "IPv4"
- case SFlowProtoIPv6:
- return "IPv6"
- case SFlowProtoMPLS:
- return "MPLS"
- case SFlowProtoPOS:
- return "POS"
- }
- return "UNKNOWN"
- }
- func decodeRawPacketFlowRecord(data *[]byte) (SFlowRawPacketFlowRecord, error) {
- rec := SFlowRawPacketFlowRecord{}
- header := []byte{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.HeaderProtocol = (*data)[4:], SFlowRawHeaderProtocol(binary.BigEndian.Uint32((*data)[:4]))
- *data, rec.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.PayloadRemoved = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.HeaderLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- headerLenWithPadding := int(rec.HeaderLength + ((4 - rec.HeaderLength) % 4))
- *data, header = (*data)[headerLenWithPadding:], (*data)[:headerLenWithPadding]
- rec.Header = gopacket.NewPacket(header, LayerTypeEthernet, gopacket.Default)
- return rec, nil
- }
- // SFlowExtendedSwitchFlowRecord give additional information
- // about the sampled packet if it's available. It's mainly
- // useful for getting at the incoming and outgoing VLANs
- // An agent may or may not provide this information.
- type SFlowExtendedSwitchFlowRecord struct {
- SFlowBaseFlowRecord
- IncomingVLAN uint32
- IncomingVLANPriority uint32
- OutgoingVLAN uint32
- OutgoingVLANPriority uint32
- }
- // Extended switch records have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Incoming VLAN |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Incoming VLAN Priority |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Outgoing VLAN |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Outgoing VLAN Priority |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- func decodeExtendedSwitchFlowRecord(data *[]byte) (SFlowExtendedSwitchFlowRecord, error) {
- es := SFlowExtendedSwitchFlowRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- es.EnterpriseID, es.Format = fdf.decode()
- *data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.IncomingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.IncomingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.OutgoingVLAN = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.OutgoingVLANPriority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return es, nil
- }
- // SFlowExtendedRouterFlowRecord gives additional information
- // about the layer 3 routing information used to forward
- // the packet
- type SFlowExtendedRouterFlowRecord struct {
- SFlowBaseFlowRecord
- NextHop net.IP
- NextHopSourceMask uint32
- NextHopDestinationMask uint32
- }
- // Extended router records have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IP version of next hop router (1=v4|2=v6) |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Next Hop address (v4=4byte|v6=16byte) /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Next Hop Source Mask |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Next Hop Destination Mask |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- func decodeExtendedRouterFlowRecord(data *[]byte) (SFlowExtendedRouterFlowRecord, error) {
- er := SFlowExtendedRouterFlowRecord{}
- var fdf SFlowFlowDataFormat
- var extendedRouterAddressType SFlowIPType
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- er.EnterpriseID, er.Format = fdf.decode()
- *data, er.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, extendedRouterAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
- *data, er.NextHop = (*data)[extendedRouterAddressType.Length():], (*data)[:extendedRouterAddressType.Length()]
- *data, er.NextHopSourceMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, er.NextHopDestinationMask = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return er, nil
- }
- // SFlowExtendedGatewayFlowRecord describes information treasured by
- // nework engineers everywhere: AS path information listing which
- // BGP peer sent the packet, and various other BGP related info.
- // This information is vital because it gives a picture of how much
- // traffic is being sent from / received by various BGP peers.
- // Extended gateway records have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IP version of next hop router (1=v4|2=v6) |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Next Hop address (v4=4byte|v6=16byte) /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | AS |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source AS |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Peer AS |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | AS Path Count |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / AS Path / Sequence /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Communities /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Local Pref |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // AS Path / Sequence:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | AS Source Type (Path=1 / Sequence=2) |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Path / Sequence length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Path / Sequence Members /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // Communities:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | communitiy length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / communitiy Members /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedGatewayFlowRecord struct {
- SFlowBaseFlowRecord
- NextHop net.IP
- AS uint32
- SourceAS uint32
- PeerAS uint32
- ASPathCount uint32
- ASPath []SFlowASDestination
- Communities []uint32
- LocalPref uint32
- }
- type SFlowASPathType uint32
- const (
- SFlowASSet SFlowASPathType = 1
- SFlowASSequence SFlowASPathType = 2
- )
- func (apt SFlowASPathType) String() string {
- switch apt {
- case SFlowASSet:
- return "AS Set"
- case SFlowASSequence:
- return "AS Sequence"
- default:
- return ""
- }
- }
- type SFlowASDestination struct {
- Type SFlowASPathType
- Count uint32
- Members []uint32
- }
- func (asd SFlowASDestination) String() string {
- switch asd.Type {
- case SFlowASSet:
- return fmt.Sprint("AS Set:", asd.Members)
- case SFlowASSequence:
- return fmt.Sprint("AS Sequence:", asd.Members)
- default:
- return ""
- }
- }
- func (ad *SFlowASDestination) decodePath(data *[]byte) {
- *data, ad.Type = (*data)[4:], SFlowASPathType(binary.BigEndian.Uint32((*data)[:4]))
- *data, ad.Count = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- ad.Members = make([]uint32, ad.Count)
- for i := uint32(0); i < ad.Count; i++ {
- var member uint32
- *data, member = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- ad.Members[i] = member
- }
- }
- func decodeExtendedGatewayFlowRecord(data *[]byte) (SFlowExtendedGatewayFlowRecord, error) {
- eg := SFlowExtendedGatewayFlowRecord{}
- var fdf SFlowFlowDataFormat
- var extendedGatewayAddressType SFlowIPType
- var communitiesLength uint32
- var community uint32
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- eg.EnterpriseID, eg.Format = fdf.decode()
- *data, eg.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, extendedGatewayAddressType = (*data)[4:], SFlowIPType(binary.BigEndian.Uint32((*data)[:4]))
- *data, eg.NextHop = (*data)[extendedGatewayAddressType.Length():], (*data)[:extendedGatewayAddressType.Length()]
- *data, eg.AS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, eg.SourceAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, eg.PeerAS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, eg.ASPathCount = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- for i := uint32(0); i < eg.ASPathCount; i++ {
- asPath := SFlowASDestination{}
- asPath.decodePath(data)
- eg.ASPath = append(eg.ASPath, asPath)
- }
- *data, communitiesLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- eg.Communities = make([]uint32, communitiesLength)
- for j := uint32(0); j < communitiesLength; j++ {
- *data, community = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- eg.Communities[j] = community
- }
- *data, eg.LocalPref = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return eg, nil
- }
- // **************************************************
- // Extended URL Flow Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | direction |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | URL |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Host |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowURLDirection uint32
- const (
- SFlowURLsrc SFlowURLDirection = 1
- SFlowURLdst SFlowURLDirection = 2
- )
- func (urld SFlowURLDirection) String() string {
- switch urld {
- case SFlowURLsrc:
- return "Source address is the server"
- case SFlowURLdst:
- return "Destination address is the server"
- default:
- return ""
- }
- }
- type SFlowExtendedURLRecord struct {
- SFlowBaseFlowRecord
- Direction SFlowURLDirection
- URL string
- Host string
- }
- func decodeExtendedURLRecord(data *[]byte) (SFlowExtendedURLRecord, error) {
- eur := SFlowExtendedURLRecord{}
- var fdf SFlowFlowDataFormat
- var urlLen uint32
- var urlLenWithPad int
- var hostLen uint32
- var hostLenWithPad int
- var urlBytes []byte
- var hostBytes []byte
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- eur.EnterpriseID, eur.Format = fdf.decode()
- *data, eur.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, eur.Direction = (*data)[4:], SFlowURLDirection(binary.BigEndian.Uint32((*data)[:4]))
- *data, urlLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- urlLenWithPad = int(urlLen + ((4 - urlLen) % 4))
- *data, urlBytes = (*data)[urlLenWithPad:], (*data)[:urlLenWithPad]
- eur.URL = string(urlBytes[:urlLen])
- *data, hostLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- hostLenWithPad = int(hostLen + ((4 - hostLen) % 4))
- *data, hostBytes = (*data)[hostLenWithPad:], (*data)[:hostLenWithPad]
- eur.Host = string(hostBytes[:hostLen])
- return eur, nil
- }
- // **************************************************
- // Extended User Flow Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source Character Set |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source User Id |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destination Character Set |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destination User ID |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedUserFlow struct {
- SFlowBaseFlowRecord
- SourceCharSet SFlowCharSet
- SourceUserID string
- DestinationCharSet SFlowCharSet
- DestinationUserID string
- }
- type SFlowCharSet uint32
- const (
- SFlowCSunknown SFlowCharSet = 2
- SFlowCSASCII SFlowCharSet = 3
- SFlowCSISOLatin1 SFlowCharSet = 4
- SFlowCSISOLatin2 SFlowCharSet = 5
- SFlowCSISOLatin3 SFlowCharSet = 6
- SFlowCSISOLatin4 SFlowCharSet = 7
- SFlowCSISOLatinCyrillic SFlowCharSet = 8
- SFlowCSISOLatinArabic SFlowCharSet = 9
- SFlowCSISOLatinGreek SFlowCharSet = 10
- SFlowCSISOLatinHebrew SFlowCharSet = 11
- SFlowCSISOLatin5 SFlowCharSet = 12
- SFlowCSISOLatin6 SFlowCharSet = 13
- SFlowCSISOTextComm SFlowCharSet = 14
- SFlowCSHalfWidthKatakana SFlowCharSet = 15
- SFlowCSJISEncoding SFlowCharSet = 16
- SFlowCSShiftJIS SFlowCharSet = 17
- SFlowCSEUCPkdFmtJapanese SFlowCharSet = 18
- SFlowCSEUCFixWidJapanese SFlowCharSet = 19
- SFlowCSISO4UnitedKingdom SFlowCharSet = 20
- SFlowCSISO11SwedishForNames SFlowCharSet = 21
- SFlowCSISO15Italian SFlowCharSet = 22
- SFlowCSISO17Spanish SFlowCharSet = 23
- SFlowCSISO21German SFlowCharSet = 24
- SFlowCSISO60DanishNorwegian SFlowCharSet = 25
- SFlowCSISO69French SFlowCharSet = 26
- SFlowCSISO10646UTF1 SFlowCharSet = 27
- SFlowCSISO646basic1983 SFlowCharSet = 28
- SFlowCSINVARIANT SFlowCharSet = 29
- SFlowCSISO2IntlRefVersion SFlowCharSet = 30
- SFlowCSNATSSEFI SFlowCharSet = 31
- SFlowCSNATSSEFIADD SFlowCharSet = 32
- SFlowCSNATSDANO SFlowCharSet = 33
- SFlowCSNATSDANOADD SFlowCharSet = 34
- SFlowCSISO10Swedish SFlowCharSet = 35
- SFlowCSKSC56011987 SFlowCharSet = 36
- SFlowCSISO2022KR SFlowCharSet = 37
- SFlowCSEUCKR SFlowCharSet = 38
- SFlowCSISO2022JP SFlowCharSet = 39
- SFlowCSISO2022JP2 SFlowCharSet = 40
- SFlowCSISO13JISC6220jp SFlowCharSet = 41
- SFlowCSISO14JISC6220ro SFlowCharSet = 42
- SFlowCSISO16Portuguese SFlowCharSet = 43
- SFlowCSISO18Greek7Old SFlowCharSet = 44
- SFlowCSISO19LatinGreek SFlowCharSet = 45
- SFlowCSISO25French SFlowCharSet = 46
- SFlowCSISO27LatinGreek1 SFlowCharSet = 47
- SFlowCSISO5427Cyrillic SFlowCharSet = 48
- SFlowCSISO42JISC62261978 SFlowCharSet = 49
- SFlowCSISO47BSViewdata SFlowCharSet = 50
- SFlowCSISO49INIS SFlowCharSet = 51
- SFlowCSISO50INIS8 SFlowCharSet = 52
- SFlowCSISO51INISCyrillic SFlowCharSet = 53
- SFlowCSISO54271981 SFlowCharSet = 54
- SFlowCSISO5428Greek SFlowCharSet = 55
- SFlowCSISO57GB1988 SFlowCharSet = 56
- SFlowCSISO58GB231280 SFlowCharSet = 57
- SFlowCSISO61Norwegian2 SFlowCharSet = 58
- SFlowCSISO70VideotexSupp1 SFlowCharSet = 59
- SFlowCSISO84Portuguese2 SFlowCharSet = 60
- SFlowCSISO85Spanish2 SFlowCharSet = 61
- SFlowCSISO86Hungarian SFlowCharSet = 62
- SFlowCSISO87JISX0208 SFlowCharSet = 63
- SFlowCSISO88Greek7 SFlowCharSet = 64
- SFlowCSISO89ASMO449 SFlowCharSet = 65
- SFlowCSISO90 SFlowCharSet = 66
- SFlowCSISO91JISC62291984a SFlowCharSet = 67
- SFlowCSISO92JISC62991984b SFlowCharSet = 68
- SFlowCSISO93JIS62291984badd SFlowCharSet = 69
- SFlowCSISO94JIS62291984hand SFlowCharSet = 70
- SFlowCSISO95JIS62291984handadd SFlowCharSet = 71
- SFlowCSISO96JISC62291984kana SFlowCharSet = 72
- SFlowCSISO2033 SFlowCharSet = 73
- SFlowCSISO99NAPLPS SFlowCharSet = 74
- SFlowCSISO102T617bit SFlowCharSet = 75
- SFlowCSISO103T618bit SFlowCharSet = 76
- SFlowCSISO111ECMACyrillic SFlowCharSet = 77
- SFlowCSa71 SFlowCharSet = 78
- SFlowCSa72 SFlowCharSet = 79
- SFlowCSISO123CSAZ24341985gr SFlowCharSet = 80
- SFlowCSISO88596E SFlowCharSet = 81
- SFlowCSISO88596I SFlowCharSet = 82
- SFlowCSISO128T101G2 SFlowCharSet = 83
- SFlowCSISO88598E SFlowCharSet = 84
- SFlowCSISO88598I SFlowCharSet = 85
- SFlowCSISO139CSN369103 SFlowCharSet = 86
- SFlowCSISO141JUSIB1002 SFlowCharSet = 87
- SFlowCSISO143IECP271 SFlowCharSet = 88
- SFlowCSISO146Serbian SFlowCharSet = 89
- SFlowCSISO147Macedonian SFlowCharSet = 90
- SFlowCSISO150 SFlowCharSet = 91
- SFlowCSISO151Cuba SFlowCharSet = 92
- SFlowCSISO6937Add SFlowCharSet = 93
- SFlowCSISO153GOST1976874 SFlowCharSet = 94
- SFlowCSISO8859Supp SFlowCharSet = 95
- SFlowCSISO10367Box SFlowCharSet = 96
- SFlowCSISO158Lap SFlowCharSet = 97
- SFlowCSISO159JISX02121990 SFlowCharSet = 98
- SFlowCSISO646Danish SFlowCharSet = 99
- SFlowCSUSDK SFlowCharSet = 100
- SFlowCSDKUS SFlowCharSet = 101
- SFlowCSKSC5636 SFlowCharSet = 102
- SFlowCSUnicode11UTF7 SFlowCharSet = 103
- SFlowCSISO2022CN SFlowCharSet = 104
- SFlowCSISO2022CNEXT SFlowCharSet = 105
- SFlowCSUTF8 SFlowCharSet = 106
- SFlowCSISO885913 SFlowCharSet = 109
- SFlowCSISO885914 SFlowCharSet = 110
- SFlowCSISO885915 SFlowCharSet = 111
- SFlowCSISO885916 SFlowCharSet = 112
- SFlowCSGBK SFlowCharSet = 113
- SFlowCSGB18030 SFlowCharSet = 114
- SFlowCSOSDEBCDICDF0415 SFlowCharSet = 115
- SFlowCSOSDEBCDICDF03IRV SFlowCharSet = 116
- SFlowCSOSDEBCDICDF041 SFlowCharSet = 117
- SFlowCSISO115481 SFlowCharSet = 118
- SFlowCSKZ1048 SFlowCharSet = 119
- SFlowCSUnicode SFlowCharSet = 1000
- SFlowCSUCS4 SFlowCharSet = 1001
- SFlowCSUnicodeASCII SFlowCharSet = 1002
- SFlowCSUnicodeLatin1 SFlowCharSet = 1003
- SFlowCSUnicodeJapanese SFlowCharSet = 1004
- SFlowCSUnicodeIBM1261 SFlowCharSet = 1005
- SFlowCSUnicodeIBM1268 SFlowCharSet = 1006
- SFlowCSUnicodeIBM1276 SFlowCharSet = 1007
- SFlowCSUnicodeIBM1264 SFlowCharSet = 1008
- SFlowCSUnicodeIBM1265 SFlowCharSet = 1009
- SFlowCSUnicode11 SFlowCharSet = 1010
- SFlowCSSCSU SFlowCharSet = 1011
- SFlowCSUTF7 SFlowCharSet = 1012
- SFlowCSUTF16BE SFlowCharSet = 1013
- SFlowCSUTF16LE SFlowCharSet = 1014
- SFlowCSUTF16 SFlowCharSet = 1015
- SFlowCSCESU8 SFlowCharSet = 1016
- SFlowCSUTF32 SFlowCharSet = 1017
- SFlowCSUTF32BE SFlowCharSet = 1018
- SFlowCSUTF32LE SFlowCharSet = 1019
- SFlowCSBOCU1 SFlowCharSet = 1020
- SFlowCSWindows30Latin1 SFlowCharSet = 2000
- SFlowCSWindows31Latin1 SFlowCharSet = 2001
- SFlowCSWindows31Latin2 SFlowCharSet = 2002
- SFlowCSWindows31Latin5 SFlowCharSet = 2003
- SFlowCSHPRoman8 SFlowCharSet = 2004
- SFlowCSAdobeStandardEncoding SFlowCharSet = 2005
- SFlowCSVenturaUS SFlowCharSet = 2006
- SFlowCSVenturaInternational SFlowCharSet = 2007
- SFlowCSDECMCS SFlowCharSet = 2008
- SFlowCSPC850Multilingual SFlowCharSet = 2009
- SFlowCSPCp852 SFlowCharSet = 2010
- SFlowCSPC8CodePage437 SFlowCharSet = 2011
- SFlowCSPC8DanishNorwegian SFlowCharSet = 2012
- SFlowCSPC862LatinHebrew SFlowCharSet = 2013
- SFlowCSPC8Turkish SFlowCharSet = 2014
- SFlowCSIBMSymbols SFlowCharSet = 2015
- SFlowCSIBMThai SFlowCharSet = 2016
- SFlowCSHPLegal SFlowCharSet = 2017
- SFlowCSHPPiFont SFlowCharSet = 2018
- SFlowCSHPMath8 SFlowCharSet = 2019
- SFlowCSHPPSMath SFlowCharSet = 2020
- SFlowCSHPDesktop SFlowCharSet = 2021
- SFlowCSVenturaMath SFlowCharSet = 2022
- SFlowCSMicrosoftPublishing SFlowCharSet = 2023
- SFlowCSWindows31J SFlowCharSet = 2024
- SFlowCSGB2312 SFlowCharSet = 2025
- SFlowCSBig5 SFlowCharSet = 2026
- SFlowCSMacintosh SFlowCharSet = 2027
- SFlowCSIBM037 SFlowCharSet = 2028
- SFlowCSIBM038 SFlowCharSet = 2029
- SFlowCSIBM273 SFlowCharSet = 2030
- SFlowCSIBM274 SFlowCharSet = 2031
- SFlowCSIBM275 SFlowCharSet = 2032
- SFlowCSIBM277 SFlowCharSet = 2033
- SFlowCSIBM278 SFlowCharSet = 2034
- SFlowCSIBM280 SFlowCharSet = 2035
- SFlowCSIBM281 SFlowCharSet = 2036
- SFlowCSIBM284 SFlowCharSet = 2037
- SFlowCSIBM285 SFlowCharSet = 2038
- SFlowCSIBM290 SFlowCharSet = 2039
- SFlowCSIBM297 SFlowCharSet = 2040
- SFlowCSIBM420 SFlowCharSet = 2041
- SFlowCSIBM423 SFlowCharSet = 2042
- SFlowCSIBM424 SFlowCharSet = 2043
- SFlowCSIBM500 SFlowCharSet = 2044
- SFlowCSIBM851 SFlowCharSet = 2045
- SFlowCSIBM855 SFlowCharSet = 2046
- SFlowCSIBM857 SFlowCharSet = 2047
- SFlowCSIBM860 SFlowCharSet = 2048
- SFlowCSIBM861 SFlowCharSet = 2049
- SFlowCSIBM863 SFlowCharSet = 2050
- SFlowCSIBM864 SFlowCharSet = 2051
- SFlowCSIBM865 SFlowCharSet = 2052
- SFlowCSIBM868 SFlowCharSet = 2053
- SFlowCSIBM869 SFlowCharSet = 2054
- SFlowCSIBM870 SFlowCharSet = 2055
- SFlowCSIBM871 SFlowCharSet = 2056
- SFlowCSIBM880 SFlowCharSet = 2057
- SFlowCSIBM891 SFlowCharSet = 2058
- SFlowCSIBM903 SFlowCharSet = 2059
- SFlowCSIBBM904 SFlowCharSet = 2060
- SFlowCSIBM905 SFlowCharSet = 2061
- SFlowCSIBM918 SFlowCharSet = 2062
- SFlowCSIBM1026 SFlowCharSet = 2063
- SFlowCSIBMEBCDICATDE SFlowCharSet = 2064
- SFlowCSEBCDICATDEA SFlowCharSet = 2065
- SFlowCSEBCDICCAFR SFlowCharSet = 2066
- SFlowCSEBCDICDKNO SFlowCharSet = 2067
- SFlowCSEBCDICDKNOA SFlowCharSet = 2068
- SFlowCSEBCDICFISE SFlowCharSet = 2069
- SFlowCSEBCDICFISEA SFlowCharSet = 2070
- SFlowCSEBCDICFR SFlowCharSet = 2071
- SFlowCSEBCDICIT SFlowCharSet = 2072
- SFlowCSEBCDICPT SFlowCharSet = 2073
- SFlowCSEBCDICES SFlowCharSet = 2074
- SFlowCSEBCDICESA SFlowCharSet = 2075
- SFlowCSEBCDICESS SFlowCharSet = 2076
- SFlowCSEBCDICUK SFlowCharSet = 2077
- SFlowCSEBCDICUS SFlowCharSet = 2078
- SFlowCSUnknown8BiT SFlowCharSet = 2079
- SFlowCSMnemonic SFlowCharSet = 2080
- SFlowCSMnem SFlowCharSet = 2081
- SFlowCSVISCII SFlowCharSet = 2082
- SFlowCSVIQR SFlowCharSet = 2083
- SFlowCSKOI8R SFlowCharSet = 2084
- SFlowCSHZGB2312 SFlowCharSet = 2085
- SFlowCSIBM866 SFlowCharSet = 2086
- SFlowCSPC775Baltic SFlowCharSet = 2087
- SFlowCSKOI8U SFlowCharSet = 2088
- SFlowCSIBM00858 SFlowCharSet = 2089
- SFlowCSIBM00924 SFlowCharSet = 2090
- SFlowCSIBM01140 SFlowCharSet = 2091
- SFlowCSIBM01141 SFlowCharSet = 2092
- SFlowCSIBM01142 SFlowCharSet = 2093
- SFlowCSIBM01143 SFlowCharSet = 2094
- SFlowCSIBM01144 SFlowCharSet = 2095
- SFlowCSIBM01145 SFlowCharSet = 2096
- SFlowCSIBM01146 SFlowCharSet = 2097
- SFlowCSIBM01147 SFlowCharSet = 2098
- SFlowCSIBM01148 SFlowCharSet = 2099
- SFlowCSIBM01149 SFlowCharSet = 2100
- SFlowCSBig5HKSCS SFlowCharSet = 2101
- SFlowCSIBM1047 SFlowCharSet = 2102
- SFlowCSPTCP154 SFlowCharSet = 2103
- SFlowCSAmiga1251 SFlowCharSet = 2104
- SFlowCSKOI7switched SFlowCharSet = 2105
- SFlowCSBRF SFlowCharSet = 2106
- SFlowCSTSCII SFlowCharSet = 2107
- SFlowCSCP51932 SFlowCharSet = 2108
- SFlowCSWindows874 SFlowCharSet = 2109
- SFlowCSWindows1250 SFlowCharSet = 2250
- SFlowCSWindows1251 SFlowCharSet = 2251
- SFlowCSWindows1252 SFlowCharSet = 2252
- SFlowCSWindows1253 SFlowCharSet = 2253
- SFlowCSWindows1254 SFlowCharSet = 2254
- SFlowCSWindows1255 SFlowCharSet = 2255
- SFlowCSWindows1256 SFlowCharSet = 2256
- SFlowCSWindows1257 SFlowCharSet = 2257
- SFlowCSWindows1258 SFlowCharSet = 2258
- SFlowCSTIS620 SFlowCharSet = 2259
- SFlowCS50220 SFlowCharSet = 2260
- SFlowCSreserved SFlowCharSet = 3000
- )
- func decodeExtendedUserFlow(data *[]byte) (SFlowExtendedUserFlow, error) {
- eu := SFlowExtendedUserFlow{}
- var fdf SFlowFlowDataFormat
- var srcUserLen uint32
- var srcUserLenWithPad int
- var srcUserBytes []byte
- var dstUserLen uint32
- var dstUserLenWithPad int
- var dstUserBytes []byte
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- eu.EnterpriseID, eu.Format = fdf.decode()
- *data, eu.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, eu.SourceCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
- *data, srcUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- srcUserLenWithPad = int(srcUserLen + ((4 - srcUserLen) % 4))
- *data, srcUserBytes = (*data)[srcUserLenWithPad:], (*data)[:srcUserLenWithPad]
- eu.SourceUserID = string(srcUserBytes[:srcUserLen])
- *data, eu.DestinationCharSet = (*data)[4:], SFlowCharSet(binary.BigEndian.Uint32((*data)[:4]))
- *data, dstUserLen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- dstUserLenWithPad = int(dstUserLen + ((4 - dstUserLen) % 4))
- *data, dstUserBytes = (*data)[dstUserLenWithPad:], (*data)[:dstUserLenWithPad]
- eu.DestinationUserID = string(dstUserBytes[:dstUserLen])
- return eu, nil
- }
- // **************************************************
- // Packet IP version 4 Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Protocol |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source IPv4 |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destination IPv4 |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source Port |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destionation Port |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | TCP Flags |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | TOS |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowIpv4Record struct {
- // The length of the IP packet excluding ower layer encapsulations
- Length uint32
- // IP Protocol type (for example, TCP = 6, UDP = 17)
- Protocol uint32
- // Source IP Address
- IPSrc net.IP
- // Destination IP Address
- IPDst net.IP
- // TCP/UDP source port number or equivalent
- PortSrc uint32
- // TCP/UDP destination port number or equivalent
- PortDst uint32
- // TCP flags
- TCPFlags uint32
- // IP type of service
- TOS uint32
- }
- func decodeSFlowIpv4Record(data *[]byte) (SFlowIpv4Record, error) {
- si := SFlowIpv4Record{}
- *data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.IPSrc = (*data)[4:], net.IP((*data)[:4])
- *data, si.IPDst = (*data)[4:], net.IP((*data)[:4])
- *data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.TOS = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return si, nil
- }
- // **************************************************
- // Packet IP version 6 Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Protocol |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source IPv4 |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destination IPv4 |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source Port |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destionation Port |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | TCP Flags |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Priority |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowIpv6Record struct {
- // The length of the IP packet excluding ower layer encapsulations
- Length uint32
- // IP Protocol type (for example, TCP = 6, UDP = 17)
- Protocol uint32
- // Source IP Address
- IPSrc net.IP
- // Destination IP Address
- IPDst net.IP
- // TCP/UDP source port number or equivalent
- PortSrc uint32
- // TCP/UDP destination port number or equivalent
- PortDst uint32
- // TCP flags
- TCPFlags uint32
- // IP priority
- Priority uint32
- }
- func decodeSFlowIpv6Record(data *[]byte) (SFlowIpv6Record, error) {
- si := SFlowIpv6Record{}
- *data, si.Length = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.Protocol = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.IPSrc = (*data)[16:], net.IP((*data)[:16])
- *data, si.IPDst = (*data)[16:], net.IP((*data)[:16])
- *data, si.PortSrc = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.PortDst = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.TCPFlags = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, si.Priority = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return si, nil
- }
- // **************************************************
- // Extended IPv4 Tunnel Egress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Packet IP version 4 Record /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedIpv4TunnelEgressRecord struct {
- SFlowBaseFlowRecord
- SFlowIpv4Record SFlowIpv4Record
- }
- func decodeExtendedIpv4TunnelEgress(data *[]byte) (SFlowExtendedIpv4TunnelEgressRecord, error) {
- rec := SFlowExtendedIpv4TunnelEgressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
- return rec, nil
- }
- // **************************************************
- // Extended IPv4 Tunnel Ingress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Packet IP version 4 Record /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedIpv4TunnelIngressRecord struct {
- SFlowBaseFlowRecord
- SFlowIpv4Record SFlowIpv4Record
- }
- func decodeExtendedIpv4TunnelIngress(data *[]byte) (SFlowExtendedIpv4TunnelIngressRecord, error) {
- rec := SFlowExtendedIpv4TunnelIngressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- rec.SFlowIpv4Record, _ = decodeSFlowIpv4Record(data)
- return rec, nil
- }
- // **************************************************
- // Extended IPv6 Tunnel Egress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Packet IP version 6 Record /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedIpv6TunnelEgressRecord struct {
- SFlowBaseFlowRecord
- SFlowIpv6Record
- }
- func decodeExtendedIpv6TunnelEgress(data *[]byte) (SFlowExtendedIpv6TunnelEgressRecord, error) {
- rec := SFlowExtendedIpv6TunnelEgressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
- return rec, nil
- }
- // **************************************************
- // Extended IPv6 Tunnel Ingress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / Packet IP version 6 Record /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedIpv6TunnelIngressRecord struct {
- SFlowBaseFlowRecord
- SFlowIpv6Record
- }
- func decodeExtendedIpv6TunnelIngress(data *[]byte) (SFlowExtendedIpv6TunnelIngressRecord, error) {
- rec := SFlowExtendedIpv6TunnelIngressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- rec.SFlowIpv6Record, _ = decodeSFlowIpv6Record(data)
- return rec, nil
- }
- // **************************************************
- // Extended Decapsulate Egress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Inner Header Offset |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedDecapsulateEgressRecord struct {
- SFlowBaseFlowRecord
- InnerHeaderOffset uint32
- }
- func decodeExtendedDecapsulateEgress(data *[]byte) (SFlowExtendedDecapsulateEgressRecord, error) {
- rec := SFlowExtendedDecapsulateEgressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return rec, nil
- }
- // **************************************************
- // Extended Decapsulate Ingress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Inner Header Offset |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedDecapsulateIngressRecord struct {
- SFlowBaseFlowRecord
- InnerHeaderOffset uint32
- }
- func decodeExtendedDecapsulateIngress(data *[]byte) (SFlowExtendedDecapsulateIngressRecord, error) {
- rec := SFlowExtendedDecapsulateIngressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.InnerHeaderOffset = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return rec, nil
- }
- // **************************************************
- // Extended VNI Egress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | VNI |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedVniEgressRecord struct {
- SFlowBaseFlowRecord
- VNI uint32
- }
- func decodeExtendedVniEgress(data *[]byte) (SFlowExtendedVniEgressRecord, error) {
- rec := SFlowExtendedVniEgressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return rec, nil
- }
- // **************************************************
- // Extended VNI Ingress
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | VNI |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowExtendedVniIngressRecord struct {
- SFlowBaseFlowRecord
- VNI uint32
- }
- func decodeExtendedVniIngress(data *[]byte) (SFlowExtendedVniIngressRecord, error) {
- rec := SFlowExtendedVniIngressRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- rec.EnterpriseID, rec.Format = fdf.decode()
- *data, rec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, rec.VNI = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return rec, nil
- }
- // **************************************************
- // Counter Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | counter length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / counter data /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowBaseCounterRecord struct {
- EnterpriseID SFlowEnterpriseID
- Format SFlowCounterRecordType
- FlowDataLength uint32
- }
- func (bcr SFlowBaseCounterRecord) GetType() SFlowCounterRecordType {
- switch bcr.Format {
- case SFlowTypeGenericInterfaceCounters:
- return SFlowTypeGenericInterfaceCounters
- case SFlowTypeEthernetInterfaceCounters:
- return SFlowTypeEthernetInterfaceCounters
- case SFlowTypeTokenRingInterfaceCounters:
- return SFlowTypeTokenRingInterfaceCounters
- case SFlowType100BaseVGInterfaceCounters:
- return SFlowType100BaseVGInterfaceCounters
- case SFlowTypeVLANCounters:
- return SFlowTypeVLANCounters
- case SFlowTypeLACPCounters:
- return SFlowTypeLACPCounters
- case SFlowTypeProcessorCounters:
- return SFlowTypeProcessorCounters
- case SFlowTypeOpenflowPortCounters:
- return SFlowTypeOpenflowPortCounters
- case SFlowTypePORTNAMECounters:
- return SFlowTypePORTNAMECounters
- case SFLowTypeAPPRESOURCESCounters:
- return SFLowTypeAPPRESOURCESCounters
- case SFlowTypeOVSDPCounters:
- return SFlowTypeOVSDPCounters
- }
- unrecognized := fmt.Sprint("Unrecognized counter record type:", bcr.Format)
- panic(unrecognized)
- }
- // **************************************************
- // Counter Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | counter length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfIndex |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfType |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfSpeed |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfDirection |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfStatus |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IFInOctets |
- // | |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfInUcastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfInMulticastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfInBroadcastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfInDiscards |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | InInErrors |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfInUnknownProtos |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOutOctets |
- // | |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOutUcastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOutMulticastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOutBroadcastPkts |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOutDiscards |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfOUtErrors |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | IfPromiscouousMode |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowGenericInterfaceCounters struct {
- SFlowBaseCounterRecord
- IfIndex uint32
- IfType uint32
- IfSpeed uint64
- IfDirection uint32
- IfStatus uint32
- IfInOctets uint64
- IfInUcastPkts uint32
- IfInMulticastPkts uint32
- IfInBroadcastPkts uint32
- IfInDiscards uint32
- IfInErrors uint32
- IfInUnknownProtos uint32
- IfOutOctets uint64
- IfOutUcastPkts uint32
- IfOutMulticastPkts uint32
- IfOutBroadcastPkts uint32
- IfOutDiscards uint32
- IfOutErrors uint32
- IfPromiscuousMode uint32
- }
- func decodeGenericInterfaceCounters(data *[]byte) (SFlowGenericInterfaceCounters, error) {
- gic := SFlowGenericInterfaceCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- gic.EnterpriseID, gic.Format = cdf.decode()
- *data, gic.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfIndex = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfType = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfSpeed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, gic.IfDirection = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfStatus = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, gic.IfInUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfInUnknownProtos = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfOutOctets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, gic.IfOutUcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfOutMulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfOutBroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfOutDiscards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfOutErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, gic.IfPromiscuousMode = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return gic, nil
- }
- // **************************************************
- // Counter Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | counter length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // / counter data /
- // / /
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowEthernetCounters struct {
- SFlowBaseCounterRecord
- AlignmentErrors uint32
- FCSErrors uint32
- SingleCollisionFrames uint32
- MultipleCollisionFrames uint32
- SQETestErrors uint32
- DeferredTransmissions uint32
- LateCollisions uint32
- ExcessiveCollisions uint32
- InternalMacTransmitErrors uint32
- CarrierSenseErrors uint32
- FrameTooLongs uint32
- InternalMacReceiveErrors uint32
- SymbolErrors uint32
- }
- func decodeEthernetCounters(data *[]byte) (SFlowEthernetCounters, error) {
- ec := SFlowEthernetCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- ec.EnterpriseID, ec.Format = cdf.decode()
- *data, ec.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.AlignmentErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.FCSErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.SingleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.MultipleCollisionFrames = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.SQETestErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.DeferredTransmissions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.LateCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.ExcessiveCollisions = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.InternalMacTransmitErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.CarrierSenseErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.FrameTooLongs = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.InternalMacReceiveErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ec.SymbolErrors = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return ec, nil
- }
- // VLAN Counter
- type SFlowVLANCounters struct {
- SFlowBaseCounterRecord
- VlanID uint32
- Octets uint64
- UcastPkts uint32
- MulticastPkts uint32
- BroadcastPkts uint32
- Discards uint32
- }
- func decodeVLANCounters(data *[]byte) (SFlowVLANCounters, error) {
- vc := SFlowVLANCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- vc.EnterpriseID, vc.Format = cdf.decode()
- vc.EnterpriseID, vc.Format = cdf.decode()
- *data, vc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, vc.VlanID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, vc.Octets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, vc.UcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, vc.MulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, vc.BroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, vc.Discards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return vc, nil
- }
- //SFLLACPportState : SFlow LACP Port State (All(4) - 32 bit)
- type SFLLACPPortState struct {
- PortStateAll uint32
- }
- //LACPcounters : LACP SFlow Counters ( 64 Bytes )
- type SFlowLACPCounters struct {
- SFlowBaseCounterRecord
- ActorSystemID net.HardwareAddr
- PartnerSystemID net.HardwareAddr
- AttachedAggID uint32
- LacpPortState SFLLACPPortState
- LACPDUsRx uint32
- MarkerPDUsRx uint32
- MarkerResponsePDUsRx uint32
- UnknownRx uint32
- IllegalRx uint32
- LACPDUsTx uint32
- MarkerPDUsTx uint32
- MarkerResponsePDUsTx uint32
- }
- func decodeLACPCounters(data *[]byte) (SFlowLACPCounters, error) {
- la := SFlowLACPCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- la.EnterpriseID, la.Format = cdf.decode()
- *data, la.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.ActorSystemID = (*data)[6:], (*data)[:6]
- *data = (*data)[2:] // remove padding
- *data, la.PartnerSystemID = (*data)[6:], (*data)[:6]
- *data = (*data)[2:] //remove padding
- *data, la.AttachedAggID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.LacpPortState.PortStateAll = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.LACPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.MarkerPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.MarkerResponsePDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.UnknownRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.IllegalRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.LACPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.MarkerPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, la.MarkerResponsePDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return la, nil
- }
- // **************************************************
- // Processor Counter Record
- // **************************************************
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | counter length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | FiveSecCpu |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | OneMinCpu |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | GiveMinCpu |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | TotalMemory |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | FreeMemory |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- type SFlowProcessorCounters struct {
- SFlowBaseCounterRecord
- FiveSecCpu uint32 // 5 second average CPU utilization
- OneMinCpu uint32 // 1 minute average CPU utilization
- FiveMinCpu uint32 // 5 minute average CPU utilization
- TotalMemory uint64 // total memory (in bytes)
- FreeMemory uint64 // free memory (in bytes)
- }
- func decodeProcessorCounters(data *[]byte) (SFlowProcessorCounters, error) {
- pc := SFlowProcessorCounters{}
- var cdf SFlowCounterDataFormat
- var high32, low32 uint32
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- pc.EnterpriseID, pc.Format = cdf.decode()
- *data, pc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, pc.FiveSecCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, pc.OneMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, pc.FiveMinCpu = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- pc.TotalMemory = (uint64(high32) << 32) + uint64(low32)
- *data, high32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, low32 = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- pc.FreeMemory = (uint64(high32)) + uint64(low32)
- return pc, nil
- }
- // SFlowEthernetFrameFlowRecord give additional information
- // about the sampled packet if it's available.
- // An agent may or may not provide this information.
- type SFlowEthernetFrameFlowRecord struct {
- SFlowBaseFlowRecord
- FrameLength uint32
- SrcMac net.HardwareAddr
- DstMac net.HardwareAddr
- Type uint32
- }
- // Ethernet frame flow records have the following structure:
- // 0 15 31
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | 20 bit Interprise (0) |12 bit format |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | record length |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Source Mac Address |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Destination Mac Address |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | Ethernet Packet Type |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- func decodeEthernetFrameFlowRecord(data *[]byte) (SFlowEthernetFrameFlowRecord, error) {
- es := SFlowEthernetFrameFlowRecord{}
- var fdf SFlowFlowDataFormat
- *data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- es.EnterpriseID, es.Format = fdf.decode()
- *data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, es.SrcMac = (*data)[8:], net.HardwareAddr((*data)[:6])
- *data, es.DstMac = (*data)[8:], net.HardwareAddr((*data)[:6])
- *data, es.Type = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return es, nil
- }
- //SFlowOpenflowPortCounters : OVS-Sflow OpenFlow Port Counter ( 20 Bytes )
- type SFlowOpenflowPortCounters struct {
- SFlowBaseCounterRecord
- DatapathID uint64
- PortNo uint32
- }
- func decodeOpenflowportCounters(data *[]byte) (SFlowOpenflowPortCounters, error) {
- ofp := SFlowOpenflowPortCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- ofp.EnterpriseID, ofp.Format = cdf.decode()
- *data, ofp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, ofp.DatapathID = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, ofp.PortNo = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return ofp, nil
- }
- //SFlowAppresourcesCounters : OVS_Sflow App Resources Counter ( 48 Bytes )
- type SFlowAppresourcesCounters struct {
- SFlowBaseCounterRecord
- UserTime uint32
- SystemTime uint32
- MemUsed uint64
- MemMax uint64
- FdOpen uint32
- FdMax uint32
- ConnOpen uint32
- ConnMax uint32
- }
- func decodeAppresourcesCounters(data *[]byte) (SFlowAppresourcesCounters, error) {
- app := SFlowAppresourcesCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- app.EnterpriseID, app.Format = cdf.decode()
- *data, app.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.UserTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.SystemTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.MemUsed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, app.MemMax = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
- *data, app.FdOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.FdMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.ConnOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, app.ConnMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return app, nil
- }
- //SFlowOVSDPCounters : OVS-Sflow DataPath Counter ( 32 Bytes )
- type SFlowOVSDPCounters struct {
- SFlowBaseCounterRecord
- NHit uint32
- NMissed uint32
- NLost uint32
- NMaskHit uint32
- NFlows uint32
- NMasks uint32
- }
- func decodeOVSDPCounters(data *[]byte) (SFlowOVSDPCounters, error) {
- dp := SFlowOVSDPCounters{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- dp.EnterpriseID, dp.Format = cdf.decode()
- *data, dp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NMissed = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NLost = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NMaskHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NFlows = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, dp.NMasks = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- return dp, nil
- }
- //SFlowPORTNAME : OVS-Sflow PORTNAME Counter Sampletype ( 20 Bytes )
- type SFlowPORTNAME struct {
- SFlowBaseCounterRecord
- Len uint32
- Str string
- }
- func decodePortnameCounters(data *[]byte) (SFlowPORTNAME, error) {
- pn := SFlowPORTNAME{}
- var cdf SFlowCounterDataFormat
- *data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
- pn.EnterpriseID, pn.Format = cdf.decode()
- *data, pn.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, pn.Len = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
- *data, pn.Str = (*data)[8:], string(binary.BigEndian.Uint64((*data)[:8]))
- return pn, nil
- }
|