00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <strings.h>
00006 #include <assert.h>
00007 #include <iostream.h>
00008
00009
00010 #define _RED_ROUTER_MAIN_
00011 #include "asim.h"
00012
00013 #define sp " "
00014
00015
00016 #include<vector>
00017 using namespace std;
00018
00019 typedef struct c{
00020 int no;
00021 double delay;
00022 double drop;
00023 double p_tput;
00024 double t;
00025
00026 int is_sflow;
00027 double slambda;
00028 int snopkts;
00029 RedRouter * red;
00030 int scaled;
00031 }flow_stats;
00032
00033 typedef struct n{
00034 int red;
00035 double pmin, pmax, minth, maxth;
00036 double lambda;
00037 double plambda;
00038 double tlambda;
00039 double mu;
00040 double prop;
00041 double qdelay;
00042 int buffer;
00043 double drop;
00044 int nflows;
00045 vector<int> theflows;
00046 double scaled_lambda;
00047 double unscaled_lambda;
00048
00049 double utput;
00050 double uc;
00051
00052
00053 RedRouter * redrouter;
00054
00055 }link_stats;
00056
00057
00058 class asim {
00059
00060 public:
00061
00062
00063 int nConnections;
00064 int K, MaxHops;
00065 int nLinks;
00066 int **Adj;
00067 int *nAdj;
00068
00069 link_stats* links;
00070 flow_stats* flows;
00071
00072 double min(double x, double y){
00073 return (x<y)?x:y;
00074 }
00075
00076 double padhye(double rtt, double p){
00077
00078 double rto = 1;
00079 double t=1;
00080 t = rtt*sqrt(2*p/3)+rto*min(1,(3*sqrt(3*p/8)))*p*(1+32*p*p);
00081 return min(20/rtt,1/t);
00082
00083 }
00084
00085 double Po(double rho, int K){
00086
00087 if(rho==1)
00088 return 1.0/(K+1);
00089
00090 double t;
00091 t=(1.0*(1-rho))/(1.0-pow(rho,K));
00092 return t;
00093
00094 }
00095
00096 double Pk(double rho, int K, int k){
00097
00098 if(rho==1)
00099 return 1.0/(K+1);
00100
00101 if(rho==0)
00102 return 0;
00103
00104 double t;
00105
00106 t=((1-rho)*pow(rho,k))/(1-pow(rho,K+1));
00107 return t;
00108 }
00109
00110 double Lq(double rho, int K){
00111
00112 double t1,t2;
00113
00114 if(rho==1){
00115 return (1.0*K*(K-1))/(2.0*(K+1));
00116 }
00117
00118 t1=rho*1.0/(1-rho);
00119 t2=rho*1.0/(1-pow(rho,K+1));
00120 t2*=K*pow(rho,K)+1;
00121 return (t1-t2)/2;
00122
00123 }
00124
00125 double get_link_drop(int x){
00126 assert(x<nLinks);
00127 return links[x].drop;
00128 }
00129
00130 double get_link_delay(int x){
00131 assert(x<nLinks);
00132 return links[x].qdelay + links[x].prop ;
00133 }
00134
00135 double get_link_qdelay(int x){
00136 assert(x<nLinks);
00137 return links[x].qdelay;
00138 }
00139
00140 double get_link_pdelay(int x){
00141 assert(x<nLinks);
00142 return links[x].prop;
00143 }
00144
00145 double get_link_tput(int x){
00146 assert(x<nLinks);
00147 return links[x].lambda;
00148 }
00149
00150 double get_flow_delay(int x){
00151 assert(x<nConnections);
00152 return flows[x].delay;
00153 }
00154
00155 double get_flow_tput(int x){
00156 assert(x<nConnections);
00157 return flows[x].p_tput;
00158 }
00159
00160 double get_flow_drop(int x){
00161 assert(x<nConnections);
00162 return flows[x].drop;
00163 }
00164
00165 void GetInputs(char *argv) {
00166
00167
00168 nConnections = 0;
00169 nLinks = 0;
00170
00171
00172 FILE *f;
00173 f = fopen(argv,"r");
00174 assert(f);
00175
00176 char s[256];
00177 while (fgets(s, 255, f)) {
00178
00179
00180 char *t;
00181 t = strtok(s, " \t\n");
00182
00183
00184 if (!t || !t[0] || (t[0] == '#') || !strncasecmp(t, "comment", 6))
00185 continue;
00186
00187
00188 if (!strcasecmp(t,"n")) {
00189 t = strtok(NULL," \t");
00190 assert(t);
00191 nConnections = atoi(t);
00192 assert(nConnections > 0);
00193 assert(nConnections >= 0);
00194 nAdj = new int[nConnections];
00195 Adj = new int*[nConnections];
00196 flows = new flow_stats[nConnections];
00197 for (int i=0; i<nConnections; ++i)
00198 nAdj[i] = -1;
00199 continue;
00200 }
00201
00202
00203 else if (!strcasecmp(t,"m")) {
00204
00205 t = strtok(NULL," \t");
00206 assert(t);
00207
00208 nLinks = atoi(t);
00209 assert(nLinks > 0);
00210
00211 links = new link_stats[nLinks];
00212 continue;
00213 }
00214
00215
00216 else if (!strcasecmp(t,"route")) {
00217
00218 assert (nConnections > 0);
00219 assert (nLinks > 0);
00220 t = strtok(NULL," \t");
00221 assert(t);
00222 int i = atoi(t);
00223 assert(i > 0 && i<= nConnections);
00224 i--;
00225
00226
00227 flows[i].is_sflow = 0;
00228 flows[i].drop = 0;
00229 flows[i].scaled = 0;
00230
00231 t = strtok(NULL," \t");
00232 assert(t);
00233 nAdj[i] = atoi(t);
00234 assert(nAdj[i] > 0 && nAdj[i] <= nLinks);
00235
00236 Adj[i] = new int[nAdj[i]];
00237 for (int j=0; j<nAdj[i]; ++j) {
00238 t = strtok(NULL," \t");
00239 assert(t);
00240 int l = atoi(t);
00241 assert(l > 0 && l <= nLinks);
00242 l--;
00243 Adj[i][j] = l;
00244 }
00245
00246 if (MaxHops < nAdj[i]) MaxHops = nAdj[i];
00247
00248
00249 t = strtok(NULL," \t");
00250
00251
00252
00253
00254 if (t && !strcasecmp(t,"sh")) {
00255
00256 flows[i].is_sflow = 1;
00257
00258
00259 t = strtok(NULL," \t");
00260 assert(t);
00261 double tmp = atof(t);
00262 flows[i].slambda = tmp;
00263
00264
00265 t = strtok(NULL," \t");
00266 assert(t);
00267 int tmpi = atoi(t);
00268 flows[i].snopkts = tmpi;
00269 }
00270
00271
00272
00273
00274
00275 if (t && !strcasecmp(t,"cbr")) {
00276
00277 flows[i].is_sflow = 2;
00278
00279
00280 t = strtok(NULL," \t");
00281 assert(t);
00282 double tmp = atof(t);
00283 flows[i].slambda = tmp;
00284 flows[i].snopkts = 1;
00285 }
00286
00287
00288
00289
00290 int l_;
00291 for(int j=0;j<nAdj[i];j++){
00292 l_ = Adj[i][j];
00293 (links[l_].theflows).push_back(i);
00294 links[l_].nflows++;
00295 if(flows[i].is_sflow){
00296 links[l_].lambda+=flows[i].slambda*flows[i].snopkts;
00297 }
00298 }
00299
00300 continue;
00301 }
00302
00303 else if(!strcasecmp(t,"link")){
00304
00305 assert (nLinks > 0);
00306
00307
00308 t = strtok(NULL," \t");
00309 assert(t);
00310 int i = atoi(t);
00311 assert(i > 0 && i<= nLinks);
00312 i--;
00313
00314
00315 t = strtok(NULL," \t");
00316 assert(t);
00317 double p = atof(t);
00318 assert(p>=0);
00319 links[i].prop = p;
00320
00321
00322 t = strtok(NULL," \t");
00323 assert(t);
00324 p = atof(t);
00325 assert(p>=0);
00326 links[i].lambda = 0;
00327 links[i].tlambda = p;
00328 links[i].plambda = p;
00329
00330
00331 t = strtok(NULL," \t");
00332 assert(t);
00333 p = atof(t);
00334 assert(p>=0);
00335 links[i].mu = p;
00336
00337
00338 t = strtok(NULL," \t");
00339 assert(t);
00340 int t1 = atoi(t);
00341 assert(t1>0);
00342 links[i].buffer = t1;
00343
00344
00345 t = strtok(NULL," \t");
00346 if(t && !strcasecmp(t,"red")){
00347
00348
00349
00350
00351 links[i].red=1;
00352
00353 t = strtok(NULL," \t");
00354 double dt = atof(t);
00355
00356 links[i].minth=dt;
00357
00358
00359 t = strtok(NULL," \t");
00360 dt = atof(t);
00361
00362 links[i].pmin=dt;
00363
00364
00365 t = strtok(NULL," \t");
00366 dt = atof(t);
00367
00368 links[i].maxth=dt;
00369
00370
00371 t = strtok(NULL," \t");
00372 dt = atof(t);
00373
00374 links[i].pmax=dt;
00375
00376
00377
00378 links[i].redrouter = new RedRouter((int)links[i].minth,
00379 (int)links[i].maxth,
00380 links[i].pmax);
00381 assert(links[i].red);
00382
00383 }
00384 else{
00385 links[i].red=0;
00386 }
00387
00388 links[i].nflows = 0;
00389
00390 continue;
00391
00392 }
00393
00394 assert(0);
00395 }
00396
00397
00398 assert (nConnections > 0);
00399 assert (nLinks > 0);
00400 for (int i=0; i<nConnections; ++i)
00401 assert(nAdj[i] > 0);
00402
00403
00404 }
00405
00406
00407
00408 double redFn(double minth, double pmin,
00409 double maxth, double pmax, double qlength){
00410
00411 assert(qlength>=0 && qlength<=1);
00412 assert(pmax>=0 && pmax<=1);
00413 assert(pmin>=0 && pmin<=1);
00414 assert(minth>=0 && minth<=1);
00415 assert(maxth>=0 && maxth<=1);
00416 assert(maxth>=minth);
00417 assert(pmax>pmin);
00418
00419 double t;
00420 if(qlength<minth)
00421 return 0;
00422 if(qlength>maxth)
00423 return 1;
00424 return pmin + (qlength-minth)/(pmax-pmin);
00425
00426 }
00427
00428
00429 void CalcLinkStats(int flag = 0){
00430
00431
00432
00433
00434
00435 for(int i=0; i<nLinks; i++){
00436
00437 double rho = links[i].lambda/links[i].mu;
00438 double qlength = Lq(rho,links[i].buffer);
00439
00440 links[i].qdelay = qlength/links[i].mu;
00441 links[i].drop = Pk(rho,links[i].buffer,links[i].buffer);
00442
00443
00444
00445 if(flag){
00446 if(links[i].red){
00447 double minth, maxth, pmin, pmax, delay,p;
00448 minth = links[i].minth;
00449 maxth = links[i].maxth;
00450 pmin = links[i].pmin;
00451 pmax = links[i].pmax;
00452
00453
00454 p=(links[i].redrouter)->ComputeProbability(rho, delay);
00455 links[i].drop = p;
00456 qlength = Lq(rho*(1-p), links[i].buffer);
00457 links[i].qdelay = delay;
00458 }
00459 }
00460
00461 }
00462
00463 }
00464
00465 void CalcPerFlowStats(){
00466
00467 for(int i=0; i<nConnections; i++){
00468 double d = 0, p = 1 ;
00469
00470 for(int j=0;j<nAdj[i];j++){
00471 d += 2*links[Adj[i][j]].prop + links[Adj[i][j]].qdelay;
00472 p *= 1-links[Adj[i][j]].drop;
00473 }
00474 p = 1-p;
00475
00476
00477 flows[i].no = nAdj[i];
00478 flows[i].delay = d;
00479 flows[i].drop = p;
00480 flows[i].t = flows[i].p_tput;
00481
00482
00483
00484
00485
00486
00487
00488 if(flows[i].is_sflow==1){
00489
00490
00491 double t = (flows[i].slambda*flows[i].snopkts);
00492 flows[i].p_tput = t/(1-p);
00493 }
00494 else if(flows[i].is_sflow==2){
00495
00496
00497 flows[i].p_tput = flows[i].slambda*(1-p);
00498
00499 }
00500 else{
00501
00502 if(!p){
00503
00504 }
00505 flows[i].p_tput = padhye(d,p);
00506 }
00507
00508
00509
00510
00511
00512 }
00513 }
00514
00515 void PrintData(){
00516 for(int i=0;i<nLinks;i++){
00517 cout << i << sp << links[i].lambda << sp << links[i].mu;
00518 cout << sp << links[i].buffer << endl;
00519 }
00520 }
00521
00522
00523 void PrintResults(){
00524
00525 for(int i=0;i<nLinks;i++){
00526 printf("l %d qdel %.5lf drop %.5lf lam %.3lf\n", i+1, links[i].qdelay, links[i].drop,links[i].lambda);
00527 }
00528
00529 for(int i=0; i<nConnections; i++){
00530 printf("c %d gput %.5lf drop %.5lf e2edel %.5lf\n", i+1,
00531 flows[i].p_tput,
00532 flows[i].drop,
00533 flows[i].delay);
00534 }
00535
00536 }
00537
00538 void UpdateHelper(int flag=0){
00539
00540
00541
00542
00543 for(int i=0; i<nLinks; i++){
00544 links[i].tlambda=0;
00545 }
00546
00547 for(int i=0; i<nConnections; i++){
00548 if(!flag || !flows[i].scaled)
00549 for(int j=0;j<nAdj[i];j++){
00550 if(flows[i].is_sflow==2){
00551
00552 links[Adj[i][j]].tlambda += flows[i].slambda*(1-links[Adj[i][j]].drop);
00553
00554
00555 }
00556 else
00557 links[Adj[i][j]].tlambda += flows[i].p_tput;
00558 }
00559
00560 }
00561
00562 }
00563
00564
00565 void Update(int niter){
00566
00567 UpdateHelper();
00568
00569 for(int i=0; i<nLinks; i++){
00570 links[i].plambda = links[i].lambda;
00571 double t;
00572 double tk=links[i].mu*(1.05)+5;
00573
00574 if(niter){
00575 if(links[i].tlambda>tk)
00576
00577 t = ((links[i].lambda)+tk)/2;
00578
00579 else
00580
00581 t= ((links[i].tlambda)+(links[i].lambda))/2;
00582
00583 }
00584 else t = links[i].tlambda;
00585 links[i].lambda = t;
00586 }
00587
00588 }
00589
00590
00591 int allscaled(){
00592
00593
00594
00595 for(int i=0; i<nConnections; i++)
00596 if(!flows[i].is_sflow && !flows[i].scaled){
00597
00598 return 0;
00599 }
00600
00601 cout << "All are scaled\n";
00602
00603 return 1;
00604
00605 }
00606
00607
00608
00609
00610 void newupdate(int niter){
00611
00612
00613
00614 for (int i=0;i<nLinks;i++){
00615 links[i].uc = links[i].mu*(1.05);
00616 links[i].utput = 0;
00617 }
00618
00619
00620
00621
00622 for(int i=0; i<nConnections; i++){
00623 if(flows[i].is_sflow)
00624 flows[i].scaled = 1;
00625 else
00626 flows[i].scaled = 0;
00627 for(int j=0;j<nAdj[i];j++){
00628 if(flows[i].is_sflow)
00629 links[Adj[i][j]].uc -= flows[i].p_tput;
00630 else
00631 links[Adj[i][j]].utput += flows[i].p_tput;
00632 }
00633 }
00634
00635
00636
00637
00638
00639 double maxgamma;
00640 int bneck;
00641 double t;
00642
00643 bneck = -1;
00644 maxgamma = 0;
00645 for(int i=0; i<nLinks; i++){
00646 if(links[i].uc){
00647 t=links[i].utput/links[i].uc;
00648 if(t > maxgamma){
00649 bneck = i;
00650 maxgamma = t;
00651 }
00652 }
00653 }
00654
00655 while(bneck+1){
00656
00657
00658 for(int i=0; i<links[bneck].nflows; i++){
00659
00660 int t = links[bneck].theflows[i];
00661
00662
00663
00664 if(!flows[t].is_sflow && !flows[t].scaled){
00665 flows[t].p_tput /= maxgamma;
00666
00667 flows[t].scaled = 1;
00668 for(int j=0;j<nAdj[t];j++){
00669
00670
00671 links[Adj[t][j]].uc -= flows[t].p_tput;
00672 links[Adj[t][j]].utput -= flows[t].p_tput*maxgamma;
00673
00674 }
00675
00676 }
00677 }
00678
00679
00680
00681 links[bneck].uc = 0;
00682
00683 bneck = -1;
00684 maxgamma = 0;
00685 for(int i=0; i<nLinks; i++){
00686 if(links[i].uc){
00687 t=links[i].utput/links[i].uc;
00688 if(t > maxgamma){
00689 bneck = i;
00690 maxgamma = t;
00691 }
00692 }
00693 }
00694
00695 }
00696
00697 Update(niter);
00698
00699 }
00700
00701
00702 asim(){
00703
00704 }
00705
00706 };
00707
00708
00709 int main(int argc, char **argv) {
00710
00711 int niter = 0;
00712
00713
00714
00715 if (argc != 2) {
00716 fprintf(stderr,"Usage: %s <InputFile>\n", argv[0]);
00717 exit(-1);
00718 }
00719
00720
00721 asim sim;
00722 sim.GetInputs(argv[1]);
00723
00724
00725
00726 for(int i=0; i<3; i++){
00727 sim.CalcLinkStats(1);
00728
00729 sim.CalcPerFlowStats();
00730
00731
00732 sim.newupdate(niter);
00733
00734
00735 }
00736 sim.PrintResults();
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751