Skip to content
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

Fix precision issue on pcapng reader #1514

Merged
merged 2 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ typedef struct _light_pcapng_file_info {
size_t user_app_desc_size;
size_t interface_block_count;
uint16_t link_types[MAX_SUPPORTED_INTERFACE_BLOCKS];
double timestamp_resolution[MAX_SUPPORTED_INTERFACE_BLOCKS];
uint64_t timestamp_ticks_per_second[MAX_SUPPORTED_INTERFACE_BLOCKS]; // PCPP patch

} light_pcapng_file_info;

Expand Down
29 changes: 15 additions & 14 deletions 3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We add a // PCPP patch comment everywhere we change something in LightPcapNg so we can later hopefully contribute them to the original repo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amended the commit

Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,25 @@ static light_pcapng_file_info *__create_file_info(light_pcapng pcapng_head)
return file_info;
}

static double __power_of(int x, int y)
// PCPP patch
static uint64_t int_pow(uint64_t x, uint8_t y)
{
int i;
double res = 1;

if (y < 0)
return 1 / __power_of(x, -y);
uint64_t res = 1;

for (i = 0; i < y; i++)
res *= x;

return res;
}
// PCPP patch end

// PCPP patch
static void __append_interface_block_to_file_info(const light_pcapng interface_block, light_pcapng_file_info* info)
{
struct _light_interface_description_block* interface_desc_block;
light_option ts_resolution_option = NULL;
uint32_t ticks_per_sec;

if (info->interface_block_count >= MAX_SUPPORTED_INTERFACE_BLOCKS)
return;
Expand All @@ -150,19 +151,21 @@ static void __append_interface_block_to_file_info(const light_pcapng interface_b
ts_resolution_option = light_get_option(interface_block, LIGHT_OPTION_IF_TSRESOL);
if (ts_resolution_option == NULL)
{
info->timestamp_resolution[info->interface_block_count] = __power_of(10,-6);
ticks_per_sec = int_pow(10, 6);
}
else
{
uint8_t* raw_ts_data = (uint8_t*)light_get_option_data(ts_resolution_option);
if (*raw_ts_data < 128)
info->timestamp_resolution[info->interface_block_count] = __power_of(10, (-1)*(*raw_ts_data));
ticks_per_sec = int_pow(10, (*raw_ts_data));
else
info->timestamp_resolution[info->interface_block_count] = __power_of(2, (-1)*((*raw_ts_data)-128));
ticks_per_sec = int_pow(2, ((*raw_ts_data)-128));
}
info->timestamp_ticks_per_second[info->interface_block_count] = ticks_per_sec;

info->link_types[info->interface_block_count++] = interface_desc_block->link_type;
}
// PCPP patch end

static light_boolean __is_open_for_write(const struct _light_pcapng_t* pcapng)
{
Expand Down Expand Up @@ -418,15 +421,13 @@ int light_get_next_packet(light_pcapng_t *pcapng, light_packet_header *packet_he
uint64_t timestamp = epb->timestamp_high;
timestamp = timestamp << 32;
timestamp += epb->timestamp_low;
double timestamp_res = pcapng->file_info->timestamp_resolution[epb->interface_id];
uint64_t packet_secs = timestamp * timestamp_res;
uint64_t ticks_per_sec = pcapng->file_info->timestamp_ticks_per_second[epb->interface_id];
uint64_t packet_secs = timestamp / ticks_per_sec;
uint64_t ticks = timestamp % ticks_per_sec;
if (packet_secs <= MAXIMUM_PACKET_SECONDS_VALUE)
{
packet_header->timestamp.tv_sec = packet_secs;
packet_header->timestamp.tv_nsec =
(timestamp - (packet_secs / timestamp_res)) // number of time units less than seconds
* timestamp_res // shift . to the left to get 0.{previous_number}
* 1000000000; // get the nanoseconds
packet_header->timestamp.tv_nsec = (1000000000ul * ticks) / ticks_per_sec;
seladb marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
Expand Down
1 change: 1 addition & 0 deletions Tests/Pcap++Test/Common/PcapFileNamesDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
#define SLL2_PCAP_WRITE_PATH "PcapExamples/sll2_copy.pcap"
#define EXAMPLE_PCAP_MICRO_PATH "PcapExamples/microsecs.pcap"
#define EXAMPLE_PCAP_NANO_PATH "PcapExamples/nanosecs.pcap"
#define EXAMPLE_PCAPNG_NANO_PATH "PcapExamples/nanosecs.pcapng"
1 change: 1 addition & 0 deletions Tests/Pcap++Test/TestDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ PTF_TEST_CASE(TestPcapNgFileTooManyInterfaces);
PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv6);
PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv4);
PTF_TEST_CASE(TestSolarisSnoopFileRead);
PTF_TEST_CASE(TestPcapNgFilePrecision);

// Implemented in LiveDeviceTests.cpp
PTF_TEST_CASE(TestPcapLiveDeviceList);
Expand Down
21 changes: 21 additions & 0 deletions Tests/Pcap++Test/Tests/FileTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,27 @@ PTF_TEST_CASE(TestPcapFilePrecision)
readerDevMicro.close();
} // TestPcapFilePrecision

PTF_TEST_CASE(TestPcapNgFilePrecision)
{
std::array<uint8_t, 16> testPayload = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
pcpp::RawPacket rawPacketNano(testPayload.data(), testPayload.size(), timespec({ 1722196160, 123456789 }),
false); // 1722196160.123456789

pcpp::PcapNgFileWriterDevice writerDev(EXAMPLE_PCAPNG_NANO_PATH);
PTF_ASSERT_TRUE(writerDev.open());
PTF_ASSERT_TRUE(writerDev.writePacket(rawPacketNano));
writerDev.close();

pcpp::PcapNgFileReaderDevice readerDev(EXAMPLE_PCAPNG_NANO_PATH);
PTF_ASSERT_TRUE(readerDev.open());
pcpp::RawPacket readPacket;
PTF_ASSERT_TRUE(readerDev.getNextPacket(readPacket));
PTF_ASSERT_EQUAL(readPacket.getPacketTimeStamp().tv_sec, 1722196160);
PTF_ASSERT_EQUAL(readPacket.getPacketTimeStamp().tv_nsec, 123456789);
readerDev.close();
} // TestPcapNgFilePrecision

PTF_TEST_CASE(TestPcapSllFileReadWrite)
{
pcpp::PcapFileReaderDevice readerDev(SLL_PCAP_PATH);
Expand Down
1 change: 1 addition & 0 deletions Tests/Pcap++Test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ int main(int argc, char* argv[])
PTF_RUN_TEST(TestPcapNgFileReadWrite, "no_network;pcap;pcapng");
PTF_RUN_TEST(TestPcapNgFileReadWriteAdv, "no_network;pcap;pcapng");
PTF_RUN_TEST(TestPcapNgFileTooManyInterfaces, "no_network;pcap;pcapng");
PTF_RUN_TEST(TestPcapNgFilePrecision, "no_network;pcapng");
PTF_RUN_TEST(TestPcapFileReadLinkTypeIPv6, "no_network;pcap");
PTF_RUN_TEST(TestPcapFileReadLinkTypeIPv4, "no_network;pcap");
PTF_RUN_TEST(TestSolarisSnoopFileRead, "no_network;pcap;snoop");
Expand Down
Loading