|
INET Framework for OMNeT++/OMNEST
|
00001 #include "AnsaOSPFRouter.h" 00002 #include "RoutingTableAccess.h" 00003 00008 AnsaOSPF::Router::Router(AnsaOSPF::RouterID id, cSimpleModule* containingModule) : 00009 routerID(id), 00010 rfc1583Compatibility(false) 00011 { 00012 messageHandler = new AnsaOSPF::MessageHandler(this, containingModule); 00013 ageTimer = new OSPFTimer; 00014 ageTimer->setTimerKind(DatabaseAgeTimer); 00015 ageTimer->setContextPointer(this); 00016 ageTimer->setName("AnsaOSPF::Router::DatabaseAgeTimer"); 00017 messageHandler->StartTimer(ageTimer, 1.0); 00018 00019 } 00020 00021 00026 AnsaOSPF::Router::~Router(void) 00027 { 00028 long areaCount = areas.size(); 00029 for (long i = 0; i < areaCount; i++) { 00030 delete areas[i]; 00031 } 00032 long lsaCount = asExternalLSAs.size(); 00033 for (long j = 0; j < lsaCount; j++) { 00034 delete asExternalLSAs[j]; 00035 } 00036 long routeCount = routingTable.size(); 00037 for (long k = 0; k < routeCount; k++) { 00038 delete routingTable[k]; 00039 } 00040 messageHandler->ClearTimer(ageTimer); 00041 delete ageTimer; 00042 delete messageHandler; 00043 } 00044 00045 00049 void AnsaOSPF::Router::AddWatches(void) 00050 { 00051 WATCH(routerID); 00052 WATCH_PTRVECTOR(areas); 00053 WATCH_PTRVECTOR(asExternalLSAs); 00054 } 00055 00056 00061 void AnsaOSPF::Router::AddArea(AnsaOSPF::Area* area) 00062 { 00063 00064 area->SetRouter(this); 00065 areasByID[area->GetAreaID()] = area; 00066 areas.push_back(area); 00067 } 00068 00069 00075 AnsaOSPF::Area* AnsaOSPF::Router::GetArea(AnsaOSPF::AreaID areaID) 00076 { 00077 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00078 if (areaIt != areasByID.end()) { 00079 return (areaIt->second); 00080 } 00081 else { 00082 return NULL; 00083 } 00084 } 00085 00086 00092 AnsaOSPF::Area* AnsaOSPF::Router::GetArea(AnsaOSPF::IPv4Address address) 00093 { 00094 long areaCount = areas.size(); 00095 for (long i = 0; i < areaCount; i++) { 00096 if (areas[i]->ContainsAddress(address)) { 00097 return areas[i]; 00098 } 00099 } 00100 return NULL; 00101 } 00102 00103 00109 AnsaOSPF::Interface* AnsaOSPF::Router::GetNonVirtualInterface(unsigned char ifIndex) 00110 { 00111 long areaCount = areas.size(); 00112 for (long i = 0; i < areaCount; i++) { 00113 AnsaOSPF::Interface* intf = areas[i]->GetInterface(ifIndex); 00114 if (intf != NULL) { 00115 return intf; 00116 } 00117 } 00118 return NULL; 00119 } 00120 00121 00130 bool AnsaOSPF::Router::InstallLSA(OSPFLSA* lsa, AnsaOSPF::AreaID areaID /*= BackboneAreaID*/) 00131 { 00132 switch (lsa->getHeader().getLsType()) { 00133 case RouterLSAType: 00134 { 00135 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00136 if (areaIt != areasByID.end()) { 00137 OSPFRouterLSA* ospfRouterLSA = check_and_cast<OSPFRouterLSA*> (lsa); 00138 return areaIt->second->InstallRouterLSA(ospfRouterLSA); 00139 } 00140 } 00141 break; 00142 case NetworkLSAType: 00143 { 00144 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00145 if (areaIt != areasByID.end()) { 00146 OSPFNetworkLSA* ospfNetworkLSA = check_and_cast<OSPFNetworkLSA*> (lsa); 00147 return areaIt->second->InstallNetworkLSA(ospfNetworkLSA); 00148 } 00149 } 00150 break; 00151 case SummaryLSA_NetworksType: 00152 case SummaryLSA_ASBoundaryRoutersType: 00153 { 00154 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00155 if (areaIt != areasByID.end()) { 00156 OSPFSummaryLSA* ospfSummaryLSA = check_and_cast<OSPFSummaryLSA*> (lsa); 00157 return areaIt->second->InstallSummaryLSA(ospfSummaryLSA); 00158 } 00159 } 00160 break; 00161 case ASExternalLSAType: 00162 { 00163 OSPFASExternalLSA* ospfASExternalLSA = check_and_cast<OSPFASExternalLSA*> (lsa); 00164 return InstallASExternalLSA(ospfASExternalLSA); 00165 } 00166 break; 00167 default: 00168 ASSERT(false); 00169 break; 00170 } 00171 return false; 00172 } 00173 00174 00182 bool AnsaOSPF::Router::InstallASExternalLSA(OSPFASExternalLSA* lsa) 00183 { 00201 // TODO: how to solve this problem? 00202 00203 AnsaOSPF::RouterID advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt(); 00204 bool reachable = false; 00205 unsigned int routeCount = routingTable.size(); 00206 00207 for (unsigned int i = 0; i < routeCount; i++) { 00208 if ((((routingTable[i]->GetDestinationType() & AnsaOSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) || 00209 ((routingTable[i]->GetDestinationType() & AnsaOSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) && 00210 (routingTable[i]->GetDestinationID().getInt() == advertisingRouter)) 00211 { 00212 reachable = true; 00213 break; 00214 } 00215 } 00216 00217 bool ownLSAFloodedOut = false; 00218 AnsaOSPF::LSAKeyType lsaKey; 00219 00220 lsaKey.linkStateID = lsa->getHeader().getLinkStateID(); 00221 lsaKey.advertisingRouter = routerID; 00222 00223 std::map<AnsaOSPF::LSAKeyType, AnsaOSPF::ASExternalLSA*, AnsaOSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey); 00224 if ((lsaIt != asExternalLSAsByID.end()) && 00225 reachable && 00226 (lsaIt->second->getContents().getE_ExternalMetricType() == lsa->getContents().getE_ExternalMetricType()) && 00227 (lsaIt->second->getContents().getRouteCost() == lsa->getContents().getRouteCost()) && 00228 (lsa->getContents().getForwardingAddress().getInt() != 0) && // forwarding address != 0.0.0.0 00229 (lsaIt->second->getContents().getForwardingAddress() == lsa->getContents().getForwardingAddress())) 00230 { 00231 if (routerID > advertisingRouter) { 00232 return false; 00233 } else { 00234 lsaIt->second->getHeader().setLsAge(MAX_AGE); 00235 FloodLSA(lsaIt->second, AnsaOSPF::BackboneAreaID); 00236 lsaIt->second->IncrementInstallTime(); 00237 ownLSAFloodedOut = true; 00238 } 00239 } 00240 00241 lsaKey.advertisingRouter = advertisingRouter; 00242 00243 lsaIt = asExternalLSAsByID.find(lsaKey); 00244 if (lsaIt != asExternalLSAsByID.end()) { 00245 unsigned long areaCount = areas.size(); 00246 for (unsigned long i = 0; i < areaCount; i++) { 00247 areas[i]->RemoveFromAllRetransmissionLists(lsaKey); 00248 } 00249 return ((lsaIt->second->Update(lsa)) | ownLSAFloodedOut); 00250 } else { 00251 AnsaOSPF::ASExternalLSA* lsaCopy = new AnsaOSPF::ASExternalLSA(*lsa); 00252 asExternalLSAsByID[lsaKey] = lsaCopy; 00253 asExternalLSAs.push_back(lsaCopy); 00254 return true; 00255 } 00256 } 00257 00258 00267 OSPFLSA* AnsaOSPF::Router::FindLSA(LSAType lsaType, AnsaOSPF::LSAKeyType lsaKey, AnsaOSPF::AreaID areaID) 00268 { 00269 switch (lsaType) { 00270 case RouterLSAType: 00271 { 00272 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00273 if (areaIt != areasByID.end()) { 00274 return areaIt->second->FindRouterLSA(lsaKey.linkStateID); 00275 } 00276 } 00277 break; 00278 case NetworkLSAType: 00279 { 00280 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00281 if (areaIt != areasByID.end()) { 00282 return areaIt->second->FindNetworkLSA(lsaKey.linkStateID); 00283 } 00284 } 00285 break; 00286 case SummaryLSA_NetworksType: 00287 case SummaryLSA_ASBoundaryRoutersType: 00288 { 00289 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00290 if (areaIt != areasByID.end()) { 00291 return areaIt->second->FindSummaryLSA(lsaKey); 00292 } 00293 } 00294 break; 00295 case ASExternalLSAType: 00296 { 00297 return FindASExternalLSA(lsaKey); 00298 } 00299 break; 00300 default: 00301 ASSERT(false); 00302 break; 00303 } 00304 return NULL; 00305 } 00306 00307 00313 AnsaOSPF::ASExternalLSA* AnsaOSPF::Router::FindASExternalLSA(AnsaOSPF::LSAKeyType lsaKey) 00314 { 00315 std::map<AnsaOSPF::LSAKeyType, AnsaOSPF::ASExternalLSA*, AnsaOSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey); 00316 if (lsaIt != asExternalLSAsByID.end()) { 00317 return lsaIt->second; 00318 } else { 00319 return NULL; 00320 } 00321 } 00322 00323 00329 const AnsaOSPF::ASExternalLSA* AnsaOSPF::Router::FindASExternalLSA(AnsaOSPF::LSAKeyType lsaKey) const 00330 { 00331 std::map<AnsaOSPF::LSAKeyType, AnsaOSPF::ASExternalLSA*, AnsaOSPF::LSAKeyType_Less>::const_iterator lsaIt = asExternalLSAsByID.find(lsaKey); 00332 if (lsaIt != asExternalLSAsByID.end()) { 00333 return lsaIt->second; 00334 } else { 00335 return NULL; 00336 } 00337 } 00338 00339 00345 void AnsaOSPF::Router::AgeDatabase(void) 00346 { 00347 long lsaCount = asExternalLSAs.size(); 00348 bool rebuildRoutingTable = false; 00349 00350 for (long i = 0; i < lsaCount; i++) { 00351 unsigned short lsAge = asExternalLSAs[i]->getHeader().getLsAge(); 00352 bool selfOriginated = (asExternalLSAs[i]->getHeader().getAdvertisingRouter().getInt() == routerID); 00353 bool unreachable = IsDestinationUnreachable(asExternalLSAs[i]); 00354 AnsaOSPF::ASExternalLSA* lsa = asExternalLSAs[i]; 00355 00356 if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) { 00357 lsa->getHeader().setLsAge(lsAge + 1); 00358 if ((lsAge + 1) % CHECK_AGE == 0) { 00359 if (!lsa->ValidateLSChecksum()) { 00360 EV << "Invalid LS checksum. Memory error detected!\n"; 00361 } 00362 } 00363 lsa->IncrementInstallTime(); 00364 } 00365 if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) { 00366 if (unreachable) { 00367 lsa->getHeader().setLsAge(MAX_AGE); 00368 FloodLSA(lsa, AnsaOSPF::BackboneAreaID); 00369 lsa->IncrementInstallTime(); 00370 } else { 00371 long sequenceNumber = lsa->getHeader().getLsSequenceNumber(); 00372 if (sequenceNumber == MAX_SEQUENCE_NUMBER) { 00373 lsa->getHeader().setLsAge(MAX_AGE); 00374 FloodLSA(lsa, AnsaOSPF::BackboneAreaID); 00375 lsa->IncrementInstallTime(); 00376 } else { 00377 AnsaOSPF::ASExternalLSA* newLSA = OriginateASExternalLSA(lsa); 00378 00379 newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1); 00380 newLSA->getHeader().setLsChecksum(0); // TODO: calculate correct LS checksum 00381 rebuildRoutingTable |= lsa->Update(newLSA); 00382 delete newLSA; 00383 00384 FloodLSA(lsa, AnsaOSPF::BackboneAreaID); 00385 } 00386 } 00387 } 00388 if (!selfOriginated && (lsAge == MAX_AGE - 1)) { 00389 lsa->getHeader().setLsAge(MAX_AGE); 00390 FloodLSA(lsa, AnsaOSPF::BackboneAreaID); 00391 lsa->IncrementInstallTime(); 00392 } 00393 if (lsAge == MAX_AGE) { 00394 AnsaOSPF::LSAKeyType lsaKey; 00395 00396 lsaKey.linkStateID = lsa->getHeader().getLinkStateID(); 00397 lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt(); 00398 00399 if (!IsOnAnyRetransmissionList(lsaKey) && 00400 !HasAnyNeighborInStates(AnsaOSPF::Neighbor::ExchangeState | AnsaOSPF::Neighbor::LoadingState)) 00401 { 00402 if (!selfOriginated || unreachable) { 00403 asExternalLSAsByID.erase(lsaKey); 00404 delete lsa; 00405 asExternalLSAs[i] = NULL; 00406 rebuildRoutingTable = true; 00407 } else { 00408 if (lsa->GetPurgeable()) { 00409 asExternalLSAsByID.erase(lsaKey); 00410 delete lsa; 00411 asExternalLSAs[i] = NULL; 00412 rebuildRoutingTable = true; 00413 } else { 00414 AnsaOSPF::ASExternalLSA* newLSA = OriginateASExternalLSA(lsa); 00415 long sequenceNumber = lsa->getHeader().getLsSequenceNumber(); 00416 00417 newLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1); 00418 newLSA->getHeader().setLsChecksum(0); // TODO: calculate correct LS checksum 00419 rebuildRoutingTable |= lsa->Update(newLSA); 00420 delete newLSA; 00421 00422 FloodLSA(lsa, AnsaOSPF::BackboneAreaID); 00423 } 00424 } 00425 } 00426 } 00427 } 00428 00429 std::vector<ASExternalLSA*>::iterator it = asExternalLSAs.begin(); 00430 while (it != asExternalLSAs.end()) { 00431 if ((*it) == NULL) { 00432 it = asExternalLSAs.erase(it); 00433 } else { 00434 it++; 00435 } 00436 } 00437 00438 long areaCount = areas.size(); 00439 for (long j = 0; j < areaCount; j++) { 00440 areas[j]->AgeDatabase(); 00441 } 00442 messageHandler->StartTimer(ageTimer, 1.0); 00443 00444 if (rebuildRoutingTable) { 00445 RebuildRoutingTable(); 00446 } 00447 } 00448 00449 00455 bool AnsaOSPF::Router::HasAnyNeighborInStates(int states) const 00456 { 00457 long areaCount = areas.size(); 00458 for (long i = 0; i < areaCount; i++) { 00459 if (areas[i]->HasAnyNeighborInStates(states)) { 00460 return true; 00461 } 00462 } 00463 return false; 00464 } 00465 00466 00472 void AnsaOSPF::Router::RemoveFromAllRetransmissionLists(AnsaOSPF::LSAKeyType lsaKey) 00473 { 00474 long areaCount = areas.size(); 00475 for (long i = 0; i < areaCount; i++) { 00476 areas[i]->RemoveFromAllRetransmissionLists(lsaKey); 00477 } 00478 } 00479 00480 00486 bool AnsaOSPF::Router::IsOnAnyRetransmissionList(AnsaOSPF::LSAKeyType lsaKey) const 00487 { 00488 long areaCount = areas.size(); 00489 for (long i = 0; i < areaCount; i++) { 00490 if (areas[i]->IsOnAnyRetransmissionList(lsaKey)) { 00491 return true; 00492 } 00493 } 00494 return false; 00495 } 00496 00497 00507 bool AnsaOSPF::Router::FloodLSA(OSPFLSA* lsa, AnsaOSPF::AreaID areaID /*= BackboneAreaID*/, AnsaOSPF::Interface* intf /*= NULL*/, AnsaOSPF::Neighbor* neighbor /*= NULL*/) 00508 { 00509 bool floodedBackOut = false; 00510 00511 if (lsa != NULL) { 00512 if (lsa->getHeader().getLsType() == ASExternalLSAType) { 00513 long areaCount = areas.size(); 00514 for (long i = 0; i < areaCount; i++) { 00515 if (areas[i]->GetExternalRoutingCapability()) { 00516 if (areas[i]->FloodLSA(lsa, intf, neighbor)) { 00517 floodedBackOut = true; 00518 } 00519 } 00520 } 00521 } else { 00522 std::map<AnsaOSPF::AreaID, AnsaOSPF::Area*>::iterator areaIt = areasByID.find(areaID); 00523 if (areaIt != areasByID.end()) { 00524 floodedBackOut = areaIt->second->FloodLSA(lsa, intf, neighbor); 00525 } 00526 } 00527 } 00528 00529 return floodedBackOut; 00530 } 00531 00532 00538 bool AnsaOSPF::Router::IsLocalAddress(AnsaOSPF::IPv4Address address) const 00539 { 00540 long areaCount = areas.size(); 00541 for (long i = 0; i < areaCount; i++) { 00542 if (areas[i]->IsLocalAddress(address)) { 00543 return true; 00544 } 00545 } 00546 return false; 00547 } 00548 00549 00555 bool AnsaOSPF::Router::HasAddressRange(AnsaOSPF::IPv4AddressRange addressRange) const 00556 { 00557 long areaCount = areas.size(); 00558 for (long i = 0; i < areaCount; i++) { 00559 if (areas[i]->HasAddressRange(addressRange)) { 00560 return true; 00561 } 00562 } 00563 return false; 00564 } 00565 00566 00572 AnsaOSPF::ASExternalLSA* AnsaOSPF::Router::OriginateASExternalLSA(AnsaOSPF::ASExternalLSA* lsa) 00573 { 00574 AnsaOSPF::ASExternalLSA* asExternalLSA = new AnsaOSPF::ASExternalLSA(*lsa); 00575 OSPFLSAHeader& lsaHeader = asExternalLSA->getHeader(); 00576 OSPFOptions lsaOptions; 00577 00578 lsaHeader.setLsAge(0); 00579 memset(&lsaOptions, 0, sizeof(OSPFOptions)); 00580 lsaOptions.E_ExternalRoutingCapability = true; 00581 lsaHeader.setLsOptions(lsaOptions); 00582 lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER); 00583 asExternalLSA->SetSource(AnsaOSPF::LSATrackingInfo::Originated); 00584 00585 return asExternalLSA; 00586 } 00587 00588 00593 bool AnsaOSPF::Router::IsDestinationUnreachable(OSPFLSA* lsa) const 00594 { 00595 IPAddress destination = lsa->getHeader().getLinkStateID(); 00596 00597 OSPFRouterLSA* routerLSA = dynamic_cast<OSPFRouterLSA*> (lsa); 00598 OSPFNetworkLSA* networkLSA = dynamic_cast<OSPFNetworkLSA*> (lsa); 00599 OSPFSummaryLSA* summaryLSA = dynamic_cast<OSPFSummaryLSA*> (lsa); 00600 OSPFASExternalLSA* asExternalLSA = dynamic_cast<OSPFASExternalLSA*> (lsa); 00601 // TODO: verify 00602 if (routerLSA != NULL) { 00603 AnsaOSPF::RoutingInfo* routingInfo = check_and_cast<AnsaOSPF::RoutingInfo*> (routerLSA); 00604 if (routerLSA->getHeader().getLinkStateID() == routerID) { // this is spfTreeRoot 00605 return false; 00606 } 00607 00608 // get the interface address pointing backwards on the shortest path tree 00609 unsigned int linkCount = routerLSA->getLinksArraySize(); 00610 AnsaOSPF::RouterLSA* toRouterLSA = dynamic_cast<AnsaOSPF::RouterLSA*> (routingInfo->GetParent()); 00611 if (toRouterLSA != NULL) { 00612 bool destinationFound = false; 00613 bool unnumberedPointToPointLink = false; 00614 IPAddress firstNumberedIfAddress; 00615 00616 for (unsigned int i = 0; i < linkCount; i++) { 00617 Link& link = routerLSA->getLinks(i); 00618 00619 if (link.getType() == PointToPointLink) { 00620 if (link.getLinkID() == toRouterLSA->getHeader().getLinkStateID()) { 00621 if ((link.getLinkData() & 0xFF000000) == 0) { 00622 unnumberedPointToPointLink = true; 00623 if (!firstNumberedIfAddress.isUnspecified()) { 00624 break; 00625 } 00626 } else { 00627 destination = link.getLinkData(); 00628 destinationFound = true; 00629 break; 00630 } 00631 } else { 00632 if (((link.getLinkData() & 0xFF000000) != 0) && 00633 firstNumberedIfAddress.isUnspecified()) 00634 { 00635 firstNumberedIfAddress = link.getLinkData(); 00636 } 00637 } 00638 } else if (link.getType() == TransitLink) { 00639 if (firstNumberedIfAddress.isUnspecified()) { 00640 firstNumberedIfAddress = link.getLinkData(); 00641 } 00642 } else if (link.getType() == VirtualLink) { 00643 if (link.getLinkID() == toRouterLSA->getHeader().getLinkStateID()) { 00644 destination = link.getLinkData(); 00645 destinationFound = true; 00646 break; 00647 } else { 00648 if (firstNumberedIfAddress.isUnspecified()) { 00649 firstNumberedIfAddress = link.getLinkData(); 00650 } 00651 } 00652 } 00653 // There's no way to get an interface address for the router from a StubLink 00654 } 00655 if (unnumberedPointToPointLink) { 00656 if (!firstNumberedIfAddress.isUnspecified()) { 00657 destination = firstNumberedIfAddress; 00658 } else { 00659 return true; 00660 } 00661 } 00662 if (!destinationFound) { 00663 return true; 00664 } 00665 } else { 00666 AnsaOSPF::NetworkLSA* toNetworkLSA = dynamic_cast<AnsaOSPF::NetworkLSA*> (routingInfo->GetParent()); 00667 if (toNetworkLSA != NULL) { 00668 // get the interface address pointing backwards on the shortest path tree 00669 bool destinationFound = false; 00670 for (unsigned int i = 0; i < linkCount; i++) { 00671 Link& link = routerLSA->getLinks(i); 00672 00673 if ((link.getType() == TransitLink) && 00674 (link.getLinkID() == toNetworkLSA->getHeader().getLinkStateID())) 00675 { 00676 destination = link.getLinkData(); 00677 destinationFound = true; 00678 break; 00679 } 00680 } 00681 if (!destinationFound) { 00682 return true; 00683 } 00684 } else { 00685 return true; 00686 } 00687 } 00688 } 00689 if (networkLSA != NULL) { 00690 destination = networkLSA->getHeader().getLinkStateID() & networkLSA->getNetworkMask().getInt(); 00691 } 00692 if ((summaryLSA != NULL) && (summaryLSA->getHeader().getLsType() == SummaryLSA_NetworksType)) { 00693 destination = summaryLSA->getHeader().getLinkStateID() & summaryLSA->getNetworkMask().getInt(); 00694 } 00695 if (asExternalLSA != NULL) { 00696 destination = asExternalLSA->getHeader().getLinkStateID() & asExternalLSA->getContents().getNetworkMask().getInt(); 00697 } 00698 00699 if (Lookup(destination) == NULL) { 00700 return true; 00701 } else { 00702 return false; 00703 } 00704 } 00705 00706 00714 AnsaOSPF::RoutingTableEntry* AnsaOSPF::Router::Lookup(IPAddress destination, std::vector<AnsaOSPF::RoutingTableEntry*>* table /*= NULL*/) const 00715 { 00716 const std::vector<AnsaOSPF::RoutingTableEntry*>& rTable = (table == NULL) ? routingTable : (*table); 00717 unsigned long dest = destination.getInt(); 00718 unsigned long routingTableSize = rTable.size(); 00719 bool unreachable = false; 00720 std::vector<AnsaOSPF::RoutingTableEntry*> discard; 00721 unsigned long i; 00722 00723 unsigned long areaCount = areas.size(); 00724 for (i = 0; i < areaCount; i++) { 00725 unsigned int addressRangeCount = areas[i]->GetAddressRangeCount(); 00726 for (unsigned int j = 0; j < addressRangeCount; j++) { 00727 AnsaOSPF::IPv4AddressRange range = areas[i]->GetAddressRange(j); 00728 00729 for (unsigned int k = 0; k < routingTableSize; k++) { 00730 AnsaOSPF::RoutingTableEntry* entry = rTable[k]; 00731 00732 if (entry->GetDestinationType() != AnsaOSPF::RoutingTableEntry::NetworkDestination) { 00733 continue; 00734 } 00735 if (((entry->GetDestinationID().getInt() & entry->GetAddressMask().getInt() & ULongFromIPv4Address(range.mask)) == ULongFromIPv4Address(range.address & range.mask)) && 00736 (entry->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea)) 00737 { 00738 // active area address range 00739 AnsaOSPF::RoutingTableEntry* discardEntry = new AnsaOSPF::RoutingTableEntry; 00740 discardEntry->SetDestinationID(ULongFromIPv4Address(range.address)); 00741 discardEntry->SetAddressMask(ULongFromIPv4Address(range.mask)); 00742 discardEntry->SetDestinationType(AnsaOSPF::RoutingTableEntry::NetworkDestination); 00743 discardEntry->SetPathType(AnsaOSPF::RoutingTableEntry::InterArea); 00744 discardEntry->SetArea(areas[i]->GetAreaID()); 00745 discard.push_back(discardEntry); 00746 break; 00747 } 00748 } 00749 } 00750 } 00751 00752 AnsaOSPF::RoutingTableEntry* bestMatch = NULL; 00753 unsigned long longestMatch = 0; 00754 00755 for (i = 0; i < routingTableSize; i++) { 00756 if (rTable[i]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) { 00757 AnsaOSPF::RoutingTableEntry* entry = rTable[i]; 00758 unsigned long entryAddress = entry->GetDestinationID().getInt(); 00759 unsigned long entryMask = entry->GetAddressMask().getInt(); 00760 00761 if ((entryAddress & entryMask) == (dest & entryMask)) { 00762 if ((dest & entryMask) > longestMatch) { 00763 longestMatch = (dest & entryMask); 00764 bestMatch = entry; 00765 } 00766 } 00767 } 00768 } 00769 00770 unsigned int discardCount = discard.size(); 00771 if (bestMatch == NULL) { 00772 unreachable = true; 00773 } else { 00774 for (i = 0; i < discardCount; i++) { 00775 AnsaOSPF::RoutingTableEntry* entry = discard[i]; 00776 unsigned long entryAddress = entry->GetDestinationID().getInt(); 00777 unsigned long entryMask = entry->GetAddressMask().getInt(); 00778 00779 if ((entryAddress & entryMask) == (dest & entryMask)) { 00780 if ((dest & entryMask) > longestMatch) { 00781 unreachable = true; 00782 break; 00783 } 00784 } 00785 } 00786 } 00787 00788 for (i = 0; i < discardCount; i++) { 00789 delete discard[i]; 00790 } 00791 00792 if (unreachable) { 00793 return NULL; 00794 } else { 00795 return bestMatch; 00796 } 00797 } 00798 00799 00804 void AnsaOSPF::Router::RebuildRoutingTable(void) 00805 { 00806 unsigned long areaCount = areas.size(); 00807 bool hasTransitAreas = false; 00808 std::vector<AnsaOSPF::RoutingTableEntry*> newTable; 00809 unsigned long i; 00810 00811 EV << "Rebuilding routing table:\n"; 00812 00813 for (i = 0; i < areaCount; i++) { 00814 areas[i]->CalculateShortestPathTree(newTable); 00815 if (areas[i]->GetTransitCapability()) { 00816 hasTransitAreas = true; 00817 } 00818 } 00819 if (areaCount > 1) { 00820 AnsaOSPF::Area* backbone = GetArea(AnsaOSPF::BackboneAreaID); 00821 if (backbone != NULL) { 00822 backbone->CalculateInterAreaRoutes(newTable); 00823 } 00824 } else { 00825 if (areaCount == 1) { 00826 areas[0]->CalculateInterAreaRoutes(newTable); 00827 } 00828 } 00829 if (hasTransitAreas) { 00830 for (i = 0; i < areaCount; i++) { 00831 if (areas[i]->GetTransitCapability()) { 00832 areas[i]->ReCheckSummaryLSAs(newTable); 00833 } 00834 } 00835 } 00836 CalculateASExternalRoutes(newTable); 00837 00838 // backup the routing table 00839 unsigned long routeCount = routingTable.size(); 00840 std::vector<AnsaOSPF::RoutingTableEntry*> oldTable; 00841 00842 oldTable.assign(routingTable.begin(), routingTable.end()); 00843 routingTable.clear(); 00844 routingTable.assign(newTable.begin(), newTable.end()); 00845 00846 RoutingTableAccess routingTableAccess; 00847 std::vector<const IPRoute*> eraseEntries; 00848 IRoutingTable* simRoutingTable = routingTableAccess.get(); 00849 unsigned long routingEntryNumber = simRoutingTable->getNumRoutes(); 00850 // remove entries from the IP routing table inserted by the OSPF module 00851 for (i = 0; i < routingEntryNumber; i++) { 00852 const IPRoute *entry = simRoutingTable->getRoute(i); 00853 const AnsaOSPF::RoutingTableEntry* ospfEntry = dynamic_cast<const AnsaOSPF::RoutingTableEntry*>(entry); 00854 if (ospfEntry != NULL) { 00855 eraseEntries.push_back(entry); 00856 } 00857 } 00858 00859 unsigned int eraseCount = eraseEntries.size(); 00860 for (i = 0; i < eraseCount; i++) { 00861 simRoutingTable->deleteRoute(eraseEntries[i]); 00862 } 00863 00864 // add the new routing entries 00865 routeCount = routingTable.size(); 00866 for (i = 0; i < routeCount; i++) { 00867 if (routingTable[i]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) { 00868 simRoutingTable->addRoute(new AnsaOSPF::RoutingTableEntry(*(routingTable[i]))); 00869 } 00870 } 00871 00872 NotifyAboutRoutingTableChanges(oldTable); 00873 00874 routeCount = oldTable.size(); 00875 for (i = 0; i < routeCount; i++) { 00876 delete(oldTable[i]); 00877 } 00878 00879 EV << "Routing table was rebuilt.\n" 00880 << "Results:\n"; 00881 00882 routeCount = routingTable.size(); 00883 for (i = 0; i < routeCount; i++) { 00884 EV << *routingTable[i] 00885 << "\n"; 00886 } 00887 } 00888 00889 00896 bool AnsaOSPF::Router::HasRouteToASBoundaryRouter(const std::vector<AnsaOSPF::RoutingTableEntry*>& inRoutingTable, AnsaOSPF::RouterID asbrRouterID) const 00897 { 00898 long routeCount = inRoutingTable.size(); 00899 for (long i = 0; i < routeCount; i++) { 00900 AnsaOSPF::RoutingTableEntry* routingEntry = inRoutingTable[i]; 00901 if (((routingEntry->GetDestinationType() & AnsaOSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) && 00902 (routingEntry->GetDestinationID().getInt() == asbrRouterID)) 00903 { 00904 return true; 00905 } 00906 } 00907 return false; 00908 } 00909 00910 00918 std::vector<AnsaOSPF::RoutingTableEntry*> AnsaOSPF::Router::GetRoutesToASBoundaryRouter(const std::vector<AnsaOSPF::RoutingTableEntry*>& fromRoutingTable, AnsaOSPF::RouterID asbrRouterID) const 00919 { 00920 std::vector<AnsaOSPF::RoutingTableEntry*> results; 00921 long routeCount = fromRoutingTable.size(); 00922 00923 for (long i = 0; i < routeCount; i++) { 00924 AnsaOSPF::RoutingTableEntry* routingEntry = fromRoutingTable[i]; 00925 if (((routingEntry->GetDestinationType() & AnsaOSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) && 00926 (routingEntry->GetDestinationID().getInt() == asbrRouterID)) 00927 { 00928 results.push_back(routingEntry); 00929 } 00930 } 00931 return results; 00932 } 00933 00934 00941 void AnsaOSPF::Router::PruneASBoundaryRouterEntries(std::vector<AnsaOSPF::RoutingTableEntry*>& asbrEntries) const 00942 { 00943 bool hasNonBackboneIntraAreaPath = false; 00944 for (std::vector<AnsaOSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin(); it != asbrEntries.end(); it++) { 00945 AnsaOSPF::RoutingTableEntry* routingEntry = *it; 00946 if ((routingEntry->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) && 00947 (routingEntry->GetArea() != AnsaOSPF::BackboneAreaID)) 00948 { 00949 hasNonBackboneIntraAreaPath = true; 00950 break; 00951 } 00952 } 00953 00954 if (hasNonBackboneIntraAreaPath) { 00955 std::vector<AnsaOSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin(); 00956 while (it != asbrEntries.end()) { 00957 if (((*it)->GetPathType() != AnsaOSPF::RoutingTableEntry::IntraArea) || 00958 ((*it)->GetArea() == AnsaOSPF::BackboneAreaID)) 00959 { 00960 it = asbrEntries.erase(it); 00961 } else { 00962 it++; 00963 } 00964 } 00965 } 00966 } 00967 00968 00975 AnsaOSPF::RoutingTableEntry* AnsaOSPF::Router::SelectLeastCostRoutingEntry(std::vector<AnsaOSPF::RoutingTableEntry*>& entries) const 00976 { 00977 if (entries.empty()) { 00978 return NULL; 00979 } 00980 00981 AnsaOSPF::RoutingTableEntry* leastCostEntry = entries[0]; 00982 Metric leastCost = leastCostEntry->GetCost(); 00983 long routeCount = entries.size(); 00984 00985 for (long i = 1; i < routeCount; i++) { 00986 Metric currentCost = entries[i]->GetCost(); 00987 if ((currentCost < leastCost) || 00988 ((currentCost == leastCost) && (entries[i]->GetArea() > leastCostEntry->GetArea()))) 00989 { 00990 leastCostEntry = entries[i]; 00991 leastCost = currentCost; 00992 } 00993 } 00994 00995 return leastCostEntry; 00996 } 00997 00998 01017 AnsaOSPF::RoutingTableEntry* AnsaOSPF::Router::GetPreferredEntry(const OSPFLSA& lsa, bool skipSelfOriginated, std::vector<AnsaOSPF::RoutingTableEntry*>* fromRoutingTable /*= NULL*/) 01018 { 01019 if (fromRoutingTable == NULL) { 01020 fromRoutingTable = &routingTable; 01021 } 01022 01023 const OSPFLSAHeader& lsaHeader = lsa.getHeader(); 01024 const OSPFASExternalLSA* asExternalLSA = dynamic_cast<const OSPFASExternalLSA*> (&lsa); 01025 unsigned long externalCost = (asExternalLSA != NULL) ? asExternalLSA->getContents().getRouteCost() : 0; 01026 unsigned short lsAge = lsaHeader.getLsAge(); 01027 AnsaOSPF::RouterID originatingRouter = lsaHeader.getAdvertisingRouter().getInt(); 01028 bool selfOriginated = (originatingRouter == routerID); 01029 IPAddress forwardingAddress; // 0.0.0.0 01030 01031 if (asExternalLSA != NULL) { 01032 forwardingAddress = asExternalLSA->getContents().getForwardingAddress(); 01033 } 01034 01035 if ((externalCost == LS_INFINITY) || (lsAge == MAX_AGE) || (skipSelfOriginated && selfOriginated)) { // (1) and(2) 01036 return NULL; 01037 } 01038 01039 if (!HasRouteToASBoundaryRouter(*fromRoutingTable, originatingRouter)) { // (3) 01040 return NULL; 01041 } 01042 01043 if (forwardingAddress.isUnspecified()) { // (3) 01044 std::vector<AnsaOSPF::RoutingTableEntry*> asbrEntries = GetRoutesToASBoundaryRouter(*fromRoutingTable, originatingRouter); 01045 if (!rfc1583Compatibility) { 01046 PruneASBoundaryRouterEntries(asbrEntries); 01047 } 01048 return SelectLeastCostRoutingEntry(asbrEntries); 01049 } else { 01050 AnsaOSPF::RoutingTableEntry* forwardEntry = Lookup(forwardingAddress, fromRoutingTable); 01051 01052 if (forwardEntry == NULL) { 01053 return NULL; 01054 } 01055 01056 if ((forwardEntry->GetPathType() != AnsaOSPF::RoutingTableEntry::IntraArea) && 01057 (forwardEntry->GetPathType() != AnsaOSPF::RoutingTableEntry::InterArea)) 01058 { 01059 return NULL; 01060 } 01061 01062 return forwardEntry; 01063 } 01064 01065 return NULL; 01066 } 01067 01068 01076 void AnsaOSPF::Router::CalculateASExternalRoutes(std::vector<AnsaOSPF::RoutingTableEntry*>& newRoutingTable) 01077 { 01078 unsigned long lsaCount = asExternalLSAs.size(); 01079 unsigned long i; 01080 01081 for (i = 0; i < lsaCount; i++) { 01082 AnsaOSPF::ASExternalLSA* currentLSA = asExternalLSAs[i]; 01083 OSPFLSAHeader& currentHeader = currentLSA->getHeader(); 01084 unsigned short externalCost = currentLSA->getContents().getRouteCost(); 01085 AnsaOSPF::RouterID originatingRouter = currentHeader.getAdvertisingRouter().getInt(); 01086 01087 AnsaOSPF::RoutingTableEntry* preferredEntry = GetPreferredEntry(*currentLSA, true, &newRoutingTable); 01088 if (preferredEntry == NULL) { 01089 continue; 01090 } 01091 01092 IPAddress destination = currentHeader.getLinkStateID() & currentLSA->getContents().getNetworkMask().getInt(); 01093 01094 Metric preferredCost = preferredEntry->GetCost(); 01095 AnsaOSPF::RoutingTableEntry* destinationEntry = Lookup(destination, &newRoutingTable); // (5) 01096 if (destinationEntry == NULL) { 01097 bool type2ExternalMetric = currentLSA->getContents().getE_ExternalMetricType(); 01098 unsigned int nextHopCount = preferredEntry->GetNextHopCount(); 01099 AnsaOSPF::RoutingTableEntry* newEntry = new AnsaOSPF::RoutingTableEntry; 01100 01101 newEntry->SetDestinationID(destination); 01102 newEntry->SetAddressMask(currentLSA->getContents().getNetworkMask().getInt()); 01103 newEntry->SetArea(preferredEntry->GetArea()); 01104 newEntry->SetPathType(type2ExternalMetric ? AnsaOSPF::RoutingTableEntry::Type2External : AnsaOSPF::RoutingTableEntry::Type1External); 01105 if (type2ExternalMetric) { 01106 newEntry->SetCost(preferredCost); 01107 newEntry->SetType2Cost(externalCost); 01108 } else { 01109 newEntry->SetCost(preferredCost + externalCost); 01110 } 01111 newEntry->SetDestinationType(AnsaOSPF::RoutingTableEntry::NetworkDestination); 01112 newEntry->SetOptionalCapabilities(currentHeader.getLsOptions()); 01113 newEntry->SetLinkStateOrigin(currentLSA); 01114 01115 for (unsigned int j = 0; j < nextHopCount; j++) { 01116 NextHop nextHop = preferredEntry->GetNextHop(j); 01117 01118 nextHop.advertisingRouter = originatingRouter; 01119 newEntry->AddNextHop(nextHop); 01120 } 01121 01122 newRoutingTable.push_back(newEntry); 01123 } else { 01124 AnsaOSPF::RoutingTableEntry::RoutingPathType destinationPathType = destinationEntry->GetPathType(); 01125 bool type2ExternalMetric = currentLSA->getContents().getE_ExternalMetricType(); 01126 unsigned int nextHopCount = preferredEntry->GetNextHopCount(); 01127 01128 if ((destinationPathType == AnsaOSPF::RoutingTableEntry::IntraArea) || 01129 (destinationPathType == AnsaOSPF::RoutingTableEntry::InterArea)) // (6) (a) 01130 { 01131 continue; 01132 } 01133 01134 if (((destinationPathType == AnsaOSPF::RoutingTableEntry::Type1External) && 01135 (type2ExternalMetric)) || 01136 ((destinationPathType == AnsaOSPF::RoutingTableEntry::Type2External) && 01137 (type2ExternalMetric) && 01138 (destinationEntry->GetType2Cost() < externalCost))) // (6) (b) 01139 { 01140 continue; 01141 } 01142 01143 AnsaOSPF::RoutingTableEntry* destinationPreferredEntry = GetPreferredEntry(*(destinationEntry->GetLinkStateOrigin()), false, &newRoutingTable); 01144 if ((!rfc1583Compatibility) && 01145 (destinationPreferredEntry->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) && 01146 (destinationPreferredEntry->GetArea() != AnsaOSPF::BackboneAreaID) && 01147 ((preferredEntry->GetPathType() != AnsaOSPF::RoutingTableEntry::IntraArea) || 01148 (preferredEntry->GetArea() == AnsaOSPF::BackboneAreaID))) 01149 { 01150 continue; 01151 } 01152 01153 if ((((destinationPathType == AnsaOSPF::RoutingTableEntry::Type1External) && 01154 (!type2ExternalMetric) && 01155 (destinationEntry->GetCost() < preferredCost + externalCost))) || 01156 ((destinationPathType == AnsaOSPF::RoutingTableEntry::Type2External) && 01157 (type2ExternalMetric) && 01158 (destinationEntry->GetType2Cost() == externalCost) && 01159 (destinationPreferredEntry->GetCost() < preferredCost))) 01160 { 01161 continue; 01162 } 01163 01164 if (((destinationPathType == AnsaOSPF::RoutingTableEntry::Type1External) && 01165 (!type2ExternalMetric) && 01166 (destinationEntry->GetCost() == (preferredCost + externalCost))) || 01167 ((destinationPathType == AnsaOSPF::RoutingTableEntry::Type2External) && 01168 (type2ExternalMetric) && 01169 (destinationEntry->GetType2Cost() == externalCost) && 01170 (destinationPreferredEntry->GetCost() == preferredCost))) // equal cost 01171 { 01172 for (unsigned int j = 0; j < nextHopCount; j++) { 01173 // TODO: merge next hops, not add 01174 NextHop nextHop = preferredEntry->GetNextHop(j); 01175 01176 nextHop.advertisingRouter = originatingRouter; 01177 destinationEntry->AddNextHop(nextHop); 01178 } 01179 continue; 01180 } 01181 01182 // LSA is better 01183 destinationEntry->SetArea(preferredEntry->GetArea()); 01184 destinationEntry->SetPathType(type2ExternalMetric ? AnsaOSPF::RoutingTableEntry::Type2External : AnsaOSPF::RoutingTableEntry::Type1External); 01185 if (type2ExternalMetric) { 01186 destinationEntry->SetCost(preferredCost); 01187 destinationEntry->SetType2Cost(externalCost); 01188 } else { 01189 destinationEntry->SetCost(preferredCost + externalCost); 01190 } 01191 destinationEntry->SetDestinationType(AnsaOSPF::RoutingTableEntry::NetworkDestination); 01192 destinationEntry->SetOptionalCapabilities(currentHeader.getLsOptions()); 01193 destinationEntry->ClearNextHops(); 01194 01195 for (unsigned int j = 0; j < nextHopCount; j++) { 01196 NextHop nextHop = preferredEntry->GetNextHop(j); 01197 01198 nextHop.advertisingRouter = originatingRouter; 01199 destinationEntry->AddNextHop(nextHop); 01200 } 01201 } 01202 } 01203 } 01204 01205 01215 AnsaOSPF::IPv4AddressRange AnsaOSPF::Router::GetContainingAddressRange(AnsaOSPF::IPv4AddressRange addressRange, bool* advertise /*= NULL*/) const 01216 { 01217 unsigned long areaCount = areas.size(); 01218 for (unsigned long i = 0; i < areaCount; i++) { 01219 AnsaOSPF::IPv4AddressRange containingAddressRange = areas[i]->GetContainingAddressRange(addressRange, advertise); 01220 if (containingAddressRange != AnsaOSPF::NullIPv4AddressRange) { 01221 return containingAddressRange; 01222 } 01223 } 01224 if (advertise != NULL) { 01225 *advertise = false; 01226 } 01227 return AnsaOSPF::NullIPv4AddressRange; 01228 } 01229 01230 01246 AnsaOSPF::LinkStateID AnsaOSPF::Router::GetUniqueLinkStateID(AnsaOSPF::IPv4AddressRange destination, 01247 AnsaOSPF::Metric destinationCost, 01248 AnsaOSPF::ASExternalLSA*& lsaToReoriginate, 01249 bool externalMetricIsType2 /*= false*/) const 01250 { 01251 if (lsaToReoriginate != NULL) { 01252 delete lsaToReoriginate; 01253 lsaToReoriginate = NULL; 01254 } 01255 01256 AnsaOSPF::LSAKeyType lsaKey; 01257 01258 lsaKey.linkStateID = ULongFromIPv4Address(destination.address); 01259 lsaKey.advertisingRouter = routerID; 01260 01261 const AnsaOSPF::ASExternalLSA* foundLSA = FindASExternalLSA(lsaKey); 01262 01263 if (foundLSA == NULL) { 01264 return lsaKey.linkStateID; 01265 } else { 01266 AnsaOSPF::IPv4Address existingMask = IPv4AddressFromULong(foundLSA->getContents().getNetworkMask().getInt()); 01267 01268 if (destination.mask >= existingMask) { 01269 return (lsaKey.linkStateID | (~(ULongFromIPv4Address(destination.mask)))); 01270 } else { 01271 AnsaOSPF::ASExternalLSA* asExternalLSA = new AnsaOSPF::ASExternalLSA(*foundLSA); 01272 01273 long sequenceNumber = asExternalLSA->getHeader().getLsSequenceNumber(); 01274 01275 asExternalLSA->getHeader().setLsAge(0); 01276 asExternalLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1); 01277 asExternalLSA->getContents().setNetworkMask(ULongFromIPv4Address(destination.mask)); 01278 asExternalLSA->getContents().setE_ExternalMetricType(externalMetricIsType2); 01279 asExternalLSA->getContents().setRouteCost(destinationCost); 01280 asExternalLSA->getHeader().setLsChecksum(0); // TODO: calculate correct LS checksum 01281 01282 lsaToReoriginate = asExternalLSA; 01283 01284 return (lsaKey.linkStateID | (~(ULongFromIPv4Address(existingMask)))); 01285 } 01286 } 01287 } 01288 01289 01298 // TODO: review this algorithm + add virtual link changes(RFC2328 Section 16.7.). 01299 void AnsaOSPF::Router::NotifyAboutRoutingTableChanges(std::vector<AnsaOSPF::RoutingTableEntry*>& oldRoutingTable) 01300 { 01301 if (areas.size() <= 1) { 01302 return; 01303 } 01304 01305 unsigned long routeCount = oldRoutingTable.size(); 01306 std::map<unsigned long, RoutingTableEntry*> oldTableMap; 01307 std::map<unsigned long, RoutingTableEntry*> newTableMap; 01308 unsigned long i, j, k; 01309 01310 for (i = 0; i < routeCount; i++) { 01311 unsigned long destination = oldRoutingTable[i]->GetDestinationID().getInt() & oldRoutingTable[i]->GetAddressMask().getInt(); 01312 oldTableMap[destination] = oldRoutingTable[i]; 01313 } 01314 01315 routeCount = routingTable.size(); 01316 for (i = 0; i < routeCount; i++) { 01317 unsigned long destination = routingTable[i]->GetDestinationID().getInt() & routingTable[i]->GetAddressMask().getInt(); 01318 newTableMap[destination] = routingTable[i]; 01319 } 01320 01321 unsigned long areaCount = areas.size(); 01322 for (i = 0; i < areaCount; i++) { 01323 std::map<AnsaOSPF::LSAKeyType, bool, AnsaOSPF::LSAKeyType_Less> originatedLSAMap; 01324 std::map<AnsaOSPF::LSAKeyType, bool, AnsaOSPF::LSAKeyType_Less> deletedLSAMap; 01325 AnsaOSPF::LSAKeyType lsaKey; 01326 01327 routeCount = routingTable.size(); 01328 for (j = 0; j < routeCount; j++) { 01329 unsigned long destination = routingTable[j]->GetDestinationID().getInt() & routingTable[j]->GetAddressMask().getInt(); 01330 std::map<unsigned long, RoutingTableEntry*>::iterator destIt = oldTableMap.find(destination); 01331 if (destIt == oldTableMap.end()) { // new routing entry 01332 AnsaOSPF::SummaryLSA* lsaToReoriginate = NULL; 01333 AnsaOSPF::SummaryLSA* newLSA = areas[i]->OriginateSummaryLSA(routingTable[j], originatedLSAMap, lsaToReoriginate); 01334 01335 if (newLSA != NULL) { 01336 if (lsaToReoriginate != NULL) { 01337 areas[i]->InstallSummaryLSA(lsaToReoriginate); 01338 // FloodLSA(lsaToReoriginate, AnsaOSPF::BackboneAreaID); 01339 FloodLSA(lsaToReoriginate, areas[i]->GetAreaID()); 01340 01341 lsaKey.linkStateID = lsaToReoriginate->getHeader().getLinkStateID(); 01342 lsaKey.advertisingRouter = routerID; 01343 originatedLSAMap[lsaKey] = true; 01344 01345 delete lsaToReoriginate; 01346 } 01347 01348 areas[i]->InstallSummaryLSA(newLSA); 01349 // FloodLSA(newLSA, AnsaOSPF::BackboneAreaID); 01350 FloodLSA(newLSA, areas[i]->GetAreaID()); 01351 01352 lsaKey.linkStateID = newLSA->getHeader().getLinkStateID(); 01353 lsaKey.advertisingRouter = routerID; 01354 originatedLSAMap[lsaKey] = true; 01355 01356 delete newLSA; 01357 } 01358 } else { 01359 if (*(routingTable[j]) != *(destIt->second)) { // modified routing entry 01360 AnsaOSPF::SummaryLSA* lsaToReoriginate = NULL; 01361 AnsaOSPF::SummaryLSA* newLSA = areas[i]->OriginateSummaryLSA(routingTable[j], originatedLSAMap, lsaToReoriginate); 01362 01363 if (newLSA != NULL) { 01364 if (lsaToReoriginate != NULL) { 01365 areas[i]->InstallSummaryLSA(lsaToReoriginate); 01366 // FloodLSA(lsaToReoriginate, AnsaOSPF::BackboneAreaID); 01367 FloodLSA(lsaToReoriginate, areas[i]->GetAreaID()); 01368 01369 lsaKey.linkStateID = lsaToReoriginate->getHeader().getLinkStateID(); 01370 lsaKey.advertisingRouter = routerID; 01371 originatedLSAMap[lsaKey] = true; 01372 01373 delete lsaToReoriginate; 01374 } 01375 01376 areas[i]->InstallSummaryLSA(newLSA); 01377 // FloodLSA(newLSA, AnsaOSPF::BackboneAreaID); 01378 FloodLSA(newLSA, areas[i]->GetAreaID()); 01379 01380 lsaKey.linkStateID = newLSA->getHeader().getLinkStateID(); 01381 lsaKey.advertisingRouter = routerID; 01382 originatedLSAMap[lsaKey] = true; 01383 01384 delete newLSA; 01385 } else { 01386 AnsaOSPF::IPv4AddressRange destinationAddressRange; 01387 01388 destinationAddressRange.address = IPv4AddressFromULong(routingTable[j]->GetDestinationID().getInt()); 01389 destinationAddressRange.mask = IPv4AddressFromULong(routingTable[j]->GetAddressMask().getInt()); 01390 01391 if ((routingTable[j]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) && 01392 ((routingTable[j]->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) || 01393 (routingTable[j]->GetPathType() == AnsaOSPF::RoutingTableEntry::InterArea))) 01394 { 01395 AnsaOSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange(destinationAddressRange); 01396 if (containingAddressRange != AnsaOSPF::NullIPv4AddressRange) { 01397 destinationAddressRange = containingAddressRange; 01398 } 01399 } 01400 01401 Metric maxRangeCost = 0; 01402 Metric oneLessCost = 0; 01403 01404 for (k = 0; k < routeCount; k++) { 01405 if ((routingTable[k]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) && 01406 (routingTable[k]->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) && 01407 ((routingTable[k]->GetDestinationID().getInt() & routingTable[k]->GetAddressMask().getInt() & ULongFromIPv4Address(destinationAddressRange.mask)) == 01408 ULongFromIPv4Address(destinationAddressRange.address & destinationAddressRange.mask)) && 01409 (routingTable[k]->GetCost() > maxRangeCost)) 01410 { 01411 oneLessCost = maxRangeCost; 01412 maxRangeCost = routingTable[k]->GetCost(); 01413 } 01414 } 01415 01416 if (maxRangeCost == routingTable[j]->GetCost()) { // this entry gives the range's cost 01417 lsaKey.linkStateID = ULongFromIPv4Address(destinationAddressRange.address); 01418 lsaKey.advertisingRouter = routerID; 01419 01420 AnsaOSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA(lsaKey); 01421 01422 if (summaryLSA != NULL) { 01423 if (oneLessCost != 0) { // there's an other entry in this range 01424 summaryLSA->setRouteCost(oneLessCost); 01425 // FloodLSA(summaryLSA, AnsaOSPF::BackboneAreaID); 01426 FloodLSA(summaryLSA, areas[i]->GetAreaID()); 01427 01428 originatedLSAMap[lsaKey] = true; 01429 } else { // no more entries in this range -> delete it 01430 std::map<AnsaOSPF::LSAKeyType, bool, AnsaOSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find(lsaKey); 01431 if (deletedIt == deletedLSAMap.end()) { 01432 summaryLSA->getHeader().setLsAge(MAX_AGE); 01433 // FloodLSA(summaryLSA, AnsaOSPF::BackboneAreaID); 01434 FloodLSA(summaryLSA, areas[i]->GetAreaID()); 01435 01436 deletedLSAMap[lsaKey] = true; 01437 } 01438 } 01439 } 01440 } 01441 } 01442 } 01443 } 01444 } 01445 01446 routeCount = oldRoutingTable.size(); 01447 for (j = 0; j < routeCount; j++) { 01448 unsigned long destination = oldRoutingTable[j]->GetDestinationID().getInt() & oldRoutingTable[j]->GetAddressMask().getInt(); 01449 std::map<unsigned long, RoutingTableEntry*>::iterator destIt = newTableMap.find(destination); 01450 if (destIt == newTableMap.end()) { // deleted routing entry 01451 01452 AnsaOSPF::IPv4AddressRange destinationAddressRange; 01453 01454 destinationAddressRange.address = IPv4AddressFromULong(oldRoutingTable[j]->GetDestinationID().getInt()); 01455 destinationAddressRange.mask = IPv4AddressFromULong(oldRoutingTable[j]->GetAddressMask().getInt()); 01456 01457 if ((oldRoutingTable[j]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) && 01458 ((oldRoutingTable[j]->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) || 01459 (oldRoutingTable[j]->GetPathType() == AnsaOSPF::RoutingTableEntry::InterArea))) 01460 { 01461 AnsaOSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange(destinationAddressRange); 01462 if (containingAddressRange != AnsaOSPF::NullIPv4AddressRange) { 01463 destinationAddressRange = containingAddressRange; 01464 } 01465 } 01466 01467 Metric maxRangeCost = 0; 01468 01469 unsigned long newRouteCount = routingTable.size(); 01470 for (k = 0; k < newRouteCount; k++) { 01471 if ((routingTable[k]->GetDestinationType() == AnsaOSPF::RoutingTableEntry::NetworkDestination) && 01472 (routingTable[k]->GetPathType() == AnsaOSPF::RoutingTableEntry::IntraArea) && 01473 ((routingTable[k]->GetDestinationID().getInt() & routingTable[k]->GetAddressMask().getInt() & ULongFromIPv4Address(destinationAddressRange.mask)) == 01474 ULongFromIPv4Address(destinationAddressRange.address & destinationAddressRange.mask)) && 01475 (routingTable[k]->GetCost() > maxRangeCost)) 01476 { 01477 maxRangeCost = routingTable[k]->GetCost(); 01478 } 01479 } 01480 01481 if (maxRangeCost < oldRoutingTable[j]->GetCost()) { // the range's cost will change 01482 lsaKey.linkStateID = ULongFromIPv4Address(destinationAddressRange.address); 01483 lsaKey.advertisingRouter = routerID; 01484 01485 AnsaOSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA(lsaKey); 01486 01487 if (summaryLSA != NULL) { 01488 if (maxRangeCost > 0) { // there's an other entry in this range 01489 summaryLSA->setRouteCost(maxRangeCost); 01490 // FloodLSA(summaryLSA, AnsaOSPF::BackboneAreaID); 01491 FloodLSA(summaryLSA, areas[i]->GetAreaID()); 01492 01493 originatedLSAMap[lsaKey] = true; 01494 } else { // no more entries in this range -> delete it 01495 std::map<AnsaOSPF::LSAKeyType, bool, AnsaOSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find(lsaKey); 01496 if (deletedIt == deletedLSAMap.end()) { 01497 summaryLSA->getHeader().setLsAge(MAX_AGE); 01498 // FloodLSA(summaryLSA, AnsaOSPF::BackboneAreaID); 01499 FloodLSA(summaryLSA, areas[i]->GetAreaID()); 01500 01501 deletedLSAMap[lsaKey] = true; 01502 } 01503 } 01504 } 01505 } 01506 } 01507 } 01508 } 01509 } 01510 01511 01519 void AnsaOSPF::Router::UpdateExternalRoute(AnsaOSPF::IPv4Address networkAddress, const OSPFASExternalLSAContents& externalRouteContents, int ifIndex) 01520 { 01521 AnsaOSPF::ASExternalLSA* asExternalLSA = new AnsaOSPF::ASExternalLSA; 01522 OSPFLSAHeader& lsaHeader = asExternalLSA->getHeader(); 01523 OSPFOptions lsaOptions; 01524 //AnsaOSPF::LSAKeyType lsaKey; 01525 01526 IRoutingTable* simRoutingTable = RoutingTableAccess().get(); 01527 unsigned long routingEntryNumber = simRoutingTable->getNumRoutes(); 01528 bool inRoutingTable = false; 01529 // add the external route to the routing table if it was not added by another module 01530 for (unsigned long i = 0; i < routingEntryNumber; i++) { 01531 const IPRoute *entry = simRoutingTable->getRoute(i); 01532 if ((entry->getHost().getInt() & entry->getNetmask().getInt()) == 01533 (ULongFromIPv4Address(networkAddress) & externalRouteContents.getNetworkMask().getInt())) 01534 { 01535 inRoutingTable = true; 01536 } 01537 } 01538 if (!inRoutingTable) { 01539 IPRoute* entry = new IPRoute; 01540 entry->setHost(ULongFromIPv4Address(networkAddress)); 01541 entry->setNetmask(externalRouteContents.getNetworkMask()); 01542 entry->setInterface(InterfaceTableAccess().get()->getInterfaceById(ifIndex)); 01543 entry->setType(IPRoute::REMOTE); 01544 entry->setSource(IPRoute::MANUAL); 01545 entry->setMetric(externalRouteContents.getRouteCost()); 01546 simRoutingTable->addRoute(entry); // IRoutingTable deletes entry pointer 01547 } 01548 01549 lsaHeader.setLsAge(0); 01550 memset(&lsaOptions, 0, sizeof(OSPFOptions)); 01551 lsaOptions.E_ExternalRoutingCapability = true; 01552 lsaHeader.setLsOptions(lsaOptions); 01553 lsaHeader.setLsType(ASExternalLSAType); 01554 lsaHeader.setLinkStateID(ULongFromIPv4Address(networkAddress)); // TODO: get unique LinkStateID 01555 lsaHeader.setAdvertisingRouter(routerID); 01556 lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER); 01557 01558 asExternalLSA->setContents(externalRouteContents); 01559 01560 lsaHeader.setLsChecksum(0); // TODO: calculate correct LS checksum 01561 01562 asExternalLSA->SetSource(AnsaOSPF::LSATrackingInfo::Originated); 01563 01564 externalRoutes[networkAddress] = externalRouteContents; 01565 01566 bool rebuild = InstallASExternalLSA(asExternalLSA); 01567 FloodLSA(asExternalLSA, AnsaOSPF::BackboneAreaID); 01568 delete asExternalLSA; 01569 01570 if (rebuild) { 01571 RebuildRoutingTable(); 01572 } 01573 } 01574 01575 01581 void AnsaOSPF::Router::RemoveExternalRoute(AnsaOSPF::IPv4Address networkAddress) 01582 { 01583 AnsaOSPF::LSAKeyType lsaKey; 01584 01585 lsaKey.linkStateID = ULongFromIPv4Address(networkAddress); 01586 lsaKey.advertisingRouter = routerID; 01587 01588 std::map<AnsaOSPF::LSAKeyType, AnsaOSPF::ASExternalLSA*, AnsaOSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey); 01589 if (lsaIt != asExternalLSAsByID.end()) { 01590 lsaIt->second->getHeader().setLsAge(MAX_AGE); 01591 lsaIt->second->SetPurgeable(); 01592 FloodLSA(lsaIt->second, AnsaOSPF::BackboneAreaID); 01593 } 01594 01595 std::map<AnsaOSPF::IPv4Address, OSPFASExternalLSAContents, AnsaOSPF::IPv4Address_Less>::iterator externalIt = externalRoutes.find(networkAddress); 01596 if (externalIt != externalRoutes.end()) { 01597 externalRoutes.erase(externalIt); 01598 } 01599 }