elmazzun elmazzun - 9 days ago 6
C++ Question

Why is there a 0 second delay between two captured packets in my libpcap session?

My forking proxy duplicates for every incoming connection: every child process launches a detached thread which logs packets for that connection with a

pcap
session. Looking in my log file I found a 0 second delay between two captured packets belonging to the same connection.

I don't know if this is because of a mistake of mine, or there's something I'm missing in the
pcap
library but this is a serious isuue for me: delay is used to compute packets per second with the formula
1000000 / delay
(delay is in microseconds).

Is this something I should worry about? Or the
pcap_pkthdr
doesn't provide enough precision? I'm not familiar with how fast packets are received (proxy is running in my laptop and I'm using my modest home network, 5 Mbps in download).

This happens only with downloading packets (while I'm getting a Debian ISO or watching a YouTube video) and it occurs 10 times in almost 80000 captured packets. If the
timeval
in
pcap_pkthdr
would use
nanoseconds
, would the 0 delay disappear?

Anyway, here's the code every logging thread executes:

int res;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle;
struct bpf_program fp;
bpf_u_int32 net = PCAP_NETMASK_UNKNOWN;
struct pcap_pkthdr *header;
const u_char *pkt_data;
struct timeval oldTimeUploadStruct;
struct timeval oldTimeDownloadStruct;

const char *filter_exp = // big filter of mine

handle = pcap_open_live("wlan0", 65535, 0, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device wlan0: %s\n", errbuf);
return;
}

// Compile and apply the filter
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}

gettimeofday(&oldTimeUploadStruct, NULL);
gettimeofday(&oldTimeDownloadStruct, NULL);

long long oldTimeUpload = (oldTimeUploadStruct.tv_sec * 1000000) + oldTimeUploadStruct.tv_usec;
long long oldTimeDownload = (oldTimeDownloadStruct.tv_sec * 1000000) + oldTimeDownloadStruct.tv_usec;

// stopLogging is a flag set to false from child process before detaching this thread;
// when connection is over, the flag is set to true and this loop breaks
while ((res = pcap_next_ex(handle, &header, &pkt_data)) && (stopLogging == false)) {

// 0 if the timeout set with pcap_open_live() has elapsed.
// In this case pkt_header and pkt_data don't point to a valid packet
if (res == 0) {
continue;
}

if (packet is in upload) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeUpload;
std::stringstream mylogstream;
// creating string to log: I omitted some variables
// like IP addresses and ports for brevity
mylogstream << host << " UPLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeUpload = timestamp;
}

else if (packet is in download) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeDownload;
std::stringstream mylogstream;
mylogstream << host << " DOWNLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeDownload = timestamp;
}
}

if(res == -1)
printf("Error reading the packets: %s\n", pcap_geterr(handle));

debugGreen("Quit logging connection towards " << hostName);
pcap_close(handle);

Answer

Because you got two packets within the same CPU clock tick. Since network cards raise interrupts when they receive packets this is possible.