|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright 2011 Martin Danko 00003 // 00004 // This library is free software, you can redistribute it and/or modify 00005 // it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; 00007 // either version 2 of the License, or any later version. 00008 // The library is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 // See the GNU Lesser General Public License for more details. 00012 // 00013 00014 //#include <stdlib.h> 00015 00016 #include <math.h> 00017 #include <fstream> 00018 00019 #include "TrafGen.h" 00020 #include "InterfaceTableAccess.h" 00021 #include "IInterfaceTable.h" 00022 #include "IPv4InterfaceData.h" 00023 00024 00025 00026 Define_Module(TrafGen); 00027 00028 /* 00029 * initialize(): 00030 * Metoda pre inicializaciu modulu. 00031 * @param stage - aktualna sekvencia volania 00032 */ 00033 void TrafGen::initialize(int stage) 00034 { 00035 if (stage == 4) 00036 { 00037 numSent = 0; 00038 numReceived = 0; 00039 counter = 0; 00040 00041 const char *fileName = par("flowDefFile"); 00042 00043 // nacitanie konfiguracie tokov 00044 if (fileName == NULL || (!strcmp(fileName, "")) || !LoadFlowsFromXML(fileName)) 00045 error("Error reading TrafGen flows from file %s", fileName); 00046 00047 // inicializacne procedury 00048 detectRoles(); 00049 initTimers(); 00050 bindSockets(); 00051 initStats(); 00052 00053 cMessage *timer = new cMessage("StatsTimer"); 00054 scheduleAt(1.0, timer); 00055 00056 // nastavenie statistik pre graficke rozhranie 00057 WATCH(numSent); 00058 WATCH(numReceived); 00059 WATCH_VECTOR(sentStatistics); 00060 WATCH_VECTOR(receivedStatistics); 00061 00062 } 00063 else if( stage == 5) 00064 installRcvStatIts(); 00065 } 00066 00067 /* 00068 * LoadFlowsFromXML(): 00069 * Nacita konfiguraciu tokov zo XML suboru 00070 * @filename - nazov XML suboru 00071 * @return - vrati true pokial nacitanie prebehlo v poriadku 00072 */ 00073 bool TrafGen::LoadFlowsFromXML(const char * filename) 00074 { 00075 cXMLElement* trafgenConfig = ev.getXMLDocument(filename); 00076 if (trafgenConfig == NULL) 00077 error("Cannot read TrafGen flows configuration from file: %s", filename); 00078 00079 std::string nodeName = trafgenConfig->getTagName(); 00080 00081 if(nodeName == "trafgen") 00082 { 00083 cXMLElementList flowsConfigList= trafgenConfig->getChildren(); 00084 for (cXMLElementList::iterator flowIt = flowsConfigList.begin(); flowIt != flowsConfigList.end(); flowIt++) 00085 { 00086 std::string elName = (*flowIt)->getTagName(); 00087 if (elName == "flow" && (*flowIt)->getAttribute("id")) 00088 parseFlow(*(*flowIt)); 00089 else 00090 error("Wrong flow definition"); 00091 } 00092 } 00093 else 00094 return false; 00095 00096 if(flows.size() == 0) 00097 return false; 00098 00099 return true; 00100 } 00101 00102 /* 00103 * parseFlow(): 00104 * Zo XML suvboru rozparsuje a vyhodnoti konfiguraciu jedneho toku 00105 * @flowConfig - XML blok s konfiguraciou tokov 00106 */ 00107 void TrafGen::parseFlow(const cXMLElement& flowConfig) 00108 { 00109 TG::FlowRecord flw; 00110 cXMLElement* element; 00111 00112 flw.setId(flowConfig.getAttribute("id")); 00113 00114 if(flw.getId() == "" || getFlowById(flw.getId()) != flows.end()) 00115 { 00116 error("Missing or duplicate flow ID"); 00117 return; 00118 } 00119 00120 element = flowConfig.getFirstChildWithTag("duration"); 00121 if(element != NULL) 00122 flw.setDuration(atof(element->getNodeValue())); 00123 00124 element = flowConfig.getFirstChildWithTag("start_time"); 00125 if(element != NULL) 00126 flw.setStartTime(atof(element->getNodeValue())); 00127 00128 cXMLElement* ipHeader = flowConfig.getFirstChildWithTag("ip_header"); 00129 if(ipHeader != NULL) 00130 { 00131 element = ipHeader->getFirstChildWithTag("source_ip"); 00132 if(element != NULL) 00133 flw.setSrcIP(IPAddress(element->getNodeValue())); 00134 00135 element = ipHeader->getFirstChildWithTag("destination_ip"); 00136 if(element != NULL) 00137 flw.setDstIP(IPAddress(element->getNodeValue())); 00138 00139 element = ipHeader->getFirstChildWithTag("tos"); 00140 if(element != NULL) 00141 flw.setTos(readDscp(element->getNodeValue())); 00142 00143 element = ipHeader->getFirstChildWithTag("ttl"); 00144 if(element != NULL) 00145 flw.setTtl(atoi(element->getNodeValue())); 00146 00147 element = ipHeader->getFirstChildWithTag("protocol"); 00148 if(element != NULL) 00149 { 00150 std::string prtStr = element->getNodeValue(); 00151 if (prtStr == "tcp" || prtStr == "Tcp" || prtStr == "TCP") 00152 flw.setProtocol(IP_PROT_TCP); 00153 else 00154 flw.setProtocol(IP_PROT_UDP); 00155 } 00156 } 00157 00158 cXMLElement* transHeader = flowConfig.getFirstChildWithTag("transport_header"); 00159 if(ipHeader != NULL) 00160 { 00161 element = transHeader->getFirstChildWithTag("source_port"); 00162 if(element != NULL) 00163 flw.setSrcPort(atoi(element->getNodeValue())); 00164 00165 element = transHeader->getFirstChildWithTag("destination_port"); 00166 if(element != NULL) 00167 flw.setDstPort(atoi(element->getNodeValue())); 00168 } 00169 00170 cXMLElement* appEl = flowConfig.getFirstChildWithTag("application"); 00171 if(appEl != NULL && appEl->getAttribute("type")) 00172 { 00173 if(!flw.setApplication(*appEl)) 00174 error("Wrong application configuration for flow with ID: %s", flw.getId().c_str()); 00175 } 00176 00177 if(!isValidFlow(flw)) 00178 { 00179 error("Invalid definition of flow with ID: %s", flw.getId().c_str()); 00180 return; 00181 } 00182 00183 00184 flows.push_back(flw); 00185 } 00186 00187 /* 00188 * isValidFlow(): 00189 * Zisti, ci dany tok je definovavy korektne 00190 * @return - Vrati true pokial je tok definovany korektne 00191 */ 00192 bool TrafGen::isValidFlow(TG::FlowRecord &flw) 00193 { 00194 if(flw.getSrcIP().get4() == IPAddress::UNSPECIFIED_ADDRESS) 00195 return false; 00196 if(flw.getDstIP().get4() == IPAddress::UNSPECIFIED_ADDRESS) 00197 return false; 00198 if(flw.getTtl() < 1) 00199 return false; 00200 if(flw.getSrcPort() < 1) 00201 return false; 00202 if(flw.getDstPort() < 1) 00203 return false; 00204 00205 return true; 00206 } 00207 00208 /* 00209 * readDscp(): 00210 * Funkcia prevedie string z DSCP hodnotou na 8 bitovu hodotu ToS 00211 * @param dscpString - retazec DSCP hodnoty 00212 * @return - Vrati hodnotu ToS zakodovanu v DSCP retazcu 00213 */ 00214 unsigned char TrafGen::readDscp(std::string dscpString) 00215 { 00216 00217 if(dscpString.size() == 3) 00218 { 00219 std::string prf = dscpString.substr(0,2); 00220 unsigned char cls = dscpString[2] - '0'; 00221 if((prf == "CS" || prf == "Cs" || prf == "cs") && cls > 0 && cls < 8) 00222 return cls*32; 00223 } 00224 else if (dscpString.size() == 4) 00225 { 00226 std::string prf = dscpString.substr(0,2); 00227 unsigned char cls = dscpString[2] - '0'; 00228 unsigned char dp = dscpString[3] - '0'; 00229 if((prf == "AF" || prf == "Af" || prf == "af") && cls > 0 && cls < 5 && dp > 0 && dp < 4) 00230 return cls*32 + dp*8; 00231 } 00232 else if(dscpString == "EF" || dscpString == "Ef" || dscpString == "ef") 00233 return 184; 00234 00235 return atoi(dscpString.c_str()); 00236 } 00237 00238 /* 00239 * detectRoles(): 00240 * Zisti, ci dany modul pre konkretny tok je v ulohe generatora alebo analyzera 00241 */ 00242 void TrafGen::detectRoles() 00243 { 00244 IInterfaceTable *ift = InterfaceTableAccess().get(); 00245 00246 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00247 { 00248 for(int i = 0; i < ift->getNumInterfaces(); ++i) 00249 { 00250 if(ift->getInterface(i)->ipv4Data()->getIPAddress() == it->getSrcIP().get4()) 00251 it->setGenerating(true); 00252 if(ift->getInterface(i)->ipv4Data()->getIPAddress() == it->getDstIP().get4()) 00253 it->setAnalyzing(true); 00254 } 00255 } 00256 00257 } 00258 00259 /* 00260 * initTimers(): 00261 * Inicializuje casovace pre planovanie generovania tokov 00262 */ 00263 void TrafGen::initTimers() 00264 { 00265 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00266 { 00267 if(it->isGenerating() && it->getDuration() > 0.0) 00268 { 00269 cMessage *timer = new cMessage(it->getId().c_str()); 00270 scheduleAt(it->getStartTime(), timer); 00271 } 00272 } 00273 } 00274 00275 /* 00276 * initStats(): 00277 * Inicializuje statistiky tokov 00278 */ 00279 void TrafGen::initStats() 00280 { 00281 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00282 { 00283 if(it->isAnalyzing()) 00284 { 00285 TG::RcvFlowRecord rr; 00286 rr.setId(it->getId()); 00287 rr.setStartTime(it->getStartTime()); 00288 receivedStatistics.push_back(rr); 00289 cOutVector* recVec1 = new cOutVector; 00290 std::string vecName1 = "Flow " + it->getId() + " actual birate"; 00291 recVec1->setName(vecName1.c_str()); 00292 actBitrateVec[it->getId()] = recVec1; 00293 00294 cOutVector* recVec2 = new cOutVector; 00295 std::string vecName2 = "Flow " + it->getId() + " actual packetrate"; 00296 recVec2->setName(vecName2.c_str()); 00297 actPacketrateVec[it->getId()] = recVec2; 00298 } 00299 if(it->isGenerating()) 00300 { 00301 TG::SntFlowRecord sr; 00302 sr.setId(it->getId()); 00303 sr.setStartTime(it->getStartTime()); 00304 sentStatistics.push_back(sr); 00305 } 00306 } 00307 } 00308 00309 /* 00310 * bindSockets(): 00311 * Vytvori UDP/TCP sokety pre nasluchanie na potrebnom porte 00312 */ 00313 void TrafGen::bindSockets() 00314 { 00315 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00316 { 00317 if(it->isAnalyzing()) 00318 { 00319 if(it->getProtocol() == IP_PROT_UDP) 00320 { 00321 if(!isListening(IP_PROT_UDP, it->getDstPort())) 00322 { 00323 cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND); 00324 UDPControlInfo *ctrl = new UDPControlInfo(); 00325 ctrl->setSockId(UDPSocket::generateSocketId()); 00326 ctrl->setSrcPort(it->getDstPort()); 00327 msg->setControlInfo(ctrl); 00328 send(msg, "udpOut"); 00329 udpListenPort.push_back(it->getDstPort()); 00330 } 00331 } 00332 else if(it->getProtocol() == IP_PROT_TCP) 00333 { 00334 if(!isListening(IP_PROT_TCP, it->getDstPort())) 00335 { 00336 TCPSocket socket; 00337 socket.setOutputGate(gate("tcpOut")); 00338 socket.bind(it->getDstIP(), it->getDstPort()); 00339 socket.listen(); 00340 tcpListenPort.push_back(it->getDstPort()); 00341 } 00342 } 00343 } 00344 } 00345 } 00346 00347 /* 00348 * installRcvStatIts(): 00349 * Ku kazdemu generovanemu toku ziska ukazovatel do statistik prijemcu. 00350 * Dovodom je aby prijemca mal informacie o tom kolko paketov odosielatel vygeneroval 00351 */ 00352 void TrafGen::installRcvStatIts() 00353 { 00354 cTopology topology; 00355 00356 topology.extractByNedTypeName(cStringTokenizer("inet.ansa.TrafficGenerator.TrafGen").asVector()); 00357 00358 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00359 { 00360 if(it->isGenerating()) 00361 { 00362 bool found = false; 00363 for(int i = 0; i < topology.getNumNodes(); ++i) 00364 { 00365 cTopology::Node *node = topology.getNode(i); 00366 TrafGen *tgpt = check_and_cast<TrafGen*> (node->getModule()); 00367 if(tgpt->getFlowById(it->getId())->isAnalyzing()) 00368 { 00369 it->setRcvModStatsIt(tgpt->getRcvFlowStatById(it->getId())); 00370 found = true; 00371 } 00372 } 00373 if(!found) 00374 error("Missing receiver for flow with ID: %s", it->getId().c_str()); 00375 } 00376 } 00377 } 00378 00379 /* 00380 * createPacket(): 00381 * Vygeneruje dalsi paket na odoslanie z daneho toku 00382 * @param flowIt - iterator na tok 00383 * @return - Vrati ukazovatel na vytvoreny paket 00384 */ 00385 cPacket *TrafGen::createPacket(TG::Flows::iterator flowIt) 00386 { 00387 char msgName[32]; 00388 sprintf(msgName,"TrafGenPacket - Flow %s", flowIt->getId().c_str()); 00389 00390 int totalDataLen = flowIt->getPApplication()->getPacketSize() + flowIt->getPApplication()->anotherEncapsulationOverhead(); 00391 00392 // TrafGenPacket - nesie informacie o ID toku, nazvu aplikacie a casu zaslania 00393 TrafGenPacket *payload = new TrafGenPacket(msgName); 00394 payload->setFlowId(flowIt->getId().c_str()); 00395 payload->setApplication((flowIt->getAppName()).c_str()); 00396 payload->setSentTime(simTime().dbl()); 00397 payload->setByteLength(totalDataLen); 00398 return payload; 00399 } 00400 00401 /* 00402 * sendPacket(): 00403 * Funkcia posle paket toku urceneho parametrom 00404 * @param flowIt - iterator na tok 00405 * @return - Vrati v pripade uspesneho odoslania 00406 */ 00407 bool TrafGen::sendPacket(TG::Flows::iterator flowIt) 00408 { 00409 cPacket *payload; 00410 00411 if (flowIt->getProtocol() == IP_PROT_UDP) 00412 { // vygeneruje UDP paket 00413 if (flowIt->getStartTime() + flowIt->getDuration() < simTime().dbl()) 00414 return false; // tok presiahol dobu generovania 00415 00416 // vytvorenie paketu 00417 payload = createPacket(flowIt); 00418 00419 payload->setKind(UDP_C_DATA); 00420 // pripojenie kontrolnych informacii 00421 UDPControlInfo *ctrl = new UDPControlInfo(); 00422 ctrl->setSrcAddr(flowIt->getSrcIP()); 00423 ctrl->setSrcPort(flowIt->getSrcPort()); 00424 ctrl->setDestAddr(flowIt->getDstIP()); 00425 ctrl->setDestPort(flowIt->getDstPort()); 00426 payload->setControlInfo(ctrl); 00427 00428 send(payload, "udpOut"); 00429 } 00430 else if (flowIt->getProtocol() == IP_PROT_TCP) 00431 { // vygeneruje TCP paket 00432 if (flowIt->getStartTime() + flowIt->getDuration() < simTime().dbl()) 00433 { // tok presiahol dobu generovania 00434 flowIt->tcpClose(); 00435 return false; 00436 } 00437 else 00438 { 00439 if(!flowIt->isTcpConnected()) 00440 { // pripojenie TCP v pripade, ze uz nie je pripojene 00441 flowIt->tcpConnect(gate("tcpOut")); 00442 } 00443 // vytvorenie paketu a odoslanie 00444 payload = createPacket(flowIt); 00445 flowIt->sendTcpPacket(payload); 00446 } 00447 } 00448 00449 return true; 00450 } 00451 00452 /* 00453 * handleMessage(): 00454 * Spracuje prijatu pravu zo siete 00455 * @msg - prijata sprava 00456 */ 00457 void TrafGen::processPacket(cMessage *msg) 00458 { 00459 if (msg->getKind() == UDP_I_ERROR && msg->getArrivalGate() == gate("udpIn")) 00460 { // chybny UDP paket -> je zahodeny 00461 delete msg; 00462 } 00463 else if (msg->getKind()==TCP_I_PEER_CLOSED) 00464 { // TCP spojenie zavrate protistranou 00465 TCPCommand *controlInfo = check_and_cast<TCPCommand *>(msg->getControlInfo()); 00466 if(isLocalTcpOrig(controlInfo->getConnId())) 00467 { 00468 delete msg; 00469 } 00470 else 00471 { 00472 msg->setName("close"); 00473 msg->setKind(TCP_C_CLOSE); 00474 send(msg, "tcpOut"); 00475 } 00476 } 00477 else if (msg->getKind() == UDP_I_DATA || msg->getKind()==TCP_I_DATA || msg->getKind()==TCP_I_URGENT_DATA) 00478 { // paket je OK -> bude spracovany 00479 TrafGenPacket *packet = check_and_cast<TrafGenPacket *>(msg); 00480 00481 // najde tok, do ktoreho paket patri 00482 TG::Flows::iterator flowIt = getFlowById(packet->getFlowId()); 00483 if(flowIt != flows.end()) 00484 { 00485 // najdes zaznam o statistikach daneho toku 00486 TG::RcvStats::iterator flowStatIt = getRcvFlowStatById(flowIt->getId()); 00487 if(flowStatIt != receivedStatistics.end()) 00488 { // aktualizuje staisticke informacie toku 00489 double actTime = simTime().dbl(); 00490 double delay = actTime - packet->getSentTime(); 00491 double jitter; 00492 00493 flowStatIt->setEndTime(actTime); 00494 00495 if(flowStatIt->getTotalRcvPkts() == 0) 00496 { 00497 flowStatIt->setStartTime(actTime); 00498 flowStatIt->setMinDelay(delay); 00499 flowStatIt->setMaxDelay(delay); 00500 jitter = 0.0; 00501 } 00502 else 00503 jitter = fabs(delay - (flowStatIt->getTotalDelay()/flowStatIt->getTotalRcvPkts())); 00504 00505 if(flowStatIt->getMinDelay() > delay) 00506 flowStatIt->setMinDelay(delay); 00507 if(flowStatIt->getMaxDelay() < delay) 00508 flowStatIt->setMaxDelay(delay); 00509 00510 flowStatIt->addTotalDelay(delay); 00511 flowStatIt->addTotalJitter(jitter); 00512 00513 int dataLen = packet->getByteLength() - flowIt->getPApplication()->anotherEncapsulationOverhead(); 00514 00515 flowStatIt->updateActVec(simTime().dbl(),dataLen); 00516 flowStatIt->addTotalBytes(dataLen); 00517 flowStatIt->addTotalRcvPkts(); 00518 numReceived++; 00519 } 00520 } 00521 delete msg; 00522 } 00523 else 00524 { 00525 delete msg; 00526 } 00527 } 00528 00529 /* 00530 * handleMessage(): 00531 * Metoda spracuje prijatu spravu 00532 * @msg - prijata sprava 00533 */ 00534 void TrafGen::handleMessage(cMessage *msg) 00535 { 00536 if (msg->isSelfMessage()) 00537 { 00538 std::string mName = msg->getName(); 00539 if(mName == "StatsTimer") 00540 { 00541 updateActVectorStats(); 00542 scheduleAt(simTime() + 0.5 , msg); 00543 } 00544 else 00545 { 00546 // vyprsal timer -> dojde ku generovaniu dalsej spravy 00547 TG::Flows::iterator flowIt = getFlowById(mName); 00548 // vysle paket a naplanuje cas odoslania dalsieho paketu daneho toku 00549 bool scheduleNext = sendPacket(flowIt); 00550 if(scheduleNext) 00551 scheduleAt(simTime()+ flowIt->getPApplication()->getNextPacketTime(), msg); 00552 else 00553 delete msg; 00554 } 00555 } 00556 else 00557 { 00558 // spracuje prichadzajuci paket zo siete 00559 processPacket(msg); 00560 } 00561 } 00562 00563 /* 00564 * finish(): 00565 * Metoda po skonceni simulacie vygeneruje statistiky tokov pre, ktore bol modul prijemca 00566 */ 00567 void TrafGen::finish() 00568 { 00569 if(receivedStatistics.size() > 0) 00570 { 00571 std::ofstream outFile; 00572 std::string moduleName = this->getParentModule()->getName(); 00573 std::string filename = "results/TrafGen-" + moduleName + ".txt"; 00574 outFile.open (filename.c_str()); 00575 00576 int numFlows = 0; 00577 double tStartTime = 0.0; 00578 double tEndTime = 0.0; 00579 double tMinDelay = 0.0; 00580 double tMaxDelay = 0.0; 00581 double tTotDelay = 0.0; 00582 double tTotJitter = 0.0; 00583 long tSent = 0; 00584 long tReceived = 0; 00585 long tBytes = 0; 00586 long tDropped = 0; 00587 long dropInFlow = 0; 00588 00589 for(TG::RcvStats::iterator it = receivedStatistics.begin(); it != receivedStatistics.end(); ++it) 00590 { 00591 TG::Flows::iterator fit = getFlowById(it->getId()); 00592 outFile << "----------------------------------------------------------" << std::endl; 00593 outFile << "Flow ID: " << it->getId() << std::endl; 00594 outFile << "From:\t" << fit->getSrcIP().str() << ":" << fit->getSrcPort() << std::endl; 00595 outFile << "To:\t" << fit->getDstIP().str() << ":" << fit->getDstPort() << std::endl; 00596 if(fit->getProtocol() == IP_PROT_TCP) 00597 outFile << "Protocol: TCP" << std::endl; 00598 if(fit->getProtocol() == IP_PROT_UDP) 00599 outFile << "Protocol: UDP" << std::endl; 00600 outFile << "----------------------------------------------------------" << std::endl; 00601 if(it->getTotalRcvPkts() > 0) 00602 { 00603 if(numFlows == 0) 00604 { 00605 tStartTime = it->getStartTime(); 00606 tEndTime = it->getEndTime(); 00607 tMinDelay = it->getMinDelay(); 00608 tMaxDelay = it->getMaxDelay(); 00609 } 00610 else 00611 { 00612 if(tStartTime > it->getStartTime()) 00613 tStartTime = it->getStartTime(); 00614 if(tEndTime < it->getEndTime()) 00615 tEndTime = it->getEndTime(); 00616 if(tMinDelay > it->getMinDelay()) 00617 tMinDelay = it->getMinDelay(); 00618 if(tMaxDelay < it->getMaxDelay()) 00619 tMaxDelay = it->getMaxDelay(); 00620 } 00621 dropInFlow = it->getTotalSentPkts() - it->getTotalRcvPkts(); 00622 tSent += it->getTotalSentPkts(); 00623 tTotDelay += it->getTotalDelay(); 00624 tTotJitter += it->getTotalJitter(); 00625 tReceived += it->getTotalRcvPkts(); 00626 tBytes += it->getTotalBytes(); 00627 tDropped += dropInFlow; 00628 ++numFlows; 00629 00630 double duration = it->getEndTime() - it->getStartTime(); 00631 outFile << "Duration = " << duration << " s" << std::endl; 00632 outFile << "Received packets = " << it->getTotalRcvPkts() << std::endl; 00633 outFile << "Minimum delay = " << it->getMinDelay() << " s" << std::endl; 00634 outFile << "Maximum delay = " << it->getMaxDelay() << " s" << std::endl; 00635 outFile << "Average delay = " << it->getTotalDelay() / it->getTotalRcvPkts() << " s" << std::endl; 00636 outFile << "Average jitter = " << it->getTotalJitter() / it->getTotalRcvPkts() << " s" << std::endl; 00637 outFile << "Bytes received = " << it->getTotalBytes() << std::endl; 00638 outFile << "Average bitrate = " << (it->getTotalBytes() * 8)/(duration * 1000) << " Kbit/s" << std::endl; 00639 outFile << "Average packet rate = " << it->getTotalRcvPkts()/duration << " pkt/s" << std::endl; 00640 outFile << "Packets dropped = " << dropInFlow << std::endl; 00641 outFile << "Percent dropped = " << ((double)(dropInFlow* 100)) / it->getTotalSentPkts() << " %"<< std::endl; 00642 } 00643 else 00644 { 00645 outFile << "No received data yet" << std::endl; 00646 } 00647 00648 outFile << "----------------------------------------------------------" << std::endl; 00649 00650 } 00651 outFile << std::endl; 00652 outFile << "__________________________________________________________" << std::endl; 00653 outFile << "**************** TOTAL RESULTS ******************" << std::endl; 00654 outFile << "__________________________________________________________" << std::endl; 00655 00656 double duration = tEndTime - tStartTime; 00657 outFile << "Number of flows = " << numFlows << std::endl; 00658 outFile << "Duration = " << duration << " s" << std::endl; 00659 outFile << "Received packets = " << tReceived << std::endl; 00660 outFile << "Minimum delay = " << tMinDelay << " s" << std::endl; 00661 outFile << "Maximum delay = " << tMaxDelay << " s" << std::endl; 00662 outFile << "Average delay = " << tTotDelay / tReceived << " s" << std::endl; 00663 outFile << "Average jitter = " << tTotJitter / tReceived << " s" << std::endl; 00664 outFile << "Bytes received = " << tBytes << std::endl; 00665 outFile << "Average bitrate = " << (tBytes * 8)/(duration * 1000) << " Kbit/s" << std::endl; 00666 outFile << "Average packet rate = " << tReceived/duration << " pkt/s" << std::endl; 00667 outFile << "Packets dropped = " << tDropped << std::endl; 00668 outFile << "Percent dropped = " << ((double) (tDropped * 100 ))/ tSent << " %"<< std::endl; 00669 00670 outFile << "----------------------------------------------------------" << std::endl; 00671 00672 outFile.close(); 00673 } 00674 } 00675 00676 /* 00677 * getFlowById(): 00678 * Funkcia najde tok podla jeho identifikatora 00679 * @param s_id - identifikator toku 00680 * @return - Vrati itertor na zanam statistik 00681 */ 00682 TG::Flows::iterator TrafGen::getFlowById(std::string s_id) 00683 { 00684 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00685 { 00686 if(it->getId() == s_id) 00687 return it; 00688 } 00689 return flows.end(); 00690 } 00691 00692 /* 00693 * getSntFlowStatById(): 00694 * Funkcia najde podla identifikatora statisitiky odoslanych paketov daneho toku 00695 * @param s_id - identifikator toku 00696 * @return - Vrati itertor na zanam statistik 00697 */ 00698 TG::SntStats::iterator TrafGen::getSntFlowStatById(std::string s_id) 00699 { 00700 for(TG::SntStats::iterator it = sentStatistics.begin(); it != sentStatistics.end(); ++it) 00701 { 00702 if(it->getId() == s_id) 00703 return it; 00704 } 00705 return sentStatistics.end(); 00706 } 00707 00708 /* 00709 * getRcvFlowStatById(): 00710 * Funkcia najde podla identifikatora statisitiky prijatych paketov daneho toku 00711 * @param r_id - identifikator toku 00712 * @return - Vrati itertor na zanam statistik 00713 */ 00714 TG::RcvStats::iterator TrafGen::getRcvFlowStatById(std::string r_id) 00715 { 00716 for(TG::RcvStats::iterator it = receivedStatistics.begin(); it != receivedStatistics.end(); ++it) 00717 { 00718 if(it->getId() == r_id) 00719 return it; 00720 } 00721 return receivedStatistics.end(); 00722 } 00723 00724 /* 00725 * getDscpByFlowInfo(): 00726 * Funkcia zisti DSCP hodnotu toku podla danych parametrov 00727 * @param srcAdd - zdrojova IP adresa toku 00728 * @param destAdd - cielova IP adresa toku 00729 * @param prot - transportny protokol toku 00730 * @param srcPort - zdrojovy port toku 00731 * @param destPort - cielovy port toku 00732 * @return - Vrati zistenu DSCP hodnotu 00733 */ 00734 unsigned char TrafGen::getDscpByFlowInfo(IPAddress &srcAdd,IPAddress &destAdd, short prot, int srcPort, int destPort) 00735 { 00736 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00737 { 00738 if(it->getSrcIP() == srcAdd && it->getDstIP() == destAdd && it->getProtocol() == prot) 00739 if(it->getSrcPort() == srcPort && it->getDstPort() == destPort) 00740 return it->getTos(); 00741 } 00742 return 0; 00743 } 00744 00745 /* 00746 * getTtlByFlowInfo(): 00747 * Funkcia zisti TTL hodnotu toku podla danych parametrov 00748 * @param srcAdd - zdrojova IP adresa toku 00749 * @param destAdd - cielova IP adresa toku 00750 * @param prot - transportny protokol toku 00751 * @param srcPort - zdrojovy port toku 00752 * @param destPort - cielovy port toku 00753 * @return - Vrati zistenu ttl hodnotu 00754 */ 00755 short TrafGen::getTtlByFlowInfo(IPAddress &srcAdd,IPAddress &destAdd, short prot, int srcPort, int destPort) 00756 { 00757 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00758 { 00759 if(it->getSrcIP() == srcAdd && it->getDstIP() == destAdd && it->getProtocol() == prot) 00760 if(it->getSrcPort() == srcPort && it->getDstPort() == destPort) 00761 return it->getTtl(); 00762 } 00763 return 32; 00764 } 00765 00766 /* 00767 * isLocalTcpOrig(): 00768 * Funkcia zisti ci je povodcom TCP spojenie s danym ID 00769 * @param id - identifikator TCP spojenia 00770 * @return - Vrati true pokial je povodcom 00771 */ 00772 bool TrafGen::isLocalTcpOrig(int id) 00773 { 00774 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00775 { 00776 if(it->isSocketCreated()) 00777 if(it->getSocketConId() == id) 00778 return true; 00779 } 00780 return false; 00781 } 00782 00783 /* 00784 * isListening(): 00785 * Funkcia zisti ci na danm porte uz naslucha 00786 * @param prot - protokol (TCP/UDP) 00787 * @param port - port 00788 * @return - Vrati true uz na dom porte danslucha 00789 */ 00790 bool TrafGen::isListening(short prot, int port) 00791 { 00792 std::vector<int>::iterator it; 00793 00794 if (prot == IP_PROT_UDP) 00795 { 00796 for(it=udpListenPort.begin(); it<udpListenPort.end(); ++it) 00797 if(*it == port) 00798 return true; 00799 } 00800 else if (prot == IP_PROT_TCP) 00801 { 00802 for(it=tcpListenPort.begin(); it<tcpListenPort.end(); ++it) 00803 if(*it == port) 00804 return true; 00805 } 00806 return false; 00807 } 00808 00809 void TrafGen::updateSentStats(cPacket * payload) 00810 { 00811 if(payload != NULL) 00812 { 00813 std::string type = payload->getClassName(); 00814 if(type == "TrafGenPacket") 00815 { 00816 TrafGenPacket *TGpacket = dynamic_cast<TrafGenPacket*> (payload); 00817 TG::Flows::iterator flowIt = getFlowById(TGpacket->getFlowId()); 00818 // aktualizacia statistik odoslanych paketov 00819 int appDataLen = TGpacket->getByteLength() - flowIt->getPApplication()->anotherEncapsulationOverhead(); 00820 00821 getSntFlowStatById(flowIt->getId())->addTotalSentPkts(); 00822 getSntFlowStatById(flowIt->getId())->addTotalBytes(appDataLen); 00823 flowIt->getRcvModStatsIt()->addTotalSentPkts(); 00824 numSent++; 00825 } 00826 delete payload; 00827 } 00828 } 00829 00830 /* 00831 * FlowRecord(): 00832 * Konstruktor zaznamu o toku - inicializuje premenne 00833 */ 00834 TG::FlowRecord::FlowRecord() 00835 { 00836 id.erase(); 00837 startTime = 0.0; 00838 duration = 0.0; 00839 srcIP = IPAddress::UNSPECIFIED_ADDRESS; 00840 dstIP = IPAddress::UNSPECIFIED_ADDRESS; 00841 tos = 0; 00842 ttl = 0; 00843 protocol = 0; 00844 srcPort = 0; 00845 dstPort = 0; 00846 00847 pApplication = NULL; 00848 socket = NULL; 00849 00850 generating = false; 00851 analyzing = false; 00852 } 00853 00854 /* 00855 * setApplication(): 00856 * Funkcia pre dany tok vytvori objekt aplikacie a nacita jej konfiguraciu 00857 * @param appConfig - XML blok s konfiguraciu aplikacie 00858 * @return - Vrati true pokial bola aplikacia spravne nastavena 00859 */ 00860 bool TG::FlowRecord::setApplication(const cXMLElement& appConfig) 00861 { 00862 appName = appConfig.getAttribute("type"); 00863 00864 pApplication = check_and_cast<ITrafGenApplication *>(createOne(appName.c_str())); 00865 00866 if(pApplication != NULL) 00867 return pApplication->loadConfig(appConfig); 00868 00869 return false; 00870 } 00871 00872 /* 00873 * tcpConnect(): 00874 * Funkcia vytvory pre dany tok TCP spojenie 00875 * @param toTcp - ukazovatel na vystupnu branu k TCP modulu 00876 */ 00877 void TG::FlowRecord::tcpConnect(cGate *toTcp) 00878 { 00879 socket = new TCPSocket(); 00880 // nastavenie parametrov soketu 00881 socket->bind(srcIP, srcPort); 00882 socket->setOutputGate(toTcp); 00883 00884 // pripojenie TCP soketu 00885 socket->connect(dstIP, dstPort); 00886 } 00887 00888 /* 00889 * RcvFlowRecord(): 00890 * Konstruktor zaznomov o prijatych paketoch - nastavi hodnoty na nulu 00891 */ 00892 TG::RcvFlowRecord::RcvFlowRecord() 00893 { 00894 startTime = 0.0; 00895 totalSentPkts = 0; 00896 totalRcvPkts = 0; 00897 minDelay = 0.0; 00898 maxDelay = 0.0; 00899 totalDelay = 0.0; 00900 totalJitter = 0.0; 00901 totalBytes = 0.0; 00902 } 00903 00904 /* 00905 * ~TrafGen(): 00906 * Destruktor modulu - uvolni vektorove objekty pre zaznam statistik 00907 */ 00908 TrafGen::~TrafGen() 00909 { 00910 std::map<std::string, cOutVector*>::iterator it; 00911 00912 for (it=actBitrateVec.begin(); it!=actBitrateVec.end(); ++it) 00913 delete it->second; 00914 actBitrateVec.clear(); 00915 00916 for (it=actPacketrateVec.begin(); it!=actPacketrateVec.end(); ++it) 00917 delete it->second; 00918 actPacketrateVec.clear(); 00919 00920 } 00921 00922 /* 00923 * getActBitrate(): 00924 * Funkcia vrati aktualnu prenosovu rychlost za poslednu sekundu 00925 * @return - Vrati prenosovy rychlost 00926 */ 00927 double TG::RcvFlowRecord::getActBitrate() 00928 { 00929 actualizeVector(); 00930 std::vector<PktRec>::iterator it; 00931 double bitrate = 0.0; 00932 for(it=actStat.begin(); it!=actStat.end(); ++it) 00933 bitrate += it->getLength()*8; 00934 00935 return bitrate/1000; 00936 } 00937 00938 /* 00939 * actualizeVector(): 00940 * Aktualizuje vektor pre vypocet aktualnej rychlosti - ostrani zaznamy starsie ako jedna sekunda 00941 */ 00942 void TG::RcvFlowRecord::actualizeVector() 00943 { 00944 while((actStat.size() > 0) && (actStat.front().getTime() < (simTime().dbl() - 1.0))) 00945 actStat.erase(actStat.begin()); 00946 } 00947 00948 /* 00949 * updateActVectorStats(): 00950 * Zapise do vektorovych statistik aktualnu rychlost primania vo vsetkych analyzovanych tokoch 00951 */ 00952 void TrafGen::updateActVectorStats() 00953 { 00954 00955 for(TG::Flows::iterator it = flows.begin(); it != flows.end(); ++it) 00956 { 00957 if(it->isAnalyzing()) 00958 { 00959 TG::RcvStats::iterator flowStatIt = getRcvFlowStatById(it->getId()); 00960 if(flowStatIt != receivedStatistics.end()) 00961 { 00962 actBitrateVec[it->getId()]->record(flowStatIt->getActBitrate()); 00963 actPacketrateVec[it->getId()]->record(flowStatIt->getActualPacketrate()); 00964 } 00965 } 00966 } 00967 00968 } 00969