|
INET Framework for OMNeT++/OMNEST
|
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