|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2011 Martin Danko 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU 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 General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 // 00018 00019 00020 #ifndef __ANSA_QOS_SYSTEM_H 00021 #define __ANSA_QOS_SYSTEM_H 00022 00023 #include <vector> 00024 #include <iostream> 00025 #include <omnetpp.h> 00026 #include "AnsaQosClassifiers.h" 00027 #include "PassiveQueueBase.h" 00028 00029 00030 namespace ANSAQOS { 00031 00032 /* Vycet typov fronty */ 00033 enum QueueType { 00034 Q_FIFO = 1, 00035 Q_PQ = 2, 00036 Q_CQ = 3, 00037 Q_WFQ = 4, 00038 Q_CBWFQ = 5, 00039 Q_WRED = 6 00040 }; 00041 00042 /* Vycet typov podfronty */ 00043 enum SubQueueType { 00044 S_FIFO = 1, 00045 S_WFQ = 2, 00046 S_WRED = 3 00047 }; 00048 00049 /* Vycet typov vysledku operacie vlozenia do fronty */ 00050 enum EnqueueingResult { 00051 QUEUED = 1, 00052 NOMATCH = 2, 00053 NOTQUEUED = 3 00054 }; 00055 00056 /* Trieda pre uchovanie parametrov fronty */ 00057 class QueueConfig { 00058 private: 00059 QueueType qt; // typ fronty 00060 std::string listId; // ID Priority alebo Custom listu 00061 int numQueues; // aktualny pocet front 00062 int maxActQueues; // maximalny pocet aktivnych front 00063 int maxQueues; // maximalny limit poctu front 00064 int currentHold; // aktualny celkovy pocet paketov vo fronte 00065 int holdCapacity; // maximalny limit poctu paketov vo fronte 00066 int cdt; // Congestive Discard Threshold pre WFQ 00067 int droped; // pocet zahodenych paketov 00068 int currentCQQueueId; // ID prave obsluhovanej podfronty u CQ 00069 int defaultQueueId; // defaultna fronta u PQ a CQ 00070 00071 cOutVector *qlenVec; // ukazovatel na vektor pre zaznamenanie dlzky fronty 00072 cOutVector *dropVec; // ukazovatel na vektor pre zaznamenanie zahodenych paketov 00073 00074 public: 00075 QueueConfig() {currentHold = 0;} 00076 00077 void setQueueType(QueueType type) {qt = type;} 00078 QueueType getQueueType() {return qt;} 00079 void setListId(std::string id) {listId = id;} 00080 std::string getListId() {return listId;} 00081 void setNumQueues(int num) {numQueues = num;} 00082 int getNumQueues() {return numQueues;} 00083 void setMaxActQueues(int num) {maxActQueues = num;} 00084 int getMaxActQueues() {return maxActQueues;} 00085 void setMaxQueues(int num) {maxQueues = num;} 00086 int getMaxQueues() {return maxQueues;} 00087 void setCurrentHold(int num) {currentHold = num;} 00088 int getCurrentHold() {return currentHold;} 00089 void setHoldCapacity(int num) {holdCapacity = num;} 00090 void addHoldCapacity(int num) {holdCapacity += num;} 00091 int getHoldCapacity() {return holdCapacity;} 00092 void setCdt(int num) {cdt = num;} 00093 int getCdt() {return cdt;} 00094 void setDroped(int num) {droped = num;} 00095 int getDroped() {return droped;} 00096 void setCurrentCQQueueId(int id) {currentCQQueueId = id;} 00097 void addCurrentCQQueueId() {currentCQQueueId = (currentCQQueueId + 1) % 16;} 00098 int getCurrentCQQueueId() {return currentCQQueueId;} 00099 void setDefaultQueueId(int id) {defaultQueueId = id;} 00100 int getDefaultQueueId() {return defaultQueueId;} 00101 void setVectorPointer(cOutVector* l, cOutVector* d) { qlenVec = l; dropVec = d;} 00102 00103 void addNumQueues() {++numQueues; maxActQueues = (numQueues < maxActQueues ? maxActQueues:numQueues);} 00104 void remNumQueues() {--numQueues;} 00105 void addCurrentHold() {++currentHold; qlenVec->record(currentHold);} 00106 void remCurrentHold() {--currentHold; qlenVec->record(currentHold);} 00107 void addDroped() {++droped; dropVec->record(1);} 00108 00109 /* Inicializacia parametrov FIFO fronty */ 00110 void setVectorName (QueueType type); 00111 00112 void setFIFO(int hold) {qt=Q_FIFO; currentHold = droped = 0; maxQueues = numQueues = 1; 00113 holdCapacity = cdt = hold; setVectorName(Q_FIFO);} 00114 /* Inicializacia parametrov WFQ fronty */ 00115 void setWFQ() {qt=Q_WFQ; numQueues = maxActQueues = currentHold = droped = 0; 00116 maxQueues = 256; holdCapacity = 1000; cdt = 64; setVectorName(Q_WFQ);} 00117 /* Inicializacia parametrov PQ fronty */ 00118 void setPQ() {qt=Q_PQ; currentHold = droped = holdCapacity = cdt = 0; 00119 maxQueues = numQueues = 4; defaultQueueId = 3; setVectorName(Q_PQ);} 00120 /* Inicializacia parametrov CQ fronty */ 00121 void setCQ() {qt=Q_CQ; currentHold = droped = holdCapacity = cdt = 0; 00122 maxQueues = numQueues = 16; defaultQueueId = currentCQQueueId= 1; setVectorName(Q_CQ);} 00123 }; 00124 00125 00126 /* Trieda reprezentujuca paket zo sekvencnym cislom */ 00127 class SNPacket { 00128 00129 private: 00130 cMessage *msg; // ukazovatel na paket 00131 int sn; // sekvencne cislo paketu 00132 00133 public: 00134 SNPacket() {msg = NULL; sn = 0;} 00135 SNPacket(cMessage *c_msg, int c_sn) {msg = c_msg; sn = c_sn;} 00136 00137 int getSn() {return sn;} 00138 void setSn(int n_sn) {sn = n_sn;} 00139 void substractSn(int subNum) {sn = sn - subNum;} 00140 00141 cMessage *getMsg() {return msg;} 00142 void setMsg(cMessage *n_msg) {msg = n_msg;} 00143 }; 00144 00145 00146 /* Trieda reprezentujuca podfrontu */ 00147 class SubQueue { 00148 00149 private: 00150 Classifier *clsfr; // klasifikator pre podfrontu 00151 QueueType qt; // typ fronty, ktorej je podfronta clenom 00152 SubQueueType sbqt; // typ podfronty 00153 int queueId; // ID fronty 00154 int maxLength; // maximalna dlzka podfronty 00155 int lastSn; // sekvencne cislo posledneho paketu fronty 00156 int droped; // pocet zahodenych paketov v podfronte 00157 int weight; // vaha podfronty 00158 int actualBytes; // aktualny volny pocet bajtov pre CQ alg. 00159 00160 cOutVector *qlenVec; // vektor pre zaznamenanie dlzky fronty 00161 cOutVector *dropVec; // vektor pre zaznamenanie zahodenych paketov 00162 00163 std::vector<SNPacket> snPackets; // ulozene pakety v podfronte 00164 00165 00166 public: 00167 00168 SubQueue() {lastSn = 0; qlenVec = dropVec = NULL;} 00169 SubQueue(cMessage *msg, int cdt); 00170 SubQueue(QueueType t1, SubQueueType t2, int len, cXMLElement& clsfrConfig); 00171 00172 void clearSubQueue(); 00173 00174 void setQueueType(QueueType type) {qt = type;} 00175 QueueType getQueueType() {return qt;} 00176 void setSubQueueType(SubQueueType type) {sbqt = type;} 00177 SubQueueType getSubQueueType() {return sbqt;} 00178 void setQueueId(int id) {queueId = id;} 00179 int getQueueId() {return queueId;} 00180 void setMaxLength(int len) {maxLength = len;} 00181 int getMaxLength() {return maxLength;} 00182 void setLastSn(int n_sn) {lastSn = n_sn;} 00183 int getLastSn() {return lastSn;} 00184 void addDroped() {++droped; } 00185 int getDroped() {return droped;} 00186 void setWeight(cMessage *msg); 00187 void setWeight(int w) {weight = w;} 00188 int getWeight() {return weight;} 00189 void setActualBytes() {actualBytes = weight;} 00190 void setActualBytes(int b) {actualBytes = b;} 00191 void addActualBytes(int b) {actualBytes += b;} 00192 void remActualBytes(int b) {actualBytes -= b;} 00193 int getActualBytes() {return actualBytes;} 00194 std::string getClassifierInfo() {return clsfr->info();} 00195 void setVectorPointer(cOutVector* l, cOutVector* d) { qlenVec = l; dropVec = d;} 00196 void updateVectorLenght() {if(qlenVec) qlenVec->record(snPackets.size());} 00197 void updateVectorDrop() {if(dropVec) dropVec->record(1);} 00198 00199 int getQueueLength() {return snPackets.size();} 00200 bool isQueueEmpty() {return getQueueLength()>0 ? false : true ;} 00201 void substractSnFromAll(int subNum); 00202 int getLowestSn() {return (snPackets.front()).getSn();} 00203 int calculateSn(cMessage *msg); 00204 00205 short enqueue(cMessage *msg, bool classify); 00206 cMessage *dequeue(); 00207 }; 00208 00209 /* 00210 * Pretazenie operatoru "<<" pre vypis stavu podfronty do grafickeho rozhrania 00211 */ 00212 00213 inline std::ostream& operator<< (std::ostream& ostr, SubQueue& sbq) 00214 { 00215 switch (sbq.getQueueType()) 00216 { 00217 case ANSAQOS::Q_FIFO : 00218 ostr << "No subqueues in FIFO queue"; 00219 break; 00220 case ANSAQOS::Q_WFQ : 00221 ostr << "(depth/weight/total drops) "; 00222 ostr << sbq.getQueueLength() << "/"; 00223 ostr << sbq.getWeight() << "/"; 00224 ostr << sbq.getDroped() << " "; 00225 ostr << sbq.getClassifierInfo(); 00226 break; 00227 case ANSAQOS::Q_PQ : 00228 switch (sbq.getQueueId()) 00229 { 00230 case 1 : 00231 ostr << "High: "; 00232 break; 00233 case 2 : 00234 ostr << "Medium: "; 00235 break; 00236 case 3 : 00237 ostr << "Normal: "; 00238 break; 00239 case 4 : 00240 ostr << "Low: "; 00241 break; 00242 default: 00243 ostr << "Error"; 00244 } 00245 ostr << sbq.getQueueLength() << "/"; 00246 ostr << sbq.getMaxLength() << "/"; 00247 ostr << sbq.getDroped() ; 00248 ostr << " (size/max/drops) Classifier: "; 00249 ostr << sbq.getClassifierInfo(); 00250 00251 break; 00252 case ANSAQOS::Q_CQ : 00253 ostr << "Queue "<< sbq.getQueueId() <<": "; 00254 ostr << sbq.getQueueLength() << "/"; 00255 ostr << sbq.getMaxLength() << "/"; 00256 ostr << sbq.getDroped() ; 00257 ostr << " (size/max/drops) ByteCount: "; 00258 ostr << sbq.getActualBytes() << "/"; 00259 ostr << sbq.getWeight() ; 00260 ostr << " (actual/max) Classifier: "; 00261 ostr << sbq.getClassifierInfo(); 00262 break; 00263 default : 00264 ostr << "Error"; 00265 } 00266 00267 return ostr; 00268 } 00269 00270 } 00271 00272 typedef std::vector<ANSAQOS::SubQueue> AnsaSubQueues; 00273 00274 /* Trieda definujuca modul s frontami FIFO, WFQ, PQ, CQ */ 00275 class INET_API AnsaQosSystem : public PassiveQueueBase 00276 { 00277 protected: 00278 00279 AnsaSubQueues subQueues; // podfronty 00280 cGate *outGate; // vystupna brana modulu 00281 00282 cOutVector qlenVec; // vektor pre zaznamenanie dlzky fronty 00283 cOutVector dropVec; // vektor pre zaznamenanie zahodenych paketov 00284 00285 cOutVector *subqlenVec; // vektory podfront 00286 cOutVector *subdropVec; // vektory podfront 00287 00288 ANSAQOS::QueueConfig QueueInfo; // parametre fronty 00289 00290 public: 00291 AnsaQosSystem() {QueueInfo.setVectorPointer(&qlenVec, &dropVec);}; 00292 ~AnsaQosSystem(); 00293 00294 void loadConfigFromXML(); 00295 int getLowestSn(); 00296 AnsaSubQueues::iterator getSubQueueBySn(int sn); 00297 void substractSnInAllQueues(int sn); 00298 void setPQSubQueue(std::string id, cXMLElement* pql, int len); 00299 void setCQSubQueue (int id, cXMLElement* pql); 00300 void initSubQueueVectors(ANSAQOS::QueueType type); 00301 00302 00303 protected: 00304 00305 virtual void initialize(int stage); 00306 00307 /* Redefinovane z PassiveQueueBase. */ 00308 virtual bool enqueue(cMessage *msg); 00309 00310 /* Redefinovane z PassiveQueueBase. */ 00311 virtual cMessage *dequeue(); 00312 00313 /* Redefinovane z PassiveQueueBase. */ 00314 virtual void sendOut(cMessage *msg); 00315 00316 virtual int numInitStages() const { return 5;} 00317 00318 }; 00319 00320 00321 #endif 00322 00323