Skip to content

Commit 7265159

Browse files
authored
fix: NetFlow v9 bad timestamp calculation (#325)
Producer was assuming sysUptime was in seconds instead of milliseconds
1 parent 3dd0e8a commit 7265159

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

producer/proto/producer_nf.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,21 +538,22 @@ func ConvertNetFlowDataSet(flowMessage *ProtoProducerMessage, version uint16, ba
538538
default:
539539
if version == 9 {
540540
// NetFlow v9 time works with a differential based on router's uptime
541+
uptimeNs := uint64(uptime) * 1e6 // uptime is in milliseconds in NetFlow v9, converts to nanoseconds
541542
switch df.Type {
542543
case netflow.NFV9_FIELD_FIRST_SWITCHED:
543544
var timeFirstSwitched uint32
544545
if err := DecodeUNumber(v, &timeFirstSwitched); err != nil {
545546
return err
546547
}
547-
timeDiff := (uptime - timeFirstSwitched)
548-
flowMessage.TimeFlowStartNs = baseTimeNs - uint64(timeDiff)*1000000000
548+
timeDiff := (uptimeNs - uint64(timeFirstSwitched)*1e6)
549+
flowMessage.TimeFlowStartNs = baseTimeNs - timeDiff
549550
case netflow.NFV9_FIELD_LAST_SWITCHED:
550551
var timeLastSwitched uint32
551552
if err := DecodeUNumber(v, &timeLastSwitched); err != nil {
552553
return err
553554
}
554-
timeDiff := (uptime - timeLastSwitched)
555-
flowMessage.TimeFlowEndNs = baseTimeNs - uint64(timeDiff)*1000000000
555+
timeDiff := (uptimeNs - uint64(timeLastSwitched)*1e6)
556+
flowMessage.TimeFlowEndNs = baseTimeNs - timeDiff
556557
}
557558
} else if version == 10 {
558559
switch df.Type {

producer/proto/producer_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,19 @@ func TestProcessIPv4Fragment(t *testing.T) {
262262
assert.Equal(t, uint32(24025), flowMessage.FragmentId)
263263
assert.Equal(t, uint32(185), flowMessage.FragmentOffset)
264264
}
265+
266+
func TestNetFlowV9Time(t *testing.T) {
267+
// This test ensures the NetFlow v9 timestamps are properly calculated.
268+
// It passes a baseTime = 2024-01-01 00:00:00 (in seconds) and an uptime of 2 seconds (in milliseconds).
269+
// The flow record was logged at 1 second of uptime (in milliseconds).
270+
// The calculation is the following: baseTime - uptime + flowUptime.
271+
var flowMessage ProtoProducerMessage
272+
err := ConvertNetFlowDataSet(&flowMessage, 9, 1704067200, 2000, []netflow.DataField{
273+
netflow.DataField{
274+
Type: netflow.NFV9_FIELD_FIRST_SWITCHED,
275+
Value: []byte{0x0, 0x0, 0x03, 0xe8}, // 1000
276+
},
277+
}, nil, nil)
278+
assert.Nil(t, err)
279+
assert.Equal(t, uint64(1704067199)*1e9, flowMessage.TimeFlowStartNs)
280+
}

0 commit comments

Comments
 (0)