INET Framework for OMNeT++/OMNEST
TrafGen.cc
Go to the documentation of this file.
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