Skip to content

Commit 5695659

Browse files
authored
Fix netflow port numbers and start/finish (#715)
* Fix netflow port numbers and start/finish * Add unit tests for netflow v5
1 parent 9301d74 commit 5695659

3 files changed

Lines changed: 56 additions & 14 deletions

File tree

src/handlers/flow/test_flows.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <catch2/catch_test_macros.hpp>
2-
#include <catch2/matchers/catch_matchers.hpp>
32
#include <catch2/catch_test_visor.hpp>
3+
#include <catch2/matchers/catch_matchers.hpp>
44

55
#include "FlowInputStream.h"
66
#include "FlowStreamHandler.h"
@@ -399,7 +399,49 @@ TEST_CASE("Parse sflow stream with interfaces filter", "[sflow][flow]")
399399
CHECK(j["devices"]["192.168.0.11"]["interfaces"]["37"]["top_out_src_ips_and_port_bytes"][0]["estimate"] == nullptr);
400400
}
401401

402-
TEST_CASE("Parse netflow stream", "[netflow][flow]")
402+
TEST_CASE("Parse netflow v5 stream", "[netflow][flow]")
403+
{
404+
405+
FlowInputStream stream{"netflow-test"};
406+
stream.config_set("flow_type", "netflow");
407+
stream.config_set("pcap_file", "tests/fixtures/nf5.pcap");
408+
409+
visor::Config c;
410+
auto stream_proxy = stream.add_event_proxy(c);
411+
c.config_set<uint64_t>("num_periods", 1);
412+
FlowStreamHandler flow_handler{"flow-test", stream_proxy, &c};
413+
flow_handler.config_set<visor::Configurable::StringList>("enable", visor::Configurable::StringList({"top_tos"}));
414+
415+
flow_handler.start();
416+
stream.start();
417+
stream.stop();
418+
flow_handler.stop();
419+
420+
auto event_data = flow_handler.metrics()->bucket(0)->event_data_locked();
421+
422+
// confirmed with wireshark
423+
CHECK(event_data.num_events->value() == 2);
424+
CHECK(event_data.num_samples->value() == 2);
425+
426+
nlohmann::json j;
427+
flow_handler.metrics()->bucket(0)->to_json(j);
428+
429+
CHECK(j["devices"]["10.0.0.2"]["records_flows"] == 3);
430+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["cardinality"]["dst_ips_out"] == 2);
431+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["cardinality"]["src_ips_in"] == 1);
432+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["cardinality"]["dst_ports_out"] == 3);
433+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["cardinality"]["src_ports_in"] == 2);
434+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_src_ips_bytes"][0]["estimate"] == 1720);
435+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_src_ips_packets"][0]["estimate"] == 33);
436+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_dscp_bytes"][0]["estimate"] == 1220);
437+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_dscp_bytes"][0]["name"] == "CS6");
438+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_ecn_packets"][0]["estimate"] == 33);
439+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_ecn_packets"][0]["name"] == "Not-ECT");
440+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_dst_ports_bytes"][0]["estimate"] == 1128);
441+
CHECK(j["devices"]["10.0.0.2"]["interfaces"]["0"]["top_in_dst_ports_bytes"][0]["name"] == "telnet");
442+
}
443+
444+
TEST_CASE("Parse netflow v9 stream", "[netflow][flow]")
403445
{
404446

405447
FlowInputStream stream{"netflow-test"};

src/inputs/flow/NetflowData.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ static bool process_netflow_v1(NFSample *sample)
8787
memcpy(flow_sample.dst_ip.data(), &nf1_flow->dest_ip, sizeof(uint32_t));
8888
memcpy(flow_sample.nexthop_ip.data(), &nf1_flow->nexthop_ip, sizeof(uint32_t));
8989

90-
flow_sample.src_port = nf1_flow->src_port;
91-
flow_sample.dst_port = nf1_flow->dest_port;
90+
flow_sample.src_port = be16toh(nf1_flow->src_port);
91+
flow_sample.dst_port = be16toh(nf1_flow->dest_port);
9292

93-
flow_sample.flow_start = nf1_flow->flow_start;
94-
flow_sample.flow_finish = nf1_flow->flow_finish;
93+
flow_sample.flow_start = be32toh(nf1_flow->flow_start);
94+
flow_sample.flow_finish = be32toh(nf1_flow->flow_finish);
9595

9696
flow_sample.if_index_in = be16toh(nf1_flow->if_index_in);
9797
flow_sample.if_index_out = be16toh(nf1_flow->if_index_out);
@@ -136,11 +136,11 @@ static bool process_netflow_v5(NFSample *sample)
136136
memcpy(flow_sample.dst_ip.data(), &nf5_flow->dest_ip, sizeof(uint32_t));
137137
memcpy(flow_sample.nexthop_ip.data(), &nf5_flow->nexthop_ip, sizeof(uint32_t));
138138

139-
flow_sample.src_port = nf5_flow->src_port;
140-
flow_sample.dst_port = nf5_flow->dest_port;
139+
flow_sample.src_port = be16toh(nf5_flow->src_port);
140+
flow_sample.dst_port = be16toh(nf5_flow->dest_port);
141141

142-
flow_sample.flow_start = nf5_flow->flow_start;
143-
flow_sample.flow_finish = nf5_flow->flow_finish;
142+
flow_sample.flow_start = be32toh(nf5_flow->flow_start);
143+
flow_sample.flow_finish = be32toh(nf5_flow->flow_finish);
144144

145145
flow_sample.if_index_in = be16toh(nf5_flow->if_index_in);
146146
flow_sample.if_index_out = be16toh(nf5_flow->if_index_out);
@@ -190,11 +190,11 @@ static bool process_netflow_v7(NFSample *sample)
190190
memcpy(flow_sample.dst_ip.data(), &nf7_flow->dest_ip, sizeof(uint32_t));
191191
memcpy(flow_sample.nexthop_ip.data(), &nf7_flow->nexthop_ip, sizeof(uint32_t));
192192

193-
flow_sample.src_port = nf7_flow->src_port;
194-
flow_sample.dst_port = nf7_flow->dest_port;
193+
flow_sample.src_port = be16toh(nf7_flow->src_port);
194+
flow_sample.dst_port = be16toh(nf7_flow->dest_port);
195195

196-
flow_sample.flow_start = nf7_flow->flow_start;
197-
flow_sample.flow_finish = nf7_flow->flow_finish;
196+
flow_sample.flow_start = be32toh(nf7_flow->flow_start);
197+
flow_sample.flow_finish = be32toh(nf7_flow->flow_finish);
198198

199199
flow_sample.if_index_in = be16toh(nf7_flow->if_index_in);
200200
flow_sample.if_index_out = be16toh(nf7_flow->if_index_out);

src/tests/fixtures/nf5.pcap

332 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)