Skip to content

Commit

Permalink
send_packet: Avoid clock drift by using time since first packet
Browse files Browse the repository at this point in the history
Prior to this change, time between packets was calculated as deltas
and over time errors would quickly add up. The work here switches
to use the wall time since the first packet was sent as the reference
which is compared to the PCAP packet timestamp relative to the first
packet. In this way there are no errors and clock drift is avoided.
As a result tcpreplay can now be used to play back very time sensitive
captures such as video streams with PCR.
  • Loading branch information
Dave-Craig-Brightsign committed Feb 19, 2021
1 parent 72dcf55 commit ec50def
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ typedef struct {
struct timeval end_time;
struct timeval pkt_ts_delta;
struct timeval last_print;
struct timeval first_packet_sent_wall_time;
struct timeval first_packet_pcap_timestamp;
COUNTER flow_non_flow_packets;
COUNTER flows;
COUNTER flows_unique;
Expand Down
18 changes: 13 additions & 5 deletions src/send_packets.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,18 +588,26 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
ctx->skip_packets = 0;

if (options->speed.mode == speed_multiplier) {
if(!timerisset(&stats->first_packet_sent_wall_time))
{
/* We're sending the first packet, so we have an absolute time reference. */
TIMEVAL_SET(&stats->first_packet_sent_wall_time, &now);
TIMEVAL_SET(&stats->first_packet_pcap_timestamp, &pkthdr.ts);
}

if (!timerisset(&last_pkt_ts)) {
TIMEVAL_SET(&last_pkt_ts, &pkthdr.ts);
} else if (timercmp(&pkthdr.ts, &last_pkt_ts, >)) {
struct timeval delta;

timersub(&pkthdr.ts, &last_pkt_ts, &delta);
timeradd(&stats->pkt_ts_delta, &delta, &stats->pkt_ts_delta);
/* pkt_ts_delta is the packet time stamp difference since the first packet */
timersub(&pkthdr.ts, &stats->first_packet_pcap_timestamp, &stats->pkt_ts_delta);

/* time_delta is the wall time difference since sending the first packet */
timersub(&now, &stats->first_packet_sent_wall_time, &stats->time_delta);

TIMEVAL_SET(&last_pkt_ts, &pkthdr.ts);
}

if (!timerisset(&stats->time_delta))
TIMEVAL_SET(&stats->pkt_ts_delta, &stats->pkt_ts_delta);
}

if (!top_speed) {
Expand Down

0 comments on commit ec50def

Please sign in to comment.