INET Framework for OMNeT++/OMNEST
ISIS.cc
Go to the documentation of this file.
00001 // Author: Matej Hrncirik
00002 // FIT VUT 2012
00003 //
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU Lesser General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program.  If not, see http://www.gnu.org/licenses/.
00017 //
00018 
00019 
00020 #include "ISIS.h"
00021 
00022 Define_Module(ISIS);
00023 
00024 ISIS::ISIS(){
00025     this->L1LSPDb = new std::vector<LSPRecord*>;
00026     this->L2LSPDb = new std::vector<LSPRecord*>;
00027 
00028     this->L1SRMBQueue = new std::vector<std::vector<FlagRecord *> *>;
00029     this->L2SRMBQueue = new std::vector<std::vector<FlagRecord *> *>;
00030 
00031     this->L1SRMPTPQueue = new std::vector<std::vector<FlagRecord *> *>;
00032     this->L2SRMPTPQueue = new std::vector<std::vector<FlagRecord *> *>;
00033 
00034     this->L1SSNBQueue = new std::vector<std::vector<FlagRecord *> *>;
00035     this->L2SSNBQueue = new std::vector<std::vector<FlagRecord *> *>;
00036 
00037     this->L1SSNPTPQueue = new std::vector<std::vector<FlagRecord *> *>;
00038     this->L2SSNPTPQueue = new std::vector<std::vector<FlagRecord *> *>;
00039 
00040 }
00041 
00042 /*
00043  * This method deallocate dynamically created objects and free their memory.
00044  */
00045 ISIS::~ISIS()
00046 {
00047     if(this->L1LSPDb != NULL){
00048         std::vector<LSPRecord *>::iterator it = this->L1LSPDb->begin();
00049         for(; it != this->L1LSPDb->end(); ++it){
00050             //delete (*it)->LSP;
00051             //delete (*it)->deadTimer;
00052             delete (*it);
00053         }
00054         this->L1LSPDb->clear();
00055         delete this->L1LSPDb;
00056     }
00057 
00058     if(this->L2LSPDb != NULL){
00059         std::vector<LSPRecord *>::iterator it = this->L2LSPDb->begin();
00060             for(; it != this->L2LSPDb->end(); ++it){
00061                 //delete (*it)->LSP;
00062                 //delete (*it)->deadTimer;
00063                 delete (*it);
00064             }
00065             this->L2LSPDb->clear();
00066             delete this->L2LSPDb;
00067         }
00068 
00069     /* delete SRM */
00070     if(this->L1SRMBQueue != NULL){
00071         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L1SRMBQueue->begin();
00072         for(; qIt != this->L1SRMBQueue->end(); ++qIt){
00073             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00074             for(; it != (*qIt)->end(); ++it){
00075                 delete (*it);
00076             }
00077             (*qIt)->clear();
00078             delete (*qIt);
00079         }
00080         this->L1SRMBQueue->clear();
00081         delete this->L1SRMBQueue;
00082     }
00083 
00084     if(this->L1SRMPTPQueue != NULL){
00085         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L1SRMPTPQueue->begin();
00086         for(; qIt != this->L1SRMPTPQueue->end(); ++qIt){
00087             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00088             for(; it != (*qIt)->end(); ++it){
00089                 delete (*it);
00090             }
00091             (*qIt)->clear();
00092             delete (*qIt);
00093         }
00094         this->L1SRMPTPQueue->clear();
00095         delete this->L1SRMPTPQueue;
00096     }
00097 
00098     if(this->L2SRMBQueue != NULL){
00099         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L2SRMBQueue->begin();
00100         for(; qIt != this->L2SRMBQueue->end(); ++qIt){
00101             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00102             for(; it != (*qIt)->end(); ++it){
00103                 delete (*it);
00104             }
00105             (*qIt)->clear();
00106             delete (*qIt);
00107         }
00108         this->L2SRMBQueue->clear();
00109         delete this->L2SRMBQueue;
00110     }
00111 
00112     if(this->L2SRMPTPQueue != NULL){
00113         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L2SRMPTPQueue->begin();
00114         for(; qIt != this->L2SRMPTPQueue->end(); ++qIt){
00115             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00116             for(; it != (*qIt)->end(); ++it){
00117                 delete (*it);
00118             }
00119             (*qIt)->clear();
00120             delete (*qIt);
00121         }
00122         this->L2SRMPTPQueue->clear();
00123         delete this->L2SRMPTPQueue;
00124     }
00125     /* end of delete SRM */
00126 
00127     /* delete SSN */
00128     if(this->L1SSNBQueue != NULL){
00129         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L1SSNBQueue->begin();
00130         for(; qIt != this->L1SSNBQueue->end(); ++qIt){
00131             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00132             for(; it != (*qIt)->end(); ++it){
00133 
00134                 delete (*it);
00135 
00136             }
00137             (*qIt)->clear();
00138             delete (*qIt);
00139         }
00140         this->L1SSNBQueue->clear();
00141         delete this->L1SSNBQueue;
00142     }
00143 
00144     if(this->L1SSNPTPQueue != NULL){
00145         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L1SSNPTPQueue->begin();
00146         for(; qIt != this->L1SSNPTPQueue->end(); ++qIt){
00147             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00148             for(; it != (*qIt)->end(); ++it){
00149                 delete (*it);
00150             }
00151             (*qIt)->clear();
00152             delete (*qIt);
00153         }
00154         this->L1SSNPTPQueue->clear();
00155         delete this->L1SSNPTPQueue;
00156     }
00157 
00158     if(this->L2SSNBQueue != NULL){
00159         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L2SSNBQueue->begin();
00160         for(; qIt != this->L2SSNBQueue->end(); ++qIt){
00161             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00162             for(; it != (*qIt)->end(); ++it){
00163                 delete (*it);
00164             }
00165             (*qIt)->clear();
00166             delete (*qIt);
00167         }
00168         this->L2SSNBQueue->clear();
00169         delete this->L2SSNBQueue;
00170     }
00171 
00172     if(this->L2SSNPTPQueue != NULL){
00173         std::vector<std::vector<FlagRecord*> *>::iterator qIt = this->L2SSNPTPQueue->begin();
00174         for(; qIt != this->L2SSNPTPQueue->end(); ++qIt){
00175             std::vector<FlagRecord*>::iterator it = (*qIt)->begin();
00176             for(; it != (*qIt)->end(); ++it){
00177                 delete (*it);
00178             }
00179             (*qIt)->clear();
00180             delete (*qIt);
00181         }
00182         this->L2SSNPTPQueue->clear();
00183         delete this->L2SSNPTPQueue;
00184     }
00185         /* end of delete SSN */
00186 
00187 }
00188 
00189 
00200 void ISIS::initialize(int stage) {
00201     //interface init at stage 2
00202     if (stage == 3) {
00203 
00204         deviceType = par("deviceType");
00205         deviceId = par("deviceId");
00206         configFile = par("configFile");
00207 
00208         ift = AnsaInterfaceTableAccess().get();
00209         if (ift == NULL) {
00210             throw cRuntimeError("AnsaInterfaceTable not found");
00211         }
00212 
00213         cXMLElement *device = xmlParser::GetDevice(deviceType, deviceId,
00214                 configFile);
00215         if (device == NULL) {
00216             EV << "deviceId " << deviceId
00217                       << ": ISIS is not enabled on this device\n";
00218             return;
00219         }
00220 
00221         //load IS-IS routing info from config file
00222         cXMLElement *isisRouting = xmlParser::GetIsisRouting(device);
00223         if (isisRouting == NULL) {
00224             EV << "deviceId " << deviceId
00225                       << ": ISIS is not enabled on this device\n";
00226             return;
00227         }
00228         //TODO: multiple NETs for migrating purposes (merging, splitting areas)
00229         cXMLElement *net = isisRouting->getFirstChildWithTag("NET");
00230         if (net == NULL) {
00231             EV << "deviceId " << deviceId
00232                       << ": Net address wasn't specified in IS-IS routing\n";
00233             return;
00234         }
00235 
00236         netAddr = net->getNodeValue();
00237         if (netAddr == NULL || strcmp("", netAddr) == 0) {
00238             EV << "deviceId " << deviceId
00239                       << ": Net address wasn't specified in IS-IS routing\n";
00240             return;
00241         } else {
00242             if (!parseNetAddr()) {
00243                 EV << "deviceId " << deviceId
00244                           << ": Invalid net address format\n";
00245                 return;
00246             } else {
00247                 EV << "deviceId " << deviceId << ": Net address set to: "
00248                           << netAddr << "\n";
00249             }
00250         }
00251 
00252         //set router IS type {L1 | L2 | L1L2 (default)}
00253         cXMLElement *routertype = isisRouting->getFirstChildWithTag("IS-Type");
00254         if (routertype == NULL) {
00255             this->isType = L1L2_TYPE;
00256         } else {
00257             const char* routerTypeValue = routertype->getNodeValue();
00258             if (routerTypeValue == NULL) {
00259                 this->isType = L1L2_TYPE;
00260             } else {
00261                 if (strcmp(routerTypeValue, "level-1") == 0) {
00262                     this->isType = L1_TYPE;
00263                 } else {
00264                     if (strcmp(routerTypeValue, "level-2") == 0) {
00265                         this->isType = L2_TYPE;
00266                     } else {
00267                         this->isType = L1L2_TYPE;
00268                     }
00269                 }
00270             }
00271         }
00272 
00273         //set L1 hello interval in seconds
00274         cXMLElement *L1HelloInt = isisRouting->getFirstChildWithTag(
00275                 "L1-Hello-Interval");
00276         if (L1HelloInt == NULL || L1HelloInt->getNodeValue() == NULL) {
00277             this->L1HelloInterval = ISIS_HELLO_INTERVAL;
00278         } else {
00279             this->L1HelloInterval = atoi(L1HelloInt->getNodeValue());
00280         }
00281 
00282         //set L1 hello multiplier
00283         cXMLElement *L1HelloMult = isisRouting->getFirstChildWithTag(
00284                 "L1-Hello-Multiplier");
00285         if (L1HelloMult == NULL || L1HelloMult->getNodeValue() == NULL) {
00286             this->L1HelloMultiplier = ISIS_HELLO_MULTIPLIER;
00287         } else {
00288             this->L1HelloMultiplier = atoi(L1HelloMult->getNodeValue());
00289         }
00290 
00291         //set L2 hello interval in seconds
00292         cXMLElement *L2HelloInt = isisRouting->getFirstChildWithTag(
00293                 "L2-Hello-Interval");
00294         if (L2HelloInt == NULL || L2HelloInt->getNodeValue() == NULL) {
00295             this->L2HelloInterval = ISIS_HELLO_INTERVAL;
00296         } else {
00297             this->L2HelloInterval = atoi(L2HelloInt->getNodeValue());
00298         }
00299 
00300         //set L2 hello multiplier
00301         cXMLElement *L2HelloMult = isisRouting->getFirstChildWithTag(
00302                 "L2-Hello-Multiplier");
00303         if (L2HelloMult == NULL || L2HelloMult->getNodeValue() == NULL) {
00304             this->L2HelloMultiplier = ISIS_HELLO_MULTIPLIER;
00305         } else {
00306             this->L2HelloMultiplier = atoi(L2HelloMult->getNodeValue());
00307         }
00308 
00309         //set lspInterval
00310         cXMLElement *cxlspInt = isisRouting->getFirstChildWithTag("LSP-Interval");
00311         if (cxlspInt == NULL || cxlspInt->getNodeValue() == NULL)
00312         {
00313             this->lspInterval = ISIS_LSP_INTERVAL;
00314         }
00315         else
00316         {
00317             this->lspInterval = atoi(cxlspInt->getNodeValue());
00318         }
00319 
00320         //set lspRefreshInterval
00321         cXMLElement *cxlspRefInt = isisRouting->getFirstChildWithTag("LSP-Refresh-Interval");
00322         if (cxlspRefInt == NULL || cxlspRefInt->getNodeValue() == NULL)
00323         {
00324             this->lspRefreshInterval = ISIS_LSP_REFRESH_INTERVAL;
00325         }
00326         else
00327         {
00328             this->lspRefreshInterval = atoi(cxlspRefInt->getNodeValue());
00329         }
00330 
00331         //set lspMaxLifetime
00332         cXMLElement *cxlspMaxLife = isisRouting->getFirstChildWithTag("LSP-Max-Lifetime");
00333         if (cxlspMaxLife == NULL || cxlspMaxLife->getNodeValue() == NULL)
00334         {
00335             this->lspMaxLifetime = ISIS_LSP_MAX_LIFETIME;
00336         }
00337         else
00338         {
00339             this->lspMaxLifetime = atoi(cxlspMaxLife->getNodeValue());
00340         }
00341 
00342         //set L1LspGenInterval (CISCO's
00343         cXMLElement *cxL1lspGenInt = isisRouting->getFirstChildWithTag("L1-LSP-Gen-Interval");
00344         if (cxL1lspGenInt == NULL || cxL1lspGenInt->getNodeValue() == NULL)
00345         {
00346             this->L1LspGenInterval = ISIS_LSP_GEN_INTERVAL;
00347         }
00348         else
00349         {
00350             this->L1LspGenInterval = atoi(cxL1lspGenInt->getNodeValue());
00351         }
00352 
00353         //set L2LspGenInterval
00354         cXMLElement *cxL2lspGenInt = isisRouting->getFirstChildWithTag("L2-LSP-Gen-Interval");
00355         if (cxL2lspGenInt == NULL || cxL2lspGenInt->getNodeValue() == NULL)
00356         {
00357             this->L2LspGenInterval = ISIS_LSP_GEN_INTERVAL;
00358         }
00359         else
00360         {
00361             this->L2LspGenInterval = atoi(cxL2lspGenInt->getNodeValue());
00362         }
00363 
00364         //set L1LspSendInterval
00365         cXMLElement *cxL1lspSendInt = isisRouting->getFirstChildWithTag("L1-LSP-Send-Interval");
00366         if (cxL1lspSendInt == NULL || cxL1lspSendInt->getNodeValue() == NULL)
00367         {
00368             this->L1LspSendInterval = ISIS_LSP_SEND_INTERVAL;
00369         }
00370         else
00371         {
00372             this->L1LspSendInterval = atoi(cxL1lspSendInt->getNodeValue());
00373         }
00374 
00375         //set L2LspSendInterval
00376         cXMLElement *cxL2lspSendInt = isisRouting->getFirstChildWithTag("L2-LSP-Send-Interval");
00377         if (cxL2lspSendInt == NULL || cxL2lspSendInt->getNodeValue() == NULL)
00378         {
00379             this->L2LspSendInterval = ISIS_LSP_SEND_INTERVAL;
00380         }
00381         else
00382         {
00383             this->L2LspSendInterval = atoi(cxL2lspSendInt->getNodeValue());
00384         }
00385 
00386         //set L1LspInitWait
00387         cXMLElement *cxL1lspInitWait = isisRouting->getFirstChildWithTag("L1-LSP-Init-Wait");
00388         if (cxL1lspInitWait == NULL || cxL1lspInitWait->getNodeValue() == NULL)
00389         {
00390             this->L1LspInitWait = ISIS_LSP_INIT_WAIT;
00391         }
00392         else
00393         {
00394             this->L1LspInitWait = atoi(cxL1lspInitWait->getNodeValue());
00395         }
00396         //set L2LspInitWait
00397         cXMLElement *cxL2lspInitWait = isisRouting->getFirstChildWithTag("L2-LSP-Init-Wait");
00398         if (cxL2lspInitWait == NULL || cxL2lspInitWait->getNodeValue() == NULL)
00399         {
00400             this->L2LspInitWait = ISIS_LSP_INIT_WAIT;
00401         }
00402         else
00403         {
00404             this->L2LspInitWait = atoi(cxL2lspInitWait->getNodeValue());
00405         }
00406 
00407         //set L1CsnpInterval
00408         cXMLElement *cxL1CsnpInt = isisRouting->getFirstChildWithTag("L1-CSNP-Interval");
00409         if (cxL1CsnpInt == NULL || cxL1CsnpInt->getNodeValue() == NULL)
00410         {
00411             this->L1CsnpInterval = ISIS_CSNP_INTERVAL;
00412         }
00413         else
00414         {
00415             this->L1CsnpInterval = atoi(cxL1CsnpInt->getNodeValue());
00416         }
00417 
00418         //set L2PsnpInterval
00419         cXMLElement *cxL2CsnpInt = isisRouting->getFirstChildWithTag("L2-CSNP-Interval");
00420         if (cxL2CsnpInt == NULL || cxL2CsnpInt->getNodeValue() == NULL)
00421         {
00422             this->L2CsnpInterval = ISIS_CSNP_INTERVAL;
00423         }
00424         else
00425         {
00426             this->L2CsnpInterval = atoi(cxL2CsnpInt->getNodeValue());
00427         }
00428 
00429         //set L1PsnpInterval
00430         cXMLElement *cxL1PsnpInt = isisRouting->getFirstChildWithTag("L1-PSNP-Interval");
00431         if (cxL1PsnpInt == NULL || cxL1PsnpInt->getNodeValue() == NULL)
00432         {
00433             this->L1PsnpInterval = ISIS_CSNP_INTERVAL;
00434         }
00435         else
00436         {
00437             this->L1PsnpInterval = atoi(cxL1PsnpInt->getNodeValue());
00438         }
00439 
00440         //set L2PsnpInterval
00441         cXMLElement *cxL2PsnpInt = isisRouting->getFirstChildWithTag("L2-PSNP-Interval");
00442         if (cxL2PsnpInt == NULL || cxL2PsnpInt->getNodeValue() == NULL)
00443         {
00444             this->L2PsnpInterval = ISIS_CSNP_INTERVAL;
00445         }
00446         else
00447         {
00448             this->L2PsnpInterval = atoi(cxL2PsnpInt->getNodeValue());
00449         }
00450 
00451 
00452         cXMLElement *interfaces = device->getFirstChildWithTag("Interfaces");
00453         if (interfaces == NULL) {
00454             EV
00455                       << "deviceId "
00456                       << deviceId
00457                       << ": <Interfaces></Interfaces> tag is missing in configuration file: \""
00458                       << configFile << "\"\n";
00459             return;
00460         }
00461 
00462         // add all interfaces to ISISIft vector containing additional information
00463         InterfaceEntry *entryIFT = new InterfaceEntry();
00464         for (int i = 0; i < ift->getNumInterfaces(); i++) {
00465             entryIFT = ift->getInterface(i);
00466             //EV << entryIFT->getNetworkLayerGateIndex() << " " << entryIFT->getName() << " " << entryIFT->getFullName() << "\n";
00467             insertIft(
00468                     entryIFT,
00469                     interfaces->getFirstChildWithAttribute("Interface", "name",
00470                             entryIFT->getName()));
00471         }
00472 
00473         //TODO passive-interface
00474 
00475 
00476         //create SRMQueue for each interface (even though it would be used only for broadcast interfaces)
00477         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00478             this->L1SRMBQueue->push_back(new std::vector<FlagRecord *>);
00479         }
00480 
00481         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00482             this->L1SRMPTPQueue->push_back(new std::vector<FlagRecord *>);
00483         }
00484 
00485         //SSNflags
00486         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00487             this->L1SSNBQueue->push_back(new std::vector<FlagRecord *>);
00488         }
00489 
00490         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00491             this->L1SSNPTPQueue->push_back(new std::vector<FlagRecord *>);
00492         }
00493 
00494 
00495         //create SRMQueue for each interface (even though it would be used only for broadcast interfaces)
00496         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00497             this->L2SRMBQueue->push_back(new std::vector<FlagRecord *>);
00498         }
00499 
00500         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00501             this->L2SRMPTPQueue->push_back(new std::vector<FlagRecord *>);
00502         }
00503 
00504         //SSNflags
00505         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00506             this->L2SSNBQueue->push_back(new std::vector<FlagRecord *>);
00507         }
00508 
00509         for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
00510             this->L2SSNPTPQueue->push_back(new std::vector<FlagRecord *>);
00511         }
00512 
00513         //TODO
00514         this->L1SPFFullInterval = ISIS_SPF_FULL_INTERVAL;
00515         this->L2SPFFullInterval = ISIS_SPF_FULL_INTERVAL;
00516 
00517 
00518     }else if(stage == 4){
00519         this->initISIS();
00520         //        ISISTimer *timerMsg = new ISISTimer("ISIS Start", ISIS_START);
00521         //        this->schedule(timerMsg);
00522     }
00523 
00524 }
00525 
00526 
00532 void ISIS::insertIft(InterfaceEntry *entry, cXMLElement *intElement)
00533 {
00534 
00535     if(intElement == NULL){
00536         return;
00537     }
00538     ISISinterface newIftEntry;
00539     newIftEntry.intID = entry->getInterfaceId();
00540 
00541     newIftEntry.gateIndex = entry->getNetworkLayerGateIndex();
00542     EV <<"deviceId: " << this->deviceId << "ISIS: adding interface, gateIndex: " <<newIftEntry.gateIndex <<endl;
00543 
00544     //set interface priority
00545     newIftEntry.priority = ISIS_DIS_PRIORITY;  //default value
00546 
00547     /* Interface is NOT enabled by default. If ANY IS-IS related property is configured on interface then it's enabled. */
00548     newIftEntry.ISISenabled = false;
00549 
00550     cXMLElement *priority = intElement->getFirstChildWithTag("ISIS-Priority");
00551     if (priority != NULL && priority->getNodeValue() != NULL)
00552     {
00553         newIftEntry.priority = (unsigned char) atoi(priority->getNodeValue());
00554         newIftEntry.ISISenabled = true;
00555     }
00556 
00557 
00558     //set network type (point-to-point vs. broadcast)
00559 
00560     newIftEntry.network = true; //default value
00561 
00562     cXMLElement *network = intElement->getFirstChildWithTag("ISIS-Network");
00563     if (network != NULL && network->getNodeValue() != NULL)
00564     {
00565         if (!strcmp(network->getNodeValue(), "point-to-point"))
00566         {
00567             newIftEntry.network = false;
00568             EV << "Interface network type is point-to-point " << network->getNodeValue() << endl;
00569         }
00570         else if (!strcmp(network->getNodeValue(), "broadcast"))
00571         {
00572             EV << "Interface network type is broadcast " << network->getNodeValue() << endl;
00573         }
00574         else
00575         {
00576             EV << "ERORR: Unrecognized interface's network type: " << network->getNodeValue() << endl;
00577 
00578         }
00579         newIftEntry.ISISenabled = true;
00580 
00581     }
00582 
00583 
00584 
00585     //set interface metric
00586 
00587     newIftEntry.metric = ISIS_METRIC;    //default value
00588 
00589         cXMLElement *metric = intElement->getFirstChildWithTag("ISIS-Metric");
00590         if(metric != NULL && metric->getNodeValue() != NULL)
00591         {
00592             newIftEntry.metric = (unsigned char) atoi(metric->getNodeValue());
00593             newIftEntry.ISISenabled = true;
00594         }
00595 
00596 
00597 
00598 
00599     //set interface type according to global router configuration
00600     switch(this->isType)
00601     {
00602         case(L1_TYPE):
00603                  newIftEntry.circuitType = L1_TYPE;
00604                  break;
00605         case(L2_TYPE):
00606                  newIftEntry.circuitType = L2_TYPE;
00607                  break;
00608         //if router is type is equal L1L2, then interface configuration sets the type
00609         default: {
00610 
00611             newIftEntry.circuitType = L1L2_TYPE;
00612 
00613             cXMLElement *circuitType = intElement->getFirstChildWithTag("ISIS-Circuit-Type");
00614             if (circuitType != NULL && circuitType->getNodeValue() != NULL)
00615             {
00616                 if (strcmp(circuitType->getNodeValue(), "L2") == 0){
00617                     newIftEntry.circuitType = L2_TYPE;
00618                 }
00619                 else
00620                 {
00621                     if (strcmp(circuitType->getNodeValue(), "L1") == 0)
00622                         newIftEntry.circuitType = L1_TYPE;
00623                 }
00624                 newIftEntry.ISISenabled = true;
00625             }
00626             else
00627             {
00628                 newIftEntry.circuitType = L1L2_TYPE;
00629             }
00630 
00631             break;
00632         }
00633     }
00634 
00635     //set L1 hello interval in seconds
00636     cXMLElement *L1HelloInt = intElement->getFirstChildWithTag(
00637             "ISIS-L1-Hello-Interval");
00638     if (L1HelloInt == NULL || L1HelloInt->getNodeValue() == NULL) {
00639         newIftEntry.L1HelloInterval = this->L1HelloInterval;
00640     } else {
00641         newIftEntry.L1HelloInterval = atoi(L1HelloInt->getNodeValue());
00642     }
00643 
00644     //set L1 hello multiplier
00645     cXMLElement *L1HelloMult = intElement->getFirstChildWithTag(
00646             "ISIS-L1-Hello-Multiplier");
00647     if (L1HelloMult == NULL || L1HelloMult->getNodeValue() == NULL) {
00648         newIftEntry.L1HelloMultiplier = this->L1HelloMultiplier;
00649     } else {
00650         newIftEntry.L1HelloMultiplier = atoi(L1HelloMult->getNodeValue());
00651     }
00652 
00653     //set L2 hello interval in seconds
00654     cXMLElement *L2HelloInt = intElement->getFirstChildWithTag(
00655             "ISIS-L2-Hello-Interval");
00656     if (L2HelloInt == NULL || L2HelloInt->getNodeValue() == NULL) {
00657         newIftEntry.L2HelloInterval = this->L2HelloInterval;
00658     } else {
00659         newIftEntry.L2HelloInterval = atoi(L2HelloInt->getNodeValue());
00660     }
00661 
00662     //set L2 hello multiplier
00663     cXMLElement *L2HelloMult = intElement->getFirstChildWithTag(
00664             "ISIS-L2-Hello-Multiplier");
00665     if (L2HelloMult == NULL || L2HelloMult->getNodeValue() == NULL) {
00666         newIftEntry.L2HelloMultiplier = this->L2HelloMultiplier;
00667     } else {
00668         newIftEntry.L2HelloMultiplier = atoi(L2HelloMult->getNodeValue());
00669     }
00670 
00671     //set lspInterval
00672     cXMLElement *cxlspInt = intElement->getFirstChildWithTag("ISIS-LSP-Interval");
00673     if (cxlspInt == NULL || cxlspInt->getNodeValue() == NULL)
00674     {
00675         newIftEntry.lspInterval = ISIS_LSP_INTERVAL;
00676     }
00677     else
00678     {
00679         newIftEntry.lspInterval = atoi(cxlspInt->getNodeValue());
00680     }
00681 
00682     //set L1CsnpInterval
00683     cXMLElement *cxL1CsnpInt = intElement->getFirstChildWithTag("ISIS-L1-CSNP-Interval");
00684     if (cxL1CsnpInt == NULL || cxL1CsnpInt->getNodeValue() == NULL)
00685     {
00686         newIftEntry.L1CsnpInterval = ISIS_CSNP_INTERVAL;
00687     }
00688     else
00689     {
00690         newIftEntry.L1CsnpInterval = atoi(cxL1CsnpInt->getNodeValue());
00691     }
00692 
00693     //set L2CsnpInterval
00694     cXMLElement *cxL2CsnpInt = intElement->getFirstChildWithTag("ISIS-L2-CSNP-Interval");
00695     if (cxL2CsnpInt == NULL || cxL2CsnpInt->getNodeValue() == NULL)
00696     {
00697         newIftEntry.L2CsnpInterval = ISIS_CSNP_INTERVAL;
00698     }
00699     else
00700     {
00701         newIftEntry.L2CsnpInterval = atoi(cxL2CsnpInt->getNodeValue());
00702     }
00703 
00704     //set L1PsnpInterval
00705     cXMLElement *cxL1PsnpInt = intElement->getFirstChildWithTag("ISIS-L1-PSNP-Interval");
00706     if (cxL1PsnpInt == NULL || cxL1PsnpInt->getNodeValue() == NULL)
00707     {
00708         newIftEntry.L1PsnpInterval = ISIS_CSNP_INTERVAL;
00709     }
00710     else
00711     {
00712         newIftEntry.L1PsnpInterval = atoi(cxL1PsnpInt->getNodeValue());
00713     }
00714 
00715     //set L2PsnpInterval
00716     cXMLElement *cxL2PsnpInt = intElement->getFirstChildWithTag("ISIS-L2-PSNP-Interval");
00717     if (cxL2PsnpInt == NULL || cxL2PsnpInt->getNodeValue() == NULL)
00718     {
00719         newIftEntry.L2PsnpInterval = ISIS_CSNP_INTERVAL;
00720     }
00721     else
00722     {
00723         newIftEntry.L2PsnpInterval = atoi(cxL2PsnpInt->getNodeValue());
00724     }
00725 
00726 
00727     //TODO  priority is not needed for point-to-point
00728     //set priority of current DIS = me at start
00729     newIftEntry.L1DISpriority = newIftEntry.priority;
00730     newIftEntry.L2DISpriority = newIftEntry.priority;
00731 
00732     //set initial designated IS as himself
00733     this->copyArrayContent((unsigned char*)this->sysId, newIftEntry.L1DIS, ISIS_SYSTEM_ID, 0, 0);
00734     //set LAN identifier; -99 is because, OMNeT starts numbering interfaces from 100 -> interfaceID 100 means LAN ID 0; and we want to start numbering from 1
00735     //newIftEntry.L1DIS[6] = entry->getInterfaceId() - 99;
00736     newIftEntry.L1DIS[ISIS_SYSTEM_ID] = newIftEntry.gateIndex + 1;
00737     //do the same for L2 DIS
00738     this->copyArrayContent((unsigned char*)this->sysId, newIftEntry.L2DIS, ISIS_SYSTEM_ID, 0, 0);
00739     //newIftEntry.L2DIS[6] = entry->getInterfaceId() - 99;
00740     newIftEntry.L2DIS[ISIS_SYSTEM_ID] = newIftEntry.gateIndex + 1;
00741 
00742     newIftEntry.passive = false;
00743     newIftEntry.entry = entry;
00744     this->ISISIft.push_back(newIftEntry);
00745 }
00746 
00747 
00748 
00749 
00753 void ISIS::initISIS()
00754 {
00755     this->initHello();
00756     this->initGenerate();
00757     this->initRefresh(); //this could be called after at least one adjcency becomes UP
00758     this->initPeriodicSend();
00759     this->initCsnp(); //this could be called within initRefresh();
00760     this->initPsnp(); //see above
00761     this->initSPF();
00762 
00763 }
00764 
00765 /*
00766  * Initiate scheduling Hello timers.
00767  */
00768 void ISIS::initHello(){
00769     ISISTimer *timerMsg;
00770     ISISinterface *iface;
00771     for (unsigned int k = 0; k < this->ISISIft.size(); k++)
00772     {
00773 
00774         //schedule Hello timer per level => check if L1L2 on broadcast => schedule two timers
00775         //on PTP is L1L2 Hello valid timer
00776         iface = &(this->ISISIft.at(k));
00777 
00778         //don't schedule sending hello PDU on passive or not ISIS-enabled interface
00779         if(!iface->ISISenabled || iface->passive){
00780             continue;
00781         }
00782 
00783 
00784         if (iface->network && iface->circuitType == L1L2_TYPE)
00785         {
00786             timerMsg = new ISISTimer("Hello_L1_timer");
00787             timerMsg->setTimerKind(HELLO_TIMER);
00788             timerMsg->setIsType(L1_TYPE);
00789             timerMsg->setInterfaceIndex(k);
00790             this->schedule(timerMsg);
00791 
00792             timerMsg = new ISISTimer("Hello_L2_timer");
00793             timerMsg->setTimerKind(HELLO_TIMER);
00794             timerMsg->setIsType(L2_TYPE);
00795             timerMsg->setInterfaceIndex(k);
00796             this->schedule(timerMsg);
00797 
00798         }
00799         else
00800         {
00801             timerMsg = new ISISTimer("Hello_timer");
00802             timerMsg->setTimerKind(HELLO_TIMER);
00803             timerMsg->setIsType(iface->circuitType);
00804             timerMsg->setInterfaceIndex(k);
00805             this->schedule(timerMsg);
00806 
00807         }
00808     }
00809 }
00810 
00811 /*
00812  * Initial schedule of timer for generating LSPs
00813  */
00814 void ISIS::initGenerate()
00815 {
00816     ISISTimer *timerMsg;
00817 
00818     if (this->isType == L1L2_TYPE)
00819     {
00820         timerMsg = new ISISTimer("Generate LSPs timer");
00821         timerMsg->setTimerKind(GENERATE_LSP_TIMER);
00822         timerMsg->setIsType(L1_TYPE);
00823         this->schedule(timerMsg);
00824 
00825         timerMsg = new ISISTimer("Generate LSPs timer");
00826         timerMsg->setTimerKind(GENERATE_LSP_TIMER);
00827         timerMsg->setIsType(L2_TYPE);
00828         this->schedule(timerMsg);
00829 
00830     }
00831     else
00832     {
00833         timerMsg = new ISISTimer("Generate LSPs timer");
00834         timerMsg->setTimerKind(GENERATE_LSP_TIMER);
00835         timerMsg->setIsType(this->isType);
00836         this->schedule(timerMsg);
00837 
00838     }
00839     EV << "ISIS: initGenerate()" << endl;
00840 
00841 }
00842 /*
00843  * Initial schedule of timer for refreshing LSPs
00844  */
00845 void ISIS::initRefresh()
00846 {
00847     ISISTimer *timerMsg;
00848 
00849     timerMsg = new ISISTimer("Refresh LSPs timer");
00850     timerMsg->setTimerKind(LSP_REFRESH);
00851     timerMsg->setIsType(this->isType);
00852     this->schedule(timerMsg);
00853     EV << "ISIS: initRefresh()" << endl;
00854 
00855 }
00856 
00857 /*
00858  * Initial schedule of timer for periodic sending LSPs.
00859  */
00860 void ISIS::initPeriodicSend()
00861 {
00862     ISISTimer *timerMsg;
00863 
00864     if (this->isType == L1L2_TYPE)
00865     {
00866         timerMsg = new ISISTimer("Periodic send");
00867         timerMsg->setTimerKind(PERIODIC_SEND);
00868         timerMsg->setIsType(L1_TYPE);
00869         this->schedule(timerMsg);
00870 
00871         timerMsg = new ISISTimer("Periodic send");
00872         timerMsg->setTimerKind(PERIODIC_SEND);
00873         timerMsg->setIsType(L2_TYPE);
00874         this->schedule(timerMsg);
00875     }
00876     else
00877     {
00878         timerMsg = new ISISTimer("Periodic send");
00879         timerMsg->setTimerKind(PERIODIC_SEND);
00880         timerMsg->setIsType(this->isType);
00881         this->schedule(timerMsg);
00882     }
00883 }
00884 
00885 /*
00886  * Initial schedule of timer for sending CSNP.
00887  */
00888 void ISIS::initCsnp()
00889 {
00890 
00891     ISISTimer *timerMsg;
00892     ISISinterface *iface;
00893     for (unsigned int k = 0; k < this->ISISIft.size(); k++)
00894     {
00895         iface = &(this->ISISIft.at(k));
00896 
00897         //don't schedule sending CSNP PDU on passive or not ISIS-enabled interface
00898         if (!iface->ISISenabled || iface->passive)
00899         {
00900             continue;
00901         }
00902 
00903         if (iface->network && iface->circuitType == L1L2_TYPE)
00904         {
00905             timerMsg = new ISISTimer("CSNP L1");
00906             timerMsg->setTimerKind(CSNP_TIMER);
00907             timerMsg->setIsType(L1_TYPE);
00908             timerMsg->setInterfaceIndex(k);
00909             this->schedule(timerMsg);
00910 
00911             timerMsg = new ISISTimer("CSNP L2");
00912             timerMsg->setTimerKind(CSNP_TIMER);
00913             timerMsg->setIsType(L2_TYPE);
00914             timerMsg->setInterfaceIndex(k);
00915             this->schedule(timerMsg);
00916 
00917         }
00918         else
00919         {
00920             timerMsg = new ISISTimer("CSNP");
00921             timerMsg->setTimerKind(CSNP_TIMER);
00922             timerMsg->setIsType(iface->circuitType);
00923             timerMsg->setInterfaceIndex(k);
00924             this->schedule(timerMsg);
00925 
00926         }
00927     }
00928 }
00929 
00930 /*
00931  * Initial schedule of timer for sending PSNP.
00932  */
00933 void ISIS::initPsnp()
00934 {
00935 
00936     ISISTimer *timerMsg;
00937     ISISinterface *iface;
00938     for (unsigned int k = 0; k < this->ISISIft.size(); k++)
00939     {
00940         iface = &(this->ISISIft.at(k));
00941 
00942         //don't schedule sending PSNP on passive or not ISIS-enabled interface
00943         if (!iface->ISISenabled || iface->passive)
00944         {
00945             continue;
00946         }
00947 
00948         if (iface->network && iface->circuitType == L1L2_TYPE)
00949         {
00950             timerMsg = new ISISTimer("PSNP L1");
00951             timerMsg->setTimerKind(PSNP_TIMER);
00952             timerMsg->setIsType(L1_TYPE);
00953             timerMsg->setInterfaceIndex(k);
00954             this->schedule(timerMsg);
00955 
00956             timerMsg = new ISISTimer("PSNP L2");
00957             timerMsg->setTimerKind(PSNP_TIMER);
00958             timerMsg->setIsType(L2_TYPE);
00959             timerMsg->setInterfaceIndex(k);
00960             this->schedule(timerMsg);
00961 
00962         }
00963         else
00964         {
00965             timerMsg = new ISISTimer("PSNP");
00966             timerMsg->setTimerKind(PSNP_TIMER);
00967             timerMsg->setIsType(iface->circuitType);
00968             timerMsg->setInterfaceIndex(k);
00969             this->schedule(timerMsg);
00970 
00971         }
00972     }
00973 }
00974 
00975 /*
00976  * Initial schedule of timer for computing shortest paths.
00977  */
00978 void ISIS::initSPF()
00979 {
00980     ISISTimer *timerMsg;
00981 
00982     if (this->isType == L1L2_TYPE)
00983     {
00984         timerMsg = new ISISTimer("L1 SPF Full");
00985         timerMsg->setTimerKind(SPF_FULL);
00986         timerMsg->setIsType(L1_TYPE);
00987         this->schedule(timerMsg);
00988 
00989         timerMsg = new ISISTimer("L2 SPF Full");
00990         timerMsg->setTimerKind(SPF_FULL);
00991         timerMsg->setIsType(L2_TYPE);
00992         this->schedule(timerMsg);
00993     }
00994     else
00995     {
00996         timerMsg = new ISISTimer("SPF Full");
00997         timerMsg->setTimerKind(SPF_FULL);
00998         timerMsg->setIsType(this->isType);
00999         this->schedule(timerMsg);
01000     }
01001 }
01002 
01003 
01009 void ISIS::handleMessage(cMessage* msg)
01010 {
01011 
01012     if (msg->isSelfMessage())
01013     {
01014         ISISTimer *timer = check_and_cast<ISISTimer *>(msg);
01015         switch (timer->getTimerKind())
01016             {
01017             case (ISIS_START):
01018                 this->initISIS();
01019                 delete timer;
01020                 break;
01021 
01022             case (HELLO_TIMER):
01023                 this->sendHelloMsg(timer);
01024                 break;
01025 
01026             case (NEIGHBOUR_DEAD):
01027                 this->removeDeadNeighbour(timer);
01028                 delete timer;
01029                 break;
01030 
01031             case (GENERATE_LSP_TIMER):
01032                 this->generateLSP(timer);
01033                 break;
01034 
01035             case (LSP_REFRESH):
01036                 this->refreshLSP(timer);
01037                 break;
01038 
01039             case (LSP_DEAD):
01040                 this->purgeLSP(this->getLspID(timer), timer->getIsType());
01041 
01042                 //delete timer; don't delete timer, it's re-used for LSP_DELETE
01043                 break;
01044 
01045             case (LSP_DELETE):
01046                 this->deleteLSP(timer);
01047                 this->drop(timer);
01048                 delete timer;
01049                 break;
01050 
01051             case (CSNP_TIMER):
01052                 if (timer->getIsType() == L1_TYPE)
01053                 {
01054                     this->sendL1Csnp(timer);
01055                 }
01056                 else if (timer->getIsType() == L2_TYPE)
01057                 {
01058                     EV << "ISIS: Warning: Discarding CSNP_TIMER for level 2" << endl;
01059                     delete timer;
01060                 }
01061                 else
01062                 {
01063                     EV << "ISIS: Warning: Discarding CSNP_TIMER for L1L2." << endl;
01064                     delete timer;
01065                 }
01066                 break;
01067 
01068             case (PSNP_TIMER):
01069                 if (timer->getIsType() == L1_TYPE)
01070                 {
01071                     this->sendL1Psnp(timer);
01072                 }
01073                 else if (timer->getIsType() == L2_TYPE)
01074                 {
01075                     delete timer;
01076                     EV << "ISIS: Warning: Discarding PSNP_TIMER for level 2" << endl;
01077                 }
01078                 else
01079                 {
01080                     delete timer;
01081                     EV << "ISIS: Warning: Discarding PSNP_TIMER for L1L2." << endl;
01082                 }
01083                 break;
01084 
01085             case (PERIODIC_SEND):
01086                 this->periodicSend(timer, timer->getIsType());
01087                 break;
01088 
01089             case (SPF_FULL):
01090                     this->fullSPF(timer);
01091             break;
01092 
01093             default:
01094                 EV<< "ISIS: Warning: Received unsupported Timer type in handleMessage" <<endl;
01095                 delete timer;
01096                 break;
01097         }
01098     }
01099     else
01100     {
01101 
01102         //every (at least all Hello) message should be checked for matching system-ID length
01103 
01104         //shouldn't check this->isType, but rather circuitType on incoming interface
01105         ISISMessage *inMsg = check_and_cast<ISISMessage *>(msg);
01106         if(!this->isMessageOK(inMsg)){
01107             EV<< "ISIS: Warning: discarding message" <<endl;
01108             //TODO schedule event discarding message
01109             delete msg;
01110             return;
01111         }
01112 
01113         //get arrival interface
01114         int gateIndex = inMsg->getArrivalGate()->getIndex();
01115         ISISinterface * tmpIntf = this->getIfaceByGateIndex(gateIndex);
01116         if(tmpIntf == NULL){
01117             EV << "ISIS: ERROR: Couldn't find interface by gate index when ISIS::handleMessage" << endl;
01118             delete msg;
01119             return;
01120         }
01121 
01122         //get circuit type for arrival interface
01123         short circuitType = tmpIntf->circuitType;
01124 
01125         /* Usually we shouldn't need to check matching circuit type with arrived message,
01126          * and these messages should be filtered based on destination MAC address.
01127          * Since we use broadcast MAC address, IS(router) cannot determine if it's
01128          * for ALL L1 or ALL L2 systems. Therefore wee need to check manually.
01129          * If appropriate Level isn't enabled on interface, then the message is dicarded.
01130         */
01131 
01132         switch (inMsg->getType())
01133         {
01134             case (LAN_L1_HELLO):
01135                 if (circuitType == L1_TYPE || circuitType == L1L2_TYPE)
01136                 {
01137                     this->handleL1HelloMsg(inMsg);
01138 
01139                     //comment if printing of the adjacency table is too disturbing
01140                     this->printAdjTable();
01141 
01142                 }else{
01143                     EV << "deviceId " << deviceId
01144                                           << ": ISIS: WARNING: Discarding LAN_L1_HELLO message on unsupported circuit type interface "<< inMsg->getId() << endl;
01145                 }
01146                 delete inMsg;
01147                 break;
01148             case (LAN_L2_HELLO):
01149                 if (circuitType == L2_TYPE || circuitType == L1L2_TYPE)
01150                 {
01151                     this->handleL2HelloMsg(inMsg);
01152                     this->printAdjTable();
01153 
01154                 }
01155                 else
01156                 {
01157                     EV << "deviceId "
01158                                     << deviceId
01159                                     << ": ISIS: WARNING: Discarding LAN_L2_HELLO message on unsupported circuit type interface "
01160                                     << inMsg->getId() << endl;
01161                 }
01162                 delete inMsg;
01163                 break;
01164             case (PTP_HELLO):
01165                     //On PTP link process all Hellos
01166                 if (circuitType != RESERVED_TYPE)
01167                 {
01168                     this->handlePTPHelloMsg(inMsg);
01169                     this->printAdjTable();
01170                 }
01171                 else
01172                 {
01173                     EV
01174                                     << "deviceId "
01175                                     << deviceId
01176                                     << ": ISIS: WARNING: Discarding PTP_HELLO message. Received RESERVED_TYPE circuit type "
01177                                     << inMsg->getId() << endl;
01178                 }
01179                 delete inMsg;
01180                 break;
01181 
01182             case (L1_LSP):
01183                 if (circuitType == L1_TYPE || circuitType == L1L2_TYPE)
01184                 {
01185                     //this->handleL1LSP(inMsg);
01186                     //this->printLSPDB();
01187 //                    std::cout<<"Handle LSP on: ";
01188 //                        this->printSysId((unsigned char *)this->sysId);
01189 //                        std::cout<< endl;
01190                     //this->printLSP(check_and_cast<ISISLSPPacket *>(msg), "Handle L1_LSP");
01191                     this->handleL1Lsp(check_and_cast<ISISLSPPacket *>(msg));
01192 
01193 
01194                     //comment if printing of the link-state database is too disturbing
01195                     this->printLSPDB();
01196                 }
01197                 else
01198                 {
01199                     EV
01200                                     << "deviceId "
01201                                     << deviceId
01202                                     << ": ISIS: WARNING: Discarding LAN_L1_HELLO message on unsupported circuit type interface "
01203                                     << inMsg->getId() << endl;
01204                 }
01205                 //delete inMsg; //TODO don't delete inMsg in new version
01206                 break;
01207 
01208             case (L1_CSNP):
01209                 if (circuitType == L1_TYPE || circuitType == L1L2_TYPE)
01210                 {
01211                     //this->handleL1CSNP(inMsg);
01212                     this->handleL1Csnp(check_and_cast<ISISCSNPPacket *>(msg));
01213                     this->printLSPDB();
01214                 }
01215                 else
01216                 {
01217                     EV
01218                                     << "deviceId "
01219                                     << deviceId
01220                                     << ": ISIS: WARNING: Discarding LAN_L1_HELLO message on unsupported circuit type interface\n"
01221                                     << inMsg->getId() << endl;
01222                 }
01223                 //delete inMsg;
01224                 break;
01225             case (L1_PSNP):
01226                 if (circuitType == L1_TYPE || circuitType == L1L2_TYPE)
01227                 {
01228                     this->handleL1Psnp(check_and_cast<ISISPSNPPacket *>(msg));
01229                     this->printLSPDB();
01230                     //delete inMsg;
01231                 }
01232                 break;
01233             default:
01234                 EV  << "deviceId " << deviceId << ": ISIS: WARNING: Discarding unknown message type. Msg id: "
01235                                 << inMsg->getId() << endl;
01236                 delete inMsg;
01237                 break;
01238 
01239         }
01240     }
01241 }
01242 
01243 
01244 
01245 
01251 void ISIS::sendHelloMsg(ISISTimer* timer)
01252 {
01253     if (this->ISISIft.at(timer->getInterfaceIndex()).network)
01254     {
01255         EV << "ISIS: sendingBroadcastHello: " << endl;
01256         this->sendBroadcastHelloMsg(timer->getInterfaceIndex(), timer->getIsType());
01257 
01258     }
01259     else
01260     {
01261         EV << "ISIS: sendingPTPHello: " << endl;
01262         this->sendPTPHelloMsg(timer->getInterfaceIndex(), timer->getIsType());
01263     }
01264     //re-schedule timer
01265     this->schedule(timer);
01266 
01267 }
01268 
01269 /*
01270  * Send hello message on specified broadcast interface.
01271  * Packets contain IS_NEIGHBOURS_HELLO and AREA_ADDRESS TLVs.
01272  * @param k is interface index (index to ISISIft)
01273  * @param circuitType is circuit type of specified interface.
01274  */
01275 void ISIS::sendBroadcastHelloMsg(int k, short circuitType){
01276     // create L1 and L2 hello packets
01277 
01278     ISISL1HelloPacket *helloL1 = new ISISL1HelloPacket("L1 Hello");
01279     ISISL2HelloPacket *helloL2 = new ISISL2HelloPacket("L2 Hello");
01280 
01281 
01282     //set circuit type field
01283     helloL1->setCircuitType(L1_TYPE);
01284     helloL2->setCircuitType(L2_TYPE);
01285 
01286 
01287     //set source id
01288     for (unsigned int i = 0; i < 6; i++)
01289     {
01290         helloL1->setSourceID(i, sysId[i]);
01291         helloL2->setSourceID(i, sysId[i]);
01292     }
01293     EV << endl;
01294 
01295 
01296 
01297     /* TODO
01298      * They should have separate Ethernet control info but OMNeT++ simulation
01299      doesn't recognize 01:80:c2:00:00:14 and 01:80:c2:00:00:15 as multicast OSI
01300      MAC addresses. Therefore destination MAC address is always set to broadcast
01301      ff:ff:ff:ff:ff:ff
01302      */
01303 
01304     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
01305     Ieee802Ctrl *ctrl2;
01306 
01307     // set DSAP & NSAP fields
01308     ctrl->setDsap(SAP_CLNS);
01309     ctrl->setSsap(SAP_CLNS);
01310 
01311     //set appropriate destination MAC addresses
01312     MACAddress ma;
01313     ma.setAddress("ff:ff:ff:ff:ff:ff");
01314 
01315     ctrl->setDest(ma);
01316 
01317     ctrl2 = ctrl->dup();
01318 
01319     //assign Ethernet control info
01320     helloL1->setControlInfo(ctrl);
01321     helloL2->setControlInfo(ctrl2);
01322 
01323 
01324     //set TLVs
01325     TLV_t myTLV;
01326     //helloL1->setTLVArraySize(0);
01327 
01328     //set area address
01329     myTLV.type = AREA_ADDRESS;
01330     myTLV.length = 3;
01331     myTLV.value = new unsigned char[3];
01332     this->copyArrayContent((unsigned char *) areaId, myTLV.value, 3, 0, 0);
01333     unsigned int tlvSize = helloL1->getTLVArraySize();
01334     helloL1->setTLVArraySize(tlvSize + 1); //resize array
01335     helloL1->setTLV(tlvSize, myTLV);
01336 
01337     tlvSize = helloL2->getTLVArraySize();
01338     helloL2->setTLVArraySize(tlvSize + 1); //resize array
01339     helloL2->setTLV(tlvSize, myTLV);
01340 
01341 
01342     //set NEIGHBOURS L1 TLV
01343     myTLV.type = IS_NEIGHBOURS_HELLO;
01344     myTLV.length = adjL1Table.size() * 6; //number of records * 6 (6 is size of system ID/MAC address)
01345     myTLV.value = new unsigned char[adjL1Table.size() * 6];
01346 
01347     for (unsigned int h = 0; h < adjL1Table.size(); h++)
01348     {
01349         this->copyArrayContent(adjL1Table.at(h).mac.getAddressBytes(), myTLV.value, 6, 0, h * 6);
01350     }
01351 
01352     tlvSize = helloL1->getTLVArraySize();
01353     helloL1->setTLVArraySize(tlvSize + 1);
01354     helloL1->setTLV(tlvSize, myTLV);
01355 
01356     //L2 neighbours
01357     myTLV.type = IS_NEIGHBOURS_HELLO;
01358     myTLV.length = adjL2Table.size() * 6; //number of records * 6 (6 is size of system ID/MAC address)
01359     myTLV.value = new unsigned char[adjL2Table.size() * 6];
01360     //L2 neighbours
01361     for (unsigned int h = 0; h < adjL2Table.size(); h++)
01362     {
01363         this->copyArrayContent(adjL2Table.at(h).mac.getAddressBytes(), myTLV.value, 6, 0, h * 6);
01364     }
01365 
01366     tlvSize = helloL2->getTLVArraySize();
01367     helloL2->setTLVArraySize(tlvSize + 1);
01368     helloL2->setTLV(tlvSize, myTLV);
01369 
01370 
01371     //PADDING TLV is omitted
01372 
01373     //TODO Authentication TLV
01374 
01375     //TODO add eventually another TLVs (eg. from RFC 1195)
01376 
01377     //don't send hello packets from passive interfaces
01378     if (!ISISIft.at(k).passive && ISISIft.at(k).ISISenabled)
01379     {
01380         // if this interface is DIS for LAN, hellos are sent 3-times faster (3.33sec instead of 10.0)
01381         // decision is made according to global hello counter (dirty hax - don't blame me pls, but i don't have time to code it nice way :)
01382 
01383         switch (ISISIft.at(k).circuitType)
01384             {
01385             case (L1_TYPE): {
01386                 //copy packet with control info
01387                 ISISL1HelloPacket *copy1 = helloL1->dup();
01388                 Ieee802Ctrl *ctrlCopy1 = ctrl->dup();
01389                 copy1->setControlInfo(ctrlCopy1);
01390 
01391                 //set LAN ID field (designated L1 IS)
01392                 for (unsigned int j = 0; j < 7; j++)
01393                 {
01394                     copy1->setLanID(j, ISISIft.at(k).L1DIS[j]);
01395                 }
01396 
01397                 copy1->setPriority(ISISIft.at(k).priority);
01398                 send(copy1, "ifOut", ISISIft.at(k).gateIndex);
01399                 EV
01400                         << "'devideId :" << deviceId << " ISIS: L1 Hello packet was sent from "
01401                                 << ISISIft.at(k).entry->getName() << "\n";
01402                 break;
01403             }
01404             case (L2_TYPE): { //copy packet with control info
01405                 ISISL2HelloPacket *copy2 = helloL2->dup();
01406                 Ieee802Ctrl *ctrlCopy2 = ctrl->dup();
01407                 copy2->setControlInfo(ctrlCopy2);
01408 
01409                 //set LAN ID field (designated L2 IS)
01410                 for (unsigned int j = 0; j < 7; j++)
01411                 {
01412                     copy2->setLanID(j, ISISIft.at(k).L2DIS[j]);
01413                 }
01414 
01415                 copy2->setPriority(ISISIft.at(k).priority);
01416                 send(copy2, "ifOut", ISISIft.at(k).gateIndex);
01417                 EV
01418                         << "deviceId " << deviceId << ": L2 Hello packet was sent from "
01419                                 << ISISIft.at(k).entry->getName() << "\n";
01420                 break;
01421             }
01422             case (L1L2_TYPE): {
01423                 /*Newly this method should be called per circuit type so this "case" shouldn't be needed.
01424                 * Before deletion, this behavior needs to be implemented on several places throughout the code.
01425                 * Mainly in initISIS and rescheduling new events.
01426                 */
01427                 //send both - L1 & L2 hellos
01428                 ISISL1HelloPacket *copy = helloL1->dup();
01429                 Ieee802Ctrl *ctrlCopy = ctrl->dup();
01430                 copy->setControlInfo(ctrlCopy);
01431                 //set LAN ID field (designated L1 IS)
01432                 for (unsigned int j = 0; j < 7; j++)
01433                 {
01434                     copy->setLanID(j, ISISIft.at(k).L1DIS[j]);
01435                 }
01436                 copy->setPriority(ISISIft.at(k).priority);
01437                 send(copy, "ifOut", ISISIft.at(k).gateIndex);
01438                 EV
01439                         << "'devideId " << deviceId << ": L1 Hello packet was sent from "
01440                                 << ISISIft.at(k).entry->getName() << "\n";
01441 
01442                 ISISL2HelloPacket *copy2 = helloL2->dup();
01443                 Ieee802Ctrl *ctrlCopy2 = ctrl->dup();
01444                 copy2 = helloL2->dup();
01445                 ctrlCopy2 = ctrl->dup();
01446                 copy2->setControlInfo(ctrlCopy2);
01447                 //set LAN ID field (designated L2 IS)
01448                 for (unsigned int j = 0; j < 7; j++)
01449                 {
01450                     copy2->setLanID(j, ISISIft.at(k).L2DIS[j]);
01451                 }
01452                 copy2->setPriority(ISISIft.at(k).priority);
01453                 send(copy2, "ifOut", ISISIft.at(k).gateIndex);
01454                 EV
01455                         << "deviceId " << deviceId << ": L2 Hello packet was sent from "
01456                                 << ISISIft.at(k).entry->getName() << "\n";
01457                 break;
01458             }
01459             default:
01460                 EV << "deviceId " << deviceId << ": Warning: Unrecognized circuit type" << endl;
01461                 break;
01462 
01463 
01464             }
01465 
01466     }
01467 
01468     delete helloL1;
01469     delete helloL2; //TODO
01470 }
01471 
01472 
01473 /*
01474  * Sends hello message to specified PtP interface.
01475  * Packets contain IS_NEIGHBOURS_HELLO and AREA_ADDRESS TLVs.
01476  * @param k is interface index (index to ISISIft)
01477  * @param circuitType is circuit type of specified interface.
01478  */
01479 void ISIS::sendPTPHelloMsg(int k, short circuitType){
01480     //don't send hello packets from passive interfaces
01481     if(ISISIft.at(k).passive || !ISISIft.at(k).ISISenabled){
01482         return;
01483     }
01484 
01485     /* TODO
01486      * They should have separate Ethernet control info but OMNeT++ simulation
01487      doesn't recognize 01:80:c2:00:00:14 and 01:80:c2:00:00:15 as multicast OSI
01488      MAC addresses. Therefore destination MAC address is always set to broadcast
01489      ff:ff:ff:ff:ff:ff
01490      */
01491 
01492     //TODO change to appropriate layer-2 protocol
01493     Ieee802Ctrl *ctrlPtp = new Ieee802Ctrl();
01494 
01495     // set DSAP & NSAP fields
01496     ctrlPtp->setDsap(SAP_CLNS);
01497     ctrlPtp->setSsap(SAP_CLNS);
01498 
01499     //set appropriate destination MAC addresses
01500     MACAddress ma;
01501     ma.setAddress("ff:ff:ff:ff:ff:ff");
01502 
01503     ctrlPtp->setDest(ma);
01504 
01505     //type
01506     ISISPTPHelloPacket *ptpHello = new ISISPTPHelloPacket("PTP Hello");
01507 
01508     //assign Ethernet control info
01509     ptpHello->setControlInfo(ctrlPtp);
01510     //circuitType
01511     ptpHello->setCircuitType(ISISIft.at(k).circuitType);
01512 
01513     //sourceID
01514     //set source id
01515     for (unsigned int i = 0; i < 6; i++)
01516     {
01517         ptpHello->setSourceID(i, sysId[i]);
01518     }
01519 
01520     //holdTime
01521     //set holdTime
01522     ptpHello->setHoldTime(this->getHoldTime(k, ISISIft.at(k).circuitType));
01523 
01524     //pduLength
01525 
01526     //localCircuitID
01527     ptpHello->setLocalCircuitID(ISISIft.at(k).gateIndex);
01528 
01529     //TLV[]
01530     //set TLVs
01531     TLV_t myTLV;
01532 
01533     //set area address
01534     myTLV.type = AREA_ADDRESS;
01535     myTLV.length = 3;
01536     myTLV.value = new unsigned char[3];
01537     this->copyArrayContent((unsigned char *) areaId, myTLV.value, 3, 0, 0);
01538 
01539     unsigned int tlvSize = ptpHello->getTLVArraySize();
01540     ptpHello->setTLVArraySize(tlvSize + 1);
01541     ptpHello->setTLV(tlvSize, myTLV);
01542 
01543         //ptp adjacency state TLV #240
01544 
01545     myTLV.type = PTP_HELLO_STATE;
01546     myTLV.length = 1;
01547     myTLV.value = new unsigned char[myTLV.length];
01548     ISISadj* tempAdj;
01549     //if adjacency for this interface exists, then its state is either UP or INIT
01550     //we also assumes that on point-to-point link only one adjacency can exist
01551     //TODO we check appropriate level adjacency table, but what to do for L1L2? In such case there's should be adjacency in both tables so we check just L1
01552     if ((tempAdj = this->getAdjByGateIndex(ISISIft.at(k).gateIndex, circuitType) ) != NULL)
01553     {
01554         if (!tempAdj->state)
01555         {
01556             myTLV.value[0] = PTP_INIT;
01557             EV << "ISIS::sendPTPHello: sending state PTP_INIT "<< endl;
01558         }
01559         else
01560         {
01561             myTLV.value[0] = PTP_UP;
01562             EV << "ISIS::sendPTPHello: sending state PTP_UP "<< endl;
01563         }
01564 
01565     }
01566     else
01567     {
01568         //if adjacency doesn't exist yet, then it's for sure down
01569         myTLV.value[0] = PTP_DOWN;
01570         EV << "ISIS::sendPTPHello: sending state PTP_DOWN "<< endl;
01571     }
01572     tlvSize = ptpHello->getTLVArraySize();
01573     ptpHello->setTLVArraySize(tlvSize + 1);
01574     ptpHello->setTLV(tlvSize, myTLV);
01575     //TODO TLV #129 Protocols supported
01576 
01577 
01578     this->send(ptpHello,"ifOut", ISISIft.at(k).gateIndex);
01579 
01580 
01581 }
01582 /*
01583  * Schedule specified timer according to it's type.
01584  * @param timer is timer to be scheduled
01585  * @param timee additional time information
01586  */
01587 void ISIS::schedule(ISISTimer *timer, double timee)
01588 {
01589 
01590     double timeAt;
01591     double randomTime;
01592 
01593 
01594     switch (timer->getTimerKind())
01595     {
01596         case (ISIS_START):
01597             this->scheduleAt(0, timer);
01598             break;
01599 
01600         case (HELLO_TIMER):
01601             timeAt = this->getHelloInterval(timer->getInterfaceIndex(), timer->getIsType());
01602             randomTime = uniform(0, 0.25 * timeAt);
01603             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01604             EV << "ISIS::schedule: timeAt: " << timeAt << " randomTime: " << randomTime << endl;
01605             break;
01606 
01607         case (NEIGHBOUR_DEAD):
01608         if(timee < 0){
01609                             EV << "ISIS: Warning: You forgot provide additional time to schedule for NEIGHBOUR_DEAD" << endl;
01610                             timee = 0;
01611                         }
01612             timeAt = timee;
01613             randomTime = uniform(0, 0.25 * timeAt);
01614             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01615             break;
01616 
01617         case (PERIODIC_SEND):
01618             if (timer->getIsType() == L1_TYPE)
01619             {
01620                 timeAt = this->L1LspSendInterval;
01621             }
01622             else if (timer->getIsType() == L2_TYPE)
01623             {
01624                 timeAt = this->L2LspSendInterval;
01625             }
01626             else
01627             {
01628                 EV << "ISIS: Warning: Unsupported IS-Type in schedule for PERIODIC_SEND" << endl;
01629             }
01630 
01631             randomTime = uniform(0, 0.25 * timeAt);
01632             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01633             break;
01634 
01635         case (LSP_REFRESH):
01636             timeAt = this->lspRefreshInterval;
01637             randomTime = uniform(0, 0.25 * timeAt);
01638             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01639             break;
01640 
01641         case (LSP_DEAD):
01642                 if(timee < 0){
01643                     EV << "ISIS: Warning: You forgot provide additional time to schedule for LSP_DEAD" << endl;
01644                     timee = 0;
01645                 }
01646             timeAt = timee;
01647             //randomTime = uniform(0, 0.25 * timeAt);
01648             this->scheduleAt(simTime() + timeAt, timer);
01649             break;
01650 
01651         case (LSP_DELETE):
01652             timeAt = this->lspMaxLifetime * 2;
01653             this->scheduleAt(simTime() + timeAt, timer);
01654             break;
01655 
01656         case (CSNP_TIMER):
01657                 if (timer->getIsType() == L1_TYPE)
01658                 {
01659                     timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L1CsnpInterval;
01660                 }
01661                 else if (timer->getIsType() == L2_TYPE)
01662                 {
01663                     timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L2CsnpInterval;
01664                 }
01665                 else
01666                 {
01667                     EV << "ISIS: Warning: Unsupported IS-Type in schedule for CSNP_TIMER" << endl;
01668                 }
01669 
01670                 randomTime = uniform(0, 0.25 * timeAt);
01671                 this->scheduleAt(simTime() + timeAt - randomTime, timer);
01672                 break;
01673         case (PSNP_TIMER):
01674                 if (timer->getIsType() == L1_TYPE)
01675                 {
01676                     timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L1PsnpInterval;
01677                 }
01678                 else if (timer->getIsType() == L2_TYPE)
01679                 {
01680                     timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L2PsnpInterval;
01681                 }
01682                 else
01683                 {
01684                     EV << "ISIS: Warning: Unsupported IS-Type in schedule for PSNP_TIMER" << endl;
01685                 }
01686 
01687                 randomTime = uniform(0, 0.25 * timeAt);
01688                 this->scheduleAt(simTime() + timeAt - randomTime, timer);
01689                 break;
01690 
01691         case (L1_CSNP):
01692             timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L1CsnpInterval;
01693             randomTime = uniform(0, 0.25 * timeAt);
01694             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01695 
01696             break;
01697 
01698         case (L1_PSNP):
01699             timeAt = this->ISISIft.at(timer->getInterfaceIndex()).L1PsnpInterval;
01700             randomTime = uniform(0, 0.25 * timeAt);
01701             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01702 
01703             break;
01704 
01705         case (GENERATE_LSP_TIMER):
01706             if (timer->getIsType() == L1_TYPE)
01707             {
01708                 if ((simTime().dbl() + this->L1LspGenInterval) * 1000 < this->L1LspInitWait)
01709                 {
01710                     timeAt = this->L1LspInitWait / 1000;
01711                 }
01712                 else
01713                 {
01714                     timeAt = this->L1LspGenInterval;
01715                 }
01716             }
01717             else if (timer->getIsType() == L2_TYPE)
01718             {
01719                 if ((simTime().dbl() + this->L2LspGenInterval) * 1000 < this->L2LspInitWait)
01720                 {
01721                     timeAt = this->L2LspInitWait / 1000;
01722                 }
01723                 else
01724                 {
01725                     timeAt = this->L2LspGenInterval;
01726                 }
01727             }else{
01728                 EV << "ISIS: ERROR: Unsupported IS-Type in PERIODIC_SEND timer" << endl;
01729             }
01730             randomTime = uniform(0, 0.25 * timeAt);
01731             this->scheduleAt(simTime() + timeAt - randomTime, timer);
01732 
01733             break;
01734 
01735         case (SPF_FULL):
01736                 if(timer->getIsType() == L1_TYPE){
01737                    timeAt = this->L1SPFFullInterval;
01738                 }else if(timer->getIsType() == L2_TYPE){
01739                     timeAt = this->L2SPFFullInterval;
01740                 }else{
01741                     EV<<"ISIS: Error Unsupported IS-Type in SPF_FULL timer" <<endl;
01742                 }
01743                 randomTime = uniform(0, 0.25 * timeAt);
01744                 this->scheduleAt(simTime() + timeAt - randomTime, timer);
01745                 break;
01746 
01747         default:
01748             EV << "ISIS: ERROR: Unsupported timer type in schedule" << endl;
01749             break;
01750     }
01751 
01752 
01753 }
01754 
01761 bool ISIS::parseNetAddr()
01762 {
01763     std::string net = netAddr;
01764     unsigned int dots = 0;
01765     size_t found;
01766 
01767     //net address (in this module - not according to standard O:-) MUST have this format:
01768     //49.0001.1921.6801.2003.00
01769 
01770     found=net.find_first_of(".");
01771     if(found != 2 || net.length()!=25)
01772     {
01773         return false;
01774     }
01775 
01776 
01777     unsigned char *area = new unsigned char[3];
01778     unsigned char *systemId = new unsigned char[6];
01779     unsigned char *nsel = new unsigned char[1];
01780 
01781     while (found!=string::npos)
01782     {
01783 
01784         switch(found){
01785             case 2:
01786                 dots++;
01787                 area[0] = (unsigned char)(atoi(net.substr(0,2).c_str()));
01788                 EV<<"BEZ ATOI" << net.substr(0,2).c_str() <<endl;
01789                 break;
01790             case 7:
01791                 dots++;
01792                 area[1] = (unsigned char)(atoi(net.substr(3,2).c_str()));
01793                 area[2] = (unsigned char)(atoi(net.substr(5,2).c_str()));
01794                 break;
01795             case 12:
01796                 dots++;
01797                 systemId[0] = (unsigned char)(atoi(net.substr(8,2).c_str()));
01798                 systemId[1] = (unsigned char)(atoi(net.substr(10,2).c_str()));
01799                 break;
01800             case 17:
01801                 dots++;
01802                 systemId[2] = (unsigned char)(atoi(net.substr(13,2).c_str()));
01803                 systemId[3] = (unsigned char)(atoi(net.substr(15,2).c_str()));
01804                 break;
01805             case 22:
01806                 dots++;
01807                 systemId[4] = (unsigned char)(atoi(net.substr(18,2).c_str()));
01808                 systemId[5] = (unsigned char)(atoi(net.substr(20,2).c_str()));
01809                 break;
01810             default:
01811                 return false;
01812                 break;
01813 
01814         }
01815 
01816         found=net.find_first_of(".",found+1);
01817     }
01818 
01819     if(dots!=5)
01820     {
01821          return false;
01822     }
01823 
01824     nsel[0] = (unsigned char)(atoi(net.substr(23,2).c_str()));
01825 
01826     //49.0001.1921.6801.2003.00
01827 
01828     areaId = area;
01829     EV <<"ISIS: AreaID: "<< areaId[0] <<endl;
01830     EV <<"ISIS: AreaID: "<< areaId[1] <<endl;
01831     EV <<"ISIS: AreaID: "<< areaId[2] <<endl;
01832     sysId = systemId;
01833     EV <<"ISIS: SystemID: "<< sysId <<endl;
01834     NSEL = nsel;
01835     EV <<"ISIS: NSEL: "<< NSEL <<endl;
01836 
01837     return true;
01838 }
01839 
01845 void ISIS::handleL1HelloMsg(ISISMessage *inMsg)
01846 {
01847 
01848     //duplicate system ID check
01849     if(this->checkDuplicateSysID(inMsg))
01850     {
01851         //TODO schedule event duplicitSystemID
01852         return;
01853     }
01854 
01855     ISISL1HelloPacket *msg = check_and_cast<ISISL1HelloPacket *>(inMsg);
01856 
01857 
01858     //check if at least one areaId matches our areaId (don't do this for L2)
01859     bool areaOK = false;
01860     TLV_t* tmpTLV;
01861     for (int i = 0; (tmpTLV = this->getTLVByType(msg, AREA_ADDRESS, i)) != NULL; i++)
01862     {
01863         areaOK = areaOK || this->isAreaIDOK(tmpTLV);
01864     }
01865 
01866     if (!areaOK)
01867     {
01868         //TODO schedule event AreaIDMismatch
01869         EV << "ISIS: Warning: L1_LAN_HELLO doesn't contain Area address TLV." << endl;
01870         return;
01871     }
01872 
01873 
01874 
01875 
01876     //if remote system ID is contained in adjL1Table
01877     ISISadj *tmpAdj;
01878     if((tmpAdj = this->getAdj(inMsg)) != NULL)
01879     {
01880 
01881         //reset timer
01882         cancelEvent(tmpAdj->timer);
01883 
01884         //TODO use this->schedule()
01885         //scheduleAt(simTime() + msg->getHoldTime(), tmpAdj->timer);
01886         this->schedule(tmpAdj->timer, msg->getHoldTime());
01887 
01888         //DONT update the interface, if the gateIndex has changed, then declare the adjacency as down or at least init and then change gateIndex
01889         //update interface
01890         //tmpAdj->gateIndex = msg->getArrivalGate()->getIndex();
01891 
01892         //check for DIS priority and eventually set new DIS if needed; do it only if exists adjacency with state "UP"
01893         if(tmpAdj->state)
01894             electL1DesignatedIS(msg);
01895 
01896         //find neighbours TLV
01897         if ((tmpTLV = this->getTLVByType(msg, IS_NEIGHBOURS_HELLO)) != NULL)
01898         {
01899             unsigned char *tmpRecord = new unsigned char[ISIS_SYSTEM_ID];
01900             //walk through all neighbour identifiers contained in TLV
01901             for (unsigned int r = 0; r < (tmpTLV->length / ISIS_SYSTEM_ID); r++)
01902             {
01903                 //check if my system id is contained in neighbour's adjL1Table
01904                 this->copyArrayContent(tmpTLV->value, tmpRecord, ISIS_SYSTEM_ID, r * ISIS_SYSTEM_ID, 0);
01905 
01906                 int gateIndex = inMsg->getArrivalGate()->getIndex();
01907                 ISISinterface *tmpIntf = this->getIfaceByGateIndex(gateIndex);
01908                 MACAddress tmpMAC = tmpIntf->entry->getMacAddress();
01909                 if (compareArrays(tmpMAC.getAddressBytes(), tmpRecord, 6))
01910                 {
01911                     //store previous state
01912                     bool changed = tmpAdj->state;
01913                     tmpAdj->state = true;
01914 
01915                     //if state changed, flood new LSP
01916                     if (changed != tmpAdj->state /*&& simTime() > 35.0*/) //TODO use at least some kind of ISIS_INITIAL_TIMER
01917                         //this->sendMyL1LSPs();
01918                     //generate event adjacencyStateChanged
01919 
01920                     break;
01921                 }
01922 
01923             }
01924             delete tmpRecord;
01925 
01926 
01927         } else {
01928             //TODO Delete after debugging
01929 
01930             EV << "ISIS: Warning: Didn't find IS_NEIGHBOURS_HELLO TLV in LAN_L1_HELLO" << endl;
01931             return;
01932         }
01933 
01934     }
01935 
01936     //else create new record in adjL1Table
01937     else
01938     {
01939         //EV << "CREATING NEW ADJ RECORD\n";
01940 
01941         //find area ID TLV
01942 
01943         //create new neighbour record and set parameters
01944         ISISadj neighbour;
01945         neighbour.state = false; //set state to initial
01946 
01947         //set timeout of neighbour
01948         neighbour.timer = new ISISTimer("Neighbour_timeout");
01949         neighbour.timer->setTimerKind(NEIGHBOUR_DEAD);
01950         neighbour.timer->setIsType(L1_TYPE);
01951         neighbour.timer->setInterfaceIndex(this->getIfaceIndex(this->getIfaceByGateIndex(neighbour.gateIndex)));
01952         //set source system ID in neighbour record & in timer to identify it
01953         //set also lspId for easier purging LSPs
01954         for (unsigned int the_game = 0; the_game < msg->getSourceIDArraySize(); the_game++)
01955         {
01956             neighbour.sysID[the_game] = msg->getSourceID(the_game);
01957             neighbour.timer->setSysID(the_game, msg->getSourceID(the_game));
01958             neighbour.timer->setLSPid(the_game, msg->getSourceID(the_game));
01959         }
01960         neighbour.timer->setLSPid(ISIS_SYSTEM_ID, 0);
01961         neighbour.timer->setLSPid(ISIS_SYSTEM_ID + 1, 0);
01962 
01963         //TODO should be from message's TLV Area Addresses
01964         for (unsigned int i = 0; i < ISIS_AREA_ID; i++){
01965             neighbour.areaID[i] = this->areaId[i];
01966         }
01967 
01968 
01969         //get source MAC address of received frame
01970         Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->getControlInfo());
01971         neighbour.mac = ctrl->getSrc();
01972 
01973         //set gate index, which is neighbour connected to
01974         neighbour.gateIndex = msg->getArrivalGate()->getIndex();
01975 
01976         //set network type
01977         neighbour.network = this->getIfaceByGateIndex(neighbour.gateIndex)->network;
01978 
01979         this->schedule(neighbour.timer, msg->getHoldTime());
01980         //scheduleAt(simTime() + msg->getHoldTime(), neighbour.timer);
01981 
01982         //insert neighbour into adjL1Table
01983         adjL1Table.push_back(neighbour);
01984         std::sort(this->adjL1Table.begin(), this->adjL1Table.end());
01985 
01986         //EV << "deviceId " << deviceId << ": new adjacency\n";
01987 
01988    }
01989 }
01990 
01996 void ISIS::handleL2HelloMsg(ISISMessage *inMsg)
01997 {
01998 
01999     //duplicate system ID check
02000     if(this->checkDuplicateSysID(inMsg))
02001     {
02002         //TODO schedule event duplicitSystemID
02003         return;
02004     }
02005 
02006 
02007     ISISL2HelloPacket *msg = check_and_cast<ISISL2HelloPacket *>(inMsg);
02008     bool idMatch = false;
02009 
02010     //check for DIS priority and eventually set new DI if needed
02011 
02012     //TODO enable L2 election when it's implemented ^_^
02013     //electL2DesignatedIS(msg);
02014 
02015 
02016     unsigned int i;
02017     //walk through adjacency table and look for existing L2 neighbours
02018     for(i=0;i<adjL2Table.size();i++)
02019     {
02020 
02021         bool found = true;
02022         //try to find match in system ID
02023         for(unsigned int j=0; j<msg->getSourceIDArraySize();j++)
02024         {
02025             if(msg->getSourceID(j) != adjL2Table.at(i).sysID[j])
02026                 found = false;
02027         }
02028 
02029         //area ID must also match
02030         for(unsigned int j=0; j<msg->getTLVArraySize();j++)
02031         {
02032             if(msg->getTLV(j).type == AREA_ADDRESS)
02033             {
02034                 if(!(this->compareArrays(msg->getTLV(j).value, adjL2Table.at(i).areaID, ISIS_AREA_ID)))
02035                 {
02036                     found = false;
02037                 }
02038             }
02039         }
02040 
02041         //if we found match
02042         if(found)
02043         {
02044             idMatch = true;
02045             break;
02046         }
02047      }
02048 
02049     //if remote system ID is contained in adjL2Table
02050     if(idMatch)
02051     {
02052 
02053         //reset timer
02054         cancelEvent(adjL2Table.at(i).timer);
02055         scheduleAt(simTime() + msg->getHoldTime(), adjL2Table.at(i).timer);
02056 
02057         //update interface
02058         adjL2Table.at(i).gateIndex = msg->getArrivalGate()->getIndex();
02059 
02060         //find neighbours TLV
02061         for(unsigned int j = 0; j< msg->getTLVArraySize(); j++)
02062         {
02063             //we found it!
02064             if(msg->getTLV(j).type == IS_NEIGHBOURS_HELLO)
02065             {
02066 
02067                 unsigned char *tmpRecord = new unsigned char [6];
02068                 //walk through all neighbour identifiers contained in TLV
02069 
02070                 //EV<< "TLV Length " << msg->getTLV(j).length <<endl;
02071                 for(unsigned int r = 0; r < (msg->getTLV(j).length / 6); r++)
02072                 {
02073                     //check if my system id is contained in neighbour's adjL1Table
02074                     this->copyArrayContent(msg->getTLV(j).value, tmpRecord, 6, r*6, 0);
02075 
02076                     EV << "MAC: ";
02077                     for(unsigned int hh = 0; hh < 6; hh++)
02078                     {
02079                         EV << setfill('0') << setw(2) << hex << (unsigned int)tmpRecord[hh] << ":";
02080                     }
02081                     EV <<endl;
02082 
02083                     //check if TLV contains one of my own MAC addresses
02084                     for(unsigned int o = 0; o<ISISIft.size(); o++)
02085                     {
02086                         MACAddress tmpMAC = ISISIft.at(o).entry->getMacAddress();
02087                         if(compareArrays(tmpMAC.getAddressBytes(), tmpRecord, 6))
02088                         {
02089                             adjL2Table.at(i).state = true;
02090                             break;
02091                         }
02092                     }
02093                 }
02094                 delete tmpRecord;
02095                 break;  //break finding cycle
02096             }
02097         }
02098     }
02099 
02100     //else create new record in adjL1Table
02101     else
02102     {
02103         //EV << "CREATING NEW ADJ RECORD\n";
02104 
02105         //find area ID TLV
02106         unsigned int k;
02107         for(k = 0; k<msg->getTLVArraySize(); k++)
02108         {
02109             //we found area ID TLV
02110             //area IDs have to be different!!
02111             if(msg->getTLV(k).type == AREA_ADDRESS)
02112             {
02113 
02114                 //create new neighbour record and set parameters
02115                 ISISadj neighbour;
02116                 neighbour.state = false;                    //set state to initial
02117 
02118                 //set timeout of neighbour
02119                 neighbour.timer = new ISISTimer("Neighbour_timeout");
02120                 neighbour.timer->setTimerKind(NEIGHBOUR_DEAD);
02121                 //TODO set interfaceIndex
02122                 neighbour.timer->setIsType(L2_TYPE);
02123                 //set source system ID in neighbour record & in timer to identify it
02124 
02125                 //set neighbours system ID
02126                 for(unsigned int the_game = 0; the_game<msg->getSourceIDArraySize(); the_game++)
02127                 {
02128                     neighbour.sysID[the_game] = msg->getSourceID(the_game);
02129                     neighbour.timer->setSysID(the_game, msg->getSourceID(the_game));
02130                 }
02131 
02132                 //set neighbours area ID
02133                 this->copyArrayContent(msg->getTLV(k).value, neighbour.areaID, msg->getTLV(k).length, 0, 0);
02134 
02135                 for(unsigned int z=0; z<msg->getTLV(k).length; z++)
02136                 {
02137                     neighbour.timer->setAreaID(z, msg->getTLV(k).value[z]);
02138                 }
02139 
02140                 //get source MAC address of received frame
02141                 Ieee802Ctrl *ctrl = check_and_cast <Ieee802Ctrl *> (msg->getControlInfo());
02142                 neighbour.mac = ctrl->getSrc();
02143 
02144                 //set gate index, which is neighbour connected to
02145                 neighbour.gateIndex = msg->getArrivalGate()->getIndex();
02146 
02147                 //set network type
02148                 neighbour.network = this->getIfaceByGateIndex(neighbour.gateIndex)->network;
02149 
02150                 this->schedule(neighbour.timer, msg->getHoldTime());
02151                 //scheduleAt(simTime() + msg->getHoldTime(), neighbour.timer);
02152 
02153                 //insert neighbour into adjL1Table
02154                 adjL2Table.push_back(neighbour);
02155                 std::sort(this->adjL2Table.begin(), this->adjL2Table.end());
02156 
02157                 //EV << "deviceId " << deviceId << ": new adjacency\n";
02158                  break;  //end cycle
02159             }
02160         }
02161    }
02162 }
02163 
02170 void ISIS::handlePTPHelloMsg(ISISMessage *inMsg){
02171     //duplicate system ID check
02172     if (this->checkDuplicateSysID(inMsg))
02173     {
02174         //TODO schedule event duplicitSystemID
02175         return;
02176     }
02177 
02178     ISISPTPHelloPacket *msg = check_and_cast<ISISPTPHelloPacket *>(inMsg);
02179 
02180     //check if at least one areaId matches our areaId (don't do this for L2)
02181     TLV_t* tmpTLV;
02182     if (msg->getCircuitType() != L2_TYPE)
02183     {
02184         bool areaOK = false;
02185         tmpTLV = this->getTLVByType(msg, AREA_ADDRESS, 0);
02186         for (int i = 0; (tmpTLV) != NULL; i++)
02187         {
02188             areaOK = areaOK || this->isAreaIDOK(tmpTLV);
02189             tmpTLV = this->getTLVByType(msg, AREA_ADDRESS, i);
02190         }
02191 
02192         if (!areaOK)
02193         {
02194             //TODO schedule event AreaIDMismatch
02195             EV << "ISIS: Warning: PTP_HELLO doesn't contain Area address TLV." << endl;
02196             return;
02197         }
02198     }
02199     //if remote system ID is contained in adjL1Table
02200     ISISadj *tmpAdj;
02201     if (msg->getCircuitType() == L1_TYPE || msg->getCircuitType() == L1L2_TYPE)
02202     {
02203 
02204         if ((tmpAdj = this->getAdj(inMsg, L1_TYPE)) != NULL)
02205         {
02206 
02207             //reset timer
02208             cancelEvent(tmpAdj->timer);
02209 
02210             //TODO use this->schedule()
02211             scheduleAt(simTime() + msg->getHoldTime(), tmpAdj->timer);
02212 
02213             //find neighbours TLV
02214             if ((tmpTLV = this->getTLVByType(msg, PTP_HELLO_STATE)) != NULL)
02215             {
02216                 if (tmpTLV->length == 1)
02217                 {
02218 
02219                     if (tmpAdj->state) //UP
02220                     {
02221 
02222                         if (tmpTLV->value[0] == PTP_UP)
02223                         {
02224                             //OK do nothing
02225                         }
02226                         else if(tmpTLV->value[0] == PTP_DOWN)
02227                         {
02228                             //state init
02229                             //TODO
02230                             tmpAdj->state = false;
02231 
02232                         }else{
02233                             //state accept
02234                         }
02235 
02236                     }
02237                     else // INIT
02238                     {
02239                         if (tmpTLV->value[0] == PTP_UP || tmpTLV->value[0] == PTP_INIT)
02240                         {
02241                             //OK
02242                             tmpAdj->state = true;
02243 //                            if (simTime() > 35.0){ //TODO use at least some kind of ISIS_INITIAL_TIMER
02244                             //this->sendMyL1LSPs();
02245 //                            }
02246                             //TODO
02247                             //schedule adjacencyStateChange(up);
02248                         }
02249                         else
02250                         {
02251                             //stay init
02252                         }
02253                     }
02254                 }
02255 
02256             }
02257             else
02258             {
02259                 //TODO Delete after debugging
02260                 EV << "ISIS: Warning: Didn't find PTP_HELLO_STATE TLV in PTP_HELLO L2" << endl;
02261                 return;
02262             }
02263 
02264         }
02265 
02266         //else create new record in adjL1Table
02267         else
02268         {
02269             //EV << "CREATING NEW ADJ RECORD\n";
02270 
02271             //find area ID TLV
02272 
02273             //create new neighbour record and set parameters
02274             ISISadj neighbour;
02275             neighbour.state = false; //set state to initial
02276 
02277             //set timeout of neighbour
02278             neighbour.timer = new ISISTimer("Neighbour_timeout");
02279             neighbour.timer->setTimerKind(NEIGHBOUR_DEAD);
02280             neighbour.timer->setIsType(L1_TYPE);
02281             neighbour.timer->setInterfaceIndex(this->getIfaceIndex(this->getIfaceByGateIndex(neighbour.gateIndex)));
02282             //set source system ID in neighbour record & in timer to identify it
02283 
02284             for (unsigned int the_game = 0; the_game < msg->getSourceIDArraySize(); the_game++)
02285             {
02286                 neighbour.sysID[the_game] = msg->getSourceID(the_game);
02287                 neighbour.timer->setSysID(the_game, msg->getSourceID(the_game));
02288             }
02289 
02290             //TODO should be from message's TLV Area Addresses
02291             for (unsigned int i = 0; i < ISIS_AREA_ID; i++)
02292             {
02293                 neighbour.areaID[i] = this->areaId[i];
02294             }
02295 
02296             //get source MAC address of received frame
02297             Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->getControlInfo());
02298             neighbour.mac = ctrl->getSrc();
02299 
02300             //set gate index, which is neighbour connected to
02301             neighbour.gateIndex = msg->getArrivalGate()->getIndex();
02302 
02303             //set network type
02304             neighbour.network = this->getIfaceByGateIndex(neighbour.gateIndex)->network;
02305 
02306             this->schedule(neighbour.timer, msg->getHoldTime());
02307             //scheduleAt(simTime() + msg->getHoldTime(), neighbour.timer);
02308 
02309             //insert neighbour into adjL1Table
02310             adjL1Table.push_back(neighbour);
02311             std::sort(this->adjL1Table.begin(), this->adjL1Table.end());
02312 
02313             //EV << "deviceId " << deviceId << ": new adjacency\n";
02314 
02315         }
02316     }
02317 
02318     if (msg->getCircuitType() == L2_TYPE || msg->getCircuitType() == L1L2_TYPE)
02319     {
02320         if ((tmpAdj = this->getAdj(inMsg, L2_TYPE)) != NULL)
02321         {
02322             //reset timer
02323             cancelEvent(tmpAdj->timer);
02324 
02325             //TODO use this->schedule()
02326             scheduleAt(simTime() + msg->getHoldTime(), tmpAdj->timer);
02327 
02328             //find neighbours TLV
02329             if ((tmpTLV = this->getTLVByType(msg, PTP_HELLO_STATE)) != NULL)
02330             {
02331                 if (tmpTLV->length == 1)
02332                 {
02333                     if (tmpAdj->state) //UP
02334                     {
02335                         if (tmpTLV->value[0] == PTP_UP)
02336                         {
02337                             //OK do nothing
02338                         }
02339                         else if (tmpTLV->value[0] == PTP_DOWN)
02340                         {
02341                             //state init
02342                             //TODO
02343                             tmpAdj->state = false;
02344 
02345                         }
02346                         else
02347                         {
02348                             //state accept
02349                         }
02350 
02351                     }
02352                     else // INIT
02353                     {
02354                         if (tmpTLV->value[0] == PTP_UP || tmpTLV->value[0] == PTP_INIT)
02355                         {
02356                             //OK
02357                             tmpAdj->state = true;
02358 //                            if (simTime() > 35.0)
02359 //                            { //TODO use at least some kind of ISIS_INITIAL_TIMER
02360                                 //this->sendMyL2LSPs();
02361 //                            }
02362                             //TODO
02363                             //schedule adjacencyStateChange(up);
02364                         }
02365                         else
02366                         {
02367                             //stay init
02368                         }
02369                     }
02370                 }
02371 
02372             }
02373             else
02374             {
02375                 //TODO Delete after debugging
02376                 EV << "ISIS: Warning: Didn't find PTP_HELLO_STATE TLV in PTP_HELLO" << endl;
02377                 return;
02378             }
02379 
02380         }
02381 
02382         //else create new record in adjL2Table
02383         else
02384         {
02385             //EV << "CREATING NEW ADJ RECORD\n";
02386 
02387             //find area ID TLV
02388 
02389             //create new neighbour record and set parameters
02390             ISISadj neighbour;
02391             neighbour.state = false; //set state to initial
02392 
02393             //set timeout of neighbour
02394             neighbour.timer = new ISISTimer("Neighbour_timeout");
02395             neighbour.timer->setTimerKind(NEIGHBOUR_DEAD);
02396             neighbour.timer->setIsType(L2_TYPE);
02397             neighbour.timer->setInterfaceIndex(this->getIfaceIndex(this->getIfaceByGateIndex(neighbour.gateIndex)));
02398 
02399             //set source system ID in neighbour record & in timer to identify it
02400             for (unsigned int the_game = 0; the_game < msg->getSourceIDArraySize(); the_game++)
02401             {
02402                 neighbour.sysID[the_game] = msg->getSourceID(the_game);
02403                 neighbour.timer->setSysID(the_game, msg->getSourceID(the_game));
02404             }
02405             //set neighbours area ID
02406             tmpTLV = this->getTLVByType(msg, AREA_ADDRESS);
02407 
02408              this->copyArrayContent(tmpTLV->value, neighbour.areaID, tmpTLV->length, 0, 0);
02409 
02410              for(unsigned int z=0; z<tmpTLV->length; z++)
02411              {
02412                  neighbour.timer->setAreaID(z, tmpTLV->value[z]);
02413              }
02414 
02415             //get source MAC address of received frame
02416             Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->getControlInfo());
02417             neighbour.mac = ctrl->getSrc();
02418 
02419             //set gate index, which is neighbour connected to
02420             neighbour.gateIndex = msg->getArrivalGate()->getIndex();
02421 
02422             //set network type
02423             neighbour.network = this->getIfaceByGateIndex(neighbour.gateIndex)->network;
02424 
02425             this->schedule(neighbour.timer, msg->getHoldTime());
02426             //scheduleAt(simTime() + msg->getHoldTime(), neighbour.timer);
02427 
02428             //insert neighbour into adjL2Table
02429             adjL2Table.push_back(neighbour);
02430             std::sort(this->adjL2Table.begin(), this->adjL2Table.end());
02431 
02432             //EV << "deviceId " << deviceId << ": new adjacency\n";
02433 
02434         }
02435 
02436     }
02437 
02438 }
02439 
02440 bool ISIS::isAdjBySystemID(unsigned char *systemID, short ciruitType)
02441 {
02442     if (ciruitType == L1_TYPE)
02443     {
02444         //walk through adjacency table and look for existing neighbours
02445         for (std::vector<ISISadj>::iterator it = this->adjL1Table.begin(); it != adjL1Table.end(); ++it)
02446         {
02447             if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02448             {
02449                 return true;
02450             }
02451 
02452         }
02453     }else if(ciruitType == L2_TYPE)
02454     {
02455         //walk through adjacency table and look for existing neighbours
02456         for (std::vector<ISISadj>::iterator it = this->adjL2Table.begin(); it != adjL2Table.end(); ++it)
02457         {
02458             if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02459             {
02460                 return true;
02461             }
02462 
02463         }
02464     }
02465 
02466     return false;
02467 }
02473 ISISadj* ISIS::getAdj(ISISMessage *inMsg, short circuitType)
02474 {
02475 //    short circuitType;
02476     unsigned char * systemID = new unsigned char[ISIS_SYSTEM_ID];
02477     std::vector<ISISadj> *adjTable;
02478 
02479     if (inMsg->getType() == LAN_L1_HELLO)
02480     {
02481         ISISL1HelloPacket *msg = check_and_cast<ISISL1HelloPacket *>(inMsg);
02482         systemID = this->getSysID(msg);
02483                     circuitType = L1_TYPE;
02484         adjTable = &(this->adjL1Table);
02485     }
02486     else if (inMsg->getType() == LAN_L2_HELLO)
02487     {
02488         ISISL2HelloPacket *msg = check_and_cast<ISISL2HelloPacket *>(inMsg);
02489         systemID = this->getSysID(msg);
02490                     circuitType = L2_TYPE;
02491         adjTable = &(this->adjL2Table);
02492     }
02493     else if (inMsg->getType() == PTP_HELLO)
02494     {
02495         ISISPTPHelloPacket *msg = check_and_cast<ISISPTPHelloPacket *>(inMsg);
02496         systemID = this->getSysID(msg);
02497 //        circuitType = msg->getCircuitType();
02498 
02499         adjTable = &(this->adjL1Table);
02500         if (circuitType == L1_TYPE)
02501         {
02502             adjTable = &(this->adjL1Table);
02503         }
02504         else if (circuitType == L2_TYPE)
02505         {
02506             adjTable = &(this->adjL2Table);
02507         }
02508     }
02509 
02510 
02511 
02512     int gateIndex = inMsg->getArrivalGate()->getIndex();
02513  //            ISISinterface * tmpIntf = this->getIfaceByGateIndex(gateIndex);
02514              //TODO for truly point-to-point link there would not be MAC address
02515              Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(inMsg->getControlInfo());
02516              MACAddress tmpMac = ctrl->getSrc();
02517 
02518     for (std::vector<ISISadj>::iterator it = adjTable->begin(); it != adjTable->end(); ++it)
02519     {
02520         //System-ID match?
02521         if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02522         {
02523 
02524             //MAC Address and gateIndex
02525             //we need to check source (tmpMac) and destination interface thru we received this hello
02526 
02527             if (tmpMac.compareTo((*it).mac) == 0 && gateIndex == (*it).gateIndex)
02528             {
02529                 if(circuitType != L2_TYPE){ //shoudn't it be "!="
02530                     //check if at least one areaId matches our areaId (don't do this for L2)
02531                     bool areaOK = false;
02532                     TLV_t* tmpTLV;
02533                     tmpTLV = this->getTLVByType(inMsg, AREA_ADDRESS, 0);
02534                     for (int i = 0; tmpTLV  != NULL; i++)
02535                     {
02536                         areaOK = areaOK || this->isAreaIDOK(tmpTLV, (*it).areaID);
02537                         tmpTLV = this->getTLVByType(inMsg, AREA_ADDRESS, i);
02538                     }
02539 
02540                     if (!areaOK)
02541                     {
02542                         //TODO schedule event AreaIDMismatch
02543 //                        EV << "ISIS: Warning: L1_LAN_HELLO doesn't contain Area address TLV." << endl;
02544                         break;
02545                     }
02546                 }
02547                 delete systemID;
02548                 return &(*it);
02549             }
02550         }
02551     }
02552     delete systemID;
02553     return NULL;
02554 
02555 }
02563 ISISadj *ISIS::getAdjBySystemID(unsigned char *systemID, short circuitType, int gateIndex){
02564 
02565     /* For redundant links there could be more than one adjacency for the same System-ID.
02566      * We should return std::vector<ISISadj> with all adjacencies */
02567 
02568     if (circuitType == L1_TYPE)
02569     {
02570 
02571         for (std::vector<ISISadj>::iterator it = this->adjL1Table.begin(); it != this->adjL1Table.end(); ++it)
02572         {
02573             if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02574             {
02575                 if (gateIndex > -1 && (*it).gateIndex != gateIndex)
02576                 {
02577                     continue;
02578                 }
02579                 return &(*it);
02580             }
02581 
02582         }
02583     }
02584     else if (circuitType == L2_TYPE)
02585     {
02586 
02587         for (std::vector<ISISadj>::iterator it = this->adjL2Table.begin(); it != this->adjL2Table.end(); ++it)
02588         {
02589             if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02590             {
02591                 if (gateIndex > -1 && (*it).gateIndex != gateIndex)
02592                 {
02593                     continue;
02594                 }
02595                 return &(*it);
02596             }
02597 
02598         }
02599     }else if (circuitType == L1L2_TYPE){
02600         EV << "ISIS: ERROR: getAdjBySystemID for L1L2_TYPE is not implemented (yet)" <<endl;
02601         //TODO
02602         /* For point-to-point link there should be only ONE adjacency in both tables*/
02603         for (std::vector<ISISadj>::iterator it = this->adjL1Table.begin(); it != this->adjL1Table.end(); ++it)
02604         {
02605             if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID))
02606             {
02607                 return &(*it);
02608             }
02609 
02610         }
02611 
02612     }
02613     return NULL;
02614 }
02615 
02616 /*
02617  * Extract System-ID from message.
02618  * @param msg incomming msg
02619  * @return newly allocated system-id
02620  */
02621 unsigned char * ISIS::getSysID(ISISMessage *msg)
02622 {
02623 
02624     unsigned char *systemID = new unsigned char[ISIS_SYSTEM_ID];
02625     if (msg->getType() == LAN_L1_HELLO)
02626     {
02627         ISISL1HelloPacket *l1hello = check_and_cast<ISISL1HelloPacket *>(msg);
02628         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02629         {
02630             systemID[i] = l1hello->getSourceID(i);
02631         }
02632     }
02633     else if (msg->getType() == LAN_L2_HELLO)
02634     {
02635         ISISL2HelloPacket *l2hello = check_and_cast<ISISL2HelloPacket *>(msg);
02636         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02637         {
02638             systemID[i] = l2hello->getSourceID(i);
02639         }
02640     }
02641     else if (msg->getType() == PTP_HELLO)
02642     {
02643         ISISPTPHelloPacket *ptphello = check_and_cast<ISISPTPHelloPacket *>(msg);
02644         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02645         {
02646             systemID[i] = ptphello->getSourceID(i);
02647         }
02648 
02649     }
02650     else if (msg->getType() == L1_PSNP)
02651     {
02652         ISISPSNPPacket *psnp = check_and_cast<ISISPSNPPacket *>(msg);
02653         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02654         {
02655             systemID[i] = psnp->getSourceID(i);
02656         }
02657 
02658     }
02659     else if (msg->getType() == L1_CSNP)
02660     {
02661         ISISCSNPPacket *csnp = check_and_cast<ISISCSNPPacket *>(msg);
02662         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02663         {
02664             systemID[i] = csnp->getSourceID(i);
02665         }
02666 
02667     }
02668     else if (msg->getType() == L1_LSP || msg->getType() == L2_LSP)
02669     {
02670         ISISLSPPacket *lsp = check_and_cast<ISISLSPPacket *>(msg);
02671         for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02672         {
02673             systemID[i] = lsp->getLspID(i);
02674         }
02675 
02676     }
02677     else
02678     {
02679         EV << "ISIS: ERROR: getSysID for this message type is not implemented (yet?): "<< msg->getType() << endl;
02680     }
02681 
02682 
02683     return systemID;
02684 
02685 }
02686 
02687 /*
02688  * Extract System-ID from timer.
02689  * @param msg incomming msg
02690  * @return newly allocated system-id
02691  */
02692 unsigned char* ISIS::getSysID(ISISTimer *timer){
02693     unsigned char *systemID = new unsigned char[ISIS_SYSTEM_ID];
02694 
02695     for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02696     {
02697         systemID[i] = timer->getSysID(i);
02698     }
02699 
02700     return systemID;
02701 }
02702 
02703 /*
02704  * Extract LSP-ID from timer.
02705  * @param timer incomming timer
02706  * @return newly allocated system-id
02707  */
02708 unsigned char* ISIS::getLspID(ISISTimer *timer){
02709     unsigned char *lspID = new unsigned char[ISIS_SYSTEM_ID + 2];
02710 
02711     for (int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
02712     {
02713         lspID[i] = timer->getLSPid(i);
02714     }
02715 
02716     return lspID;
02717 }
02718 
02719 /*
02720 
02721 unsigned char * ISIS::getSysID(ISISL1HelloPacket *msg){
02722     unsigned char *systemID = new unsigned char[ISIS_SYSTEM_ID];
02723 
02724     for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02725     {
02726         systemID[i] = msg->getSourceID(i);
02727     }
02728 
02729     return systemID;
02730 }
02731 
02732 unsigned char * ISIS::getSysID(ISISL2HelloPacket *msg){
02733     unsigned char *systemID = new unsigned char[ISIS_SYSTEM_ID];
02734 
02735     for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02736     {
02737         systemID[i] = msg->getSourceID(i);
02738     }
02739 
02740     return systemID;
02741 }
02742 
02743 unsigned char * ISIS::getSysID(ISISPTPHelloPacket *msg){
02744     unsigned char *systemID = new unsigned char[ISIS_SYSTEM_ID];
02745 
02746     for (int i = 0; i < ISIS_SYSTEM_ID; i++)
02747     {
02748         systemID[i] = msg->getSourceID(i);
02749     }
02750 
02751     return systemID;
02752 }
02753 */
02754 /*
02755  * Extract LSP-ID from message.
02756  * @param msg incomming msg
02757  * @return newly allocated system-id
02758  */
02759 unsigned char* ISIS::getLspID(ISISLSPPacket *msg){
02760 
02761     unsigned char *lspId = new unsigned char[8]; //TODO change back to ISIS_SYSTEM_ID + 2
02762 
02763     for (int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
02764     {
02765         lspId[i] = msg->getLspID(i);
02766     }
02767 
02768     return lspId;
02769 
02770 }
02771 
02772 void ISIS::setLspID(ISISLSPPacket *msg, unsigned char * lspId){
02773 
02774     for (int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
02775     {
02776        msg->setLspID(i, lspId[i]);
02777     }
02778 
02779 }
02780 
02786 void ISIS::printAdjTable()
02787 {
02788     std::sort(this->adjL1Table.begin(), this->adjL1Table.end());
02789     EV << "L1 adjacency table of IS ";
02790 
02791     //print area id
02792     for(unsigned int i=0; i<3; i++)
02793     {
02794         EV << setfill('0') << setw(2) << dec << (unsigned int)areaId[i];
02795         if(i % 2 == 0)
02796             EV << ".";
02797 
02798     }
02799 
02800     //print system id
02801     for(unsigned int i=0; i<6; i++)
02802     {
02803         EV << setfill('0') << setw(2) << dec << (unsigned int)sysId[i];
02804         if(i % 2 == 1)
02805             EV << ".";
02806     }
02807 
02808     //print NSEL
02809     EV << setfill('0') << setw(2) << dec << (unsigned int) NSEL[0] << "\tNo. of records in Table: " << adjL1Table.size() << endl;
02810 
02811     //print neighbour records
02812     for(unsigned int j=0; j<adjL1Table.size(); j++)
02813     {
02814         EV << "\t";
02815         //print neighbour system id
02816         for(unsigned int i=0; i<6; i++)
02817         {
02818             EV <<  setfill('0') << setw(2) << dec << (unsigned int)adjL1Table.at(j).sysID[i];
02819             if(i == 1 || i ==3)
02820                         EV << ".";
02821         }
02822         EV << "\t";
02823 
02824 
02825         //print neighbour MAC address
02826         for(unsigned int i=0; i<6; i++)
02827         {
02828             EV <<  setfill('0') << setw(2) << hex << (unsigned int)adjL1Table.at(j).mac.getAddressByte(i);
02829             if(i <5)
02830                  EV << ":";
02831         }
02832         EV << "\t";
02833 
02834 
02835         if(!adjL1Table.at(j).state)
02836             EV << "Init\n";
02837         else
02838             EV << "Up\n";
02839     }
02840 
02841     EV << "--------------------------------------------------------------------\n";
02842 
02843     EV << "L2 adjacency table of IS ";
02844 
02845         //print area id
02846         for(unsigned int i=0; i<3; i++)
02847         {
02848             EV << setfill('0') << setw(2) << dec << (unsigned int)areaId[i];
02849             if(i % 2 == 0)
02850                 EV << ".";
02851 
02852         }
02853 
02854         //print system id
02855         for(unsigned int i=0; i<6; i++)
02856         {
02857             EV << setfill('0') << setw(2) << dec << (unsigned int)sysId[i];
02858             if(i % 2 == 1)
02859                 EV << ".";
02860         }
02861 
02862         //print NSEL
02863         EV << setfill('0') << setw(2) << dec << (unsigned int) NSEL[0] << "\tNo. of records in Table: " << adjL2Table.size() << endl;
02864 
02865         //print neighbour records
02866         for(unsigned int j=0; j<adjL2Table.size(); j++)
02867         {
02868             EV << "\t";
02869             //print neighbour area id and system id
02870             for(unsigned int i=0; i<3; i++)
02871             {
02872                 EV << setfill('0') << setw(2) << dec << (unsigned int)adjL2Table.at(j).areaID[i];
02873                 if(i % 2 == 0)
02874                     EV << ".";
02875 
02876             }
02877 
02878 
02879             for(unsigned int i=0; i<6; i++)
02880             {
02881                 EV <<  setfill('0') << setw(2) << dec << (unsigned int)adjL2Table.at(j).sysID[i];
02882                 if(i == 1 || i ==3)
02883                             EV << ".";
02884             }
02885             EV << "\t";
02886 
02887 
02888             //print neighbour MAC address
02889             for(unsigned int i=0; i<6; i++)
02890             {
02891                 EV <<  setfill('0') << setw(2) << hex << (unsigned int)adjL2Table.at(j).mac.getAddressByte(i);
02892                 if(i <5)
02893                      EV << ":";
02894             }
02895             EV << "\t";
02896 
02897 
02898             if(!adjL2Table.at(j).state)
02899                 EV << "Init\n";
02900             else
02901                 EV << "Up\n";
02902         }
02903 }
02904 
02905 
02906 
02907 
02911 void ISIS::printLSPDB()
02912 {
02913     short circuitType = L1_TYPE;
02914     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
02915     EV << "L1 LSP database of IS ";
02916 
02917     //print area id
02918     for (unsigned int i = 0; i < 3; i++)
02919     {
02920         EV << setfill('0') << setw(2) << dec << (unsigned int) areaId[i];
02921         if (i % 2 == 0)
02922             EV << ".";
02923 
02924     }
02925 
02926     //print system id
02927     for (unsigned int i = 0; i < 6; i++)
02928     {
02929         EV << setfill('0') << setw(2) << dec << (unsigned int) sysId[i];
02930         if (i % 2 == 1)
02931             EV << ".";
02932     }
02933 
02934     //print NSEL
02935     EV
02936             << setfill('0') << setw(2) << dec << (unsigned int) NSEL[0] << "\tNo. of records in database: "
02937                     << lspDb->size() << endl;
02938     unsigned char *lspId;
02939     std::vector<LSPRecord *>::iterator it = lspDb->begin();
02940     for (; it != lspDb->end(); ++it)
02941     {
02942         EV << "\t";
02943         //print LSP ID
02944         for (unsigned int j = 0; j < 8; j++)
02945         {
02946             EV << setfill('0') << setw(2) << dec << (unsigned int) (*it)->LSP->getLspID(j);
02947             if (j == 1 || j == 3 || j == 5)
02948                 EV << ".";
02949             if (j == 6)
02950                 EV << "-";
02951         }
02952         EV << "\t0x";
02953 
02954         //print sequence number
02955         EV << setfill('0') << setw(8) << hex << (*it)->LSP->getSeqNumber();
02956         EV<< "\t" << setfill('0') << setw(5) << dec << (*it)->LSP->getRemLifeTime() <<endl;
02957         //EV <<"SeqNum: " << (*it)->LSP->getSeqNumber()<<endl;
02958 
02959         TLV_t *tmpTlv;
02960 
02961         //print neighbours
02962         for (unsigned int k = 0; (tmpTlv = this->getTLVByType((*it)->LSP, IS_NEIGHBOURS_LSP, k)) != NULL; k++)
02963         {
02964             for (unsigned int m = 1; m + 11 <= tmpTlv->length; m += 11)
02965             {
02966                 EV << "\t\t";
02967                 for (unsigned int l = 0; l < 7; l++)
02968                 {
02969                     //1 = virtual flag, m = current neighbour record, 4 is offset in current neigh. record(start LAN-ID)
02970                     EV << setfill('0') << setw(2) << dec << (unsigned int) tmpTlv->value[m + 4 + l];
02971                     if (l % 2 == 1)
02972                         EV << ".";
02973                 }
02974 
02975                 EV
02976                         << "\tmetric: " << setfill('0') << setw(2) << dec
02977                                 << (unsigned int) tmpTlv->value[m + 0] << endl;
02978             }
02979 
02980         }
02981 
02982     }
02983 
02984     /* EV << "L1 LSP database of IS ";
02985 
02986     //print area id
02987     for(unsigned int i=0; i<3; i++)
02988     {
02989         EV << setfill('0') << setw(2) << dec << (unsigned int)areaId[i];
02990         if(i % 2 == 0)
02991             EV << ".";
02992 
02993     }
02994 
02995     //print system id
02996     for(unsigned int i=0; i<6; i++)
02997     {
02998         EV << setfill('0') << setw(2) << dec << (unsigned int)sysId[i];
02999         if(i % 2 == 1)
03000             EV << ".";
03001     }
03002 
03003     //print NSEL
03004     EV << setfill('0') << setw(2) << dec << (unsigned int) NSEL[0] << "\tNo. of records in database: " << L1LSP.size() << endl;
03005 
03006 
03007     for(unsigned int i=0;i<L1LSP.size();i++)
03008     {
03009         EV << "\t";
03010         //print LSP ID
03011         for(unsigned int j=0; j<8; j++)
03012         {
03013             EV <<  setfill('0') << setw(2) << dec << (unsigned int)L1LSP.at(i).LSPid[j];
03014             if(j == 1 || j == 3 || j == 5)
03015                         EV << ".";
03016             if(j==6)
03017                 EV<<"-";
03018         }
03019         EV << "\t0x";
03020 
03021         //print sequence number
03022         EV << setfill('0') << setw(8) << hex << L1LSP.at(i).seq << endl;
03023 
03024 
03025 
03026         //print neighbours
03027         for(unsigned int k=0; k<L1LSP.at(i).neighbours.size(); k++)
03028         {
03029             EV <<"\t\t";
03030             for(unsigned int l=0; l<7; l++)
03031             {
03032                 EV <<  setfill('0') << setw(2) << dec << (unsigned int)L1LSP.at(i).neighbours.at(k).LANid[l];
03033                 if(l % 2 == 1)
03034                     EV << ".";
03035             }
03036 
03037             EV << "\tmetric: " << setfill('0') << setw(2) << dec << (unsigned int)L1LSP.at(i).neighbours.at(k).metrics.defaultMetric << endl;
03038 
03039 
03040         }
03041 
03042     }
03043 
03044 
03045  *
03046  */
03047 
03048     //TODO print L2 LSP DB
03049 }
03050 /*
03051  * Print contents of LSP to std::cout
03052  * @param lsp is LSP packet
03053  * @param from is description where from this print has been called.
03054  */
03055 void ISIS::printLSP(ISISLSPPacket *lsp, char *from){
03056     std::cout<<"PrintLSP called from: " << from << endl;
03057     unsigned char * lspId = this->getLspID(lsp);
03058     std::cout << "Printing LSP: ";
03059     this->printLspId(lspId);
03060     std::cout << "Print LSP->test:";
03061     this->printLspId((unsigned char *)lsp->getTest());
03062     std::cout << "seqNum: " << lsp->getSeqNumber() <<endl;
03063     std::cout << "Length of TLVarray: " << lsp->getTLVArraySize()<<endl;
03064     std::cout << "TLV: " <<endl;
03065     for(unsigned int i = 0; i < lsp->getTLVArraySize(); i++){
03066         std::cout<< "Type: "<< (unsigned short) lsp->getTLV(i).type <<endl;
03067         std::cout<< "Length: "<< (unsigned short) lsp->getTLV(i).length <<endl;
03068     }
03069 
03070 
03071     TLV_t *tmpTlv;
03072     for (unsigned int k = 0; (tmpTlv = this->getTLVByType(lsp, IS_NEIGHBOURS_LSP, k)) != NULL; k++)
03073     {
03074         std::cout <<"Start printing TLV of length: "<< (unsigned int)tmpTlv->length << endl;
03075         for (unsigned int m = 0; (m + 11) < tmpTlv->length; m += 11)
03076         {
03077             std::cout << "LAN-ID:";
03078             for (unsigned int l = 0; l < 7; l++)
03079             {
03080                 //1 = virtual flag, m = current neighbour record, 4 is offset in current neigh. record(start LAN-ID)
03081                 std::cout << (unsigned short) tmpTlv->value[1 + m + 4 + l];
03082                 if (l % 2 == 1)
03083                     std::cout << ".";
03084             }
03085 
03086             std::cout << "\t metric: " << (unsigned short) tmpTlv->value[1 + m + 0] << endl;
03087         }
03088     }
03089 }
03090 
03091 void ISIS::printLspId(unsigned char *lspId){
03092 
03093     this->printSysId(lspId);
03094     std::cout << setfill('0') << setw(2) << dec << (unsigned int) lspId[ISIS_SYSTEM_ID] ;
03095     std::cout << "-";
03096     std::cout << setfill('0') << setw(2) << dec << (unsigned int) lspId[ISIS_SYSTEM_ID + 1] << endl ;
03097 }
03098 
03099 void ISIS::printSysId(unsigned char *sysId){
03100 
03101 
03102     //print system id
03103         for (unsigned int i = 0; i < 6; i++)
03104         {
03105             std::cout << setfill('0') << setw(2) << dec << (unsigned int) sysId[i];
03106             if (i % 2 == 1)
03107                 std::cout << ".";
03108         }
03109 }
03110 
03111 
03119 bool ISIS::compareArrays(unsigned char * first, unsigned char * second, unsigned int size)
03120 {
03121     bool result = true;
03122     for(unsigned int i=0; i<size;i++)
03123     {
03124         if(first[i] != second[i])
03125             result = false;
03126     }
03127 
03128     return result;
03129 }
03130 
03139 void ISIS::copyArrayContent(unsigned char * src, unsigned char * dst, unsigned int size, unsigned int startSrc, unsigned int startDst)
03140 {
03141     for(unsigned int i=0; i<size;i++)
03142     {
03143         dst[i+startDst] = src[i+startSrc];
03144     }
03145 }
03146 
03152 void ISIS::removeDeadNeighbour(ISISTimer *msg)
03153 {
03154 
03155     /* Check it and rewrite it */
03156     EV << "ISIS: Warning: RemoveDeadNeighbour: If everything is working correctly, this method shoudn't be called" <<endl;
03157 
03158     //L1 neighbour dead
03159     // * remove from adjL1Table
03160     // * reset DIS on Ift
03161 
03162     if(msg->getIsType() == L1_TYPE)
03163     {
03164         for(unsigned int i=0; i<adjL1Table.size();)
03165         {
03166             bool found = true;
03167             for(unsigned int j = 0; j<msg->getSysIDArraySize(); j++)
03168             {
03169                 if(msg->getSysID(j) != adjL1Table.at(i).sysID[j])
03170                     found = false;
03171             }
03172 
03173             if(found)
03174             {
03175                 adjL1Table.erase(adjL1Table.begin() + i);
03176             }else{
03177                 i++;
03178             }
03179         }
03180         std::sort(this->adjL1Table.begin(), this->adjL1Table.end());
03181 
03182         unsigned char *lspId = this->getLspID(msg);
03183         this->purgeRemainLSP(lspId, msg->getIsType());
03184 
03185 
03186         if(this->ISISIft.at(msg->getInterfaceIndex()).network){
03187             //lspId has two bytes more than we need (that does no harm)
03188             this->resetDIS(lspId, msg->getInterfaceIndex(), msg->getIsType());
03189         }
03190         delete lspId;
03191 
03192     }
03193 
03194     //else it's L2 dead neighbour
03195     // * remove from adjL2Table
03196     else
03197     {
03198         for(unsigned int i=0; i<adjL2Table.size(); i++)
03199         {
03200             bool found = true;
03201             for(unsigned int j = 0; j<msg->getSysIDArraySize(); j++)
03202             {
03203                 if(msg->getSysID(j) != adjL2Table.at(i).sysID[j])
03204                     found = false;
03205             }
03206 
03207             // WHY must area ID also match??
03208 
03209             //area ID must also match
03210             for(unsigned int j=0; j<msg->getAreaIDArraySize();j++)
03211             {
03212                 if(msg->getAreaID(j) != adjL2Table.at(i).areaID[j])
03213                 {
03214                     found = false;
03215                 }
03216             }
03217 
03218             if(found)
03219             {
03220                 adjL2Table.erase(adjL2Table.begin()+i);
03221             }
03222         }
03223         std::sort(this->adjL2Table.begin(), this->adjL2Table.end());
03224 
03225         unsigned char *lspId = this->getLspID(msg);
03226         this->purgeRemainLSP(lspId, msg->getIsType());
03227 
03228         if(this->ISISIft.at(msg->getInterfaceIndex()).network){
03229             //lspId has two bytes more than we need (that does no harm)
03230             this->resetDIS(lspId, msg->getInterfaceIndex(), msg->getIsType());
03231         }
03232 
03233         delete lspId;
03234 
03235 
03236     }
03237 
03238 }
03239 
03240 
03247 void ISIS::electL1DesignatedIS(ISISL1HelloPacket *msg)
03248 {
03249     /* TODO Please rewrite this mess. */
03250 
03251 //    Ieee802Ctrl *ctrl = check_and_cast <Ieee802Ctrl *> (msg->getControlInfo());
03252     short circuitType = L1_TYPE;
03253     unsigned int i;
03254     for(i=0; i<ISISIft.size(); i++)
03255     {
03256         if(ISISIft.at(i).gateIndex == msg->getArrivalGate()->getIndex())
03257         {
03258             if(ISISIft.at(i).gateIndex != i){
03259                 EV << "ISIS: Warning: Houston, we got a problem! A BIG ONE!" << endl;
03260             }
03261             //break the cycle, we have the right position stored at "i"
03262             break;
03263         }
03264     }
03265 
03266     //compare LAN-ID from message aka LAN DIS with supposed DIS
03267     bool equal = true;
03268     unsigned char * msgLanID = new unsigned char [7];
03269     for(unsigned int k=0; k<msg->getLanIDArraySize(); k++)
03270     {
03271         msgLanID[k] = msg->getLanID(k);
03272         if(msg->getLanID(k) != ISISIft.at(i).L1DIS[k]){
03273             equal = false;
03274             //break;
03275         }
03276     }
03277     if(equal){
03278         //DIS-ID from IIH and local DIS in interface->L1DIS is same so we don't need to elect anybody
03279         return;
03280 
03281     }
03282 
03283 //    bool last = this->amIL1DIS(i);
03284     unsigned char* lastDIS = new unsigned char[ISIS_SYSTEM_ID + 1];
03285     for (unsigned int k = 0; k < msg->getLanIDArraySize(); k++)
03286     {
03287         lastDIS[k] = ISISIft.at(i).L1DIS[k];
03288     }
03289 
03290     MACAddress localDIS, receivedDIS;
03291     ISISadj *tmpAdj;
03292 
03293 //    MACAddress tmpMAC = ISISIft.at(i).entry->getMacAddress();
03294 
03295 
03296     //first old/local DIS
03297     //if DIS == me then use my MAC for specified interface
03298     if (this->amIL1DIS(i))
03299     {
03300         localDIS = ISISIft.at(i).entry->getMacAddress();
03301     }
03302     //else find adjacency and from that use MAC
03303     else
03304     {
03305         if((tmpAdj = this->getAdjBySystemID(lastDIS, L1_TYPE, ISISIft.at(i).gateIndex)) != NULL){
03306             localDIS = tmpAdj->mac;
03307         }else{
03308             EV << "deviceId: " << deviceId << " ISIS: Warning: Didn't find adjacency for local MAC comparison in electL1DesignatedIS "<<endl;
03309             localDIS = MACAddress("000000000000");
03310         }
03311     }
03312     //find out MAC address for IS with LAN-ID from received message
03313     if ((tmpAdj = this->getAdjBySystemID(msgLanID, L1_TYPE, ISISIft.at(i).gateIndex)) != NULL)
03314     {
03315         receivedDIS = tmpAdj->mac;
03316     }
03317     else
03318     {
03319         EV
03320                 << "deviceId: " << deviceId
03321                         << " ISIS: Warning: Didn't find adjacency for received MAC comparison in electL1DesignatedIS "
03322                         << endl;
03323         receivedDIS = MACAddress("000000000000");
03324     }
03325 
03326 
03327     //if announced DIS priority is higher then actual one or if they are equal and src MAC is higher than mine, then it's time to update DIS
03328     if ((!equal)
03329             && ((msg->getPriority() > ISISIft.at(i).L1DISpriority)
03330                     || (msg->getPriority() == ISISIft.at(i).L1DISpriority
03331                             && (receivedDIS.compareTo(localDIS) > 0) )))
03332     {
03333         unsigned char * disLspID = new unsigned char [ISIS_SYSTEM_ID + 2];
03334         this->copyArrayContent(lastDIS, disLspID, ISIS_SYSTEM_ID + 1, 0, 0);
03335         disLspID[ISIS_SYSTEM_ID + 1] = 0;//set fragment-ID
03336         //purge lastDIS's LSPs
03337         this->purgeRemainLSP(disLspID, circuitType);
03338 
03339         for (unsigned int j = 0; j < msg->getLanIDArraySize(); j++)
03340         {
03341             //set new DIS
03342             ISISIft.at(i).L1DIS[j] = msg->getLanID(j);
03343         }
03344         //and set his priority
03345         ISISIft.at(i).L1DISpriority = msg->getPriority();
03346 
03347         //purge DIS LSP
03348         //clear LSP containing dead neighbour
03349 
03350 /*        for (unsigned int it = 0; it < L1LSP.size();)
03351         {
03352             bool found = false;
03353             if (this->compareArrays(this->L1LSP.at(it).LSPid, lastDIS, ISIS_SYSTEM_ID + 1))
03354             {
03355                 found = true;
03356 
03357             }
03358 
03359             if (found)
03360             {
03361                 //mark with sequence number 0
03362                 L1LSP.at(it).seq = 0;
03363                 L1LSP.at(it).neighbours.clear();
03364                 //send empty LSP informing about expiration
03365                 this->sendSpecificL1LSP(L1LSP.at(it).LSPid);
03366                 //now completely delete
03367                 L1LSP.erase(L1LSP.begin() + it);
03368 
03369             }
03370             else
03371             {
03372                 it++;
03373 
03374             }
03375         }*/
03376 
03377     }
03378 }
03379 
03380 
03381 
03382 
03387 void ISIS::electL2DesignatedIS(ISISL2HelloPacket *msg)
03388 {
03389 
03390     //TODO implement
03391 }
03392 
03398 void ISIS::resetDIS(unsigned char* systemID, int gateIndex, short circuitType)
03399 {
03400 
03401 ISISinterface *iface = &(this->ISISIft.at(gateIndex));
03402     if(circuitType == L1_TYPE || circuitType == L1L2_TYPE)
03403     {
03404         //if the systemID was DIS, then set DIS = me. if dead neighbour wasn't DIS do nothing.
03405         if(this->compareArrays(systemID, iface->L1DIS, ISIS_SYSTEM_ID + 1)){
03406             //set myself as DIS
03407             iface->L1DISpriority = iface->priority;
03408             //set initial designated IS as himself
03409             this->copyArrayContent((unsigned char*)this->sysId, iface->L1DIS, ISIS_SYSTEM_ID, 0, 0);
03410             //set LAN identifier; -99 is because, OMNeT starts numbering interfaces from 100 -> interfaceID 100 means LAN ID 0; and we want to start numbering from 1
03411             iface->L1DIS[ISIS_SYSTEM_ID] = iface->gateIndex + 1;
03412         }
03413     }
03414 
03415     if(circuitType == L2_TYPE || circuitType == L1L2_TYPE)
03416     {
03417         //if the systemID was DIS, then set DIS = me. if dead neighbour wasn't DIS do nothing.
03418         if(this->compareArrays(systemID, iface->L2DIS, ISIS_SYSTEM_ID + 1)){
03419             //set myself as DIS
03420             iface->L2DISpriority = iface->priority;
03421             //set initial designated IS as himself
03422             this->copyArrayContent((unsigned char*)this->sysId, iface->L2DIS, ISIS_SYSTEM_ID, 0, 0);
03423             //set LAN identifier; -99 is because, OMNeT starts numbering interfaces from 100 -> interfaceID 100 means LAN ID 0; and we want to start numbering from 1
03424             iface->L2DIS[ISIS_SYSTEM_ID] = iface->gateIndex + 1;
03425         }
03426     }
03427 }
03428 
03434 void ISIS::sendMyL1LSPs()
03435 {
03436     EV << "ISIS: Warning: Running deprecated method" << endl;
03437     //update my own LSPs
03438     this->updateMyLSP();
03439 
03440     ISISLSPL1Packet *LSP = new ISISLSPL1Packet("L1 LSP");
03441 
03442     //add Ethernet controll info
03443     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
03444 
03445     // set DSAP & NSAP fields
03446     ctrl->setDsap(SAP_CLNS);
03447     ctrl->setSsap(SAP_CLNS);
03448 
03449     //set destination broadcast address
03450     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
03451     MACAddress ma;
03452     ma.setAddress("ff:ff:ff:ff:ff:ff");
03453     ctrl->setDest(ma);
03454 
03455     //set area address TLV
03456     TLV_t myTLV;
03457     myTLV.type = AREA_ADDRESS;
03458     myTLV.length = ISIS_AREA_ID;
03459     myTLV.value = new unsigned char[ISIS_AREA_ID];
03460     this->copyArrayContent((unsigned char*)this->areaId, myTLV.value, 3, 0, 0);
03461 
03462     LSP->setTLVArraySize(1);
03463     LSP->setTLV(0, myTLV);
03464 
03465     /* - TODO Auth TLV
03466        - eventually implement ES neighbours TLV, but I don't think it's necessary
03467        - next TLVs from RFC 1195 if IP should be supported
03468     */
03469 
03470     for(unsigned int a=0; a<ISISIft.size(); a++)
03471     {
03472         if(!ISISIft.at(a).passive && ISISIft.at(a).ISISenabled && (ISISIft.at(a).circuitType == L1_TYPE || ISISIft.at(a).circuitType == L1L2_TYPE))
03473         {
03474             //flood my LSP on links
03475             for(unsigned int i=0; i<L1LSP.size(); i++)
03476             {
03477                 //if I find LSP of my own, send it out
03478                 if(this->compareArrays(L1LSP.at(i).LSPid, (unsigned char*)this->sysId, ISIS_SYSTEM_ID))
03479                 {
03480                     ISISLSPL1Packet *LSPcopy = LSP->dup();
03481                     Ieee802Ctrl *ctrlCopy = ctrl->dup();
03482                     LSPcopy->setControlInfo(ctrlCopy);
03483 
03484                     //set LSP ID field
03485                     for(unsigned int j=0; j<LSPcopy->getLspIDArraySize(); j++)
03486                     {
03487                         LSPcopy->setLspID(j, L1LSP.at(i).LSPid[j]);
03488                     }
03489 
03490                     //set sequence number
03491                     LSPcopy->setSeqNumber(L1LSP.at(i).seq);
03492 
03493 
03494                     myTLV.type = IS_NEIGHBOURS_LSP;
03495                     myTLV.length = 1 + L1LSP.at(i).neighbours.size()*11;
03496                     myTLV.value = new unsigned char [myTLV.length];
03497                     myTLV.value[0] = 0;                                     //reserved byte
03498 
03499                     //set neighbours
03500                     for(unsigned int k=0; k<L1LSP.at(i).neighbours.size(); k++)
03501                     {
03502                         myTLV.value[(k*11)+1] = L1LSP.at(i).neighbours.at(k).metrics.defaultMetric;
03503                         myTLV.value[(k*11)+2] = L1LSP.at(i).neighbours.at(k).metrics.delayMetric;
03504                         myTLV.value[(k*11)+3] = L1LSP.at(i).neighbours.at(k).metrics.expenseMetric;
03505                         myTLV.value[(k*11)+4] = L1LSP.at(i).neighbours.at(k).metrics.errortMetric;
03506                         this->copyArrayContent(L1LSP.at(i).neighbours.at(k).LANid, myTLV.value, 7, 0, (k*11)+5); //set system ID
03507                     }
03508 
03509                     //assign TLV
03510                     LSPcopy->setTLVArraySize(2);
03511                     LSPcopy->setTLV(1, myTLV);
03512 
03513                     send(LSPcopy, "ifOut", ISISIft.at(a).gateIndex);
03514                 }
03515             }
03516         }
03517     }
03518 
03519 
03520     //schedule refresh timer (after 900s)
03521     ISISTimer *timer = new ISISTimer("LSP_Refresh");
03522     timer->setTimerKind(LSP_REFRESH);
03523     scheduleAt(simTime() + 18.0, timer);//TODO
03524 
03525     delete LSP;
03526 }
03527 
03532 void ISIS::sendMyL2LSPs()
03533 {
03534     EV << "ISIS: Warning: Running deprecated method" << endl;
03535     //TODO
03536 }
03537 
03549 void ISIS::handleL1LSP(ISISMessage * inMsg)
03550 {
03551     EV << "ISIS: Warning: Running deprecated method" << endl;
03552     ISISLSPL1Packet *msg = check_and_cast<ISISLSPL1Packet *>(inMsg);
03553 
03554     //TODO if the Remaining Life Time is 0 a.k.a purge LSP then no TLV is present and this check should be omitted
03555     //check if area IDs match
03556     for(unsigned int i = 0; i<msg->getTLVArraySize(); i++)
03557     {
03558         if(msg->getTLV(i).type == AREA_ADDRESS && this->compareArrays((unsigned char *) this->areaId, msg->getTLV(i).value, msg->getTLV(i).length))
03559         {
03560 
03561             //area address is OK
03562             //try to find LSDP ID in L1 LSP DB
03563             bool match = false;
03564             unsigned int j;
03565             for(j=0; j<L1LSP.size(); j++)
03566             {
03567                 bool found = true;
03568                 //compare LSP IDs
03569                 for(unsigned int k=0; k<msg->getLspIDArraySize(); k++)
03570                 {
03571                     if(msg->getLspID(k) != L1LSP.at(j).LSPid[k])
03572                         found = false;
03573                 }
03574 
03575                 if(found)
03576                 {
03577                     match = true;
03578                     break;
03579 
03580                 }
03581             }
03582 
03583             //update record
03584             if(match)
03585             {
03586 
03587                 //update record only if we receiver LSP with higher sequence number
03588                 if(msg->getSeqNumber() > L1LSP.at(j).seq)
03589                 {
03590 
03591                     //update timer
03592                     cancelEvent(L1LSP.at(j).deadTimer);
03593                     scheduleAt(simTime() + msg->getRemLifeTime(), L1LSP.at(j).deadTimer);   //should be 1200 secs.
03594 
03595                     //update sequence number
03596                     L1LSP.at(j).seq = msg->getSeqNumber();
03597 
03598                     //update neighbour records
03599                     std::vector<LSPneighbour> neighbours;
03600 
03601                     //find IS_NEIGHBOURS_LSP  TLV
03602                     for(unsigned int a = 0; a<msg->getTLVArraySize(); a++)
03603                     {
03604                         if(msg->getTLV(a).type == IS_NEIGHBOURS_LSP)
03605                         {
03606 
03607                             unsigned int size = (msg->getTLV(a).length - 1)/11;
03608                             for(unsigned int b=0; b<size; b++)
03609                             {
03610                                 //neighbour record
03611                                 LSPneighbour neighbour;
03612 
03613                                 //set metrics
03614                                 neighbour.metrics.defaultMetric = msg->getTLV(a).value[(b*11)+1];
03615                                 neighbour.metrics.delayMetric = msg->getTLV(a).value[(b*11)+2];
03616                                 neighbour.metrics.expenseMetric = msg->getTLV(a).value[(b*11)+3];
03617                                 neighbour.metrics.errortMetric = msg->getTLV(a).value[(b*11)+4];
03618 
03619 
03620                                 //copy LAN id
03621                                 this->copyArrayContent(msg->getTLV(a).value, neighbour.LANid, 7, (b*11)+5, 0 );
03622 
03623                                 //store to neighbours vector
03624                                 neighbours.push_back(neighbour);
03625                             }
03626 
03627                             L1LSP.at(j).neighbours = neighbours;
03628 
03629                             break;
03630                         }
03631                     }
03632 
03633                     //flood msg further to other neighbours
03634                     this->floodFurtherL1LSP(msg);
03635                 }
03636                 else
03637                 {
03638                     //if seqNumber is zero, purge that LSP and flood empty LSP ID with seqNumber 0 to other neighbour, so they can purge it too
03639                     if(msg->getSeqNumber() == 0)
03640                     {
03641                         //delete LSP
03642                         L1LSP.erase(L1LSP.begin() + j);
03643                         //send further message informing about LSP death
03644                         this->floodFurtherL1LSP(msg);
03645                     }
03646                     else
03647                     {
03648                         //we have received older version of LSP than we have in L1LSP DB
03649                         //our task is to transmit our newer version of LSP to all neighbours
03650                         if(msg->getSeqNumber() < L1LSP.at(j).seq)
03651                         {
03652                             this->sendSpecificL1LSP(L1LSP.at(j).LSPid);
03653                         }
03654                     }
03655                 }
03656             }
03657             else    //create new LSP record
03658             {
03659 
03660                 //don't create already dead LSP
03661                 if(msg->getSeqNumber() > 0)
03662                 {
03663 
03664                     //set timer
03665                     LSPrecord record;
03666                     record.deadTimer = new ISISTimer("L1 LSP dead");
03667                     record.deadTimer->setTimerKind(LSP_DEAD);
03668 
03669                     //set timer LSP ID and record LSP ID
03670                     for(unsigned int a=0; a<msg->getLspIDArraySize(); a++)
03671                     {
03672                         record.LSPid[a] = msg->getLspID(a);
03673                         record.deadTimer->setLSPid(a, msg->getLspID(a));
03674                     }
03675                     scheduleAt(simTime() + msg->getRemLifeTime(), record.deadTimer);
03676 
03677                     //set sequence number
03678                     record.seq = msg->getSeqNumber();
03679 
03680                     //find IS_NEIGHBOURS_LSP  TLV
03681                     for(unsigned int a = 0; a<msg->getTLVArraySize(); a++)
03682                     {
03683                         if(msg->getTLV(a).type == IS_NEIGHBOURS_LSP)
03684                         {
03685 
03686                             unsigned int size = (msg->getTLV(a).length - 1)/11;
03687                             for(unsigned int b=0; b<size; b++)
03688                             {
03689                                 //neighbour record
03690                                 LSPneighbour neighbour;
03691 
03692                                 //set metrics
03693                                 neighbour.metrics.defaultMetric = msg->getTLV(a).value[(b*11)+1];
03694                                 neighbour.metrics.delayMetric = msg->getTLV(a).value[(b*11)+2];
03695                                 neighbour.metrics.expenseMetric = msg->getTLV(a).value[(b*11)+3];
03696                                 neighbour.metrics.errortMetric = msg->getTLV(a).value[(b*11)+4];
03697 
03698 
03699                                 //copy LAN id
03700                                 this->copyArrayContent(msg->getTLV(a).value, neighbour.LANid, 7, (b*11)+5, 0 );
03701 
03702                                 //store to neighbours vector
03703                                 record.neighbours.push_back(neighbour);
03704                             }
03705 
03706                             L1LSP.push_back(record);
03707 
03708                             break;
03709                         }
03710                     }
03711 
03712                     this->floodFurtherL1LSP(msg);
03713                 }
03714             }
03715         }
03716     }
03717 }
03718 
03719 
03720 /*
03721  * Handles L1 LSP according to ISO 10589 7.3.15.1
03722  * @param lsp is received LSP
03723  */
03724 void ISIS::handleL1Lsp(ISISLSPPacket *lsp){
03725 
03726     /*
03727      * Verify that we have adjacency UP for Source-ID in lsp
03728      * if the lsp is received on broadcast circuit compare senders MAC address with MAC address in adjacency
03729      * We don't need to check Area address, it was done by verifying adjacency
03730      * if remainingLifetime == 0 -> purgeLSP
03731      * if lsp->getLspId() == this->sysID //if it's my LSP
03732      *  and i don't have it anymore in my lspDb, then init network wide purge ... purgeLSP()
03733      *  if it's my LSP and I have it in DB perform 7.3.16.1 -> they have old version so send new version to that link
03734      *  source is somebody else:
03735      * received lsp is newer or i don't have it in DB => installLSP
03736      *   set SRMflags and clear it for incomming interface
03737      *   if received on PTP set SSNflag for that interface and clear other
03738      * received lsp is equal(same lsp-ID, seqNumber, remLifetime both zero or both non-zero)
03739      *   clear SRM flag for C
03740      *   if C is PTP set SSN
03741      * received is older than in DB
03742      *   set SRM flag for C
03743      *   clear SSN flag for C
03744      *
03745 
03746      * Process PATT.. flag (IS Type, overload, etc.)
03747 
03748      *
03749      * this->updateLSP(lsp, L1_TYPE);
03750      */
03751     /* 7.3.15.1. */
03752     unsigned char *lspID;
03753     int circuitType = L1_TYPE;
03754     int gateIndex = lsp->getArrivalGate()->getIndex();
03755     /* 7.3.15.1. a) 6) */
03756     //returns true if for source-id in LSP there is adjacency with matching MAC address
03757     if(!this->isAdjUp(lsp, circuitType)){
03758         //no adjacency for source-id => discard lsp
03759         //generate event?
03760 
03761         EV <<"ISIS: Warning: Discarding LSP: didn't find adjacency in state UP for this LSP" <<endl;
03762         delete lsp;
03763         return;
03764     }
03765 
03766     lspID = this->getLspID(lsp);
03767 
03768     /* 7.3.15.1. b */
03769     if(lsp->getRemLifeTime() == 0){
03770 
03771         this->purgeLSP(lsp, circuitType);
03772         /* lsp is already deleted in purgeLSP */
03773         //delete lsp;
03774         delete lspID;
03775         return;
03776 
03777 
03778     }
03779     LSPRecord *lspRec;
03780     //is it my LSP?
03781     if(this->compareArrays(lspID, (unsigned char*) this->sysId, ISIS_SYSTEM_ID)){
03782 
03783         //if i don't have it anymore
03784         /* 7.3.15.1 c) i don't have it in DB */
03785         if((lspRec = this->getLSPFromDbByID(lspID, circuitType)) == NULL){
03786             //init network wide purge
03787             this->purgeLSP(lsp, circuitType);
03788             //delete lsp;
03789             delete lspID;
03790             return;
03791         }else{
03792             /* 7.3.15.1 c) OR no longer in the set of LSPs generated by this system */
03793             if (lspRec->deadTimer->getTimerKind() == LSP_DELETE) //TODO improve this
03794             {/*if the deadTimer is set to xxLSP_DELETE, then it's already purged
03795             * and in database is kept just header.
03796             */
03797                 /* 7.3.15.1 c) */
03798                 this->purgeLSP(lsp, circuitType);
03799                 delete lspID;
03800                 return;
03801             }
03802             /* 7.3.15.1 d) */
03803             //if we have it
03804             /* 7.3.16.1 sequence numbers */
03805             if(lsp->getSeqNumber() > lspRec->LSP->getSeqNumber()){
03806 //                std::cout<<"handle seqNum: "<< lspRec->LSP->getSeqNumber() <<endl;
03807                 lspRec->LSP->setSeqNumber(lsp->getSeqNumber() + 1); //TODO handle overflow of seqNumer
03808 //                std::cout<<"handle seqNum: "<< lspRec->LSP->getSeqNumber() <<endl;
03809                 this->setSRMflags(lspRec, circuitType);
03810                 //TODO set new remaining lifetime
03811                 //TODO reschedule deadTimer
03812 
03813 
03814 
03815             }else{
03816 
03817                 delete lsp;
03818                 delete lspID;
03819                 return;
03820             }
03821 
03822 
03823         }
03824     }else{
03825         /* 7.3.15.1 e) 1) */
03826         lspRec = this->getLSPFromDbByID(lspID, circuitType);
03827         if(lspRec == NULL ){
03828             /* 7.3.15.1 e) 1) i. */
03829             this->installLSP(lsp, circuitType);
03830             delete lspID;
03831             return;
03832 
03833         }else{
03834             if(lsp->getSeqNumber() > lspRec->LSP->getSeqNumber()){
03835                 /* 7.3.15.1 e) 1) i. */
03836                 this->replaceLSP(lsp, lspRec, circuitType);
03837                 delete lspID;
03838                 return;
03839 
03840             }
03841             /* 7.3.15.1 e) 2) */
03842             /* should check also lsp->getRemLifetime != 0  OR both zero, but this is handled in purgeLSP*/
03843             else if(lsp->getSeqNumber() == lspRec->LSP->getSeqNumber() && lspRec->LSP->getRemLifeTime() != 0){
03844 
03845                 /* 7.3.15.1 e) 2) i. */
03846                 this->clearSRMflag(lspRec, gateIndex, circuitType);
03847 
03848                 if (!this->ISISIft.at(gateIndex).network)
03849                 {
03850                     /* 7.3.15.1 e) 2) ii. */
03851                     this->setSSNflag(lspRec, gateIndex, circuitType);
03852                 }
03853 
03854 
03855             }
03856             /* 7.3.15.1 e) 3) */
03857             else if (lsp->getSeqNumber() < lspRec->LSP->getSeqNumber()){
03858                 /* 7.3.15.1 e) 3) i. */
03859                 this->setSRMflag(lspRec, gateIndex, circuitType);
03860                 /* 7.3.15.1 e) 3) ii. */
03861                 this->clearSSNflag(lspRec, gateIndex, circuitType);
03862             }
03863         }
03864 
03865 
03866     }
03867     delete lsp;
03868     delete lspID;
03869 }
03870 
03871 
03872 /*
03873  * This method is not used and will be deleted.
03874  */
03875 void ISIS::updateLSP(ISISLSPPacket *lsp, short circuitType){
03876 
03877     unsigned char *lspId;
03878     LSPRecord * tmpLSPRecord;
03879         lspId = this->getLspID(lsp);
03880     if((tmpLSPRecord = this->getLSPFromDbByID(lspId, circuitType)) == NULL){
03881         //installLSP
03882     }else{
03883         //we have that LSP
03884     }
03885 }
03886 
03887 
03892 void ISIS::handleL2LSP(ISISMessage * msg)
03893 {
03894     //TODO
03895 }
03896 
03897 
03898 /*
03899  * Create and send CSNP message to DIS interface.
03900  * @param timer is specific CSNP timer
03901  */
03902 void ISIS::sendL1Csnp(ISISTimer *timer)
03903 {
03904     //TODO don't know how to handle csnp over PtP yet (there is no periodic sending, but initial csnp is sent)
03905     /* Maybe send CSNP during some initial interval (or number of times, or just once) and then just don't re-schedule timer for this interface */
03906     if(!this->ISISIft.at(timer->getInterfaceIndex()).network || !this->amIL1DIS(timer->getInterfaceIndex())){
03907         this->schedule(timer);
03908         return;
03909     }
03910     short circuitType = L1_TYPE;
03911 
03912     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
03913     std::vector<LSPRecord *>::iterator it = lspDb->begin();
03914     for (int fragment = 0; it != lspDb->end(); fragment++)
03915 
03916     {
03917         ISISCSNPPacket *packet = new ISISCSNPPacket("L1 CSNP");
03918         packet->setType(L1_CSNP);
03919         packet->setLength(0); //TODO set to length of header
03920 
03921         //add Ethernet control info
03922         Ieee802Ctrl *ctrl = new Ieee802Ctrl();
03923 
03924         // set DSAP & NSAP fields
03925         ctrl->setDsap(SAP_CLNS);
03926         ctrl->setSsap(SAP_CLNS);
03927 
03928         //set destination broadcast address
03929         //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
03930         MACAddress ma;
03931         ma.setAddress("ff:ff:ff:ff:ff:ff");
03932         ctrl->setDest(ma);
03933         packet->setControlInfo(ctrl);
03934 
03935         //set system ID field which consists of my system id + zero circuit id inc this case
03936         for (unsigned int i = 0; i < packet->getSourceIDArraySize() - 1; i++)
03937         {
03938             packet->setSourceID(i, this->sysId[i]);
03939         }
03940         packet->setSourceID(6, 0); //ORLY? have to be changed during sending according to interface this CSNP is being send on
03941 
03942         int lspCount = lspDb->end() - it;
03943 
03944         //TODO set start LSP-ID
03945         if (fragment != 0)
03946         {
03947             for (unsigned int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
03948             {
03949                 packet->setStartLspID(i, (*it)->LSP->getLspID(i));
03950             }
03951         }
03952         else
03953         {
03954             for (unsigned int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
03955             {
03956                 packet->setStartLspID(i, 0);
03957             }
03958         }
03959 
03960         for (; it != lspDb->end() && packet->getLength() < ISIS_LSP_MAX_SIZE;)
03961         {
03962 
03963             TLV_t myTLV;
03964             myTLV.type = LSP_ENTRIES;
03965 
03966             if (lspCount * 16 > 255)
03967             { //TODO replace "16" with something more appropriate
03968                 myTLV.length = 255 - (255 % 16); //TODO minus size of header
03969             }
03970             else
03971             {
03972                 myTLV.length = lspCount * 16;
03973             }
03974             myTLV.value = new unsigned char[myTLV.length];
03975             myTLV.length = 0;
03976 
03977             for (int i = 0;
03978                     (myTLV.length + 16) < 255 && it != lspDb->end()
03979                             && (packet->getLength() + (myTLV.length + 16) + 2) < ISIS_LSP_MAX_SIZE; ++it, i++)
03980             { //255 is maximum that can fit into Length field of TLV
03981                 //add entry from lspDb
03982                 //convert unsigned short to unsigned char array and insert to TLV
03983                 myTLV.value[(i * 16)] = (((*it)->LSP->getRemLifeTime() >> 8) & 0xFF);
03984                 myTLV.value[(i * 16) + 1] = ((*it)->LSP->getRemLifeTime() & 0xFF);
03985 
03986                 //copy LSP ID to TLV
03987                 unsigned char *lspId = this->getLspID((*it)->LSP);
03988                 this->copyArrayContent(lspId, myTLV.value, ISIS_SYSTEM_ID + 2, 0, (i * 16) + 2);
03989                 delete lspId;
03990                 //convert unsigned long seq number to unsigned char array[4] and insert into TLV
03991                 for (unsigned int j = 0; j < 4; j++)
03992                 {
03993                     myTLV.value[(i * 16) + 10 + j] = ((*it)->LSP->getSeqNumber() >> (24 - (8 * j))) & 0xFF;
03994                 }
03995 
03996                 //set end LSP-ID
03997 
03998                 myTLV.length += 16;
03999                 //packet->setLength(packet->getLength() + 16);
04000             }
04001             //int tlvSize = packet->getTLVArraySize();
04002             this->addTLV(packet, &myTLV);
04003             packet->setLength(packet->getLength() + myTLV.length + 2);
04004 
04005             delete myTLV.value;
04006 
04007         }
04008         if (it != lspDb->end()) //if there is still another lsp in DB
04009         {
04010             for (unsigned int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
04011             {
04012                 packet->setEndLspID(i, (*it)->LSP->getLspID(i));
04013             }
04014         }
04015         else
04016         //this was last lsp, so mark it as last with LSP-ID FFFFF...
04017         {
04018             for (unsigned int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
04019             {
04020                 packet->setEndLspID(i, 255);
04021             }
04022 
04023         }
04024 
04025         if (timer->getInterfaceIndex() != this->getIfaceIndex(this->getIfaceByGateIndex(timer->getInterfaceIndex())))
04026         {
04027             EV << "ISIS: Warning: Houston, we got a problem! A BIG ONE!" << endl;
04028         }
04029 
04030         //send only on interface specified in timer
04031         send(packet, "ifOut", timer->getInterfaceIndex());
04032 
04033         /*
04034          //send packet on ALL interfaces with adjacency UP
04035          for(std::vector<ISISinterface>::iterator intIt = this->ISISIft.begin(); intIt != this->ISISIft.end(); ++intIt)
04036          {
04037          if(isUp((*intIt).gateIndex, circuitType) && (*intIt).network && this->compareArrays((unsigned char *)this->sysId, (*intIt).L1DIS, ISIS_SYSTEM_ID))//TODO L1DIS is not based on circuitType
04038          {
04039          ISISCSNPPacket *packetDup = packet->dup();
04040          Ieee802Ctrl *ctrlDup = ctrl->dup();
04041          packetDup->setControlInfo(ctrlDup);
04042          //set source LAN ID
04043          packetDup->setSourceID(ISIS_SYSTEM_ID, (*intIt).gateIndex);
04044          send(packetDup, "ifOut", (*intIt).gateIndex);
04045          }
04046          }
04047          delete ctrl;
04048          delete packet;
04049          */
04050     }
04051 
04052     //reschedule timer
04053     this->schedule(timer);
04054 
04055 }
04056 
04057 /*
04058  * Create and send PSNP message to DIS interface.
04059  * @param timer is specific PSNP timer
04060  */
04061 void ISIS::sendL1Psnp(ISISTimer *timer){
04062 
04063     if(this->amIL1DIS(timer->getInterfaceIndex())){
04064         //reschedule OR make sure that during DIS election/resignation this timer is handled correctly
04065         //this is a safer, but dumber, solution
04066         //TODO see above
04067         this->schedule(timer);
04068         return;
04069 
04070     }
04071     short circuitType = L1_TYPE; //TODO get type from timer
04072     ISISinterface * iface = &(this->ISISIft.at(timer->getInterfaceIndex()));
04073     std::vector<FlagRecord*> *SSNQueue = this->getSSNQ(iface->network, iface->gateIndex, circuitType);
04074 
04075     //if queue is empty reschedule timer
04076     if(SSNQueue->empty()){
04077         this->schedule(timer);
04078         return;
04079     }
04080 
04081 
04082 
04083     ISISPSNPPacket *packet = new ISISPSNPPacket("L1 PSNP");
04084     packet->setType(L1_PSNP);
04085 
04086     //add Ethernet controll info
04087     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
04088 
04089     // set DSAP & NSAP fields
04090     ctrl->setDsap(SAP_CLNS);
04091     ctrl->setSsap(SAP_CLNS);
04092 
04093     //set destination broadcast address
04094     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
04095     MACAddress ma;
04096     ma.setAddress("ff:ff:ff:ff:ff:ff");
04097     ctrl->setDest(ma);
04098 
04099     packet->setControlInfo(ctrl);
04100 
04101     //set system ID field which consists of my system id + zero circuit id in this case
04102     for (unsigned int i = 0; i < packet->getSourceIDArraySize() - 1; i++)
04103     {
04104         packet->setSourceID(i, this->sysId[i]);
04105     }
04106     packet->setSourceID(6, 0);
04107 
04108     //TODO check that all fields of the packet are filled correctly
04109 
04110     unsigned int lspCount = SSNQueue->size();
04111     for(std::vector<FlagRecord*>::iterator it = SSNQueue->begin(); it != SSNQueue->end(); )
04112     {
04113 
04114 
04115         TLV_t myTLV;
04116         myTLV.type = LSP_ENTRIES;
04117 
04118         if (lspCount * 16 > 255)
04119         { //TODO replace "16" with something more appropriate
04120             myTLV.length = 255 - (255 % 16); //TODO minus size of header
04121         }
04122         else
04123         {
04124             myTLV.length = lspCount * 16;
04125         }
04126         myTLV.value = new unsigned char[myTLV.length];
04127         myTLV.length = 0;
04128 
04129         for (int i = 0;
04130                 (myTLV.length + 16) < 255 && it != SSNQueue->end()
04131                         && (packet->getLength() + (myTLV.length + 16) + 2) < ISIS_LSP_MAX_SIZE; it = SSNQueue->begin(), i++)
04132         { //255 is maximum that can fit into Length field of TLV
04133             //add entry from lspDb
04134 
04135             //convert unsigned short to unsigned char array and insert to TLV
04136             myTLV.value[(i * 16)] = (((*it)->lspRec->LSP->getRemLifeTime() >> 8) & 0xFF);
04137             myTLV.value[(i * 16) + 1] = ((*it)->lspRec->LSP->getRemLifeTime() & 0xFF);
04138 
04139 
04140             //copy LSP ID to TLV
04141             unsigned char *lspId = this->getLspID((*it)->lspRec->LSP);
04142             this->copyArrayContent(lspId, myTLV.value, ISIS_SYSTEM_ID + 2, 0, (i * 16) + 2);
04143             delete lspId;
04144             //convert unsigned long seq number to unsigned char array[4] and insert into TLV
04145             for (unsigned int j = 0; j < 4; j++)
04146             {
04147                 myTLV.value[(i * 16) + 10 + j] = ((*it)->lspRec->LSP->getSeqNumber() >> (24 - (8 * j))) & 0xFF;
04148             }
04149 
04150             //set end LSP-ID
04151 
04152             myTLV.length += 16;
04153             //packet->setLength(packet->getLength() + 16);
04154 
04155             //it should wait after sending the lsp, but let's just assume it will work fine
04156             //clear SSNflag, this should also remove the flagRecord from correct queue(vector
04157             this->clearSSNflag((*it)->lspRec, (*it)->index, circuitType);
04158         }
04159         //int tlvSize = packet->getTLVArraySize();
04160         this->addTLV(packet, &myTLV);
04161         packet->setLength(packet->getLength() + myTLV.length + 2);
04162         delete myTLV.value;
04163 
04164 
04165 
04166 
04167     }
04168 
04169     if (timer->getInterfaceIndex() != this->getIfaceIndex(this->getIfaceByGateIndex(timer->getInterfaceIndex())))
04170     {
04171         EV << "ISIS: Warning: Houston, we got a problem! A BIG ONE!" << endl;
04172     }
04173 
04174     //send only on interface specified in timer
04175     send(packet, "ifOut", timer->getInterfaceIndex());
04176 
04177     this->schedule(timer);
04178 }
04179 
04180 /*
04181  * Handle incomming psnp message according to ISO 10589 7.3.15.2
04182  * @param psnp is incomming PSNP message
04183  */
04184 void ISIS::handleL1Psnp(ISISPSNPPacket *psnp){
04185 
04186     short circuitType = L1_TYPE;
04187     int gateIndex = psnp->getArrivalGate()->getIndex();
04188     ISISinterface* intf = &(this->ISISIft.at(gateIndex));
04189     /* 7.3.15.2. a) If circuit C is a broadcast .. */
04190     if(intf->network && !this->amIL1DIS(gateIndex)){
04191         EV << "ISIS: Warning: Discarding PSNP. Received on nonDIS interface." <<endl;
04192         delete psnp;
04193         return;
04194     }
04195     
04196     /* 7.3.15.2 a) 6) */
04197     /* we handle broadcast and non-broadcast adjacencies same way */
04198     if (!this->isAdjUp(psnp, circuitType))
04199     {
04200         EV << "ISIS: Warning: Discarding PSNP. Didn't find matching adjacency." << endl;
04201         delete psnp;
04202         return;
04203     }
04204 
04205     /* 7.3.15.2 a) 7) */
04206     /* 7.3.15.2 a) 8) */
04207     /* Authentication is omitted */
04208 
04209     //for -> iterate over tlvArraySize and then iterate over TLV
04210 //    for(int i = 0; i < psnp->getTLVArraySize(); i++)
04211     /* 7.3.15.2 b) */
04212     TLV_t * tmpTlv;
04213     unsigned char *tmpLspID;
04214     for(int offset = 0; (tmpTlv = this->getTLVByType(psnp, LSP_ENTRIES, offset)) != NULL; offset++){
04215 
04216         for(int i = 0; i < tmpTlv->length; i+=16)//TODO change 16 to something
04217         {
04218             tmpLspID = new unsigned char [ISIS_SYSTEM_ID + 2];
04219             this->copyArrayContent(tmpTlv->value, tmpLspID, (ISIS_SYSTEM_ID + 2), i + 2, 0);
04220             unsigned short remLife = tmpTlv->value[i] * 255 +tmpTlv->value[i + 1];
04221             /* this just makes me laugh */
04222             unsigned long seqNum = tmpTlv->value[i + 10] * 255 * 255 * 255 + tmpTlv->value[i + 11] * 255 *255 + tmpTlv->value[i + 12] * 255 + tmpTlv->value[i + 13];
04223             //getLspBySysID
04224             LSPRecord *lspRec;
04225             lspRec = this->getLSPFromDbByID(tmpLspID, circuitType);
04226             if(lspRec != NULL){
04227                 /* 7.3.15.2 b) 2) */
04228                 //if values are same
04229                 if(seqNum == lspRec->LSP->getSeqNumber() && (remLife == lspRec->LSP->getRemLifeTime() || (remLife != 0 && lspRec->LSP->getRemLifeTime() !=0))){
04230                     //if non-broadcast -> clear SRMflag for C
04231                     if(!intf->network){
04232                         this->clearSRMflag(lspRec, gateIndex, circuitType);
04233                     }
04234                 }
04235                 /* 7.3.15.2 b) 3) */
04236                 //else if received is older
04237                 else if (seqNum < lspRec->LSP->getSeqNumber()){
04238                     //clean SSN and set SRM
04239                     this->clearSSNflag(lspRec, gateIndex, circuitType);
04240                     this->setSRMflag(lspRec, gateIndex, circuitType);
04241                 }
04242                 /* 7.3.15.2 b) 4) */
04243                 //else if newer
04244                 else if(seqNum > lspRec->LSP->getSeqNumber() || (seqNum == lspRec->LSP->getSeqNumber() && lspRec->LSP->getRemLifeTime() != 0) ){
04245                     //setSSNflag AND if C is non-broadcast clearSRM
04246                     this->setSSNflag(lspRec, gateIndex, circuitType);
04247                     if(!intf->network){
04248                         this->clearSRMflag(lspRec, gateIndex, circuitType);
04249                     }
04250                 }
04251             }
04252             /* 7.3.15.2 b) 5) */
04253             else{
04254                 //if remLifetime, checksum, seqNum are all non-zero
04255                 if(remLife != 0 && seqNum != 0){
04256                     this->printSysId((unsigned char *)this->sysId);
04257                     std::cout<<"Received new LSP in PSNP";
04258                     this->printLspId(tmpLspID);
04259                     //create LSP with seqNum 0 and set SSNflag for C
04260                     //DO NOT SET SRMflag!!!!!!!
04261                     ISISLSPPacket *lsp = new ISISLSPPacket("LSP Packet");
04262                     lsp->setType(L1_LSP);
04263                     //remLifeTime
04264                     lsp->setRemLifeTime(remLife);
04265                     //lspID[8]
04266                     this->setLspID(lsp, tmpLspID);
04267 
04268                     //set seqNum
04269                     lsp->setSeqNumber(0);
04270 
04271                     //set PATTLSPDBOLIS
04272                     lsp->setPATTLSPDBOLIS(0x01);
04273 
04274 
04275                     //install new "empty" LSP and set SSNflag
04276                     this->setSSNflag( this->installLSP(lsp, circuitType), gateIndex, circuitType);
04277 
04278                 }
04279             }
04280             delete tmpLspID;
04281         }
04282 
04283     }
04284     //if lsp-entry equals
04285     delete psnp;
04286 }
04287 
04288 
04289 /*
04290  * Handle incomming csnp message according to ISO 10589 7.3.15.2
04291  * @param csnp is incomming CSNP message
04292  */
04293 void ISIS::handleL1Csnp(ISISCSNPPacket *csnp){
04294 
04295     short circuitType = L1_TYPE; //TODO get circuitType from csnp
04296     int gateIndex = csnp->getArrivalGate()->getIndex();
04297     ISISinterface* intf = &(this->ISISIft.at(gateIndex));
04298 
04299 
04300     /* 7.3.15.2 a) 6) */
04301     /* we handle broadcast and non-broadcast adjacencies same way */
04302     if (!this->isAdjUp(csnp, circuitType))
04303     {
04304         EV << "ISIS: Warning: Discarding CSNP. Didn't find matching adjacency." << endl;
04305         delete csnp;
04306         return;
04307     }
04308 
04309     /* 7.3.15.2 a) 7) */
04310     /* 7.3.15.2 a) 8) */
04311     /* Authentication is omitted */
04312 
04313     std::vector<unsigned char *>* lspRange;
04314     lspRange = this->getLspRange(this->getStartLspID(csnp),this->getEndLspID(csnp), circuitType);
04315 
04316 
04317 
04318 
04319     //for -> iterate over tlvArraySize and then iterate over TLV
04320 //    for(int i = 0; i < csnp->getTLVArraySize(); i++)
04321     /* 7.3.15.2 b) */
04322     TLV_t * tmpTlv;
04323     unsigned char *tmpLspID;
04324     for(int offset = 0; (tmpTlv = this->getTLVByType(csnp, LSP_ENTRIES, offset)) != NULL; offset++)
04325     {
04326 
04327         for(int i = 0; i < tmpTlv->length; i+=16)//TODO change 16 to something
04328         {
04329             tmpLspID = new unsigned char [ISIS_SYSTEM_ID + 2];
04330             this->copyArrayContent(tmpTlv->value, tmpLspID, (ISIS_SYSTEM_ID + 2), i + 2, 0);
04331             unsigned short remLife = tmpTlv->value[i] * 255 +tmpTlv->value[i + 1];
04332             /* this just makes me laugh */
04333             unsigned long seqNum = tmpTlv->value[i + 10] * 255 * 255 * 255 + tmpTlv->value[i + 11] * 255 *255 + tmpTlv->value[i + 12] * 255 + tmpTlv->value[i + 13];
04334 
04335             /* 7.3.15.2 c) */
04336             if (!lspRange->empty())
04337             {
04338                 while (memcmp(lspRange->front(), tmpLspID, ISIS_SYSTEM_ID + 2) < 0)
04339                 {
04340                     this->setSRMflag(this->getLSPFromDbByID(lspRange->front(), circuitType), gateIndex, circuitType);
04341                     delete lspRange->front();
04342                     lspRange->erase(lspRange->begin());
04343                 }
04344 
04345                 if (memcmp(lspRange->front(), tmpLspID, ISIS_SYSTEM_ID + 2) == 0)
04346                 {
04347                     delete lspRange->front();
04348                     lspRange->erase(lspRange->begin());
04349                 }
04350             }
04351 
04352             //getLspBySysID
04353             LSPRecord *lspRec;
04354             lspRec = this->getLSPFromDbByID(tmpLspID, circuitType);
04355             if(lspRec != NULL){
04356                 //if values are same
04357                 if(seqNum == lspRec->LSP->getSeqNumber() && (remLife == lspRec->LSP->getRemLifeTime() || (remLife != 0 && lspRec->LSP->getRemLifeTime() !=0))){
04358                     //if non-broadcast -> clear SRMflag for C
04359                     if(!intf->network){
04360                         this->clearSRMflag(lspRec, gateIndex, circuitType);
04361                     }
04362                 }
04363                 //else if received is older
04364                 else if (seqNum < lspRec->LSP->getSeqNumber()){
04365                     //clean SSN and set SRM
04366                     this->clearSSNflag(lspRec, gateIndex, circuitType);
04367                     this->setSRMflag(lspRec, gateIndex, circuitType);
04368                 }
04369                 //else if newer
04370                 else if(seqNum > lspRec->LSP->getSeqNumber() || (seqNum == lspRec->LSP->getSeqNumber() && lspRec->LSP->getRemLifeTime() != 0) ){
04371                     //setSSNflag AND if C is non-broadcast clearSRM
04372                     this->setSSNflag(lspRec, gateIndex, circuitType);
04373                     if(!intf->network){
04374                         this->clearSRMflag(lspRec, gateIndex, circuitType);
04375                     }
04376                 }
04377             }
04378             /* 7.3.15.2 b) 5) */
04379             else{
04380                 //if remLifetime, checksum, seqNum are all non-zero
04381                 if(remLife != 0 && seqNum != 0){
04382                     this->printSysId((unsigned char *) this->sysId);
04383                     std::cout << "Received new LSP in CSNP";
04384                     this->printLspId(tmpLspID);
04385                     //create LSP with seqNum 0 and set SSNflag for C
04386                     //DO NOT SET SRMflag!!!!!!!
04387                     ISISLSPPacket *lsp = new ISISLSPPacket("LSP Packet");
04388                     lsp->setType(L1_LSP);
04389                     //remLifeTime
04390                     lsp->setRemLifeTime(remLife);
04391                     //lspID[8]
04392                     this->setLspID(lsp, tmpLspID);
04393 
04394                     //set seqNum
04395                     lsp->setSeqNumber(0);
04396 
04397                     //set PATTLSPDBOLIS
04398                     lsp->setPATTLSPDBOLIS(0x01);
04399 
04400 
04401                     //install new "empty" LSP and set SSNflag
04402                     this->setSSNflag( this->installLSP(lsp, circuitType), gateIndex, circuitType);
04403 
04404                 }
04405             }
04406             delete tmpLspID;
04407         }
04408 
04409     }
04410 
04411     while(!lspRange->empty()){
04412         this->setSRMflag(this->getLSPFromDbByID(lspRange->front(), circuitType), gateIndex, circuitType);
04413         delete lspRange->front();
04414         lspRange->erase(lspRange->begin());
04415 
04416     }
04417     delete lspRange;
04418     //if lsp-entry equals
04419     delete csnp;
04420 }
04421 
04422 
04423 /*
04424  * Returns set of LSP-IDs in range from startLspID to endLspID
04425  * @param startLspID beginning of range
04426  * @param endLspID end of range
04427  * @return range of LSP-IDs
04428  */
04429 std::vector<unsigned char *>* ISIS::getLspRange(unsigned char *startLspID, unsigned char * endLspID, short circuitType){
04430 
04431     int res1, res2;
04432     unsigned char * lspID;
04433     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
04434     std::vector<unsigned char*> *lspRange = new std::vector<unsigned char *>;
04435     std::sort(lspDb->begin(), lspDb->end());
04436     //TODO we can end the search before hitting lspDb->end when DB is sorted
04437     for (std::vector<LSPRecord *>::iterator it = lspDb->begin(); it != lspDb->end(); ++it)
04438     {
04439         lspID = this->getLspID((*it)->LSP);
04440         res1 = memcmp(startLspID, lspID, ISIS_SYSTEM_ID + 2);
04441         res2 = memcmp(lspID, endLspID, ISIS_SYSTEM_ID + 2);
04442         if(res1 <= 0 && res2 >= 0){
04443             lspRange->push_back(lspID);
04444         }
04445         delete lspID;
04446     }
04447 
04448     return lspRange;
04449 
04450 }
04451 
04452 /*
04453  * Extracts Start LSP-ID from CSNP message.
04454  * @param csnp incoming CSNP message.
04455  * @return start LSP-ID.
04456  */
04457 unsigned char * ISIS::getStartLspID(ISISCSNPPacket *csnp){
04458 
04459         unsigned char *lspId = new unsigned char[ISIS_SYSTEM_ID + 2];
04460 
04461         for (int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
04462         {
04463             lspId[i] = csnp->getStartLspID(i);
04464         }
04465 
04466         return lspId;
04467 }
04468 
04469 /*
04470  * Extracts End LSP-ID from CSNP message.
04471  * @param csnp incoming CSNP message.
04472  * @return end LSP-ID.
04473  */
04474 unsigned char * ISIS::getEndLspID(ISISCSNPPacket *csnp){
04475 
04476         unsigned char *lspId = new unsigned char[ISIS_SYSTEM_ID + 2];
04477 
04478         for (int i = 0; i < ISIS_SYSTEM_ID + 2; i++)
04479         {
04480             lspId[i] = csnp->getEndLspID(i);
04481         }
04482 
04483         return lspId;
04484 }
04485 
04490 void ISIS::sendL1CSNP()
04491 {
04492     EV << "ISIS: Warning: Running deprecated method" << endl;
04493     //update my own LSPs
04494 
04495     ISISCSNPL1Packet *packet = new ISISCSNPL1Packet("L1 CSNP");
04496 
04497 
04498     //add Ethernet controll info
04499     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
04500 
04501     // set DSAP & NSAP fields
04502     ctrl->setDsap(SAP_CLNS);
04503     ctrl->setSsap(SAP_CLNS);
04504 
04505     //set destination broadcast address
04506     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
04507     MACAddress ma;
04508     ma.setAddress("ff:ff:ff:ff:ff:ff");
04509     ctrl->setDest(ma);
04510 
04511     //set system ID field which consists of my system id + zero circuit id inc this case
04512     for(unsigned int i=0; i<packet->getSourceIDArraySize()-1; i++)
04513     {
04514         packet->setSourceID(i, this->sysId[i]);
04515     }
04516     packet->setSourceID(6, 0);
04517 
04518     //set start LSP ID to zeros and end LSP ID to max value
04519     for(unsigned int i=0; i<packet->getStartLspIDArraySize(); i++)
04520     {
04521         packet->setStartLspID(i,0);
04522         packet->setEndLspID(i,255);
04523     }
04524 
04525     //set area address TLV
04526     TLV_t myTLV;
04527     myTLV.type = LSP_ENTRIES;
04528     myTLV.length = this->L1LSP.size()*14;
04529     myTLV.value = new unsigned char[myTLV.length];
04530     /*
04531      * Value Multiples of LSP summaries, each consisting of the remaining lifetime (2 bytes), LSP ID (ID length + 2 bytes),
04532      * LSP sequence number(4 bytes), and LSP checksum (2 bytes). But we ignore LSP checksum so length of each LSP record in CSNP is
04533      * 2 bytes smaller.
04534      */
04535     for(unsigned int i=0;i<L1LSP.size(); i++)
04536     {
04537         //get remaining lifetime //TODO change value to constant or something
04538         unsigned short remTime = 50 - ((unsigned short)(simTime().dbl()) - (unsigned short)(L1LSP.at(i).deadTimer->getCreationTime().dbl()));
04539 
04540         //convert unsigned short to unsigned char array and insert to TLV
04541         myTLV.value[(i*14)] = ((remTime >> 8) & 0xFF);
04542         myTLV.value[(i*14)+1] = (remTime & 0xFF);
04543 
04544         //copy LSP ID to TLV
04545         this->copyArrayContent(L1LSP.at(i).LSPid, myTLV.value, 8, 0, (i*14)+2);
04546 
04547         //convert unsigned long seq number to unsigned char array[4] and insert into TLV
04548         for(unsigned int j=0; j<4; j++)
04549         {
04550             myTLV.value[(i*14)+10+j] = (L1LSP.at(i).seq >> (24-(8*j))) & 0xFF;
04551         }
04552     }
04553 
04554     packet->setTLVArraySize(1);
04555     packet->setTLV(0, myTLV);
04556 
04557 
04558     /* - TODO Auth TLV
04559        - eventually implement ES neighbours TLV, but I don't think it's necessary
04560        - next TLVs from RFC 1195 if IP should be supported in future
04561     */
04562 
04563     //walk through all itnerfaces
04564     for(unsigned int a=0; a<ISISIft.size(); a++)
04565     {
04566         //if interface status meets condition
04567         if(!ISISIft.at(a).passive && ISISIft.at(a).ISISenabled && (ISISIft.at(a).circuitType == L1_TYPE || ISISIft.at(a).circuitType == L1L2_TYPE))
04568         {
04569             //check if this Ift represents DIS on associated LAN
04570             unsigned char myLANid[7];
04571             this->copyArrayContent((unsigned char *)this->sysId, myLANid, 7, 0, 0);
04572             myLANid[6] = ISISIft.at(a).gateIndex + 1;
04573 
04574             //if they match, send CSNP packet to that LAN
04575             if(this->compareArrays(myLANid, ISISIft.at(a).L1DIS, 7))
04576             {
04577                 ISISCSNPL1Packet *packetCopy = packet->dup();
04578                 Ieee802Ctrl *ctrlCopy = ctrl->dup();
04579                 packetCopy->setControlInfo(ctrlCopy);
04580                 send(packetCopy, "ifOut", ISISIft.at(a).gateIndex);
04581             }
04582         }
04583     }
04584 
04585     //set new CNSP timer (10s)
04586     ISISTimer *CSNPtimer =  new ISISTimer("Send CSNP packets");
04587     CSNPtimer->setTimerKind(CSNP_TIMER);
04588     scheduleAt(simTime() + 10.0, CSNPtimer);
04589 
04590     delete packet;
04591 }
04592 
04596 void ISIS::sendL2CSNP()
04597 {
04598     //TODO
04599 }
04600 
04608 void ISIS::handleL1CSNP(ISISMessage * inMsg)
04609 {
04610     ISISCSNPL1Packet *msg = check_and_cast<ISISCSNPL1Packet *>(inMsg);
04611 
04612     for(unsigned int i=0; i<msg->getTLVArraySize(); i++)
04613     {
04614         //find LSP_ENTRIES TLV
04615         if(msg->getTLV(i).type == LSP_ENTRIES)
04616         {
04617 
04618             /*
04619              * TLV Value Multiples of LSP summaries, each consisting of the remaining lifetime (2 bytes), LSP ID (ID length + 2 bytes),
04620              * LSP sequence number(4 bytes), and LSP checksum (2 bytes). But we ignore LSP checksum so length of each LSP record in CSNP is
04621              * 2 bytes smaller, which give us 14 bytes of data per LSP entry.
04622              */
04623 
04624             //list of LSP to be asked for using PSNP packets
04625             std::vector<unsigned char *> LSPlist;
04626 
04627             //parse each LSP entry separatly
04628             for(unsigned int j=0; j<msg->getTLV(i).length / 14; j++)
04629             {
04630                 unsigned char *lspEntry  = new unsigned char[14];
04631                 this->copyArrayContent(msg->getTLV(i).value, lspEntry, 14, j*14, 0);
04632 
04633                 //ignore time remaining for now
04634                 //copy and compare for existing LSP id in L1LSP
04635                 unsigned char lspid[8];
04636                 this->copyArrayContent(lspEntry, lspid, 8, 2, 0);
04637 
04638                 bool found = false;
04639                 unsigned int k;
04640                 for(k=0; k<L1LSP.size(); k++)
04641                 {
04642                     if(this->compareArrays(lspid, L1LSP.at(k).LSPid, 8))
04643                     {
04644                         found = true;
04645                         break;
04646 
04647                     }
04648                 }
04649 
04650                 //LSP ID exists
04651                 if(found)
04652                 {
04653                     //compare sequence numbers
04654                     //we must built sequence number from received unsigned char array using bitshifting
04655                     unsigned long seqNum = (( lspEntry[10] << 24)
04656                             + (lspEntry[11] << 16)
04657                             + (lspEntry[12] << 8)
04658                             + (lspEntry[13] ));
04659 
04660 
04661                     //request update if DIS is holding newer version of LSP
04662                     if(seqNum > L1LSP.at(k).seq)
04663                     {
04664                          LSPlist.push_back(lspEntry);
04665                     }
04666                     else
04667                     {
04668                         //In case I received LSP with older seq number than I have stored in my db,
04669                         //flood my newer version
04670                         if(seqNum < L1LSP.at(k).seq)
04671                             this->sendSpecificL1LSP(lspid);
04672                     }
04673                 }
04674 
04675                 //LSP entry not found
04676                 else
04677                 {
04678                     LSPlist.push_back(lspEntry);
04679                 }
04680             }
04681 
04682 
04683             //send PSNP packets if I have missing/outdated LSP entry/entries
04684             if(LSPlist.size() > 0)
04685             {
04686                 this->sendL1PSNP(&LSPlist, msg->getArrivalGate()->getIndex());
04687             }
04688 
04689             break;
04690         }
04691     }
04692 }
04693 
04697 void ISIS::handleL2CSNP(ISISMessage * msg)
04698 {
04699     //TODO
04700 }
04701 
04709 void ISIS::sendL1PSNP(std::vector<unsigned char *> * LSPlist, int gateIndex)
04710 {
04711     ISISPSNPL1Packet *packet = new ISISPSNPL1Packet("L1 PSNP");
04712 
04713     //add Ethernet controll info
04714     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
04715 
04716     // set DSAP & NSAP fields
04717     ctrl->setDsap(SAP_CLNS);
04718     ctrl->setSsap(SAP_CLNS);
04719 
04720     //set destination broadcast address
04721     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
04722     MACAddress ma;
04723     ma.setAddress("ff:ff:ff:ff:ff:ff");
04724     ctrl->setDest(ma);
04725 
04726     packet->setControlInfo(ctrl);
04727 
04728     //set system ID field which consists of my system id + zero circuit id in this case
04729     for(unsigned int i=0; i<packet->getSourceIDArraySize()-1; i++)
04730     {
04731         packet->setSourceID(i, this->sysId[i]);
04732     }
04733     packet->setSourceID(6, 0);
04734 
04735     //set area address TLV
04736     TLV_t myTLV;
04737     myTLV.type = LSP_ENTRIES;
04738     myTLV.length = LSPlist->size()*14;
04739     myTLV.value = new unsigned char[myTLV.length];
04740     /*
04741      * Value� Multiples of LSP summaries, each consisting of the remaining lifetime (2 bytes), LSP ID (ID length + 2 bytes),
04742      * LSP sequence number(4 bytes), and LSP checksum (2 bytes). But we ignore LSP checksum so length of each LSP record in CSNP is
04743      * 2 bytes smaller.
04744      */
04745     for(unsigned int i=0;i<LSPlist->size(); i++)
04746     {
04747         this->copyArrayContent(LSPlist->at(i), myTLV.value, 14, 0, i*14);
04748     }
04749 
04750     packet->setTLVArraySize(1);
04751     packet->setTLV(0, myTLV);
04752 
04753 
04754     /* - TODO Auth TLV
04755        - eventually implement ES neighbours TLV, but I don't think it's necessary
04756        - next TLVs from RFC 1195 if IP should be supported in future
04757     */
04758 
04759     //send packet to same interface as CSNP packet came in
04760     //DIS should receive this packet and handle it
04761     send(packet, "ifOut", gateIndex);
04762 }
04763 
04767 void ISIS::sendL2PSNP()
04768 {
04769     //TODO
04770 }
04771 
04778 void ISIS::handleL1PSNP(ISISMessage * inMsg)
04779 {
04780     ISISPSNPL1Packet *msg = check_and_cast<ISISPSNPL1Packet *>(inMsg);
04781 
04782 
04783     //PSNP packets should process only DIS, therefore we need to check this
04784 
04785     //find interface which packet came from
04786     for(unsigned int i=0; i<ISISIft.size(); i++)
04787     {
04788         //we found dat interface
04789         if(ISISIft.at(i).gateIndex == msg->getArrivalGate()->getIndex())
04790         {
04791             unsigned char LanID[7];
04792 
04793             //set LAN ID which consists of system ID + pseudonode ID
04794             this->copyArrayContent((unsigned char *)this->sysId, LanID, 6, 0, 0);   //set system ID
04795             LanID[6] = ISISIft.at(i).gateIndex + 1;    //set pseudonode ID
04796 
04797             //compare Ift's DIS with LAN ID
04798             //if they don't match, I'm not DIS on dat LAN and no processing of PSNP packet is necessary
04799             if(!(this->compareArrays(LanID, ISISIft.at(i).L1DIS, 7)))
04800                 return;
04801         }
04802     }
04803 
04804     for(unsigned int i=0; i<msg->getTLVArraySize(); i++)
04805     {
04806         //find LSP_ENTRIES TLV
04807         if(msg->getTLV(i).type == LSP_ENTRIES)
04808         {
04809 
04810             /*
04811              * TLV Value Multiples of LSP summaries, each consisting of the remaining lifetime (2 bytes), LSP ID (ID length + 2 bytes),
04812              * LSP sequence number(4 bytes), and LSP checksum (2 bytes). But we ignore LSP checksum so length of each LSP record in CSNP is
04813              * 2 bytes smaller, which give us 14 bytes of data per LSP entry.
04814              */
04815 
04816             //parse each LSP entry separately
04817             for(unsigned int j=0; j<msg->getTLV(i).length / 14; j++)
04818             {
04819                 unsigned char lspEntry[14];
04820                 this->copyArrayContent(msg->getTLV(i).value, lspEntry, 14, j*14, 0);
04821 
04822                 //ignore time remaining for now
04823                 //copy and compare for existing LSP id in L1LSP
04824                 unsigned char lspid[8];
04825                 this->copyArrayContent(lspEntry, lspid, 8, 2, 0);
04826 
04827                 //send LSP packet containing relevant data
04828                 this->sendSpecificL1LSP(lspid);
04829             }
04830         }
04831 
04832         break;
04833     }
04834 }
04835 
04839 void ISIS::handleL2PSNP(ISISMessage * msg)
04840 {
04841     //TODO
04842 }
04843 
04848 bool ISIS::checkDuplicateSysID(ISISMessage * msg)
04849 {
04850 
04851     bool test = false;
04852 
04853     if (msg->getType() == LAN_L1_HELLO || msg->getType() == LAN_L2_HELLO)
04854     {
04855 
04856         // typecast for L1 hello; L1 and L2 hellos differ only in "type" field
04857         ISISL1HelloPacket *hello = check_and_cast<ISISL1HelloPacket *>(msg);
04858 
04859         //check for area address tlv and compare with my area id
04860         for (unsigned int j = 0; j < hello->getTLVArraySize(); j++)
04861         {
04862             if (hello->getTLV(j).type == AREA_ADDRESS
04863                     && this->compareArrays((unsigned char *) this->areaId, hello->getTLV(j).value,
04864                             hello->getTLV(j).length))
04865             {
04866 
04867                 bool equal = true;
04868 
04869                 //compare sys ID
04870                 for (unsigned int i = 0; i < hello->getSourceIDArraySize(); i++)
04871                 {
04872                     if (this->sysId[i] != hello->getSourceID(i))
04873                         equal = false;
04874                 }
04875 
04876                 test = equal;
04877                 break;
04878             }
04879         }
04880     }
04881     else if (msg->getType() == PTP_HELLO)
04882     {
04883         test = true;
04884         ISISPTPHelloPacket *hello = check_and_cast<ISISPTPHelloPacket *>(msg);
04885         for (unsigned int i = 0; i < hello->getSourceIDArraySize(); i++)
04886         {
04887             if (this->sysId[i] != hello->getSourceID(i))
04888             {
04889                 test = false;
04890                 break;
04891             }
04892         }
04893     }
04894 
04895     if (test)
04896     {
04897         EV << this->deviceId << ": IS-IS WARNING: possible duplicate system ID ";
04898         for (unsigned g = 0; g < 6; g++)
04899         {
04900             EV << setfill('0') << setw(2) << dec << (unsigned int) sysId[g];
04901             if (g == 1 || g == 3)
04902                 EV << ".";
04903         }
04904         EV << " detected" << endl;
04905     }
04906 
04907     return test;
04908 }
04909 
04915 void ISIS::removeDeadLSP(ISISTimer *timer)
04916 {
04917     for(unsigned int i=0; i<L1LSP.size(); i++)
04918     {
04919         //find dead LSP ID
04920         bool found = true;
04921         for(unsigned int j=0; j<timer->getLSPidArraySize(); j++)
04922         {
04923             if(timer->getLSPid(j) != L1LSP.at(i).LSPid[j])
04924                 found = false;
04925         }
04926 
04927         //we found it!
04928         if(found)
04929         {
04930 
04931             //mark with sequence number 0
04932             L1LSP.at(i).seq = 0;
04933             L1LSP.at(i).neighbours.clear();
04934             //send empty LSP informing about expiration
04935             this->sendSpecificL1LSP(L1LSP.at(i).LSPid);
04936             //now completely delete
04937             L1LSP.erase(L1LSP.begin() + i);
04938             break;
04939         }
04940     }
04941 }
04942 
04943 
04944 /*
04945  * Sends LSPs that have set SRM flag.
04946  * For PtP interfaces sends all messages in queue.
04947  * For broadcast sends only one random LSP.
04948  * Method is called per interface.
04949  * @param timer incomming timer
04950  * @param circuiType specify level for which send should be performed.
04951  */
04952 void ISIS::periodicSend(ISISTimer* timer, short circuitType)
04953 {
04954     /*
04955      * TODO improvement: don't scan whole database, but instead
04956      *  create queue "toBeSend" with lspRec* and index to SRMflags vector
04957      *  and when setting SRMflag (in any method) put a record in mentioned queue
04958      *  When doing periodicSend we don't have to check whole database (but should
04959      *   at least in the beginning to check that it works correctly), but just this queue
04960      *  We could have two queues (for PTP and broadcast).
04961      *  PTP queue would be simply send out.
04962      *  Broadcast queue would be subject of random picking.
04963      *
04964      */
04965 /*
04966     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
04967     std::vector<ISISadj> * adjTable = this->getAdjTab(circuitType);
04968     std::vector<ISISinterface>::iterator itIface = this->ISISIft.begin();
04969 */
04970 
04971     std::vector<std::vector<FlagRecord*>* > * SRMPTPQueue = getSRMPTPQueue(circuitType);
04972     std::vector<std::vector<FlagRecord*>* > * SRMBQueue = getSRMBQueue(circuitType);
04973 
04974     //std::cout << "Starting Periodic send for: ";
04975     //this->printSysId((unsigned char *) this->sysId);
04976     //std::cout << endl;
04977 
04978     //PTP circuits
04979     for(std::vector<std::vector<FlagRecord*>* >::iterator it = SRMPTPQueue->begin(); it != SRMPTPQueue->end(); ++it){
04980        for(std::vector<FlagRecord*>::iterator itRec = (*it)->begin(); itRec != (*it)->end(); ++itRec){
04981 
04982            //std::cout<<"sendLsp to:" << (*itRec)->index <<" : ";
04983                //this->printLspId(this->getLspID((*itRec)->lspRec->LSP));
04984 
04985                this->sendLSP((*itRec)->lspRec, (*itRec)->index);
04986                
04987            //DON'T clear SRMflag for PtP
04988 
04989            /* when the below code is commented:
04990             * it might be necessary to incorporate retransmit interval and
04991             * when checking if the SRM flag is not already set.
04992             * setting the flag multiple times may cause bloating appropriate flag queue.
04993             */
04994            //delete (*itRec);
04995            //itRec = (*it)->erase(itRec); //instead of ++itRec in for()!!!!!!
04996        }
04997 
04998     }
04999 
05000 
05001     //broadcast circuits
05002     //for each queue(interface) pick one LSP and send it
05003     for(std::vector<std::vector<FlagRecord*>* >::iterator it = SRMBQueue->begin(); it != SRMBQueue->end(); ++it){
05004         int queueSize = (*it)->size();
05005         if(queueSize == 0){
05006             continue;
05007         }
05008         int index = floor(uniform(0, queueSize)); 
05010         //send random LSP from queue
05011         //TODO if queue.size() > 10 pick two LSPs (or something like it)
05012         //TODO maybe? better version would be with this->ISISIft.at((*it)->at(index)->index)
05013         this->sendLSP((*it)->at(index)->lspRec, (*it)->at(index)->index);
05014 
05015         //clear SRMflag
05016         this->clearSRMflag((*it)->at(index)->lspRec, (*it)->at(index)->index, circuitType);
05017 /*        (*it)->at(index)->lspRec->SRMflags.at((*it)->at(index)->index);
05018 
05019         delete (*it)->at(index);
05020         //and remove FlagRecord from queue
05021         (*it)->erase((*it)->begin() + index);
05022         */
05023         queueSize = (*it)->size();
05024         int a = 5;
05025 
05026     }
05027     //reschedule PERIODIC_SEND timer
05028     this->schedule(timer);
05029 }
05030 
05031 /*
05032  * This method actually sends the LSP out of this module to specified interface.
05033  * @param lspRec specify record in LSP database that needs to be send
05034  * @param gateIndex specify interface to which the lsp should be send
05035  */
05036 void ISIS::sendLSP(LSPRecord *lspRec, int gateIndex){
05037 
05038     /* TODO
05039      * incorporate this->lspInterval ... Minimum delay in ms between sending two LSPs.
05040      *
05041      */
05042 /*    std::cout<<"Sending LSP from: ";
05043     this->printSysId((unsigned char *)this->sysId);
05044     std::cout<< endl;
05045     std::cout<<"sendLsp to:" << gateIndex <<" : ";
05046     this->printLspId(this->getLspID(lspRec->LSP));
05047 
05048     this->printLSP(lspRec->LSP, "sendLSP");*/
05049     //update remainingLifeTime
05050     //TODO check if new remLifeTime is not 0 or smaller
05051     if(lspRec->deadTimer->getTimerKind() == LSP_DELETE){
05052 
05053     }else{
05054         double remLife = lspRec->simLifetime - simTime().dbl();
05055         if (remLife < 0)
05056         {
05057             EV << "ISIS: Warning: Remaining lifetime smaller than zero in senLSP" << endl;
05058             lspRec->LSP->setRemLifeTime(1);
05059         }
05060         else
05061         {
05062             unsigned short rem = floor(remLife);
05063             lspRec->LSP->setRemLifeTime(rem);
05064         }
05065     }
05066 
05067     ISISLSPPacket *tmpLSP = lspRec->LSP->dup();
05068     //TODO add proper control Info for point-to-point
05069     Ieee802Ctrl *tmpCtrl = new Ieee802Ctrl();
05070 
05071     // set DSAP & NSAP fields
05072     tmpCtrl->setDsap(SAP_CLNS);
05073     tmpCtrl->setSsap(SAP_CLNS);
05074 
05075     //set destination broadcast address
05076     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
05077     MACAddress ma;
05078     ma.setAddress("ff:ff:ff:ff:ff:ff");
05079     tmpCtrl->setDest(ma);
05080 
05081     tmpLSP->setControlInfo(tmpCtrl);
05082 
05083     send(tmpLSP, "ifOut", gateIndex);
05084 
05085 
05086 }
05087 
05088 
05094 std::vector<ISISLSPPacket *>* ISIS::genLSP(short circuitType)
05095 {
05096     unsigned char *myLSPID = this->getLSPID();
05097     ISISLSPPacket* LSP; // = new ISISLSPL1Packet;
05098 
05099 //    if ((LSP = this->getLSPFromDbByID(myLSPID, circuitType)) != NULL)
05100     //we have at least "System-ID.00-00" LSP
05101 
05102     //generate LSP and then compare it with one found in database
05103     //if they differ get sequence number from the one found in database, increment it by one
05104     //and replace the original LSP entry -> if only one LSP is present in DB then it's easy,
05105     //but what to do when there are multiple fragments
05106 
05107     //how to compare two LSP and recognize
05108 
05109     //generate LSP only up to ISIS_LSP_MAX_SIZE
05110     /* after reaching ISIS_LSP_MAX_SIZE (minus few %) (and comparing the two LSPs and such)
05111      * 1.if there's more -> create new LSP
05112      * 2.if not, check if there's another fragment in DB (it should be enough to check only next fragment)
05113      *
05114      */
05115 
05116     //create new LSP
05117     std::vector<TLV_t *>* tlvTable = new std::vector<TLV_t *>;
05118 
05119     //if sizeOfNeighboursUp == 0 then return NULL
05120     if (!this->isAdjUp(circuitType))
05121     {
05122         //FIXME
05123         return new std::vector<ISISLSPPacket *>;
05124     }
05125     //TLV IS_NEIGHBOURS
05126     this->addTLV(tlvTable, IS_NEIGHBOURS_LSP, circuitType, 0);
05127 
05128     //TLV AREA ADDRESS
05129     this->addTLV(tlvTable, AREA_ADDRESS, circuitType);
05130 
05131     //add other TLVs
05132 
05133     //now start putting informations from tlvTable into LSP Packets
05134 
05135     /*
05136      * while(! tlvTable->empty())
05137      *   get first tlv from tlvTable
05138      *   if tlv_entry.length > max_lsp_size (minus header)
05139      *     we won't fit it into single lsp
05140      *
05141      *   else if tlv_entry.length > available_space in current LSP
05142      *     allocate new lsp
05143      *   else
05144      *     start putting it in current LSP
05145      *     remove it from vector
05146      *     DONT FORGET to PUT EVERY GENERATED LSP INTO returning vector
05147      *     start new iteration
05148      */
05149 
05150     TLV_t * tmpTlv;
05151     unsigned int tlvSize; //tmp variable
05152     unsigned int availableSpace = ISIS_LSP_MAX_SIZE; //available space in LSP
05153 
05154     //deleted at the end of generateLSP
05155     std::vector<ISISLSPPacket *>* tmpLSPDb = new std::vector<ISISLSPPacket *>;
05156     for (unsigned char fragment = 0; !tlvTable->empty(); fragment++)
05157     {
05158         if (circuitType == L1_TYPE)
05159         {
05160             LSP = new ISISLSPPacket("L1 LSP");
05161             LSP->setType(L1_LSP);
05162         }
05163         else if (circuitType == L2_TYPE)
05164         {
05165             LSP = new ISISLSPPacket("L2 LSP");
05166             LSP->setType(L2_LSP);
05167         }
05168         else
05169         {
05170             EV << "ISIS: ERROR: Wrong circuitType in genLSP()" << endl;
05171         }
05172 
05173         //set pduLength
05174 
05175         //set remLifeTime
05176         LSP->setRemLifeTime(this->lspMaxLifetime);
05177 
05178         //set lspID[8];
05179         myLSPID[ISIS_SYSTEM_ID + 1] = fragment;
05180         this->setLspID(LSP, myLSPID);
05181 
05182         //set seqNum
05183         LSP->setSeqNumber(1);
05184 
05185         //set checksum
05186 
05187         //set PATTLSPDBOLIS
05188         LSP->setPATTLSPDBOLIS(0x01); //only setting IS type = L1 (TODO)
05189         //set TLV
05190         LSP->setTest("ahoj");
05191                         const char * lspId = (const char *)this->getLspID(LSP);
05192                         LSP->setTest(lspId);
05193         //TLV_t tmpTLV;
05194 
05195 
05196         for (; !tlvTable->empty();)
05197         {
05198             tmpTlv = tlvTable->at(0);
05199 
05200             //TODO incorporate header size and mostly get actual MTU something like this->ISISIft.at(0).entry->getMTU()
05201             if (tmpTlv->length > ISIS_LSP_MAX_SIZE)
05202             {
05203                 //tlv won't fit into single message (this shouldn't happen)
05204                 EV << "ISIS: Warning: TLV won't fit into single message (this shouldn't happen)" << endl;
05205                 tlvTable->erase(tlvTable->begin());
05206             }
05207             else if (tmpTlv->length > availableSpace)
05208             {
05209                 //tlv won't fit into this LSP, so break cycle and create new LSP
05210 //                tmpLSPDb->push_back(LSP);
05211                 EV << "ISIS: This TLV is full." << endl;
05212                 break;//ends inner cycle
05213 
05214             }
05215             else
05216             {
05217                 this->addTLV(LSP,tmpTlv);
05218                 //tlvSize = LSP->getTLVArraySize();
05219                 //LSP->setTLVArraySize(tlvSize + 1);
05220 
05221                 //update availableSpace
05222                 availableSpace = availableSpace - (2 + tmpTlv->length);// "2" means Type and Length fields
05223 
05224                 //clean up
05225                 delete tmpTlv->value;
05226                 delete tmpTlv;
05227                 tlvTable->erase(tlvTable->begin());
05228 
05229             }
05230         }
05231         //this->printLSP(LSP, "genLSP, non-pseudo");
05232         tmpLSPDb->push_back(LSP);
05233 
05234     }
05235     //what about pseudonode?
05236     /*
05237      * H   H  EEEEE  RRRR   EEEEE
05238      * H   H  E      R   R  E
05239      * HHHHH  EEEEE  RRRR   EEEEE
05240      * H   H  E      R  R   E
05241      * H   H  EEEEE  R   R  EEEEE
05242      */
05243 
05244 
05245     std::vector<bool> activeIface; //interfaces with adjacency in state UP
05246 
05247 
05248     for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it){
05249         activeIface.push_back(this->isUp((*it).gateIndex, circuitType));
05250 
05251     }
05252 
05253     for(std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it)
05254     {
05255         //if at least one adjacency is UP and network type is broadcast (there is no DIS on PTP) AND I am DIS on this interface
05256         if(this->isUp((*it).gateIndex, circuitType) && (*it).network && this->amIL1DIS(this->getIfaceIndex(&(*it))))
05257         {
05258             tlvTable->clear();
05259             //tmpLSPDb->clear(); //Why? Why? Why, you fucked-up crazy-ass weirdo beaver?!?
05260             availableSpace = ISIS_LSP_MAX_SIZE;
05261             unsigned char nsel;
05262             if(circuitType == L1_TYPE){
05263                 myLSPID[ISIS_SYSTEM_ID] = (*it).L1DIS[ISIS_SYSTEM_ID];
05264                 nsel = (*it).L1DIS[ISIS_SYSTEM_ID];
05265             }else if (circuitType == L2_TYPE){
05266                 myLSPID[ISIS_SYSTEM_ID] = (*it).L2DIS[ISIS_SYSTEM_ID];
05267                 nsel = (*it).L2DIS[ISIS_SYSTEM_ID];
05268             }else{
05269                 EV <<"ISIS: ERROR: Wrong circuitType in genLSP()" << endl;
05270             }
05271 
05272             //TLV IS_NEIGHBOURS
05273             this->addTLV(tlvTable, IS_NEIGHBOURS_LSP, circuitType, nsel);
05274 
05275             //TLV AREA_ADDRESS
05276             this->addTLV(tlvTable, AREA_ADDRESS, circuitType);
05277 
05278             for (unsigned char fragment = 0; !tlvTable->empty(); fragment++)
05279                 {
05280 
05281                 if (circuitType == L1_TYPE)
05282                 {
05283                     LSP = new ISISLSPPacket("L1 LSP"); //TODO based on circuitType
05284                     LSP->setType(L1_LSP);
05285                 }
05286                 else if (circuitType == L2_TYPE)
05287                 {
05288                     LSP = new ISISLSPPacket("L2 LSP"); //TODO based on circuitType
05289                     LSP->setType(L2_LSP);
05290                 }
05291                 else
05292                 {
05293                     EV << "ISIS: ERROR: Wrong circuitType in genLSP()" << endl;
05294                 }
05295 
05296                 //set pduLength
05297 
05298                 //set remLifeTime
05299                 LSP->setRemLifeTime(this->lspMaxLifetime);
05300 
05301                 //set lspID[8];
05302                 myLSPID[ISIS_SYSTEM_ID + 1] = fragment;
05303                 this->setLspID(LSP, myLSPID);
05304 
05305                 //set seqNum
05306                 LSP->setSeqNumber(1);
05307 
05308                 //set checksum
05309 
05310                 //set PATTLSPDBOLIS
05311                 LSP->setPATTLSPDBOLIS(0x01); //only setting IS type = L1 (TODO)
05312                 //set TLV
05313                 LSP->setTest("ahoj");
05314                 const char * lspId = (const char *)this->getLspID(LSP);
05315                 LSP->setTest(lspId);
05316                 //TLV_t tmpTLV;
05317 
05318                 for (; !tlvTable->empty();)
05319                 {
05320                     tmpTlv = tlvTable->at(0);
05321 
05322                     //TODO incorporate header size and mostly get actual MTU something like this->ISISIft.at(0).entry->getMTU()
05323                     if (tmpTlv->length > ISIS_LSP_MAX_SIZE)
05324                     {
05325                         //tlv won't fit into single message (this shouldn't happen)
05326                         EV << "ISIS: Warning: TLV won't fit into single message (this shouldn't happen)" << endl;
05327                         tlvTable->erase(tlvTable->begin());
05328                     }
05329                     else if (tmpTlv->length > availableSpace)
05330                     {
05331                         //tlv won't fit into this LSP, so break cycle and create new LSP
05332                         //                tmpLSPDb->push_back(LSP);
05333                         EV << "ISIS: This TLV is full." << endl;
05334                         break; //ends inner cycle
05335 
05336                     }
05337                     else
05338                     {
05339                         this->addTLV(LSP, tmpTlv);
05340                         //tlvSize = LSP->getTLVArraySize();
05341                         //LSP->setTLVArraySize(tlvSize + 1);
05342 
05343                         //update availableSpace
05344                         availableSpace = availableSpace - (2 + tmpTlv->length);
05345 
05346                         //clean up
05347                         delete tmpTlv->value;
05348                         delete tmpTlv;
05349                         tlvTable->erase(tlvTable->begin());
05350 
05351                     }
05352                 }
05353                 //this->printLSP(LSP, "genLSP, pseudo");
05354                 tmpLSPDb->push_back(LSP);
05355 
05356             }
05357 
05358         }
05359     }
05360 
05361 
05362 
05363     delete myLSPID;
05364     return tmpLSPDb;
05365 }
05366 
05367 /*
05368  * Calls refresh for appropriate level specified by timer.
05369  * @timer incomming timer
05370  */
05371 void ISIS::refreshLSP(ISISTimer *timer){
05372     //this->printLSPDB();
05373 
05374     if (this->isType == L1_TYPE || this->isType == L1L2_TYPE)
05375     {
05376         this->refreshLSP(L1_TYPE);
05377     }
05378     if (this->isType == L2_TYPE || this->isType == L1L2_TYPE)
05379     {
05380         this->refreshLSP(L2_TYPE);
05381     }
05382     //this->printLSPDB();
05383 
05384     this->schedule(timer);
05385 
05386 }
05387 
05388 /*
05389  * Increment sequence number for LSPs that belongs to this IS and set new remaining lifetime.
05390  * But only if their remaining lifetime is not already zero, or deadTimer set to LSP_DELETE.
05391  * @param circuitType is level
05392  */
05393 void ISIS::refreshLSP(short circuitType)
05394 {
05395     std::vector<LSPRecord*>* lspDb = this->getLSPDb(circuitType);
05396     std::vector<LSPRecord*>::iterator it = lspDb->begin();
05397     unsigned char *lspId;
05398     for(; it != lspDb->end(); ++it){
05399         lspId = this->getLspID((*it)->LSP);
05400         if(this->compareArrays(lspId, (unsigned char *) this->sysId, ISIS_SYSTEM_ID) && (*it)->deadTimer->getTimerKind() != LSP_DELETE && (*it)->LSP->getRemLifeTime() != 0 ){
05401             //this->printLSP((*it)->LSP, "print from refreshLSP");
05402             //std::cout<<"RefreshLSP: seqNum: " <<(*it)->LSP->getSeqNumber() << endl;
05403             (*it)->LSP->setSeqNumber((*it)->LSP->getSeqNumber() + 1);
05404             //std::cout<<"RefreshLSP: seqNum: " <<(*it)->LSP->getSeqNumber() << endl;
05405            // this->printLSP((*it)->LSP, "print from refreshLSP");
05406             (*it)->LSP->setRemLifeTime(this->lspMaxLifetime);
05407             //cancel original deadTimer
05408             cancelEvent((*it)->deadTimer);
05409 
05410             this->setSRMflags((*it), circuitType);
05411             //TODO what about SSNflags?
05412             //this->clearSSNflags((*it), circuitType);
05413 
05414             (*it)->simLifetime = simTime().dbl() + (*it)->LSP->getRemLifeTime();
05415 
05416             //re-schedule dead timer
05417             this->schedule((*it)->deadTimer, (*it)->LSP->getRemLifeTime());
05418         }
05419         delete lspId;
05420     }
05421 }
05422 
05423 
05424 
05425 /*
05426  * Call generateLSP for appropriate level.
05427  * @param timer is incomming timer.
05428  */
05429 void ISIS::generateLSP(ISISTimer *timer){
05430 
05431     if (this->isType == L1_TYPE || this->isType == L1L2_TYPE)
05432     {
05433         this->generateLSP(L1_TYPE);
05434     }
05435     if (this->isType == L2_TYPE || this->isType == L1L2_TYPE)
05436     {
05437         this->generateLSP(L2_TYPE);
05438     }
05439 
05440     this->schedule(timer);
05441 
05442 }
05443 
05444 
05445 /*
05446  * Generate and if necessary replace existing LSPs.
05447  * @param circuitType is level.
05448  */
05449 void ISIS::generateLSP(short circuitType)
05450 {
05451     /*
05452      * I am not 100% sure that this method correctly handle situation in which:
05453      * There are DIS's LSPs in DB, but when the DIS resign, and we don't generate any DIS's LSPs
05454      * we don't even know that we should purge something.
05455      * In worst case scenario these LSPs age out.
05456      */
05457 
05458     unsigned char *lspId;
05459     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
05460     //don't forget to delete it
05461     std::vector<ISISLSPPacket *>* tmpLSPDb;
05462 
05463     tmpLSPDb = this->genLSP(circuitType);
05464 
05465     if (lspDb->empty())
05466     {
05467         //our database is empty, so put everything from tmpLSPDb into L1LSPDb
05468         //LSPRecord* tmpLSPRecord;
05469         for (std::vector<ISISLSPPacket *>::iterator it = tmpLSPDb->begin(); it != tmpLSPDb->end(); ++it)
05470         {
05471             this->installLSP((*it), circuitType);
05472 
05473         }
05474         tmpLSPDb->clear();
05475     }
05476 
05477     else if (tmpLSPDb->empty())
05478     {
05479         //nothing generated so purge all existing LSPs
05480         this->purgeMyLSPs(circuitType);
05481     }
05482     else
05483     {
05484         //something in between
05485         /*
05486          * 1. get System-ID + NSEL from LSP-ID
05487          * 2. after processing check if the next generated (if any exist) has the same LAN-ID
05488          *      if not -> purge all remaining LSP fragments from database with same LAN-ID
05489          *      if they have same LAN-ID OR there is not another LSP fragment, continue in processing
05490          */
05491 
05492         //lspId = this->getLspID(tmpLSPDb->at(0));
05493         //we need to compare each LSP
05494         //because of the way we create LSP, from the first one that doesn't match we can discard/replace all successive
05495         LSPRecord * tmpLSPRecord; // = this->getLSPFromDbByID(this->getLspID(tmpLSPDb->at(0)), circuitType);
05496         for (; !tmpLSPDb->empty();)
05497         {
05498             lspId = this->getLspID(tmpLSPDb->front());
05499             if ((tmpLSPRecord = this->getLSPFromDbByID(this->getLspID(tmpLSPDb->at(0)), circuitType)) != NULL)
05500             {
05501                 if (this->compareLSP(tmpLSPRecord->LSP, tmpLSPDb->at(0)))
05502                 {
05503                     //LSP match we don't need to do anything
05504                     delete tmpLSPDb->at(0);
05505                     tmpLSPDb->erase(tmpLSPDb->begin());
05506                     tmpLSPRecord = NULL;
05507                     //continue;
05508 
05509                 }
05510                 else
05511                 {
05512                     //install tmpLSPDb->at(0) into this->L1LSPDb
05513                     this->replaceLSP(tmpLSPDb->at(0), tmpLSPRecord, circuitType);
05514                     //set SRMflag on all circuits (that have at least one adjacency UP)
05515                     //done in replaceLSP
05516 
05517                     //erase
05518                     tmpLSPDb->erase(tmpLSPDb->begin());
05519 
05520                     //set tmpLSPRecord to NULL
05521                     tmpLSPRecord = NULL;
05522                     //continue;
05523                 }
05524             }
05525             else
05526             {
05527                 //install tmpLSPDb->at(0)
05528                 this->installLSP(*tmpLSPDb->begin(), circuitType);
05529 
05530                 //erase
05531                 tmpLSPDb->erase(tmpLSPDb->begin());
05532                 //break;
05533             }
05534             /* if there is any generated LSP in tmpLSPDb, and the current LSP-ID
05535              *  and next LSP's LSP-ID doesn't match (without fragment-ID) => we don't have any LSPs from this LAN-ID,
05536              *  so purge all remaining LSPs with matching LAN-ID (System-ID + NSEL)
05537              */
05538             if (!tmpLSPDb->empty() && !this->compareArrays(lspId, this->getLspID((*tmpLSPDb->begin())), ISIS_SYSTEM_ID + 1)) {
05539                 //purge all remaining fragments with lspId (without fragment-ID)
05540                 lspId[ISIS_SYSTEM_ID + 1] = lspId[ISIS_SYSTEM_ID + 1] + 1;
05541                 this->purgeRemainLSP(lspId, circuitType);
05542             }
05543             //tmpLSPRecord = this->getLSPFromDbByID(this->getLspID(tmpLSPDb->at(0)), circuitType);
05544 
05545             delete lspId;
05546         }
05547 
05548     }
05549 
05550     delete tmpLSPDb;
05551 }
05552 
05553 /*
05554  * Purge successive LSPs for lspId. (lspId itself is not purged)
05555  * @param lspId is first LSP that should be purged.
05556  * @param circuitType is level
05557  */
05558 void ISIS::purgeRemainLSP(unsigned char *lspId, short circuitType){
05559 
05560     //lspId[ISIS_SYSTEM_ID + 1] = lspId[ISIS_SYSTEM_ID + 1] + 1;
05561 
05562     while(this->getLSPFromDbByID(lspId, circuitType) != NULL){
05563         this->purgeLSP(lspId, circuitType);
05564         //this should increment fragment-ID for the next round check
05565         lspId[ISIS_SYSTEM_ID + 1] = lspId[ISIS_SYSTEM_ID + 1] + 1;
05566 
05567     }
05568 }
05569 
05570 /*
05571  * Initiate purge of ALL LSPs generated by this IS on specified level.
05572  * @param circuitType is level.
05573  */
05574 void ISIS::purgeMyLSPs(short circuitType){
05575 
05576     std::vector<LSPRecord *>* lspDb;
05577 
05578     lspDb = this->getLSPDb(circuitType);
05579     unsigned char *lspId;
05580     for(std::vector<LSPRecord*>::iterator it = lspDb->begin(); it != lspDb->end(); ++it){
05581         lspId = this->getLspID((*it)->LSP);
05582         if(this->compareArrays(lspId, (unsigned char *) this->sysId, ISIS_SYSTEM_ID)){
05583             this->purgeLSP(lspId, circuitType);
05584         }
05585         delete lspId;
05586     }
05587 }
05588 
05589 /*
05590  * This method is used for purging in-memory LSP's when the remaining Lifetime becomes zero.
05591  */
05592 void ISIS::purgeLSP(unsigned char *lspId, short circuitType){
05593 
05594     LSPRecord * lspRec;
05595     if((lspRec = this->getLSPFromDbByID(lspId, circuitType)) != NULL){
05596         //std::cout<<"purgeLSP seqNum: " << lspRec->LSP->getSeqNumber() <<endl;
05597         //lspRec->LSP->setSeqNumber(0);
05598         //TODO do we need to increment seqNum or equal seqNum with remLife == 0 will replace that LSP?
05599         //lspRec->LSP->setSeqNumber(lspRec->LSP->getSeqNumber() + 1);
05600         //std::cout<<"purgeLSP seqNum: " << lspRec->LSP->getSeqNumber() <<endl;
05601         /* 7.3.16.4.  */
05602         lspRec->LSP->setRemLifeTime(0);
05603         //delete all TLV from lspRec-LSP and set TLVArraySize = 0
05604         //TODO check if area address TLV is necessary
05605         //add only Area Address
05606 /*        for(unsigned int i = 0; i < lspRec->LSP->getTLVArraySize(); i++){
05607             if(lspRec->LSP->getTLV(i).value != NULL){
05608                 delete lspRec->LSP->getTLV(i).value;
05609             }
05610         }*/
05611 
05612         lspRec->LSP->setTLVArraySize(0);
05613         //if TLV Area Addresses should be present even in purge LSP than add it
05614         //this->addTLV(lspRec->LSP, AREA_ADDRESS);
05615 
05616         this->setSRMflags(lspRec, circuitType);
05617 
05618 
05619         //simLifetime now express the time when the LSP has been purged so after "N" seconds it can be removed completely
05620         lspRec->simLifetime = simTime().dbl();
05621 
05622         //remove the deadTimer from future events
05623         cancelEvent(lspRec->deadTimer);
05624         //change timer type
05625         lspRec->deadTimer->setTimerKind(LSP_DELETE);
05626         //and reschedule it again
05627         this->schedule(lspRec->deadTimer);
05628     }
05629 
05630 }
05631 
05632 /*
05633  * Purge of an received LSP with zero Remaining Lifetime according to 7.3.16.4
05634  * Received lsp is deleted at the end. Only exception is when replacing current LSP then
05635  * early return is executed to avoid deleting received lsp.
05636  *
05637  */
05638 void ISIS::purgeLSP(ISISLSPPacket *lsp, short circuitType){
05639     LSPRecord *lspRec;
05640     int gateIndex = lsp->getArrivalGate()->getIndex();
05641     //std::vector<LSPRecord *> * lspDb = this->getLSPDb(circuitType);
05642     unsigned char * lspId = this->getLspID(lsp);
05643 
05644     //if lsp is not in memory
05645     if((lspRec = this->getLSPFromDbByID(lspId, circuitType)) == NULL){
05646 
05647         //send an ack of the LSP on circuit C
05648         if(!this->getIfaceByGateIndex(gateIndex)->network){
05649             /* TODO uncomment warning when sending ack for lsp NOT in db is implemented */
05650             EV<<"ISIS: Warning: Should send ACK for purged LSP over non-broadcast circuit. (Not yet implemented)."<<endl;
05651             //explicit ack are only on non-broadcast circuits
05652             //this->setSSNflag(lspRec, gateIndex, circuitType);
05653         }
05654     }else
05655 
05656     {   /*7.3.16.4. b) LSP from S is in the DB */
05657         if (!this->compareArrays(this->getSysID(lsp), (unsigned char *) this->sysId, ISIS_SYSTEM_ID))
05658         {
05659             //if received LSP is newer
05660             //7.3.16.4 b) 1)
05661             if (lsp->getSeqNumber() > lspRec->LSP->getSeqNumber()
05662                     || (lsp->getSeqNumber() == lspRec->LSP->getSeqNumber() && lspRec->LSP->getRemLifeTime() != 0))
05663             {
05664                 //store the new LSP in DB, overwriting existing LSP
05665                 //replaceLSP
05666                 this->replaceLSP(lsp, lspRec, circuitType);
05667                 //lsp is installed in DB => don't delete it, so early return
05668                 delete lspId;
05669                 return;
05670             }
05671             /* 7.3.16.4. b) 2)*/
05672             else if (lsp->getSeqNumber() == lspRec->LSP->getSeqNumber() && lsp->getRemLifeTime() == 0
05673                     && lspRec->LSP->getRemLifeTime() == 0)
05674             {
05675                 /* clear SRMflag for C and
05676                  * if C is non-broadcast circuit, set SSNflag for C
05677                  */
05678                 /* 7.3.16.4. b) 2) i.*/
05679                 this->clearSRMflag(lspRec, gateIndex, circuitType);
05680                 if (!this->getIfaceByGateIndex(gateIndex)->network)
05681                 {
05682                     /* 7.3.16.4. b) 2) ii.*/
05683                     //explicit ack are only on non-broadcast circuits
05684                     this->setSSNflag(lspRec, gateIndex, circuitType);
05685                 }
05686 
05687             }
05688             /* 7.3.16.4. b) 3).*/
05689             else if (lsp->getSeqNumber() < lspRec->LSP->getSeqNumber())
05690             {
05691                 /* 7.3.16.4. b) 3) i.*/
05692                 this->setSRMflag(lspRec, gateIndex, circuitType);
05693                 /* 7.3.16.4. b) 3) ii.*/
05694                 this->clearSSNflag(lspRec, gateIndex, circuitType);
05695             }
05696 
05697 
05698         }
05699         /*7.3.16.4. c) it's our own LSP */
05700         else{
05701             if(lspRec->LSP->getRemLifeTime() != 0){
05702                 if(lsp->getSeqNumber() >= lspRec->LSP->getSeqNumber()){
05703                     //std::cout<<"purgeLSP seqNum: " << lspRec->LSP->getSeqNumber() <<endl;
05704                     lspRec->LSP->setSeqNumber(lsp->getSeqNumber() + 1);
05705                     //std::cout<<"purgeLSP seqNum: " << lspRec->LSP->getSeqNumber() <<endl;
05706                 }
05707                 /*7.3.16.4. c) 4) set SRMflags for all circuits */
05708                 this->setSRMflags(lspRec, circuitType);
05709             }
05710         }
05711     }
05712     delete lsp;
05713     delete lspId;
05714 }
05715 
05716 /*
05717  * This method permanently removes LSP from DB.
05718  * @timer is timer.
05719  */
05720 void ISIS::deleteLSP(ISISTimer *timer)
05721 {
05722     short circuitType = timer->getIsType();
05723     unsigned char* lspId = this->getLspID(timer);
05724     std::vector<LSPRecord *> *lspDb = this->getLSPDb(circuitType);
05725     unsigned char * tmpLspId;
05726 
05727     for(std::vector<LSPRecord*>::iterator it = lspDb->begin(); it != lspDb->end(); ++it){
05728         tmpLspId = this->getLspID((*it)->LSP);
05729         if(this->compareArrays(tmpLspId, lspId, ISIS_SYSTEM_ID + 2)){
05730             //clearing *flags shoudn't be necessary, but just to be sure
05731             this->clearSRMflags((*it), timer->getIsType());
05732             this->clearSSNflags((*it), timer->getIsType());
05733             delete (*it);
05734             lspDb->erase(it);
05735             delete lspId;
05736             delete tmpLspId;
05737             return;
05738         }
05739         delete tmpLspId;
05740     }
05741 
05742     delete lspId;
05743 }
05744 
05745 
05746 /*
05747  * Returns pointer to LSP database specified by level
05748  * @param circuitType is level.
05749  * @return pointer to LSP database.
05750  */
05751 std::vector<LSPRecord *> * ISIS::getLSPDb(short circuitType)
05752 {
05753 
05754     if (circuitType == L1_TYPE)
05755     {
05756         return this->L1LSPDb;
05757     }
05758     else if (circuitType == L2_TYPE)
05759     {
05760         return this->L2LSPDb;
05761     }
05762 
05763     return NULL;
05764 }
05765 
05766 /*
05767  * Return pointer to adjacency table specified by level.
05768  * @param circuitType is level
05769  * @return pointer to adjacency table.
05770  */
05771 std::vector<ISISadj> * ISIS::getAdjTab(short circuitType)
05772 {
05773 
05774     if (circuitType == L1_TYPE)
05775     {
05776         return &(this->adjL1Table);
05777     }
05778     else if (circuitType == L2_TYPE)
05779     {
05780         return &(this->adjL2Table);
05781     }
05782 
05783     return NULL;
05784 }
05785 
05786 /*
05787  * Returns appropriate SRM Queues for point-to-point link.
05788  * @param circuitType is level.
05789  * @return vector (of vector) of SRM flags.
05790  */
05791 std::vector<std::vector<FlagRecord*>* > * ISIS::getSRMPTPQueue(short circuitType){
05792 
05793     if (circuitType == L1_TYPE)
05794     {
05795         return (this->L1SRMPTPQueue);
05796     }
05797     else if (circuitType == L2_TYPE)
05798     {
05799         return (this->L2SRMPTPQueue);
05800     }
05801 
05802     return NULL;
05803 }
05804 
05805 std::vector<std::vector<FlagRecord*>* > * ISIS::getSRMBQueue(short circuitType){
05806 
05807     if (circuitType == L1_TYPE)
05808     {
05809         return (this->L1SRMBQueue);
05810     }
05811     else if (circuitType == L2_TYPE)
05812     {
05813         return (this->L2SRMBQueue);
05814     }
05815 
05816     return NULL;
05817 }
05818 
05819 std::vector<std::vector<FlagRecord*>* > * ISIS::getSSNPTPQueue(short circuitType){
05820 
05821     if (circuitType == L1_TYPE)
05822     {
05823         return (this->L1SSNPTPQueue);
05824     }
05825     else if (circuitType == L2_TYPE)
05826     {
05827         return (this->L2SSNPTPQueue);
05828     }
05829 
05830     return NULL;
05831 }
05832 
05833 std::vector<std::vector<FlagRecord*>* > * ISIS::getSSNBQueue(short circuitType){
05834 
05835     if (circuitType == L1_TYPE)
05836     {
05837         return (this->L1SSNBQueue);
05838     }
05839     else if (circuitType == L2_TYPE)
05840     {
05841         return (this->L2SSNBQueue);
05842     }
05843 
05844     return NULL;
05845 }
05846 
05847 
05848 
05849 
05850 /*
05851  * @param circuitType is probably redundant and will be removed
05852  */
05853 
05854 void ISIS::setSRMflag(LSPRecord * lspRec, int index, short circuitType)
05855 {
05856     ISISinterface * iface = &(this->ISISIft.at(index));
05857     std::vector<FlagRecord*> *SRMQueue = this->getSRMQ(iface->network, index, circuitType);
05858     if(lspRec->SRMflags.size() == 0 ){
05859         this->addFlags(lspRec, circuitType);
05860     }
05861     /* This should prevent from adding multiple FlagRecord for the same LSP-gateIndex pair */
05862     if(lspRec->SRMflags.at(index) == true){
05863         return;
05864     }
05865 
05866     //set SRMflag on interface only if there is  at least one adjacency UP
05867     if (this->isUp(index, circuitType))
05868     {
05869         lspRec->SRMflags.at(index) = true; //setting true (Send Routing Message) on every interface
05870         FlagRecord *tmpSRMRec = new FlagRecord;
05871         tmpSRMRec->lspRec = lspRec;
05872         tmpSRMRec->index = index;
05873         SRMQueue->push_back(tmpSRMRec);
05874         /*
05875         if (this->ISISIft.at(index).network)
05876         {
05877             //TODO how do you know it's L1 and not L2
05878             this->L1SRMBQueue->at(index)->push_back(tmpSRMRec);
05879         }
05880         else
05881         {
05882             this->L1SRMPTPQueue->at(index)->push_back(tmpSRMRec);
05883         }*/
05884     }
05885 
05886 }
05887 
05888 void ISIS::setSRMflags(LSPRecord *lspRec, short circuitType)
05889 {
05890     if(lspRec->SRMflags.size() == 0 ){
05891         this->addFlags(lspRec, circuitType);
05892     }
05893     for (unsigned int i = 0; i < lspRec->SRMflags.size(); i++)
05894     {
05895         this->setSRMflag(lspRec, i, circuitType);
05896     }
05897 
05898 }
05899 
05900 void ISIS::setSRMflagsBut(LSPRecord *lspRec, unsigned int index, short circuitType)
05901 {
05902     if(lspRec->SRMflags.size() == 0 ){
05903         this->addFlags(lspRec, circuitType);
05904     }
05905     for (unsigned int i = 0; i < lspRec->SRMflags.size(); i++)
05906     {
05907         if(i == index){
05908             this->clearSRMflag(lspRec, i, circuitType);
05909         }else{
05910             this->setSRMflag(lspRec, i, circuitType);
05911         }
05912     }
05913 
05914 }
05915 
05916 void ISIS::clearSRMflag(LSPRecord *lspRec, int index, short circuitType){
05917 
05918     std::vector<FlagRecord*>* srmQ;
05919     srmQ =  this->getSRMQ(this->ISISIft.at(index).network, this->ISISIft.at(index).gateIndex, circuitType);
05920 
05921     //clear flag
05922     lspRec->SRMflags.at(index) = false;
05923 
05924     //and remove FlagRecord from Queue
05925     std::vector<FlagRecord*>::iterator it = srmQ->begin();
05926     for (; it != srmQ->end(); )
05927     {
05928         if ((*it)->index == index && (*it)->lspRec == lspRec)
05929         {
05930             it = srmQ->erase(it);
05931             //break;
05932         }else{
05933             ++it;
05934         }
05935     }
05936 }
05937 
05938 void ISIS::clearSRMflags(LSPRecord *lspRec, short circuitType){
05939 
05940     if(lspRec->SRMflags.size() == 0 ){
05941         this->addFlags(lspRec, circuitType);
05942     }
05943     for (unsigned int i = 0; i < lspRec->SRMflags.size(); i++)
05944     {
05945         this->clearSRMflag(lspRec, i, circuitType);
05946     }
05947 
05948 }
05949 
05950 void ISIS::clearSRMflagsBut(LSPRecord *lspRec, unsigned int index, short circuitType)
05951 {
05952     if(lspRec->SRMflags.size() == 0 ){
05953         this->addFlags(lspRec, circuitType);
05954     }
05955     for (unsigned int i = 0; i < lspRec->SRMflags.size(); i++)
05956     {
05957         if(i == index){
05958             this->setSRMflag(lspRec, i, circuitType);
05959         }else{
05960             this->clearSRMflag(lspRec, i, circuitType);
05961         }
05962     }
05963 
05964 }
05965 
05966 
05967 
05968 std::vector<FlagRecord*>* ISIS::getSRMQ(bool network, int index, short circuitType){
05969     if(circuitType == L1_TYPE){
05970         if(network){
05971             return this->L1SRMBQueue->at(index);
05972         }else{
05973             return this->L1SRMPTPQueue->at(index);
05974         }
05975 
05976     }else if (circuitType == L2_TYPE){
05977         if(network){
05978                     return this->L2SRMBQueue->at(index);
05979                 }else{
05980                     return this->L2SRMPTPQueue->at(index);
05981                 }
05982     }
05983     return NULL;
05984 }
05985 
05986 
05987 void ISIS::setSSNflag(LSPRecord * lspRec, int index, short circuitType)
05988 {
05989 
05990     ISISinterface * iface = &(this->ISISIft.at(index));
05991         std::vector<FlagRecord*> *SSNQueue = this->getSSNQ(iface->network, index, circuitType);
05992 
05993     if (lspRec->SSNflags.size() == 0)
05994         {
05995             this->addFlags(lspRec, circuitType);
05996         }
05997 
05998     /* This should prevent from adding multiple FlagRecord for the same LSP-gateIndex pair */
05999      if(lspRec->SSNflags.at(index) == true){
06000          return;
06001      }
06002     //set SSNflag on interface only if there is  at least one adjacency UP
06003     if (this->isUp(index, circuitType))
06004     {
06005 
06006         lspRec->SSNflags.at(index) = true; //setting true (Send Routing Message) on every interface
06007         FlagRecord *tmpSSNRec = new FlagRecord;
06008         tmpSSNRec->lspRec = lspRec;
06009         tmpSSNRec->index = index;
06010         SSNQueue->push_back(tmpSSNRec);
06011 //        if (this->ISISIft.at(index).network)
06012 //        {
06013 //            this->L1SSNBQueue->at(index)->push_back(tmpSSNRec);
06014 //        }
06015 //        else
06016 //        {
06017 //            this->L1SSNPTPQueue->at(index)->push_back(tmpSSNRec);
06018 //        }
06019     }
06020 
06021 }
06022 
06023 void ISIS::setSSNflags(LSPRecord *lspRec, short circuitType)
06024 {
06025     if (lspRec->SSNflags.size() == 0)
06026     {
06027         this->addFlags(lspRec, circuitType);
06028     }
06029 
06030     for (unsigned int i = 0; i < lspRec->SSNflags.size(); i++)
06031     {
06032         this->setSSNflag(lspRec, i, circuitType);
06033     }
06034 
06035 }
06036 
06037 void ISIS::setSSNflagsBut(LSPRecord *lspRec, unsigned int index, short circuitType)
06038 {
06039     if(lspRec->SSNflags.size() == 0 ){
06040         this->addFlags(lspRec, circuitType);
06041     }
06042     for (unsigned int i = 0; i < lspRec->SSNflags.size(); i++)
06043     {
06044         if(i == index){
06045             this->clearSSNflag(lspRec, i, circuitType);
06046         }else{
06047             this->setSSNflag(lspRec, i, circuitType);
06048         }
06049     }
06050 
06051 }
06052 
06053 
06054 void ISIS::clearSSNflag(LSPRecord *lspRec, int index, short circuitType){
06055 
06056     std::vector<FlagRecord*>* ssnQ;
06057     ssnQ =  this->getSSNQ(this->ISISIft.at(index).network, this->ISISIft.at(index).gateIndex, circuitType);
06058 
06059     //clear flag
06060     lspRec->SSNflags.at(index) = false;
06061 
06062     //and remove FlagRecord from Queue
06063     std::vector<FlagRecord*>::iterator it = ssnQ->begin();
06064     for (; it != ssnQ->end();)
06065     {
06066         if ((*it)->index == index && (*it)->lspRec == lspRec)
06067         {
06068             it = ssnQ->erase(it);
06069             //break;
06070         }else{
06071             ++it;
06072         }
06073     }
06074 }
06075 
06076 void ISIS::clearSSNflags(LSPRecord *lspRec, short circuitType){
06077 
06078     if(lspRec->SSNflags.size() == 0 ){
06079         this->addFlags(lspRec, circuitType);
06080     }
06081     for (unsigned int i = 0; i < lspRec->SSNflags.size(); i++)
06082     {
06083         this->clearSSNflag(lspRec, i, circuitType);
06084     }
06085 
06086 }
06087 
06088 void ISIS::clearSSNflagsBut(LSPRecord *lspRec, unsigned int index, short circuitType)
06089 {
06090     if(lspRec->SSNflags.size() == 0 ){
06091         this->addFlags(lspRec, circuitType);
06092     }
06093     for (unsigned int i = 0; i < lspRec->SSNflags.size(); i++)
06094     {
06095         if(i == index){
06096             this->setSSNflag(lspRec, i, circuitType);
06097         }else{
06098             this->clearSSNflag(lspRec, i, circuitType);
06099         }
06100     }
06101 
06102 }
06103 
06104 std::vector<FlagRecord*>* ISIS::getSSNQ(bool network, int index, short circuitType){
06105     if(circuitType == L1_TYPE){
06106         if(network){
06107             return this->L1SSNBQueue->at(index);
06108         }else{
06109             return this->L1SSNPTPQueue->at(index);
06110         }
06111 
06112     }else if (circuitType == L2_TYPE){
06113         if(network){
06114                     return this->L2SSNBQueue->at(index);
06115                 }else{
06116                     return this->L2SSNPTPQueue->at(index);
06117                 }
06118     }
06119     return NULL;
06120 }
06121 
06122 
06123 
06124 
06125 void ISIS::replaceLSP(ISISLSPPacket *lsp, LSPRecord *lspRecord, short circuitType){
06126 
06127     //increase sequence number
06128     //std::cout<<"replaceLSP seqNum: "<< lspRecord->LSP->getSeqNumber() <<endl;
06129     /*if(lsp->getSeqNumber() < lspRecord->LSP->getSeqNumber()){
06130         lsp->setSeqNumber(lspRecord->LSP->getSeqNumber() + 1);
06131     }else{
06132         lsp->setSeqNumber(lsp->getSeqNumber() + 1);
06133     }*/
06134     lsp->setSeqNumber(lspRecord->LSP->getSeqNumber() + 1);
06135     //now we can delete the previous LSP
06136 
06137     delete lspRecord->LSP;
06138 
06139     //set new lsp
06140     lspRecord->LSP = lsp;
06141     //std::cout<<"replaceLSP seqNum: "<< lspRecord->LSP->getSeqNumber() <<endl;
06142     //create new timer
06143     //lspRecord->deadTimer = new ISISTimer("LSP Dead Timer");
06144     //select appropriate type (this could be performed based on lsp)
06145     this->cancelEvent(lspRecord->deadTimer);
06146 
06147     lspRecord->deadTimer->setTimerKind(LSP_DEAD);
06148 
06149 
06150     lspRecord->deadTimer->setIsType(circuitType);
06151     for (unsigned int i = 0; i < lspRecord->deadTimer->getLSPidArraySize(); i++)
06152     {
06153         lspRecord->deadTimer->setLSPid(i, lspRecord->LSP->getLspID(i));
06154     }
06155 
06156     /* need to check  this for replacing LSP from genLSP */
06157     if(lsp->getArrivalGate() != NULL){
06158         //received so don't set SRM flag on that interface
06159 //        int gateIndex = lsp->getArrivalGate()->getIndex();
06160 //        /* 7.3.15.1 e) 1) ii. and iii. */ /* 7.3.16.4 b) 1) ii. and iii. */
06161 //        this->setSRMflagsBut(lspRecord, gateIndex , circuitType);
06162 //        /* 7.3.16.4 b) 1) v.  MODIFIED*/
06163 //        this->clearSSNflags(lspRecord, circuitType);
06164 //        //for non-broadcast /* 7.3.16.4 b) 1) iv. */
06165 //        if(!this->ISISIft.at(gateIndex).network){
06166 //            this->setSSNflag(lspRecord, gateIndex, circuitType);
06167 //        }
06168         //received so don't set SRM flag on that interface
06169         int gateIndex = lsp->getArrivalGate()->getIndex();
06170         this->setSRMflagsBut(lspRecord, gateIndex , circuitType);
06171         //for non-broadcast /* 7.3.16.4 b) 1) iv. */
06172         if(!this->ISISIft.at(gateIndex).network){
06173             this->setSSNflag(lspRecord, gateIndex, circuitType);
06174         }
06175         /* 7.3.16.4 b) 1) v. */
06176         this->clearSSNflagsBut(lspRecord, gateIndex, circuitType);
06177 
06178 
06179 
06180 
06181     }else{
06182         //generated -> set SRM on all interfaces
06183         this->setSRMflags(lspRecord, circuitType);
06184         //TODO what with SSN?
06185         //this->clearSSNflags(lspRecord, circuitType);
06186     }
06187 
06188 
06189 
06190     //set simulation time when the lsp will expire
06191     lspRecord->simLifetime = simTime().dbl() + lspRecord->LSP->getRemLifeTime();
06192 
06193     this->schedule(lspRecord->deadTimer, lsp->getRemLifeTime());
06194 
06195 
06196 }
06197 
06198 void ISIS::addFlags(LSPRecord *lspRec, short circuitType){
06199 
06200     //add flags
06201     if(!lspRec->SRMflags.empty() || !lspRec->SSNflags.empty()){
06202         EV <<"ISIS: Warning: Adding *flags to non-empty vectors." <<endl;
06203         return;
06204 
06205     }
06206     for (std::vector<ISISinterface>::iterator intIt = this->ISISIft.begin(); intIt != this->ISISIft.end(); ++intIt)
06207     {
06208 
06209         lspRec->SRMflags.push_back(false);
06210         lspRec->SSNflags.push_back(false);
06211 
06212     }
06213     //set SRM
06214     //this->setSRMflags(lspRec, circuitType);
06215 }
06216 
06217 
06218 LSPRecord * ISIS::installLSP(ISISLSPPacket *lsp, short circuitType)
06219 {
06220 
06221     LSPRecord * tmpLSPRecord = new LSPRecord;
06222     std::vector<LSPRecord*> * lspDb = this->getLSPDb(circuitType);
06223 
06224     tmpLSPRecord->LSP = lsp;
06225     //TODO
06226     /* if lsp is my LSP
06227      *   then set all flags
06228      * else
06229      *   set all BUT the received circuts
06230      */
06231 
06232     if(lsp->getArrivalGate() !=NULL){
06233         int gateIndex = lsp->getArrivalGate()->getIndex();
06234         /* 7.3.15.1 e) 1) ii. */
06235         this->setSRMflagsBut(tmpLSPRecord, gateIndex, circuitType);
06236         /*TODO 7.3.15.1 e) 1) iii. -> redundant?? */
06237         //this->clearSRMflag(tmpLSPRecord, lsp->getArrivalGate()->getIndex(), circuitType);
06238 
06239         /* change from specification */
06240         /* iv. and v. are "switched */
06241         /* 7.3.15.1 e) 1) v. */
06242         this->clearSSNflags(tmpLSPRecord, circuitType);
06243 
06244         if (!this->ISISIft.at(gateIndex).network)
06245         {
06246             /* 7.3.15.1 e) 1) iv. */
06247             this->setSSNflag(tmpLSPRecord, gateIndex, circuitType);
06248         }
06249 
06250     }else{
06251         /* Never set SRM flag for lsp with seqNum == 0 */
06252         if(lsp->getSeqNumber() > 0){
06253         /* installLSP is called from genLSP */
06254             this->setSRMflags(tmpLSPRecord, circuitType);
06255         }
06256         //TODO what about SSNflags?
06257         //this->clearSSNflags(tmpLSPRecord, circuitType);
06258     }
06259 
06260 
06261     tmpLSPRecord->deadTimer = new ISISTimer("LSP Dead Timer");
06262     tmpLSPRecord->deadTimer->setTimerKind(LSP_DEAD);
06263     tmpLSPRecord->deadTimer->setIsType(circuitType);
06264     for (unsigned int i = 0; i < tmpLSPRecord->deadTimer->getLSPidArraySize(); i++)
06265     {
06266         tmpLSPRecord->deadTimer->setLSPid(i, tmpLSPRecord->LSP->getLspID(i));
06267     }
06268 
06269     tmpLSPRecord->simLifetime = simTime().dbl() + tmpLSPRecord->LSP->getRemLifeTime();
06270 
06271     this->schedule(tmpLSPRecord->deadTimer, lsp->getRemLifeTime());
06272 
06273     lspDb->push_back(tmpLSPRecord);
06274 
06275     return lspDb->back();
06276 }
06277 
06278 /*
06279  * Returns true if packets match
06280  */
06281 bool ISIS::compareLSP(ISISLSPPacket *lsp1, ISISLSPPacket *lsp2){
06282 
06283     //pduLength
06284     //so far this field is not used, or at least not properly
06285 
06286     //remLifeTime
06287     //newly generated LSP will have different remaining time
06288 
06289     //lspID
06290     //lspIDs have to match, because lsp2 is selected based on matching LSP-ID
06291 
06292     //seqNumber
06293     //newly generated LSP will have seqNumber set to 1
06294 
06295     //checksum
06296     //not used
06297 
06298     //PATTLSPDBOLIS
06299     //so far this field is set only to 0x01 = only IS Type = L1, but check anyway
06300     if(lsp1->getPATTLSPDBOLIS() != lsp2->getPATTLSPDBOLIS()){
06301         return false;
06302     }
06303 
06304     if(lsp1->getTLVArraySize() != lsp2->getTLVArraySize()){
06305         return false;
06306     }
06307 
06308     for(unsigned int i = 0; i < lsp1->getTLVArraySize(); i++){
06309         if(lsp1->getTLV(i).type != lsp2->getTLV(i).type || lsp1->getTLV(i).length != lsp2->getTLV(i).length || !this->compareArrays(lsp1->getTLV(i).value, lsp2->getTLV(i).value, lsp1->getTLV(i).length) ){
06310             return false;
06311         }
06312     }
06313 
06314     //packets match
06315     return true;
06316 }
06317 
06318 /*
06319  * Returns LSPRecord from LSP database specified by LSP-ID.
06320  * @param LSPID is ID of LSP to be returned.
06321  * @param circuitType is level.
06322  */
06323 LSPRecord* ISIS::getLSPFromDbByID(unsigned char *LSPID, short circuitType)
06324 {
06325 
06326     std::vector<LSPRecord *> *lspDb;
06327 
06328     if (LSPID == NULL)
06329     {
06330         return NULL;
06331     }
06332 
06333     lspDb = this->getLSPDb(circuitType);
06334     unsigned char *lspId;
06335     for (std::vector<LSPRecord*>::iterator it = lspDb->begin(); it != lspDb->end(); ++it)
06336     {
06337         lspId = this->getLspID((*it)->LSP);
06338         if (this->compareArrays(lspId, LSPID, ISIS_SYSTEM_ID + 2))
06339         {
06340             delete lspId;
06341             return (*it);
06342         }
06343         delete lspId;
06344     }
06345 
06346     return NULL;
06347 }
06348 
06349 /*
06350  * Returns "first" LSP-ID of this system eg. SYSTEM-ID.00-00, because this LSP-I
06351  */
06352 unsigned char* ISIS::getLSPID()
06353 {
06354 
06355     unsigned char *myLSPID = new unsigned char[8];
06356 
06357     this->copyArrayContent((unsigned char*) this->sysId, myLSPID, ISIS_SYSTEM_ID, 0, 0);
06358     myLSPID[6] = 0;
06359     myLSPID[7] = 0;
06360     return myLSPID;
06361 }
06362 
06363 
06364 
06369 void ISIS::updateMyLSP()
06370 {
06371     unsigned char myLSPid[8];
06372 
06373     //at first, we generate (or update existing) non-psudonode LSP with pesudonode ID (myLSPid[6]) equal to 0 according to ISO10859
06374     //myLSPid[7] is always 0 because omnet doesn't support packet fragmentation (or I don't want to solve that :D)
06375     this->copyArrayContent((unsigned char*)this->sysId, myLSPid, 6, 0, 0);
06376     myLSPid[6] = 0; myLSPid[7] = 0;
06377 
06378 
06379     bool found = false;
06380 
06381     //we try to find existing LSP with this ID
06382     for(unsigned int j=0; j<L1LSP.size(); j++)
06383     {
06384         //if we have found matching LSP ID
06385         if(this->compareArrays(myLSPid, L1LSP.at(j).LSPid, 8))
06386         {
06387             //update it
06388 
06389             //increment sequence number
06390             L1LSP.at(j).seq++;
06391 
06392             //reset dead timer
06393             cancelEvent(L1LSP.at(j).deadTimer);
06394             scheduleAt(simTime() + 50, L1LSP.at(j).deadTimer);   //should be 1200 secs.
06395 
06396             //set neighbours (pseudonode neighbours)
06397             std::vector<LSPneighbour> neighbours;
06398 
06399             //as we are using ethernet, which is multiaccess medium, we have to add pseudonodes as IS neighbours
06400             //at this point, network should be converged and assigned appropriate designated IS for each LAN
06401 
06402             for(unsigned int i=0; i<ISISIft.size(); i++)
06403             {
06404                 if(ISISIft.at(i).ISISenabled && (ISISIft.at(i).circuitType == L1_TYPE || ISISIft.at(i).circuitType == L1L2_TYPE))
06405                 {
06406                     LSPneighbour neighbour;
06407                     ISISadj *tmpAdj = this->getAdjByGateIndex(ISISIft.at(i).gateIndex, L1_TYPE);
06408                     //if there's not adjacency in state "UP" for specified interface, then skip this interface
06409                     if(tmpAdj == NULL || !tmpAdj->state){
06410                         continue;
06411                     }
06412                     //for broadcast network use DIS's System-ID
06413                     if (ISISIft.at(i).network)
06414                     {
06415                         this->copyArrayContent(ISISIft.at(i).L1DIS, neighbour.LANid, 7, 0, 0);
06416                     }
06417                     else
06418                         //for point-to-point links use actual System-ID padded with 0 byte
06419                     {
06420                         this->copyArrayContent(tmpAdj->sysID, neighbour.LANid, ISIS_SYSTEM_ID, 0, 0);
06421                         neighbour.LANid[ISIS_SYSTEM_ID] = 0;
06422                     }
06423 
06424                     //find interface which is DIS connected to and set metrics
06425                     neighbour.metrics.defaultMetric = ISISIft.at(i).metric;     //default = 10
06426                     neighbour.metrics.delayMetric = 128;    //disabled;
06427                     neighbour.metrics.expenseMetric = 128;  //disabled
06428                     neighbour.metrics.errortMetric = 128;   //disabled
06429 
06430                     neighbours.push_back(neighbour);
06431                 }
06432             }
06433 
06434             //replace old neighbours
06435             L1LSP.at(j).neighbours = neighbours;
06436 
06437 
06438             found = true;
06439             break;
06440         }
06441     }
06442 
06443     //if LSP record doesn't exist, create it
06444     if(!found)
06445     {
06446         LSPrecord record;
06447 
06448         //set LSP ID
06449         this->copyArrayContent(myLSPid, record.LSPid, 8, 0, 0);
06450 
06451         //set dead timer
06452         record.deadTimer = new ISISTimer("L1 LSP dead");
06453         record.deadTimer->setTimerKind(LSP_DEAD);
06454         for(unsigned int x = 0; x < record.deadTimer->getLSPidArraySize(); x++)
06455         {
06456             record.deadTimer->setLSPid(x, myLSPid[x]);
06457         }
06458         scheduleAt(simTime() + 50.0, record.deadTimer);//TODO
06459 
06460         //initial sequence number = 1
06461         record.seq = 1;
06462 
06463         //set pseudonode neighbours
06464         std::vector<LSPneighbour> neighbours;
06465 
06466         for(unsigned int i=0; i<ISISIft.size(); i++)
06467         {
06468             if(ISISIft.at(i).ISISenabled && (ISISIft.at(i).circuitType == L1_TYPE || ISISIft.at(i).circuitType == L1L2_TYPE))
06469             {
06470                 for(unsigned int f=0; f< this->adjL1Table.size(); f++)
06471                 {
06472                     if(ISISIft.at(i).gateIndex == adjL1Table.at(f).gateIndex && adjL1Table.at(f).state)
06473                     {
06474                         LSPneighbour neighbour;
06475                         if(ISISIft.at(i).network){
06476                             this->copyArrayContent(ISISIft.at(i).L1DIS, neighbour.LANid, 7, 0, 0);
06477                         }else{
06478                             this->copyArrayContent(this->adjL1Table.at(f).sysID, neighbour.LANid, ISIS_SYSTEM_ID, 0, 0);
06479                             neighbour.LANid[6]=0;
06480 
06481                         }
06482 
06483                         //find interface which is DIS connected to and set metrics
06484                         neighbour.metrics.defaultMetric = ISISIft.at(i).metric;     //default = 10
06485                         neighbour.metrics.delayMetric = 128;    //disabled;
06486                         neighbour.metrics.expenseMetric = 128;  //disabled
06487                         neighbour.metrics.errortMetric = 128;   //disabled
06488 
06489                         neighbours.push_back(neighbour);
06490                         break;
06491                     }
06492                 }
06493             }
06494         }
06495 
06496         if(neighbours.size() > 0)
06497         {
06498             record.neighbours = neighbours;
06499             L1LSP.push_back(record);
06500         }
06501      }
06502 
06503 
06504     //end of non-pseudonode LSP
06505     //####################################################################################################
06506     //start of pseudonode LSP
06507 
06508     for(unsigned int i=0; i<ISISIft.size(); i++)
06509     {
06510         //check if this interface is DIS for LAN AND if it is broadcast interface
06511         if(this->compareArrays((unsigned char*) this->sysId, ISISIft.at(i).L1DIS, 6) && ISISIft.at(i).network)
06512         {
06513             //check if LSP ID exists; update neighbours if record exists; create new record otherwise
06514             //I have already my system id contained in myLSPid; we have to set only pseudonode ID byte
06515 
06516             found = false;
06517             myLSPid[6] = ISISIft.at(i).L1DIS[6];
06518             for(unsigned int j=0; j< L1LSP.size(); j++)
06519             {
06520                 //we found the match
06521                 if(this->compareArrays(myLSPid, L1LSP.at(j).LSPid, 8))
06522                 {
06523 
06524                     //update sequence number
06525                     L1LSP.at(j).seq++;
06526 
06527                     //reset dead timer
06528                     cancelEvent(L1LSP.at(j).deadTimer);
06529                     scheduleAt(simTime() + 50, L1LSP.at(j).deadTimer);   //should be 1200 secs.
06530 
06531                     //set neighbours (NON-pseudonode neighbours)
06532                     std::vector<LSPneighbour> neighbours;
06533 
06534                     //set every adjacent IS as neighbour
06535                     for(unsigned int k=0; k<adjL1Table.size(); k++)
06536                     {
06537                         //consider only directly connected neighbours in "UP" state
06538                         if(adjL1Table.at(k).state && adjL1Table.at(k).gateIndex == ISISIft.at(i).gateIndex)
06539                         {
06540                             LSPneighbour neighbour;
06541                             this->copyArrayContent(adjL1Table.at(k).sysID, neighbour.LANid, 6, 0, 0);
06542                             neighbour.LANid[6] = 0;
06543                             neighbour.metrics.defaultMetric = 0;     //metric to every neighbour in pseudonode LSP is always zero!!!
06544                             neighbour.metrics.delayMetric = 128;    //disabled;
06545                             neighbour.metrics.expenseMetric = 128;  //disabled
06546                             neighbour.metrics.errortMetric = 128;   //disabled
06547 
06548                             neighbours.push_back(neighbour);
06549                         }
06550                     }
06551 
06552                     //add also mine non-pseudonode interface as neighbour
06553                     LSPneighbour neighbour;
06554                     this->copyArrayContent((unsigned char*)this->sysId, neighbour.LANid, 6, 0, 0);
06555                     neighbour.LANid[6] = 0;
06556                     neighbour.metrics.defaultMetric = 0;     //metric to every neighbour in pseudonode LSP is always zero!!!
06557                     neighbour.metrics.delayMetric = 128;    //disabled;
06558                     neighbour.metrics.expenseMetric = 128;  //disabled
06559                     neighbour.metrics.errortMetric = 128;   //disabled
06560 
06561                     neighbours.push_back(neighbour);
06562 
06563                     //replace old neighbours
06564                     L1LSP.at(j).neighbours = neighbours;
06565 
06566                     found = true;
06567                     break;
06568                 }
06569             }
06570 
06571 
06572             //create new pseudonode LSP record
06573             if(!found)
06574             {
06575                 LSPrecord record;
06576 
06577                 //set LSP ID
06578                 this->copyArrayContent(myLSPid, record.LSPid, 8, 0, 0);
06579 
06580                 //set dead timer
06581                 record.deadTimer = new ISISTimer("L1 LSP dead");
06582                 record.deadTimer->setTimerKind(LSP_DEAD);
06583                 for(unsigned int x=0; x<record.deadTimer->getLSPidArraySize(); x++)
06584                 {
06585                     record.deadTimer->setLSPid(x, myLSPid[x]);
06586                 }
06587                 scheduleAt(simTime() + 50.0, record.deadTimer);
06588 
06589                 //initial sequence number = 1
06590                 record.seq = 1;
06591 
06592                 //set neighbours (NON-pseudonode neighbours)
06593                 std::vector<LSPneighbour> neighbours;
06594 
06595 
06596                 //set every adjacent IS as neighbour
06597                 for(unsigned int k=0; k<adjL1Table.size(); k++)
06598                 {
06599                     //consider only directly connected neighbours in "UP" state
06600                     if(adjL1Table.at(k).state && adjL1Table.at(k).gateIndex == ISISIft.at(i).gateIndex)
06601                     {
06602                         LSPneighbour neighbour;
06603                         this->copyArrayContent(adjL1Table.at(k).sysID, neighbour.LANid, 6, 0, 0);
06604                         neighbour.LANid[6] = 0;
06605                         neighbour.metrics.defaultMetric = 0;     //metric to every neighbour in pseudonode LSP is always zero!!!
06606                         neighbour.metrics.delayMetric = 128;    //disabled;
06607                         neighbour.metrics.expenseMetric = 128;  //disabled
06608                         neighbour.metrics.errortMetric = 128;   //disabled
06609 
06610                         neighbours.push_back(neighbour);
06611                     }
06612                 }
06613 
06614                 if(neighbours.size() > 0)
06615                 {
06616                     //add also mine non-pseudonode interface as neighbour
06617                     LSPneighbour neighbour;
06618                     this->copyArrayContent((unsigned char*)this->sysId, neighbour.LANid, 6, 0, 0);
06619                     neighbour.LANid[6] = 0;
06620                     neighbour.metrics.defaultMetric = 0;     //metric to every neighbour in pseudonode LSP is always zero!!!
06621                     neighbour.metrics.delayMetric = 128;    //disabled;
06622                     neighbour.metrics.expenseMetric = 128;  //disabled
06623                     neighbour.metrics.errortMetric = 128;   //disabled
06624 
06625                     neighbours.push_back(neighbour);
06626 
06627                     record.neighbours = neighbours;
06628 
06629                     //replace old neighbours
06630                     L1LSP.push_back(record);
06631                 }
06632             }
06633         }
06634     }
06635 }
06636 
06641 void ISIS::floodFurtherL1LSP(ISISLSPL1Packet *msg)
06642 {
06643     //duplicate packet
06644 
06645     Ieee802Ctrl *ctrl = check_and_cast <Ieee802Ctrl *> (msg->getControlInfo());
06646 
06647 
06648     //resend unchanged message to all L1 IS-IS enabled interfaces except of that, which message came from
06649     for(unsigned int i=0; i<ISISIft.size(); i++)
06650     {
06651         if(!ISISIft.at(i).passive &&
06652             ISISIft.at(i).ISISenabled &&
06653            (ISISIft.at(i).circuitType == L1_TYPE || ISISIft.at(i).circuitType == L1L2_TYPE) &&
06654             ISISIft.at(i).gateIndex != msg->getArrivalGate()->getIndex())
06655         {
06656             //send it
06657             ISISLSPL1Packet *myMsg = msg->dup();
06658             Ieee802Ctrl *ctrlCopy = ctrl->dup();
06659             myMsg->setControlInfo(ctrlCopy);
06660 
06661             send(myMsg, "ifOut", ISISIft.at(i).gateIndex);
06662         }
06663     }
06664 
06665 }
06666 
06671 void ISIS::sendSpecificL1LSP(unsigned char *LSPid)
06672 {
06673     ISISLSPL1Packet *LSP = new ISISLSPL1Packet("L1 LSP");
06674     //add Ethernet controll info
06675     Ieee802Ctrl *ctrl = new Ieee802Ctrl();
06676 
06677     // set DSAP & NSAP fields
06678     ctrl->setDsap(SAP_CLNS);
06679     ctrl->setSsap(SAP_CLNS);
06680 
06681     //set destination broadcast address
06682     //It should be multicast 01-80-C2-00-00-14 MAC address, but it doesn't work in OMNeT
06683     MACAddress ma;
06684     ma.setAddress("ff:ff:ff:ff:ff:ff");
06685     ctrl->setDest(ma);
06686 
06687     //set LSP ID packet field
06688     for(unsigned int j=0; j<LSP->getLspIDArraySize(); j++)
06689     {
06690         LSP->setLspID(j, LSPid[j]);
06691     }
06692 
06693 
06694     //set area address TLV
06695     TLV_t myTLV;
06696     myTLV.type = AREA_ADDRESS;
06697     myTLV.length = 3;
06698     myTLV.value = new unsigned char[3];
06699     this->copyArrayContent((unsigned char*)this->areaId, myTLV.value, 3, 0, 0);
06700 
06701     LSP->setTLVArraySize(1);
06702     LSP->setTLV(0, myTLV);
06703 
06704     //find LSP
06705     bool found = false;
06706     unsigned int j;
06707     for(j=0; j<L1LSP.size(); j++)
06708     {
06709         if(this->compareArrays(LSPid, L1LSP.at(j).LSPid, 8))
06710         {
06711             found = true;
06712             break;
06713         }
06714     }
06715 
06716     if(found)
06717     {
06718 
06719         //set sequence number
06720         LSP->setSeqNumber(L1LSP.at(j).seq);
06721 
06722         //cout << "seq: " << LSP->getSeqNumber() << endl;
06723 
06724 
06725         //set neighbours TLV
06726         myTLV.type = IS_NEIGHBOURS_LSP;
06727         myTLV.length = 1 + L1LSP.at(j).neighbours.size()*11;
06728         myTLV.value = new unsigned char [myTLV.length];
06729         myTLV.value[0] = 0;                                     //reserved byte
06730 
06731         //set neighbours
06732         for(unsigned int k=0; k<L1LSP.at(j).neighbours.size(); k++)
06733         {
06734             myTLV.value[(k*11)+1] = L1LSP.at(j).neighbours.at(k).metrics.defaultMetric;
06735             myTLV.value[(k*11)+2] = L1LSP.at(j).neighbours.at(k).metrics.delayMetric;
06736             myTLV.value[(k*11)+3] = L1LSP.at(j).neighbours.at(k).metrics.expenseMetric;
06737             myTLV.value[(k*11)+4] = L1LSP.at(j).neighbours.at(k).metrics.errortMetric;
06738             this->copyArrayContent(L1LSP.at(j).neighbours.at(k).LANid, myTLV.value, 7, 0, (k*11)+5); //set LAN ID
06739         }
06740 
06741         LSP->setTLVArraySize(2);
06742         LSP->setTLV(1, myTLV);
06743 
06744         /* - TODO Auth TLV
06745            - eventually implement ES neighbours TLV, but I don't think it's necessary
06746            - next TLVs from RFC 1195 if IP should be supported
06747         */
06748 
06749         for(unsigned int a=0; a<ISISIft.size(); a++)
06750         {
06751             if(!ISISIft.at(a).passive && ISISIft.at(a).ISISenabled && (ISISIft.at(a).circuitType == L1_TYPE || ISISIft.at(a).circuitType == L1L2_TYPE))
06752             {
06753                 ISISLSPL1Packet *LSPcopy = LSP->dup();
06754                 Ieee802Ctrl *ctrlCopy = ctrl->dup();
06755                 LSPcopy->setControlInfo(ctrlCopy);
06756                 send(LSPcopy, "ifOut", ISISIft.at(a).gateIndex);
06757             }
06758         }
06759     }
06760     //cleanup
06761     delete LSP;
06762 }
06763 
06764 
06770 ISISadj* ISIS::getAdjByGateIndex(int gateIndex, short circuitType, int offset)
06771 {
06772 
06773     if (circuitType == L1_TYPE || circuitType == L1L2_TYPE)//L1L2_TYPE option is there for L1L2 PTP links, because for such links there should be adjacency in both tables
06774     {
06775         for (std::vector<ISISadj>::iterator it = this->adjL1Table.begin(); it != this->adjL1Table.end(); ++it)
06776         {
06777             if ((*it).gateIndex == gateIndex)
06778             {
06779                 if (offset == 0)
06780                 {
06781                     return &(*it);
06782                 }
06783                 else
06784                 {
06785                     offset--;
06786                 }
06787 
06788             }
06789         }
06790     }
06791     else if (circuitType == L2_TYPE)
06792     {
06793         for (std::vector<ISISadj>::iterator it = this->adjL2Table.begin(); it != this->adjL2Table.end(); ++it)
06794         {
06795             if (offset == 0)
06796             {
06797                 return &(*it);
06798             }
06799             else
06800             {
06801                 offset--;
06802             }
06803 
06804         }
06805     }
06806     return NULL;
06807 
06808 
06809 }
06810 
06816 ISISinterface* ISIS::getIfaceByGateIndex(int gateIndex)
06817 {
06818 
06819     for (std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it)
06820     {
06821 
06822         if ((*it).gateIndex == gateIndex)
06823         {
06824             return &(*it);
06825         }
06826     }
06827     return NULL;
06828 }
06829 
06830 
06834 unsigned short ISIS::getHoldTime(int interfaceIndex, short circuitType){
06835 
06836     int dis1, dis2;
06837     dis1 = dis2 = 1;
06838     ISISinterface tmpIntf = this->ISISIft.at(interfaceIndex);
06839     //TODO check whether this interface is DIS and if so, return only 1/3
06840     if (this->amIL1DIS(interfaceIndex))
06841     {
06842         dis1 = 3;
06843     }
06844 
06845     if (this->amIL2DIS(interfaceIndex))
06846     {
06847         dis2 = 3;
06848     }
06849 
06850     if (circuitType == L1_TYPE)
06851     {
06852         if (tmpIntf.L1HelloInterval == 0)
06853         {
06854             return 1;
06855         }
06856         else
06857         {
06858             return (tmpIntf.L1HelloMultiplier * tmpIntf.L1HelloInterval) / dis1;
06859         }
06860     }
06861     else if (circuitType == L2_TYPE)
06862     {
06863         if (tmpIntf.L2HelloInterval == 0)
06864         {
06865             return 1;
06866         }
06867         else
06868         {
06869             return (tmpIntf.L2HelloMultiplier * tmpIntf.L2HelloInterval) / dis2;
06870         }
06871 
06872     }
06873     else if (circuitType == L1L2_TYPE)
06874     {
06875         //return smaller of L1 and L2 hold timers
06876         return (this->getHoldTime(interfaceIndex, L1_TYPE) < this->getHoldTime(interfaceIndex, L2_TYPE) ? this->getHoldTime(
06877                 interfaceIndex, L1_TYPE) :
06878                 this->getHoldTime(interfaceIndex, L2_TYPE));
06879 
06880     }
06881     else
06882     {
06883         return 1;
06884         EV << "deviceId " << deviceId << ": Warning: Unrecognized circuitType used in ISIS::getHoldTime()\n";
06885     }
06886     return 1; //this is here just so OMNeT wouldn't bother me with "no return in non-void method" warning
06887 }
06888 
06889 /*
06890  * Returns Hello interval for interface and level.
06891  * If this IS is DIS on specified interface, returns only one third of the value.
06892  * @param interfaceIndex is index to ISISIft
06893  * @param circuitType is level
06894  * @return number of seconds.
06895  */
06896 double ISIS::getHelloInterval(int interfaceIndex, short circuitType)
06897 {
06898 
06899     //check if interface is DIS for specified circuitType (only on broadcast interfaces)
06900     //for DIS interface return one third of actual value
06901     int dis1, dis2;
06902     dis1 = dis2 = 1;
06903     ISISinterface tmpIntf = this->ISISIft.at(interfaceIndex);
06904     //TODO check whether this interface is DIS and if so, return only 1/3
06905     if (this->amIL1DIS(interfaceIndex))
06906     {
06907         dis1 = 3;
06908     }
06909 
06910     if (this->amIL2DIS(interfaceIndex))
06911     {
06912         dis2 = 3;
06913     }
06914 
06915     if (circuitType == L1_TYPE)
06916         {
06917             if (tmpIntf.L1HelloInterval == 0)
06918             {
06919                 return 1 / tmpIntf.L1HelloMultiplier;
06920             }
06921             else
06922             {
06923                 return (tmpIntf.L1HelloInterval) / dis1;
06924             }
06925         }
06926         else if (circuitType == L2_TYPE)
06927         {
06928             if (tmpIntf.L2HelloInterval == 0)
06929             {
06930                 return 1 / tmpIntf.L2HelloMultiplier;
06931             }
06932             else
06933             {
06934                 return (tmpIntf.L2HelloInterval) / dis2;
06935             }
06936 
06937         }
06938         else if (circuitType == L1L2_TYPE)
06939         {
06940             EV << "deviceId " << deviceId << ": Warning: Are you sure you want to know Hello interval for L1L2_TYPE ?!? in ISIS::getHelloInterval()\n";
06941             //return smaller of L1 and L2 hold timers
06942             return (this->getHelloInterval(interfaceIndex, L1_TYPE) < this->getHelloInterval(interfaceIndex, L2_TYPE) ? this->getHelloInterval(
06943                     interfaceIndex, L1_TYPE) :
06944                     this->getHelloInterval(interfaceIndex, L2_TYPE));
06945 
06946         }
06947         else
06948         {
06949             return 1;
06950             EV << "deviceId " << deviceId << ": Warning: Unrecognized circuitType used in ISIS::getHelloInterval()\n";
06951         }
06952 
06953 return 0.0;
06954 
06955 
06956 
06957 }
06958 /*
06959  * Determines if this IS is DIS on specified interface for L1
06960  * @param interfaceIndex is index to ISISIft
06961  * return true if this IS is DIS on specified interface for L1.
06962  */
06963 bool ISIS::amIL1DIS(int interfaceIndex)
06964 {
06965     //if this is not broadcast interface then no DIS is elected
06966     if (!this->ISISIft.at(interfaceIndex).network)
06967     {
06968         return false;
06969     }
06970 
06971     return (compareArrays((unsigned char *) this->sysId, this->ISISIft.at(interfaceIndex).L1DIS, ISIS_SYSTEM_ID));
06972 
06973 }
06974 
06975 /*
06976  * Determines if this IS is DIS on specified interface for L2
06977  * @param interfaceIndex is index to ISISIft
06978  * return true if this IS is DIS on specified interface for L2.
06979  */
06980 bool ISIS::amIL2DIS(int interfaceIndex)
06981 {
06982     //if this is not broadcast interface then no DIS is elected
06983     if (!this->ISISIft.at(interfaceIndex).network)
06984     {
06985         return false;
06986     }
06987 
06988     return (compareArrays((unsigned char *) this->sysId, this->ISISIft.at(interfaceIndex).L2DIS, ISIS_SYSTEM_ID));
06989 
06990 }
06991 
06992 /*
06993  * Returns pointer to TLV array in ISISMessage specified by tlvType.
06994  * @param inMsg message to be parsed
06995  * @param tlvType is type of TLV
06996  * @param offset is n-th found TLV
06997  * @return pointer to TLV array.
06998  */
06999 TLV_t* ISIS::getTLVByType(ISISMessage *inMsg, enum TLVtypes tlvType, int offset)
07000 {
07001 
07002     for (unsigned int i = 0; i < inMsg->getTLVArraySize(); i++)
07003     {
07004         if (inMsg->getTLV(i).type == tlvType)
07005         {
07006             if (offset == 0)
07007             {
07008                 return &(inMsg->getTLV(i));
07009             }
07010             else
07011             {
07012                 offset--;
07013             }
07014         }
07015     }
07016 
07017     return NULL;
07018 }
07019 /*
07020 
07021 
07022 TLV_t* ISIS::getTLVByType(ISISL1HelloPacket *msg, enum TLVtypes tlvType, int offset)
07023 {
07024 
07025     for(unsigned int i = 0; i < msg->getTLVArraySize(); i++){
07026         if(msg->getTLV(i).type == tlvType){
07027             if(offset == 0){
07028                 return &(msg->getTLV(i));
07029             }else{
07030                 offset--;
07031             }
07032         }
07033     }
07034 
07035     return NULL;
07036 }
07037 
07038 TLV_t* ISIS::getTLVByType(ISISL2HelloPacket *msg, enum TLVtypes tlvType, int offset)
07039 {
07040 
07041     for(unsigned int i = 0; i < msg->getTLVArraySize(); i++){
07042         if(msg->getTLV(i).type == tlvType){
07043             if(offset == 0){
07044                 return &(msg->getTLV(i));
07045             }else{
07046                 offset--;
07047             }
07048         }
07049     }
07050 
07051     return NULL;
07052 }
07053 
07054 TLV_t* ISIS::getTLVByType(ISISPTPHelloPacket *msg, enum TLVtypes tlvType, int offset)
07055 {
07056 
07057     for (unsigned int i = 0; i < msg->getTLVArraySize(); i++)
07058     {
07059         if (msg->getTLV(i).type == tlvType)
07060         {
07061             if (offset == 0)
07062             {
07063                 return &(msg->getTLV(i));
07064             }
07065             else
07066             {
07067                 offset--;
07068             }
07069         }
07070     }
07071 
07072     return NULL;
07073 }
07074 */
07075 /*
07076  * Checks if the incomming message is correct.
07077  * @pram inMsg is incomming message
07078  * @return true if message is OK.
07079  */
07080 bool ISIS::isMessageOK(ISISMessage *inMsg)
07081 {
07082 
07083     if (inMsg->getIdLength() != ISIS_SYSTEM_ID && inMsg->getIdLength() != 0)
07084     {
07085         return false;
07086     }
07087 
07088     if (inMsg->getMaxAreas() != ISIS_MAX_AREAS && inMsg->getMaxAreas() != 0)
07089     {
07090         return false;
07091     }
07092 
07093     return true;
07094 }
07095 
07096 /*
07097  * Compares Area-ID of this IS with Area-ID TLV.
07098  * @param areaAddressTLV is TLV with area address TLV.
07099  * @return true if at least one area-id match.
07100  */
07101 bool ISIS::isAreaIDOK(TLV_t *areaAddressTLV, unsigned char *compare)
07102 {
07103     if(compare == NULL){
07104         compare = (unsigned char *) this->areaId;
07105     }
07106 
07107     if(areaAddressTLV->length == 0){
07108         return false;
07109     }
07110     for(unsigned int i = 0; i < areaAddressTLV->length / ISIS_AREA_ID; i++){
07111         if(this->compareArrays(compare, &areaAddressTLV->value[i * ISIS_AREA_ID], ISIS_AREA_ID)){
07112             //if one address match return false
07113             return true;
07114         }
07115 
07116     }
07117     //not even single areaID match, so return false
07118     return false;
07119 }
07120 
07121 /*
07122  * Returns index to ISISIft for specified interface.
07123  * @param interface is pointer to interface
07124  * @return index to ISISIft vector
07125  */
07126 int ISIS::getIfaceIndex(ISISinterface *interface)
07127 {
07128 
07129     for (unsigned int i = 0; i < this->ISISIft.size(); i++)
07130     {
07131 
07132         if (interface == &(ISISIft.at(i)))
07133         {
07134             return i;
07135         }
07136     }
07137     return 0;
07138 }
07139 
07140 
07141 /*
07142  * Generates and adds specified TLV to the message.
07143  * @param inMsg message
07144  * @param tlvType is TLV type to be generated.
07145  */
07146 void ISIS::addTLV(ISISMessage *inMsg, enum TLVtypes tlvType)
07147 {
07148     unsigned int tlvSize;
07149     switch (tlvType)
07150     {
07151         case (AREA_ADDRESS):
07152             TLV_t myTLV;
07153             myTLV.type = AREA_ADDRESS;
07154             myTLV.length = ISIS_AREA_ID;
07155             myTLV.value = new unsigned char[ISIS_AREA_ID];
07156             this->copyArrayContent((unsigned char*) this->areaId, myTLV.value, 3, 0, 0);
07157 
07158             tlvSize = inMsg->getTLVArraySize();
07159             inMsg->setTLVArraySize(tlvSize + 1);
07160             inMsg->setTLV(tlvSize, myTLV);
07161             break;
07162 
07163         default:
07164             EV <<"ISIS: ERROR: This TLV type is not (yet) implemented in addTLV(ISISMessage*, enum TLVtypes)" << endl;
07165             break;
07166 
07167     }
07168 
07169 }
07170 
07171 /*
07172  * Copy already generated TLV to message and sets correct TLV array size.
07173  * @param inMsg message
07174  * @param tlv pointer to TLV to be added.
07175  */
07176 void ISIS::addTLV(ISISMessage* inMsg, TLV_t *tlv){
07177     TLV_t tmpTlv;
07178     unsigned int tlvSize;
07179 
07180     tmpTlv.type = tlv->type; // set type
07181     tmpTlv.length = tlv->length; //set length
07182     tmpTlv.value = new unsigned char [tlv->length]; //allocate appropriate space
07183     this->copyArrayContent(tlv->value, tmpTlv.value, tlv->length, 0, 0); //copy it
07184 
07185 
07186     tlvSize = inMsg->getTLVArraySize(); //get array size
07187     inMsg->setTLVArraySize(tlvSize + 1);// increase it by one
07188     inMsg->setTLV(tlvSize, tmpTlv); //finally add TLV at the end
07189 }
07190 
07191 /*
07192  * Generates and adds specified TLV type to the set of TLVs
07193  * @param tlvTable set of TLVs
07194  * @param tlvType TLV type to be generated
07195  * @param circuitType is level.
07196  */
07197 void ISIS::addTLV(std::vector<TLV_t *> *tlvTable, enum TLVtypes tlvType, short circuitType, unsigned char nsel)
07198 {
07199 
07200     TLV_t * myTLV;
07201 
07202 
07203     if (tlvType == AREA_ADDRESS)
07204     {
07205         myTLV = new TLV_t;
07206         myTLV->type = AREA_ADDRESS;
07207         myTLV->length = ISIS_AREA_ID;
07208         myTLV->value = new unsigned char[ISIS_AREA_ID];
07209         this->copyArrayContent((unsigned char*) this->areaId, myTLV->value, 3, 0, 0);
07210         tlvTable->push_back(myTLV);
07211 
07212     }
07213     else if (tlvType == IS_NEIGHBOURS_LSP)
07214     {
07215 
07216         if (nsel == 0)
07217         {
07218             std::vector<LSPneighbour> neighbours;
07219             ISISadj *tmpAdj;
07220             for (std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it)
07221             {
07222                 LSPneighbour neighbour;
07223                 tmpAdj = this->getAdjByGateIndex((*it).gateIndex, circuitType);
07224                 //if there's not adjacency in state "UP" for specified interface, then skip this interface
07225                 if (tmpAdj == NULL || !tmpAdj->state)
07226                 {
07227                     continue;
07228                 }
07229 
07230                 if ((*it).network)
07231                 {
07232                     //TODO how do you know it's L1DIS and not L2
07233                     this->copyArrayContent((*it).L1DIS, neighbour.LANid, ISIS_SYSTEM_ID + 1, 0, 0);
07234                 }
07235                 else
07236                 {
07237                     this->copyArrayContent(tmpAdj->sysID, neighbour.LANid, ISIS_SYSTEM_ID, 0, 0);
07238                     neighbour.LANid[ISIS_SYSTEM_ID] = 0;
07239                 }
07240 
07241                 //find interface which is DIS connected to and set metrics
07242                 neighbour.metrics.defaultMetric = (*it).metric; //default = 10
07243                 neighbour.metrics.delayMetric = 128; //disabled;
07244                 neighbour.metrics.expenseMetric = 128; //disabled
07245                 neighbour.metrics.errortMetric = 128; //disabled
07246 
07247                 neighbours.push_back(neighbour);
07248 
07249             }
07250             //we have vector of neighbours
07251 
07252             //now compute size needed in tlv
07253             // virtual link + ((metrics + System-ID + 1) * number_of_neighbours
07254 
07255 
07256             int entrySize = (4 + ISIS_SYSTEM_ID + 1);
07257             //run until there's any neighbour
07258             for (; !neighbours.empty();)
07259             {
07260                 myTLV = new TLV_t;
07261                 myTLV->type = IS_NEIGHBOURS_LSP;
07262                 myTLV->length = 1 + ((4 + ISIS_SYSTEM_ID + 1) * neighbours.size());
07263                 myTLV->value = new unsigned char[ISIS_LSP_MAX_SIZE];
07264 
07265                 //virtualFlag
07266                 myTLV->value[0] = 40;//TODO should be 0
07267                 //inner loop for separate TLV; after reaching ISIS_LSP_MAX_SIZE or empty neighbours stop filling this tlv
07268                 // 2 bytes for type and length fields and 1 byte for virtual circuit
07269                 for (unsigned int i = 0; ((i + 1) * entrySize) + 1 < 255 && 2 + 1 + (entrySize * i) + entrySize < ISIS_LSP_MAX_SIZE && !neighbours.empty();
07270                         i++)
07271                 {
07272                     myTLV->value[(i * 11) + 1] = neighbours.at(0).metrics.defaultMetric;
07273                     myTLV->value[(i * 11) + 2] = neighbours.at(0).metrics.delayMetric;
07274                     myTLV->value[(i * 11) + 3] = neighbours.at(0).metrics.expenseMetric;
07275                     myTLV->value[(i * 11) + 4] = neighbours.at(0).metrics.errortMetric;
07276                     this->copyArrayContent(neighbours.at(0).LANid, myTLV->value, ISIS_SYSTEM_ID + 1, 0, (i * 11) + 5); //set system ID
07277                     myTLV->length = 1 + ((4 + ISIS_SYSTEM_ID + 1) * (i + 1));
07278                     //delete first entry
07279                     neighbours.erase(neighbours.begin());
07280                 }
07281                 //this tlv is full or no other neighbour entry is present
07282                 tlvTable->push_back(myTLV);
07283                 //TODO do i need to create new myTLV and allocate value?
07284                 //myTLV = new TLV_t;
07285 
07286             }
07287             return;
07288         }
07289         else
07290         //pseudonode
07291         {
07292             std::vector<LSPneighbour> neighbours;
07293 
07294             ISISadj *tmpAdj;
07295             for (std::vector<ISISinterface>::iterator it = this->ISISIft.begin(); it != this->ISISIft.end(); ++it)
07296             {
07297 
07298                 for (int offset = 0; (tmpAdj = this->getAdjByGateIndex((*it).gateIndex, circuitType, offset)) != NULL;
07299                         offset++)
07300                 {
07301                     LSPneighbour neighbour;
07302                     if (!tmpAdj->state)
07303                     {
07304                         continue;
07305                     }
07306 
07307                     this->copyArrayContent(tmpAdj->sysID, neighbour.LANid, ISIS_SYSTEM_ID, 0, 0);
07308                     neighbour.LANid[ISIS_SYSTEM_ID] = 0;
07309 
07310                     neighbour.metrics.defaultMetric = 0; //metric from DIS is 0
07311                     neighbour.metrics.delayMetric = 128; //disabled;
07312                     neighbour.metrics.expenseMetric = 128; //disabled
07313                     neighbour.metrics.errortMetric = 128; //disabled
07314 
07315                     neighbours.push_back(neighbour);
07316                 }
07317             }
07318             //add also mine non-pseudonode interface as neighbour
07319                         LSPneighbour neighbour;
07320                         this->copyArrayContent((unsigned char*) this->sysId, neighbour.LANid, ISIS_SYSTEM_ID, 0, 0);
07321                         neighbour.LANid[ISIS_SYSTEM_ID] = 0;
07322                         neighbour.metrics.defaultMetric = 0;  //metric to every neighbour in pseudonode LSP is always zero!!!
07323                         neighbour.metrics.delayMetric = 128; //disabled;
07324                         neighbour.metrics.expenseMetric = 128; //disabled
07325                         neighbour.metrics.errortMetric = 128; //disabled
07326 
07327                         neighbours.push_back(neighbour);
07328 
07329             //we have vector neighbours for pseudo
07330 
07331             int entrySize = (4 + ISIS_SYSTEM_ID + 1);
07332             //run until there's any neighbour
07333             for (; !neighbours.empty();)
07334             {
07335                 myTLV = new TLV_t;
07336                 myTLV->type = IS_NEIGHBOURS_LSP;
07337                 myTLV->length = 1 + ((4 + ISIS_SYSTEM_ID + 1) * neighbours.size());
07338                 myTLV->value = new unsigned char[ISIS_LSP_MAX_SIZE];
07339 
07340                 //virtualFlag
07341                 myTLV->value[0] = 40; //TODO should be 0
07342                 //inner loop for separate TLV; after reaching ISIS_LSP_MAX_SIZE or empty neighbours stop filling this tlv
07343                 // 2 bytes for type and length fields and 1 byte for virtual circuit
07344                 for (unsigned int i = 0;
07345                         ((i + 1) * entrySize) + 1 < 255 && 2 + 1 + (entrySize * i) + entrySize < ISIS_LSP_MAX_SIZE
07346                                 && !neighbours.empty(); i++)
07347                 {
07348                     myTLV->value[(i * 11) + 1] = neighbours.at(0).metrics.defaultMetric;
07349                     myTLV->value[(i * 11) + 2] = neighbours.at(0).metrics.delayMetric;
07350                     myTLV->value[(i * 11) + 3] = neighbours.at(0).metrics.expenseMetric;
07351                     myTLV->value[(i * 11) + 4] = neighbours.at(0).metrics.errortMetric;
07352                     this->copyArrayContent(neighbours.at(0).LANid, myTLV->value, ISIS_SYSTEM_ID + 1, 0, (i * 11) + 5); //set system ID
07353                     myTLV->length = 1 + ((4 + ISIS_SYSTEM_ID + 1) * (i + 1));
07354                     //delete first entry
07355                     neighbours.erase(neighbours.begin());
07356                 }
07357                 //this tlv is full or no other neighbour entry is present
07358                 tlvTable->push_back(myTLV);
07359                 //TODO do i need to create new myTLV and allocate value?
07360                 //myTLV = new TLV_t;
07361 
07362             }
07363         }
07364 
07365 
07366 
07367 
07368 
07369         //end of TLV IS_NEIGHBOURS_LSP
07370     }
07371     else
07372     {
07373         EV << "ISIS: ERROR: This TLV type is not (yet) implemented in addTLV" << endl;
07374     }
07375 }
07376 
07377 /*
07378  * Returns true if this System have ANY adjacency UP on level specified by circuitType
07379  * @param circuitType is level.
07380  */
07381 bool ISIS::isAdjUp(short circuitType)
07382 {
07383     std::vector<ISISadj>* adjTable = this->getAdjTab(circuitType);
07384 
07385     for (std::vector<ISISadj>::iterator it = adjTable->begin(); it != adjTable->end(); ++it)
07386     {
07387         if ((*it).state)
07388         {
07389             return true;
07390         }
07391     }
07392     return false;
07393 }
07394 
07395 /*
07396  * This method returns true if there is ANY adjacency on interface identified by gateIndex in state UP
07397  * Method does NOT check SNPA (aka MAC).
07398  * Can be used to check if we should send LSP on such interface.
07399  * @param gateIndex is gate index
07400  * @param circuitType is level
07401  */
07402 bool ISIS::isUp(int gateIndex, short circuitType)
07403 {
07404     std::vector<ISISadj> *adjTable;
07405 
07406     adjTable = this->getAdjTab(circuitType);
07407     for (std::vector<ISISadj>::iterator it = adjTable->begin(); it != adjTable->end(); ++it)
07408     {
07409         if ((*it).gateIndex == gateIndex && (*it).state)
07410         {
07411             return true;
07412         }
07413     }
07414     return false;
07415 
07416 }
07417 
07418 /*
07419  * Verify if adjacency for specified message is in state UP.
07420  * @param msg incomming message
07421  * @param circuitType is level.
07422  */
07423 bool ISIS::isAdjUp(ISISMessage *msg, short circuitType)
07424 {
07425     /* Pretty messy code, please clean up */
07426     std::vector<ISISadj> *adjTable = this->getAdjTab(circuitType);
07427     int gateIndex = msg->getArrivalGate()->getIndex();
07428 
07429     //TODO for truly point-to-point link there would not be MAC address
07430     Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->getControlInfo());
07431     MACAddress tmpMac = ctrl->getSrc();
07432     unsigned char * systemID;
07433 
07434     systemID = this->getSysID(msg);
07435     for (std::vector<ISISadj>::iterator it = adjTable->begin(); it != adjTable->end(); ++it)
07436     {
07437         //System-ID match?
07438         /* Exception for LSP is here because to satisfy  7.3.15.1 a) 6) is enough to check SNPA and interface e.g gateIndex */
07439         if (compareArrays(systemID, (*it).sysID, ISIS_SYSTEM_ID) || msg->getType() == L1_LSP || msg->getType() == L2_LSP)
07440         {
07441             //MAC Address and gateIndex
07442             //we need to check source (tmpMac) and destination interface thru we received this hello
07443             if (tmpMac.compareTo((*it).mac) == 0 && gateIndex == (*it).gateIndex && (*it).state)
07444             {
07445 
07446                 delete systemID;
07447                 return true;
07448 
07449             }
07450         }
07451     }
07452     delete systemID;
07453 
07454     return false;
07455 }
07456 
07457 /*
07458  * Performs full run of SPF algorithm.
07459  * @param timer is initiating timer.
07460  */
07461 void ISIS::fullSPF(ISISTimer *timer){
07462 
07463     ISISCons_t initial;
07464     ISISPaths_t ISISPaths;
07465     ISISPaths_t ISISTent;
07466     ISISPath * tmpPath;
07467 
07468     //let's fill up the initial paths with supported-protocol's reachability informations
07469 
07470     //fill ISO
07471     bool result;
07472     result = this->extractISO(&initial, timer->getIsType());
07473     if(!result){
07474         //there was an error during extraction so cancel SPF
07475         //todo reschedule
07476         this->schedule(timer);
07477         //TODO clean
07478         return;
07479     }
07480 
07481     //put myself (this IS) on TENT list
07482     unsigned char *lspId = this->getLSPID();//returns sysId + 00
07483 
07484 
07485     tmpPath = new ISISPath;
07486     tmpPath->to = new unsigned char[ISIS_SYSTEM_ID + 2];
07487     this->copyArrayContent(lspId, tmpPath->to, ISIS_SYSTEM_ID + 2, 0, 0);
07488 
07489     tmpPath->metric = 0;
07490 
07491     ISISNeighbour *neighbour = new ISISNeighbour;
07492     neighbour->id = new unsigned char[ISIS_SYSTEM_ID + 2];
07493     this->copyArrayContent(lspId, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07494     neighbour->type = false; //not a leaf
07495     tmpPath->from.push_back(neighbour);
07496 
07497     ISISTent.push_back(tmpPath);
07498 
07499 
07500 //    ISISCons_t *cons = this->getCons(&initial, lspId);
07501 //    if(cons->empty()){
07502 //        EV <<"ISIS: Error during SPF. Didn't find my own LSP"<<endl;
07503 //        //TODO clean
07504 //        delete cons;
07505 //        return;
07506 //    }
07507 //
07508 
07509 
07510     //add my connections as a starting point
07511   /*  for(ISISCons_t::iterator it = cons->begin(); it != cons->end(); ++it){
07512         if ((tmpPath = this->getPath(&(ISISTent), (*it)->to)) == NULL)
07513         {
07514             //path to this destination doesn't exist, co create new
07515             tmpPath = new ISISPath;
07516             tmpPath->to = new unsigned char[ISIS_SYSTEM_ID + 2];
07517             this->copyArrayContent((*it)->to, tmpPath->to, ISIS_SYSTEM_ID + 2, 0, 0);
07518             tmpPath->metric = (*it)->metric;
07519 
07520             ISISNeighbour *neighbour = new ISISNeighbour;
07521             neighbour->id = new unsigned char[ISIS_SYSTEM_ID + 2];
07522             this->copyArrayContent((*it)->from, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07523             neighbour->type = false; //not a leaf
07524             tmpPath->from.push_back(neighbour);
07525 
07526             ISISTent.push_back(tmpPath);
07527         }
07528         else
07529         {
07530             if(tmpPath->metric >= (*it)->metric){
07531                 if(tmpPath->metric > (*it)->metric){
07532                     //we got better metric so clear "from" neighbours
07533                     tmpPath->from.clear();
07534                 }
07535                 //append
07536                 tmpPath->metric = (*it)->metric;
07537                 ISISNeighbour *neighbour = new ISISNeighbour;
07538                 neighbour->id = new unsigned char[ISIS_SYSTEM_ID + 2];
07539                 this->copyArrayContent((*it)->from, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07540                 neighbour->type = false; //not a leaf
07541                 tmpPath->from.push_back(neighbour);
07542 
07543             }
07544 
07545         }
07546 
07547     }*/
07548 
07549     //TODO shoudn't i put myself in PATH list?
07550 
07551     for(;!ISISTent.empty();)
07552     {
07553         //tmpPath = this->getBestPath(&(this->ISISTent));
07554 
07555         //this->moveToPath(tmpPath);
07556         this->bestToPath(&initial, &ISISTent, &ISISPaths);
07557 
07558     }
07559 
07560     this->printPaths(&ISISPaths);
07561 
07562     //find shortest metric in TENT
07563 
07564 
07565     this->schedule(timer);
07566 }
07567 /*
07568  * Print best paths informations to stdout
07569  * @param paths is set of best paths.
07570  */
07571 void ISIS::printPaths(ISISPaths_t *paths){
07572 
07573 
07574         std::cout << "Best paths of IS: ";
07575         //print area id
07576             for (unsigned int i = 0; i < 3; i++)
07577             {
07578                 std::cout << setfill('0') << setw(2) << dec << (unsigned int) this->areaId[i];
07579                 if (i % 2 == 0)
07580                     std::cout << ".";
07581 
07582             }
07583 
07584             //print system id
07585             for (unsigned int i = 0; i < 6; i++)
07586             {
07587                 std::cout << setfill('0') << setw(2) << dec << (unsigned int) this->sysId[i];
07588                 if (i % 2 == 1)
07589                     std::cout << ".";
07590             }
07591 
07592             //print NSEL
07593             std::cout
07594                     << setfill('0') << setw(2) << dec << (unsigned int) this->NSEL[0] << "\tNo. of paths: "
07595                             << paths->size() << endl;
07596     for(ISISPaths_t::iterator it = paths->begin(); it != paths->end(); ++it){
07597         this->printSysId((*it)->to);
07598         std::cout << setfill('0') << setw(2) << dec <<(unsigned short)(*it)->to[6]<< endl;;
07599         std::cout <<"\t\t metric: "<< (*it)->metric <<"\t via:"<<endl;;
07600         for(ISISNeighbours_t::iterator nIt = (*it)->from.begin(); nIt != (*it)->from.end(); ++nIt){
07601             std::cout<<"\t\t\t\t\t";
07602             this->printSysId((*nIt)->id);
07603             std::cout  << setfill('0') << setw(2) << dec <<(unsigned short)(*nIt)->id[6]<< endl;;
07604         }
07605     }
07606 }
07607 
07608 /*
07609  * Moves best path from ISISTent to ISISPaths and initiate move of appropirate connections from init to ISISTent
07610  * @param initial is set of connections
07611  * @param ISISTent is set of tentative paths
07612  * @param ISISPaths is set of best paths from this IS
07613  */
07614 void ISIS::bestToPath(ISISCons_t *init, ISISPaths_t *ISISTent, ISISPaths_t *ISISPaths){
07615 
07616     ISISPath *path;
07617     ISISPath *tmpPath;
07618     //sort it
07619     std::sort(ISISTent->begin(), ISISTent->end());
07620     //save best in path
07621     path = ISISTent->front();
07622     //mov
07623     this->moveToTent(init, path->to, path->metric, ISISTent);
07624 
07625     ISISTent->erase(ISISTent->begin());
07626 
07627     if ((tmpPath = this->getPath(ISISPaths, path->to)) == NULL)
07628     {
07629         //path to this destination doesn't exist, so simply push
07630 
07631         ISISPaths->push_back(path);
07632     }
07633     else
07634     {
07635         if (tmpPath->metric >= path->metric)
07636         {
07637             if (tmpPath->metric > path->metric)
07638             {
07639                 EV <<"ISIS: Error during SPF. We got better metric than the one PATHS."<<endl;
07640                 //we got better metric so clear "from" neighbours
07641                 tmpPath->from.clear();
07642             }
07643             EV <<"ISIS: Error during SPF. I think we shouldn't have neither same metric."<<endl;
07644             //append
07645             tmpPath->metric = path->metric;
07646             for(ISISNeighbours_t::iterator it = path->from.begin(); it != path->from.end(); ++it){
07647                 tmpPath->from.push_back((*it));
07648             }
07649 
07650         }
07651     }
07652 
07653 }
07654 
07655 /* Moves connections with matching "from" from init to Tent
07656  * @param initial is set of connections
07657  * @param from specify which connections to move
07658  * @param metric is metric to get to "from" node
07659  * @param ISISTent is set of tentative paths
07660  */
07661 void ISIS::moveToTent(ISISCons_t *initial, unsigned char *from, uint32_t metric, ISISPaths_t *ISISTent){
07662 
07663     ISISPath *tmpPath;
07664     ISISCons_t *cons = this->getCons(initial, from);
07665 /*       if(cons->empty()){
07666            EV <<"ISIS: Error during SPF. Didn't find my own LSP"<<endl;
07667            //TODO clean
07668 //           delete cons;
07669   //         return;
07670        }*/
07671 
07672 
07673        //add my connections as a starting point
07674        for(ISISCons_t::iterator it = cons->begin(); it != cons->end(); ++it){
07675            if ((tmpPath = this->getPath(ISISTent, (*it)->to)) == NULL)
07676            {
07677                //path to this destination doesn't exist, co create new
07678                tmpPath = new ISISPath;
07679                tmpPath->to = new unsigned char[ISIS_SYSTEM_ID + 2];
07680                this->copyArrayContent((*it)->to, tmpPath->to, ISIS_SYSTEM_ID + 2, 0, 0);
07681                tmpPath->metric = (*it)->metric + metric;
07682 
07683                ISISNeighbour *neighbour = new ISISNeighbour;
07684 
07685                neighbour->id = new unsigned char[ISIS_SYSTEM_ID + 2];
07686                if(this->compareArrays((*it)->from,(unsigned char *) this->sysId, ISIS_SYSTEM_ID)){
07687                    this->copyArrayContent((*it)->to, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07688                }else{
07689                    this->copyArrayContent((*it)->from, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07690                }
07691                neighbour->type = false; //not a leaf
07692                tmpPath->from.push_back(neighbour);
07693 
07694                ISISTent->push_back(tmpPath);
07695            }
07696            else
07697            {
07698                if(tmpPath->metric >= (*it)->metric + metric){
07699                    if(tmpPath->metric > (*it)->metric + metric){
07700                        //we got better metric so clear "from" neighbours
07701                        tmpPath->from.clear();
07702                    }
07703                    //append
07704                    tmpPath->metric = (*it)->metric + metric;
07705                    ISISNeighbour *neighbour = new ISISNeighbour;
07706                    neighbour->id = new unsigned char[ISIS_SYSTEM_ID + 2];
07707                    this->copyArrayContent((*it)->from, neighbour->id, ISIS_SYSTEM_ID + 2, 0, 0);
07708                    neighbour->type = false; //not a leaf
07709                    tmpPath->from.push_back(neighbour);
07710 
07711                }
07712 
07713            }
07714 
07715        }
07716 }
07717 
07718 
07719 /*
07720  * Returns pointer to besh path in provided vector.
07721  * @param paths is vector of paths
07722  * @return pointer to path with best metric
07723  */
07724 ISISPath * ISIS::getBestPath(ISISPaths_t *paths){
07725 
07726     std::sort(paths->begin(), paths->end());
07727     return paths->front();
07728 
07729 }
07730 
07731 
07732 void ISIS::getBestMetric(ISISPaths_t *paths){
07733 
07734     for(ISISPaths_t::iterator it = paths->begin(); it != paths->end(); ++it){
07735 
07736     }
07737 }
07738 
07739 
07740 /*
07741  * This methods extract ISO information from LSP database.
07742  */
07743 bool ISIS::extractISO(ISISCons_t *initial, short circuitType){
07744 
07745     ISISLspDb_t *lspDb = this->getLSPDb(circuitType);
07746     unsigned char *lspId;
07747 
07748     ISISCon* connection;
07749 
07750     for(ISISLspDb_t::iterator it = lspDb->begin(); it != lspDb->end(); ++it){
07751         //getLspId
07752         lspId = this->getLspID((*it)->LSP);
07753 
07754         //check if it's zero-th fragment. if not try to find it -> getLspFromDbByID
07755 
07756         if(lspId[ISIS_SYSTEM_ID + 1] != 0){
07757             unsigned char backup = lspId[ISIS_SYSTEM_ID + 1];
07758             lspId[ISIS_SYSTEM_ID + 1] = 0;
07759             //if doesn't exist -> continue to next lsp
07760             if(this->getLSPFromDbByID(lspId, circuitType) == NULL){
07761                 continue;
07762             }
07763             lspId[ISIS_SYSTEM_ID + 1] = backup;
07764 
07765         }
07766         //else
07767         else{
07768             TLV_t *tmpTLV;
07769             for(int offset = 0; (tmpTLV = this->getTLVByType((*it)->LSP, IS_NEIGHBOURS_LSP, offset)) != NULL; offset++){
07770                 for(unsigned int i = 1; i + 11 <= tmpTLV->length; i += 11)
07771                 {
07772                     connection = new ISISCon;
07773                     connection->from = new unsigned char [ISIS_SYSTEM_ID + 2];
07774                     this->copyArrayContent(lspId, connection->from, ISIS_SYSTEM_ID + 1, 0, 0);
07775                     connection->from[ISIS_SYSTEM_ID + 1] = 0;
07776                     connection->to = new unsigned char [ISIS_SYSTEM_ID + 2];
07777                     this->copyArrayContent(tmpTLV->value, connection->to, ISIS_SYSTEM_ID +1, i + 4, 0);
07778                     connection->to[ISIS_SYSTEM_ID + 1] = 0;
07779                     connection->metric = tmpTLV->value[i];//default metric
07780                     connection->type = false;//it's not a leaf
07781 
07782                     initial->push_back(connection);
07783                     //path->neighbours.push_back(neighbour);
07784                 }
07785 
07786 
07787             }
07788 
07789         }
07790     }
07791 
07792     this->twoWayCheck(initial);
07793 
07794     return true;
07795 }
07796 
07797 /*
07798  * This methods performs two-way check of reported connections.
07799  * @param cons is vector of connections.
07800  */
07801 void ISIS::twoWayCheck(ISISCons_t *cons){
07802     ISISCons_t *tmpCons;
07803     for(ISISCons_t::iterator it = cons->begin(); it != cons->end(); ){
07804         //if there is not reverse connection
07805         //TODO is this enough? there could be two one-way connections between two ISs
07806         if(!this->isCon(cons, (*it)->to, (*it)->from)){
07807             it = cons->erase(it);
07808         }else{
07809             ++it;
07810         }
07811     }
07812 }
07813 
07814 /*
07815  * @return vector of connections with matching from in @param cons.
07816  */
07817 ISISCons_t * ISIS::getCons(ISISCons_t *cons, unsigned char *from){
07818 
07819     ISISCons_t *retCon = new ISISCons_t;
07820     for(ISISCons_t::iterator it = cons->begin(); it != cons->end(); ){
07821         if(this->compareArrays((*it)->from, from, 8)){
07822             retCon->push_back((*it));
07823             it = cons->erase(it);
07824         }else{
07825             ++it;
07826         }
07827     }
07828 
07829     return retCon;
07830 }
07831 /*
07832  * Check if connection from @param from to @param to exists.
07833  * @return true if there is connection with matching field from and to
07834  *
07835  */
07836 bool ISIS::isCon(ISISCons_t *cons, unsigned char *from, unsigned char *to){
07837 
07838     for (ISISCons_t::iterator it = cons->begin(); it != cons->end(); ++it)
07839     {
07840         if(this->compareArrays((*it)->from, from, ISIS_SYSTEM_ID + 2) && this->compareArrays((*it)->to, to, ISIS_SYSTEM_ID + 2)){
07841             return true;
07842         }
07843     }
07844     return false;
07845 }
07846 
07847 /*
07848  * Returns path with specified id.
07849  * @param paths vector of paths
07850  * @param id is identificator of desired path
07851  * @return path
07852  */
07853 ISISPath * ISIS::getPath(ISISPaths_t *paths, unsigned char *id){
07854 
07855     for(ISISPaths_t::iterator it = paths->begin(); it != paths->end(); ++it){
07856         if(this->compareArrays((*it)->to, id, 8)){
07857             return (*it);
07858         }
07859     }
07860 
07861     return NULL;
07862 }
07863