Changeset 2006
- Timestamp:
- 05/01/08 04:46:55 (2 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
- 4 copied
-
configure.ac (modified) (4 diffs)
-
src/Makefile.am (modified) (3 diffs)
-
src/common.h (modified) (1 diff)
-
src/common/Makefile.am (modified) (2 diffs)
-
src/common/rdtsc.c (copied) (copied from features/performance/src/common/rdtsc.c)
-
src/common/rdtsc.h (copied) (copied from features/performance/src/common/rdtsc.h)
-
src/common/timer.c (modified) (1 diff)
-
src/common/timer.h (modified) (7 diffs)
-
src/defines.h.in (modified) (2 diffs)
-
src/send_packets.c (modified) (17 diffs)
-
src/sleep.c (copied) (copied from features/performance/src/sleep.c) (3 diffs)
-
src/sleep.h (copied) (copied from features/performance/src/sleep.h)
-
src/tcpprep.c (modified) (1 diff)
-
src/tcpreplay.c (modified) (5 diffs)
-
src/tcpreplay.h (modified) (5 diffs)
-
src/tcpreplay_opts.def (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/configure.ac
r2004 r2006 68 68 AUTOGEN_MAJOR=`echo ${AUTOGEN_VERSION} | ${SED} 's|^\([[0-9]]\)\.[[0-9]]|\1|'` 69 69 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); then70 if ( ${AUTOGEN_MAJOR} -eq 5 && ${AUTOGEN_MINOR} -lt 9 ) || ${AUTOGEN_MAJOR} -lt 5 ; then 71 71 AC_MSG_RESULT(no) 72 72 AC_MSG_WARN([${AUTOGEN} is too old (${AUTOGEN_VERSION}) for building from SVN. Please upgrade to 5.9)]) … … 1085 1085 disable_pcap_findalldevs=no 1086 1086 1087 1087 osx_frameworks=no 1088 1088 dnl these need to be dynamic based on OS 1089 1089 case $host in … … 1112 1112 disable_pcap_findalldevs=yes 1113 1113 fi 1114 AC_DEFINE([HAVE_ABSOLUTE_TIME], [1], [Have OS X UpTime()/AbsoluteTime high-precision timing]) 1115 osx_frameworks=yes 1114 1116 AC_MSG_RESULT(Apple OS X) 1115 1117 ;; … … 1134 1136 esac]) 1135 1137 1138 AM_CONDITIONAL([ENABLE_OSX_FRAMEWORKS], test "$osx_frameworks" == "yes") 1136 1139 1137 1140 AC_ARG_WITH(testnic2, -
trunk/src/Makefile.am
r1965 r2006 60 60 61 61 tcpreplay_LDADD += ./common/libcommon.a $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) 62 tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c 62 tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c sleep.c 63 64 if ENABLE_OSX_FRAMEWORKS 65 tcpreplay_LDFLAGS = -framework CoreServices -framework Carbon 66 endif 63 67 64 68 tcpreplay_OBJECTS: tcpreplay_opts.h … … 94 98 tcpbridge_LDADD = ./tcpedit/libtcpedit.a ./common/libcommon.a \ 95 99 $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) @DMALLOC_LIB@ 96 tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c 100 if ENABLE_OSX_FRAMEWORKS 101 tcpbridge_LDFLAGS = -framework CoreServices -framework Carbon 102 endif 103 tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c sleep.c 97 104 tcpbridge_OBJECTS: tcpbridge_opts.h 98 105 tcpbridge_opts.h: tcpbridge_opts.c … … 104 111 tcpreplay_edit_opts.h tcprewrite.h tcprewrite_opts.h tcpprep_opts.h \ 105 112 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 107 114 108 115 -
trunk/src/common.h
r1757 r2006 16 16 #include "common/utils.h" 17 17 #include "common/xX.h" 18 #include "common/rdtsc.h" 18 19 #include "common/tcpdump.h" 19 20 #include "common/timer.h" -
trunk/src/common/Makefile.am
r1961 r2006 15 15 fakepcap.c fakepcapnav.c fakepoll.c xX.c utils.c \ 16 16 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 18 18 19 19 if ENABLE_TCPDUMP … … 28 28 fakepcap.h fakepcapnav.h fakepoll.h xX.h utils.h \ 29 29 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 31 31 32 32 MOSTLYCLEANFILES = *~ -
trunk/src/common/timer.c
r1897 r2006 57 57 } 58 58 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 */ 60 void timesdiv(struct timespec *tvs, float div) 64 61 { 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 } 66 71 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 43 43 #include <math.h> 44 44 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 45 66 /* 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 47 71 * 1 microsec = 1,000 nanosec 48 * 1 sec = 1,000,000,000 nanosec49 72 */ 50 73 51 74 void timerdiv(struct timeval *tvp, float div); 75 void timesdiv(struct timespec *tvs, float div); 52 76 53 77 /* convert float time to struct timeval *tvp */ … … 57 81 tvp->tv_sec = time; \ 58 82 tvp->tv_usec = (time - tvp->tv_sec) * 100000; \ 59 } while (0) ;83 } while (0) 60 84 #endif 61 85 … … 67 91 #endif 68 92 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 69 108 /* zero out a timer */ 70 109 #ifndef timerclear … … 72 111 #endif 73 112 113 /* zero out a timespec */ 114 #ifndef timesclear 115 #define timesclear(tvs) (tvs)->tv_sec = (tvs)->tv_nsec = 0 116 #endif 117 74 118 /* is timer non-zero? */ 75 119 #ifndef timerisset 76 120 #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) 77 121 #endif 122 123 /* is timespec non-zero? */ 124 #ifndef timesisset 125 #define timesisset(tvs) ((tvs)->tv_sec || (tvs)->tv_nsec) 126 #endif 127 78 128 79 129 /* add tvp and uvp and store in vvp */ … … 103 153 #endif 104 154 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 105 167 /* compare tvp and uvp using cmp */ 106 168 #ifndef timercmp … … 109 171 ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 110 172 ((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)) 111 180 #endif 112 181 … … 122 191 } while(0) 123 192 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 */ 203 static inline void 204 start_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 */ 217 static inline void 218 get_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 162 162 163 163 /* struct timeval print structs */ 164 #define TIMEVAL_FORMAT "%lu.%06lu" 164 #define TIMEVAL_FORMAT "%lus %luusec" 165 #define TIMESPEC_FORMAT "%lus %lunsec" 165 166 166 167 /* force a word or half-word swap on both Big and Little endian systems */ … … 232 233 233 234 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 234 276 #endif /* DEFINES */ -
trunk/src/send_packets.c
r1898 r2006 2 2 3 3 /* 4 * Copyright (c) 2001-200 7Aaron Turner.4 * Copyright (c) 2001-2008 Aaron Turner. 5 5 * All rights reserved. 6 6 * … … 31 31 */ 32 32 33 #define ADJUSTER_OFFSET 5 /* number of usec to compensate for packet timing */ 33 34 34 35 #include "config.h" … … 59 60 60 61 #include "send_packets.h" 62 #include "sleep.h" 61 63 62 64 extern tcpreplay_opt_t options; … … 69 71 #endif 70 72 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); 73 static void do_sleep(struct timeval *time, struct timeval *last, int len, 74 int accurate, sendpacket_t *sp, COUNTER counter, delta_t *ctx); 75 static const u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, 76 int file_idx, packet_cache_t **prev_packet); 77 static u_int32_t get_user_count(sendpacket_t *sp, COUNTER counter); 75 78 76 79 /** … … 92 95 struct pcap_pkthdr *pkthdr_ptr; 93 96 #endif 94 97 delta_t delta_ctx; 98 95 99 /* register signals */ 96 100 didsig = 0; … … 160 164 /* 161 165 * 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) 163 168 */ 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 166 175 /* write packet out on network */ 167 176 if (sendpacket(sp, pktdata, pktlen) < (int)pktlen) 168 177 warnx("Unable to send packet: %s", sendpacket_geterr(sp)); 169 178 170 179 /* 171 180 * track the time of the "last packet sent". Again, because of OpenBSD … … 194 203 * will be updated as new entries are added (or retrieved) from the cache list. 195 204 */ 196 static u_char *205 static const u_char * 197 206 get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx, 198 207 packet_cache_t **prev_packet) … … 233 242 * We should read the pcap file, and cache the results 234 243 */ 235 pktdata = pcap_next(pcap, pkthdr);244 pktdata = (u_char *)pcap_next(pcap, pkthdr); 236 245 if (pktdata != NULL) { 237 246 if (*prev_packet == NULL) { … … 263 272 * Read pcap file as normal 264 273 */ 265 pktdata = pcap_next(pcap, pkthdr);274 pktdata = (u_char *)pcap_next(pcap, pkthdr); 266 275 } 267 276 277 /* this get's casted to a const on the way out */ 268 278 return pktdata; 269 279 } … … 310 320 */ 311 321 static void 312 do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, sendpacket_t *sp,313 COUNTER counter)322 do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, 323 sendpacket_t *sp, COUNTER counter, delta_t *delta_ctx) 314 324 { 315 325 static struct timeval didsleep = { 0, 0 }; … … 318 328 static struct timeval totalsleep = { 0, 0 }; 319 329 #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; 322 335 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 --; 330 350 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) 335 356 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); 339 359 340 360 /* First time through for this file */ 341 361 if (pkts_sent == 0 || ((options.speed.mode != SPEED_MBPSRATE) && (counter == 0))) { 342 362 start = now; 343 timerclear(& delta);363 timerclear(&sleep_until); 344 364 timerclear(&didsleep); 345 365 } 346 366 else { 347 timersub(&now, &start, & delta);367 timersub(&now, &start, &sleep_until); 348 368 } 349 369 350 370 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 351 379 case SPEED_MULTIPLIER: 352 380 /* … … 354 382 */ 355 383 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); 358 387 } 359 388 else { … … 363 392 * last packet. 364 393 */ 365 time rclear(&nap);366 } 394 timesclear(&nap); 395 } 367 396 break; 368 397 … … 375 404 n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */ 376 405 nap.tv_sec = n; 377 nap.tv_usec = (n - nap.tv_sec) * 1000000; 406 nap.tv_nsec = (n - nap.tv_sec) * 1000000000; 407 378 408 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); 380 410 } 381 411 else { 382 timerclear(&nap); 412 /* don't sleep at all for the first packet */ 413 timesclear(&nap); 383 414 } 384 415 break; 385 416 386 417 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 394 427 case SPEED_ONEATATIME: 395 428 /* do we skip prompting for a key press? */ 396 429 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); 431 431 } 432 432 … … 446 446 } 447 447 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); 459 561 #ifdef DEBUG 460 timeradd(&totalsleep, &nap , &totalsleep);562 timeradd(&totalsleep, &nap_this_time, &totalsleep); 461 563 #endif 462 564 if (nanosleep(&sleep, &ignore) == -1) { … … 464 566 } 465 567 } 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 471 574 #ifdef DEBUG 472 575 dbgx(4, "Total sleep time: " TIMEVAL_FORMAT, totalsleep.tv_sec, totalsleep.tv_usec); 473 576 #endif 577 578 dbgx(2, "sleep delta: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec); 579 474 580 } 475 581 … … 479 585 * but at the cost of being more CPU intensive. 480 586 */ 481 static u_int32_t 482 sleep_loop(struct timeval time) 587 static u_int32_t 588 get_user_count(sendpacket_t *sp, COUNTER counter) 483 589 { 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; 491 629 } 492 630 -
trunk/src/sleep.c
r1977 r2006 61 61 #ifdef HAVE_IOPERM 62 62 ioperm(0x80,1,1); 63 ioport_sleep_value = inb(0x80); 63 64 #else 64 65 err(1, "Platform does not support IO Port for timing"); 65 66 #endif 66 ioport_sleep_value=inb(0x80);67 67 } 68 68 … … 70 70 ioport_sleep(const struct timespec nap) 71 71 { 72 #ifdef HAVE_IOPERM 72 73 struct timeval nap_for; 73 74 u_int32_t usec; … … 95 96 outb(ioport_sleep_value, 0x80); 96 97 } 98 #else 99 err(1, "Platform does not support IO Port for timing"); 100 #endif 97 101 } -
trunk/src/tcpprep.c
r1988 r2006 460 460 check_ip_tree(DIR_UNKNOWN, ip_hdr->ip_src.s_addr)); 461 461 break; 462 463 default: 464 errx(1, "Whops! What mode are we in anyways? %d", options.mode); 462 465 } 463 466 #ifdef ENABLE_VERBOSE -
trunk/src/tcpreplay.c
r1992 r2006 2 2 3 3 /* 4 * Copyright (c) 2001-200 7Aaron Turner.4 * Copyright (c) 2001-2008 Aaron Turner. 5 5 * All rights reserved. 6 6 * … … 68 68 #endif 69 69 70 #ifdef HAVE_ABSOLUTE_TIME 71 #include <CoreServices/CoreServices.h> 72 #endif 73 70 74 void replay_file(int file_idx); 71 75 void usage(void); … … 276 280 char ebuf[SENDPACKET_ERRBUF_SIZE]; 277 281 int int1dlt, int2dlt; 282 float gtod = 14.5; 278 283 279 284 #ifdef ENABLE_PCAP_FINDALLDEVS … … 290 295 warn("not configured with --enable-debug. Debugging disabled."); 291 296 #endif 292 297 293 298 options.loop = OPT_VALUE_LOOP; 294 299 … … 330 335 } 331 336 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 335 381 if (HAVE_OPT(PKTLEN)) 336 382 warn("--pktlen may cause problems. Use with caution."); -
trunk/src/tcpreplay.h
r1944 r2006 2 2 3 3 /* 4 * Copyright (c) 2001-200 7Aaron Turner.4 * Copyright (c) 2001-2008 Aaron Turner. 5 5 * All rights reserved. 6 6 * … … 47 47 #endif 48 48 49 struct packet_cache_s 50 { 49 struct packet_cache_s { 51 50 struct pcap_pkthdr pkthdr; 52 51 u_char *pktdata; … … 57 56 typedef struct packet_cache_s packet_cache_t; 58 57 59 typedef struct 60 { 58 typedef struct { 61 59 int index; 62 60 int cached; … … 72 70 sendpacket_t *intf1; 73 71 sendpacket_t *intf2; 74 /* disable data dump mode75 pcap_t *savepcap1;76 pcap_t *savepcap2;77 pcap_dumper_t *savedumper1;78 pcap_dumper_t *savedumper2;79 72 80 int datadump_mode;81 int datadumpfile1;82 int datadumpfile2;83 */84 73 tcpr_speed_t speed; 85 74 u_int32_t loop; … … 94 83 int truncate; 95 84 96 /* use gettimeofday() instead of sleeping between packets*/85 /* accurate mode to use */ 97 86 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 98 93 99 94 char *files[MAX_FILES]; 100 95 COUNTER limit_send; 101 96 102 103 /* disable bridge mode104 pcap_t *listen1;105 pcap_t *listen2;106 int sniff_snaplen;107 int sniff_bridge;108 int promisc;109 int poll_timeout;110 */111 112 97 #ifdef ENABLE_VERBOSE 113 98 /* tcpdump verbose printing */ -
trunk/src/tcpreplay_opts.def
r2003 r2006 79 79 processor, disk and system bus will allow. 80 80 81 Packet timing at high speeds is a black art and very OS/CPU dependent. 82 Your 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 84 with HPET enabled may have good results with @var{--timing=gtod}. 85 81 86 Replaying captured traffic may simulate odd or broken conditions on your 82 87 network and cause problems. … … 114 119 115 120 flag = { 116 name = accurate;117 value = a;121 name = timer; 122 value = T; 118 123 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"; 121 126 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. 127 Allows 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 143 EOText; 144 }; 145 146 flag = { 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 152 Reduce the amount of time we would normally sleep between two packets by the 153 specified number of usec. This is primarily intended to compensate for the 154 overhead in tcpreplay to process & send packets. Default is 5usec which seems 155 to work well on my 2.16Ghz MacBook Pro. 156 EOText; 157 }; 158 159 flag = { 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 166 Override the calculated number of RDTSC clicks/usec which is often the speed of the 167 CPU in Mhz. Only useful if you specified @var{--timer=rdtsc} 141 168 EOText; 142 169 }; … … 172 199 }; 173 200 174 /* Cache files to internal memory */ 201 /* Cache files to internal memory */ 175 202 flag = { 176 203 name = enable_file_cache; … … 222 249 doc = ""; 223 250 }; 224 251 /* 225 252 flag = { 226 253 ifdef = ENABLE_PCAP_FINDALLDEVS; … … 238 265 EOFlag; 239 266 }; 240 267 */ 241 268 /* 242 269 * Limits and loops: -l
Note: See TracChangeset
for help on using the changeset viewer.
