Changeset 2006


Ignore:
Timestamp:
05/01/08 04:46:55 (2 years ago)
Author:
aturner
Message:

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

Location:
trunk
Files:
12 edited
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                 dbg(1, "Input was less then 1 or non-numeric, assuming 1"); 
    426  
    427                 /* assume send only one packet */ 
    428                 send = 1; 
    429             } 
    430              
     430            send = get_user_count(sp, counter); 
    431431        } 
    432432 
     
    446446    } 
    447447 
    448     if (!accurate) { 
    449         timeradd(&didsleep, &nap, &didsleep); 
    450  
    451         dbgx(4, "I will sleep " TIMEVAL_FORMAT, nap.tv_sec, nap.tv_usec); 
    452  
    453         if (timercmp(&didsleep, &delta, >)) { 
    454             timersub(&didsleep, &delta, &nap); 
    455  
    456             sleep.tv_sec = nap.tv_sec; 
    457             sleep.tv_nsec = nap.tv_usec * 1000; /* convert microsec to ns */ 
    458             dbgx(4, "Sleeping " TIMEVAL_FORMAT, nap.tv_sec, nap.tv_usec); 
     448    /*  
     449     * since we apply the adjuster to the sleep time, we can't modify nap 
     450     */ 
     451    nap_this_time.tv_sec = nap.tv_sec; 
     452    nap_this_time.tv_nsec = nap.tv_nsec; 
     453 
     454    if (accurate != ACCURATE_ABS_TIME) { 
     455 
     456        switch (options.speed.mode) { 
     457            /* Mbps & Multipler are dynamic timings, so we round to the nearest usec */ 
     458            case SPEED_MBPSRATE: 
     459            case SPEED_MULTIPLIER: 
     460                ROUND_TIMESPEC_TO_MICROSEC(&nap_this_time); 
     461                break; 
     462 
     463            /* Packets/sec is static, so we weight packets for .1usec accuracy */ 
     464            case SPEED_PACKETRATE: 
     465                if (nsec_adjuster < 0) 
     466                    nsec_adjuster = (nap_this_time.tv_nsec % 10000) / 1000; 
     467         
     468                /* update in the range of 0-9 */ 
     469                nsec_times = (nsec_times + 1) % 10; 
     470         
     471                if (nsec_times < nsec_adjuster) { 
     472                    /* sorta looks like a no-op, but gives us a nice round usec number */ 
     473                    nap_this_time.tv_nsec = (nap_this_time.tv_nsec / 1000 * 1000) + 1000; 
     474                } else { 
     475                    nap_this_time.tv_nsec -= (nap_this_time.tv_nsec % 1000); 
     476                } 
     477     
     478                dbgx(3, "(%ld)\tnsec_times = %ld\tnap adjust: %lu -> %lu", nsec_adjuster, nsec_times, nap.tv_nsec, nap_this_time.tv_nsec);             
     479                break; 
     480                 
     481            default: 
     482                errx(1, "Unknown/supported speed mode: %d", options.speed.mode); 
     483        } 
     484    } 
     485 
     486 
     487    get_delta_time(delta_ctx, &delta_time); 
     488    dbgx(2, "delta: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec); 
     489 
     490    if (timesisset(&delta_time)) { 
     491        if (timescmp(&nap_this_time, &delta_time, >)) { 
     492            timessub(&nap_this_time, &delta_time, &nap_this_time); 
     493            dbgx(3, "timesub: %lu %lu", delta_time.tv_sec, delta_time.tv_nsec); 
     494        } else {  
     495            timesclear(&nap_this_time); 
     496            dbgx(3, "timesclear: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec); 
     497        } 
     498    } 
     499 
     500    /* apply the adjuster... */ 
     501    if (timesisset(&adjuster)) { 
     502        if (timescmp(&nap_this_time, &adjuster, >)) { 
     503            timessub(&nap_this_time, &adjuster, &nap_this_time); 
     504        } else {  
     505            timesclear(&nap_this_time); 
     506        } 
     507    } 
     508     
     509    dbgx(2, "Sleeping: " TIMESPEC_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_nsec); 
     510 
     511    /* don't sleep if nap = {0, 0} */ 
     512    if (!timesisset(&nap_this_time)) 
     513        return; 
     514         
     515    /* 
     516     * Depending on the accurate method & packet rate computation method 
     517     * We have multiple methods of sleeping, pick the right one... 
     518     */ 
     519    switch (accurate) { 
     520#ifdef HAVE_SELECT 
     521    case ACCURATE_SELECT: 
     522        select_sleep(nap_this_time); 
     523        break; 
     524#endif 
     525 
     526#ifdef HAVE_IOPERM 
     527    case ACCURATE_IOPORT: 
     528        ioport_sleep(nap_this_time); 
     529        break; 
     530#endif 
     531 
     532#ifdef HAVE_RDTSC         
     533    case ACCURATE_RDTSC: 
     534        rdtsc_sleep(nap_this_time); 
     535        break; 
     536#endif 
     537 
     538#ifdef HAVE_ABSOLUTE_TIME 
     539    case ACCURATE_ABS_TIME: 
     540        absolute_time_sleep(nap_this_time); 
     541        break; 
     542#endif 
     543 
     544    case ACCURATE_GTOD: 
     545        gettimeofday_sleep(nap_this_time); 
     546        break; 
     547 
     548    case ACCURATE_NANOSLEEP: 
     549        nanosleep_sleep(nap_this_time); 
     550        break; 
     551        /* 
     552        timeradd(&didsleep, &nap_this_time, &didsleep); 
     553 
     554        dbgx(4, "I will sleep " TIMEVAL_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_usec); 
     555 
     556        if (timercmp(&didsleep, &sleep_until, >)) { 
     557            timersub(&didsleep, &sleep_until, &nap_this_time); 
     558             
     559            TIMEVAL_TO_TIMESPEC(&nap_this_time, &sleep); 
     560            dbgx(4, "Sleeping " TIMEVAL_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_usec); 
    459561#ifdef DEBUG 
    460             timeradd(&totalsleep, &nap, &totalsleep); 
     562            timeradd(&totalsleep, &nap_this_time, &totalsleep); 
    461563#endif 
    462564            if (nanosleep(&sleep, &ignore) == -1) { 
     
    464566            } 
    465567        } 
    466     } else { 
    467         timeradd(&now, &nap, &delta); 
    468         loop = sleep_loop(delta); 
    469         dbgx(3, "sleep_loop looped %u times", loop); 
    470     } 
     568        break; 
     569        */ 
     570    default: 
     571        errx(1, "Unknown timer mode %d", accurate); 
     572    } 
     573 
    471574#ifdef DEBUG 
    472575    dbgx(4, "Total sleep time: " TIMEVAL_FORMAT, totalsleep.tv_sec, totalsleep.tv_usec); 
    473576#endif 
     577 
     578    dbgx(2, "sleep delta: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec); 
     579 
    474580} 
    475581 
     
    479585 * but at the cost of being more CPU intensive. 
    480586 */ 
    481 static u_int32_t  
    482 sleep_loop(struct timeval time) 
     587static u_int32_t 
     588get_user_count(sendpacket_t *sp, COUNTER counter)  
    483589{ 
    484    struct timeval now; 
    485    u_int32_t loop = 0; 
    486    do { 
    487         gettimeofday(&now, NULL); 
    488         loop ++; 
    489    } while (now.tv_sec < time.tv_sec || now.tv_usec < time.tv_usec); 
    490    return loop; 
     590    struct pollfd poller[1];        /* use poll to read from the keyboard */ 
     591    char input[EBUF_SIZE]; 
     592    u_int32_t send = 0; 
     593     
     594    printf("**** Next packet #" COUNTER_SPEC " out %s.  How many packets do you wish to send? ", 
     595        counter, (sp == options.intf1 ? options.intf1_name : options.intf2_name)); 
     596    fflush(NULL); 
     597    poller[0].fd = STDIN_FILENO; 
     598    poller[0].events = POLLIN | POLLPRI | POLLNVAL; 
     599    poller[0].revents = 0; 
     600 
     601    if (fcntl(0, F_SETFL, fcntl(0, F_GETFL) & ~O_NONBLOCK))  
     602           errx(1, "Unable to clear non-blocking flag on stdin: %s", strerror(errno)); 
     603 
     604    /* wait for the input */ 
     605    if (poll(poller, 1, -1) < 0) 
     606        errx(1, "Error reading user input from stdin: %s", strerror(errno)); 
     607     
     608    /* 
     609     * read to the end of the line or EBUF_SIZE, 
     610     * Note, if people are stupid, and type in more text then EBUF_SIZE 
     611     * then the next fgets() will pull in that data, which will have poor  
     612     * results.  fuck them. 
     613     */ 
     614    if (fgets(input, sizeof(input), stdin) == NULL) { 
     615        errx(1, "Unable to process user input for fd %d: %s", fileno(stdin), strerror(errno)); 
     616    } else if (strlen(input) > 1) { 
     617        send = strtoul(input, NULL, 0); 
     618    } 
     619 
     620    /* how many packets should we send? */ 
     621    if (send == 0) { 
     622        dbg(1, "Input was less then 1 or non-numeric, assuming 1"); 
     623 
     624        /* assume send only one packet */ 
     625        send = 1; 
     626    } 
     627     
     628    return send; 
    491629} 
    492630 
  • trunk/src/sleep.c

    r1977 r2006  
    6161#ifdef HAVE_IOPERM 
    6262    ioperm(0x80,1,1); 
     63    ioport_sleep_value = inb(0x80);     
    6364#else 
    6465    err(1, "Platform does not support IO Port for timing"); 
    6566#endif 
    66     ioport_sleep_value=inb(0x80);     
    6767} 
    6868 
     
    7070ioport_sleep(const struct timespec nap)  
    7171{ 
     72#ifdef HAVE_IOPERM 
    7273    struct timeval nap_for; 
    7374    u_int32_t usec; 
     
    9596        outb(ioport_sleep_value, 0x80); 
    9697    } 
     98#else 
     99    err(1, "Platform does not support IO Port for timing"); 
     100#endif 
    97101} 
  • trunk/src/tcpprep.c

    r1988 r2006  
    460460                check_ip_tree(DIR_UNKNOWN, ip_hdr->ip_src.s_addr)); 
    461461            break; 
     462             
     463        default: 
     464            errx(1, "Whops!  What mode are we in anyways? %d", options.mode); 
    462465        } 
    463466#ifdef ENABLE_VERBOSE 
  • trunk/src/tcpreplay.c

    r1992 r2006  
    22 
    33/* 
    4  * Copyright (c) 2001-2007 Aaron Turner. 
     4 * Copyright (c) 2001-2008 Aaron Turner. 
    55 * All rights reserved. 
    66 * 
     
    6868#endif 
    6969 
     70#ifdef HAVE_ABSOLUTE_TIME 
     71#include <CoreServices/CoreServices.h> 
     72#endif 
     73 
    7074void replay_file(int file_idx); 
    7175void usage(void); 
     
    276280    char ebuf[SENDPACKET_ERRBUF_SIZE]; 
    277281    int int1dlt, int2dlt; 
     282    float gtod = 14.5; 
    278283     
    279284#ifdef ENABLE_PCAP_FINDALLDEVS 
     
    290295        warn("not configured with --enable-debug.  Debugging disabled."); 
    291296#endif 
    292      
     297         
    293298    options.loop = OPT_VALUE_LOOP; 
    294299 
     
    330335        } 
    331336 
    332     if (HAVE_OPT(ACCURATE)) 
    333         options.accurate = 1; 
    334          
     337    if (HAVE_OPT(TIMER)) { 
     338        if (strcmp(OPT_ARG(TIMER), "select") == 0) { 
     339#ifdef HAVE_SELECT 
     340            options.accurate = ACCURATE_SELECT; 
     341#else 
     342            err(1, "tcpreplay not compiled with select support"); 
     343#endif 
     344        } else if (strcmp(OPT_ARG(TIMER), "rdtsc") == 0) { 
     345#ifdef HAVE_RDTSC 
     346            options.accurate = ACCURATE_RDTSC; 
     347#else 
     348            err(1, "tcpreplay not compiled with rdtsc support"); 
     349#endif 
     350        } else if (strcmp(OPT_ARG(TIMER), "ioport") == 0) { 
     351#if defined HAVE_IOPERM && defined(__i386__) 
     352            options.accurate = ACCURATE_IOPORT; 
     353            ioport_sleep_init(); 
     354#else 
     355            err(1, "tcpreplay not compiled with IO Port 0x80 support"); 
     356#endif 
     357        } else if (strcmp(OPT_ARG(TIMER), "gtod") == 0) { 
     358            options.accurate = ACCURATE_GTOD; 
     359        } else if (strcmp(OPT_ARG(TIMER), "nano") == 0) { 
     360            options.accurate = ACCURATE_NANOSLEEP; 
     361        } else if (strcmp(OPT_ARG(TIMER), "abstime") == 0) { 
     362#ifdef HAVE_ABSOLUTE_TIME 
     363            options.accurate = ACCURATE_ABS_TIME; 
     364            if  (!MPLibraryIsLoaded()) { 
     365                err(1, "The MP library did not load.\n"); 
     366            }             
     367#else 
     368            err(1, "tcpreplay only supports absolute time on Apple OS X"); 
     369#endif 
     370        } else { 
     371            errx(1, "Unsupported timer mode: %s", OPT_ARG(TIMER)); 
     372        } 
     373    } 
     374 
     375#ifdef HAVE_RDTSC 
     376    if (HAVE_OPT(RDTSC_CLICKS)) { 
     377        rdtsc_calibrate(OPT_VALUE_RDTSC_CLICKS); 
     378    } 
     379#endif 
     380 
    335381    if (HAVE_OPT(PKTLEN)) 
    336382        warn("--pktlen may cause problems.  Use with caution."); 
  • trunk/src/tcpreplay.h

    r1944 r2006  
    22 
    33/* 
    4  * Copyright (c) 2001-2007 Aaron Turner. 
     4 * Copyright (c) 2001-2008 Aaron Turner. 
    55 * All rights reserved. 
    66 * 
     
    4747#endif 
    4848 
    49 struct packet_cache_s 
    50 { 
     49struct packet_cache_s { 
    5150        struct pcap_pkthdr pkthdr; 
    5251        u_char *pktdata; 
     
    5756typedef struct packet_cache_s packet_cache_t; 
    5857 
    59 typedef struct 
    60 { 
     58typedef struct { 
    6159        int index; 
    6260        int cached; 
     
    7270    sendpacket_t *intf1; 
    7371    sendpacket_t *intf2; 
    74 /* disable data dump mode 
    75     pcap_t *savepcap1; 
    76     pcap_t *savepcap2; 
    77     pcap_dumper_t *savedumper1; 
    78     pcap_dumper_t *savedumper2; 
    7972 
    80     int datadump_mode; 
    81     int datadumpfile1; 
    82     int datadumpfile2; 
    83 */ 
    8473    tcpr_speed_t speed; 
    8574    u_int32_t loop; 
     
    9483    int truncate; 
    9584     
    96     /* use gettimeofday() instead of sleeping between packets */ 
     85    /* accurate mode to use */ 
    9786    int accurate; 
     87#define ACCURATE_NANOSLEEP  0 
     88#define ACCURATE_SELECT     1 
     89#define ACCURATE_RDTSC      2 
     90#define ACCURATE_IOPORT     3 
     91#define ACCURATE_GTOD       4 
     92#define ACCURATE_ABS_TIME   5 
    9893     
    9994    char *files[MAX_FILES]; 
    10095    COUNTER limit_send; 
    10196     
    102      
    103 /* disable bridge mode 
    104     pcap_t *listen1; 
    105     pcap_t *listen2; 
    106     int sniff_snaplen; 
    107     int sniff_bridge; 
    108     int promisc; 
    109     int poll_timeout; 
    110 */ 
    111  
    11297#ifdef ENABLE_VERBOSE 
    11398    /* tcpdump verbose printing */ 
  • trunk/src/tcpreplay_opts.def

    r2003 r2006  
    7979processor, disk and system bus will allow. 
    8080 
     81Packet timing at high speeds is a black art and very OS/CPU dependent.   
     82Your best bet is to use @var{--timing=rdtsc}, do your own testing and tweak the  
     83@var{--rdtsc-clicks} option accordingly.  Newer CPU's and Linux kernels 
     84with HPET enabled may have good results with @var{--timing=gtod}. 
     85 
    8186Replaying captured traffic may simulate odd or broken conditions on your 
    8287network and cause problems. 
     
    114119 
    115120flag = { 
    116         name            = accurate; 
    117         value           = a; 
     121        name            = timer; 
     122        value           = T; 
    118123        max                     = 1; 
    119         flags-cant  = accurate2; 
    120         descrip         = "Enable more accurate packet timing"; 
     124        arg-type    = string; 
     125        descrip         = "Select packet timing mode: select, ioport, rdtsc, gtod, nano, abstime"; 
    121126        doc                     = <<- EOText 
    122 Enables more accurate timing between packets at the cost of higher 
    123 CPU utilization by using the gettimeofday() system call.  This method 
    124 works better on some systems then others and may have rather non-granular 
    125 resolution which makes it problematic for replaying at high rates of speed. 
    126 EOText; 
    127 }; 
    128  
    129 flag = { 
    130     name        = accurate2; 
    131     max         = 1; 
    132     flags-cant  = accurate; 
    133     arg-type    = number; 
    134     descrip     = "Enable even more accurate packet timing"; 
    135     doc         = <<- EOText 
    136 Enables the "even more" accurate timing at the cost of higher CPU 
    137 utilization by using a tight loop which increments a counter.   This method 
    138 provides the most accurate timing of any option, but requires you to specify 
    139 a cost for each loop.  This cost value is VERY system dependent, so you will 
    140 need to run --loop-test to get this value. 
     127Allows you to select the packet timing method to use: 
     128@enumerate 
     129@item nano 
     130- Use nanosleep() API [default] 
     131@item select 
     132- Use select() API 
     133@item ioport 
     134- Write to the i386 IO Port 0x80 
     135@item rdtsc   
     136- Use the x86/x86_64/PPC RDTSC 
     137@item gtod    
     138- Use a gettimeofday() loop 
     139@item abstime 
     140- Use OS X's AbsoluteTime 
     141@end enumerate 
     142 
     143EOText; 
     144}; 
     145 
     146flag = { 
     147    name        = sleep-accel; 
     148    arg-type    = number; 
     149    arg-default = 5; 
     150    descrip     = "Reduce the amount of time to sleep by specified usec"; 
     151    doc         = <<- EOText 
     152Reduce the amount of time we would normally sleep between two packets by the  
     153specified number of usec.  This is primarily intended to compensate for the 
     154overhead in tcpreplay to process & send packets.  Default is 5usec which seems 
     155to work well on my 2.16Ghz MacBook Pro. 
     156EOText; 
     157}; 
     158 
     159flag = { 
     160    name        = rdtsc-clicks; 
     161    max         = 1; 
     162    arg-type    = number; 
     163    arg-default = 0; 
     164    descrip     = "Specify the RDTSC clicks/usec"; 
     165    doc         = <<- EOText 
     166Override the calculated number of RDTSC clicks/usec which is often the speed of the  
     167CPU in Mhz.  Only useful if you specified @var{--timer=rdtsc} 
    141168EOText; 
    142169}; 
     
    172199}; 
    173200 
    174 /* Cache files to internal memory */ 
     201/* Cache files to internal memory */  
    175202flag = { 
    176203        name            = enable_file_cache; 
     
    222249    doc         = ""; 
    223250}; 
    224  
     251/* 
    225252flag = { 
    226253        ifdef           = ENABLE_PCAP_FINDALLDEVS; 
     
    238265EOFlag; 
    239266}; 
    240  
     267*/ 
    241268/* 
    242269 * Limits and loops: -l 
Note: See TracChangeset for help on using the changeset viewer.