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 }