OSPFRouter.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Andras Babos and Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include "OSPFRouter.h"
00019 #include "RoutingTableAccess.h"
00020 
00025 OSPF::Router::Router(OSPF::RouterID id, cSimpleModule* containingModule) :
00026     routerID(id),
00027     rfc1583Compatibility(false)
00028 {
00029     messageHandler = new OSPF::MessageHandler(this, containingModule);
00030     ageTimer = new OSPFTimer;
00031     ageTimer->setTimerKind(DatabaseAgeTimer);
00032     ageTimer->setContextPointer(this);
00033     ageTimer->setName("OSPF::Router::DatabaseAgeTimer");
00034     messageHandler->StartTimer(ageTimer, 1.0);
00035 }
00036 
00037 
00042 OSPF::Router::~Router(void)
00043 {
00044     long areaCount = areas.size();
00045     for (long i = 0; i < areaCount; i++) {
00046         delete areas[i];
00047     }
00048     long lsaCount = asExternalLSAs.size();
00049     for (long j = 0; j < lsaCount; j++) {
00050         delete asExternalLSAs[j];
00051     }
00052     long routeCount = routingTable.size();
00053     for (long k = 0; k < routeCount; k++) {
00054         delete routingTable[k];
00055     }
00056     messageHandler->ClearTimer(ageTimer);
00057     delete ageTimer;
00058     delete messageHandler;
00059 }
00060 
00061 
00065 void OSPF::Router::AddWatches(void)
00066 {
00067     WATCH(routerID);
00068     WATCH_PTRVECTOR(areas);
00069     WATCH_PTRVECTOR(asExternalLSAs);
00070 }
00071 
00072 
00077 void OSPF::Router::AddArea(OSPF::Area* area)
00078 {
00079 
00080     area->SetRouter(this);
00081     areasByID[area->GetAreaID()] = area;
00082     areas.push_back(area);
00083 }
00084 
00085 
00091 OSPF::Area* OSPF::Router::GetArea(OSPF::AreaID areaID)
00092 {
00093     std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00094     if (areaIt != areasByID.end()) {
00095         return (areaIt->second);
00096     }
00097     else {
00098         return NULL;
00099     }
00100 }
00101 
00102 
00108 OSPF::Area* OSPF::Router::GetArea(OSPF::IPv4Address address)
00109 {
00110     long areaCount = areas.size();
00111     for (long i = 0; i < areaCount; i++) {
00112         if (areas[i]->ContainsAddress(address)) {
00113             return areas[i];
00114         }
00115     }
00116     return NULL;
00117 }
00118 
00119 
00125 OSPF::Interface* OSPF::Router::GetNonVirtualInterface(unsigned char ifIndex)
00126 {
00127     long areaCount = areas.size();
00128     for (long i = 0; i < areaCount; i++) {
00129         OSPF::Interface* intf = areas[i]->GetInterface(ifIndex);
00130         if (intf != NULL) {
00131             return intf;
00132         }
00133     }
00134     return NULL;
00135 }
00136 
00137 
00146 bool OSPF::Router::InstallLSA(OSPFLSA* lsa, OSPF::AreaID areaID /*= BackboneAreaID*/)
00147 {
00148     switch (lsa->getHeader().getLsType()) {
00149         case RouterLSAType:
00150             {
00151                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00152                 if (areaIt != areasByID.end()) {
00153                     OSPFRouterLSA* ospfRouterLSA = check_and_cast<OSPFRouterLSA*> (lsa);
00154                     return areaIt->second->InstallRouterLSA(ospfRouterLSA);
00155                 }
00156             }
00157             break;
00158         case NetworkLSAType:
00159             {
00160                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00161                 if (areaIt != areasByID.end()) {
00162                     OSPFNetworkLSA* ospfNetworkLSA = check_and_cast<OSPFNetworkLSA*> (lsa);
00163                     return areaIt->second->InstallNetworkLSA(ospfNetworkLSA);
00164                 }
00165             }
00166             break;
00167         case SummaryLSA_NetworksType:
00168         case SummaryLSA_ASBoundaryRoutersType:
00169             {
00170                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00171                 if (areaIt != areasByID.end()) {
00172                     OSPFSummaryLSA* ospfSummaryLSA = check_and_cast<OSPFSummaryLSA*> (lsa);
00173                     return areaIt->second->InstallSummaryLSA(ospfSummaryLSA);
00174                 }
00175             }
00176             break;
00177         case ASExternalLSAType:
00178             {
00179                 OSPFASExternalLSA* ospfASExternalLSA = check_and_cast<OSPFASExternalLSA*> (lsa);
00180                 return InstallASExternalLSA(ospfASExternalLSA);
00181             }
00182             break;
00183         default:
00184             ASSERT(false);
00185             break;
00186     }
00187     return false;
00188 }
00189 
00190 
00198 bool OSPF::Router::InstallASExternalLSA(OSPFASExternalLSA* lsa)
00199 {
00217      // TODO: how to solve this problem?
00218 
00219     OSPF::RouterID advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00220     bool           reachable         = false;
00221     unsigned int   routeCount        = routingTable.size();
00222 
00223     for (unsigned int i = 0; i < routeCount; i++) {
00224         if ((((routingTable[i]->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
00225              ((routingTable[i]->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
00226             (routingTable[i]->GetDestinationID().getInt() == advertisingRouter))
00227         {
00228             reachable = true;
00229             break;
00230         }
00231     }
00232 
00233     bool             ownLSAFloodedOut = false;
00234     OSPF::LSAKeyType lsaKey;
00235 
00236     lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00237     lsaKey.advertisingRouter = routerID;
00238 
00239     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey);
00240     if ((lsaIt != asExternalLSAsByID.end()) &&
00241         reachable &&
00242         (lsaIt->second->getContents().getE_ExternalMetricType() == lsa->getContents().getE_ExternalMetricType()) &&
00243         (lsaIt->second->getContents().getRouteCost() == lsa->getContents().getRouteCost()) &&
00244         (lsa->getContents().getForwardingAddress().getInt() != 0) &&   // forwarding address != 0.0.0.0
00245         (lsaIt->second->getContents().getForwardingAddress() == lsa->getContents().getForwardingAddress()))
00246     {
00247         if (routerID > advertisingRouter) {
00248             return false;
00249         } else {
00250             lsaIt->second->getHeader().setLsAge(MAX_AGE);
00251             FloodLSA(lsaIt->second, OSPF::BackboneAreaID);
00252             lsaIt->second->IncrementInstallTime();
00253             ownLSAFloodedOut = true;
00254         }
00255     }
00256 
00257     lsaKey.advertisingRouter = advertisingRouter;
00258 
00259     lsaIt = asExternalLSAsByID.find(lsaKey);
00260     if (lsaIt != asExternalLSAsByID.end()) {
00261         unsigned long areaCount = areas.size();
00262         for (unsigned long i = 0; i < areaCount; i++) {
00263             areas[i]->RemoveFromAllRetransmissionLists(lsaKey);
00264         }
00265         return ((lsaIt->second->Update(lsa)) | ownLSAFloodedOut);
00266     } else {
00267         OSPF::ASExternalLSA* lsaCopy = new OSPF::ASExternalLSA(*lsa);
00268         asExternalLSAsByID[lsaKey] = lsaCopy;
00269         asExternalLSAs.push_back(lsaCopy);
00270         return true;
00271     }
00272 }
00273 
00274 
00283 OSPFLSA* OSPF::Router::FindLSA(LSAType lsaType, OSPF::LSAKeyType lsaKey, OSPF::AreaID areaID)
00284 {
00285     switch (lsaType) {
00286         case RouterLSAType:
00287             {
00288                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00289                 if (areaIt != areasByID.end()) {
00290                     return areaIt->second->FindRouterLSA(lsaKey.linkStateID);
00291                 }
00292             }
00293             break;
00294         case NetworkLSAType:
00295             {
00296                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00297                 if (areaIt != areasByID.end()) {
00298                     return areaIt->second->FindNetworkLSA(lsaKey.linkStateID);
00299                 }
00300             }
00301             break;
00302         case SummaryLSA_NetworksType:
00303         case SummaryLSA_ASBoundaryRoutersType:
00304             {
00305                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00306                 if (areaIt != areasByID.end()) {
00307                     return areaIt->second->FindSummaryLSA(lsaKey);
00308                 }
00309             }
00310             break;
00311         case ASExternalLSAType:
00312             {
00313                 return FindASExternalLSA(lsaKey);
00314             }
00315             break;
00316         default:
00317             ASSERT(false);
00318             break;
00319     }
00320     return NULL;
00321 }
00322 
00323 
00329 OSPF::ASExternalLSA* OSPF::Router::FindASExternalLSA(OSPF::LSAKeyType lsaKey)
00330 {
00331     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey);
00332     if (lsaIt != asExternalLSAsByID.end()) {
00333         return lsaIt->second;
00334     } else {
00335         return NULL;
00336     }
00337 }
00338 
00339 
00345 const OSPF::ASExternalLSA* OSPF::Router::FindASExternalLSA(OSPF::LSAKeyType lsaKey) const
00346 {
00347     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::const_iterator lsaIt = asExternalLSAsByID.find(lsaKey);
00348     if (lsaIt != asExternalLSAsByID.end()) {
00349         return lsaIt->second;
00350     } else {
00351         return NULL;
00352     }
00353 }
00354 
00355 
00361 void OSPF::Router::AgeDatabase(void)
00362 {
00363     long lsaCount            = asExternalLSAs.size();
00364     bool rebuildRoutingTable = false;
00365 
00366     for (long i = 0; i < lsaCount; i++) {
00367         unsigned short       lsAge          = asExternalLSAs[i]->getHeader().getLsAge();
00368         bool                 selfOriginated = (asExternalLSAs[i]->getHeader().getAdvertisingRouter().getInt() == routerID);
00369         bool                 unreachable    = IsDestinationUnreachable(asExternalLSAs[i]);
00370         OSPF::ASExternalLSA* lsa            = asExternalLSAs[i];
00371 
00372         if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) {
00373             lsa->getHeader().setLsAge(lsAge + 1);
00374             if ((lsAge + 1) % CHECK_AGE == 0) {
00375                 if (!lsa->ValidateLSChecksum()) {
00376                     EV << "Invalid LS checksum. Memory error detected!\n";
00377                 }
00378             }
00379             lsa->IncrementInstallTime();
00380         }
00381         if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) {
00382             if (unreachable) {
00383                 lsa->getHeader().setLsAge(MAX_AGE);
00384                 FloodLSA(lsa, OSPF::BackboneAreaID);
00385                 lsa->IncrementInstallTime();
00386             } else {
00387                 long sequenceNumber = lsa->getHeader().getLsSequenceNumber();
00388                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00389                     lsa->getHeader().setLsAge(MAX_AGE);
00390                     FloodLSA(lsa, OSPF::BackboneAreaID);
00391                     lsa->IncrementInstallTime();
00392                 } else {
00393                     OSPF::ASExternalLSA* newLSA = OriginateASExternalLSA(lsa);
00394 
00395                     newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00396                     newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00397                     rebuildRoutingTable |= lsa->Update(newLSA);
00398                     delete newLSA;
00399 
00400                     FloodLSA(lsa, OSPF::BackboneAreaID);
00401                 }
00402             }
00403         }
00404         if (!selfOriginated && (lsAge == MAX_AGE - 1)) {
00405             lsa->getHeader().setLsAge(MAX_AGE);
00406             FloodLSA(lsa, OSPF::BackboneAreaID);
00407             lsa->IncrementInstallTime();
00408         }
00409         if (lsAge == MAX_AGE) {
00410             OSPF::LSAKeyType lsaKey;
00411 
00412             lsaKey.linkStateID       = lsa->getHeader().getLinkStateID();
00413             lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00414 
00415             if (!IsOnAnyRetransmissionList(lsaKey) &&
00416                 !HasAnyNeighborInStates(OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState))
00417             {
00418                 if (!selfOriginated || unreachable) {
00419                     asExternalLSAsByID.erase(lsaKey);
00420                     delete lsa;
00421                     asExternalLSAs[i] = NULL;
00422                     rebuildRoutingTable = true;
00423                 } else {
00424                     if (lsa->GetPurgeable()) {
00425                         asExternalLSAsByID.erase(lsaKey);
00426                         delete lsa;
00427                         asExternalLSAs[i] = NULL;
00428                         rebuildRoutingTable = true;
00429                     } else {
00430                         OSPF::ASExternalLSA* newLSA              = OriginateASExternalLSA(lsa);
00431                         long                 sequenceNumber      = lsa->getHeader().getLsSequenceNumber();
00432 
00433                         newLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
00434                         newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00435                         rebuildRoutingTable |= lsa->Update(newLSA);
00436                         delete newLSA;
00437 
00438                         FloodLSA(lsa, OSPF::BackboneAreaID);
00439                     }
00440                 }
00441             }
00442         }
00443     }
00444 
00445     std::vector<ASExternalLSA*>::iterator it = asExternalLSAs.begin();
00446     while (it != asExternalLSAs.end()) {
00447         if ((*it) == NULL) {
00448             it = asExternalLSAs.erase(it);
00449         } else {
00450             it++;
00451         }
00452     }
00453 
00454     long areaCount = areas.size();
00455     for (long j = 0; j < areaCount; j++) {
00456         areas[j]->AgeDatabase();
00457     }
00458     messageHandler->StartTimer(ageTimer, 1.0);
00459 
00460     if (rebuildRoutingTable) {
00461         RebuildRoutingTable();
00462     }
00463 }
00464 
00465 
00471 bool OSPF::Router::HasAnyNeighborInStates(int states) const
00472 {
00473     long areaCount = areas.size();
00474     for (long i = 0; i < areaCount; i++) {
00475         if (areas[i]->HasAnyNeighborInStates(states)) {
00476             return true;
00477         }
00478     }
00479     return false;
00480 }
00481 
00482 
00488 void OSPF::Router::RemoveFromAllRetransmissionLists(OSPF::LSAKeyType lsaKey)
00489 {
00490     long areaCount = areas.size();
00491     for (long i = 0; i < areaCount; i++) {
00492         areas[i]->RemoveFromAllRetransmissionLists(lsaKey);
00493     }
00494 }
00495 
00496 
00502 bool OSPF::Router::IsOnAnyRetransmissionList(OSPF::LSAKeyType lsaKey) const
00503 {
00504     long areaCount = areas.size();
00505     for (long i = 0; i < areaCount; i++) {
00506         if (areas[i]->IsOnAnyRetransmissionList(lsaKey)) {
00507             return true;
00508         }
00509     }
00510     return false;
00511 }
00512 
00513 
00523 bool OSPF::Router::FloodLSA(OSPFLSA* lsa, OSPF::AreaID areaID /*= BackboneAreaID*/, OSPF::Interface* intf /*= NULL*/, OSPF::Neighbor* neighbor /*= NULL*/)
00524 {
00525     bool floodedBackOut = false;
00526 
00527     if (lsa != NULL) {
00528         if (lsa->getHeader().getLsType() == ASExternalLSAType) {
00529             long areaCount = areas.size();
00530             for (long i = 0; i < areaCount; i++) {
00531                 if (areas[i]->GetExternalRoutingCapability()) {
00532                     if (areas[i]->FloodLSA(lsa, intf, neighbor)) {
00533                         floodedBackOut = true;
00534                     }
00535                 }
00536             }
00537         } else {
00538             std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find(areaID);
00539             if (areaIt != areasByID.end()) {
00540                 floodedBackOut = areaIt->second->FloodLSA(lsa, intf, neighbor);
00541             }
00542         }
00543     }
00544 
00545     return floodedBackOut;
00546 }
00547 
00548 
00554 bool OSPF::Router::IsLocalAddress(OSPF::IPv4Address address) const
00555 {
00556     long areaCount = areas.size();
00557     for (long i = 0; i < areaCount; i++) {
00558         if (areas[i]->IsLocalAddress(address)) {
00559             return true;
00560         }
00561     }
00562     return false;
00563 }
00564 
00565 
00571 bool OSPF::Router::HasAddressRange(OSPF::IPv4AddressRange addressRange) const
00572 {
00573     long areaCount = areas.size();
00574     for (long i = 0; i < areaCount; i++) {
00575         if (areas[i]->HasAddressRange(addressRange)) {
00576             return true;
00577         }
00578     }
00579     return false;
00580 }
00581 
00582 
00588 OSPF::ASExternalLSA* OSPF::Router::OriginateASExternalLSA(OSPF::ASExternalLSA* lsa)
00589 {
00590     OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA(*lsa);
00591     OSPFLSAHeader& lsaHeader = asExternalLSA->getHeader();
00592     OSPFOptions    lsaOptions;
00593 
00594     lsaHeader.setLsAge(0);
00595     memset(&lsaOptions, 0, sizeof(OSPFOptions));
00596     lsaOptions.E_ExternalRoutingCapability = true;
00597     lsaHeader.setLsOptions(lsaOptions);
00598     lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
00599     asExternalLSA->SetSource(OSPF::LSATrackingInfo::Originated);
00600 
00601     return asExternalLSA;
00602 }
00603 
00604 
00609 bool OSPF::Router::IsDestinationUnreachable(OSPFLSA* lsa) const
00610 {
00611     IPAddress destination = lsa->getHeader().getLinkStateID();
00612 
00613     OSPFRouterLSA* routerLSA         = dynamic_cast<OSPFRouterLSA*> (lsa);
00614     OSPFNetworkLSA* networkLSA       = dynamic_cast<OSPFNetworkLSA*> (lsa);
00615     OSPFSummaryLSA* summaryLSA       = dynamic_cast<OSPFSummaryLSA*> (lsa);
00616     OSPFASExternalLSA* asExternalLSA = dynamic_cast<OSPFASExternalLSA*> (lsa);
00617     // TODO: verify
00618     if (routerLSA != NULL) {
00619         OSPF::RoutingInfo* routingInfo = check_and_cast<OSPF::RoutingInfo*> (routerLSA);
00620         if (routerLSA->getHeader().getLinkStateID() == routerID) { // this is spfTreeRoot
00621             return false;
00622         }
00623 
00624         // get the interface address pointing backwards on the shortest path tree
00625         unsigned int     linkCount   = routerLSA->getLinksArraySize();
00626         OSPF::RouterLSA* toRouterLSA = dynamic_cast<OSPF::RouterLSA*> (routingInfo->GetParent());
00627         if (toRouterLSA != NULL) {
00628             bool      destinationFound           = false;
00629             bool      unnumberedPointToPointLink = false;
00630             IPAddress firstNumberedIfAddress;
00631 
00632             for (unsigned int i = 0; i < linkCount; i++) {
00633                 Link& link = routerLSA->getLinks(i);
00634 
00635                 if (link.getType() == PointToPointLink) {
00636                     if (link.getLinkID() == toRouterLSA->getHeader().getLinkStateID()) {
00637                         if ((link.getLinkData() & 0xFF000000) == 0) {
00638                             unnumberedPointToPointLink = true;
00639                             if (!firstNumberedIfAddress.isUnspecified()) {
00640                                 break;
00641                             }
00642                         } else {
00643                             destination = link.getLinkData();
00644                             destinationFound = true;
00645                             break;
00646                         }
00647                     } else {
00648                         if (((link.getLinkData() & 0xFF000000) != 0) &&
00649                              firstNumberedIfAddress.isUnspecified())
00650                         {
00651                             firstNumberedIfAddress = link.getLinkData();
00652                         }
00653                     }
00654                 } else if (link.getType() == TransitLink) {
00655                     if (firstNumberedIfAddress.isUnspecified()) {
00656                         firstNumberedIfAddress = link.getLinkData();
00657                     }
00658                 } else if (link.getType() == VirtualLink) {
00659                     if (link.getLinkID() == toRouterLSA->getHeader().getLinkStateID()) {
00660                         destination = link.getLinkData();
00661                         destinationFound = true;
00662                         break;
00663                     } else {
00664                         if (firstNumberedIfAddress.isUnspecified()) {
00665                             firstNumberedIfAddress = link.getLinkData();
00666                         }
00667                     }
00668                 }
00669                 // There's no way to get an interface address for the router from a StubLink
00670             }
00671             if (unnumberedPointToPointLink) {
00672                 if (!firstNumberedIfAddress.isUnspecified()) {
00673                     destination = firstNumberedIfAddress;
00674                 } else {
00675                     return true;
00676                 }
00677             }
00678             if (!destinationFound) {
00679                 return true;
00680             }
00681         } else {
00682             OSPF::NetworkLSA* toNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (routingInfo->GetParent());
00683             if (toNetworkLSA != NULL) {
00684                 // get the interface address pointing backwards on the shortest path tree
00685                 bool destinationFound = false;
00686                 for (unsigned int i = 0; i < linkCount; i++) {
00687                     Link& link = routerLSA->getLinks(i);
00688 
00689                     if ((link.getType() == TransitLink) &&
00690                         (link.getLinkID() == toNetworkLSA->getHeader().getLinkStateID()))
00691                     {
00692                         destination = link.getLinkData();
00693                         destinationFound = true;
00694                         break;
00695                     }
00696                 }
00697                 if (!destinationFound) {
00698                     return true;
00699                 }
00700             } else {
00701                 return true;
00702             }
00703         }
00704     }
00705     if (networkLSA != NULL) {
00706         destination = networkLSA->getHeader().getLinkStateID() & networkLSA->getNetworkMask().getInt();
00707     }
00708     if ((summaryLSA != NULL) && (summaryLSA->getHeader().getLsType() == SummaryLSA_NetworksType)) {
00709         destination = summaryLSA->getHeader().getLinkStateID() & summaryLSA->getNetworkMask().getInt();
00710     }
00711     if (asExternalLSA != NULL) {
00712         destination = asExternalLSA->getHeader().getLinkStateID() & asExternalLSA->getContents().getNetworkMask().getInt();
00713     }
00714 
00715     if (Lookup(destination) == NULL) {
00716         return true;
00717     } else {
00718         return false;
00719     }
00720 }
00721 
00722 
00730 OSPF::RoutingTableEntry* OSPF::Router::Lookup(IPAddress destination, std::vector<OSPF::RoutingTableEntry*>* table /*= NULL*/) const
00731 {
00732     const std::vector<OSPF::RoutingTableEntry*>& rTable           = (table == NULL) ? routingTable : (*table);
00733     unsigned long                                dest             = destination.getInt();
00734     unsigned long                                routingTableSize = rTable.size();
00735     bool                                         unreachable      = false;
00736     std::vector<OSPF::RoutingTableEntry*>        discard;
00737     unsigned long                                i;
00738 
00739     unsigned long areaCount = areas.size();
00740     for (i = 0; i < areaCount; i++) {
00741         unsigned int addressRangeCount = areas[i]->GetAddressRangeCount();
00742         for (unsigned int j = 0; j < addressRangeCount; j++) {
00743             OSPF::IPv4AddressRange range = areas[i]->GetAddressRange(j);
00744 
00745             for (unsigned int k = 0; k < routingTableSize; k++) {
00746                 OSPF::RoutingTableEntry* entry = rTable[k];
00747 
00748                 if (entry->GetDestinationType() != OSPF::RoutingTableEntry::NetworkDestination) {
00749                     continue;
00750                 }
00751                 if (((entry->GetDestinationID().getInt() & entry->GetAddressMask().getInt() & ULongFromIPv4Address(range.mask)) == ULongFromIPv4Address(range.address & range.mask)) &&
00752                     (entry->GetPathType() == OSPF::RoutingTableEntry::IntraArea))
00753                 {
00754                     // active area address range
00755                     OSPF::RoutingTableEntry* discardEntry = new OSPF::RoutingTableEntry;
00756                     discardEntry->SetDestinationID(ULongFromIPv4Address(range.address));
00757                     discardEntry->SetAddressMask(ULongFromIPv4Address(range.mask));
00758                     discardEntry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
00759                     discardEntry->SetPathType(OSPF::RoutingTableEntry::InterArea);
00760                     discardEntry->SetArea(areas[i]->GetAreaID());
00761                     discard.push_back(discardEntry);
00762                     break;
00763                 }
00764             }
00765         }
00766     }
00767 
00768     OSPF::RoutingTableEntry* bestMatch = NULL;
00769     unsigned long            longestMatch = 0;
00770 
00771     for (i = 0; i < routingTableSize; i++) {
00772         if (rTable[i]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) {
00773             OSPF::RoutingTableEntry* entry        = rTable[i];
00774             unsigned long            entryAddress = entry->GetDestinationID().getInt();
00775             unsigned long            entryMask    = entry->GetAddressMask().getInt();
00776 
00777             if ((entryAddress & entryMask) == (dest & entryMask)) {
00778                 if ((dest & entryMask) > longestMatch) {
00779                     longestMatch = (dest & entryMask);
00780                     bestMatch    = entry;
00781                 }
00782             }
00783         }
00784     }
00785 
00786     unsigned int discardCount = discard.size();
00787     if (bestMatch == NULL) {
00788         unreachable = true;
00789     } else {
00790         for (i = 0; i < discardCount; i++) {
00791             OSPF::RoutingTableEntry* entry        = discard[i];
00792             unsigned long            entryAddress = entry->GetDestinationID().getInt();
00793             unsigned long            entryMask    = entry->GetAddressMask().getInt();
00794 
00795             if ((entryAddress & entryMask) == (dest & entryMask)) {
00796                 if ((dest & entryMask) > longestMatch) {
00797                     unreachable = true;
00798                     break;
00799                 }
00800             }
00801         }
00802     }
00803 
00804     for (i = 0; i < discardCount; i++) {
00805         delete discard[i];
00806     }
00807 
00808     if (unreachable) {
00809         return NULL;
00810     } else {
00811         return bestMatch;
00812     }
00813 }
00814 
00815 
00820 void OSPF::Router::RebuildRoutingTable(void)
00821 {
00822     unsigned long                         areaCount       = areas.size();
00823     bool                                  hasTransitAreas = false;
00824     std::vector<OSPF::RoutingTableEntry*> newTable;
00825     unsigned long                         i;
00826 
00827     EV << "Rebuilding routing table:\n";
00828 
00829     for (i = 0; i < areaCount; i++) {
00830         areas[i]->CalculateShortestPathTree(newTable);
00831         if (areas[i]->GetTransitCapability()) {
00832             hasTransitAreas = true;
00833         }
00834     }
00835     if (areaCount > 1) {
00836         OSPF::Area* backbone = GetArea(OSPF::BackboneAreaID);
00837         if (backbone != NULL) {
00838             backbone->CalculateInterAreaRoutes(newTable);
00839         }
00840     } else {
00841         if (areaCount == 1) {
00842             areas[0]->CalculateInterAreaRoutes(newTable);
00843         }
00844     }
00845     if (hasTransitAreas) {
00846         for (i = 0; i < areaCount; i++) {
00847             if (areas[i]->GetTransitCapability()) {
00848                 areas[i]->ReCheckSummaryLSAs(newTable);
00849             }
00850         }
00851     }
00852     CalculateASExternalRoutes(newTable);
00853 
00854     // backup the routing table
00855     unsigned long                         routeCount = routingTable.size();
00856     std::vector<OSPF::RoutingTableEntry*> oldTable;
00857 
00858     oldTable.assign(routingTable.begin(), routingTable.end());
00859     routingTable.clear();
00860     routingTable.assign(newTable.begin(), newTable.end());
00861 
00862     RoutingTableAccess         routingTableAccess;
00863     std::vector<const IPRoute*> eraseEntries;
00864     IRoutingTable*              simRoutingTable    = routingTableAccess.get();
00865     unsigned long              routingEntryNumber = simRoutingTable->getNumRoutes();
00866     // remove entries from the IP routing table inserted by the OSPF module
00867     for (i = 0; i < routingEntryNumber; i++) {
00868         const IPRoute *entry = simRoutingTable->getRoute(i);
00869         const OSPF::RoutingTableEntry* ospfEntry = dynamic_cast<const OSPF::RoutingTableEntry*>(entry);
00870         if (ospfEntry != NULL) {
00871             eraseEntries.push_back(entry);
00872         }
00873     }
00874 
00875     unsigned int eraseCount = eraseEntries.size();
00876     for (i = 0; i < eraseCount; i++) {
00877         simRoutingTable->deleteRoute(eraseEntries[i]);
00878     }
00879 
00880     // add the new routing entries
00881     routeCount = routingTable.size();
00882     for (i = 0; i < routeCount; i++) {
00883         if (routingTable[i]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) {
00884             simRoutingTable->addRoute(new OSPF::RoutingTableEntry(*(routingTable[i])));
00885         }
00886     }
00887 
00888     NotifyAboutRoutingTableChanges(oldTable);
00889 
00890     routeCount = oldTable.size();
00891     for (i = 0; i < routeCount; i++) {
00892         delete(oldTable[i]);
00893     }
00894 
00895     EV << "Routing table was rebuilt.\n"
00896        << "Results:\n";
00897 
00898     routeCount = routingTable.size();
00899     for (i = 0; i < routeCount; i++) {
00900         EV << *routingTable[i]
00901            << "\n";
00902     }
00903 }
00904 
00905 
00912 bool OSPF::Router::HasRouteToASBoundaryRouter(const std::vector<OSPF::RoutingTableEntry*>& inRoutingTable, OSPF::RouterID asbrRouterID) const
00913 {
00914     long routeCount = inRoutingTable.size();
00915     for (long i = 0; i < routeCount; i++) {
00916         OSPF::RoutingTableEntry* routingEntry = inRoutingTable[i];
00917         if (((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) &&
00918             (routingEntry->GetDestinationID().getInt() == asbrRouterID))
00919         {
00920             return true;
00921         }
00922     }
00923     return false;
00924 }
00925 
00926 
00934 std::vector<OSPF::RoutingTableEntry*> OSPF::Router::GetRoutesToASBoundaryRouter(const std::vector<OSPF::RoutingTableEntry*>& fromRoutingTable, OSPF::RouterID asbrRouterID) const
00935 {
00936     std::vector<OSPF::RoutingTableEntry*> results;
00937     long                                  routeCount = fromRoutingTable.size();
00938 
00939     for (long i = 0; i < routeCount; i++) {
00940         OSPF::RoutingTableEntry* routingEntry = fromRoutingTable[i];
00941         if (((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) &&
00942             (routingEntry->GetDestinationID().getInt() == asbrRouterID))
00943         {
00944             results.push_back(routingEntry);
00945         }
00946     }
00947     return results;
00948 }
00949 
00950 
00957 void OSPF::Router::PruneASBoundaryRouterEntries(std::vector<OSPF::RoutingTableEntry*>& asbrEntries) const
00958 {
00959     bool hasNonBackboneIntraAreaPath = false;
00960     for (std::vector<OSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin(); it != asbrEntries.end(); it++) {
00961         OSPF::RoutingTableEntry* routingEntry = *it;
00962         if ((routingEntry->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
00963             (routingEntry->GetArea() != OSPF::BackboneAreaID))
00964         {
00965             hasNonBackboneIntraAreaPath = true;
00966             break;
00967         }
00968     }
00969 
00970     if (hasNonBackboneIntraAreaPath) {
00971         std::vector<OSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin();
00972         while (it != asbrEntries.end()) {
00973             if (((*it)->GetPathType() != OSPF::RoutingTableEntry::IntraArea) ||
00974                 ((*it)->GetArea() == OSPF::BackboneAreaID))
00975             {
00976                 it = asbrEntries.erase(it);
00977             } else {
00978                 it++;
00979             }
00980         }
00981     }
00982 }
00983 
00984 
00991 OSPF::RoutingTableEntry* OSPF::Router::SelectLeastCostRoutingEntry(std::vector<OSPF::RoutingTableEntry*>& entries) const
00992 {
00993     if (entries.empty()) {
00994         return NULL;
00995     }
00996 
00997     OSPF::RoutingTableEntry* leastCostEntry = entries[0];
00998     Metric                   leastCost      = leastCostEntry->GetCost();
00999     long                     routeCount     = entries.size();
01000 
01001     for (long i = 1; i < routeCount; i++) {
01002         Metric currentCost = entries[i]->GetCost();
01003         if ((currentCost < leastCost) ||
01004             ((currentCost == leastCost) && (entries[i]->GetArea() > leastCostEntry->GetArea())))
01005         {
01006             leastCostEntry = entries[i];
01007             leastCost = currentCost;
01008         }
01009     }
01010 
01011     return leastCostEntry;
01012 }
01013 
01014 
01033 OSPF::RoutingTableEntry* OSPF::Router::GetPreferredEntry(const OSPFLSA& lsa, bool skipSelfOriginated, std::vector<OSPF::RoutingTableEntry*>* fromRoutingTable /*= NULL*/)
01034 {
01035     if (fromRoutingTable == NULL) {
01036         fromRoutingTable = &routingTable;
01037     }
01038 
01039     const OSPFLSAHeader&     lsaHeader         = lsa.getHeader();
01040     const OSPFASExternalLSA* asExternalLSA     = dynamic_cast<const OSPFASExternalLSA*> (&lsa);
01041     unsigned long            externalCost      = (asExternalLSA != NULL) ? asExternalLSA->getContents().getRouteCost() : 0;
01042     unsigned short           lsAge             = lsaHeader.getLsAge();
01043     OSPF::RouterID           originatingRouter = lsaHeader.getAdvertisingRouter().getInt();
01044     bool                     selfOriginated    = (originatingRouter == routerID);
01045     IPAddress                forwardingAddress; // 0.0.0.0
01046 
01047     if (asExternalLSA != NULL) {
01048         forwardingAddress = asExternalLSA->getContents().getForwardingAddress();
01049     }
01050 
01051     if ((externalCost == LS_INFINITY) || (lsAge == MAX_AGE) || (skipSelfOriginated && selfOriginated)) { // (1) and(2)
01052         return NULL;
01053     }
01054 
01055     if (!HasRouteToASBoundaryRouter(*fromRoutingTable, originatingRouter)) { // (3)
01056         return NULL;
01057     }
01058 
01059     if (forwardingAddress.isUnspecified()) {   // (3)
01060         std::vector<OSPF::RoutingTableEntry*> asbrEntries = GetRoutesToASBoundaryRouter(*fromRoutingTable, originatingRouter);
01061         if (!rfc1583Compatibility) {
01062             PruneASBoundaryRouterEntries(asbrEntries);
01063         }
01064         return SelectLeastCostRoutingEntry(asbrEntries);
01065     } else {
01066         OSPF::RoutingTableEntry* forwardEntry = Lookup(forwardingAddress, fromRoutingTable);
01067 
01068         if (forwardEntry == NULL) {
01069             return NULL;
01070         }
01071 
01072         if ((forwardEntry->GetPathType() != OSPF::RoutingTableEntry::IntraArea) &&
01073             (forwardEntry->GetPathType() != OSPF::RoutingTableEntry::InterArea))
01074         {
01075             return NULL;
01076         }
01077 
01078         return forwardEntry;
01079     }
01080 
01081     return NULL;
01082 }
01083 
01084 
01092 void OSPF::Router::CalculateASExternalRoutes(std::vector<OSPF::RoutingTableEntry*>& newRoutingTable)
01093 {
01094     unsigned long lsaCount = asExternalLSAs.size();
01095     unsigned long i;
01096 
01097     for (i = 0; i < lsaCount; i++) {
01098         OSPF::ASExternalLSA* currentLSA        = asExternalLSAs[i];
01099         OSPFLSAHeader&       currentHeader     = currentLSA->getHeader();
01100         unsigned short       externalCost      = currentLSA->getContents().getRouteCost();
01101         OSPF::RouterID       originatingRouter = currentHeader.getAdvertisingRouter().getInt();
01102 
01103         OSPF::RoutingTableEntry* preferredEntry = GetPreferredEntry(*currentLSA, true, &newRoutingTable);
01104         if (preferredEntry == NULL) {
01105             continue;
01106         }
01107 
01108         IPAddress destination = currentHeader.getLinkStateID() & currentLSA->getContents().getNetworkMask().getInt();
01109 
01110         Metric                   preferredCost    = preferredEntry->GetCost();
01111         OSPF::RoutingTableEntry* destinationEntry = Lookup(destination, &newRoutingTable);   // (5)
01112         if (destinationEntry == NULL) {
01113             bool                     type2ExternalMetric = currentLSA->getContents().getE_ExternalMetricType();
01114             unsigned int             nextHopCount        = preferredEntry->GetNextHopCount();
01115             OSPF::RoutingTableEntry* newEntry            = new OSPF::RoutingTableEntry;
01116 
01117             newEntry->SetDestinationID(destination);
01118             newEntry->SetAddressMask(currentLSA->getContents().getNetworkMask().getInt());
01119             newEntry->SetArea(preferredEntry->GetArea());
01120             newEntry->SetPathType(type2ExternalMetric ? OSPF::RoutingTableEntry::Type2External : OSPF::RoutingTableEntry::Type1External);
01121             if (type2ExternalMetric) {
01122                 newEntry->SetCost(preferredCost);
01123                 newEntry->SetType2Cost(externalCost);
01124             } else {
01125                 newEntry->SetCost(preferredCost + externalCost);
01126             }
01127             newEntry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
01128             newEntry->SetOptionalCapabilities(currentHeader.getLsOptions());
01129             newEntry->SetLinkStateOrigin(currentLSA);
01130 
01131             for (unsigned int j = 0; j < nextHopCount; j++) {
01132                 NextHop nextHop = preferredEntry->GetNextHop(j);
01133 
01134                 nextHop.advertisingRouter = originatingRouter;
01135                 newEntry->AddNextHop(nextHop);
01136             }
01137 
01138             newRoutingTable.push_back(newEntry);
01139         } else {
01140             OSPF::RoutingTableEntry::RoutingPathType destinationPathType = destinationEntry->GetPathType();
01141             bool                                     type2ExternalMetric = currentLSA->getContents().getE_ExternalMetricType();
01142             unsigned int                             nextHopCount        = preferredEntry->GetNextHopCount();
01143 
01144             if ((destinationPathType == OSPF::RoutingTableEntry::IntraArea) ||
01145                 (destinationPathType == OSPF::RoutingTableEntry::InterArea))   // (6) (a)
01146             {
01147                 continue;
01148             }
01149 
01150             if (((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01151                  (type2ExternalMetric)) ||
01152                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01153                  (type2ExternalMetric) &&
01154                  (destinationEntry->GetType2Cost() < externalCost))) // (6) (b)
01155             {
01156                 continue;
01157             }
01158 
01159             OSPF::RoutingTableEntry* destinationPreferredEntry = GetPreferredEntry(*(destinationEntry->GetLinkStateOrigin()), false, &newRoutingTable);
01160             if ((!rfc1583Compatibility) &&
01161                 (destinationPreferredEntry->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
01162                 (destinationPreferredEntry->GetArea() != OSPF::BackboneAreaID) &&
01163                 ((preferredEntry->GetPathType() != OSPF::RoutingTableEntry::IntraArea) ||
01164                  (preferredEntry->GetArea() == OSPF::BackboneAreaID)))
01165             {
01166                 continue;
01167             }
01168 
01169             if ((((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01170                   (!type2ExternalMetric) &&
01171                   (destinationEntry->GetCost() < preferredCost + externalCost))) ||
01172                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01173                  (type2ExternalMetric) &&
01174                  (destinationEntry->GetType2Cost() == externalCost) &&
01175                  (destinationPreferredEntry->GetCost() < preferredCost)))
01176             {
01177                 continue;
01178             }
01179 
01180             if (((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01181                  (!type2ExternalMetric) &&
01182                  (destinationEntry->GetCost() == (preferredCost + externalCost))) ||
01183                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01184                  (type2ExternalMetric) &&
01185                  (destinationEntry->GetType2Cost() == externalCost) &&
01186                  (destinationPreferredEntry->GetCost() == preferredCost)))   // equal cost
01187             {
01188                 for (unsigned int j = 0; j < nextHopCount; j++) {
01189                     // TODO: merge next hops, not add
01190                     NextHop nextHop = preferredEntry->GetNextHop(j);
01191 
01192                     nextHop.advertisingRouter = originatingRouter;
01193                     destinationEntry->AddNextHop(nextHop);
01194                 }
01195                 continue;
01196             }
01197 
01198             // LSA is better
01199             destinationEntry->SetArea(preferredEntry->GetArea());
01200             destinationEntry->SetPathType(type2ExternalMetric ? OSPF::RoutingTableEntry::Type2External : OSPF::RoutingTableEntry::Type1External);
01201             if (type2ExternalMetric) {
01202                 destinationEntry->SetCost(preferredCost);
01203                 destinationEntry->SetType2Cost(externalCost);
01204             } else {
01205                 destinationEntry->SetCost(preferredCost + externalCost);
01206             }
01207             destinationEntry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
01208             destinationEntry->SetOptionalCapabilities(currentHeader.getLsOptions());
01209             destinationEntry->ClearNextHops();
01210 
01211             for (unsigned int j = 0; j < nextHopCount; j++) {
01212                 NextHop nextHop = preferredEntry->GetNextHop(j);
01213 
01214                 nextHop.advertisingRouter = originatingRouter;
01215                 destinationEntry->AddNextHop(nextHop);
01216             }
01217         }
01218     }
01219 }
01220 
01221 
01231 OSPF::IPv4AddressRange OSPF::Router::GetContainingAddressRange(OSPF::IPv4AddressRange addressRange, bool* advertise /*= NULL*/) const
01232 {
01233     unsigned long areaCount = areas.size();
01234     for (unsigned long i = 0; i < areaCount; i++) {
01235         OSPF::IPv4AddressRange containingAddressRange = areas[i]->GetContainingAddressRange(addressRange, advertise);
01236         if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01237             return containingAddressRange;
01238         }
01239     }
01240     if (advertise != NULL) {
01241         *advertise = false;
01242     }
01243     return OSPF::NullIPv4AddressRange;
01244 }
01245 
01246 
01262 OSPF::LinkStateID OSPF::Router::GetUniqueLinkStateID(OSPF::IPv4AddressRange destination,
01263                                                       OSPF::Metric destinationCost,
01264                                                       OSPF::ASExternalLSA*& lsaToReoriginate,
01265                                                       bool externalMetricIsType2 /*= false*/) const
01266 {
01267     if (lsaToReoriginate != NULL) {
01268         delete lsaToReoriginate;
01269         lsaToReoriginate = NULL;
01270     }
01271 
01272     OSPF::LSAKeyType lsaKey;
01273 
01274     lsaKey.linkStateID = ULongFromIPv4Address(destination.address);
01275     lsaKey.advertisingRouter = routerID;
01276 
01277     const OSPF::ASExternalLSA* foundLSA = FindASExternalLSA(lsaKey);
01278 
01279     if (foundLSA == NULL) {
01280         return lsaKey.linkStateID;
01281     } else {
01282         OSPF::IPv4Address existingMask = IPv4AddressFromULong(foundLSA->getContents().getNetworkMask().getInt());
01283 
01284         if (destination.mask >= existingMask) {
01285             return (lsaKey.linkStateID | (~(ULongFromIPv4Address(destination.mask))));
01286         } else {
01287             OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA(*foundLSA);
01288 
01289             long sequenceNumber = asExternalLSA->getHeader().getLsSequenceNumber();
01290 
01291             asExternalLSA->getHeader().setLsAge(0);
01292             asExternalLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
01293             asExternalLSA->getContents().setNetworkMask(ULongFromIPv4Address(destination.mask));
01294             asExternalLSA->getContents().setE_ExternalMetricType(externalMetricIsType2);
01295             asExternalLSA->getContents().setRouteCost(destinationCost);
01296             asExternalLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
01297 
01298             lsaToReoriginate = asExternalLSA;
01299 
01300             return (lsaKey.linkStateID | (~(ULongFromIPv4Address(existingMask))));
01301         }
01302     }
01303 }
01304 
01305 
01314 // TODO: review this algorithm + add virtual link changes(RFC2328 Section 16.7.).
01315 void OSPF::Router::NotifyAboutRoutingTableChanges(std::vector<OSPF::RoutingTableEntry*>& oldRoutingTable)
01316 {
01317     if (areas.size() <= 1) {
01318         return;
01319     }
01320 
01321     unsigned long                                 routeCount = oldRoutingTable.size();
01322     std::map<unsigned long, RoutingTableEntry*>   oldTableMap;
01323     std::map<unsigned long, RoutingTableEntry*>   newTableMap;
01324     unsigned long                                 i, j, k;
01325 
01326     for (i = 0; i < routeCount; i++) {
01327         unsigned long destination = oldRoutingTable[i]->GetDestinationID().getInt() & oldRoutingTable[i]->GetAddressMask().getInt();
01328         oldTableMap[destination] = oldRoutingTable[i];
01329     }
01330 
01331     routeCount = routingTable.size();
01332     for (i = 0; i < routeCount; i++) {
01333         unsigned long   destination = routingTable[i]->GetDestinationID().getInt() & routingTable[i]->GetAddressMask().getInt();
01334         newTableMap[destination] = routingTable[i];
01335     }
01336 
01337     unsigned long areaCount = areas.size();
01338     for (i = 0; i < areaCount; i++) {
01339         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less> originatedLSAMap;
01340         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less> deletedLSAMap;
01341         OSPF::LSAKeyType                                        lsaKey;
01342 
01343         routeCount = routingTable.size();
01344         for (j = 0; j < routeCount; j++) {
01345             unsigned long                                         destination = routingTable[j]->GetDestinationID().getInt() & routingTable[j]->GetAddressMask().getInt();
01346             std::map<unsigned long, RoutingTableEntry*>::iterator destIt      = oldTableMap.find(destination);
01347             if (destIt == oldTableMap.end()) { // new routing entry
01348                 OSPF::SummaryLSA* lsaToReoriginate = NULL;
01349                 OSPF::SummaryLSA* newLSA           = areas[i]->OriginateSummaryLSA(routingTable[j], originatedLSAMap, lsaToReoriginate);
01350 
01351                 if (newLSA != NULL) {
01352                     if (lsaToReoriginate != NULL) {
01353                         areas[i]->InstallSummaryLSA(lsaToReoriginate);
01354 //                        FloodLSA(lsaToReoriginate, OSPF::BackboneAreaID);
01355                         FloodLSA(lsaToReoriginate, areas[i]->GetAreaID());
01356 
01357                         lsaKey.linkStateID       = lsaToReoriginate->getHeader().getLinkStateID();
01358                         lsaKey.advertisingRouter = routerID;
01359                         originatedLSAMap[lsaKey] = true;
01360 
01361                         delete lsaToReoriginate;
01362                     }
01363 
01364                     areas[i]->InstallSummaryLSA(newLSA);
01365 //                    FloodLSA(newLSA, OSPF::BackboneAreaID);
01366                     FloodLSA(newLSA, areas[i]->GetAreaID());
01367 
01368                     lsaKey.linkStateID       = newLSA->getHeader().getLinkStateID();
01369                     lsaKey.advertisingRouter = routerID;
01370                     originatedLSAMap[lsaKey] = true;
01371 
01372                     delete newLSA;
01373                 }
01374             } else {
01375                 if (*(routingTable[j]) != *(destIt->second)) {  // modified routing entry
01376                     OSPF::SummaryLSA* lsaToReoriginate = NULL;
01377                     OSPF::SummaryLSA* newLSA           = areas[i]->OriginateSummaryLSA(routingTable[j], originatedLSAMap, lsaToReoriginate);
01378 
01379                     if (newLSA != NULL) {
01380                         if (lsaToReoriginate != NULL) {
01381                             areas[i]->InstallSummaryLSA(lsaToReoriginate);
01382 //                            FloodLSA(lsaToReoriginate, OSPF::BackboneAreaID);
01383                             FloodLSA(lsaToReoriginate, areas[i]->GetAreaID());
01384 
01385                             lsaKey.linkStateID       = lsaToReoriginate->getHeader().getLinkStateID();
01386                             lsaKey.advertisingRouter = routerID;
01387                             originatedLSAMap[lsaKey] = true;
01388 
01389                             delete lsaToReoriginate;
01390                         }
01391 
01392                         areas[i]->InstallSummaryLSA(newLSA);
01393 //                        FloodLSA(newLSA, OSPF::BackboneAreaID);
01394                         FloodLSA(newLSA, areas[i]->GetAreaID());
01395 
01396                         lsaKey.linkStateID       = newLSA->getHeader().getLinkStateID();
01397                         lsaKey.advertisingRouter = routerID;
01398                         originatedLSAMap[lsaKey] = true;
01399 
01400                         delete newLSA;
01401                     } else {
01402                         OSPF::IPv4AddressRange destinationAddressRange;
01403 
01404                         destinationAddressRange.address = IPv4AddressFromULong(routingTable[j]->GetDestinationID().getInt());
01405                         destinationAddressRange.mask = IPv4AddressFromULong(routingTable[j]->GetAddressMask().getInt());
01406 
01407                         if ((routingTable[j]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01408                             ((routingTable[j]->GetPathType() == OSPF::RoutingTableEntry::IntraArea) ||
01409                              (routingTable[j]->GetPathType() == OSPF::RoutingTableEntry::InterArea)))
01410                         {
01411                             OSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange(destinationAddressRange);
01412                             if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01413                                 destinationAddressRange = containingAddressRange;
01414                             }
01415                         }
01416 
01417                         Metric maxRangeCost = 0;
01418                         Metric oneLessCost  = 0;
01419 
01420                         for (k = 0; k < routeCount; k++) {
01421                             if ((routingTable[k]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01422                                 (routingTable[k]->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
01423                                 ((routingTable[k]->GetDestinationID().getInt() & routingTable[k]->GetAddressMask().getInt() & ULongFromIPv4Address(destinationAddressRange.mask)) ==
01424                                  ULongFromIPv4Address(destinationAddressRange.address & destinationAddressRange.mask)) &&
01425                                 (routingTable[k]->GetCost() > maxRangeCost))
01426                             {
01427                                 oneLessCost  = maxRangeCost;
01428                                 maxRangeCost = routingTable[k]->GetCost();
01429                             }
01430                         }
01431 
01432                         if (maxRangeCost == routingTable[j]->GetCost()) {  // this entry gives the range's cost
01433                             lsaKey.linkStateID       = ULongFromIPv4Address(destinationAddressRange.address);
01434                             lsaKey.advertisingRouter = routerID;
01435 
01436                             OSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA(lsaKey);
01437 
01438                             if (summaryLSA != NULL) {
01439                                 if (oneLessCost != 0) { // there's an other entry in this range
01440                                     summaryLSA->setRouteCost(oneLessCost);
01441 //                                    FloodLSA(summaryLSA, OSPF::BackboneAreaID);
01442                                     FloodLSA(summaryLSA, areas[i]->GetAreaID());
01443 
01444                                     originatedLSAMap[lsaKey] = true;
01445                                 } else {    // no more entries in this range -> delete it
01446                                     std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find(lsaKey);
01447                                     if (deletedIt == deletedLSAMap.end()) {
01448                                         summaryLSA->getHeader().setLsAge(MAX_AGE);
01449 //                                        FloodLSA(summaryLSA, OSPF::BackboneAreaID);
01450                                         FloodLSA(summaryLSA, areas[i]->GetAreaID());
01451 
01452                                         deletedLSAMap[lsaKey]    = true;
01453                                     }
01454                                 }
01455                             }
01456                         }
01457                     }
01458                 }
01459             }
01460         }
01461 
01462         routeCount = oldRoutingTable.size();
01463         for (j = 0; j < routeCount; j++) {
01464             unsigned long                                         destination = oldRoutingTable[j]->GetDestinationID().getInt() & oldRoutingTable[j]->GetAddressMask().getInt();
01465             std::map<unsigned long, RoutingTableEntry*>::iterator destIt      = newTableMap.find(destination);
01466             if (destIt == newTableMap.end()) { // deleted routing entry
01467                 OSPF::IPv4AddressRange destinationAddressRange;
01468 
01469                 destinationAddressRange.address = IPv4AddressFromULong(oldRoutingTable[j]->GetDestinationID().getInt());
01470                 destinationAddressRange.mask = IPv4AddressFromULong(oldRoutingTable[j]->GetAddressMask().getInt());
01471 
01472                 if ((oldRoutingTable[j]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01473                     ((oldRoutingTable[j]->GetPathType() == OSPF::RoutingTableEntry::IntraArea) ||
01474                      (oldRoutingTable[j]->GetPathType() == OSPF::RoutingTableEntry::InterArea)))
01475                 {
01476                     OSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange(destinationAddressRange);
01477                     if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01478                         destinationAddressRange = containingAddressRange;
01479                     }
01480                 }
01481 
01482                 Metric maxRangeCost = 0;
01483 
01484                 unsigned long newRouteCount = routingTable.size();
01485                 for (k = 0; k < newRouteCount; k++) {
01486                     if ((routingTable[k]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01487                         (routingTable[k]->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
01488                         ((routingTable[k]->GetDestinationID().getInt() & routingTable[k]->GetAddressMask().getInt() & ULongFromIPv4Address(destinationAddressRange.mask)) ==
01489                          ULongFromIPv4Address(destinationAddressRange.address & destinationAddressRange.mask)) &&
01490                         (routingTable[k]->GetCost() > maxRangeCost))
01491                     {
01492                         maxRangeCost = routingTable[k]->GetCost();
01493                     }
01494                 }
01495 
01496                 if (maxRangeCost < oldRoutingTable[j]->GetCost()) {  // the range's cost will change
01497                     lsaKey.linkStateID       = ULongFromIPv4Address(destinationAddressRange.address);
01498                     lsaKey.advertisingRouter = routerID;
01499 
01500                     OSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA(lsaKey);
01501 
01502                     if (summaryLSA != NULL) {
01503                         if (maxRangeCost > 0) { // there's an other entry in this range
01504                             summaryLSA->setRouteCost(maxRangeCost);
01505                             FloodLSA(summaryLSA, OSPF::BackboneAreaID);
01506 
01507                             originatedLSAMap[lsaKey] = true;
01508                         } else {    // no more entries in this range -> delete it
01509                             std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find(lsaKey);
01510                             if (deletedIt == deletedLSAMap.end()) {
01511                                 summaryLSA->getHeader().setLsAge(MAX_AGE);
01512                                 FloodLSA(summaryLSA, OSPF::BackboneAreaID);
01513 
01514                                 deletedLSAMap[lsaKey]    = true;
01515                             }
01516                         }
01517                     }
01518                 }
01519             }
01520         }
01521     }
01522 }
01523 
01524 
01532 void OSPF::Router::UpdateExternalRoute(OSPF::IPv4Address networkAddress, const OSPFASExternalLSAContents& externalRouteContents, int ifIndex)
01533 {
01534     OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA;
01535     OSPFLSAHeader&       lsaHeader     = asExternalLSA->getHeader();
01536     OSPFOptions          lsaOptions;
01537     //OSPF::LSAKeyType     lsaKey;
01538 
01539     IRoutingTable*      simRoutingTable    = RoutingTableAccess().get();
01540     unsigned long      routingEntryNumber = simRoutingTable->getNumRoutes();
01541     bool               inRoutingTable     = false;
01542     // add the external route to the routing table if it was not added by another module
01543     for (unsigned long i = 0; i < routingEntryNumber; i++) {
01544         const IPRoute *entry = simRoutingTable->getRoute(i);
01545         if ((entry->getHost().getInt() & entry->getNetmask().getInt()) ==
01546             (ULongFromIPv4Address(networkAddress) & externalRouteContents.getNetworkMask().getInt()))
01547         {
01548             inRoutingTable = true;
01549         }
01550     }
01551     if (!inRoutingTable) {
01552         IPRoute* entry = new IPRoute;
01553         entry->setHost(ULongFromIPv4Address(networkAddress));
01554         entry->setNetmask(externalRouteContents.getNetworkMask());
01555         entry->setInterface(InterfaceTableAccess().get()->getInterfaceById(ifIndex));
01556         entry->setType(IPRoute::REMOTE);
01557         entry->setSource(IPRoute::MANUAL);
01558         entry->setMetric(externalRouteContents.getRouteCost());
01559         simRoutingTable->addRoute(entry);   // IRoutingTable deletes entry pointer
01560     }
01561 
01562     lsaHeader.setLsAge(0);
01563     memset(&lsaOptions, 0, sizeof(OSPFOptions));
01564     lsaOptions.E_ExternalRoutingCapability = true;
01565     lsaHeader.setLsOptions(lsaOptions);
01566     lsaHeader.setLsType(ASExternalLSAType);
01567     lsaHeader.setLinkStateID(ULongFromIPv4Address(networkAddress));   // TODO: get unique LinkStateID
01568     lsaHeader.setAdvertisingRouter(routerID);
01569     lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01570 
01571     asExternalLSA->setContents(externalRouteContents);
01572 
01573     lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01574 
01575     asExternalLSA->SetSource(OSPF::LSATrackingInfo::Originated);
01576 
01577     externalRoutes[networkAddress] = externalRouteContents;
01578 
01579     bool rebuild = InstallASExternalLSA(asExternalLSA);
01580     FloodLSA(asExternalLSA, OSPF::BackboneAreaID);
01581     delete asExternalLSA;
01582 
01583     if (rebuild) {
01584         RebuildRoutingTable();
01585     }
01586 }
01587 
01588 
01594 void OSPF::Router::RemoveExternalRoute(OSPF::IPv4Address networkAddress)
01595 {
01596     OSPF::LSAKeyType     lsaKey;
01597 
01598     lsaKey.linkStateID = ULongFromIPv4Address(networkAddress);
01599     lsaKey.advertisingRouter = routerID;
01600 
01601     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find(lsaKey);
01602     if (lsaIt != asExternalLSAsByID.end()) {
01603         lsaIt->second->getHeader().setLsAge(MAX_AGE);
01604         lsaIt->second->SetPurgeable();
01605         FloodLSA(lsaIt->second, OSPF::BackboneAreaID);
01606     }
01607 
01608     std::map<OSPF::IPv4Address, OSPFASExternalLSAContents, OSPF::IPv4Address_Less>::iterator externalIt = externalRoutes.find(networkAddress);
01609     if (externalIt != externalRoutes.end()) {
01610         externalRoutes.erase(externalIt);
01611     }
01612 }