00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "config.h"
00048
00049 #include <math.h>
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <string.h>
00053 #include <strings.h>
00054 #include <assert.h>
00055 #include <iostream>
00056
00057 #include "agent.h"
00058
00059
00060 #define _RED_ROUTER_MAIN_
00061 #include "asim.h"
00062
00063 #define sp " "
00064
00065 typedef struct c{
00066 int no;
00067 double delay;
00068 double drop;
00069 double p_tput;
00070 double t;
00071
00072 int is_sflow;
00073 double slambda;
00074 int snopkts;
00075 RedRouter * red;
00076 int scaled;
00077 }flow_stats;
00078
00079 typedef struct n{
00080 int red;
00081 double pmin, pmax, minth, maxth;
00082 double lambda;
00083 double plambda;
00084 double tlambda;
00085 double mu;
00086 double prop;
00087 double qdelay;
00088 int buffer;
00089 double drop;
00090 int nflows;
00091 int *theflows;
00092 double scaled_lambda;
00093 double unscaled_lambda;
00094
00095 double utput;
00096 double uc;
00097
00098
00099 RedRouter * redrouter;
00100
00101 }link_stats;
00102
00103
00104 class asim : public NsObject{
00105
00106 public:
00107
00108
00109 int nConnections;
00110 int K, MaxHops;
00111 int nLinks;
00112 int **Adj;
00113 int *nAdj;
00114
00115 link_stats* links;
00116 flow_stats* flows;
00117
00118 double min(double x, double y){
00119 return (x<y)?x:y;
00120 }
00121
00122 double padhye(double rtt, double p){
00123
00124 double rto = 1;
00125 double t=1;
00126 t = rtt*sqrt(2*p/3)+rto*min(1,(3*sqrt(3*p/8)))*p*(1+32*p*p);
00127 return min(20/rtt,1/t);
00128
00129 }
00130
00131 double Po(double rho, int K){
00132
00133 if(rho==1)
00134 return 1.0/(K+1);
00135
00136 double t;
00137 t=(1.0*(1-rho))/(1.0-pow(rho,K));
00138 return t;
00139
00140 }
00141
00142 double Pk(double rho, int K, int k){
00143
00144 if(rho==1)
00145 return 1.0/(K+1);
00146
00147 double t;
00148 t=(1-rho)*pow(rho,k);
00149 t/=1-pow(rho,K+1);
00150 return t;
00151 }
00152
00153 double Lq(double rho, int K){
00154
00155 double t1,t2;
00156
00157 if(rho==1){
00158 return (1.0*K*(K-1))/(2.0*(K+1));
00159 }
00160
00161 t1=rho*1.0/(1-rho);
00162 t2=rho*1.0/(1-pow(rho,K+1));
00163 t2*=K*pow(rho,K)+1;
00164 return (t1-t2)/2;
00165
00166 }
00167
00168 int command (int argc, const char*const* argv){
00169
00170 if (strcmp(argv[1], "run") == 0) {
00171 int niter=0;
00172 for(int i=0; i<20; i++){
00173 CalcLinkDelays(1);
00174 CalcPerFlowDelays();
00175 newupdate(niter);
00176 }
00177
00178 return (TCL_OK);
00179 }
00180
00181 if (strcmp(argv[1], "readinput") == 0) {
00182 GetInputs((char*)argv[2]);
00183
00184 return (TCL_OK);
00185 }
00186
00187 if (strcmp(argv[1], "get-link-drop") == 0) {
00188 cout << "Hi";
00189 Tcl& tcl = Tcl::instance();
00190 tcl.resultf("%lf",get_link_drop(atoi(argv[2])));
00191 return (TCL_OK);
00192 }
00193
00194 if (strcmp(argv[1], "get-link-delay") == 0) {
00195 Tcl& tcl = Tcl::instance();
00196 tcl.resultf("%lf",get_link_delay(atoi(argv[2])));
00197 return (TCL_OK);
00198 }
00199
00200 if (strcmp(argv[1], "get-link-tput") == 0) {
00201 Tcl& tcl = Tcl::instance();
00202 tcl.resultf("%lf",get_link_tput(atoi(argv[2])));
00203 return (TCL_OK);
00204 }
00205
00206 if (strcmp(argv[1], "get-flow-tput") == 0) {
00207 Tcl& tcl = Tcl::instance();
00208 tcl.resultf("%lf",get_flow_tput(atoi(argv[2])));
00209 return (TCL_OK);
00210 }
00211
00212 if (strcmp(argv[1], "get-flow-delay") == 0) {
00213 Tcl& tcl = Tcl::instance();
00214 tcl.resultf("%lf",get_flow_delay(atoi(argv[2])));
00215 return (TCL_OK);
00216 }
00217
00218 if (strcmp(argv[1], "get-flow-drop") == 0) {
00219 Tcl& tcl = Tcl::instance();
00220 tcl.resultf("%lf",get_flow_drop(atoi(argv[2])));
00221 return (TCL_OK);
00222 }
00223 return 0;
00224 }
00225
00226 double get_link_drop(int x){
00227 assert(x<nLinks);
00228 return links[x].drop;
00229 }
00230
00231 double get_link_delay(int x){
00232 assert(x<nLinks);
00233 return links[x].qdelay + links[x].prop ;
00234 }
00235
00236 double get_link_qdelay(int x){
00237 assert(x<nLinks);
00238 return links[x].qdelay;
00239 }
00240
00241 double get_link_pdelay(int x){
00242 assert(x<nLinks);
00243 return links[x].prop;
00244 }
00245
00246 double get_link_tput(int x){
00247 assert(x<nLinks);
00248 return links[x].lambda;
00249 }
00250
00251 double get_flow_delay(int x){
00252 assert(x<nConnections);
00253 return flows[x].delay;
00254 }
00255
00256 double get_flow_tput(int x){
00257 assert(x<nConnections);
00258 return flows[x].p_tput;
00259 }
00260
00261 double get_flow_drop(int x){
00262 assert(x<nConnections);
00263 return flows[x].drop;
00264 }
00265
00266 void GetInputs(char *argv) {
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 MaxHops = 0;
00277
00278
00279
00280
00281
00282 nConnections = 0;
00283 nLinks = 0;
00284
00285
00286 FILE *f;
00287 f = fopen(argv,"r");
00288 assert(f);
00289
00290 char s[256];
00291 while (fgets(s, 255, f)) {
00292
00293
00294 char *t;
00295 t = strtok(s, " \t\n");
00296
00297
00298 if (!t || !t[0] || (t[0] == '#') || !strncasecmp(t, "comment", 6))
00299 continue;
00300
00301
00302 if (!strcasecmp(t,"n")) {
00303 t = strtok(NULL," \t");
00304 assert(t);
00305 nConnections = atoi(t);
00306 assert(nConnections > 0);
00307 assert(nConnections >= 0);
00308 nAdj = new int[nConnections];
00309 Adj = new int*[nConnections];
00310 flows = new flow_stats[nConnections];
00311 for (int i=0; i<nConnections; ++i)
00312 nAdj[i] = -1;
00313 continue;
00314 }
00315
00316
00317 else if (!strcasecmp(t,"m")) {
00318
00319 t = strtok(NULL," \t");
00320 assert(t);
00321
00322 nLinks = atoi(t);
00323 assert(nLinks > 0);
00324
00325 links = new link_stats[nLinks];
00326 continue;
00327 }
00328
00329
00330 else if (!strcasecmp(t,"route")) {
00331
00332 assert (nConnections > 0);
00333 assert (nLinks > 0);
00334 t = strtok(NULL," \t");
00335 assert(t);
00336 int i = atoi(t);
00337 assert(i > 0 && i<= nConnections);
00338 i--;
00339
00340
00341 flows[i].is_sflow = 0;
00342 flows[i].drop = 0;
00343 flows[i].scaled = 0;
00344
00345 t = strtok(NULL," \t");
00346 assert(t);
00347 nAdj[i] = atoi(t);
00348 assert(nAdj[i] > 0 && nAdj[i] <= nLinks);
00349 Adj[i] = new int[nAdj[i]];
00350 for (int j=0; j<nAdj[i]; ++j) {
00351 t = strtok(NULL," \t");
00352 assert(t);
00353 int l = atoi(t);
00354 assert(l > 0 && l <= nLinks);
00355 l--;
00356 Adj[i][j] = l;
00357 }
00358
00359 if (MaxHops < nAdj[i]) MaxHops = nAdj[i];
00360
00361
00362 t = strtok(NULL," \t");
00363
00364
00365
00366
00367 if (t && !strcasecmp(t,"sh")) {
00368
00369 flows[i].is_sflow = 1;
00370
00371
00372 t = strtok(NULL," \t");
00373 assert(t);
00374 double tmp = atof(t);
00375 flows[i].slambda = tmp;
00376
00377
00378 t = strtok(NULL," \t");
00379 assert(t);
00380 int tmpi = atoi(t);
00381 flows[i].snopkts = tmpi;
00382 }
00383
00384 continue;
00385 }
00386
00387 else if(!strcasecmp(t,"link")){
00388
00389 assert (nLinks > 0);
00390
00391
00392 t = strtok(NULL," \t");
00393 assert(t);
00394 int i = atoi(t);
00395 assert(i > 0 && i<= nLinks);
00396 i--;
00397
00398
00399 t = strtok(NULL," \t");
00400 assert(t);
00401 double p = atof(t);
00402 assert(p>=0);
00403 links[i].prop = p;
00404
00405
00406 t = strtok(NULL," \t");
00407 assert(t);
00408 p = atof(t);
00409 assert(p>=0);
00410 links[i].lambda = 0;
00411 links[i].tlambda = p;
00412 links[i].plambda = p;
00413
00414
00415 t = strtok(NULL," \t");
00416 assert(t);
00417 p = atof(t);
00418 assert(p>=0);
00419 links[i].mu = p;
00420
00421
00422 t = strtok(NULL," \t");
00423 assert(t);
00424 int t1 = atoi(t);
00425 assert(t1>0);
00426 links[i].buffer = t1;
00427
00428
00429 t = strtok(NULL," \t");
00430 if(t && !strcasecmp(t,"red")){
00431
00432
00433
00434
00435 links[i].red=1;
00436
00437 t = strtok(NULL," \t");
00438 double dt = atof(t);
00439
00440 links[i].minth=dt;
00441
00442
00443 t = strtok(NULL," \t");
00444 dt = atof(t);
00445
00446 links[i].pmin=dt;
00447
00448
00449 t = strtok(NULL," \t");
00450 dt = atof(t);
00451
00452 links[i].maxth=dt;
00453
00454
00455 t = strtok(NULL," \t");
00456 dt = atof(t);
00457
00458 links[i].pmax=dt;
00459
00460
00461
00462 links[i].redrouter = new RedRouter((int)links[i].minth,
00463 (int)links[i].maxth,
00464 links[i].pmax);
00465 assert(links[i].red);
00466
00467 }
00468 else{
00469 links[i].red=0;
00470 }
00471
00472 continue;
00473
00474 }
00475
00476 assert(0);
00477 }
00478
00479
00480 assert (nConnections > 0);
00481 assert (nLinks > 0);
00482 int i;
00483 for (i=0; i<nConnections; ++i)
00484 assert(nAdj[i] > 0);
00485
00486
00487
00488
00489
00490 for(i=0;i<nLinks;i++){
00491
00492
00493 int c=0; links[i].tlambda=0;
00494
00495 for(int j=0;j<nConnections;j++){
00496 for(int k=0;k<nAdj[j];k++){
00497 if(Adj[j][k]==i){
00498 c++;
00499 }
00500 }
00501 }
00502 links[i].nflows=c;
00503
00504
00505 if(c){
00506 links[i].theflows = new int[c];
00507 c = 0;
00508
00509 for(int j=0;j<nConnections;j++){
00510 for(int k=0;k<nAdj[j];k++){
00511 if(Adj[j][k]==i){
00512 if(flows[j].is_sflow){
00513 links[i].lambda+=flows[j].slambda*flows[j].snopkts;
00514 }
00515 links[i].theflows[c++]=j;
00516
00517 }
00518 }
00519 }
00520
00521 }
00522
00523 else links[i].theflows = 0;
00524
00525
00526
00527
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 }
00543
00544
00545
00546 double redFn(double minth, double pmin,
00547 double maxth, double pmax, double qlength){
00548
00549 assert(qlength>=0 && qlength<=1);
00550 assert(pmax>=0 && pmax<=1);
00551 assert(pmin>=0 && pmin<=1);
00552 assert(minth>=0 && minth<=1);
00553 assert(maxth>=0 && maxth<=1);
00554 assert(maxth>=minth);
00555 assert(pmax>pmin);
00556
00557
00558 if(qlength<minth)
00559 return 0;
00560 if(qlength>maxth)
00561 return 1;
00562 return pmin + (qlength-minth)/(pmax-pmin);
00563
00564 }
00565
00566
00567 void CalcLinkDelays(int flag = 0){
00568
00569
00570
00571
00572
00573 for(int i=0; i<nLinks; i++){
00574
00575 double rho = links[i].lambda/links[i].mu;
00576 double qlength = Lq(rho,links[i].buffer);
00577
00578 links[i].qdelay = qlength/links[i].mu;
00579 links[i].drop = Pk(rho,links[i].buffer,links[i].buffer);
00580
00581
00582
00583 if(flag){
00584 if(links[i].red){
00585 double minth, maxth, pmin, pmax, delay,p;
00586 minth = links[i].minth;
00587 maxth = links[i].maxth;
00588 pmin = links[i].pmin;
00589 pmax = links[i].pmax;
00590
00591
00592
00593
00594
00595
00596
00597 p=(links[i].redrouter)->ComputeProbability(rho, delay);
00598 links[i].drop = p;
00599 qlength = Lq(rho*(1-p), links[i].buffer);
00600 links[i].qdelay = delay;
00601 }
00602 }
00603
00604
00605
00606
00607
00608 }
00609
00610 }
00611
00612 void CalcPerFlowDelays(){
00613 for(int i=0; i<nConnections; i++){
00614 double d = 0, p = 1 ;
00615
00616 for(int j=0;j<nAdj[i];j++){
00617 d += 2*links[Adj[i][j]].prop + links[Adj[i][j]].qdelay;
00618 p *= 1-links[Adj[i][j]].drop;
00619 }
00620 p = 1-p;
00621
00622 flows[i].no = nAdj[i];
00623 flows[i].delay = d;
00624 flows[i].drop = p;
00625 flows[i].t = flows[i].p_tput;
00626
00627
00628
00629
00630
00631
00632
00633 if(flows[i].is_sflow){
00634
00635
00636 double t = (flows[i].slambda*flows[i].snopkts);
00637 flows[i].p_tput = t/(1-p);
00638 }
00639 else{
00640
00641 if(!p){
00642
00643 }
00644 flows[i].p_tput = padhye(d,p);
00645 }
00646
00647
00648
00649
00650
00651 }
00652 }
00653
00654 void PrintData(){
00655 for(int i=0;i<nLinks;i++){
00656 cout << i << sp << links[i].lambda << sp << links[i].mu;
00657 cout << sp << links[i].buffer << endl;
00658 }
00659 }
00660
00661 void PrintResults(){
00662 int i;
00663
00664 for(i=0;i<nLinks;i++){
00665
00666 cout << sp << "Qdelay = " << links[i].prop << sp << links[i].lambda;
00667 cout << sp << links[i].drop << endl;
00668 }
00669
00670 for(i=0; i<nConnections; i++){
00671 cout << i << sp << flows[i].delay << sp;
00672 cout << flows[i].drop << sp << flows[i].p_tput << sp;
00673 cout << sp << endl;
00674 }
00675
00676 }
00677
00678 void UpdateHelper(int flag=0){
00679
00680
00681
00682
00683 int i;
00684 for(i=0; i<nLinks; i++){
00685 links[i].tlambda=0;
00686 }
00687
00688 for(i=0; i<nConnections; i++){
00689 if(!flag || !flows[i].scaled)
00690 for(int j=0;j<nAdj[i];j++)
00691 links[Adj[i][j]].tlambda += flows[i].p_tput;
00692
00693 }
00694
00695 }
00696
00697
00698 void Update(int niter){
00699
00700 UpdateHelper();
00701
00702 for(int i=0; i<nLinks; i++){
00703 links[i].plambda = links[i].lambda;
00704 double t;
00705 double tk=links[i].mu*(1.1);
00706
00707 if(niter){
00708 if(links[i].tlambda>tk)
00709
00710 t = ((links[i].lambda)+tk)/2;
00711
00712 else
00713
00714 t= ((links[i].tlambda)+(links[i].lambda))/2;
00715
00716 }
00717 else t = links[i].tlambda;
00718 links[i].lambda = t;
00719 }
00720
00721 }
00722
00723
00724 void Update2(){
00725
00726 UpdateHelper();
00727
00728 for(int i=0; i<nLinks; i++){
00729 links[i].plambda = links[i].lambda;
00730 links[i].lambda = (links[i].lambda + links[i].tlambda)/2;
00731 }
00732 }
00733
00734 int allscaled(){
00735
00736
00737
00738 for(int i=0; i<nConnections; i++)
00739 if(!flows[i].is_sflow && !flows[i].scaled){
00740 cout << "Connection " << i << " not scaled as yet\n";
00741 return 0;
00742 }
00743
00744
00745
00746 return 1;
00747
00748 }
00749
00750
00751 void Update3(int flag = 0){
00752
00753
00754
00755
00756 double maxtlambda = -1e7;
00757 int bneck = -1;
00758 int i;
00759
00760
00761 for(i=0; i<nConnections; i++)
00762 flows[i].scaled = 0;
00763
00764
00765 UpdateHelper();
00766
00767
00768
00769 for(i=0; i<nLinks; i++){
00770
00771 if(links[i].tlambda>maxtlambda){
00772 bneck = i;
00773 maxtlambda = links[i].tlambda;
00774 }
00775 }
00776
00777 cout << "bottleneck = " << bneck << sp << maxtlambda <<endl;
00778
00779 double tk = links[bneck].mu*(1+links[bneck].drop)+5;
00780
00781
00782 while((maxtlambda > tk + 1) && ! allscaled()){
00783
00784 cout << "Maxtlambda = " << maxtlambda << " bneck = " << bneck << endl;
00785
00786
00787
00788
00789 assert(bneck>=0 && bneck<=nLinks);
00790 int i;
00791 for(i=0; i<links[bneck].nflows; i++){
00792
00793
00794 int t = links[bneck].theflows[i];
00795
00796
00797 if(flag){
00798 if(!flows[t].is_sflow && !flows[t].scaled){
00799 flows[t].p_tput *= (tk)/maxtlambda;
00800
00801 flows[t].scaled = 1;
00802 }
00803 }
00804 else
00805 flows[t].p_tput *= (tk)/maxtlambda;
00806 flows[t].scaled = 1;
00807
00808 }
00809
00810 for (i=0; i<nLinks;i++){
00811 cout << "Link " << i << " tlambda = " << links[i].tlambda << endl;
00812 }
00813
00814
00815
00816
00817 UpdateHelper(0);
00818
00819
00820 bneck = -1;
00821 maxtlambda = -1e7;
00822 for(i=0; i<nLinks; i++){
00823 if(links[i].tlambda>maxtlambda){
00824 bneck = i;
00825 maxtlambda = links[i].tlambda;
00826 }
00827 }
00828
00829
00830 tk = links[bneck].mu*(1+links[bneck].drop)+5;
00831
00832
00833 }
00834
00835 Update(0);
00836 cout << "Out of the converge loop\n";
00837 for (i =0; i<nLinks;i++){
00838 cout << "Link " << i << " tlambda = " << links[i].tlambda << endl;
00839 }
00840
00841 }
00842
00843
00844 void newupdate(int niter){
00845
00846 int i;
00847
00848
00849 for (i=0;i<nLinks;i++){
00850 links[i].uc = links[i].mu*(1.05);
00851 links[i].utput = 0;
00852 }
00853
00854
00855
00856
00857 for(i=0; i<nConnections; i++){
00858 if(flows[i].is_sflow)
00859 flows[i].scaled = 1;
00860 else
00861 flows[i].scaled = 0;
00862 for(int j=0;j<nAdj[i];j++){
00863 if(flows[i].is_sflow)
00864 links[Adj[i][j]].uc -= flows[i].p_tput;
00865 else
00866 links[Adj[i][j]].utput += flows[i].p_tput;
00867 }
00868 }
00869
00870
00871
00872
00873
00874 double maxgamma;
00875 int bneck;
00876 double t;
00877
00878 bneck = -1;
00879 maxgamma = 0;
00880 for(i=0; i<nLinks; i++){
00881 if(links[i].uc){
00882 t=links[i].utput/links[i].uc;
00883 if(t > maxgamma){
00884 bneck = i;
00885 maxgamma = t;
00886 }
00887 }
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 while(bneck+1){
00905
00906
00907
00908 for(i=0; i<links[bneck].nflows; i++){
00909
00910 int t = links[bneck].theflows[i];
00911
00912
00913
00914 if(!flows[t].is_sflow && !flows[t].scaled){
00915 flows[t].p_tput /= maxgamma;
00916
00917 flows[t].scaled = 1;
00918 for(int j=0;j<nAdj[t];j++){
00919
00920
00921 links[Adj[t][j]].uc -= flows[t].p_tput;
00922 links[Adj[t][j]].utput -= flows[t].p_tput*maxgamma;
00923
00924 }
00925
00926 }
00927 }
00928
00929
00930
00931 links[bneck].uc = 0;
00932
00933 bneck = -1;
00934 maxgamma = 0;
00935 for(i=0; i<nLinks; i++){
00936 if(links[i].uc){
00937 t=links[i].utput/links[i].uc;
00938 if(t > maxgamma){
00939 bneck = i;
00940 maxgamma = t;
00941 }
00942 }
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 }
00958
00959 Update(niter);
00960
00961 }
00962
00963
00964 asim(){
00965
00966 }
00967
00968 void recv(Packet *, Handler * = 0){}
00969
00970 };
00971
00972
00973
00974 static class AsimClass : public TclClass {
00975 public:
00976 AsimClass(): TclClass("Asim"){ }
00977 TclObject * create(int, const char*const*) {
00978 return (new asim());
00979 }
00980 } class_asim;
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020