The same bug is reported for version < 1.6
The calculation of master_record_t->last/first field is incorrect in Process_v9_data function.
The below mentioned code reference is from nfdump1.5.7, but the similar issue exists in nfdump1.6.1.
----------------------------------------------------------------------------------------------------------------------------------------------------
How do nfcapd calculate exporter boot time ?
For every template/data flowset we calculate exporter router's boot time.
/* calculate boot time in msec */
v9_header->SysUptime = ntohl(v9_header->SysUptime);
v9_header->unix_secs = ntohl(v9_header->unix_secs);
exporter->boot_time = (uint64_t)1000 * (uint64_t)(v9_header->unix_secs) - (uint64_t)v9_header->SysUptime;
where
sys_uptime 4-7( 4Bytes field) Current time in milliseconds since the export device booted.
unix_secs 8-11(4 Bytes field) Time in seconds since 0000 UTC 1970, at which the Export Packet
leaves the Exporter.
sys_uptime is a 4 byte field, so it will overflow after 4294967296 msec ( ~ 50 days). So after every ~50 days, the exporter's boot_time will shift by ~50 days.
How do nfcapd calculate the time stamp ( since 0000 UTC 1970 ) for a netflow record ( we save this in master_record->last field) ?
First = data_record->first;
Last = data_record->last;
if ( First > Last )
/* Last in msec, in case of msec overflow, between start and end */
end_time = 0x100000000LL + Last + exporter->boot_time;
else
end_time = (uint64_t)Last + exporter->boot_time;
data_record->last = end_time/1000;
Here first, last field of data_record( master_record_t) are :
LAST_SWITCHED 21 4 Bytes field System uptime at which the last packet of this flow was switched
FIRST_SWITCHED 22 4 Bytes field System uptime at which the first packet of this flow was switched
These fields are 4 bytes fields, so they will overflow after ~50 days.
Consider these conditions for a netflow record.
Condition #1
sys_uptime/last_switched/first_switched have crossed the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
- first/last_switched:: after overflow the value in these fields will be like offset after 50 days.
In this condition the calculation of data_record->last field is correct.
Condition #2
sys_uptime has crossed the 50 days boundary. But first/last_switched did not cross the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
- first/last_switched:: they are the offset from the previous exporter_boot->time boundary.
In this condition the calculation for end_time is wrong ( end_time = (uint64_t)Last + exporter->boot_time; )
Condition #3
sys_uptime & last_switched have crossed the 50 days boundary. But first_switched did not cross the 50 days boundary.
- sys_uptime overflows :: exporter->boot_time will shift by 50 days.
-last_switched:: after overflow the value in these fields will be like offset after 50 days.
In this situation First > Last condition will hold true. But the calculation for this case is again wrong ( end_time = 0x100000000LL + Last + exporter->boot_time; ).
Here we don't need to add the 0x100000000L value to Last.