diff -uNr iproute2-2.6.29-1/tc/q_netem.c iproute2-2.6.29-1-netem/tc/q_netem.c --- iproute2-2.6.29-1/tc/q_netem.c 2009-03-24 23:40:54.000000000 +0100 +++ iproute2-2.6.29-1-netem/tc/q_netem.c 2009-12-11 16:41:14.766468716 +0100 @@ -7,7 +7,6 @@ * 2 of the License, or (at your option) any later version. * * Authors: Stephen Hemminger - * */ #include @@ -29,9 +28,19 @@ { fprintf(stderr, "Usage: ... netem [ limit PACKETS ] \n" \ +" [ logging LEVEL ] \n" \ +" [ query ] \n" \ " [ delay TIME [ JITTER [CORRELATION]]]\n" \ " [ distribution {uniform|normal|pareto|paretonormal} ]\n" \ " [ drop PERCENT [CORRELATION]] \n" \ +" [ loss_GI ploss [burst_length [density [pisol [good_burst_length]]]]] \n" \ +" [ loss_GI_tran p13 p31 [p32 p23 [p14]]] \n" \ +" [ loss_bern p ] \n" \ +" [ loss_gilb_4s p r [1-h]] \n" \ +" [ loss_gilbell_4s p r [1-h [1-k]]] \n" \ +" [ loss_gilb p r [1-h]] \n" \ +" [ loss_gilbell p r [1-h [1-k]]] \n" \ +" [ loss_pattern [filename [repetitions]]] \n" \ " [ corrupt PERCENT [CORRELATION]] \n" \ " [ duplicate PERCENT [CORRELATION]]\n" \ " [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n"); @@ -138,6 +147,10 @@ memset(&opt, 0, sizeof(opt)); opt.limit = 1000; + opt.query = 0; + opt.logging = 0; + opt.pattern_length = 0; + opt.pattern_repetitions = 0; memset(&cor, 0, sizeof(cor)); memset(&reorder, 0, sizeof(reorder)); memset(&corrupt, 0, sizeof(corrupt)); @@ -150,6 +163,14 @@ explain1("limit"); return -1; } + } else if (matches(*argv, "logging") == 0) { + NEXT_ARG(); + if (get_size(&opt.logging, *argv)) { + explain1("logging"); + return -1; + } + } else if (matches(*argv, "query") == 0) { + opt.query=1; } else if (matches(*argv, "latency") == 0 || matches(*argv, "delay") == 0) { NEXT_ARG(); @@ -189,6 +210,506 @@ return -1; } } + } else if (matches(*argv, "loss_GI") == 0) { + NEXT_ARG(); + + double p13=0; + double p31=1; + double p32=0; + double p23=1; + double p14=0; + double ploss=0; + double burst_length=1; + double rho=1; + double pisol=0; + double good_burst_length=0; + + opt.algorithm=0; //algorithm 0 is GI, 1 is gilbell + + ploss=strtod(*argv,(char **)NULL)/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + burst_length=strtod(*argv,(char **)NULL); + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + rho=strtod(*argv,(char **)NULL)/100; + + if (ploss>rho) { + printf("\nError: ploss>density \n"); + break; + } + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + pisol=strtod(*argv,(char **)NULL)/100; + + if (pisol>ploss) { + printf("\nError: pisol>ploss \n"); + break; + } + + if (ploss>(rho-pisol*(rho-1))) { + printf("\nError: ploss>density-pisol(density-1) \n"); + break; + } + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + good_burst_length=strtod(*argv,(char **)NULL); + if (good_burst_length>burst_length) {printf("\nError: good burst length>burst length \n "); + break; + } + } + } + } + } + + if(burst_length==0) { + p13=ploss; + p31=1-ploss; + } + + else if((burst_length!=0) & (rho==1) & (pisol==0)) { + p13=ploss/(burst_length*(1-ploss)); + p31=1/burst_length; + } + + else if ((burst_length!=0) & (rho!=1) & (pisol==0)) { + p13=(-ploss)/(burst_length*ploss-burst_length*rho); + p31=1/(burst_length*rho); + } + + else if ((burst_length!=0) & (rho!=1) & (pisol!=0)) { + p13=(pisol-ploss)/(burst_length*(pisol-1)*(rho-ploss)); + p31=1/(burst_length*rho); + p14=pisol/(1-pisol); + } + + if((burst_length!=0) & (rho!=1)) { + + if(good_burst_length==0) { + p23=(burst_length*rho-1) / (burst_length-1); + p32=(1+rho*rho*burst_length-rho-burst_length*rho) / (rho-rho*burst_length); + } + else { + p23=1/good_burst_length; + p32=(1-rho) / (rho*good_burst_length); + } + + } + + if (burst_length==0) burst_length=1/p31; + + printf("\nTransition probabilities are:\n "); + printf("--------------------------------"); + printf("\np13 is %.3f%% ", 100*p13); + printf("\np31 is %.3f%% ", 100*p31); + printf("\np32 is %.3f%% ", 100*p32); + printf("\np23 is %.3f%% ", 100*p23); + printf("\np14 is %.3f%%\n ", 100*p14); + + printf("\nGI (General and Intuitive) parameters will be: \n"); + printf("--------------------------------"); + printf("\nploss is %.3f%% ", 100*ploss); + printf("\nburst length is %.3f", burst_length); + printf("\nburst density is %.3f%% ", 100*rho); + printf("\nisolated ploss is %.3f%% ", 100*pisol); + printf("\ngood burst length is %.3f\n ", good_burst_length); + + if(opt.query==0) { + opt.p13=4294967295u*p13; + opt.p31=4294967295u*p31; + opt.p32=4294967295u*p32; + opt.p23=4294967295u*p23; + opt.p14=4294967295u*p14; + } + + if(opt.query==1) return -1; + + } else if (matches(*argv, "loss_GI_tran") == 0) { + + double p13=0; + double p31=1; + double p32=0; + double p23=1; + double p14=0; + double ploss; + double burst_length; + double rho; + double pisol; + double good_burst_length; + + opt.algorithm=0; //algorithm 0 is 4-state, 1 is gilbell + + NEXT_ARG(); + p13=strtod(*argv,(char **)NULL)/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + p31=strtod(*argv,(char **)NULL)/100; + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + p32=strtod(*argv,(char **)NULL)/100; + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + p23=strtod(*argv,(char **)NULL)/100; + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + p14=strtod(*argv,(char **)NULL)/100; + } + } + } + } + + else p31=1-p13; + + printf("\nTransition probabilities are:\n "); + printf("--------------------------------"); + printf("\np13 is %.3f%% ", 100*p13); + printf("\np31 is %.3f%% ", 100*p31); + printf("\np32 is %.3f%% ", 100*p32); + printf("\np23 is %.3f%% ", 100*p23); + printf("\np14 is %.3f%%\n ", 100*p14); + + ploss=(p13*p23+p14*p23*p31) / (p13*p23+p23*p31+p14*p23*p31+p13*p32); + burst_length=(p32+p23) / (p23*p31); + rho=(p13*p23) / (p13*p23+p13*p32); + pisol=(p14*p23*p31) / (p14*p23*p31+p23*p31); + good_burst_length=1/p23; + + printf("\nGI (General and Intuitive) parameters will be: \n"); + printf("--------------------------------"); + printf("\nploss is %.3f%%", 100*ploss); + printf("\nburst length is %.3f", burst_length); + printf("\nburst density is %.3f%% ", 100*rho); + printf("\nisolated ploss is %.3f%% ", 100*pisol); + printf("\ngood burst length is %.3f\n ", good_burst_length); + + if(opt.query==0) { + opt.p13=4294967295u*p13; + opt.p31=4294967295u*p31; + opt.p32=4294967295u*p32; + opt.p23=4294967295u*p23; + opt.p14=4294967295u*p14; + } + + if(opt.query==1) return -1; + + } else if (matches(*argv, "loss_gilb") == 0) { + + double p=0; + double r=0; + double h=0; + + opt.algorithm=1; //algorithm 1 is gilbell + + NEXT_ARG(); + p=strtod(*argv,(char **)NULL)/100; + + NEXT_ARG(); + r=strtod(*argv,(char **)NULL)/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + h=(100-strtod(*argv,(char **)NULL))/100; + } + + printf("\nGilbert parameters will be: \n"); + printf("--------------------------------"); + printf("\np is %.3f%% ", 100*p); + printf("\nr is %.3f%%", 100*r); + printf("\n1-h is %.3f%%\n", 100*(1-h)); + + opt.gilb_p=4294967295u*p; + opt.gilb_r=4294967295u*r; + opt.gilb_h=4294967295u*h; + + } else if (matches(*argv, "loss_gilbell") == 0) { + + double p=0; + double r=0; + double h=0; + double k=1; + + opt.algorithm=1; //algorithm 1 is gilbell + + NEXT_ARG(); + p=strtod(*argv,(char **)NULL)/100; + + NEXT_ARG(); + r=strtod(*argv,(char **)NULL)/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + h=(100-strtod(*argv,(char **)NULL))/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + k=(100-strtod(*argv,(char **)NULL))/100; + } + } + + printf("\nGilbert-Elliot parameters will be: \n"); + printf("--------------------------------"); + printf("\np is %.3f%% ", 100*p); + printf("\nr is %.3f%%", 100*r); + printf("\n1-h is %.3f%% ", 100*(1-h)); + printf("\n1-k is %.3f%%\n", 100*(1-k)); + + opt.gilb_p=4294967295u*p; + opt.gilb_r=4294967295u*r; + opt.gilb_h=4294967295u*h; + opt.gilb_k=4294967295u*k; + + } else if (matches(*argv, "loss_bern") == 0) { + + double p=0; + double r=0; + double ploss=0; + double burst_length=1; + double p13=0; + double p31=0; + + opt.algorithm=0; //algorithm 0 is 4-state, 1 is gilbell + + NEXT_ARG(); + p=strtod(*argv,(char **)NULL)/100; + r=1-p; + + ploss=p/(p+r); + burst_length=1/r; + + p13=p; + p31=r; + + printf("\nTransition probabilities are:\n "); + printf("--------------------------------"); + printf("\np13 is %.3f%% ", 100*p13); + printf("\np31 is %.3f%% ", 100*p31); + printf("\np32 is 0.000%% "); + printf("\np23 is 100.000%% "); + printf("\np14 is 0.000%%\n "); + + printf("\nGI (General and Intuitive) parameters will be: \n"); + printf("--------------------------------"); + printf("\nploss is %.3f%% ", 100*ploss); + printf("\nburst length is %.3f", burst_length); + printf("\nburst density is 100.000%% "); + printf("\nisolated ploss is 0.000%% "); + printf("\ngood burst length is 1.000%%\n "); + + if(opt.query==0) { + opt.p13=4294967295u*p13; + opt.p31=4294967295u*p31; + opt.p32=0; + opt.p23=4294967295u; + opt.p14=0; + } + + if(opt.query==1) return -1; + + } else if (matches(*argv, "loss_gilb_4s") == 0) { + double p=0; + double r=0; + double h=0; + double ploss=0; + double burst_length=1; + double rho=1; + double p13=0; + double p31=1; + double p23=1; + double p32=0; + + opt.algorithm=0; //algorithm 0 is 4-state, 1 is gilbell + + NEXT_ARG(); + p=strtod(*argv,(char **)NULL)/100; + + NEXT_ARG(); + r=strtod(*argv,(char **)NULL)/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + h=(100-strtod(*argv,(char **)NULL))/100; + + } + + ploss=(r-+p-h*p)/(p+r); + burst_length=(1/(r-r*h))*((h*h*(1-h+2*r*h*h-6*r*h+2*r))+(2*h*(1-h)*(1-h+r*h*h-3*h*r+r))+((1-h)*(1-h)*(1-h))); + + if(h!=0) rho=(1-h)/(r*burst_length); + else rho=1; + + p13=(-ploss)/(burst_length*(-rho+ploss)); + p31=1/(burst_length*rho); + + if (rho<1) { + p32=(1+rho*rho*burst_length-rho-burst_length*rho) / (rho-rho*burst_length); + p23=(burst_length*rho-1) / (burst_length-1); + } + + else { + p32=0; + p23=1; + } + + printf("\nTransition probabilities are:\n "); + printf("--------------------------------"); + printf("\np13 is %.3f%% ", 100*p13); + printf("\np31 is %.3f%% ", 100*p31); + printf("\np32 is %.3f%% ", 100*p32); + printf("\np23 is %.3f%% ", 100*p23); + printf("\np14 is 0.000%%\n"); + + printf("\nGI (General and Intuitive) parameters will be: \n"); + printf("--------------------------------"); + printf("\nploss is %.3f%% ", 100*ploss); + printf("\nburst length is %.3f", burst_length); + printf("\nburst density is %.3f%% ", 100*rho); + printf("\nisolated ploss is 0.000%% "); + printf("\ngood burst length is %.3f\n ", 1/p23); + + if(opt.query==0) { + opt.p13=4294967295u*p13; + opt.p31=4294967295u*p31; + if(rho!=1) { + opt.p32=4294967295u*p32; + opt.p23=4294967295u*p23; + } + else { + opt.p32=0; + opt.p23=4294967295u; + } + } + + if(opt.query==1) return -1; + + } else if (matches(*argv, "loss_gilbell_4s") == 0) { + + double p=0; + double r=0; + double h=0; + double k=1; + double ploss=0; + double burst_length=1; + double rho=1; + double pisol=0; + double p13=0; + double p31=1; + double p23=1; + double p32=0; + double p14=0; + + opt.algorithm=0; //algoritnm 1 is gilbell + + NEXT_ARG(); + p=strtod(*argv,(char **)NULL)/100; + + NEXT_ARG(); + r=strtod(*argv,(char **)NULL)/100; + + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + h=(100-strtod(*argv,(char **)NULL))/100; + + if (NEXT_IS_NUMBER()) { + NEXT_ARG(); + k=(100-strtod(*argv,(char **)NULL))/100; + + } + } + + ploss=(r-k*r+p-h*p)/(p+r); + burst_length=(1/(r-r*h))*((h*h*(1-h+2*r*h*h-6*r*h+2*r))+(2*h*(1-h)*(1-h+r*h*h-3*h*r+r))+((1-h)*(1-h)*(1-h))); + + if(h!=0) rho=(1-h)/(r*burst_length); + else rho=1; + + if(k!=1) pisol=1-k; + else pisol=0; + + p13=(pisol-ploss)/(burst_length*(pisol*(rho-1)-rho+ploss)); + p31=1/(burst_length*rho); + + if (rho<1) { + p32=(1+rho*rho*burst_length-rho-burst_length*rho) / (rho-rho*burst_length); + p23=(burst_length*rho-1) / (burst_length-1); + } + + else { + p32=0; + p23=1; + } + + if (pisol!=0) p14=(pisol) / (1-pisol); + else p14=0; + + printf("\nTransition probabilities are:\n "); + printf("--------------------------------"); + printf("\np13 is %.3f%% ", 100*p13); + printf("\np31 is %.3f%% ", 100*p31); + printf("\np32 is %.3f%% ", 100*p32); + printf("\np23 is %.3f%% ", 100*p23); + printf("\np14 is %.3f%%\n ", 100*p14); + + printf("\nGI (General and Intuitive) parameters will be: \n"); + printf("--------------------------------"); + printf("\nploss is %.3f%% ", 100*ploss); + printf("\nburst length is %.3f", burst_length); + printf("\nburst density is %.3f%% ", 100*rho); + printf("\nisolated ploss is %.3f%% ", 100*pisol); + printf("\ngood burst length is %.3f\n ", 1/p23); + + if(opt.query==0) { + opt.p13=4294967295u*p13; + opt.p31=4294967295u*p31; + if(rho!=1) { + opt.p32=4294967295u*p32; + opt.p23=4294967295u*p23; + } + else { + opt.p32=0; + opt.p23=4294967295u; + } + if(pisol>0) opt.p14=4294967295u*p14; + else opt.p14=0; + } + + if(opt.query==1) return -1; + + } else if (matches(*argv, "loss_pattern") == 0) { //LOSS PATTERN + NEXT_ARG(); + + int i; + + FILE *sequence; + + sequence=fopen(*argv, "r"); + + if (sequence == NULL) { + printf("Could not open the file %s \n", *argv); + exit(1); } + + fseek(sequence, 0, SEEK_END); + fgetpos(sequence, &opt.pattern_length); + rewind(sequence); + + opt.user_pattern=malloc(opt.pattern_length*sizeof(int)); + opt.pattern_repetitions=0; + + for(i=1; idelay_corr) + fprintf(f, " %s", sprint_percent(cor->delay_corr, b1)); + } + } + + if (qopt.loss) { + fprintf(f, " loss %s", sprint_percent(qopt.loss, b1)); + if (cor && cor->loss_corr) + fprintf(f, " %s", sprint_percent(cor->loss_corr, b1)); + } + + if (qopt.p13) { + fprintf(f, " p13 %s", sprint_percent(qopt.p13, b1)); + fprintf(f, " p31 %s", sprint_percent(qopt.p31, b1)); + fprintf(f, " p32 %s", sprint_percent(qopt.p32, b1)); + fprintf(f, " p23 %s", sprint_percent(qopt.p23, b1)); + fprintf(f, " p14 %s", sprint_percent(qopt.p14, b1)); + } + + if (qopt.gilb_p) { + fprintf(f, " p %s", sprint_percent(qopt.gilb_p, b1)); + fprintf(f, " r %s", sprint_percent(qopt.gilb_r, b1)); + fprintf(f, " h %s", sprint_percent(qopt.gilb_h, b1)); + if (qopt.gilb_k) fprintf(f, " k %s", sprint_percent(qopt.gilb_k, b1)); + } + + fprintf(f, "limit %d", qopt.limit); if (qopt.latency) { fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));