-
Notifications
You must be signed in to change notification settings - Fork 676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add nanosecond precision to TCP reassembly #1591
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## dev #1591 +/- ##
==========================================
+ Coverage 83.12% 83.14% +0.02%
==========================================
Files 276 276
Lines 46914 46964 +50
Branches 9346 9315 -31
==========================================
+ Hits 38998 39050 +52
+ Misses 7061 7055 -6
- Partials 855 859 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Packet++/header/TcpReassembly.h
Outdated
{ | ||
endTime = endTimeValue; | ||
} | ||
void setEndTime(const std::chrono::time_point<std::chrono::system_clock>& endTimeValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are the timepoints locked to system_clock
? Generally I would prefer steady_clock
for being monotonic, or high_resolution_clock
for being the clock with the highest resolution on the system. Ideally, it should be templated, but that might be more trouble than its worth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What we need here is a data structure that holds a timestamp in nanosecond precision. The timestamp itself comes from the packet:
PcapPlusPlus/Packet++/src/TcpReassembly.cpp
Line 142 in 634a786
auto currTime = timespecToTimePoint(tcpData.getRawPacket()->getPacketTimeStamp()); |
Does it matter if it's system_clock
, steady_clock
or high_resolution_clock
? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure tbh, but I think there are a some methods of timepoint that depend on the passed clock type. It probably won't really affect the current usage, as nowhere is Clock::now()
called. so idk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested it, apparently system_clock
doesn't have nanosecond precision on all platforms, however, high_resolution_clock
does so I think it's safe to use
Packet++/header/TcpReassembly.h
Outdated
timeval endTime; | ||
/** Start timestamp of the connection with nanosecond precision */ | ||
std::chrono::time_point<std::chrono::system_clock> startTimePrecise; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not guarantee that std::chrono::time_point<std::chrono::system_clock> have nano seconds resolution.
It depends on Clock::duration. On macOS, system_clock::duration is microseconds.
IMO i would explicit which clock::duration we want to have or change all the timeval to timespec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh, using timespec might be simpler, as the timepoints in the chrono library are more specialized to be used with a clock, and we get the time externally anyway so we don't really have one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see: #1591 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant we whould explicit the duration like this:
using time_point_ns = std::chrono::time_point<std::chrono::high_resolution_clock, std::chrono::nanoseconds>;
time_point_ns startTimePrecise;
time_point_ns endTimePrecise;
This will also work for std::chrono::system_clock
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to be explicit? If we do:
std::chrono::time_point<std::chrono::high_resolution_clock>
Then the user can decide which precision they want, for example, if they want nano sec they can do the following:
std::chrono::duration_cast<std::chrono::nanoseconds>(stats.begin()>second.connData.startTimePrecise.time_since_epoch())
But they can also get any other precision
- Add some tests
PTF_ASSERT_EQUAL(stats.begin()->second.connData.endTime.tv_usec, 0); | ||
PTF_ASSERT_EQUAL(std::chrono::duration_cast<std::chrono::nanoseconds>( | ||
stats.begin()->second.connData.startTimePrecise.time_since_epoch()) | ||
.count(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a better format here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so just ignore clang-format
? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can ignore it here as the format seems not perfect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in this commit b083640, please let me know if the format looks ok now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of comments, but LGTM otherwise.
Packet++/src/TcpReassembly.cpp
Outdated
auto duration = in.time_since_epoch(); | ||
|
||
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); | ||
auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration) % 1000000000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Could possibly be done without the magic number by casting the seconds to nanosecond precision and substracting that from the main duration to get the remaining nanoseconds, but I guess this works too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ture, I think Dimi's method will be more efficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ture, I think Dimi's method will be more efficient.
Looked through it in godbolt.org. It actually does not matter under optimizations. Both compile down to mostly the same assembly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing compiler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree! Fixed in 91f6b39
Packet++/src/TcpReassembly.cpp
Outdated
|
||
struct timeval out; | ||
out.tv_sec = seconds.count(); | ||
out.tv_usec = nanoseconds.count() / 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we calculate the nanosecond precision here if we are just going to convert them to microseconds? As far as I see, the nanosecond precision duration object is not used anywhere else in this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Fixed in 91f6b39
Should address this issue: #1189