On Fri, Dec 25, 2015 at 03:19:59AM +0200, Vadim Kochan wrote: > On Wed, Dec 23, 2015 at 10:58:32PM +0200, Vadim Kochan wrote: > > 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 <[email protected]> > > > --- > > > 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>, --rate <rate> > > > +Specify the rate of packet sending in > > > <num>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 <size>, --ring-size <size> > > > Manually define the TX_RING resp. TX_RING size in ''<num>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|--cpus <uint> Specify number of forks(<= CPUs) > > > (def: #CPUs)\n" > > > " -t|--gap <time> Set approx. interpacket gap > > > (s/ms/us/ns, def: us)\n" > > > + " -b|--rate <rate> Send traffic at specified rate > > > (pps/B/kB/MB/GB/kBit/Mbit/Gbit/KiB/MiB/GiB)\n" > > > " -S|--ring-size <size> Manually set mmap size > > > (KiB/MiB/GiB)\n" > > > " -E|--seed <uint> Manually set srand(3) seed\n" > > > " -u|--user <userid> 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(&sh->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(&sh->end, NULL)); > > > + timersub(&sh->end, &sh->start, &time_sent); > > > + > > > + if (timercmp(&time_1s, &time_sent, > )) { > > > + timersub(&time_1s, &time_sent, &delay_us); > > > + timeval_to_timespec(&delay_us, &delay_ns); > > > + > > > + if ((delay_ns.tv_sec | delay_ns.tv_nsec) > 0) > > > + nanosleep(&delay_ns, NULL); > > > + } > > > + > > > + shaper_start(sh); > > > + } > > > +} > > > + > > > static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, > > > unsigned long orig_num) > > > { > > > int ret, icmp_sock = -1; > > > @@ -560,6 +630,9 @@ static void xmit_slowpath_or_die(struct ctx *ctx, > > > unsigned int cpu, unsigned lon > > > > > > bug_on(gettimeofday(&start, NULL)); > > > > > > + if (shaper_is_set(&ctx->sh)) > > > + shaper_start(&ctx->sh); > > > + > > > while (likely(sigint == 0 && num > 0 && plen > 0)) { > > > pktd = &packet_dyn[i]; > > > if (packet_dyn_has_elems(pktd)) { > > > @@ -605,6 +678,9 @@ retry: > > > if (ctx->num > 0) > > > num--; > > > > > > + if (shaper_is_set(&ctx->sh)) > > > + shaper_delay(&ctx->sh, packets[i].len); > > > + > > > if ((ctx->gap.tv_sec | ctx->gap.tv_nsec) > 0) > > > nanosleep(&ctx->gap, NULL); > > > } > > > @@ -901,6 +977,8 @@ int main(int argc, char **argv) > > > int min_opts = 5; > > > char **cpp_argv = NULL; > > > size_t cpp_argc = 0; > > > + unsigned long long rate; > > > + enum shaper_type shape_type; > > > > > > fmemset(&ctx, 0, sizeof(ctx)); > > > ctx.cpus = get_number_cpus_online(); > > > @@ -999,9 +1077,7 @@ int main(int argc, char **argv) > > > ctx.num = orig_num; > > > break; > > > case 't': > > > - slow = true; > > > ptr = optarg; > > > - prctl(PR_SET_TIMERSLACK, 1UL); > > > gap = strtoul(optarg, NULL, 0); > > > > > > for (j = i = strlen(optarg); i > 0; --i) { > > > @@ -1025,14 +1101,51 @@ int main(int argc, char **argv) > > > } else if (!strncmp(ptr, "s", strlen("s"))) { > > > ctx.gap.tv_sec = gap; > > > ctx.gap.tv_nsec = 0; > > > - } else > > > + } else { > > > panic("Syntax error in time param!\n"); > > > + } > > > + break; > > > + case 'b': > > > + rate = strtoul(optarg, &ptr, 0); > > > + if (!rate || optarg == ptr) > > > + panic("Invalid rate param\n"); > > > + > > > + if (strncmp(ptr, "pps", strlen("pps")) == 0) { > > > + shape_type = SHAPER_PKTS; > > > + } else if (strncmp(ptr, "B", strlen("B")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + } else if (strncmp(ptr, "kB", strlen("kB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000; > > > + } else if (strncmp(ptr, "MB", strlen("MB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000 * 1000; > > > + } else if (strncmp(ptr, "GB", strlen("GB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000 * 1000 * 1000; > > > + } else if (strncmp(ptr, "kbit", strlen("kbit")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000 / 8; > > > + } else if (strncmp(ptr, "Mbit", strlen("Mbit")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000 * 1000 / 8; > > > + } else if (strncmp(ptr, "Gbit", strlen("Gbit")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1000 * 1000 * 1000 / 8; > > > + } else if (strncmp(ptr, "KiB", strlen("KiB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1 << 10; > > > + } else if (strncmp(ptr, "MiB", strlen("MiB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1 << 20; > > > + } else if (strncmp(ptr, "GiB", strlen("GiB")) == 0) { > > > + shape_type = SHAPER_BYTES; > > > + rate *= 1 << 30; > > > + } else { > > > + panic("Invalid unit type for rate\n"); > > > + } > > > > > > - if (gap > 0) > > > - /* Fall back to single core to not mess up > > > - * correct timing. We are slow anyway! > > > - */ > > > - ctx.cpus = 1; > > > + shaper_init(&ctx.sh, rate, shape_type); > > > break; > > > case 'S': > > > ptr = optarg; > > > @@ -1118,6 +1231,15 @@ int main(int argc, char **argv) > > > sleep(0); > > > } > > > > > > + if (shaper_is_set(&ctx.sh) || (ctx.gap.tv_sec | ctx.gap.tv_nsec) > 0) { > > > + prctl(PR_SET_TIMERSLACK, 1UL); > > > + /* Fall back to single core to not mess up correct timing. > > > + * We are slow anyway! > > > + */ > > > + ctx.cpus = 1; > > > + slow = true; > > > + } > > > + > > > /* > > > * If number of packets is smaller than number of CPUs use only as > > > * many CPUs as there are packets. Otherwise we end up sending more > > > -- > > > 2.6.3 > > > > > > > Sorry, seems it does not work for mtu > 1500, I will try to fix it. > > Currently I did not come up with idea how to make shaping work correctly > if packet len is much bigger than rate because then trafgen will be > delayed for example for 3-5 seconds which is not what expected I think, > and in any case trafgen have to send a whole packet at a one time, so I > think the user should set a correct packet length. What do you think ? > If you are at the same point so I think the changes at least might be > reviewed ? > > Thanks,
Sorry, may be I confused you, but I think this patch seems OK, you can ignore my message that it does not work for mtu > 1500 as I was performing wrong tests where rate was much less than packet len. So you can review it. -- You received this message because you are subscribed to the Google Groups "netsniff-ng" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
