Skip to content

Commit

Permalink
Fix precision issue on pcapng reader (#1514)
Browse files Browse the repository at this point in the history
  • Loading branch information
mserdarsanli authored Aug 12, 2024
1 parent 0a84311 commit 39913f1
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 15 deletions.
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
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;
}
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

0 comments on commit 39913f1

Please sign in to comment.