@@ -235,6 +235,7 @@ fast_edit_packet_dl(struct pcap_pkthdr *pkthdr, u_char **pktdata,
235235 * dst_ptr = htonl (dst_ip );
236236}
237237
238+ #if defined HAVE_QUICK_TX || defined HAVE_NETMAP
238239static inline void wake_send_queues (sendpacket_t * sp , tcpreplay_opt_t * options )
239240{
240241#ifdef HAVE_QUICK_TX
@@ -247,6 +248,7 @@ static inline void wake_send_queues(sendpacket_t *sp, tcpreplay_opt_t *options)
247248 ioctl (sp -> handle .fd , NIOCTXSYNC , NULL ); /* flush TX buffer */
248249#endif
249250}
251+ #endif /* HAVE_QUICK_TX || HAVE_NETMAP */
250252
251253static inline void
252254fast_edit_packet (struct pcap_pkthdr * pkthdr , u_char * * pktdata ,
@@ -488,9 +490,10 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
488490 COUNTER iteration = ctx -> iteration ;
489491 bool unique_ip = options -> unique_ip ;
490492 bool preload = options -> file_cache [idx ].cached ;
491- bool top_speed = options -> speed .mode == speed_topspeed ;
493+ bool top_speed = ( options -> speed .mode == speed_topspeed ) ;
492494 bool now_is_now = false;
493495
496+ ctx -> skip_packets = 0 ;
494497 start_us = TIMEVAL_TO_MICROSEC (& ctx -> stats .start_time );
495498
496499 if (options -> limit_time > 0 )
@@ -565,12 +568,16 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
565568 if (skip_length && pktlen < skip_length ) {
566569 skip_length -= pktlen ;
567570 now_is_now = false;
571+ } else if (ctx -> skip_packets ) {
572+ -- ctx -> skip_packets ;
573+ now_is_now = false;
568574 } else {
569575 /*
570576 * time stamping is expensive, but now is the
571577 * time to do it.
572578 */
573579 skip_length = 0 ;
580+ ctx -> skip_packets = 0 ;
574581 now_is_now = true;
575582 gettimeofday (& now , NULL );
576583
@@ -580,7 +587,7 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
580587 * This also sets skip_length which will avoid timestamping for
581588 * a given number of packets.
582589 */
583- calc_sleep_time (ctx , ( struct timeval * ) & pkthdr .ts , & ctx -> stats .last_time , pktlen , sp , packetnum ,
590+ calc_sleep_time (ctx , & pkthdr .ts , & ctx -> stats .last_time , pktlen , sp , packetnum ,
584591 & ctx -> stats .end_time , & start_us , & skip_length );
585592
586593 /*
@@ -634,14 +641,12 @@ send_packets(tcpreplay_t *ctx, pcap_t *pcap, int idx)
634641 }
635642 }
636643
637- if (sp == ctx -> intf1 && ctx -> first_time_intf1 ) {
638- wake_send_queues (sp , options );
639- ctx -> first_time_intf1 = 0 ;
640- } else if (sp == ctx -> intf2 && ctx -> first_time_intf2 ) {
644+ #if defined HAVE_QUICK_TX || defined HAVE_NETMAP
645+ if (sp -> first_packet ) {
641646 wake_send_queues (sp , options );
642- ctx -> first_time_intf2 = 0 ;
647+ sp -> first_packet = false ;
643648 }
644-
649+ #endif
645650 /* stop sending based on the duration limit... */
646651 if ((end_us > 0 && TIMEVAL_TO_MICROSEC (& now ) > end_us ) ||
647652 /* ... or stop sending based on the limit -L? */
@@ -699,10 +704,10 @@ send_dual_packets(tcpreplay_t *ctx, pcap_t *pcap1, int cache_file_idx1, pcap_t *
699704 COUNTER start_us ;
700705 COUNTER end_us ;
701706 COUNTER skip_length = 0 ;
702- bool top_speed = options -> speed .mode == speed_topspeed ||
703- (options -> speed .mode == speed_mbpsrate && !options -> speed .speed );
707+ bool top_speed = (options -> speed .mode == speed_topspeed );
704708 bool now_is_now = false;
705709
710+ ctx -> skip_packets = 0 ;
706711 start_us = TIMEVAL_TO_MICROSEC (& ctx -> stats .start_time );
707712
708713 if (options -> limit_time > 0 )
@@ -809,12 +814,16 @@ send_dual_packets(tcpreplay_t *ctx, pcap_t *pcap1, int cache_file_idx1, pcap_t *
809814 if (skip_length && pktlen < skip_length ) {
810815 skip_length -= pktlen ;
811816 now_is_now = false;
817+ } else if (ctx -> skip_packets ) {
818+ -- ctx -> skip_packets ;
819+ now_is_now = false;
812820 } else {
813821 /*
814822 * time stamping is expensive, but now is the
815823 * time to do it.
816824 */
817825 skip_length = 0 ;
826+ ctx -> skip_packets = 0 ;
818827 now_is_now = true;
819828 gettimeofday (& now , NULL );
820829
@@ -824,7 +833,7 @@ send_dual_packets(tcpreplay_t *ctx, pcap_t *pcap1, int cache_file_idx1, pcap_t *
824833 * This also sets skip_length which will avoid timestamping for
825834 * a given number of packets.
826835 */
827- calc_sleep_time (ctx , ( struct timeval * ) & pkthdr_ptr -> ts , & ctx -> stats .last_time , pktlen , sp , packetnum ,
836+ calc_sleep_time (ctx , & pkthdr_ptr -> ts , & ctx -> stats .last_time , pktlen , sp , packetnum ,
828837 & ctx -> stats .end_time , & start_us , & skip_length );
829838
830839 /*
@@ -875,13 +884,12 @@ send_dual_packets(tcpreplay_t *ctx, pcap_t *pcap1, int cache_file_idx1, pcap_t *
875884 }
876885 }
877886
878- if (sp == ctx -> intf1 && ctx -> first_time_intf1 ) {
879- wake_send_queues (sp , options );
880- ctx -> first_time_intf1 = 0 ;
881- } else if (sp == ctx -> intf2 && ctx -> first_time_intf2 ) {
887+ #if defined HAVE_QUICK_TX || defined HAVE_NETMAP
888+ if (sp -> first_packet ) {
882889 wake_send_queues (sp , options );
883- ctx -> first_time_intf2 = 0 ;
890+ sp -> first_packet = false ;
884891 }
892+ #endif
885893
886894 /* get the next packet for this file handle depending on which we last used */
887895 if (sp == ctx -> intf2 ) {
@@ -1060,44 +1068,32 @@ static void calc_sleep_time(tcpreplay_t *ctx, struct timeval *pkt_time,
10601068{
10611069 tcpreplay_opt_t * options = ctx -> options ;
10621070 struct timeval nap_for ;
1063- uint64_t ppnsec ; /* packets per nsec */
10641071 COUNTER now_us ;
10651072
10661073 timesclear (& ctx -> nap );
10671074
1068- /* accelerator time? */
1069- if (ctx -> skip_packets > 0 ) {
1070- (ctx -> skip_packets )-- ;
1071- return ;
1072- }
1073-
10741075 /*
1075- * pps_multi accelerator. This uses the existing send accelerator above
1076+ * pps_multi accelerator. This uses the existing send accelerator
10761077 * and hence requires the funky math to get the expected timings.
10771078 */
10781079 if (options -> speed .mode == speed_packetrate && options -> speed .pps_multi ) {
10791080 ctx -> skip_packets = options -> speed .pps_multi - 1 ;
1080- if (ctx -> first_time_intf1 ) {
1081+ if (ctx -> first_time ) {
1082+ ctx -> first_time = false;
10811083 return ;
10821084 }
10831085 }
10841086
10851087 dbgx (4 , "This packet time: " TIMEVAL_FORMAT , pkt_time -> tv_sec , pkt_time -> tv_usec );
10861088 dbgx (4 , "Last packet time: " TIMEVAL_FORMAT , last -> tv_sec , last -> tv_usec );
10871089
1088- /* If top speed, you shouldn't even be here */
1089- // assert(options->speed.mode != speed_topspeed);
1090-
10911090 switch (options -> speed .mode ) {
10921091 case speed_multiplier :
10931092 /*
10941093 * Replay packets a factor of the time they were originally sent.
10951094 */
10961095 if (timerisset (last )) {
1097- if (timercmp (pkt_time , last , < )) {
1098- /* Packet has gone back in time! Don't sleep and warn user */
1099- warnx ("Packet #" COUNTER_SPEC " has gone back in time!" , counter );
1100- } else {
1096+ if (timercmp (pkt_time , last , >=)) {
11011097 /* pkt_time has increased or is the same, so handle normally */
11021098 timersub (pkt_time , last , & nap_for );
11031099 dbgx (3 , "original packet delta pkt_time: " TIMEVAL_FORMAT , nap_for .tv_sec , nap_for .tv_usec );
@@ -1125,27 +1121,41 @@ static void calc_sleep_time(tcpreplay_t *ctx, struct timeval *pkt_time,
11251121 /* bits * 1000000 divided by bps = microseconds */
11261122 COUNTER next_tx_us = (bits_sent * 1000000 ) / bps ;
11271123 COUNTER tx_us = now_us - * start_us ;
1128- if (next_tx_us > tx_us )
1129- NANOSEC_TO_TIMESPEC ((next_tx_us - tx_us ) * 1000LL , & ctx -> nap );
1130- else if (tx_us > next_tx_us ) {
1124+ if (next_tx_us > tx_us ) {
1125+ NANOSEC_TO_TIMESPEC ((next_tx_us - tx_us ) * 1000 , & ctx -> nap );
1126+ } else if (tx_us > next_tx_us ) {
11311127 tx_us = now_us - * start_us ;
11321128 * skip_length = ((tx_us - next_tx_us ) * bps ) / 8000000 ;
11331129 }
11341130 update_current_timestamp_trace_entry (ctx -> stats .bytes_sent + (COUNTER )len , now_us , tx_us , next_tx_us );
11351131 }
11361132
1137- dbgx (3 , "packet size " COUNTER_SPEC "\t\tequals\ tnap " TIMESPEC_FORMAT , len ,
1133+ dbgx (3 , "packet size= " COUNTER_SPEC "\t\tnap= " TIMESPEC_FORMAT , len ,
11381134 ctx -> nap .tv_sec , ctx -> nap .tv_nsec );
11391135 break ;
11401136
11411137 case speed_packetrate :
1142- /* only need to calculate this the first time */
1143- if (! timesisset (& ctx -> nap )) {
1144- /* run in packets/sec */
1145- ppnsec = 1000000000 / options -> speed .speed * (options -> speed .pps_multi > 0 ? options -> speed .pps_multi : 1 );
1146- NANOSEC_TO_TIMESPEC (ppnsec , & ctx -> nap );
1147- dbgx (1 , "sending %d packet(s) per %lu nsec" , (options -> speed .pps_multi > 0 ? options -> speed .pps_multi : 1 ), ctx -> nap .tv_nsec );
1148- }
1138+ /*
1139+ * Ignore the time supplied by the capture file and send data at
1140+ * a constant rate (packets per second).
1141+ */
1142+ now_us = TIMSTAMP_TO_MICROSEC (sent_timestamp );
1143+ if (now_us ) {
1144+ COUNTER pps = ctx -> options -> speed .speed * (ctx -> options -> speed .pps_multi > 0 ? ctx -> options -> speed .pps_multi : 1 );;
1145+ COUNTER pkts_sent = ctx -> stats .pkts_sent ;
1146+ /* packets * 1000000 divided by pps = microseconds */
1147+ COUNTER next_tx_us = (pkts_sent * 1000000 ) / pps ;
1148+ COUNTER tx_us = now_us - * start_us ;
1149+ if (next_tx_us > tx_us )
1150+ NANOSEC_TO_TIMESPEC ((next_tx_us - tx_us ) * 1000 , & ctx -> nap );
1151+ else
1152+ ctx -> skip_packets = options -> speed .pps_multi ;
1153+
1154+ update_current_timestamp_trace_entry (ctx -> stats .bytes_sent + (COUNTER )len , now_us , tx_us , next_tx_us );
1155+ }
1156+
1157+ dbgx (3 , "packet count=" COUNTER_SPEC "\t\tnap=" TIMESPEC_FORMAT , ctx -> stats .pkts_sent ,
1158+ ctx -> nap .tv_sec , ctx -> nap .tv_nsec );
11491159 break ;
11501160
11511161 case speed_oneatatime :
0 commit comments