Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

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

Generated on Tue Apr 20 12:14:14 2004 for NS2.26SourcesOriginal by doxygen 1.3.3