INET Framework for OMNeT++/OMNEST
AnsaQosClassifiers.cc
Go to the documentation of this file.
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 #include "AnsaQosClassifiers.h"
00020 
00021 /*
00022  * Pretazenie operatoru "==" pre porovnanie tokov 
00023  */
00024 
00025 bool ANSAQOS::Flow::operator==(const Flow& flow) const
00026 {
00027     if(srcAddress != flow.srcAddress)
00028         return false;
00029     if(destAddress != flow.destAddress)
00030         return false;
00031     if(transportProtocol != flow.transportProtocol)
00032         return false;
00033     if(ipPrec != flow.ipPrec)
00034         return false;
00035     if(srcPort != flow.srcPort)
00036         return false;
00037     if(destPort != flow.destPort)
00038         return false;
00039     
00040     return true;
00041 }
00042 
00043 /*
00044  * parseFromMsg(): 
00045  * Konstruktor toku, ktory nacita hodnoty zo spravy (TCP/UDP paketu)
00046  * @param msg   - sprava z ktora definuje parametre toku 
00047  */
00048  
00049 void ANSAQOS::Flow::parseFromMsg(cMessage *msg)
00050 {
00051   cMessage *copy = msg->dup();
00052 
00053   if (dynamic_cast<IPDatagram *>(copy))
00054   {
00055     IPDatagram *datagram = (IPDatagram *)copy;
00056         
00057     srcAddress = datagram->getSrcAddress();
00058     destAddress = datagram->getDestAddress();
00059     transportProtocol = datagram->getTransportProtocol();
00060     ipPrec = (short) datagram->getDiffServCodePoint()/32; // prve 3 bity ToS
00061     if(transportProtocol == IP_PROT_TCP)
00062     {
00063       TCPSegment *tcpSegm = dynamic_cast<TCPSegment *> (datagram->decapsulate());
00064       srcPort = tcpSegm->getSrcPort();
00065       destPort = tcpSegm->getDestPort();
00066       delete tcpSegm;
00067     }
00068     else if(transportProtocol == IP_PROT_UDP)
00069     {
00070       UDPPacket *udpDatag  = dynamic_cast<UDPPacket *> (datagram->decapsulate());
00071       srcPort = udpDatag->getSourcePort();
00072       destPort = udpDatag->getDestinationPort();
00073       delete udpDatag;
00074     }
00075     else
00076     {
00077       srcPort = 0;
00078       destPort = 0;
00079     }      
00080   }
00081   else
00082   {
00083     srcAddress = IPAddress::UNSPECIFIED_ADDRESS;
00084     destAddress = IPAddress::UNSPECIFIED_ADDRESS;
00085     transportProtocol = 0;
00086     ipPrec = 0;
00087     srcPort = 0;
00088     destPort = 0;
00089   }
00090   
00091   delete copy;
00092 
00093 }
00094 
00095 /*
00096  * WFQClassifier(): 
00097  * Konstruktor klasifikatoru WFQ fronty, ktory je vytvoreny 
00098  * na zaklade spravy (TCP/UDP paketu)
00099  * @param msg   - sprava z ktora definuje parametre toku 
00100  */
00101  
00102 ANSAQOS::WFQClassifier::WFQClassifier(cMessage *msg)
00103 {
00104   /* Nacita tok na zaklade hlaviciek spravy */
00105   flowID.parseFromMsg(msg);
00106 
00107   /* Vytvorenie stringu pre graficke rozhranie */    
00108   std::stringstream info;
00109   info << "Flow: src: ";
00110   info << flowID.srcAddress.str();
00111   info << ":";
00112   info << flowID.srcPort;
00113   info << " dest: ";
00114   info << flowID.destAddress.str();
00115   info << ":"; 
00116   info << flowID.destPort;
00117   info << " prec: ";
00118   info << flowID.ipPrec;
00119   info << " prot: ";
00120   info << flowID.transportProtocol; 
00121   infoString = info.str();  
00122 }
00123 
00124 /*
00125  * classifyPacket(): 
00126  * Funkcia rozhoduje o klasifikacii spravy do daneho toku
00127  * @param msg   - sprava, ktora ma byt klasifikovana
00128  * @return - Vrati true pokial je sprava klasifikovana 
00129  */
00130  
00131 bool ANSAQOS::WFQClassifier::classifyPacket(cMessage *msg)
00132 {
00133   if (flowID == Flow(msg))
00134       return true;
00135   return false;
00136 }
00137 
00138 /*
00139  * ACLClassifier(): 
00140  * Konstruktor ACL klasifikatoru, ktory nacita parametre zo XML. 
00141  * @param clsfrConfig   - XML blok s konfiguraciou klasifikatora 
00142  */
00143 
00144 ANSAQOS::ACLClassifier::ACLClassifier(cXMLElement& clsfrConfig)
00145 {
00146   /* Ziska pristup do ACL kontajneru smerovaca */  
00147   aclAccess = AclContainerAccess().get();
00148   
00149   /* Do retazca uklada informacie pre graficke rozhranie */ 
00150   infoString = "ACL:=";
00151   
00152   /* Prechadzanie elementov XML konfiguracie */  
00153   cXMLElementList aclDetails = clsfrConfig.getChildren();
00154   for (cXMLElementList::iterator aclElemIt = aclDetails.begin(); aclElemIt != aclDetails.end(); ++aclElemIt) 
00155   {
00156     std::string nodeName = (*aclElemIt)->getTagName();
00157     if (nodeName == "acl")
00158     {
00159       std::string aclname = (*aclElemIt)->getNodeValue();
00160       if (aclname.length() > 0 )
00161       {
00162         acls.push_back(aclname);
00163         infoString += " ";
00164         infoString += aclname;
00165         if(!aclAccess->existAcl(aclname))
00166           infoString += " (not defined)";
00167       }
00168     }
00169   }
00170    
00171 }
00172 
00173 /*
00174  * classifyPacket(): 
00175  * Funkcia rozhoduje o klasifikacii spravy danym ACL
00176  * @param msg   - sprava, ktora ma byt klasifikovana
00177  * @return - Vrati true pokial je sprava klasifikovana  
00178  */
00179 
00180 bool ANSAQOS::ACLClassifier::classifyPacket(cMessage *msg)
00181 {
00182   std::vector<std::string>::iterator it;
00183 
00184   for(it = acls.begin(); it != acls.end(); ++it )
00185   {  
00186     if (aclAccess->matchPacketToAcl(*it, msg))
00187       return true;
00188   }   
00189   return false;
00190 }
00191 
00192 /*
00193  * readDscp(): 
00194  * Funkcia prevedie string z DSCP hodnotou na 8 bitovu hodotu ToS
00195  * @param dscpString    - retazec DSCP hodnoty
00196  * @return - Vrati hodnotu ToS zakodovanu v DSCP retazcu  
00197  */
00198 
00199 unsigned char ANSAQOS::DSCPClassifier::readDscp(std::string dscpString)
00200 {
00201 
00202   if(dscpString.size() == 3)
00203   {
00204     std::string prf = dscpString.substr(0,2);
00205     unsigned char cls = dscpString[2] - '0';
00206     if((prf == "CS" || prf == "Cs" || prf == "cs") && cls > 0 && cls < 8)
00207       return cls*32; 
00208   }
00209   else if (dscpString.size() == 4)
00210   {
00211     std::string prf = dscpString.substr(0,2);
00212     unsigned char cls =  dscpString[2] - '0';
00213     unsigned char dp = dscpString[3] - '0';
00214     if((prf == "AF" || prf == "Af" || prf == "af") && cls > 0 && cls < 5 && dp > 0 && dp < 4)
00215       return cls*32 + dp*8;
00216   }
00217   else if(dscpString == "EF" || dscpString == "Ef" || dscpString == "ef")
00218     return 184;
00219 
00220   return atoi(dscpString.c_str());
00221 }
00222 
00223 /*
00224  * DSCPClassifier(): 
00225  * Konstruktor DSCP klasifikatoru, ktory nacita parametre zo XML. 
00226  * @param clsfrConfig   - XML blok s konfiguraciou klasifikatora 
00227  */
00228 
00229 ANSAQOS::DSCPClassifier::DSCPClassifier(cXMLElement& clsfrConfig)
00230 {
00231   /* Do retazca uklada informacie pre graficke rozhranie */
00232   infoString = "DSCP:=";
00233 
00234   /* Prechadzanie elementov XML konfiguracie */    
00235   cXMLElementList dscpDetails = clsfrConfig.getChildren();
00236   for (cXMLElementList::iterator dscpElemIt = dscpDetails.begin(); dscpElemIt != dscpDetails.end(); ++dscpElemIt) 
00237   {
00238     std::string nodeName = (*dscpElemIt)->getTagName();
00239     if (nodeName == "value")
00240     {
00241       std::string val = (*dscpElemIt)->getNodeValue();
00242       values.push_back(readDscp(val));
00243       infoString += " ";
00244       infoString += val;
00245     }
00246   }
00247    
00248 }
00249 
00250 /*
00251  * classifyPacket(): 
00252  * Funkcia rozhoduje o klasifikacii spravy danymi hodnotami DSCP
00253  * @param msg   - sprava, ktora ma byt klasifikovana
00254  * @return - Vrati true pokial je sprava klasifikovana  
00255  */
00256 
00257 bool ANSAQOS::DSCPClassifier::classifyPacket(cMessage *msg)
00258 {
00259   unsigned char tos;
00260   std::vector<unsigned char>::iterator it;
00261   cMessage *copy = msg->dup();
00262 
00263   if (dynamic_cast<IPDatagram *>(copy))
00264   {
00265     IPDatagram *datagram = (IPDatagram *)copy;
00266     tos = datagram->getDiffServCodePoint();
00267   }
00268   delete copy;
00269   
00270   for(it = values.begin(); it != values.end(); ++it )
00271   {  
00272     if (*it == tos)
00273       return true;
00274    }   
00275   return false;
00276 }
00277 
00278 /*
00279  * PRECClassifier(): 
00280  * Konstruktor IP precedence klasifikatoru, ktory nacita parametre zo XML. 
00281  * @param clsfrConfig   - XML blok s konfiguraciou klasifikatora 
00282  */
00283 
00284 ANSAQOS::PRECClassifier::PRECClassifier(cXMLElement& clsfrConfig)
00285 {
00286   /* Do retazca uklada informacie pre graficke rozhranie */
00287   infoString = "PREC:=";
00288   
00289   /* Prechadzanie elementov XML konfiguracie */  
00290   cXMLElementList dscpDetails = clsfrConfig.getChildren();
00291   for (cXMLElementList::iterator dscpElemIt = dscpDetails.begin(); dscpElemIt != dscpDetails.end(); ++dscpElemIt) 
00292   {
00293     std::string nodeName = (*dscpElemIt)->getTagName();
00294     if (nodeName == "value")
00295     {
00296       short val = (short) atoi((*dscpElemIt)->getNodeValue());
00297       if (val >= 0 && val <8) // IP precedence musi byt z rozsahu 0-7
00298       {
00299         values.push_back(val);
00300         infoString += " ";
00301         infoString += (*dscpElemIt)->getNodeValue();
00302       }
00303     }
00304   }
00305    
00306 }
00307 
00308 /*
00309  * classifyPacket(): 
00310  * Funkcia rozhoduje o klasifikacii spravy danymi hodnotami IP precedence
00311  * @param msg   - sprava, ktora ma byt klasifikovana
00312  * @return - Vrati true pokial je sprava klasifikovana  
00313  */
00314 
00315 bool ANSAQOS::PRECClassifier::classifyPacket(cMessage *msg)
00316 {
00317   short prec;
00318   std::vector<short>::iterator it;
00319   cMessage *copy = msg->dup();
00320 
00321   if (dynamic_cast<IPDatagram *>(copy))
00322   {
00323     IPDatagram *datagram = (IPDatagram *)copy;
00324     prec = (short) datagram->getDiffServCodePoint()/32; // prve 3bity TOS
00325   }
00326   delete copy;
00327   
00328   for(it = values.begin(); it != values.end(); ++it )
00329   {  
00330     if (*it == prec)
00331       return true;
00332    }   
00333   return false;
00334 }
00335 
00336