On Wed, Dec 23, 2015 at 10:31:23PM +0200, Vadim Kochan wrote:
> Added -b,--rate option in units of:
>
> pps/B/kB/MB/kBit/Mbit/Gbit/KiB/MiB/GiB
>
> to specify rate at which packets will be sent.
> Similary to -t,--gap option the packets will be sent
> in slow mode with 1 CPU.
>
> Tested with ifpps.
>
> Signed-off-by: Vadim Kochan
> ---
> v2:
> 1) Fixed KB -> kB
> 2) Added SHAPER_NONE type
>
> trafgen.8 | 4 ++
> trafgen.c | 140
> ++
> 2 files changed, 135 insertions(+), 9 deletions(-)
>
> diff --git a/trafgen.8 b/trafgen.8
> index 6f5d318..677fc7d 100644
> --- a/trafgen.8
> +++ b/trafgen.8
> @@ -136,6 +136,10 @@ probing for a given interval, iii) ping-like debugging
> with specific payload
> patterns. Furthermore, the TX_RING interface does not cope with interpacket
> gaps.
> .PP
> +.SS -b , --rate
> +Specify the rate of packet sending in
> pps/B/kB/MB/GB/kBit/Mbit/Gbit/KiB/MiB/GiB units.
> +Similary to -t,--gap option - packets are sent in slow mode.
> +.PP
> .SS -S , --ring-size
> Manually define the TX_RING resp. TX_RING size in ''KiB/MiB/GiB''. On
> default the size is being determined based on the network connectivity rate.
> diff --git a/trafgen.c b/trafgen.c
> index df2ecf4..f208336 100644
> --- a/trafgen.c
> +++ b/trafgen.c
> @@ -55,6 +55,27 @@
> #include "ring_tx.h"
> #include "csum.h"
>
> +#ifndef timeval_to_timespec
> +#define timeval_to_timespec(tv, ts) { \
> + (ts)->tv_sec = (tv)->tv_sec; \
> + (ts)->tv_nsec = (tv)->tv_usec * 1000; \
> +}
> +#endif
> +
> +enum shaper_type {
> + SHAPER_NONE,
> + SHAPER_PKTS,
> + SHAPER_BYTES,
> +};
> +
> +struct shaper {
> + enum shaper_type type;
> + unsigned long long sent;
> + unsigned long long rate;
> + struct timeval start;
> + struct timeval end;
> +};
> +
> struct ctx {
> bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce,
> qdisc_path;
> size_t reserve_size;
> @@ -65,6 +86,7 @@ struct ctx {
> struct timespec gap;
> struct sockaddr_in dest;
> char *packet_str;
> + struct shaper sh;
> };
>
> struct cpu_stats {
> @@ -83,7 +105,7 @@ size_t plen = 0;
> struct packet_dyn *packet_dyn = NULL;
> size_t dlen = 0;
>
> -static const char *short_options =
> "d:c:n:t:vJhS:rk:i:o:VRs:P:eE:pu:g:CHQqD:";
> +static const char *short_options =
> "d:c:n:t:vJhS:rk:i:o:VRs:P:eE:pu:g:CHQqD:b:";
> static const struct option long_options[] = {
> {"dev", required_argument, NULL, 'd'},
> {"out", required_argument, NULL, 'o'},
> @@ -91,6 +113,7 @@ static const struct option long_options[] = {
> {"conf",required_argument, NULL, 'c'},
> {"num", required_argument, NULL, 'n'},
> {"gap", required_argument, NULL, 't'},
> + {"rate",required_argument, NULL, 'b'},
> {"cpus",required_argument, NULL, 'P'},
> {"ring-size", required_argument, NULL, 'S'},
> {"kernel-pull", required_argument, NULL, 'k'},
> @@ -172,6 +195,7 @@ static void __noreturn help(void)
>" -r|--rand Randomize packet selection (def:
> round robin)\n"
>" -P|--cpusSpecify number of forks(<= CPUs)
> (def: #CPUs)\n"
>" -t|--gap Set approx. interpacket gap
> (s/ms/us/ns, def: us)\n"
> + " -b|--rateSend traffic at specified rate
> (pps/B/kB/MB/GB/kBit/Mbit/Gbit/KiB/MiB/GiB)\n"
>" -S|--ring-size Manually set mmap size
> (KiB/MiB/GiB)\n"
>" -E|--seedManually set srand(3) seed\n"
>" -u|--user Drop privileges and change to
> userid\n"
> @@ -535,6 +559,52 @@ static int xmit_smoke_probe(int icmp_sock, struct ctx
> *ctx)
> return -1;
> }
>
> +static bool shaper_is_set(struct shaper *sh)
> +{
> + return sh->type != SHAPER_NONE;
> +}
> +
> +static void shaper_start(struct shaper *sh)
> +{
> + bug_on(gettimeofday(>start, NULL));
> + sh->sent = 0;
> +}
> +
> +static void shaper_init(struct shaper *sh, unsigned long long rate, enum
> shaper_type type)
> +{
> + memset(sh, 0, sizeof(struct shaper));
> + sh->rate = rate;
> + sh->type = type;
> +}
> +
> +static void shaper_delay(struct shaper *sh, unsigned long pkt_len)
> +{
> + if ((sh->start.tv_sec | sh->start.tv_usec) <= 0)
> + return;
> +
> + sh->sent += sh->type == SHAPER_BYTES ? pkt_len : 1;
> +
> + if (sh->sent >= sh->rate) {
> + struct timeval delay_us;
> + struct timespec delay_ns;
> + struct timeval time_sent;
> + struct timeval time_1s = { .tv_sec = 1 };
> +
> + bug_on(gettimeofday(>end, NULL));
> +