|
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 #include <omnetpp.h> 00021 #include "AnsaQosSystem.h" 00022 #include "RoutingTableAccess.h" 00023 00024 00025 Define_Module(AnsaQosSystem); 00026 00027 /* 00028 * ~AnsaQosSystem(): 00029 * Destruktor modulu, ktory odstrani vsetky pakety v podfrontach. 00030 */ 00031 00032 AnsaQosSystem::~AnsaQosSystem() 00033 { 00034 for (AnsaSubQueues::iterator sbqIt = subQueues.begin(); sbqIt != subQueues.end(); ++sbqIt) 00035 { 00036 sbqIt->clearSubQueue(); 00037 } 00038 00039 delete[] subqlenVec; 00040 delete[] subdropVec; 00041 } 00042 00043 /* 00044 * initialize(): 00045 * Metoda pre inicializaciu modulu. 00046 * @param stage - aktualna sekvencia volania 00047 */ 00048 00049 void AnsaQosSystem::initialize(int stage) 00050 { 00051 if(stage == 0) 00052 { 00053 PassiveQueueBase::initialize(); 00054 00055 outGate = gate("out"); 00056 00057 WATCH(QueueInfo); 00058 WATCH_VECTOR(subQueues); 00059 } 00060 else if (stage == 4) 00061 { 00062 // nacitanie konfiguracie zo XML 00063 loadConfigFromXML(); 00064 } 00065 00066 } 00067 00068 /* 00069 * loadConfigFromXML(): 00070 * Metoda pre nacitanie konfiguracie modulu zo XML. 00071 */ 00072 00073 void AnsaQosSystem::loadConfigFromXML() 00074 { 00075 IRoutingTable* rt = RoutingTableAccess().get(); 00076 00077 const char *fileName = par("configFile"); 00078 cXMLElement* document = ev.getXMLDocument(fileName); 00079 if (document == NULL) 00080 { 00081 error("Cannot read AS configuration from file %s", fileName); 00082 } 00083 /* Ziskanie elementu konfiguracie daneho smerovaca */ 00084 std::string routerXPath("Router[@id='"); 00085 std::string routerId = rt->getRouterId().str(); 00086 routerXPath += routerId; 00087 routerXPath += "']"; 00088 00089 cXMLElement* router = document->getElementByPath(routerXPath.c_str()); 00090 if (router == NULL) 00091 { 00092 error("No configuration for Router ID: %s", routerId.c_str()); 00093 } 00094 00095 /* Ziskanie elementu konfiguracie daneho rozhrania */ 00096 std::string itfName = this->getParentModule()->getName(); 00097 itfName += (char)('0' + this->getParentModule()->getIndex()); 00098 std::string intXPath(".//Interface[@name='"); 00099 intXPath += itfName; 00100 intXPath += "']"; 00101 00102 cXMLElement* qInt = router->getElementByPath(intXPath.c_str()); 00103 if (qInt == NULL) 00104 { 00105 error("No configuration for Interface: %s", itfName.c_str()); 00106 } 00107 00108 /* Ziskanie elementu konfiguracie vystupnej fronty */ 00109 cXMLElement* clsfrEl = NULL; 00110 cXMLElement* qs = qInt->getFirstChildWithTag("OutputQueue"); 00111 if (qs == NULL) 00112 { // ziadna konfiguracia -> defaultne FIFO o dlzke 75 00113 QueueInfo.setFIFO(75); 00114 subQueues.push_back(ANSAQOS::SubQueue(ANSAQOS::Q_FIFO, ANSAQOS::S_FIFO, QueueInfo.getHoldCapacity(), *clsfrEl)); 00115 return; 00116 } 00117 00118 /* Nacitanie konfiguracie podla typu fronty */ 00119 std::string qType = qs->getAttribute("type"); 00120 if(qType == "WFQ") 00121 { 00122 QueueInfo.setWFQ(); 00123 cXMLElementList ifDetails = qs->getChildren(); 00124 for (cXMLElementList::iterator ifElemIt = ifDetails.begin(); ifElemIt != ifDetails.end(); ++ifElemIt) 00125 { 00126 std::string nodeName = (*ifElemIt)->getTagName(); 00127 if (nodeName == "HoldQueueLength") 00128 QueueInfo.setHoldCapacity(atoi((*ifElemIt)->getNodeValue())); 00129 if (nodeName == "CDT") 00130 QueueInfo.setCdt(atoi((*ifElemIt)->getNodeValue())); 00131 if (nodeName == "DynamicQueues") 00132 QueueInfo.setMaxQueues(atoi((*ifElemIt)->getNodeValue())); 00133 } 00134 } 00135 else if(qType == "FIFO") 00136 { 00137 int len = 75; 00138 cXMLElementList ifDetails = qs->getChildren(); 00139 for (cXMLElementList::iterator ifElemIt = ifDetails.begin(); ifElemIt != ifDetails.end(); ++ifElemIt) 00140 { 00141 std::string nodeName = (*ifElemIt)->getTagName(); 00142 if (nodeName == "HoldQueueLength") 00143 len = atoi((*ifElemIt)->getNodeValue()); 00144 } 00145 QueueInfo.setFIFO(len); 00146 subQueues.push_back(ANSAQOS::SubQueue(ANSAQOS::Q_FIFO, ANSAQOS::S_FIFO, QueueInfo.getHoldCapacity(), *clsfrEl)); 00147 } 00148 else if(qType == "PQ") 00149 { 00150 QueueInfo.setPQ(); 00151 00152 cXMLElement* pql = qs->getFirstChildWithTag("PriorityQueueList"); 00153 if (pql == NULL) 00154 { 00155 error("No priority-list specified on interface: %s", itfName.c_str()); 00156 } 00157 00158 QueueInfo.setListId(pql->getNodeValue()); 00159 std::string pqlXPath(".//PriorityQueueList[@id='"); 00160 pqlXPath += QueueInfo.getListId(); 00161 pqlXPath += "']"; 00162 00163 00164 00165 pql = router->getElementByPath(pqlXPath.c_str()); 00166 if (pql == NULL) 00167 { 00168 error("Priority-list %s is not defined", QueueInfo.getListId().c_str()); 00169 } 00170 initSubQueueVectors(ANSAQOS::Q_PQ); 00171 setPQSubQueue ("HighQueue", pql, 20); 00172 setPQSubQueue ("MediumQueue", pql, 40); 00173 setPQSubQueue ("NormalQueue", pql, 60); 00174 setPQSubQueue ("LowQueue", pql, 80); 00175 } 00176 else if(qType == "CQ") 00177 { 00178 QueueInfo.setCQ(); 00179 00180 cXMLElement* pql = qs->getFirstChildWithTag("CustomQueueList"); 00181 if (pql == NULL) 00182 { 00183 error("No custom-list specified on interface: %s", itfName.c_str()); 00184 } 00185 00186 QueueInfo.setListId(pql->getNodeValue()); 00187 std::string pqlXPath(".//CustomQueueList[@id='"); 00188 pqlXPath += QueueInfo.getListId(); 00189 pqlXPath += "']"; 00190 00191 pql = router->getElementByPath(pqlXPath.c_str()); 00192 if (pql == NULL) 00193 { 00194 error("Custom-list %s is not defined", QueueInfo.getListId().c_str()); 00195 } 00196 00197 initSubQueueVectors(ANSAQOS::Q_CQ); 00198 for(int i = 0; i < 16; ++i) 00199 setCQSubQueue (i+1, pql); 00200 } 00201 00202 } 00203 00204 /* 00205 * setPQSubQueue(): 00206 * Metoda nacita konfiguraciu a vytvori podfrontu PQ 00207 * @param id - identifikator podfronty 00208 * @param pql - XML blok s konfiguracou vystupnej fronty 00209 */ 00210 00211 void AnsaQosSystem::setPQSubQueue (std::string id, cXMLElement* pql, int len) 00212 { 00213 cXMLElement* clsfr = NULL; 00214 std::string elemDQ; 00215 00216 cXMLElementList pqlDetails = pql->getChildren(); 00217 for (cXMLElementList::iterator pqlElemIt = pqlDetails.begin(); pqlElemIt != pqlDetails.end(); ++pqlElemIt) 00218 { 00219 std::string nodeName = (*pqlElemIt)->getTagName(); 00220 if (nodeName == "DefaultQueue") 00221 elemDQ = (*pqlElemIt)->getNodeValue(); 00222 if (nodeName == id) 00223 { 00224 cXMLElementList qDetails = (*pqlElemIt)->getChildren(); 00225 for (cXMLElementList::iterator qElemIt = qDetails.begin(); qElemIt != qDetails.end(); ++qElemIt) 00226 { 00227 std::string nn = (*qElemIt)->getTagName(); 00228 if (nn == "Lenght") 00229 len = atoi((*qElemIt)->getNodeValue()); 00230 if (nn == "Classifier") 00231 clsfr = *qElemIt; 00232 } 00233 } 00234 } 00235 00236 subQueues.push_back(ANSAQOS::SubQueue(ANSAQOS::Q_PQ, ANSAQOS::S_FIFO, len, *clsfr)); 00237 int d = subQueues.size(); 00238 subQueues.back().setQueueId(d); 00239 subQueues.back().setVectorPointer(&subqlenVec[d-1], &subdropVec[d-1]); 00240 QueueInfo.addHoldCapacity(len); 00241 00242 if (elemDQ.length() > 0 && elemDQ[2] == id[2]) 00243 QueueInfo.setDefaultQueueId(subQueues.size()); 00244 00245 00246 } 00247 00248 /* 00249 * setCQSubQueue(): 00250 * Metoda nacita konfiguraciu a vytvori podfrontu CQ 00251 * @param id - identifikator podfronty 00252 * @param pql - XML blok s konfiguracou vystupnej fronty 00253 */ 00254 00255 void AnsaQosSystem::setCQSubQueue (int id, cXMLElement* pql) 00256 { 00257 cXMLElement* clsfr = NULL; 00258 int dqVal; 00259 int len = 20; 00260 int bc = 1500; 00261 00262 cXMLElementList pqlDetails = pql->getChildren(); 00263 for (cXMLElementList::iterator pqlElemIt = pqlDetails.begin(); pqlElemIt != pqlDetails.end(); ++pqlElemIt) 00264 { 00265 std::string nodeName = (*pqlElemIt)->getTagName(); 00266 if (nodeName == "DefaultQueue") 00267 dqVal = atoi((*pqlElemIt)->getNodeValue()); 00268 if (nodeName == "CustomQueue" && atoi((*pqlElemIt)->getAttribute("id")) == id) 00269 { 00270 cXMLElementList qDetails = (*pqlElemIt)->getChildren(); 00271 for (cXMLElementList::iterator qElemIt = qDetails.begin(); qElemIt != qDetails.end(); ++qElemIt) 00272 { 00273 std::string nn = (*qElemIt)->getTagName(); 00274 if (nn == "Lenght") 00275 len = atoi((*qElemIt)->getNodeValue()); 00276 if (nn == "ByteCount") 00277 bc = atoi((*qElemIt)->getNodeValue()); 00278 if (nn == "Classifier") 00279 clsfr = *qElemIt; 00280 } 00281 } 00282 } 00283 00284 subQueues.push_back(ANSAQOS::SubQueue(ANSAQOS::Q_CQ, ANSAQOS::S_FIFO, len, *clsfr)); 00285 subQueues.back().setQueueId(id); 00286 subQueues.back().setWeight(bc); 00287 subQueues.back().setActualBytes(bc); 00288 subQueues.back().setVectorPointer(&subqlenVec[id-1], &subdropVec[id-1]); 00289 QueueInfo.addHoldCapacity(len); 00290 00291 if (dqVal == id) 00292 QueueInfo.setDefaultQueueId(id); 00293 00294 } 00295 00296 /* 00297 * getLowestSn(): 00298 * Funkcia najde najnizsie sekvencne cislo vramci vsetkych podfront. 00299 * @return - Vrati hodnotu najnizsieho sekvencneho cisla 00300 */ 00301 00302 int AnsaQosSystem::getLowestSn() 00303 { 00304 int sn = -1; 00305 00306 for (AnsaSubQueues::iterator sbqIt = subQueues.begin(); sbqIt != subQueues.end(); ++sbqIt) 00307 { 00308 if(sn == -1 && !sbqIt->isQueueEmpty()) 00309 { 00310 sn = sbqIt->getLowestSn(); 00311 } 00312 else if(!sbqIt->isQueueEmpty() && sbqIt->getLowestSn() < sn ) 00313 { 00314 sn = sbqIt->getLowestSn(); 00315 } 00316 } 00317 return sn; 00318 } 00319 00320 00321 00322 /* 00323 * initSubQueueVectors(): 00324 * Funkcia vytvori vektory pre PQ a CQ 00325 * @param sn - typ fronty 00326 */ 00327 00328 void AnsaQosSystem::initSubQueueVectors(ANSAQOS::QueueType type) 00329 { 00330 std::stringstream forStr; 00331 switch(type) 00332 { 00333 case ANSAQOS::Q_PQ : 00334 subqlenVec = new cOutVector[4]; 00335 subqlenVec[0].setName("High Length"); 00336 subqlenVec[1].setName("Medium Length"); 00337 subqlenVec[2].setName("Normal Length"); 00338 subqlenVec[3].setName("Low Length"); 00339 subdropVec = new cOutVector[4]; 00340 subdropVec[0].setName("High Drops"); 00341 subdropVec[1].setName("Medium Drops"); 00342 subdropVec[2].setName("Normal Drops"); 00343 subdropVec[3].setName("Low Drops"); 00344 break; 00345 case ANSAQOS::Q_CQ : 00346 subqlenVec = new cOutVector[16]; 00347 subdropVec = new cOutVector[16]; 00348 for(int i = 0; i < 16; ++i) 00349 { 00350 forStr.str(std::string()); 00351 forStr << "Q" << i+1 << " Length"; 00352 subqlenVec[i].setName(forStr.str().c_str()); 00353 forStr.str(std::string()); 00354 forStr << "Q" << i+1 << " Drops"; 00355 subdropVec[i].setName(forStr.str().c_str()); 00356 } 00357 break; 00358 default : 00359 break; 00360 } 00361 } 00362 00363 /* 00364 * getSubQueueBySn(): 00365 * Funkcia najde frontu obsahujucu paket z danym sekvencnym cislom 00366 * @param sn - sekvencne cislo paketu, ktory ma byt najdeny 00367 * @return - Vrati iterator na frontu s paketom daneho sekvencneho cisla 00368 */ 00369 00370 AnsaSubQueues::iterator AnsaQosSystem::getSubQueueBySn(int sn) 00371 { 00372 for (AnsaSubQueues::iterator sbqIt = subQueues.begin(); sbqIt != subQueues.end(); ++sbqIt) 00373 { 00374 if(sn == sbqIt->getLowestSn()) 00375 { 00376 return sbqIt; 00377 } 00378 } 00379 return subQueues.end(); 00380 } 00381 00382 /* 00383 * substractSnInAllQueues(): 00384 * Metoda, ktora odcita hodnotu zo sekvencneho cisla paketov vsetkych podfront. 00385 * @param sn - hodnota, ktora ma byt zo sekvencnych cisel odcitana 00386 */ 00387 00388 void AnsaQosSystem::substractSnInAllQueues(int sn) 00389 { 00390 for (AnsaSubQueues::iterator sbqIt = subQueues.begin(); sbqIt != subQueues.end(); ++sbqIt) 00391 { 00392 sbqIt->substractSnFromAll(sn); 00393 } 00394 } 00395 00396 /* 00397 * enqueue(): 00398 * Funkcia prevadza operaciu vlozenia spravy do fronty. 00399 * @param msg - sprava, ktora ma byt vlozena do fronty 00400 * @return - Vrati true pokial bol paket zahodeny 00401 */ 00402 00403 bool AnsaQosSystem::enqueue(cMessage *msg) 00404 { 00405 if(QueueInfo.getCurrentHold() < QueueInfo.getHoldCapacity()) 00406 { // je miesto vo fronte 00407 for(AnsaSubQueues::iterator sbqIt = subQueues.begin(); sbqIt != subQueues.end(); ++sbqIt) 00408 { // prechadza vsetky podfronty 00409 short res = sbqIt->enqueue(msg,true); 00410 if(res == ANSAQOS::QUEUED) 00411 { 00412 QueueInfo.addCurrentHold(); 00413 return false; // paket bol vlozeny do fronty 00414 } 00415 else if(res == ANSAQOS::NOTQUEUED) 00416 { 00417 QueueInfo.addDroped(); 00418 delete msg; 00419 return true; // paket zahodeny lebo sa nevojde do podfronty 00420 } 00421 } 00422 if(QueueInfo.getQueueType() == ANSAQOS::Q_WFQ) 00423 { // vo WFQ neexistuje podfronta pre dany tok 00424 if(QueueInfo.getNumQueues() < QueueInfo.getMaxQueues()) 00425 { // je mozne vytvorit podfrontu a vlozit do nej paket 00426 subQueues.push_back(ANSAQOS::SubQueue(msg, QueueInfo.getCdt())); 00427 QueueInfo.addNumQueues(); 00428 QueueInfo.addCurrentHold(); 00429 return false; 00430 } 00431 } 00432 else if(QueueInfo.getQueueType() == ANSAQOS::Q_PQ || QueueInfo.getQueueType() == ANSAQOS::Q_CQ) 00433 { // u PQ a CQ moznost vlozenia paketu do defaultnej fronty 00434 if (subQueues[QueueInfo.getDefaultQueueId()-1].enqueue(msg,false) == ANSAQOS::QUEUED) 00435 { 00436 QueueInfo.addCurrentHold(); 00437 return false; 00438 } 00439 } 00440 } 00441 00442 QueueInfo.addDroped(); 00443 delete msg; 00444 return true; //paket bol zahodeny 00445 } 00446 00447 /* 00448 * dequeue(): 00449 * Funkcia prevadza operaciu vybrania spravy z fronty. 00450 * @return - Vrati ukazovatel na vybrany paket 00451 */ 00452 00453 cMessage *AnsaQosSystem::dequeue() 00454 { 00455 if(QueueInfo.getCurrentHold() <= 0) 00456 { 00457 return NULL; // fronta je prazdna 00458 } 00459 00460 cMessage *msg; cPacket *pkt; 00461 int sn,id; 00462 AnsaSubQueues::iterator queueIt; 00463 00464 switch (QueueInfo.getQueueType()) 00465 { 00466 /* FIFO fronta ma len jednu "podfrontu" z ktorej sa vyberie prvy paket */ 00467 case ANSAQOS::Q_FIFO : 00468 msg = subQueues.begin()->dequeue(); 00469 break; 00470 /* Vo WFQ fronte sa vyberie paket s najmensim sekvencnym cislom. 00471 V pripade, ze podfronta sa vyprazdni, tak je odstranena. 00472 Aby nedoslo k preteceniu hodnoty sekvencneho cisla, tak je po kazdom 00473 vybrani paketu jeho sekvencne cislo odcitane od ostatnych */ 00474 case ANSAQOS::Q_WFQ : 00475 sn = getLowestSn(); 00476 queueIt = getSubQueueBySn(sn); 00477 00478 msg = queueIt->dequeue(); 00479 if(queueIt->isQueueEmpty()) 00480 { 00481 subQueues.erase(queueIt); 00482 QueueInfo.remNumQueues(); 00483 } 00484 substractSnInAllQueues(getLowestSn()); 00485 break; 00486 /* PQ fronta obsahuje 4 fronty, ktore prechadza podla priority 00487 prvy paket, na ktory narazi je vybrany */ 00488 case ANSAQOS::Q_PQ : 00489 for (AnsaSubQueues::iterator queueIt = subQueues.begin(); queueIt != subQueues.end(); ++queueIt) 00490 { 00491 if(!queueIt->isQueueEmpty()) 00492 { 00493 msg = queueIt->dequeue(); 00494 break; 00495 } 00496 } 00497 break; 00498 /* CQ obsahuje 16 front, ktore su prechadzane round robin. 00499 Pakety su z fronty vyberane az dovtedy, kym obsahuje dostatocny 00500 pocet bajtov alebo je fronta prazdna*/ 00501 case ANSAQOS::Q_CQ : 00502 while (subQueues[QueueInfo.getCurrentCQQueueId()].isQueueEmpty()) 00503 { // najdenie prvej neprazdnej fronty 00504 subQueues[QueueInfo.getCurrentCQQueueId()].setActualBytes(); 00505 QueueInfo.addCurrentCQQueueId(); 00506 } 00507 00508 id = QueueInfo.getCurrentCQQueueId(); 00509 msg = subQueues[id].dequeue(); // vybranie paketu z fronty 00510 pkt = dynamic_cast<cPacket *> (msg->dup()); 00511 subQueues[id].remActualBytes(pkt->getByteLength()); // odstanenie bajtov z fronty 00512 delete pkt; 00513 00514 if(subQueues[id].getActualBytes() <= 0) 00515 { // nedostatocny pocet bajtov.. prechod na dalsiu frontu a reset bajtov 00516 subQueues[id].setActualBytes(); 00517 QueueInfo.addCurrentCQQueueId(); 00518 } 00519 break; 00520 default : 00521 msg = NULL; 00522 break; 00523 } 00524 00525 QueueInfo.remCurrentHold(); 00526 return msg; 00527 } 00528 00529 /* 00530 * sendOut(): 00531 * Metoda odosle spravu cez vystupnu branu 00532 * @param msg - sprava, ktora ma byt odoslana 00533 */ 00534 00535 void AnsaQosSystem::sendOut(cMessage *msg) 00536 { 00537 send(msg, outGate); 00538 } 00539 00540 /* 00541 * SubQueue(): 00542 * Konstruktor vytvorenia podfronty pre WFQ na zaklade spravy 00543 * @param msg - sprava, ktora definuje tok pre klasifikator podfronty 00544 * @param cdt - dlzka vytvaranej fronty 00545 */ 00546 00547 ANSAQOS::SubQueue::SubQueue(cMessage *msg, int cdt) 00548 { 00549 qlenVec = dropVec = NULL; 00550 lastSn = 0; 00551 maxLength = cdt; 00552 qt = Q_WFQ; 00553 sbqt = S_FIFO; 00554 droped = 0; 00555 this->setWeight(msg); 00556 clsfr = new WFQClassifier(msg); 00557 this->enqueue(msg,true); 00558 } 00559 00560 /* 00561 * SubQueue(): 00562 * Konstruktor pre vytvorenie podfronty na zaklade vstupnych parametrov 00563 * @param t1 - typ fronty, ktorej je podfronta sucastou 00564 * @param t2 - typ podfronty 00565 * @param len - dlzka vytvaranej fronty 00566 * @param clsfrConfig - XML blok s konfiguraciu klasifikatora podfronty 00567 */ 00568 00569 ANSAQOS::SubQueue::SubQueue(QueueType t1, SubQueueType t2, int len, cXMLElement& clsfrConfig) 00570 { 00571 qlenVec = dropVec = NULL; 00572 lastSn = 0; 00573 maxLength = len; 00574 qt = t1; 00575 sbqt = t2; 00576 droped = 0; 00577 00578 switch (qt) // na zaklade typu fronty sa vytvori klasifikator podfronty 00579 { 00580 case Q_FIFO : 00581 clsfr = new MatchAnyClassifier(); 00582 break; 00583 case Q_PQ : 00584 case Q_CQ : 00585 if (&clsfrConfig != NULL) 00586 { 00587 std::string cType = clsfrConfig.getAttribute("type"); 00588 if(cType == "DSCP") 00589 clsfr = new DSCPClassifier(clsfrConfig); 00590 else if (cType == "PREC") 00591 clsfr = new PRECClassifier(clsfrConfig); 00592 else if (cType == "ACL") 00593 clsfr = new ACLClassifier(clsfrConfig); 00594 } 00595 else 00596 clsfr = new MatchNoneClassifier(); 00597 break; 00598 default : 00599 break; 00600 } 00601 00602 } 00603 00604 /* 00605 * clearSubQueue(): 00606 * Metoda vymaze vsetky pakety z podfronty. 00607 */ 00608 00609 void ANSAQOS::SubQueue::clearSubQueue() 00610 { 00611 if(!isQueueEmpty()) 00612 { 00613 for (std::vector<SNPacket>::iterator it = snPackets.begin(); it!=snPackets.end(); ++it) 00614 { 00615 delete it->getMsg(); 00616 it->setMsg(NULL); 00617 } 00618 } 00619 } 00620 00621 /* 00622 * enqueue(): 00623 * Funkcia prevadza operaciu vlozenia spravy do subfronty. 00624 * @param msg - sprava, ktora ma byt vlozena do subfronty 00625 * @param classify - parameter urcujuci ci sa ma vykonat klasifikacia 00626 * @return - Vrati vysledok operacie 00627 */ 00628 00629 short ANSAQOS::SubQueue::enqueue(cMessage *msg, bool classify) 00630 { 00631 int sn = 0; 00632 00633 if(classify && !clsfr->classifyPacket(msg)) 00634 return NOMATCH; // paket nebol do fronty klasifikovany 00635 00636 if(this->getQueueLength() >= maxLength) 00637 { 00638 this->addDroped(); 00639 this->updateVectorDrop(); 00640 return NOTQUEUED; // fronta je plna 00641 } 00642 00643 switch (qt) 00644 { 00645 case Q_WFQ : 00646 sn = this->calculateSn(msg); // vypocet SN v pripade WFQ fronty 00647 setLastSn(sn); 00648 break; 00649 default : 00650 break; 00651 } 00652 00653 SNPacket newSNPacket(msg, sn); 00654 snPackets.push_back(newSNPacket); // vlozenie paketu do podfronty 00655 00656 this->updateVectorLenght(); 00657 return QUEUED; // paket vlozeny do fronty 00658 } 00659 00660 /* 00661 * dequeue(): 00662 * Funkcia vyberie sparavy z podfronty 00663 * @return - Vrati vybranu spravu 00664 */ 00665 00666 cMessage *ANSAQOS::SubQueue::dequeue() 00667 { 00668 cMessage *msg = (snPackets.front()).getMsg(); 00669 snPackets.erase(snPackets.begin()); 00670 00671 this->updateVectorLenght(); 00672 return msg; 00673 } 00674 00675 /* 00676 * calculateSn(): 00677 * Funkcia vypocita sekvencne cislo pre spravu na zaklade 00678 * hodnoty jej IP precedence a velkosti. 00679 * @param msg - sprava pre ktoru je vypocitavane sekvencne cislo 00680 * @return - Vrati sekvencne cislo danej spravy 00681 */ 00682 00683 int ANSAQOS::SubQueue::calculateSn(cMessage *msg) 00684 { 00685 int sn; 00686 00687 cPacket *pkt = dynamic_cast<cPacket *> (msg->dup()); 00688 int len = pkt->getByteLength(); 00689 00690 short ipPrec = 0; 00691 if (dynamic_cast<IPDatagram *>(pkt)) 00692 { 00693 IPDatagram *datagram = (IPDatagram *)pkt; 00694 ipPrec = (short) datagram->getDiffServCodePoint()/32; 00695 } 00696 00697 delete pkt; 00698 00699 sn = this->getLastSn() + ((32384 / (ipPrec + 1)) * len); 00700 00701 return sn; 00702 } 00703 00704 /* 00705 * substractSnFromAll(): 00706 * Metoda, ktora odpocita zo vsetkych sekvencych cisel paketov danej fronty 00707 * pozadovanu hodnotu. 00708 * @param subNum - hodnota, ktora bude zo sekvencnych cisel odcitana 00709 */ 00710 00711 void ANSAQOS::SubQueue::substractSnFromAll(int subNum) 00712 { 00713 if(!isQueueEmpty()) 00714 { 00715 for (std::vector<SNPacket>::iterator it = snPackets.begin(); it!=snPackets.end(); ++it) 00716 { 00717 it->substractSn(subNum); 00718 } 00719 lastSn -= subNum; 00720 } 00721 } 00722 00723 /* 00724 * setWeight(): 00725 * Metoda, ktora vypocita na zaklade hodnoty IP precedence paketu vahu 00726 * danej podfronty. 00727 * @param msg - sprava, podla ktorej sa urci hodnota vyahy 00728 */ 00729 00730 void ANSAQOS::SubQueue::setWeight(cMessage *msg) 00731 { 00732 Flow flowID; 00733 flowID.parseFromMsg(msg); 00734 weight = 32384 / (flowID.ipPrec +1); // vypocet vahy pre podfrontu 00735 } 00736 00737 /* 00738 * setVectorName(): 00739 * Metoda, ktora inicializuje nazvy vektorov pre statistiku fronty 00740 * @param type - typ fronty 00741 */ 00742 00743 void ANSAQOS::QueueConfig::setVectorName(ANSAQOS::QueueType type) 00744 { 00745 switch(type) 00746 { 00747 case ANSAQOS::Q_FIFO : 00748 qlenVec->setName("FIFO Length"); 00749 dropVec->setName("FIFO Drops"); 00750 break; 00751 case ANSAQOS::Q_WFQ : 00752 qlenVec->setName("WFQ Length"); 00753 dropVec->setName("WFQ Drops"); 00754 break; 00755 case ANSAQOS::Q_PQ : 00756 qlenVec->setName("PQ Length"); 00757 dropVec->setName("PQ Drops"); 00758 break; 00759 case ANSAQOS::Q_CQ : 00760 qlenVec->setName("CQ Length"); 00761 dropVec->setName("CQ Drops"); 00762 break; 00763 default : 00764 break; 00765 } 00766 } 00767 00768 /* 00769 * Pretazenie operatoru "<<" pre vypis stavu fronty do grafickeho rozhrania 00770 */ 00771 00772 std::ostream& operator<< (std::ostream& ostr, ANSAQOS::QueueConfig config) 00773 { 00774 switch (config.getQueueType()) 00775 { 00776 case ANSAQOS::Q_FIFO : 00777 ostr << "Strategy: fifo; Queue: "; 00778 ostr << config.getCurrentHold() << "/"; 00779 ostr << config.getDroped() << "/"; 00780 ostr << config.getHoldCapacity() << " (size/dropped/max)"; 00781 break; 00782 case ANSAQOS::Q_WFQ : 00783 ostr << "Strategy: weighted fair; Queue: "; 00784 ostr << config.getCurrentHold() << "/"; 00785 ostr << config.getHoldCapacity() << "/"; 00786 ostr << config.getCdt() << "/"; 00787 ostr << config.getDroped() << " (size/max total/threshold/drops); Conversations: "; 00788 ostr << config.getNumQueues() << "/"; 00789 ostr << config.getMaxActQueues() << "/"; 00790 ostr << config.getMaxQueues() << " (active/max active/max total)"; 00791 break; 00792 case ANSAQOS::Q_PQ : 00793 ostr << "Strategy: priority-list " << config.getListId(); 00794 switch (config.getDefaultQueueId()) 00795 { 00796 case 1 : 00797 ostr << " (Default queue: High)"; 00798 break; 00799 case 2 : 00800 ostr << " (Default queue: Medium)"; 00801 break; 00802 case 3 : 00803 ostr << " (Default queue: Normal)"; 00804 break; 00805 case 4 : 00806 ostr << " (Default queue: Low)"; 00807 break; 00808 default: 00809 ostr << " (Default queue: Error)"; 00810 } 00811 break; 00812 case ANSAQOS::Q_CQ : 00813 ostr << "Strategy: custom-list " << config.getListId(); 00814 ostr << " (Default queue: " << config.getDefaultQueueId() << ")"; 00815 break; 00816 default : 00817 ostr << "Error"; 00818 } 00819 00820 return ostr; 00821 } 00822