dsPolicy.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000 Nortel Networks
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by Nortel Networks.
00016  * 4. The name of the Nortel Networks may not be used
00017  *    to endorse or promote products derived from this software without
00018  *    specific prior written permission.
00019  * 
00020  * THIS SOFTWARE IS PROVIDED BY NORTEL AND CONTRIBUTORS ``AS IS'' AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023  * ARE DISCLAIMED.  IN NO EVENT SHALL NORTEL OR CONTRIBUTORS BE LIABLE
00024  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00025  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00026  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00027  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00029  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * Developed by: Farhan Shallwani, Jeremy Ethridge
00033  *               Peter Pieda, and Mandeep Baines
00034  * Maintainer: Peter Pieda <ppieda@nortelnetworks.com>
00035  */
00036 
00037 /* 
00038  *  Integrated into ns main distribution and reorganized by 
00039  *  Xuan Chen (xuanc@isi.edu). The main changes are:
00040  *
00041  *  1. Defined two seperated classes, PolicyClassifier and Policy, to handle 
00042  *     the work done by class Policy before.
00043  *     Class PolicyClassifier now only keeps states for each flow and pointers
00044  *     to certain policies. 
00045  *     The policies perform the diffserv related jobs as described
00046  *     below. (eg, traffic metering and packet marking.)
00047  *     class Policy functions like the class Classifer.
00048  *
00049  *  2. Created a general supper class Policy so that new policy can be added
00050  *     by just creating a subclass of Policy. Examples are given (eg, 
00051  *     DumbPolicy) to help people trying to add their own new policies.
00052  *
00053  *  TODO:
00054  *  1. implement the multiple policy support by applying the idea of 
00055  *     multi-policy.
00056  *
00057  */
00058 
00059 #include "dsPolicy.h"
00060 #include "ew.h"
00061 #include "dewp.h"
00062 #include "packet.h"
00063 #include "tcp.h"
00064 #include "random.h"
00065 
00066 // The definition of class PolicyClassifier.
00067 //Constructor.
00068 PolicyClassifier::PolicyClassifier() {
00069   int i;
00070 
00071   policyTableSize = 0;
00072   policerTableSize = 0;
00073 
00074   for (i = 0; i < MAX_POLICIES; i++) 
00075     policy_pool[i] = NULL;
00076 }
00077 
00078 /*-----------------------------------------------------------------------------
00079 void addPolicyEntry()
00080     Adds an entry to policyTable according to the arguments in argv.  A source
00081 and destination node ID must be specified in argv, followed by a policy type
00082 and policy-specific parameters.  Supported policies and their parameters
00083 are:
00084 
00085 Null          InitialCodePoint
00086 TSW2CM        InitialCodePoint  CIR
00087 TSW3CM        InitialCodePoint  CIR  PIR
00088 TokenBucket   InitialCodePoint  CIR  CBS
00089 srTCM         InitialCodePoint  CIR  CBS  EBS
00090 trTCM         InitialCodePoint  CIR  CBS  PIR  PBS
00091 
00092     No error-checking is performed on the parameters.  CIR and PIR should be
00093 specified in bits per second; CBS, EBS, and PBS should be specified in bytes.
00094 
00095     If the Policy Table is full, this method prints an error message.
00096 -----------------------------------------------------------------------------*/
00097 void PolicyClassifier::addPolicyEntry(int argc, const char*const* argv) {
00098   if (policyTableSize == MAX_POLICIES)
00099     printf("ERROR: Policy Table size limit exceeded.\n");
00100   else {
00101     policyTable[policyTableSize].sourceNode = atoi(argv[2]);
00102     policyTable[policyTableSize].destNode = atoi(argv[3]);
00103     policyTable[policyTableSize].codePt = atoi(argv[5]);
00104     policyTable[policyTableSize].arrivalTime = 0;
00105     policyTable[policyTableSize].winLen = 1.0;
00106     
00107     if ((strcmp(argv[4], "Dumb") == 0) || (strcmp(argv[4],"Null") == 0)) {
00108       if(!policy_pool[Null])
00109     policy_pool[Null] = new NullPolicy;
00110       policyTable[policyTableSize].policy_index = Null;   
00111       policyTable[policyTableSize].policer = nullPolicer;
00112       policyTable[policyTableSize].meter = nullMeter;
00113     } else if (strcmp(argv[4], "TSW2CM") == 0) {
00114       if(!policy_pool[TSW2CM])
00115     policy_pool[TSW2CM] = new TSW2CMPolicy;
00116       policyTable[policyTableSize].policy_index = TSW2CM;   
00117       policyTable[policyTableSize].policer = TSW2CMPolicer;
00118       policyTable[policyTableSize].meter = tswTagger;
00119 
00120       policyTable[policyTableSize].cir =
00121     policyTable[policyTableSize].avgRate = (double) atof(argv[6]) / 8.0;
00122       if (argc == 8) policyTable[policyTableSize].winLen = (double) atof(argv[7]);/* mb */
00123     } else if (strcmp(argv[4], "TSW3CM") == 0) {
00124       if(!policy_pool[TSW3CM])
00125     policy_pool[TSW3CM] = new TSW3CMPolicy;
00126       policyTable[policyTableSize].policy_index = TSW3CM;   
00127       policyTable[policyTableSize].policer = TSW3CMPolicer;
00128       policyTable[policyTableSize].meter = tswTagger;
00129 
00130       policyTable[policyTableSize].cir =
00131     policyTable[policyTableSize].avgRate = (double) atof(argv[6]) / 8.0;
00132       policyTable[policyTableSize].pir = (double) atof(argv[7]) / 8.0;
00133     } else if (strcmp(argv[4], "TokenBucket") == 0) {
00134       if(!policy_pool[TB])
00135     policy_pool[TB] = (Policy *) new TBPolicy;
00136       policyTable[policyTableSize].policy_index = TB;   
00137       policyTable[policyTableSize].policer = tokenBucketPolicer;
00138       policyTable[policyTableSize].meter = tokenBucketMeter;
00139       
00140       policyTable[policyTableSize].cir =
00141     policyTable[policyTableSize].avgRate = (double) atof(argv[6]) / 8.0;
00142       policyTable[policyTableSize].cbs =
00143     policyTable[policyTableSize].cBucket = (double) atof(argv[7]);
00144     } else if (strcmp(argv[4], "srTCM") == 0) {
00145       if(!policy_pool[SRTCM])
00146     policy_pool[SRTCM] = new SRTCMPolicy;
00147       policyTable[policyTableSize].policy_index = SRTCM;   
00148       policyTable[policyTableSize].policer = srTCMPolicer;
00149       policyTable[policyTableSize].meter = srTCMMeter;      
00150 
00151       policyTable[policyTableSize].cir =
00152     policyTable[policyTableSize].avgRate = (double) atof(argv[6]) / 8.0;
00153       policyTable[policyTableSize].cbs =
00154     policyTable[policyTableSize].cBucket = (double) atof(argv[7]);
00155       policyTable[policyTableSize].ebs =
00156     policyTable[policyTableSize].eBucket = (double) atof(argv[8]);
00157     } else if (strcmp(argv[4], "trTCM") == 0) {
00158       if(!policy_pool[TRTCM])
00159     policy_pool[TRTCM] = new TRTCMPolicy;
00160       policyTable[policyTableSize].policy_index = TRTCM;  
00161       policyTable[policyTableSize].policer = trTCMPolicer;
00162       policyTable[policyTableSize].meter = trTCMMeter;
00163       
00164       policyTable[policyTableSize].cir =
00165     policyTable[policyTableSize].avgRate = (double) atof(argv[6]) / 8.0;
00166       policyTable[policyTableSize].cbs =
00167     policyTable[policyTableSize].cBucket = (double) atof(argv[7]);
00168       policyTable[policyTableSize].pir = (double) atof(argv[8]) / 8.0;
00169       policyTable[policyTableSize].pbs =
00170     policyTable[policyTableSize].pBucket = (double) atof(argv[9]);
00171     } else if (strcmp(argv[4], "SFD") == 0) {
00172       if(!policy_pool[SFD])
00173     policy_pool[SFD] = new SFDPolicy;
00174       policyTable[policyTableSize].policy_index = SFD;
00175       policyTable[policyTableSize].policer = SFDPolicer;
00176       policyTable[policyTableSize].meter = sfdTagger;
00177 
00178       // Use cir as the transmission size threshold for the moment.
00179       policyTable[policyTableSize].cir = atoi(argv[6]);
00180     } else if (strcmp(argv[4], "EW") == 0) {
00181       if(!policy_pool[EW])
00182     policy_pool[EW] = new EWPolicy();
00183       
00184       ((EWPolicy *)policy_pool[EW])->
00185     init(atoi(argv[6]), atoi(argv[7]), atoi(argv[8]));
00186 
00187       policyTable[policyTableSize].policy_index = EW;
00188       policyTable[policyTableSize].policer = EWPolicer;
00189       policyTable[policyTableSize].meter = ewTagger;
00190   } else if (strcmp(argv[4], "DEWP") == 0) {
00191     if(!policy_pool[DEWP])
00192       policy_pool[DEWP] = new DEWPPolicy;
00193 
00194     ((DEWPPolicy *)policy_pool[DEWP])->
00195       init(atof(argv[6]));
00196     
00197     policyTable[policyTableSize].policy_index = DEWP;
00198     policyTable[policyTableSize].policer = DEWPPolicer;
00199     policyTable[policyTableSize].meter = dewpTagger;
00200   } else {
00201       printf("No applicable policy specified, exit!!!\n");
00202       exit(-1);
00203     }
00204     policyTableSize++;
00205   }
00206 }
00207 
00208 /*-----------------------------------------------------------------------------
00209 policyTableEntry* PolicyClassifier::getPolicyTableEntry(long source, long dest)
00210 Pre: policyTable holds exactly one entry for the specified source-dest pair.
00211 Post: Finds the policyTable array that matches the specified source-dest pair.
00212 Returns: On success, returns a pointer to the corresponding policyTableEntry;
00213   on failure, returns NULL.
00214 Note: the source-destination pair could be one-any or any-any (xuanc)
00215 -----------------------------------------------------------------------------*/
00216 policyTableEntry* PolicyClassifier::getPolicyTableEntry(nsaddr_t source, nsaddr_t dest) {
00217   for (int i = 0; i <= policyTableSize; i++) {
00218     if ((policyTable[i].sourceNode == source) || (policyTable[i].sourceNode == ANY_HOST)) {
00219       if ((policyTable[i].destNode == dest) || (policyTable[i].destNode == ANY_HOST))
00220     return(&policyTable[i]);
00221     }
00222   }
00223   
00224   // !!! Could make a default code point for undefined flows:
00225   printf("ERROR: No Policy Table entry found for Source %d-Destination %d.\n", source, dest);
00226   printPolicyTable();
00227   return(NULL);
00228 }
00229 
00230 /*-----------------------------------------------------------------------------
00231 void addPolicerEntry(int argc, const char*const* argv)
00232 Pre: argv contains a valid command line for adding a policer entry.
00233 Post: Adds an entry to policerTable according to the arguments in argv.  No
00234   error-checking is done on the arguments.  A policer type should be specified,
00235   consisting of one of the names {Null, TSW2CM, TSW3CM, TokenBucket,
00236   srTCM, trTCM}, followed by an initial code point.  Next should be an
00237   out-of-profile code point for policers with two-rate markers; or a yellow and
00238   a red code point for policers with three drop precedences.
00239       If policerTable is full, an error message is printed.
00240 -----------------------------------------------------------------------------*/
00241 void PolicyClassifier::addPolicerEntry(int argc, const char*const* argv) {
00242   //int cur_policy;
00243 
00244 
00245   if (policerTableSize == MAX_CP)
00246     printf("ERROR: Policer Table size limit exceeded.\n");
00247   else {
00248     if ((strcmp(argv[2], "Dumb") == 0) || (strcmp(argv[2],"Null") == 0)) {
00249       if(!policy_pool[Null])
00250     policy_pool[Null] = new NullPolicy;
00251       policerTable[policerTableSize].policer = nullPolicer;      
00252       policerTable[policerTableSize].policy_index = Null;      
00253     } else if (strcmp(argv[2], "TSW2CM") == 0) {
00254       if(!policy_pool[TSW2CM])
00255     policy_pool[TSW2CM] = new TSW2CMPolicy;
00256       policerTable[policerTableSize].policer = TSW2CMPolicer;
00257       policerTable[policerTableSize].policy_index = TSW2CM;      
00258     } else if (strcmp(argv[2], "TSW3CM") == 0) {
00259       if(!policy_pool[TSW3CM])
00260     policy_pool[TSW3CM] = new TSW3CMPolicy;
00261       policerTable[policerTableSize].policer = TSW3CMPolicer;
00262       policerTable[policerTableSize].policy_index = TSW3CM;      
00263     } else if (strcmp(argv[2], "TokenBucket") == 0) {
00264       if(!policy_pool[TB])
00265     policy_pool[TB] = new TBPolicy;
00266       policerTable[policerTableSize].policer = tokenBucketPolicer;
00267       policerTable[policerTableSize].policy_index = TB;      
00268     } else if (strcmp(argv[2], "srTCM") == 0) {
00269       if(!policy_pool[SRTCM])
00270     policy_pool[SRTCM] = new SRTCMPolicy;
00271       policerTable[policerTableSize].policer = srTCMPolicer;
00272       policerTable[policerTableSize].policy_index = SRTCM;      
00273     } else if (strcmp(argv[2], "trTCM") == 0){
00274       if(!policy_pool[TRTCM])
00275     policy_pool[TRTCM] = new TRTCMPolicy;
00276       policerTable[policerTableSize].policer = trTCMPolicer;
00277       policerTable[policerTableSize].policy_index = TRTCM;      
00278     } else if (strcmp(argv[2], "SFD") == 0) {
00279       if(!policy_pool[SFD])
00280     policy_pool[SFD] = new SFDPolicy;
00281       policerTable[policerTableSize].policer = SFDPolicer;
00282       policerTable[policerTableSize].policy_index = SFD;      
00283     } else if (strcmp(argv[2], "EW") == 0) {
00284       if(!policy_pool[EW])
00285     policy_pool[EW] = new EWPolicy;
00286       policerTable[policerTableSize].policer = EWPolicer;
00287       policerTable[policerTableSize].policy_index = EW;      
00288     } else if (strcmp(argv[2], "DEWP") == 0) {
00289       if(!policy_pool[DEWP])
00290     policy_pool[DEWP] = new DEWPPolicy;
00291       policerTable[policerTableSize].policer = DEWPPolicer;
00292       policerTable[policerTableSize].policy_index = DEWP;      
00293     } else {
00294       printf("No applicable policer specified, exit!!!\n");
00295       exit(-1);
00296     }
00297   };
00298   
00299   policerTable[policerTableSize].initialCodePt = atoi(argv[3]);
00300   if (policerTable[policerTableSize].policer == nullPolicer)
00301       policerTable[policerTableSize].downgrade1 = atoi(argv[3]);
00302     else
00303       policerTable[policerTableSize].downgrade1 = atoi(argv[4]);
00304   if (argc == 6)
00305     policerTable[policerTableSize].downgrade2 = atoi(argv[5]);
00306   policerTableSize++;
00307 }
00308 
00309 // Return the entry of Policer table with policerType and initCodePoint matched
00310 policerTableEntry* PolicyClassifier::getPolicerTableEntry(int policy_index, int oldCodePt) {
00311   for (int i = 0; i < policerTableSize; i++)
00312     if ((policerTable[i].policy_index == policy_index) &&
00313     (policerTable[i].initialCodePt == oldCodePt))
00314       return(&policerTable[i]);
00315 
00316   printf("ERROR: No Policer Table entry found for initial code point %d.\n", oldCodePt);
00317   //printPolicerTable();
00318   return(NULL);
00319 }
00320 
00321 /*-----------------------------------------------------------------------------
00322 int mark(Packet *pkt, double minRTT)
00323 Pre: The source-destination pair taken from pkt matches a valid entry in
00324   policyTable.
00325 Post: pkt is marked with an appropriate code point.
00326 -----------------------------------------------------------------------------*/
00327 int PolicyClassifier::mark(Packet *pkt) {
00328   policyTableEntry *policy;
00329   policerTableEntry *policer;
00330   int policy_index;
00331   int codePt;
00332   hdr_ip* iph;
00333   int fid;
00334   
00335   iph = hdr_ip::access(pkt);
00336   fid = iph->flowid();
00337   policy = getPolicyTableEntry(iph->saddr(), iph->daddr());
00338   if (policy) {
00339     codePt = policy->codePt;
00340     policy_index = policy->policy_index;
00341     policer = getPolicerTableEntry(policy_index, codePt);
00342 
00343     // bug pointed by Jason Kenney <jason@linear.engmath.dal.ca>
00344     if (policy_pool[policy_index]) {
00345       policy_pool[policy_index]->applyMeter(policy, pkt);
00346       codePt = policy_pool[policy_index]->applyPolicer(policy, policer, pkt);
00347     }
00348   } else {
00349     printf("The policy object doesn't exist, ERROR!!!\n");
00350     exit(-1);    
00351   }
00352   
00353   iph->prio_ = codePt;
00354   return(codePt);
00355 }
00356 
00357 /*-----------------------------------------------------------------------------
00358 Pre: The command line specifies a source and destination node for which an
00359   RTT-Aware policy exists and a current RTT value for that policy.
00360 Post: The aggRTT field of the appropriate policy is updated to a weighted
00361   average of the previous value and the new RTT value specified in the command
00362   line.  If no matching policy is found, an error message is printed.
00363 -----------------------------------------------------------------------------*/
00364 void PolicyClassifier::updatePolicyRTT(int argc, const char*const* argv) {
00365   policyTableEntry *policy;
00366   
00367   policy = getPolicyTableEntry(atoi(argv[2]), atoi(argv[3]));
00368   if (policy == NULL)
00369     printf("ERROR: cannot update RTT; no existing policy found for Source %d-Desination %d.\n",
00370        atoi(argv[2]), atoi(argv[3]));
00371   else {
00372     policy->winLen = (double) atof(argv[4]);
00373   }
00374 }
00375 
00376 /*-----------------------------------------------------------------------------
00377 Pre: The command line specifies a source and destination node for which a
00378   policy exists that uses a cBucket value.  That policy's cBucket parameter is
00379   currently valid.
00380 Post: The policy's cBucket value is found and returned.
00381 Returns: The value cBucket on success; or -1 on an error.
00382 -----------------------------------------------------------------------------*/
00383 double PolicyClassifier::getCBucket(const char*const* argv) {
00384   policyTableEntry *policy;
00385   
00386   policy = getPolicyTableEntry(atoi(argv[2]), atoi(argv[3]));
00387   if (policy == NULL) {
00388     printf("ERROR: cannot get bucket size; no existing policy found for Source %d-Desination %d.\n",
00389        atoi(argv[2]), atoi(argv[3]));
00390     return(-1);
00391   }
00392   else {
00393     if ((policy->policer == tokenBucketPolicer) || (policy->policer == srTCMPolicer) || (policy->policer == trTCMPolicer))
00394       return(policy->cBucket);
00395     else {
00396       printf("ERROR: cannot get bucket size; the Source %d-Desination %d Policy does not include a Committed Bucket.\n", atoi(argv[2]), atoi(argv[3]));
00397       return(-1);
00398     }
00399   }
00400 }
00401 
00402 //    Prints the policyTable, one entry per line.
00403 void PolicyClassifier::printPolicyTable() {
00404   printf("Policy Table(%d):\n",policyTableSize);
00405   for (int i = 0; i < policyTableSize; i++)
00406     {
00407       switch (policyTable[i].policer) {
00408       case nullPolicer:
00409     printf("Flow (%d to %d): Null policer, ",
00410                policyTable[i].sourceNode,policyTable[i].destNode);
00411     printf("initial code point %d\n", policyTable[i].codePt);
00412     break;
00413       case TSW2CMPolicer:
00414     printf("Flow (%d to %d): TSW2CM policer, ",
00415                policyTable[i].sourceNode,policyTable[i].destNode);
00416     printf("initial code point %d, CIR %.1f bps.\n",
00417                policyTable[i].codePt, policyTable[i].cir * 8);
00418     break;
00419       case TSW3CMPolicer:
00420     printf("Flow (%d to %d): TSW3CM policer, initial code ",
00421                policyTable[i].sourceNode, policyTable[i].destNode);
00422     printf("point %d, CIR %.1f bps, PIR %.1f bytes.\n",
00423                policyTable[i].codePt, policyTable[i].cir * 8,
00424                policyTable[i].pir * 8);
00425     break;
00426       case tokenBucketPolicer:
00427     printf("Flow (%d to %d): Token Bucket policer, ",
00428                policyTable[i].sourceNode,policyTable[i].destNode);
00429     printf("initial code  point %d, CIR %.1f bps, CBS %.1f bytes.\n",
00430                policyTable[i].codePt, policyTable[i].cir * 8,
00431                policyTable[i].cbs);
00432     break;
00433       case srTCMPolicer:
00434     printf("Flow (%d to %d): srTCM policer, initial code ",
00435                policyTable[i].sourceNode, policyTable[i].destNode);
00436     printf("point %d, CIR %.1f bps, CBS %.1f bytes, EBS %.1f bytes.\n",
00437                policyTable[i].codePt, policyTable[i].cir * 8,
00438                policyTable[i].cbs, policyTable[i].ebs);
00439     break;
00440       case trTCMPolicer:
00441     printf("Flow (%d to %d): trTCM policer, initial code ",
00442                policyTable[i].destNode, policyTable[i].sourceNode);
00443     printf("point %d, CIR %.1f bps, CBS %.1f bytes, PIR %.1f bps, ",
00444            policyTable[i].codePt, policyTable[i].cir * 8,
00445                policyTable[i].cbs, policyTable[i].pir * 8);
00446     printf("PBS %.1f bytes.\n", policyTable[i].pbs);
00447     break;
00448       case SFDPolicer:
00449     printf("Flow (%d to %d): SFD policer, ",
00450            policyTable[i].sourceNode,policyTable[i].destNode);
00451     printf("initial code point %d, TH %d bytes.\n",
00452            policyTable[i].codePt, (int)policyTable[i].cir);
00453     break;
00454       case EWPolicer:
00455     printf("Flow (%d to %d): EW policer, ",
00456            policyTable[i].sourceNode,policyTable[i].destNode);
00457     printf("initial code point %d.\n", policyTable[i].codePt);
00458     break;
00459       case DEWPPolicer:
00460     printf("Flow (%d to %d): DEWP policer, ",
00461            policyTable[i].sourceNode,policyTable[i].destNode);
00462     printf("initial code point %d.\n", policyTable[i].codePt);
00463     break;
00464       default:
00465     printf("ERROR: Unknown policer type in Policy Table.\n");
00466       }
00467     }
00468   printf("\n");
00469 }
00470 
00471 // Prints the policerTable, one entry per line.
00472 void PolicyClassifier::printPolicerTable() {
00473   bool threeColor;
00474   
00475   printf("Policer Table:\n");
00476   for (int i = 0; i < policerTableSize; i++) {
00477     threeColor = false;
00478     switch (policerTable[i].policer) {
00479     case nullPolicer:
00480       printf("Null ");
00481       break;
00482     case TSW2CMPolicer:
00483       printf("TSW2CM ");
00484       break;
00485     case TSW3CMPolicer:
00486       printf("TSW3CM ");
00487       threeColor = true;
00488       break;
00489     case tokenBucketPolicer:
00490       printf("Token Bucket ");
00491       break;
00492     case srTCMPolicer:
00493       printf("srTCM ");
00494       threeColor = true;
00495       break;
00496     case trTCMPolicer:
00497       printf("trTCM ");
00498       threeColor = true;
00499       break;
00500     case SFDPolicer:
00501       printf("SFD ");
00502       //printFlowTable();
00503       break;
00504     case EWPolicer:
00505       printf("EW ");
00506       break;
00507     case DEWPPolicer:
00508       printf("DEWP ");
00509       break;
00510     default:
00511       printf("ERROR: Unknown policer type in Policer Table.");
00512     }
00513     
00514     if (threeColor) {
00515       printf("policer code point %d is policed to yellow ",
00516          policerTable[i].initialCodePt);
00517       printf("code point %d and red code point %d.\n",
00518          policerTable[i].downgrade1,
00519          policerTable[i].downgrade2);
00520     } else
00521       printf("policer code point %d is policed to code point %d.\n",
00522          policerTable[i].initialCodePt,
00523          policerTable[i].downgrade1);
00524   }
00525   printf("\n");
00526 }
00527 
00528 // The beginning of the definition of the NullPolicy
00529 // NullPolicy will do nothing, but is also a good example to show how to add 
00530 // new policy.
00531 
00532 /*-----------------------------------------------------------------------------
00533 void NullPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00534 Do nothing
00535 -----------------------------------------------------------------------------*/
00536 void NullPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00537   policy->arrivalTime = Scheduler::instance().clock();  
00538 }
00539 
00540 /*-----------------------------------------------------------------------------
00541 int DumbPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet *pkt)
00542 Always return the initial codepoint.
00543 -----------------------------------------------------------------------------*/
00544 int NullPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet *pkt) {
00545   return(policer->initialCodePt);
00546 }
00547 
00548 // The end of NullPolicy
00549 
00550 // The beginning of the definition of TSW2CM
00551 /*-----------------------------------------------------------------------------
00552 void TSW2CMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00553 Pre: policy's variables avgRate, arrivalTime, and winLen hold valid values; and
00554   pkt points to a newly-arrived packet.
00555 Post: Adjusts policy's TSW state variables avgRate and arrivalTime (also called
00556   tFront) according to the specified packet.
00557 Note: See the paper "Explicit Allocation of Best effor Delivery Service" (David
00558   Clark and Wenjia Fang), Section 3.3, for a description of the TSW Tagger.
00559 -----------------------------------------------------------------------------*/
00560 void TSW2CMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00561   double now, bytesInTSW, newBytes;
00562   hdr_cmn* hdr = hdr_cmn::access(pkt);
00563   
00564   bytesInTSW = policy->avgRate * policy->winLen;
00565   newBytes = bytesInTSW + (double) hdr->size();
00566   now = Scheduler::instance().clock();
00567   policy->avgRate = newBytes / (now - policy->arrivalTime + policy->winLen);
00568   policy->arrivalTime = now;
00569 }
00570 
00571 /*-----------------------------------------------------------------------------
00572 int TSW2CMPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet *pkt)
00573 Pre: policy points to a policytableEntry that is using the TSW2CM policer and
00574   whose state variables (avgRate and cir) are up to date.
00575 Post: If policy's avgRate exceeds its CIR, this method returns an out-of-profile
00576   code point with a probability of ((rate - CIR) / rate).  If it does not
00577   downgrade the code point, this method simply returns the initial code point.
00578 Returns: A code point to apply to the current packet.
00579 Uses: Method downgradeOne().
00580 -----------------------------------------------------------------------------*/
00581 int TSW2CMPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet *pkt) {
00582   if ((policy->avgRate > policy->cir)
00583       && (Random::uniform(0.0, 1.0) <= (1-(policy->cir/policy->avgRate)))) {
00584     return(policer->downgrade1);
00585   }
00586   else {
00587     return(policer->initialCodePt);
00588   }
00589 }
00590 
00591 // The end of TSW2CM
00592 
00593 // The Beginning of TSW3CM
00594 /*-----------------------------------------------------------------------------
00595 void TSW3CMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00596 Pre: policy's variables avgRate, arrivalTime, and winLen hold valid values; and
00597   pkt points to a newly-arrived packet.
00598 Post: Adjusts policy's TSW state variables avgRate and arrivalTime (also called
00599   tFront) according to the specified packet.
00600 Note: See the paper "Explicit Allocation of Best effor Delivery Service" (David
00601   Clark and Wenjia Fang), Section 3.3, for a description of the TSW Tagger.
00602 -----------------------------------------------------------------------------*/
00603 void TSW3CMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00604   double now, bytesInTSW, newBytes;
00605   hdr_cmn* hdr = hdr_cmn::access(pkt);
00606   
00607   bytesInTSW = policy->avgRate * policy->winLen;
00608   newBytes = bytesInTSW + (double) hdr->size();
00609   now = Scheduler::instance().clock();
00610   policy->avgRate = newBytes / (now - policy->arrivalTime + policy->winLen);
00611   policy->arrivalTime = now;
00612 }
00613 
00614 /*-----------------------------------------------------------------------------
00615 int TSW3CMPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet *pkt)
00616 Pre: policy points to a policytableEntry that is using the TSW3CM policer and
00617   whose state variables (avgRate, cir, and pir) are up to date.
00618 Post: Sets code points with the following probabilities when rate > PIR:
00619 
00620           red:    (rate - PIR) / rate
00621           yellow: (PIR - CIR) / rate
00622           green:  CIR / rate
00623 
00624 and with the following code points when CIR < rate <= PIR:
00625 
00626           red:    0
00627           yellow: (rate - CIR) / rate
00628           green:  CIR / rate
00629 
00630     When rate is under CIR, a packet is always marked green.
00631 Returns: A code point to apply to the current packet.
00632 Uses: Methods downgradeOne() and downgradeTwo().
00633 -----------------------------------------------------------------------------*/
00634 int TSW3CMPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet *pkt) {
00635   double rand = policy->avgRate * (1.0 - Random::uniform(0.0, 1.0));
00636   
00637   if (rand > policy->pir)
00638     return (policer->downgrade2);
00639   else if (rand > policy->cir)
00640     return(policer->downgrade1);
00641   else
00642     return(policer->initialCodePt);
00643 }
00644  
00645 // End of TSW3CM
00646 
00647 // Begin of Token Bucket.
00648 /*-----------------------------------------------------------------------------
00649 void TBPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00650 Pre: policy's variables cBucket, cir, cbs, and arrivalTime hold valid values.
00651 Post: Increments policy's Token Bucket state variable cBucket according to the
00652   elapsed time since the last packet arrival.  cBucket is filled at a rate equal  to CIR, capped at an upper bound of CBS.
00653   This method also sets arrivalTime equal to the current simulator time.
00654 -----------------------------------------------------------------------------*/
00655 void TBPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00656   double now = Scheduler::instance().clock();
00657   double tokenBytes;
00658 
00659   tokenBytes = (double) policy->cir * (now - policy->arrivalTime);
00660   if (policy->cBucket + tokenBytes <= policy->cbs)
00661    policy->cBucket += tokenBytes;
00662   else
00663    policy->cBucket = policy->cbs;
00664   policy->arrivalTime = now;
00665 }
00666 
00667 /*----------------------------------------------------------------------------
00668 int TBPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt,
00669         Packet* pkt)
00670 Pre: policy points to a policytableEntry that is using the Token Bucket policer
00671 and whose state variable (cBucket) is up to date.  pkt points to a
00672 newly-arrived packet.
00673 Post: If policy's cBucket is at least as large as pkt's size, cBucket is
00674 decremented by that size and the initial code point is retained.  Otherwise,
00675 the code point is downgraded.
00676 Returns: A code point to apply to the current packet.
00677 Uses: Method downgradeOne().
00678 -----------------------------------------------------------------------------*/
00679 int TBPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet* pkt) {
00680   hdr_cmn* hdr = hdr_cmn::access(pkt);
00681 
00682   double size = (double) hdr->size();
00683 
00684   if ((policy->cBucket - size) >= 0) {
00685     policy->cBucket -= size;
00686     return(policer->initialCodePt);
00687   } else{
00688     return(policer->downgrade1);
00689   }
00690 }
00691 
00692 // End of Tocken Bucket.
00693 
00694 // Begining of SRTCM
00695 /*-----------------------------------------------------------------------------
00696 void SRTCMPolicy::applyMeter(policyTableEntry *policy)
00697 Pre: policy's variables cBucket, eBucket, cir, cbs, ebs, and arrivalTime hold
00698   valid values.
00699 Post: Increments policy's srTCM state variables cBucket and eBucket according
00700   to the elapsed time since the last packet arrival.  cBucket is filled at a
00701   rate equal to CIR, capped at an upper bound of CBS.  When cBucket is full
00702   (equal to CBS), eBucket is filled at a rate equal to CIR, capped at an upper
00703   bound of EBS.
00704       This method also sets arrivalTime equal to the current
00705   simulator time.
00706 Note: See the Internet Draft, "A Single Rate Three Color Marker" (Heinanen et
00707   al; May, 1999) for a description of the srTCM.
00708 -----------------------------------------------------------------------------*/
00709 void SRTCMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00710   double now = Scheduler::instance().clock();
00711   double tokenBytes;
00712   
00713   tokenBytes = (double) policy->cir * (now - policy->arrivalTime);
00714   if (policy->cBucket + tokenBytes <= policy->cbs)
00715     policy->cBucket += tokenBytes;
00716   else {
00717     tokenBytes = tokenBytes - (policy->cbs - policy->cBucket);
00718     
00719     policy->cBucket = policy->cbs;
00720     if (policy->eBucket + tokenBytes <= policy->ebs)
00721       policy->eBucket += tokenBytes;
00722     else
00723       policy->eBucket = policy->ebs;
00724   }
00725   policy->arrivalTime = now;
00726 }
00727 
00728 /*-----------------------------------------------------------------------------
00729 int SRTCMPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet* pkt)
00730 Pre: policy points to a policyTableEntry that is using the srTCM policer and
00731   whose state variables (cBucket and eBucket) are up to date.  pkt points to a
00732   newly-arrived packet.
00733 Post: If policy's cBucket is at least as large as pkt's size, cBucket is
00734   decremented by that size and the initial code point is retained.  Otherwise,
00735   if eBucket is at least as large as the packet, eBucket is decremented and the
00736   yellow code point is returned.  Otherwise, the red code point is returned.
00737 Returns: A code point to apply to the current packet.
00738 Uses: Method downgradeOne() and downgradeTwo().
00739 Note: See the Internet Draft, "A Single Rate Three Color Marker" (Heinanen et
00740   al; May, 1999) for a description of the srTCM.
00741 -----------------------------------------------------------------------------*/
00742 int SRTCMPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet* pkt) {
00743 
00744   hdr_cmn* hdr = hdr_cmn::access(pkt);
00745   double size = (double) hdr->size();
00746   
00747   if ((policy->cBucket - size) >= 0) {
00748     policy->cBucket -= size;
00749     return(policer->initialCodePt);
00750   } else {
00751     if ((policy->eBucket - size) >= 0) {
00752       policy->eBucket -= size;
00753       return(policer->downgrade1);
00754     } else
00755       return(policer->downgrade2);
00756   }
00757 }
00758 
00759 // End of SRTCM
00760 
00761 // Beginning of TRTCM
00762 /*----------------------------------------------------------------------------
00763 void TRTCMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00764 Pre: policy's variables cBucket, pBucket, cir, pir, cbs, pbs, and arrivalTime
00765   hold valid values.
00766 Post: Increments policy's trTCM state variables cBucket and pBucket according
00767   to the elapsed time since the last packet arrival.  cBucket is filled at a
00768   rate equal to CIR, capped at an upper bound of CBS.  pBucket is filled at a
00769   rate equal to PIR, capped at an upper bound of PBS.
00770       This method also sets arrivalTime equal to the current simulator time.
00771 Note: See the Internet Draft, "A Two Rate Three Color Marker" (Heinanen et al;
00772   May, 1999) for a description of the srTCM.
00773 ---------------------------------------------------------------------------*/
00774 void TRTCMPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00775   double now = Scheduler::instance().clock();
00776   double tokenBytes;
00777   tokenBytes = (double) policy->cir * (now - policy->arrivalTime);
00778   if (policy->cBucket + tokenBytes <= policy->cbs)
00779     policy->cBucket += tokenBytes;
00780   else
00781     policy->cBucket = policy->cbs;
00782   
00783   tokenBytes = (double) policy->pir * (now - policy->arrivalTime);
00784   if (policy->pBucket + tokenBytes <= policy->pbs)
00785     policy->pBucket += tokenBytes;
00786   else
00787     policy->pBucket = policy->pbs;
00788   
00789   policy->arrivalTime = now;
00790 }
00791 
00792 /*----------------------------------------------------------------------------
00793 int TRTCMPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet* pkt)
00794 Pre: policy points to a policyTableEntry that is using the trTCM policer and
00795   whose state variables (cBucket and pBucket) are up to date.  pkt points to a
00796   newly-arrived packet.
00797 Post: If policy's pBucket is smaller than pkt's size, the red code point is
00798   retained.  Otherwise, if cBucket is smaller than the packet size, the yellow
00799   code point is returned and pBucket is decremented.  Otherwise, the packet
00800   remains green and both buckets are decremented.
00801 Returns: A code point to apply to the current packet.
00802 Uses: Method downgradeOne() and downgradeTwo().
00803 Note: See the Internet Draft, "A Two Rate Three Color Marker" (Heinanen et al;
00804   May, 1999) for a description of the srTCM.
00805 -----------------------------------------------------------------------------*/
00806 int TRTCMPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet* pkt) {
00807   hdr_cmn* hdr = hdr_cmn::access(pkt);
00808   double size = (double) hdr->size();
00809   
00810   if ((policy->pBucket - size) < 0)
00811     return(policer->downgrade2);
00812   else {
00813     if ((policy->cBucket - size) < 0) {
00814       policy->pBucket -= size;
00815       return(policer->downgrade1);
00816     } else {
00817       policy->cBucket -= size;
00818       policy->pBucket -= size;
00819       return(policer->initialCodePt);
00820     }
00821   }
00822 }
00823 // End of TRTCM
00824 
00825 // Beginning of SFD
00826 //Constructor.
00827 SFDPolicy::SFDPolicy() : Policy() {
00828   flow_table.head = NULL;
00829   flow_table.tail = NULL;
00830 }
00831 
00832 //Deconstructor.
00833 SFDPolicy::~SFDPolicy(){
00834   struct flow_entry *p, *q;
00835   p = q = flow_table.head;
00836   while (p) {
00837     printf("free flow: %d\n", p->fid);
00838     q = p;
00839     p = p->next;
00840     free(q);
00841   }
00842 
00843   p = q = NULL;
00844   flow_table.head = flow_table.tail = NULL;
00845 }
00846 
00847 /*-----------------------------------------------------------------------------
00848  void SFDPolicy::applyMeter(policyTableEntry *policy, Packet *pkt)
00849  Flow states are kept in a linked list.
00850  Record how many bytes has been sent per flow and check if there is any flow
00851  timeout.
00852 -----------------------------------------------------------------------------*/
00853 void SFDPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
00854   int fid, src_id, dst_id;
00855   struct flow_entry *p, *q, *new_entry;
00856 
00857   double now = Scheduler::instance().clock();
00858   hdr_cmn* hdr = hdr_cmn::access(pkt);
00859   hdr_ip* iph = hdr_ip::access(pkt);
00860   fid = iph->flowid();
00861   dst_id = iph->daddr();
00862   src_id = iph->saddr();
00863 
00864   //  printf("enter applyMeter\n");
00865   //  printFlowTable();
00866 
00867   p = q = flow_table.head;
00868   while (p) {
00869     // Check if the flow has been recorded before.
00870     if (p->fid == fid) {
00871     //if (p->src_id == src_id && p->dst_id == dst_id ) {
00872       p->last_update = now;
00873       p->bytes_sent += hdr->size();
00874       return;
00875     } else if (p->last_update + FLOW_TIME_OUT < now){
00876       // The coresponding flow is expired.      
00877       if (p == flow_table.head){
00878     if (p == flow_table.tail) {
00879       flow_table.head = flow_table.tail = NULL;
00880       free(p);
00881       p = q = NULL;
00882     } else {
00883       flow_table.head = p->next;
00884       free(p);
00885       p = q = flow_table.head;
00886     }
00887       } else {
00888     q->next = p->next;
00889     if (p == flow_table.tail)
00890       flow_table.tail = q;
00891     free(p);
00892     p = q->next;
00893       }
00894     } else {
00895       q = p;
00896       p = q->next;
00897     }
00898   }
00899   
00900   // This is the firt time the flow shown up
00901   if (!p) {
00902     new_entry = new flow_entry;
00903     new_entry->fid = fid;
00904     new_entry->src_id = src_id;
00905     new_entry->dst_id = dst_id;
00906     new_entry->last_update = now;
00907     new_entry->bytes_sent = hdr->size();
00908     new_entry->count = 0;
00909     new_entry->next = NULL;
00910     
00911     // always insert the new entry to the tail.
00912     if (flow_table.tail)
00913       flow_table.tail->next = new_entry;
00914     else
00915       flow_table.head = new_entry;
00916     flow_table.tail = new_entry;
00917   }
00918   
00919   //  printf("leave applyMeter\n");
00920   return;
00921 }
00922 
00923 /*-----------------------------------------------------------------------------
00924 void SFDPolicy::applyPolicer(policyTableEntry *policy, int initialCodePt, Packet *pkt) 
00925     Prints the policyTable, one entry per line.
00926 -----------------------------------------------------------------------------*/
00927 int SFDPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet *pkt) {
00928   int fid, src_id, dst_id;
00929   struct flow_entry *p;
00930 
00931   hdr_ip* iph = hdr_ip::access(pkt);
00932   fid = iph->flowid();
00933   dst_id = iph->daddr();
00934   src_id = iph->saddr();
00935 
00936   //  printf("enter applyPolicer\n");
00937   //printFlowTable();
00938   
00939   p = flow_table.head;
00940   while (p) {
00941     // Check if the flow has been recorded before.
00942     if (p->fid == iph->flowid()) {
00943       //if (p->src_id == src_id && p->dst_id == dst_id) {
00944       if (p->bytes_sent > policy->cir) {
00945     // Use downgrade2 code to judge how to penalize out-profile packets.
00946     if (policer->downgrade2 == 0) {
00947       // Penalize every packet beyond th.
00948       //printf("leave applyPolicer  %d, every downgrade\n", p->fid);
00949       return(policer->downgrade1);
00950     } else if (policer->downgrade2 == 1) {
00951       // Randomized penalization.
00952       if (Random::uniform(0.0, 1.0) > (1 - (policy->cir/p->bytes_sent))) {
00953         //printf("leave applyPolicer %d, random initial.\n", p->fid);
00954         return(policer->initialCodePt);
00955       } else {
00956         //printf("leave applyPolicer %d, random, downgrade\n", p->fid);
00957         return(policer->downgrade1);
00958       }
00959     } else {
00960       // Simple scheduling on penalization.
00961       if (p->count == 5) {
00962         // Penalize 4 out of every 5 packets.
00963         p->count = 0;
00964         //printf("leave applyPolicer %d, initial, %d\n", p->fid, p->count);
00965         return(policer->initialCodePt);
00966       } else {
00967         p->count++;
00968         //printf("leave applyPolicer %d, downgrade, %d\n", p->fid, p->count);
00969         return(policer->downgrade1);
00970       }
00971     }
00972       } else {
00973     //  printf("leave applyPolicer, initial\n");
00974     return(policer->initialCodePt);
00975       }
00976     }
00977     p = p->next;
00978   }
00979   
00980   // Can't find the record for this flow.
00981   if (!p) {
00982     printf ("MISS: no flow %d (%d, %d) in the table\n", fid, src_id, dst_id);
00983     printFlowTable();
00984 };
00985   
00986   //  printf("leave applyPolicer, init but problem...\n");
00987   return(policer->initialCodePt);
00988 }
00989 
00990 //    Prints the flowTable, one entry per line.
00991 void SFDPolicy::printFlowTable() {
00992   struct flow_entry *p;
00993   printf("Flow table:\n");
00994 
00995   p = flow_table.head;
00996   while (p) {
00997     printf("flow id: %d [%d %d], bytesSent: %d, last_update: %f\n", 
00998        p->fid, p->src_id, p->dst_id, p->bytes_sent, p->last_update);
00999     p = p-> next;
01000   }
01001   p = NULL;
01002   printf("\n");
01003 }
01004 // End of SFD

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