asimstd.cc

Go to the documentation of this file.
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 // Integration of Ashish's RED and asim
00010 #define _RED_ROUTER_MAIN_
00011 #include "asim.h"
00012 
00013 #define sp " " 
00014 
00015 // Optimization
00016 #include<vector>
00017 using namespace std;
00018 
00019 typedef struct c{
00020     int no; // no of edges in the connection
00021     double delay; // total delay;
00022     double drop; // total drop prob
00023     double p_tput;
00024     double t;
00025     // The short flow stuff
00026     int is_sflow; // boolean to indicate whether there is a short flow
00027     double slambda; // The arrival rate of the connections
00028     int snopkts; // average of no of packets each short flow givies
00029     RedRouter * red;
00030     int scaled; // Whether this flow has been scaled or not
00031 }flow_stats;
00032 
00033 typedef struct n{
00034     int red; // flag to notify whether its a red queue or not
00035     double pmin, pmax, minth, maxth; // RED parameters
00036     double lambda; // Arrival rate - Packets per second
00037     double plambda; // Temp lambda value. previous lambda
00038     double tlambda;
00039     double mu; // Consumption rate - Packets per second
00040     double prop; // Propagation delay of the link
00041     double qdelay; // Store the queuing delay for each link
00042     int    buffer; // Total buffer
00043     double drop; // probability of drop
00044     int nflows; // Number of flows through this link
00045     vector<int> theflows; // The flows through this link
00046     double scaled_lambda;
00047     double unscaled_lambda;
00048     
00049     double utput; // unscaled tput 
00050     double uc; // unscaled capacity
00051     
00052     // RED
00053     RedRouter * redrouter;
00054     
00055 }link_stats;
00056 
00057 
00058 class asim {
00059 
00060 public:
00061 
00062     // data structures 
00063     int nConnections; // Number of connections
00064     int K, MaxHops; // 
00065     int nLinks; // Number of links 
00066     int **Adj; // Stores the edge list of each connection
00067     int *nAdj; // Stores the no of edges per connection
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         // M/M/1/K
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         // Init links and connections 
00168         nConnections = 0;
00169         nLinks = 0;
00170         
00171         // Start the reading process
00172         FILE *f;
00173         f = fopen(argv,"r");
00174         assert(f);
00175         
00176         char s[256];
00177         while (fgets(s, 255, f)) {
00178             
00179             // Read a token 
00180             char *t;
00181             t = strtok(s, " \t\n");
00182             
00183             // Ignore comments 
00184             if (!t || !t[0] || (t[0] == '#') || !strncasecmp(t, "comment", 6))
00185                 continue;
00186             
00187             // Define the number of connections
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             // Define the number of links
00203             else if (!strcasecmp(t,"m")) {
00204                 
00205                 t = strtok(NULL," \t");
00206                 assert(t);
00207                 // #of links defined
00208                 nLinks = atoi(t);
00209                 assert(nLinks > 0);
00210                 // Allocate space for sotring lambdas and mus
00211                 links = new link_stats[nLinks];
00212                 continue;
00213             }
00214             
00215             // Enter each route 
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                 // We dunno whether this will be short flow specs
00227                 flows[i].is_sflow = 0; // Lets assume its a normal flow
00228                 flows[i].drop = 0; // Assume ideal case to start off
00229                 flows[i].scaled = 0; // Not scaled as yet
00230                 
00231                 t = strtok(NULL," \t");
00232                 assert(t);
00233                 nAdj[i] = atoi(t);
00234                 assert(nAdj[i] > 0 && nAdj[i] <= nLinks);
00235                 // We know how many links it will use
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                 // assert(t);
00251                 
00252                 // Short flows stuff 
00253                 
00254                 if (t && !strcasecmp(t,"sh")) {
00255                     // There are short flows on this route.
00256                     flows[i].is_sflow = 1;
00257                     
00258                     // read the slambda
00259                     t = strtok(NULL," \t");
00260                     assert(t);
00261                     double  tmp = atof(t);
00262                     flows[i].slambda = tmp;
00263                     
00264                     // read the snopkts
00265                     t = strtok(NULL," \t");
00266                     assert(t);
00267                     int  tmpi = atoi(t);
00268                     flows[i].snopkts = tmpi;
00269                 }
00270                 
00271                 
00272                 // For cbr 
00273                 // Treat almost like a short flow!
00274                 
00275                 if (t && !strcasecmp(t,"cbr")) {
00276                     // There are short flows on this route.
00277                     flows[i].is_sflow = 2;
00278                     
00279                     // read the rate
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                 // Now, let us put the flows in persective
00289                 // Insert the flow id trhough all the links
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                 // Get the link number
00308                 t = strtok(NULL," \t");
00309                 assert(t);
00310                 int i = atoi(t);
00311                 assert(i > 0 && i<= nLinks);
00312                 i--;
00313                 
00314                 // Get the prop delay
00315                 t = strtok(NULL," \t");
00316                 assert(t);
00317                 double p = atof(t);
00318                 assert(p>=0); 
00319                 links[i].prop = p;
00320                 
00321                 // Get the lambda for this link
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                 // Get the mu for this link
00331                 t = strtok(NULL," \t");
00332                 assert(t);
00333                 p = atof(t);
00334                 assert(p>=0);
00335                 links[i].mu = p;
00336                 
00337                 // Get the buffer for this link
00338                 t = strtok(NULL," \t");
00339                 assert(t);
00340                 int t1 = atoi(t);
00341                 assert(t1>0);
00342                 links[i].buffer = t1;
00343                 
00344                 // Check for RED Q or not
00345                 t = strtok(NULL," \t");
00346                 if(t && !strcasecmp(t,"red")){
00347                     
00348                     // must be a red queue
00349                     // input red parameters
00350                     // all parameters between 0 and 1
00351                     links[i].red=1;
00352                     // get minth
00353                     t = strtok(NULL," \t");
00354                     double dt = atof(t); 
00355                     //assert(dt>=0 && dt<=1);
00356                     links[i].minth=dt;
00357                     
00358                     // get pmin
00359                     t = strtok(NULL," \t");
00360                     dt = atof(t); 
00361                     //assert(dt>=0 && dt<=1);
00362                     links[i].pmin=dt;
00363                     
00364                     // get maxth
00365                     t = strtok(NULL," \t");
00366                     dt = atof(t); 
00367                     //assert(dt>=0 && dt<=1);
00368                     links[i].maxth=dt;
00369                     
00370                     // get pmax
00371                     t = strtok(NULL," \t");
00372                     dt = atof(t); 
00373                     //assert(dt>=0 && dt<=1);
00374                     links[i].pmax=dt;
00375                     
00376                     // Invoke Ashish's RED module ... ignore pmin .....
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; // init the num of flows
00389                 
00390                 continue;
00391                 
00392             }
00393             
00394             assert(0);
00395         }
00396         
00397         // Check whether everything is all right 
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         // flag = 1 means enable RED
00432     
00433         // Calculate Link delays ... basically queuing delays
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             // cout << "Link " << i << " has drop prob = " << links[i].drop << endl;
00443 
00444             // Special code for RED gateways
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                     // The RED approx.
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 //          cout << i << sp << "rho = " << rho << " delay = " << links[i].qdelay << " and drop = " << links[i].drop << endl;
00461         }
00462     
00463     }
00464 
00465     void CalcPerFlowStats(){
00466  
00467         for(int i=0; i<nConnections; i++){
00468             double d = 0, p = 1 ;
00469             // Calculate drops and delays
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             //cout << "Flow " << i << " has drop prob = " << p << endl; 
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             // p is the end2end drop prob
00483             // If its normal flow, calculate Padhye's stuff
00484             // If its short flow, use our approximations
00485             // Nothing more
00486         
00487         
00488             if(flows[i].is_sflow==1){
00489                 // If k flows come and each each flow has n packets to 
00490                 // send then 
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                 // For CBR, dont divide by 1-p unlike short flows.
00496                 // If rate is x and prob is p, net goodput is x(1-p)
00497                 flows[i].p_tput = flows[i].slambda*(1-p);
00498                 // cout << "cbr stuff - tput = " << flows[i].p_tput << endl;
00499             }
00500             else{
00501                 // regular bulk TCP connections, Padhye et. al.
00502                 if(!p){
00503                 // cout << "Oops, something wrong";
00504                 }
00505                 flows[i].p_tput = padhye(d,p);
00506             }
00507         
00508             // cout << "connection " << sp << i << sp << d << sp << p; 
00509             //cout << sp << flows[i].p_tput << endl;
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         // if flag = 1 then update only when link is unscaled as of now
00541         // if flag = 0 then do the usual update 
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                         // cbr flow
00552                         links[Adj[i][j]].tlambda += flows[i].slambda*(1-links[Adj[i][j]].drop);
00553                         //cout << "cbr flow " << i << " adding " << flows[i].slambda*(1-links[Adj[i][j]].drop)
00554                         //    << " to link " << j << " tlam = " << links[Adj[i][j]].tlambda << endl;
00555                     }
00556                     else
00557                         links[Adj[i][j]].tlambda += flows[i].p_tput;
00558                 }
00559             //    cout << flows[i].p_tput << "\n";
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                 //t = pow((sqrt(links[i].lambda)+sqrt(links[i].mu+5))/2,2);
00577                     t = ((links[i].lambda)+tk)/2;
00578                 // t = exp((log(links[i].lambda)+log(links[i].mu+5))/2);
00579                 else
00580                 //t = pow((sqrt(links[i].tlambda)+sqrt(links[i].lambda))/2,2);
00581                     t= ((links[i].tlambda)+(links[i].lambda))/2;
00582                 // t = exp((log(links[i].tlambda)+log(links[i].lambda))/2);
00583             }
00584             else t = links[i].tlambda;
00585             links[i].lambda = t; // Update the lambda ..........
00586         }
00587 
00588     }
00589 
00590 
00591     int allscaled(){
00592 
00593         //cout << nConnections;
00594 
00595         for(int i=0; i<nConnections; i++)
00596             if(!flows[i].is_sflow && !flows[i].scaled){
00597                 //cout << "Connection " << i << " not scaled as yet\n";
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         // 1st init all unscaled tputs and cap
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         // calc all the unscaled tputs and C set all short flows 
00621         // to be scaled already 
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         //for(int i =0; i<nLinks; i++ ){
00636             //cout << i << sp << links[i].uc << sp << links[i].utput << endl;
00637         //}
00638 
00639         double maxgamma; // most congested link
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             //cout << "bneck = " << bneck << sp << links[bneck].uc << sp << links[bneck].utput << sp << maxgamma << sp << links[bneck].nflows <<endl;
00658             for(int i=0; i<links[bneck].nflows; i++){
00659                 // For all the connections passing through this link
00660                 int t = links[bneck].theflows[i]; // get a connection id
00661                 //     cout << i<< sp << t << sp ;
00662                 // Now reduce its p_tput iff its not a short flow
00663                 // For short flows we dont do scaling
00664                 if(!flows[t].is_sflow && !flows[t].scaled){
00665                     flows[t].p_tput /= maxgamma;
00666                 //cout << "Flow " << t << " getting scaled to  << " << flows[t].p_tput;
00667                     flows[t].scaled = 1; // we have scaled this flow already
00668                     for(int j=0;j<nAdj[t];j++){
00669                         // subtract this scaled throughout from all teh links that
00670                         // have this flow. 
00671                         links[Adj[t][j]].uc -= flows[t].p_tput;
00672                         links[Adj[t][j]].utput -= flows[t].p_tput*maxgamma;
00673                         // cout << sp << Adj[i][j];
00674                     }
00675                 //cout << endl;
00676                 }
00677             }
00678     
00679             //cout << links[bneck].uc << sp << links[bneck].utput << endl;
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         //cout << "Reached here\n";
00704     }
00705 
00706 };
00707 
00708 
00709 int main(int argc, char **argv) {
00710 
00711     int niter = 0;
00712 
00713     // error if usage is wrong 
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     //sim.PrintResults();
00724     //cout << "Read the input .... \n";
00725 
00726     for(int i=0; i<3; i++){
00727         sim.CalcLinkStats(1);
00728         //cout << "Calculated link delays ... \n";
00729         sim.CalcPerFlowStats();
00730         //cout << "Calculated per flow delays ... \n";
00731         //cout << " ------------------------------\n";
00732         sim.newupdate(niter);
00733         //sim.PrintResults();
00734         //cout << " ------------------------------\n"; 
00735     }
00736     sim.PrintResults();
00737 }
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 

Generated on Tue Mar 6 16:47:43 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6