From Jim Young via bug 4331:

This patch adds a new '-S' option to editcap that will rewrite timestamps of
packets to insure that the new capture file is in strict chronological order.

This option's primary use case is to fixup the occasional timestamps that have
a negative delta time relative to previous packet.

This feature is related to (but does not depend on) capinfos enhancement
submitted in bug #4315 which helps identify tracefiles with "out-of-order"
packets.

svn path=/trunk/; revision=33042
This commit is contained in:
Gerald Combs 2010-06-02 00:30:25 +00:00
parent f194916d62
commit 07354a18c1
4 changed files with 199 additions and 3 deletions

View File

@ -2483,6 +2483,7 @@ Jim Young <sysjhy [AT] langate.gsu.edu> {
Improvements LLDP dissection (803.3 "PMD Auto-Negotiation Advertised
Capability" and "Operational MAU Type")
Capinfos time order checking
Editcap time order forcing
}

View File

@ -17,6 +17,7 @@ S<[ B<-i> E<lt>seconds per fileE<gt> ]>
S<[ B<-r> ]>
S<[ B<-s> E<lt>snaplenE<gt> ]>
S<[ B<-t> E<lt>time adjustmentE<gt> ]>
S<[ B<-S> E<lt>strict time adjustmentE<gt> ]>
S<[ B<-T> E<lt>encapsulation typeE<gt> ]>
S<[ B<-v> ]>
I<infile>
@ -204,6 +205,39 @@ This feature is useful when synchronizing dumps
collected on different machines where the time difference between the
two machines is known or can be estimated.
=item -S E<lt>strict time adjustmentE<gt>
Time adjust selected packets to insure strict chronological order.
The <strict time adjustment> value represents relative seconds
specified as [-]I<seconds>[I<.fractional seconds>].
As the capture file is processed each packet's absolute time is
I<possibly> adjusted to be equal to or greater than the previous
packet's absolute timestamp depending on the <strict time
adjustment> value.
If <strict time adjustment> value is 0 or greater (e.g. 0.000001)
then B<only> packets with a timestamp less than the previous packet
will adjusted. The adjusted timestamp value will be set to be
equal to the timestamp value of the previous packet plus the value
of the <strict time adjustment> value. A <strict time adjustment>
value of 0 will adjust the minimum number of timestamp values
necessary to insure that the resulting capture file is in
strict chronological order.
If <strict time adjustment> value is specified as a
negative value, then the timestamp values of B<all>
packets will be adjusted to be equal to the timestamp value
of the previous packet plus the absolute value of the
<lt>strict time adjustment<gt> value. A <strict time
adjustment> value of -0 will result in all packets
having the timestamp value of the first packet.
This feature is useful when the trace file has an occasional
packet with a negative delta time relative to the previous
packet.
=item -T E<lt>encapsulation typeE<gt>
Sets the packet encapsulation type of the output capture file.
@ -288,6 +322,14 @@ or on Windows systems
editcap -v -D 0 capture.pcap NUL
To advance the timestamps of each packet forward by 3.0827 seconds:
editcap -t 3.0827 capture.pcap adjusted.pcap
To insure all timestamps are in strict chronological order:
editcap -S 0 capture.pcap adjusted.pcap
To introduce 5% random errors in a capture file use:
=over 4

View File

@ -137,7 +137,8 @@ Wireshark Info
<listitem>
<para>
Capinfos now checks the time order of capture files.
Capinfos and editcap now respectively support time order checking
and forcing.
</para>
</listitem>

156
editcap.c
View File

@ -134,6 +134,10 @@ static gboolean check_startstop = FALSE;
static gboolean dup_detect = FALSE;
static gboolean dup_detect_by_time = FALSE;
static int do_strict_time_adjustment = FALSE;
static struct time_adjustment strict_time_adj = {{0, 0}, 0}; /* strict time adjustment */
static nstime_t previous_time = {0, 0}; /* previous time */
static int find_dct2000_real_data(guint8 *buf);
static gchar *
@ -364,6 +368,81 @@ set_time_adjustment(char *optarg_str_p)
time_adj.tv.tv_usec = val;
}
static void
set_strict_time_adj(char *optarg)
{
char *frac, *end;
long val;
size_t frac_digits;
if (!optarg)
return;
/* skip leading whitespace */
while (*optarg == ' ' || *optarg == '\t') {
optarg++;
}
/*
* check for a negative adjustment
* A negative strict adjustment value is a flag
* to adjust all frames by the specifed delta time.
*/
if (*optarg == '-') {
strict_time_adj.is_negative = 1;
optarg++;
}
/* collect whole number of seconds, if any */
if (*optarg == '.') { /* only fractional (i.e., .5 is ok) */
val = 0;
frac = optarg;
} else {
val = strtol(optarg, &frac, 10);
if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) {
fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
optarg);
exit(1);
}
if (val < 0) { /* implies '--' since we caught '-' above */
fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
optarg);
exit(1);
}
}
strict_time_adj.tv.tv_sec = val;
/* now collect the partial seconds, if any */
if (*frac != '\0') { /* chars left, so get fractional part */
val = strtol(&(frac[1]), &end, 10);
/* if more than 6 fractional digits truncate to 6 */
if((end - &(frac[1])) > 6) {
frac[7] = 't'; /* 't' for truncate */
val = strtol(&(frac[1]), &end, 10);
}
if (*frac != '.' || end == NULL || end == frac
|| val < 0 || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) {
fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
optarg);
exit(1);
}
}
else {
return; /* no fractional digits */
}
/* adjust fractional portion from fractional to numerator
* e.g., in "1.5" from 5 to 500000 since .5*10^6 = 500000 */
if (frac && end) { /* both are valid */
frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
while(frac_digits < 6) { /* this is frac of 10^6 */
val *= 10;
frac_digits++;
}
}
strict_time_adj.tv.tv_usec = val;
}
static void
set_rel_time(char *optarg_str_p)
{
@ -613,7 +692,7 @@ usage(gboolean is_error)
fprintf(output, "\n");
fprintf(output, " NOTE: The use of the 'Duplicate packet removal' options with\n");
fprintf(output, " other editcap options except -v may not always work as expected.\n");
fprintf(output, " Specifically the -r and -t options will very likely NOT have the\n");
fprintf(stderr, " Specifically the -r, -t or -S options will very likely NOT have the\n");
fprintf(output, " desired effect if combined with the -d, -D or -w.\n");
fprintf(output, "\n");
fprintf(output, "Packet manipulation:\n");
@ -621,6 +700,14 @@ usage(gboolean is_error)
fprintf(output, " -C <choplen> chop each packet at the end by <choplen> bytes.\n");
fprintf(output, " -t <time adjustment> adjust the timestamp of each packet;\n");
fprintf(output, " <time adjustment> is in relative seconds (e.g. -0.5).\n");
fprintf(stderr, " -S <strict adjustment> adjust timestamp of packets if necessary to insure\n");
fprintf(stderr, " strict chronological increasing order. The <strict\n");
fprintf(stderr, " adjustment> is specified in relative seconds with\n");
fprintf(stderr, " values of 0 or 0.000001 being the most reasonable.\n");
fprintf(stderr, " A negative adjustment value will modify timestamps so\n");
fprintf(stderr, " that each packet's delta time is the absolute value\n");
fprintf(stderr, " of the adjustment specified. A value of -0 will set\n");
fprintf(stderr, " all packets to the timestamp of the first packet.\n");
fprintf(output, " -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
fprintf(output, " that a particular packet byte will be randomly changed.\n");
fprintf(output, "\n");
@ -734,7 +821,7 @@ main(int argc, char *argv[])
#endif
/* Process the options */
while ((opt = getopt(argc, argv, "A:B:c:C:dD:E:F:hrs:i:t:T:vw:")) !=-1) {
while ((opt = getopt(argc, argv, "A:B:c:C:dD:E:F:hrs:i:t:S:T:vw:")) !=-1) {
switch (opt) {
@ -846,6 +933,11 @@ main(int argc, char *argv[])
set_time_adjustment(optarg);
break;
case 'S':
set_strict_time_adj(optarg);
do_strict_time_adjustment = TRUE;
break;
case 'T':
out_frame_type = wtap_short_string_to_encap(optarg);
if (out_frame_type < 0) {
@ -1096,6 +1188,66 @@ main(int argc, char *argv[])
phdr = &snap_phdr;
}
/*
* Do we adjust timestamps to insure strict chronologically order?
*/
if (do_strict_time_adjustment) {
if (previous_time.secs || previous_time.nsecs) {
if (!strict_time_adj.is_negative) {
nstime_t current;
nstime_t delta;
current.secs = phdr->ts.secs;
current.nsecs = phdr->ts.nsecs;
nstime_delta(&delta, &current, &previous_time);
if (delta.secs < 0 || delta.nsecs < 0)
{
/*
* A negative delta indicates that the current packet
* has an absolute timestamp less than the previous packet
* that it is being compared to. This is NOT a normal
* situation since trace files usually have packets in
* chronological order (oldest to newest).
*/
/* printf("++out of order, need to adjust this packet!\n"); */
snap_phdr = *phdr;
snap_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.tv_sec;
snap_phdr.ts.nsecs = previous_time.nsecs;
if (snap_phdr.ts.nsecs + strict_time_adj.tv.tv_usec * 1000 > ONE_MILLION * 1000) {
/* carry */
snap_phdr.ts.secs++;
snap_phdr.ts.nsecs += (strict_time_adj.tv.tv_usec - ONE_MILLION) * 1000;
} else {
snap_phdr.ts.nsecs += strict_time_adj.tv.tv_usec * 1000;
}
phdr = &snap_phdr;
}
} else {
/*
* A negative strict time adjustment is requested.
* Unconditionally set each timestamp to previous
* packet's timestamp plus delta.
*/
snap_phdr = *phdr;
snap_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.tv_sec;
snap_phdr.ts.nsecs = previous_time.nsecs;
if (snap_phdr.ts.nsecs + strict_time_adj.tv.tv_usec * 1000 > ONE_MILLION * 1000) {
/* carry */
snap_phdr.ts.secs++;
snap_phdr.ts.nsecs += (strict_time_adj.tv.tv_usec - ONE_MILLION) * 1000;
} else {
snap_phdr.ts.nsecs += strict_time_adj.tv.tv_usec * 1000;
}
phdr = &snap_phdr;
}
}
previous_time.secs = phdr->ts.secs;
previous_time.nsecs = phdr->ts.nsecs;
}
/* assume that if the frame's tv_sec is 0, then
* the timestamp isn't supported */
if (phdr->ts.secs > 0 && time_adj.tv.tv_sec != 0) {