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