Changeset 2006

Show
Ignore:
Timestamp:
04/30/08 21:46:55 (7 months ago)
Author:
aturner
Message:

merge features/performance -r1879:2005 to trunk. and cleanup. refs #41

Location:
trunk
Files:
12 modified
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/configure.ac

    r2004 r2006  
    6868        AUTOGEN_MAJOR=`echo ${AUTOGEN_VERSION} | ${SED} 's|^\([[0-9]]\)\.[[0-9]]|\1|'` 
    6969        AUTOGEN_MINOR=`echo ${AUTOGEN_VERSION} | ${SED} 's|^\([[0-9]]\)\.\([[0-9]]\)|\2|'` 
    70         if test ((${AUTOGEN_MAJOR} -eq 5 && ${AUTOGEN_MINOR} -lt 9) || ${AUTOGEN_MAJOR} -lt 5) ; then 
     70        if ( ${AUTOGEN_MAJOR} -eq 5 && ${AUTOGEN_MINOR} -lt 9 ) || ${AUTOGEN_MAJOR} -lt 5 ; then 
    7171                AC_MSG_RESULT(no) 
    7272                AC_MSG_WARN([${AUTOGEN} is too old (${AUTOGEN_VERSION}) for building from SVN.  Please upgrade to 5.9)]) 
     
    10851085disable_pcap_findalldevs=no 
    10861086 
    1087  
     1087osx_frameworks=no 
    10881088dnl these need to be dynamic based on OS 
    10891089case $host in 
     
    11121112        disable_pcap_findalldevs=yes 
    11131113    fi 
     1114    AC_DEFINE([HAVE_ABSOLUTE_TIME], [1], [Have OS X UpTime()/AbsoluteTime high-precision timing]) 
     1115    osx_frameworks=yes 
    11141116        AC_MSG_RESULT(Apple OS X) 
    11151117        ;; 
     
    11341136esac]) 
    11351137 
     1138AM_CONDITIONAL([ENABLE_OSX_FRAMEWORKS], test "$osx_frameworks" == "yes") 
    11361139 
    11371140AC_ARG_WITH(testnic2, 
  • trunk/src/Makefile.am

    r1965 r2006  
    6060 
    6161tcpreplay_LDADD += ./common/libcommon.a $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) 
    62 tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c 
     62tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c sleep.c 
     63 
     64if ENABLE_OSX_FRAMEWORKS 
     65tcpreplay_LDFLAGS = -framework CoreServices -framework Carbon 
     66endif 
    6367 
    6468tcpreplay_OBJECTS: tcpreplay_opts.h 
     
    9498tcpbridge_LDADD = ./tcpedit/libtcpedit.a ./common/libcommon.a \ 
    9599    $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) @DMALLOC_LIB@ 
    96 tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c                 
     100if ENABLE_OSX_FRAMEWORKS 
     101tcpbridge_LDFLAGS = -framework CoreServices -framework Carbon 
     102endif 
     103tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c sleep.c 
    97104tcpbridge_OBJECTS: tcpbridge_opts.h 
    98105tcpbridge_opts.h: tcpbridge_opts.c 
     
    104111                 tcpreplay_edit_opts.h tcprewrite.h tcprewrite_opts.h tcpprep_opts.h \ 
    105112                 tcpprep_opts.def tcprewrite_opts.def tcpreplay_opts.def \ 
    106                  tcpbridge_opts.def tcpbridge.h tcpbridge_opts.h tcpr.h 
     113                 tcpbridge_opts.def tcpbridge.h tcpbridge_opts.h tcpr.h sleep.h 
    107114 
    108115 
  • trunk/src/common.h

    r1757 r2006  
    1616#include "common/utils.h" 
    1717#include "common/xX.h" 
     18#include "common/rdtsc.h" 
    1819#include "common/tcpdump.h" 
    1920#include "common/timer.h" 
  • trunk/src/common/Makefile.am

    r1961 r2006  
    1515                      fakepcap.c fakepcapnav.c fakepoll.c xX.c utils.c \ 
    1616                      timer.c svn_version.c abort.c sendpacket.c \ 
    17                           dlt_names.c mac.c interface.c 
     17                          dlt_names.c mac.c interface.c rdtsc.c 
    1818 
    1919if ENABLE_TCPDUMP 
     
    2828                 fakepcap.h fakepcapnav.h fakepoll.h xX.h utils.h \ 
    2929                 tcpdump.h timer.h abort.h pcap_dlt.h sendpacket.h \ 
    30                  dlt_names.h mac.h interface.h 
     30                 dlt_names.h mac.h interface.h rdtsc.h 
    3131 
    3232MOSTLYCLEANFILES = *~ 
  • trunk/src/common/timer.c

    r1897 r2006  
    5757} 
    5858 
    59 /* 
    60  * converts a float to a timeval structure 
    61  * converted to a #define 
    62 void 
    63 float2timer(float time, struct timeval *tvp) 
     59/* Divide tvs by div, storing the result in tvs */ 
     60void timesdiv(struct timespec *tvs, float div) 
    6461{ 
    65     float n; 
     62    double interval; 
     63     
     64    if (div == 0 || div == 1) 
     65        return; 
     66         
     67    interval = ((double)tvs->tv_sec * 1000000000 + tvs->tv_nsec) / (double)div; 
     68    tvs->tv_sec = interval / (int)1000000000; 
     69    tvs->tv_nsec = interval - (tvs->tv_nsec * 1000000000); 
     70} 
    6671 
    67     n = time; 
    68  
    69     tvp->tv_sec = n; 
    70  
    71     n -= tvp->tv_sec; 
    72     tvp->tv_usec = n * 100000; 
    73  
    74 } 
    75  */ 
  • trunk/src/common/timer.h

    r1854 r2006  
    4343#include <math.h> 
    4444 
     45#ifdef HAVE_ABSOLUTE_TIME 
     46#include <CoreServices/CoreServices.h> 
     47#endif 
     48 
     49/* AbsoluteTime methods */ 
     50#ifndef NonZero 
     51#define NonZero(x) ((x).hi | (x).lo) 
     52#endif 
     53#ifndef SetZero 
     54#define SetZero(x) do { (x).hi = 0 ; (x).lo = 0; } while(0) 
     55#endif 
     56#ifndef CopyAbsolute 
     57#define CopyAbsolute(x, y) do { (x).lo = (y).lo ; (x).hi = (y).hi; } while (0) 
     58#endif 
     59#ifndef AbsoluteCmp 
     60#define AbsoluteCmp(left, right, cmp)       \ 
     61        (((left)->hi == (right)->hi) ?              \ 
     62        ((left)->lo cmp (right)->lo) :              \ 
     63        ((left)->hi cmp (right)->hi)) 
     64#endif 
     65 
    4566/* 
    46  * 1 sec = 1,000,000 microsec 
     67 * 1 sec = 1,0000 millisec (ms) 
     68 * 1 sec = 1,000,000 microsec (us) 
     69 * 1 sec = 1,000,000,000 nanosec (ns) 
     70 * 1 millisec = 1,000 microsec 
    4771 * 1 microsec = 1,000 nanosec 
    48  * 1 sec = 1,000,000,000 nanosec 
    4972 */ 
    5073 
    5174void timerdiv(struct timeval *tvp, float div); 
     75void timesdiv(struct timespec *tvs, float div); 
    5276 
    5377/* convert float time to struct timeval *tvp */ 
     
    5781        tvp->tv_sec = time;                     \ 
    5882        tvp->tv_usec = (time - tvp->tv_sec) * 100000; \ 
    59     } while (0); 
     83    } while (0) 
    6084#endif 
    6185 
     
    6791#endif 
    6892 
     93#ifndef TIMESPEC_TO_TIMEVAL 
     94#define TIMESPEC_TO_TIMEVAL(tv, ts) {           \ 
     95    (tv)->tv_sec = (ts)->tv_sec;                \ 
     96    (tv)->tv_usec = (ts)->tv_nsec / 1000; } 
     97#endif 
     98 
     99#ifndef ROUND_TIMESPEC_TO_MICROSEC 
     100#define ROUND_TIMESPEC_TO_MICROSEC(ts)      \ 
     101    do {                                    \ 
     102        (ts)->tv_nsec = ((((ts)->tv_nsec / 1000) + ((ts)->tv_nsec % 1000 >= 500 ? 1 : 0)) * 1000);   \ 
     103    } while (0) 
     104#endif 
     105 
     106 
     107 
    69108/* zero out a timer */ 
    70109#ifndef timerclear 
     
    72111#endif 
    73112 
     113/* zero out a timespec */ 
     114#ifndef timesclear 
     115#define timesclear(tvs)     (tvs)->tv_sec = (tvs)->tv_nsec = 0 
     116#endif 
     117 
    74118/* is timer non-zero? */ 
    75119#ifndef timerisset 
    76120#define timerisset(tvp)         ((tvp)->tv_sec || (tvp)->tv_usec) 
    77121#endif 
     122 
     123/* is timespec non-zero? */ 
     124#ifndef timesisset 
     125#define timesisset(tvs)         ((tvs)->tv_sec || (tvs)->tv_nsec) 
     126#endif 
     127 
    78128 
    79129/* add tvp and uvp and store in vvp */ 
     
    103153#endif 
    104154 
     155#ifndef timessub 
     156#define timessub(tsp, usp, vsp)                                 \ 
     157        do {                                                                    \ 
     158                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \ 
     159                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \ 
     160                if ((vsp)->tv_nsec < 0) {                               \ 
     161                        (vsp)->tv_sec--;                                    \ 
     162                        (vsp)->tv_nsec += 1000000000;           \ 
     163                }                                                                   \ 
     164        } while (0) 
     165#endif 
     166 
    105167/* compare tvp and uvp using cmp */ 
    106168#ifndef timercmp 
     
    109171        ((tvp)->tv_usec cmp (uvp)->tv_usec) :           \ 
    110172        ((tvp)->tv_sec cmp (uvp)->tv_sec)) 
     173#endif 
     174 
     175#ifndef timescmp 
     176#define timescmp(tsp, usp, cmp)                             \ 
     177        (((tsp)->tv_sec == (usp)->tv_sec) ?                 \ 
     178        ((tsp)->tv_nsec cmp (usp)->tv_nsec) :           \ 
     179        ((tsp)->tv_sec cmp (usp)->tv_sec)) 
    111180#endif 
    112181 
     
    122191        } while(0) 
    123192 
    124  
    125 /* device tvp by x.  store in tvp */ 
    126 #define timerdiv2(tvp, x)                                               \ 
    127         do {                                                                    \ 
    128                 (tvp)->tv_sec = (tvp)->tv_sec / x;              \ 
    129                 (tvp)->tv_usec = (tvp)->tv_usec / x;    \ 
    130         } while(0) 
    131  
    132 #endif 
    133  
     193#ifdef HAVE_ABSOLUTE_TIME 
     194    typedef AbsoluteTime delta_t; 
     195#else 
     196    typedef struct timeval delta_t; 
     197#endif 
     198 
     199/* 
     200 * starts a timer so we can figure out how much time has passed 
     201 * when we call get_delta_timer() 
     202 */ 
     203static inline void 
     204start_delta_time(delta_t *ctx) 
     205{ 
     206#ifdef HAVE_ABSOLUTE_TIME 
     207    *ctx = UpTime(); 
     208#else 
     209    gettimeofday(ctx, NULL); 
     210#endif 
     211} 
     212 
     213/*  
     214 * returns the amount of time that has passed since the  
     215 * last time you called start_delta_time() 
     216 */ 
     217static inline void 
     218get_delta_time(delta_t *ctx, struct timespec *ret) 
     219{ 
     220/* OS X has absolute time */ 
     221#ifdef HAVE_ABSOLUTE_TIME 
     222    AbsoluteTime now, delta; 
     223    Nanoseconds nano; 
     224     
     225    now = UpTime(); 
     226     
     227    if (! NonZero(*ctx)) { 
     228        timesclear(ret); 
     229    } else { 
     230        delta = SubAbsoluteFromAbsolute(now, *ctx); 
     231        nano = AbsoluteToNanoseconds(delta); 
     232        NANOSEC_TO_TIMESPEC(UnsignedWideToUInt64(nano) / 10, ret); 
     233    } 
     234     
     235/* Everyone else just uses gettimeofday */ 
     236#else 
     237    struct timeval now, delta; 
     238     
     239    gettimeofday(&now, NULL); 
     240 
     241    if (!timerisset(ctx)) { 
     242        timesclear(ret); 
     243    } else { 
     244        timersub(&now, ctx, &delta); 
     245        TIMEVAL_TO_TIMESPEC(&delta, ret); 
     246    } 
     247#endif 
     248} 
     249 
     250#endif /* _TIMER_H_ */ 
  • trunk/src/defines.h.in

    r1945 r2006  
    162162 
    163163/* struct timeval print structs */ 
    164 #define TIMEVAL_FORMAT "%lu.%06lu" 
     164#define TIMEVAL_FORMAT "%lus %luusec" 
     165#define TIMESPEC_FORMAT "%lus %lunsec" 
    165166 
    166167/* force a word or half-word swap on both Big and Little endian systems */ 
     
    232233 
    233234 
     235/* Time converters */ 
     236#define SEC_TO_MILLISEC(x) (x * 1000) 
     237#define SEC_TO_MICROSEC(x) (x * 1000000) 
     238#define SEC_TO_NANOSEC(x)  ((u_int64_t)x * 1000000000) 
     239 
     240#define MILLISEC_TO_SEC(x) (x / 1000) 
     241#define MICROSEC_TO_SEC(x) (x / 1000000) 
     242#define NANOSEC_TO_SEC(x)  ((u_int64_t)x / 1000000000) 
     243 
     244#define TIMEVAL_TO_MILLISEC(x)  (((x)->tv_sec * 1000) + ((x)->tv_usec / 1000)) 
     245#define TIMEVAL_TO_MICROSEC(x)  (((x)->tv_sec * 1000000) + (x)->tv_usec) 
     246#define TIMEVAL_TO_NANOSEC(x)   ((u_int64_t)((x)->tv_sec * 1000000000) + ((u_int64_t)(x)->tv_usec * 1000)) 
     247 
     248#define MILLISEC_TO_TIMEVAL(x, tv)          \ 
     249    do {                                    \ 
     250        (tv)->tv_sec = (x) / 1000;          \ 
     251        (tv)->tv_usec = (x * 1000) - ((tv)->tv_sec * 1000000);   \ 
     252    } while(0) 
     253     
     254#define MICROSEC_TO_TIMEVAL(x, tv)          \ 
     255    do {                                    \ 
     256        (tv)->tv_sec = (x) / 1000000;       \ 
     257        (tv)->tv_usec = (x) - ((tv)->tv_sec * 1000000);   \ 
     258    } while(0) 
     259 
     260#define NANOSEC_TO_TIMEVAL(x, tv)           \ 
     261    do {                                    \ 
     262        (tv)->tv_sec =  (x) / 1000000000;   \ 
     263        (tv)->tv_usec = ((x) % 1000000000) / 1000);   \ 
     264    } while(0) 
     265 
     266#define NANOSEC_TO_TIMESPEC(x, ts)          \ 
     267    do {                                    \ 
     268        (ts)->tv_sec = (x) / 1000000000;    \ 
     269        (ts)->tv_nsec = (x) % 1000000000;   \ 
     270    } while(0) 
     271 
     272#define TIMESPEC_TO_MILLISEC(x)  (((x)->tv_sec * 1000) + ((x)->tv_nsec / 1000000)) 
     273#define TIMESPEC_TO_MICROSEC(x)  (((x)->tv_sec * 1000000) + (x)->tv_nsec / 1000) 
     274#define TIMESPEC_TO_NANOSEC(x) ((u_int64_t)((x)->tv_sec * 1000000000) + ((u_int64_t)(x)->tv_nsec)) 
     275 
    234276#endif /* DEFINES */ 
  • trunk/src/send_packets.c

    r1898 r2006  
    22 
    33/* 
    4  * Copyright (c) 2001-2007 Aaron Turner. 
     4 * Copyright (c) 2001-2008 Aaron Turner. 
    55 * All rights reserved. 
    66 * 
     
    3131 */ 
    3232 
     33#define ADJUSTER_OFFSET 5 /* number of usec to compensate for packet timing */ 
    3334 
    3435#include "config.h" 
     
    5960 
    6061#include "send_packets.h" 
     62#include "sleep.h" 
    6163 
    6264extern tcpreplay_opt_t options; 
     
    6971#endif 
    7072 
    71 static void do_sleep(struct timeval *time, struct timeval *last, int len, int accurate,  
    72     sendpacket_t *sp, COUNTER counter); 
    73 static u_int32_t sleep_loop(struct timeval time); 
    74 static u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx, packet_cache_t **prev_packet); 
     73static void do_sleep(struct timeval *time, struct timeval *last, int len,  
     74    int accurate, sendpacket_t *sp, COUNTER counter, delta_t *ctx); 
     75static const u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr,  
     76    int file_idx, packet_cache_t **prev_packet); 
     77static u_int32_t get_user_count(sendpacket_t *sp, COUNTER counter); 
    7578 
    7679/** 
     
    9295    struct pcap_pkthdr *pkthdr_ptr; 
    9396#endif 
    94  
     97    delta_t delta_ctx; 
     98     
    9599    /* register signals */ 
    96100    didsig = 0; 
     
    160164        /* 
    161165         * we have to cast the ts, since OpenBSD sucks 
    162          * had to be special and use bpf_timeval  
     166         * had to be special and use bpf_timeval. 
     167         * Only sleep if we're not in top speed mode (-t) 
    163168         */ 
    164         do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, options.accurate, sp, packetnum); 
    165              
     169        if (options.speed.mode != SPEED_TOPSPEED) 
     170            do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, options.accurate, sp, packetnum, &delta_ctx); 
     171         
     172        /* mark the time when we send the packet */ 
     173        start_delta_time(&delta_ctx); 
     174         
    166175        /* write packet out on network */ 
    167176        if (sendpacket(sp, pktdata, pktlen) < (int)pktlen) 
    168177            warnx("Unable to send packet: %s", sendpacket_geterr(sp)); 
    169                  
     178 
    170179        /*  
    171180         * track the time of the "last packet sent".  Again, because of OpenBSD 
     
    194203 * will be updated as new entries are added (or retrieved) from the cache list. 
    195204 */ 
    196 static u_char * 
     205static const u_char * 
    197206get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx,  
    198207    packet_cache_t **prev_packet) 
     
    233242                         * We should read the pcap file, and cache the results 
    234243                         */ 
    235                         pktdata = pcap_next(pcap, pkthdr); 
     244                        pktdata = (u_char *)pcap_next(pcap, pkthdr); 
    236245                        if (pktdata != NULL) { 
    237246                                if (*prev_packet == NULL) { 
     
    263272                 * Read pcap file as normal 
    264273                 */ 
    265                 pktdata = pcap_next(pcap, pkthdr); 
     274                pktdata = (u_char *)pcap_next(pcap, pkthdr); 
    266275        } 
    267276 
     277    /* this get's casted to a const on the way out */ 
    268278        return pktdata; 
    269279} 
     
    310320 */ 
    311321static void 
    312 do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, sendpacket_t *sp, 
    313     COUNTER counter) 
     322do_sleep(struct timeval *time, struct timeval *last, int len, int accurate,  
     323    sendpacket_t *sp, COUNTER counter, delta_t *delta_ctx) 
    314324{ 
    315325    static struct timeval didsleep = { 0, 0 }; 
     
    318328    static struct timeval totalsleep = { 0, 0 }; 
    319329#endif 
    320     struct timeval nap, now, delta; 
    321     struct timespec ignore, sleep; 
     330    struct timespec adjuster = { 0, 0 }; 
     331    static struct timespec nap = { 0, 0 }, delta_time = {0, 0}; 
     332    struct timeval nap_for, now, sleep_until; 
     333    struct timespec nap_this_time; 
     334    static int32_t nsec_adjuster = -1, nsec_times = -1; 
    322335    float n; 
    323     struct pollfd poller[1];        /* use poll to read from the keyboard */ 
    324     char input[EBUF_SIZE]; 
    325     static u_int32_t send = 0;      /* remember # of packets to send btw calls */ 
    326     u_int32_t loop; 
    327  
    328     /* just return if topspeed */ 
    329     if (options.speed.mode == SPEED_TOPSPEED) 
     336    static u_int32_t send = 0;      /* accellerator.   # of packets to send w/o sleeping */ 
     337    u_int64_t ppnsec; /* packets per usec */ 
     338 
     339 
     340#ifdef TCPREPLAY 
     341    adjuster.tv_nsec = OPT_VALUE_SLEEP_ACCEL * 1000; 
     342    dbgx(2, "Adjuster: " TIMEVAL_FORMAT, adjuster.tv_sec, adjuster.tv_nsec); 
     343#else 
     344    adjuster.tv_nsec = 0; 
     345#endif 
     346     
     347    /* acclerator time? */ 
     348    if (send > 0) { 
     349        send --; 
    330350        return; 
    331  
    332     dbgx(3, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec); 
    333  
    334     if (gettimeofday(&now, NULL) < 0) { 
     351    } 
     352         
     353    dbgx(4, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec); 
     354 
     355    if (gettimeofday(&now, NULL) < 0) 
    335356        errx(1, "Error gettimeofday: %s", strerror(errno)); 
    336     } 
    337  
    338     dbgx(3, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec); 
     357 
     358    dbgx(4, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec); 
    339359 
    340360    /* First time through for this file */ 
    341361    if (pkts_sent == 0 || ((options.speed.mode != SPEED_MBPSRATE) && (counter == 0))) { 
    342362        start = now; 
    343         timerclear(&delta); 
     363        timerclear(&sleep_until); 
    344364        timerclear(&didsleep); 
    345365    } 
    346366    else { 
    347         timersub(&now, &start, &delta); 
     367        timersub(&now, &start, &sleep_until); 
    348368    } 
    349369 
    350370    switch(options.speed.mode) { 
     371    /*  
     372     * If top speed, you shouldn't even be here, but handle it anyways 
     373     */ 
     374    case SPEED_TOPSPEED: 
     375        notice("you shouldn't call do_sleep() in top speed mode."); 
     376        return; 
     377        break; 
     378         
    351379    case SPEED_MULTIPLIER: 
    352380        /*  
     
    354382         */ 
    355383        if (timerisset(last) && timercmp(time, last, >)) { 
    356             timersub(time, last, &nap); 
    357             timerdiv(&nap, options.speed.speed); 
     384            timersub(time, last, &nap_for); 
     385            TIMEVAL_TO_TIMESPEC(&nap_for, &nap); 
     386            timesdiv(&nap, options.speed.speed); 
    358387        } 
    359388        else { 
     
    363392             * last packet. 
    364393             */ 
    365             timerclear(&nap); 
    366         } 
     394            timesclear(&nap); 
     395        }         
    367396        break; 
    368397 
     
    375404            n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */ 
    376405            nap.tv_sec = n; 
    377             nap.tv_usec = (n - nap.tv_sec) * 1000000; 
     406            nap.tv_nsec = (n - nap.tv_sec)  * 1000000000; 
     407             
    378408            dbgx(3, "packet size %d\t\tequals %f bps\t\tnap " TIMEVAL_FORMAT, len, n,  
    379                 nap.tv_sec, nap.tv_usec); 
     409                nap.tv_sec, nap.tv_nsec); 
    380410        } 
    381411        else { 
    382             timerclear(&nap); 
     412            /* don't sleep at all for the first packet */ 
     413            timesclear(&nap); 
    383414        } 
    384415        break; 
    385416 
    386417    case SPEED_PACKETRATE: 
    387         /* run in packets/sec */ 
    388         n = 1 / options.speed.speed; 
    389         nap.tv_sec = n; 
    390         n -= nap.tv_sec; 
    391         nap.tv_usec = n * 1000000; 
    392         break; 
    393  
     418        /* only need to calculate this the first time */ 
     419        if (! timesisset(&nap)) { 
     420            /* run in packets/sec */ 
     421            ppnsec = 1000000000 / options.speed.speed; 
     422            NANOSEC_TO_TIMESPEC(ppnsec, &nap); 
     423            dbgx(1, "sending 1 packet per %lu nsec", nap.tv_nsec); 
     424        } 
     425        break; 
     426         
    394427    case SPEED_ONEATATIME: 
    395428        /* do we skip prompting for a key press? */ 
    396429        if (send == 0) { 
    397             printf("**** Next packet #" COUNTER_SPEC " out %s.  How many packets do you wish to send? ", 
    398                 counter, (sp == options.intf1 ? options.intf1_name : options.intf2_name)); 
    399             fflush(NULL); 
    400             poller[0].fd = STDIN_FILENO; 
    401             poller[0].events = POLLIN | POLLPRI | POLLNVAL; 
    402             poller[0].revents = 0; 
    403  
    404             if (fcntl(0, F_SETFL, fcntl(0, F_GETFL) & ~O_NONBLOCK))  
    405                    errx(1, "Unable to clear non-blocking flag on stdin: %s", strerror(errno)); 
    406  
    407             /* wait for the input */ 
    408             if (poll(poller, 1, -1) < 0) 
    409                 errx(1, "Error reading user input from stdin: %s", strerror(errno)); 
    410              
    411             /* 
    412              * read to the end of the line or EBUF_SIZE, 
    413              * Note, if people are stupid, and type in more text then EBUF_SIZE 
    414              * then the next fgets() will pull in that data, which will have poor  
    415              * results.  fuck them. 
    416              */ 
    417             if (fgets(input, sizeof(input), stdin) == NULL) { 
    418                 errx(1, "Unable to process user input for fd %d: %s", fileno(stdin), strerror(errno)); 
    419             } else if (strlen(input) > 1) { 
    420                 send = strtoul(input, NULL, 0); 
    421             } 
    422  
    423             /* how many packets should we send? */ 
    424             if (send == 0) { 
    425