static void calc_sleep_time(tcpreplay_t *ctx, struct timeval *pkt_ts_delta,
        struct timeval *time_delta, COUNTER len,
        sendpacket_t *sp, COUNTER counter, timestamp_t *sent_timestamp,
        COUNTER start_us, COUNTER *skip_length)
{
    tcpreplay_opt_t *options = ctx->options;
    struct timeval nap_for;
    COUNTER now_us;

    timesclear(&ctx->nap);

    /*
     * pps_multi accelerator.    This uses the existing send accelerator
     * and hence requires the funky math to get the expected timings.
     */
    if (options->speed.mode == speed_packetrate && options->speed.pps_multi) {
        ctx->skip_packets = options->speed.pps_multi - 1;
    }

    /* no last packet sent, just leave */
    if (ctx->first_time) {
        ctx->first_time = false;
        return;
    }

    switch(options->speed.mode) {
    case speed_multiplier:
        /*
         * Replay packets a factor of the time they were originally sent.
         * Make sure the packet is not late.
         */
        if (timercmp(pkt_ts_delta, time_delta, >)) {
            /* pkt_time_delta has increased, so handle normally */
            timersub(pkt_ts_delta, time_delta, &nap_for);
            TIMEVAL_TO_TIMESPEC(&nap_for, &ctx->nap);
            dbgx(3, "original packet delta time: " TIMESPEC_FORMAT,
                    ctx->nap.tv_sec, ctx->nap.tv_nsec);
            timesdiv_float(&ctx->nap, options->speed.multiplier);
            dbgx(3, "original packet delta/div: " TIMESPEC_FORMAT,
                    ctx->nap.tv_sec, ctx->nap.tv_nsec);
        }
        break;

    case speed_mbpsrate:
        /*
         * Ignore the time supplied by the capture file and send data at
         * a constant 'rate' (bytes per second).
         */
        now_us = TIMSTAMP_TO_MICROSEC(sent_timestamp);
        if (now_us) {
            COUNTER next_tx_us;
            COUNTER bps = options->speed.speed;
            COUNTER bits_sent = ((ctx->stats.bytes_sent + len) * 8);
            COUNTER tx_us = now_us - start_us;

            /*
             * bits * 1000000 divided by bps = microseconds
             *
             * ensure there is no overflow in cases where bits_sent is very high
             */
            if (bits_sent > COUNTER_OVERFLOW_RISK && bps > 500000)
                next_tx_us = (bits_sent * 1000) / bps * 1000;
            else
                next_tx_us = (bits_sent * 1000000) / bps;

            if (next_tx_us > tx_us) {
                NANOSEC_TO_TIMESPEC((next_tx_us - tx_us) * 1000, &ctx->nap);
            } else if (tx_us > next_tx_us) {
                tx_us = now_us - start_us;
                *skip_length = ((tx_us - next_tx_us) * bps) / 8000000;
            }

            update_current_timestamp_trace_entry(ctx->stats.bytes_sent +
                    (COUNTER)len, now_us, tx_us, next_tx_us);
        }

        dbgx(3, "packet size=" COUNTER_SPEC "\t\tnap=" TIMESPEC_FORMAT, len,
                ctx->nap.tv_sec, ctx->nap.tv_nsec);
        break;

    case speed_packetrate:
        /*
          * Ignore the time supplied by the capture file and send data at
          * a constant rate (packets per second).
          */
         now_us = TIMSTAMP_TO_MICROSEC(sent_timestamp);
         if (now_us) {
             COUNTER next_tx_us;
             COUNTER pph = ctx->options->speed.speed;
             COUNTER pkts_sent = ctx->stats.pkts_sent;
             COUNTER tx_us = now_us - start_us;
             /*
              * packets * 1000000 divided by pps = microseconds
              * packets per sec (pps) = packets per hour / (60 * 60)
              *
              * Adjust for long running tests with high PPS to prevent overflow.
              * When active, adjusted calculation may add a bit of jitter.
              */
             if ((pkts_sent < COUNTER_OVERFLOW_RISK))
                 next_tx_us = (pkts_sent * 1000000) * (60 * 60) / pph;
             else
                 next_tx_us = (pkts_sent * 1000000) / pph / (60 * 60);

             if (next_tx_us > tx_us)
                 NANOSEC_TO_TIMESPEC((next_tx_us - tx_us) * 1000, &ctx->nap);
             else
                 ctx->skip_packets = options->speed.pps_multi;

             update_current_timestamp_trace_entry(ctx->stats.bytes_sent +
                     (COUNTER)len, now_us, tx_us, next_tx_us);
         }

         dbgx(3, "packet count=" COUNTER_SPEC "\t\tnap=" TIMESPEC_FORMAT,
                 ctx->stats.pkts_sent, ctx->nap.tv_sec, ctx->nap.tv_nsec);
        break;

    case speed_oneatatime:
        /* do we skip prompting for a key press? */
        if (ctx->skip_packets == 0) {
            ctx->skip_packets = get_user_count(ctx, sp, counter);
        }

        /* decrement our send counter */
        printf("Sending packet " COUNTER_SPEC " out: %s\n", counter,
               sp == ctx->intf1 ? options->intf1_name : options->intf2_name);
        ctx->skip_packets--;

        /* leave */
        break;

    case speed_topspeed:
        break;

    default:
        errx(-1, "Unknown/supported speed mode: %d", options->speed.mode);
        break;
    }
}
static void calc_sleep_time(tcpreplay_t *ctx, struct timeval *pkt_ts_delta,
        struct timeval *time_delta, COUNTER len,
        sendpacket_t *sp, COUNTER counter, timestamp_t *sent_timestamp,
        COUNTER start_us, COUNTER *skip_length)
{
    tcpreplay_opt_t *options = ctx->options;
    struct timeval nap_for;
    COUNTER now_us;

    timesclear(&ctx->nap);

     
    if (options->speed.mode == speed_packetrate && options->speed.pps_multi) {
        ctx->skip_packets = options->speed.pps_multi - 1;
    }

     
    if (ctx->first_time) {
        ctx->first_time = false;
        return;
    }

    switch(options->speed.mode) {
    case speed_multiplier:
         
        if (timercmp(pkt_ts_delta, time_delta, >)) {
             
            timersub(pkt_ts_delta, time_delta, &nap_for);
            TIMEVAL_TO_TIMESPEC(&nap_for, &ctx->nap);
            dbgx(3, "original packet delta time: " TIMESPEC_FORMAT,
                    ctx->nap.tv_sec, ctx->nap.tv_nsec);
            timesdiv_float(&ctx->nap, options->speed.multiplier);
            dbgx(3, "original packet delta/div: " TIMESPEC_FORMAT,
                    ctx->nap.tv_sec, ctx->nap.tv_nsec);
        }
        break;

    case speed_mbpsrate:
         
        now_us = TIMSTAMP_TO_MICROSEC(sent_timestamp);
        if (now_us) {
            COUNTER next_tx_us;
            COUNTER bps = options->speed.speed;
            COUNTER bits_sent = ((ctx->stats.bytes_sent + len) * 8);
            COUNTER tx_us = now_us - start_us;

             
            if (bits_sent > COUNTER_OVERFLOW_RISK && bps > 500000)
                next_tx_us = (bits_sent * 1000) / bps * 1000;
            else
                next_tx_us = (bits_sent * 1000000) / bps;

            if (next_tx_us > tx_us) {
                NANOSEC_TO_TIMESPEC((next_tx_us - tx_us) * 1000, &ctx->nap);
            } else if (tx_us > next_tx_us) {
                tx_us = now_us - start_us;
                *skip_length = ((tx_us - next_tx_us) * bps) / 8000000;
            }

            update_current_timestamp_trace_entry(ctx->stats.bytes_sent +
                    (COUNTER)len, now_us, tx_us, next_tx_us);
        }

        dbgx(3, "packet size=" COUNTER_SPEC "\t\tnap=" TIMESPEC_FORMAT, len,
                ctx->nap.tv_sec, ctx->nap.tv_nsec);
        break;

    case speed_packetrate:
         
         now_us = TIMSTAMP_TO_MICROSEC(sent_timestamp);
         if (now_us) {
             COUNTER next_tx_us;
             COUNTER pph = ctx->options->speed.speed;
             COUNTER pkts_sent = ctx->stats.pkts_sent;
             COUNTER tx_us = now_us - start_us;
              
             if ((pkts_sent < COUNTER_OVERFLOW_RISK))
                 next_tx_us = (pkts_sent * 1000000) * (60 * 60) / pph;
             else
                 next_tx_us = (pkts_sent * 1000000) / pph / (60 * 60);

             if (next_tx_us > tx_us)
                 NANOSEC_TO_TIMESPEC((next_tx_us - tx_us) * 1000, &ctx->nap);
             else
                 ctx->skip_packets = options->speed.pps_multi;

             update_current_timestamp_trace_entry(ctx->stats.bytes_sent +
                     (COUNTER)len, now_us, tx_us, next_tx_us);
         }

         dbgx(3, "packet count=" COUNTER_SPEC "\t\tnap=" TIMESPEC_FORMAT,
                 ctx->stats.pkts_sent, ctx->nap.tv_sec, ctx->nap.tv_nsec);
        break;

    case speed_oneatatime:
         
        if (ctx->skip_packets == 0) {
            ctx->skip_packets = get_user_count(ctx, sp, counter);
        }

         
        printf("Sending packet " COUNTER_SPEC " out: %s\n", counter,
               sp == ctx->intf1 ? options->intf1_name : options->intf2_name);
        ctx->skip_packets--;

         
        break;

    case speed_topspeed:
        break;

    default:
        errx(-1, "Unknown/supported speed mode: %d", options->speed.mode);
        break;
    }
}