REDQueue.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 
00019 #include <omnetpp.h>
00020 #include "REDQueue.h"
00021 
00022 
00023 Define_Module(REDQueue);
00024 
00025 void REDQueue::initialize()
00026 {
00027     PassiveQueueBase::initialize();
00028     queue.setName("l2queue");
00029 
00030     avgQlenVec.setName("avg queue length");
00031     qlenVec.setName("queue length");
00032     dropVec.setName("drops");
00033 
00034     // configuration
00035     wq = par("wq");
00036     minth = par("minth");
00037     maxth = par("maxth");
00038     maxp = par("maxp");
00039     pkrate = par("pkrate");
00040 
00041     outGate = gate("out");
00042 
00043     // state
00044     avg = 0;
00045     q_time = 0;
00046     count = -1;
00047     numEarlyDrops = 0;
00048 
00049     WATCH(avg);
00050     WATCH(q_time);
00051     WATCH(count);
00052     WATCH(numEarlyDrops);
00053 }
00054 
00055 bool REDQueue::enqueue(cMessage *msg)
00056 {
00057     //"
00058     // for each packet arrival
00059     //    calculate the new average queue size avg:
00060     //        if the queue is nonempty
00061     //            avg <- (1-wq)*avg + wq*q
00062     //        else
00063     //            m <- f(time-q_time)
00064     //            avg <- (1-wq)^m * avg
00065     //"
00066     if (!queue.empty())
00067     {
00068         avg = (1-wq)*avg + wq*queue.length();
00069     }
00070     else
00071     {
00072         // Note: f() is supposed to estimate the number of packets
00073         // that could have arrived during the idle interval (see Section 11
00074         // of the paper). We use pkrate for this purpose.
00075         double m = SIMTIME_DBL(simTime()-q_time) * pkrate;
00076         avg = pow(1-wq, m) * avg;
00077     }
00078 
00079     // statistics
00080     avgQlenVec.record(avg);
00081 
00082     //"
00083     //    if minth <= avg < maxth
00084     //        increment count
00085     //        calculate probability pa:
00086     //            pb <- maxp*(avg-minth) / (maxth-minth)
00087     //            pa <- pb / (1-count*pb)
00088     //        with probability pa:
00089     //            mark the arriving packet
00090     //            count <- 0
00091     //    else if maxth <= avg
00092     //        mark the arriving packet
00093     //        count <- 0
00094     //    else count <- -1
00095     //"
00096 
00097     bool mark = false;
00098     if (minth<=avg && avg<maxth)
00099     {
00100         count++;
00101         double pb = maxp*(avg-minth) / (maxth-minth);
00102         double pa = pb / (1-count*pb);
00103         if (dblrand() < pa)
00104         {
00105             EV << "Random early packet drop (avg queue len=" << avg << ", pa=" << pa << ")\n";
00106             mark = true;
00107             count = 0;
00108             numEarlyDrops++;
00109         }
00110     }
00111     else if (maxth <= avg)
00112     {
00113         EV << "Avg queue len " << avg << " >= maxth, dropping packet.\n";
00114         mark = true;
00115         count = 0;
00116     }
00117     else
00118     {
00119         count = -1;
00120     }
00121 
00122     // carry out decision
00123     if (mark || queue.length()>=maxth) // maxth is also the "hard" limit
00124     {
00125         delete msg;
00126         dropVec.record(1);
00127         return true;
00128     }
00129     else
00130     {
00131         queue.insert(msg);
00132         qlenVec.record(queue.length());
00133         return false;
00134     }
00135 }
00136 
00137 cMessage *REDQueue::dequeue()
00138 {
00139     if (queue.empty())
00140         return NULL;
00141 
00142     //"
00143     // when queue becomes empty
00144     //    q_time <- time
00145     //"
00146     cMessage *pk = (cMessage *)queue.pop();
00147     if (queue.length()==0)
00148         q_time = simTime();
00149 
00150     // statistics
00151     qlenVec.record(queue.length());
00152 
00153     return pk;
00154 }
00155 
00156 void REDQueue::sendOut(cMessage *msg)
00157 {
00158     send(msg, outGate);
00159 }
00160 
00161 void REDQueue::finish()
00162 {
00163     PassiveQueueBase::finish();
00164     recordScalar("packets dropped early by RED", numEarlyDrops);
00165 }