Skip to content

Commit 5ce5882

Browse files
authored
Netanol 201 sflow parser implementation (#79)
* feat(sflow): parse sflow header and samples Introduces parsing capabilities for sFlow headers and samples, including CounterSample and FlowSample. Restructures the SflowReader logic for better adherence to the specification. Documentation and testing are also added for the sFlow parser. Fixes were made to handle multiple records in a sample and adjust RawPacketHeader initialization for accuracy.
1 parent 714e727 commit 5ce5882

33 files changed

+991
-20
lines changed
19.4 KB
Binary file not shown.

Packrat/DotNetFlow/DotNetFlow.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
<PackageProjectUrl>https://github.com/UniStuttgart-VISUS/dotnetflow</PackageProjectUrl>
1515
<RepositoryUrl>https://github.com/UniStuttgart-VISUS/dotnetflow</RepositoryUrl>
1616
<PackageTags>netflow ipfix</PackageTags>
17+
<LangVersion>8</LangVersion>
1718
</PropertyGroup>
1819

1920
<ItemGroup>
2021
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
22+
<PackageReference Include="PcapDotNet" Version="0.10.2" />
23+
<PackageReference Include="PcapDotNet.Base" Version="1.0.4.1" />
24+
<PackageReference Include="PcapDotNet.Packets" Version="1.0.4.1" />
2125
</ItemGroup>
2226

2327
<ItemGroup>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// The format of the upcoming counter record.
5+
/// Can be extended to include other counter types.
6+
/// </summary>
7+
public enum CounterFormat
8+
{
9+
GenericInterfaceCounters = 1,
10+
EthernetInterfaceCounters = 2,
11+
VlanCounters = 5,
12+
InfiniBandCounters = 9
13+
}
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Base class for all counter records.
5+
/// </summary>
6+
public abstract class CounterRecord : IRecord
7+
{
8+
public Enterprise Enterprise { get; set; }
9+
public CounterFormat Format;
10+
}
11+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Collections.Generic;
2+
3+
namespace DotNetFlow.Sflow
4+
{
5+
/// <summary>
6+
/// A counter sample containing a set of counter records from a specific data source.
7+
/// </summary>
8+
public class CounterSample : ISample
9+
{
10+
public Enterprise Enterprise { get; set; }
11+
public SampleType Type { get; set; }
12+
public uint SampleLength { get; set; }
13+
public uint SequenceNumber { get; set; }
14+
public ushort SourceIdType { get; set; }
15+
public ushort SourceIdIndex { get; set; }
16+
public uint NumRecords { get; set; }
17+
public List<CounterRecord> CounterRecords { get; set; }
18+
}
19+
}

Packrat/DotNetFlow/Sflow/Datagram.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace DotNetFlow.Sflow
4+
{
5+
/// <summary>
6+
/// Represents an sFlow datagram.
7+
/// </summary>
8+
public class Datagram
9+
{
10+
public Header Header;
11+
List<ISample> Samples;
12+
}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents the sFlow SMI Private Enterprise Code.
5+
/// </summary>
6+
public enum Enterprise
7+
{
8+
StandardSflow = 0 // InMon Corporation
9+
}
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// The format of the upcoming flow record.
5+
/// Can be extended to include other flow types.
6+
/// </summary>
7+
public enum FlowFormat
8+
{
9+
RawPacketHeader = 1,
10+
EthernetFrame = 2,
11+
IPv4Header = 3,
12+
IPv6Header = 4,
13+
ExtendedSwitchData = 1001,
14+
ExtendedRouterData = 1002,
15+
ExtendedGatewayData = 1003,
16+
ExtendedUserFlowData = 1004
17+
}
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Base class for all flow records.
5+
/// </summary>
6+
public abstract class FlowRecord : IRecord
7+
{
8+
public Enterprise Enterprise { get; set; }
9+
public FlowFormat Format;
10+
}
11+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Collections.Generic;
2+
3+
namespace DotNetFlow.Sflow
4+
{
5+
/// <summary>
6+
/// A flow sample containing a set of flow records from a specific data source.
7+
/// </summary>
8+
public class FlowSample : ISample
9+
{
10+
public Enterprise Enterprise { get; set; }
11+
public SampleType Type { get; set; }
12+
public uint SampleLength { get; set; }
13+
public uint SequenceNumber { get; set; }
14+
public ushort SourceIdClass { get; set; }
15+
public ushort SourceIdIndex { get; set; }
16+
public uint SamplingRate { get; set; }
17+
public uint SamplePool { get; set; }
18+
public uint Drops { get; set; }
19+
public InterfaceInfo InputInterface { get; set; }
20+
public InterfaceInfo OutputInterface { get; set; }
21+
public uint NumRecords { get; set; }
22+
public List<FlowRecord> FlowRecords { get; set; }
23+
}
24+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents the direction of the interface.
5+
/// More detail can be found in the sFlow v5 specification.
6+
/// </summary>
7+
public enum IfDirection
8+
{
9+
Unknown = 0,
10+
FullDuplex = 1,
11+
HalfDuplex = 2,
12+
In = 3,
13+
Out = 4
14+
}
15+
16+
/// <summary>
17+
/// Represents the sFlow Generic Interface Counters record.
18+
/// </summary>
19+
public class GenericInterfaceCounters : CounterRecord
20+
{
21+
public Enterprise Enterprise { get; set; }
22+
public CounterFormat Format { get; set; }
23+
public uint FlowDataLength { get; set; }
24+
public uint IfIndex { get; set; }
25+
public uint IfType { get; set; }
26+
public uint IfSpeed { get; set; }
27+
public IfDirection IfDirection { get; set; }
28+
public ushort IfAdminStatus { get; set; }
29+
public ushort IfOperStatus { get; set; }
30+
public ulong InputOctets { get; set; }
31+
public uint InputPackets { get; set; }
32+
public uint InputMulticastPackets { get; set; }
33+
public uint InputBroadcastPackets { get; set; }
34+
public uint InputDiscardedPackets { get; set; }
35+
public uint InputErrors { get; set; }
36+
public uint InputUnknownProtocolPackets { get; set; }
37+
public ulong OutputOctets { get; set; }
38+
public uint OutputPackets { get; set; }
39+
public uint OutputMulticastPackets { get; set; }
40+
public uint OutputBroadcastPackets { get; set; }
41+
public uint OutputDiscardedPackets { get; set; }
42+
public uint OutputErrors { get; set; }
43+
public uint PromiscuousMode { get; set; }
44+
}
45+
}

Packrat/DotNetFlow/Sflow/Header.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Net;
2+
3+
namespace DotNetFlow.Sflow
4+
{
5+
/// <summary>
6+
/// Represents the sFlow header.
7+
/// </summary>
8+
public class Header
9+
{
10+
public uint Version; // sFlow version
11+
public uint AgentAddressType; // 1 for IPv4, 2 for IPv6
12+
public IPAddress AgentAddress; // The address of the sFlow agent
13+
public uint SubAgentId;
14+
public uint SequenceNumber;
15+
public uint SysUpTime; // System uptime in ms
16+
public uint NumSamples; // Number of samples in the datagram
17+
}
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents the first protocol of the sampled packet inside the <see cref="RawPacketHeader"/>.
5+
/// </summary>
6+
public enum HeaderProtocol
7+
{
8+
Ethernet = 1,
9+
Ppp = 7,
10+
Ipv4 = 11,
11+
Ipv6 = 12,
12+
Mpls = 13,
13+
}
14+
}

Packrat/DotNetFlow/Sflow/IRecord.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents an interface for all sFlow records.
5+
/// </summary>
6+
public interface IRecord
7+
{
8+
Enterprise Enterprise { get; set; }
9+
}
10+
}

Packrat/DotNetFlow/Sflow/ISample.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Interface for all sample types
5+
/// </summary>
6+
public interface ISample
7+
{
8+
Enterprise Enterprise { get; set; }
9+
SampleType Type { get; set; }
10+
}
11+
12+
/// <summary>
13+
/// Enumeration of the different sample types
14+
/// These are not all sample types, the most common are FlowSample and CounterSample.
15+
/// </summary>
16+
public enum SampleType
17+
{
18+
FlowSample = 1,
19+
CounterSample = 2,
20+
ExpandedFlowSample = 3,
21+
ExpandedCounterSample = 4
22+
}
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Net;
4+
using System.Runtime.InteropServices;
5+
using PcapDotNet.Packets;
6+
7+
namespace DotNetFlow.Sflow
8+
{
9+
public interface ISflowReader
10+
{
11+
// Datagram BuildDatagram(Stream datagramStream); // not sure if this is necessary
12+
Header ReadHeader(Stream datagramStream);
13+
IEnumerable<ISample> ReadSamples(Stream datagramStream, uint numSamples);
14+
}
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents the sFlow Interface Format.
5+
/// </summary>
6+
public enum InterfaceFormat
7+
{
8+
SingleInterface = 0,
9+
PacketDiscarded = 1,
10+
MultipleDestinationInterfaces = 2
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace DotNetFlow.Sflow
2+
{
3+
/// <summary>
4+
/// Represents the interface information. Either input or output.
5+
/// According to the sFlow v5 specification, the input interface can only be <see cref="InterfaceFormat.SingleInterface"/>.
6+
/// </summary>
7+
public class InterfaceInfo
8+
{
9+
public InterfaceFormat InterfaceFormat { get; set; }
10+
public uint InterfaceValue { get; set; }
11+
}
12+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using PcapDotNet.Packets;
2+
3+
namespace DotNetFlow.Sflow
4+
{
5+
/// <summary>
6+
/// Represents the sFlow Raw Packet Header record.
7+
/// </summary>
8+
public class RawPacketHeader : FlowRecord
9+
{
10+
public Enterprise Enterprise { get; set; }
11+
public FlowFormat Format { get; set; }
12+
public uint FlowDataLength { get; set; }
13+
public HeaderProtocol HeaderProtocol { get; set; }
14+
public uint FrameLength { get; set; }
15+
public uint StrippedBytes { get; set; }
16+
public uint SampledHeaderLength { get; set; }
17+
public Packet Packet { get; set; }
18+
}
19+
}

0 commit comments

Comments
 (0)