1
0
mirror of https://github.com/netsampler/goflow2.git synced 2024-05-06 15:54:52 +00:00
Vincent Bernat e3f8f990ec Add some tests for Netflow decoding
The tests are a bit more expansive than the existing tests for sFlow
or NFv5 as we check the whole structure. I am also testing the
String() function as it is easier to read. It is a bit redundant, but
checking only for the wire format makes it difficult to compare with
Wireshark. Only testing for the textual representation is not totally
good as it is not what is used by users of the decode function.
2022-02-26 16:47:08 +01:00

318 lines
9.9 KiB
Go

package netflow
import (
"fmt"
"time"
)
const (
NFV9_FIELD_IN_BYTES = 1
NFV9_FIELD_IN_PKTS = 2
NFV9_FIELD_FLOWS = 3
NFV9_FIELD_PROTOCOL = 4
NFV9_FIELD_SRC_TOS = 5
NFV9_FIELD_TCP_FLAGS = 6
NFV9_FIELD_L4_SRC_PORT = 7
NFV9_FIELD_IPV4_SRC_ADDR = 8
NFV9_FIELD_SRC_MASK = 9
NFV9_FIELD_INPUT_SNMP = 10
NFV9_FIELD_L4_DST_PORT = 11
NFV9_FIELD_IPV4_DST_ADDR = 12
NFV9_FIELD_DST_MASK = 13
NFV9_FIELD_OUTPUT_SNMP = 14
NFV9_FIELD_IPV4_NEXT_HOP = 15
NFV9_FIELD_SRC_AS = 16
NFV9_FIELD_DST_AS = 17
NFV9_FIELD_BGP_IPV4_NEXT_HOP = 18
NFV9_FIELD_MUL_DST_PKTS = 19
NFV9_FIELD_MUL_DST_BYTES = 20
NFV9_FIELD_LAST_SWITCHED = 21
NFV9_FIELD_FIRST_SWITCHED = 22
NFV9_FIELD_OUT_BYTES = 23
NFV9_FIELD_OUT_PKTS = 24
NFV9_FIELD_MIN_PKT_LNGTH = 25
NFV9_FIELD_MAX_PKT_LNGTH = 26
NFV9_FIELD_IPV6_SRC_ADDR = 27
NFV9_FIELD_IPV6_DST_ADDR = 28
NFV9_FIELD_IPV6_SRC_MASK = 29
NFV9_FIELD_IPV6_DST_MASK = 30
NFV9_FIELD_IPV6_FLOW_LABEL = 31
NFV9_FIELD_ICMP_TYPE = 32
NFV9_FIELD_MUL_IGMP_TYPE = 33
NFV9_FIELD_SAMPLING_INTERVAL = 34
NFV9_FIELD_SAMPLING_ALGORITHM = 35
NFV9_FIELD_FLOW_ACTIVE_TIMEOUT = 36
NFV9_FIELD_FLOW_INACTIVE_TIMEOUT = 37
NFV9_FIELD_ENGINE_TYPE = 38
NFV9_FIELD_ENGINE_ID = 39
NFV9_FIELD_TOTAL_BYTES_EXP = 40
NFV9_FIELD_TOTAL_PKTS_EXP = 41
NFV9_FIELD_TOTAL_FLOWS_EXP = 42
NFV9_FIELD_IPV4_SRC_PREFIX = 44
NFV9_FIELD_IPV4_DST_PREFIX = 45
NFV9_FIELD_MPLS_TOP_LABEL_TYPE = 46
NFV9_FIELD_MPLS_TOP_LABEL_IP_ADDR = 47
NFV9_FIELD_FLOW_SAMPLER_ID = 48
NFV9_FIELD_FLOW_SAMPLER_MODE = 49
NFV9_FIELD_FLOW_SAMPLER_RANDOM_INTERVAL = 50
NFV9_FIELD_MIN_TTL = 52
NFV9_FIELD_MAX_TTL = 53
NFV9_FIELD_IPV4_IDENT = 54
NFV9_FIELD_DST_TOS = 55
NFV9_FIELD_IN_SRC_MAC = 56
NFV9_FIELD_OUT_DST_MAC = 57
NFV9_FIELD_SRC_VLAN = 58
NFV9_FIELD_DST_VLAN = 59
NFV9_FIELD_IP_PROTOCOL_VERSION = 60
NFV9_FIELD_DIRECTION = 61
NFV9_FIELD_IPV6_NEXT_HOP = 62
NFV9_FIELD_BGP_IPV6_NEXT_HOP = 63
NFV9_FIELD_IPV6_OPTION_HEADERS = 64
NFV9_FIELD_MPLS_LABEL_1 = 70
NFV9_FIELD_MPLS_LABEL_2 = 71
NFV9_FIELD_MPLS_LABEL_3 = 72
NFV9_FIELD_MPLS_LABEL_4 = 73
NFV9_FIELD_MPLS_LABEL_5 = 74
NFV9_FIELD_MPLS_LABEL_6 = 75
NFV9_FIELD_MPLS_LABEL_7 = 76
NFV9_FIELD_MPLS_LABEL_8 = 77
NFV9_FIELD_MPLS_LABEL_9 = 78
NFV9_FIELD_MPLS_LABEL_10 = 79
NFV9_FIELD_IN_DST_MAC = 80
NFV9_FIELD_OUT_SRC_MAC = 81
NFV9_FIELD_IF_NAME = 82
NFV9_FIELD_IF_DESC = 83
NFV9_FIELD_SAMPLER_NAME = 84
NFV9_FIELD_IN_PERMANENT_BYTES = 85
NFV9_FIELD_IN_PERMANENT_PKTS = 86
NFV9_FIELD_FRAGMENT_OFFSET = 88
NFV9_FIELD_FORWARDING_STATUS = 89
NFV9_FIELD_MPLS_PAL_RD = 90
NFV9_FIELD_MPLS_PREFIX_LEN = 91
NFV9_FIELD_SRC_TRAFFIC_INDEX = 92
NFV9_FIELD_DST_TRAFFIC_INDEX = 93
NFV9_FIELD_APPLICATION_DESCRIPTION = 94
NFV9_FIELD_APPLICATION_TAG = 95
NFV9_FIELD_APPLICATION_NAME = 96
NFV9_FIELD_postipDiffServCodePoint = 98
NFV9_FIELD_replication_factor = 99
NFV9_FIELD_layer2packetSectionOffset = 102
NFV9_FIELD_layer2packetSectionSize = 103
NFV9_FIELD_layer2packetSectionData = 104
)
type NFv9Packet struct {
Version uint16
Count uint16
SystemUptime uint32
UnixSeconds uint32
SequenceNumber uint32
SourceId uint32
FlowSets []interface{}
}
type NFv9OptionsTemplateFlowSet struct {
FlowSetHeader
Records []NFv9OptionsTemplateRecord
}
type NFv9OptionsTemplateRecord struct {
TemplateId uint16
ScopeLength uint16
OptionLength uint16
Scopes []Field
Options []Field
}
func NFv9TypeToString(typeId uint16) string {
nameList := map[uint16]string{
1: "IN_BYTES",
2: "IN_PKTS",
3: "FLOWS",
4: "PROTOCOL",
5: "SRC_TOS",
6: "TCP_FLAGS",
7: "L4_SRC_PORT",
8: "IPV4_SRC_ADDR",
9: "SRC_MASK",
10: "INPUT_SNMP",
11: "L4_DST_PORT",
12: "IPV4_DST_ADDR",
13: "DST_MASK",
14: "OUTPUT_SNMP",
15: "IPV4_NEXT_HOP",
16: "SRC_AS",
17: "DST_AS",
18: "BGP_IPV4_NEXT_HOP",
19: "MUL_DST_PKTS",
20: "MUL_DST_BYTES",
21: "LAST_SWITCHED",
22: "FIRST_SWITCHED",
23: "OUT_BYTES",
24: "OUT_PKTS",
25: "MIN_PKT_LNGTH",
26: "MAX_PKT_LNGTH",
27: "IPV6_SRC_ADDR",
28: "IPV6_DST_ADDR",
29: "IPV6_SRC_MASK",
30: "IPV6_DST_MASK",
31: "IPV6_FLOW_LABEL",
32: "ICMP_TYPE",
33: "MUL_IGMP_TYPE",
34: "SAMPLING_INTERVAL",
35: "SAMPLING_ALGORITHM",
36: "FLOW_ACTIVE_TIMEOUT",
37: "FLOW_INACTIVE_TIMEOUT",
38: "ENGINE_TYPE",
39: "ENGINE_ID",
40: "TOTAL_BYTES_EXP",
41: "TOTAL_PKTS_EXP",
42: "TOTAL_FLOWS_EXP",
43: "*Vendor Proprietary*",
44: "IPV4_SRC_PREFIX",
45: "IPV4_DST_PREFIX",
46: "MPLS_TOP_LABEL_TYPE",
47: "MPLS_TOP_LABEL_IP_ADDR",
48: "FLOW_SAMPLER_ID",
49: "FLOW_SAMPLER_MODE",
50: "FLOW_SAMPLER_RANDOM_INTERVAL",
51: "*Vendor Proprietary*",
52: "MIN_TTL",
53: "MAX_TTL",
54: "IPV4_IDENT",
55: "DST_TOS",
56: "IN_SRC_MAC",
57: "OUT_DST_MAC",
58: "SRC_VLAN",
59: "DST_VLAN",
60: "IP_PROTOCOL_VERSION",
61: "DIRECTION",
62: "IPV6_NEXT_HOP",
63: "BPG_IPV6_NEXT_HOP",
64: "IPV6_OPTION_HEADERS",
65: "*Vendor Proprietary*",
66: "*Vendor Proprietary*",
67: "*Vendor Proprietary*",
68: "*Vendor Proprietary*",
69: "*Vendor Proprietary*",
70: "MPLS_LABEL_1",
71: "MPLS_LABEL_2",
72: "MPLS_LABEL_3",
73: "MPLS_LABEL_4",
74: "MPLS_LABEL_5",
75: "MPLS_LABEL_6",
76: "MPLS_LABEL_7",
77: "MPLS_LABEL_8",
78: "MPLS_LABEL_9",
79: "MPLS_LABEL_10",
80: "IN_DST_MAC",
81: "OUT_SRC_MAC",
82: "IF_NAME",
83: "IF_DESC",
84: "SAMPLER_NAME",
85: "IN_ PERMANENT _BYTES",
86: "IN_ PERMANENT _PKTS",
87: "*Vendor Proprietary*",
88: "FRAGMENT_OFFSET",
89: "FORWARDING STATUS",
90: "MPLS PAL RD",
91: "MPLS PREFIX LEN",
92: "SRC TRAFFIC INDEX",
93: "DST TRAFFIC INDEX",
94: "APPLICATION DESCRIPTION",
95: "APPLICATION TAG",
96: "APPLICATION NAME",
98: "postipDiffServCodePoint",
99: "replication factor",
100: "DEPRECATED",
102: "layer2packetSectionOffset",
103: "layer2packetSectionSize",
104: "layer2packetSectionData",
234: "ingressVRFID",
235: "egressVRFID",
}
if typeId > 104 || typeId == 0 {
return "Unassigned"
} else {
return nameList[typeId]
}
}
func NFv9ScopeToString(scopeId uint16) string {
nameList := map[uint16]string{
1: "System",
2: "Interface",
3: "Line Card",
4: "NetFlow Cache",
5: "Template",
}
if scopeId >= 1 && scopeId <= 5 {
return nameList[scopeId]
} else {
return "Unassigned"
}
}
func (flowSet NFv9OptionsTemplateFlowSet) String(TypeToString func(uint16) string) string {
str := fmt.Sprintf(" Id %v\n", flowSet.Id)
str += fmt.Sprintf(" Length: %v\n", flowSet.Length)
str += fmt.Sprintf(" Records (%v records):\n", len(flowSet.Records))
for j, record := range flowSet.Records {
str += fmt.Sprintf(" - Record %v:\n", j)
str += fmt.Sprintf(" TemplateId: %v\n", record.TemplateId)
str += fmt.Sprintf(" ScopeLength: %v\n", record.ScopeLength)
str += fmt.Sprintf(" OptionLength: %v\n", record.OptionLength)
str += fmt.Sprintf(" Scopes (%v):\n", len(record.Scopes))
for k, field := range record.Scopes {
str += fmt.Sprintf(" - %v. %v (%v): %v\n", k, NFv9ScopeToString(field.Type), field.Type, field.Length)
}
str += fmt.Sprintf(" Options (%v):\n", len(record.Options))
for k, field := range record.Options {
str += fmt.Sprintf(" - %v. %v (%v): %v\n", k, TypeToString(field.Type), field.Type, field.Length)
}
}
return str
}
func (p NFv9Packet) String() string {
str := "Flow Packet\n"
str += "------------\n"
str += fmt.Sprintf(" Version: %v\n", p.Version)
str += fmt.Sprintf(" Count: %v\n", p.Count)
unixSeconds := time.Unix(int64(p.UnixSeconds), 0)
str += fmt.Sprintf(" SystemUptime: %v\n", p.SystemUptime)
str += fmt.Sprintf(" UnixSeconds: %v\n", unixSeconds.UTC().String())
str += fmt.Sprintf(" SequenceNumber: %v\n", p.SequenceNumber)
str += fmt.Sprintf(" SourceId: %v\n", p.SourceId)
str += fmt.Sprintf(" FlowSets (%v):\n", len(p.FlowSets))
for i, flowSet := range p.FlowSets {
switch flowSet := flowSet.(type) {
case TemplateFlowSet:
str += fmt.Sprintf(" - TemplateFlowSet %v:\n", i)
str += flowSet.String(NFv9TypeToString)
case NFv9OptionsTemplateFlowSet:
str += fmt.Sprintf(" - OptionsTemplateFlowSet %v:\n", i)
str += flowSet.String(NFv9TypeToString)
case DataFlowSet:
str += fmt.Sprintf(" - DataFlowSet %v:\n", i)
str += flowSet.String(NFv9TypeToString)
case OptionsDataFlowSet:
str += fmt.Sprintf(" - OptionsDataFlowSet %v:\n", i)
str += flowSet.String(NFv9TypeToString, NFv9ScopeToString)
default:
str += fmt.Sprintf(" - (unknown type) %v: %v\n", i, flowSet)
}
}
return str
}