-
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
Changes from 6 commits
634a786
c609925
e5027c4
4a846a5
eff26f2
fdb7f19
b083640
3c72ddb
91f6b39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,13 +23,44 @@ | |
namespace pcpp | ||
{ | ||
|
||
static timeval timespecToTimeval(const timespec& in) | ||
static timeval timePointToTimeval(const std::chrono::time_point<std::chrono::high_resolution_clock>& in) | ||
{ | ||
timeval out; | ||
TIMESPEC_TO_TIMEVAL(&out, &in); | ||
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; | ||
|
||
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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! Fixed in 91f6b39 |
||
return out; | ||
} | ||
|
||
static std::chrono::time_point<std::chrono::high_resolution_clock> timespecToTimePoint(const timespec& in) | ||
{ | ||
auto duration = std::chrono::duration_cast<std::chrono::high_resolution_clock::duration>( | ||
std::chrono::seconds(in.tv_sec) + std::chrono::nanoseconds(in.tv_nsec)); | ||
|
||
return std::chrono::time_point<std::chrono::high_resolution_clock>(duration); | ||
} | ||
|
||
void ConnectionData::setStartTime(const std::chrono::time_point<std::chrono::high_resolution_clock>& startTimeValue) | ||
{ | ||
startTime = timePointToTimeval(startTimeValue); | ||
startTimePrecise = startTimeValue; | ||
} | ||
|
||
void ConnectionData::setEndTime(const std::chrono::time_point<std::chrono::high_resolution_clock>& endTimeValue) | ||
{ | ||
endTime = timePointToTimeval(endTimeValue); | ||
endTimePrecise = endTimeValue; | ||
} | ||
|
||
timeval TcpStreamData::getTimeStamp() const | ||
{ | ||
return timePointToTimeval(m_Timestamp); | ||
} | ||
|
||
TcpReassembly::TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie, | ||
OnTcpConnectionStart onConnectionStartCallback, | ||
OnTcpConnectionEnd onConnectionEndCallback, const TcpReassemblyConfiguration& config) | ||
|
@@ -109,7 +140,7 @@ namespace pcpp | |
uint32_t flowKey = hash5Tuple(&tcpData); | ||
|
||
// time stamp for this packet | ||
timeval currTime = timespecToTimeval(tcpData.getRawPacket()->getPacketTimeStamp()); | ||
auto currTime = timespecToTimePoint(tcpData.getRawPacket()->getPacketTimeStamp()); | ||
|
||
// find the connection in the connection map | ||
ConnectionList::iterator iter = m_ConnectionList.find(flowKey); | ||
|
@@ -146,22 +177,13 @@ namespace pcpp | |
|
||
tcpReassemblyData = &iter->second; | ||
|
||
if (currTime.tv_sec > tcpReassemblyData->connData.endTime.tv_sec) | ||
if (currTime > tcpReassemblyData->connData.endTimePrecise) | ||
{ | ||
tcpReassemblyData->connData.setEndTime(currTime); | ||
m_ConnectionInfo[flowKey].setEndTime(currTime); | ||
} | ||
else if (currTime.tv_sec == tcpReassemblyData->connData.endTime.tv_sec) | ||
{ | ||
if (currTime.tv_usec > tcpReassemblyData->connData.endTime.tv_usec) | ||
{ | ||
tcpReassemblyData->connData.setEndTime(currTime); | ||
m_ConnectionInfo[flowKey].setEndTime(currTime); | ||
} | ||
} | ||
} | ||
|
||
timeval timestampOfTheReceivedPacket = currTime; | ||
int8_t sideIndex = -1; | ||
bool first = false; | ||
|
||
|
@@ -299,7 +321,7 @@ namespace pcpp | |
if (tcpPayloadSize != 0 && m_OnMessageReadyCallback != nullptr) | ||
{ | ||
TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData, | ||
timestampOfTheReceivedPacket); | ||
currTime); | ||
m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); | ||
} | ||
status = TcpMessageHandled; | ||
|
@@ -337,7 +359,7 @@ namespace pcpp | |
if (m_OnMessageReadyCallback != nullptr) | ||
{ | ||
TcpStreamData streamData(tcpLayer->getLayerPayload() + newLength, tcpPayloadSize - newLength, 0, | ||
tcpReassemblyData->connData, timestampOfTheReceivedPacket); | ||
tcpReassemblyData->connData, currTime); | ||
m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); | ||
} | ||
status = TcpMessageHandled; | ||
|
@@ -390,7 +412,7 @@ namespace pcpp | |
if (m_OnMessageReadyCallback != nullptr) | ||
{ | ||
TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData, | ||
timestampOfTheReceivedPacket); | ||
currTime); | ||
m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); | ||
} | ||
status = TcpMessageHandled; | ||
|
@@ -436,7 +458,7 @@ namespace pcpp | |
newTcpFrag->data = new uint8_t[tcpPayloadSize]; | ||
newTcpFrag->dataLength = tcpPayloadSize; | ||
newTcpFrag->sequence = sequence; | ||
newTcpFrag->timestamp = timestampOfTheReceivedPacket; | ||
newTcpFrag->timestamp = currTime; | ||
memcpy(newTcpFrag->data, tcpLayer->getLayerPayload(), tcpPayloadSize); | ||
tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.pushBack(newTcpFrag); | ||
|
||
|
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.
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