OSPFArea.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 "OSPFArea.h"
00019 #include "OSPFRouter.h"
00020 #include <memory.h>
00021 
00022 OSPF::Area::Area(OSPF::AreaID id) :
00023     areaID(id),
00024     transitCapability(false),
00025     externalRoutingCapability(true),
00026     stubDefaultCost(1),
00027     spfTreeRoot(NULL),
00028     parentRouter(NULL)
00029 {
00030 }
00031 
00032 OSPF::Area::~Area(void)
00033 {
00034     int interfaceNum = associatedInterfaces.size();
00035     for (int i = 0; i < interfaceNum; i++) {
00036         delete(associatedInterfaces[i]);
00037     }
00038     long lsaCount = routerLSAs.size();
00039     for (long j = 0; j < lsaCount; j++) {
00040         delete routerLSAs[j];
00041     }
00042     routerLSAs.clear();
00043     lsaCount = networkLSAs.size();
00044     for (long k = 0; k < lsaCount; k++) {
00045         delete networkLSAs[k];
00046     }
00047     networkLSAs.clear();
00048     lsaCount = summaryLSAs.size();
00049     for (long m = 0; m < lsaCount; m++) {
00050         delete summaryLSAs[m];
00051     }
00052     summaryLSAs.clear();
00053 }
00054 
00055 void OSPF::Area::AddInterface(OSPF::Interface* intf)
00056 {
00057     intf->SetArea(this);
00058     associatedInterfaces.push_back(intf);
00059 }
00060 
00061 void OSPF::Area::info(char *buffer)
00062 {
00063     std::stringstream out;
00064     char areaString[16];
00065     out << "areaID: " << AddressStringFromULong(areaString, 16, areaID);
00066     strcpy(buffer, out.str().c_str());
00067 }
00068 
00069 std::string OSPF::Area::detailedInfo(void) const
00070 {
00071     std::stringstream out;
00072     char addressString[16];
00073     int i;
00074     out << "\n    areaID: " << AddressStringFromULong(addressString, 16, areaID) << ", ";
00075     out << "transitCapability: " << (transitCapability ? "true" : "false") << ", ";
00076     out << "externalRoutingCapability: " << (externalRoutingCapability ? "true" : "false") << ", ";
00077     out << "stubDefaultCost: " << stubDefaultCost << "\n";
00078     int addressRangeNum = areaAddressRanges.size();
00079     for (i = 0; i < addressRangeNum; i++) {
00080         out << "    addressRanges[" << i << "]: ";
00081         out << AddressStringFromIPv4Address(addressString, 16, areaAddressRanges[i].address);
00082         out << "/" << AddressStringFromIPv4Address(addressString, 16, areaAddressRanges[i].mask) << "\n";
00083     }
00084     int interfaceNum = associatedInterfaces.size();
00085     for (i = 0; i < interfaceNum; i++) {
00086         out << "    interface[" << i << "]: addressRange: ";
00087         out << AddressStringFromIPv4Address(addressString, 16, associatedInterfaces[i]->GetAddressRange().address);
00088         out << "/" << AddressStringFromIPv4Address(addressString, 16, associatedInterfaces[i]->GetAddressRange().mask) << "\n";
00089     }
00090 
00091     out << "\n";
00092     out << "    Database:\n";
00093     out << "      RouterLSAs:\n";
00094     long lsaCount = routerLSAs.size();
00095     for (i = 0; i < lsaCount; i++) {
00096         out << "        " << *routerLSAs[i] << "\n";
00097     }
00098     out << "      NetworkLSAs:\n";
00099     lsaCount = networkLSAs.size();
00100     for (i = 0; i < lsaCount; i++) {
00101         out << "        " << *networkLSAs[i] << "\n";
00102     }
00103     out << "      SummaryLSAs:\n";
00104     lsaCount = summaryLSAs.size();
00105     for (i = 0; i < lsaCount; i++) {
00106         out << "        " << *summaryLSAs[i] << "\n";
00107     }
00108 
00109     out << "--------------------------------------------------------------------------------";
00110 
00111     return out.str();
00112 }
00113 
00114 bool OSPF::Area::ContainsAddress(OSPF::IPv4Address address) const
00115 {
00116     int addressRangeNum = areaAddressRanges.size();
00117     for (int i = 0; i < addressRangeNum; i++) {
00118         if ((areaAddressRanges[i].address & areaAddressRanges[i].mask) == (address & areaAddressRanges[i].mask)) {
00119             return true;
00120         }
00121     }
00122     return false;
00123 }
00124 
00125 bool OSPF::Area::HasAddressRange(OSPF::IPv4AddressRange addressRange) const
00126 {
00127     int addressRangeNum = areaAddressRanges.size();
00128     for (int i = 0; i < addressRangeNum; i++) {
00129         if ((areaAddressRanges[i].address == addressRange.address) &&
00130             (areaAddressRanges[i].mask == addressRange.mask))
00131         {
00132             return true;
00133         }
00134     }
00135     return false;
00136 }
00137 
00138 OSPF::IPv4AddressRange OSPF::Area::GetContainingAddressRange(OSPF::IPv4AddressRange addressRange, bool* advertise /*= NULL*/) const
00139 {
00140     int addressRangeNum = areaAddressRanges.size();
00141     for (int i = 0; i < addressRangeNum; i++) {
00142         if ((areaAddressRanges[i].address & areaAddressRanges[i].mask) == (addressRange.address & areaAddressRanges[i].mask)) {
00143             if (advertise != NULL) {
00144                 std::map<OSPF::IPv4AddressRange, bool, OSPF::IPv4AddressRange_Less>::const_iterator rangeIt = advertiseAddressRanges.find(areaAddressRanges[i]);
00145                 if (rangeIt != advertiseAddressRanges.end()) {
00146                     *advertise = rangeIt->second;
00147                 } else {
00148                     *advertise = true;
00149                 }
00150             }
00151             return areaAddressRanges[i];
00152         }
00153     }
00154     if (advertise != NULL) {
00155         *advertise =  false;
00156     }
00157     return NullIPv4AddressRange;
00158 }
00159 
00160 OSPF::Interface*  OSPF::Area::GetInterface(unsigned char ifIndex)
00161 {
00162     int interfaceNum = associatedInterfaces.size();
00163     for (int i = 0; i < interfaceNum; i++) {
00164         if ((associatedInterfaces[i]->GetType() != OSPF::Interface::Virtual) &&
00165             (associatedInterfaces[i]->GetIfIndex() == ifIndex))
00166         {
00167             return associatedInterfaces[i];
00168         }
00169     }
00170     return NULL;
00171 }
00172 
00173 OSPF::Interface*  OSPF::Area::GetInterface(OSPF::IPv4Address address)
00174 {
00175     int interfaceNum = associatedInterfaces.size();
00176     for (int i = 0; i < interfaceNum; i++) {
00177         if ((associatedInterfaces[i]->GetType() != OSPF::Interface::Virtual) &&
00178             (associatedInterfaces[i]->GetAddressRange().address == address))
00179         {
00180             return associatedInterfaces[i];
00181         }
00182     }
00183     return NULL;
00184 }
00185 
00186 bool OSPF::Area::HasVirtualLink(OSPF::AreaID withTransitArea) const
00187 {
00188     if ((areaID != OSPF::BackboneAreaID) || (withTransitArea == OSPF::BackboneAreaID)) {
00189         return false;
00190     }
00191 
00192     int interfaceNum = associatedInterfaces.size();
00193     for (int i = 0; i < interfaceNum; i++) {
00194         if ((associatedInterfaces[i]->GetType() == OSPF::Interface::Virtual) &&
00195             (associatedInterfaces[i]->GetTransitAreaID() == withTransitArea))
00196         {
00197             return true;
00198         }
00199     }
00200     return false;
00201 }
00202 
00203 
00204 OSPF::Interface*  OSPF::Area::FindVirtualLink(OSPF::RouterID routerID)
00205 {
00206     int interfaceNum = associatedInterfaces.size();
00207     for (int i = 0; i < interfaceNum; i++) {
00208         if ((associatedInterfaces[i]->GetType() == OSPF::Interface::Virtual) &&
00209             (associatedInterfaces[i]->GetNeighborByID(routerID) != NULL))
00210         {
00211             return associatedInterfaces[i];
00212         }
00213     }
00214     return NULL;
00215 }
00216 
00217 bool OSPF::Area::InstallRouterLSA(OSPFRouterLSA* lsa)
00218 {
00219     OSPF::LinkStateID linkStateID = lsa->getHeader().getLinkStateID();
00220     std::map<OSPF::LinkStateID, OSPF::RouterLSA*>::iterator lsaIt = routerLSAsByID.find(linkStateID);
00221     if (lsaIt != routerLSAsByID.end()) {
00222         OSPF::LSAKeyType lsaKey;
00223 
00224         lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00225         lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00226 
00227         RemoveFromAllRetransmissionLists(lsaKey);
00228         return lsaIt->second->Update(lsa);
00229     } else {
00230         OSPF::RouterLSA* lsaCopy = new OSPF::RouterLSA(*lsa);
00231         routerLSAsByID[linkStateID] = lsaCopy;
00232         routerLSAs.push_back(lsaCopy);
00233         return true;
00234     }
00235 }
00236 
00237 bool OSPF::Area::InstallNetworkLSA(OSPFNetworkLSA* lsa)
00238 {
00239     OSPF::LinkStateID linkStateID = lsa->getHeader().getLinkStateID();
00240     std::map<OSPF::LinkStateID, OSPF::NetworkLSA*>::iterator lsaIt = networkLSAsByID.find(linkStateID);
00241     if (lsaIt != networkLSAsByID.end()) {
00242         OSPF::LSAKeyType lsaKey;
00243 
00244         lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00245         lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00246 
00247         RemoveFromAllRetransmissionLists(lsaKey);
00248         return lsaIt->second->Update(lsa);
00249     } else {
00250         OSPF::NetworkLSA* lsaCopy = new OSPF::NetworkLSA(*lsa);
00251         networkLSAsByID[linkStateID] = lsaCopy;
00252         networkLSAs.push_back(lsaCopy);
00253         return true;
00254     }
00255 }
00256 
00257 bool OSPF::Area::InstallSummaryLSA(OSPFSummaryLSA* lsa)
00258 {
00259     OSPF::LSAKeyType lsaKey;
00260 
00261     lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00262     lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00263 
00264     std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = summaryLSAsByID.find(lsaKey);
00265     if (lsaIt != summaryLSAsByID.end()) {
00266         OSPF::LSAKeyType lsaKey;
00267 
00268         lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00269         lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00270 
00271         RemoveFromAllRetransmissionLists(lsaKey);
00272         return lsaIt->second->Update(lsa);
00273     } else {
00274         OSPF::SummaryLSA* lsaCopy = new OSPF::SummaryLSA(*lsa);
00275         summaryLSAsByID[lsaKey] = lsaCopy;
00276         summaryLSAs.push_back(lsaCopy);
00277         return true;
00278     }
00279 }
00280 
00281 OSPF::RouterLSA* OSPF::Area::FindRouterLSA(OSPF::LinkStateID linkStateID)
00282 {
00283     std::map<OSPF::LinkStateID, OSPF::RouterLSA*>::iterator lsaIt = routerLSAsByID.find(linkStateID);
00284     if (lsaIt != routerLSAsByID.end()) {
00285         return lsaIt->second;
00286     } else {
00287         return NULL;
00288     }
00289 }
00290 
00291 const OSPF::RouterLSA* OSPF::Area::FindRouterLSA(OSPF::LinkStateID linkStateID) const
00292 {
00293     std::map<OSPF::LinkStateID, OSPF::RouterLSA*>::const_iterator lsaIt = routerLSAsByID.find(linkStateID);
00294     if (lsaIt != routerLSAsByID.end()) {
00295         return lsaIt->second;
00296     } else {
00297         return NULL;
00298     }
00299 }
00300 
00301 OSPF::NetworkLSA* OSPF::Area::FindNetworkLSA(OSPF::LinkStateID linkStateID)
00302 {
00303     std::map<OSPF::LinkStateID, OSPF::NetworkLSA*>::iterator lsaIt = networkLSAsByID.find(linkStateID);
00304     if (lsaIt != networkLSAsByID.end()) {
00305         return lsaIt->second;
00306     } else {
00307         return NULL;
00308     }
00309 }
00310 
00311 const OSPF::NetworkLSA* OSPF::Area::FindNetworkLSA(OSPF::LinkStateID linkStateID) const
00312 {
00313     std::map<OSPF::LinkStateID, OSPF::NetworkLSA*>::const_iterator lsaIt = networkLSAsByID.find(linkStateID);
00314     if (lsaIt != networkLSAsByID.end()) {
00315         return lsaIt->second;
00316     } else {
00317         return NULL;
00318     }
00319 }
00320 
00321 OSPF::SummaryLSA* OSPF::Area::FindSummaryLSA(OSPF::LSAKeyType lsaKey)
00322 {
00323     std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = summaryLSAsByID.find(lsaKey);
00324     if (lsaIt != summaryLSAsByID.end()) {
00325         return lsaIt->second;
00326     } else {
00327         return NULL;
00328     }
00329 }
00330 
00331 const OSPF::SummaryLSA* OSPF::Area::FindSummaryLSA(OSPF::LSAKeyType lsaKey) const
00332 {
00333     std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::const_iterator lsaIt = summaryLSAsByID.find(lsaKey);
00334     if (lsaIt != summaryLSAsByID.end()) {
00335         return lsaIt->second;
00336     } else {
00337         return NULL;
00338     }
00339 }
00340 
00341 void OSPF::Area::AgeDatabase(void)
00342 {
00343     long            lsaCount            = routerLSAs.size();
00344     bool            rebuildRoutingTable = false;
00345     long            i;
00346 
00347     for (i = 0; i < lsaCount; i++) {
00348         unsigned short   lsAge          = routerLSAs[i]->getHeader().getLsAge();
00349         bool             selfOriginated = (routerLSAs[i]->getHeader().getAdvertisingRouter().getInt() == parentRouter->GetRouterID());
00350         bool             unreachable    = parentRouter->IsDestinationUnreachable(routerLSAs[i]);
00351         OSPF::RouterLSA* lsa            = routerLSAs[i];
00352 
00353         if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) {
00354             lsa->getHeader().setLsAge(lsAge + 1);
00355             if ((lsAge + 1) % CHECK_AGE == 0) {
00356                 if (!lsa->ValidateLSChecksum()) {
00357                     EV << "Invalid LS checksum. Memory error detected!\n";
00358                 }
00359             }
00360             lsa->IncrementInstallTime();
00361         }
00362         if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) {
00363             if (unreachable) {
00364                 lsa->getHeader().setLsAge(MAX_AGE);
00365                 FloodLSA(lsa);
00366                 lsa->IncrementInstallTime();
00367             } else {
00368                 long sequenceNumber = lsa->getHeader().getLsSequenceNumber();
00369                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00370                     lsa->getHeader().setLsAge(MAX_AGE);
00371                     FloodLSA(lsa);
00372                     lsa->IncrementInstallTime();
00373                 } else {
00374                     OSPF::RouterLSA* newLSA = OriginateRouterLSA();
00375 
00376                     newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00377                     newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00378                     rebuildRoutingTable |= lsa->Update(newLSA);
00379                     delete newLSA;
00380 
00381                     FloodLSA(lsa);
00382                 }
00383             }
00384         }
00385         if (!selfOriginated && (lsAge == MAX_AGE - 1)) {
00386             lsa->getHeader().setLsAge(MAX_AGE);
00387             FloodLSA(lsa);
00388             lsa->IncrementInstallTime();
00389         }
00390         if (lsAge == MAX_AGE) {
00391             OSPF::LSAKeyType lsaKey;
00392 
00393             lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00394             lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00395 
00396             if (!IsOnAnyRetransmissionList(lsaKey) &&
00397                 !HasAnyNeighborInStates(OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState))
00398             {
00399                 if (!selfOriginated || unreachable) {
00400                     routerLSAsByID.erase(lsa->getHeader().getLinkStateID());
00401                     delete lsa;
00402                     routerLSAs[i] = NULL;
00403                     rebuildRoutingTable = true;
00404                 } else {
00405                     OSPF::RouterLSA* newLSA              = OriginateRouterLSA();
00406                     long             sequenceNumber      = lsa->getHeader().getLsSequenceNumber();
00407 
00408                     newLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
00409                     newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00410                     rebuildRoutingTable |= lsa->Update(newLSA);
00411                     delete newLSA;
00412 
00413                     FloodLSA(lsa);
00414                 }
00415             }
00416         }
00417     }
00418 
00419     std::vector<RouterLSA*>::iterator routerIt = routerLSAs.begin();
00420     while (routerIt != routerLSAs.end()) {
00421         if ((*routerIt) == NULL) {
00422             routerIt = routerLSAs.erase(routerIt);
00423         } else {
00424             routerIt++;
00425         }
00426     }
00427 
00428     lsaCount = networkLSAs.size();
00429     for (i = 0; i < lsaCount; i++) {
00430         unsigned short    lsAge          = networkLSAs[i]->getHeader().getLsAge();
00431         bool              unreachable    = parentRouter->IsDestinationUnreachable(networkLSAs[i]);
00432         OSPF::NetworkLSA* lsa            = networkLSAs[i];
00433         OSPF::Interface*  localIntf      = GetInterface(IPv4AddressFromULong(lsa->getHeader().getLinkStateID()));
00434         bool              selfOriginated = false;
00435 
00436         if ((localIntf != NULL) &&
00437             (localIntf->GetState() == OSPF::Interface::DesignatedRouterState) &&
00438             (localIntf->GetNeighborCount() > 0) &&
00439             (localIntf->HasAnyNeighborInStates(OSPF::Neighbor::FullState)))
00440         {
00441             selfOriginated = true;
00442         }
00443 
00444         if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) {
00445             lsa->getHeader().setLsAge(lsAge + 1);
00446             if ((lsAge + 1) % CHECK_AGE == 0) {
00447                 if (!lsa->ValidateLSChecksum()) {
00448                     EV << "Invalid LS checksum. Memory error detected!\n";
00449                 }
00450             }
00451             lsa->IncrementInstallTime();
00452         }
00453         if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) {
00454             if (unreachable) {
00455                 lsa->getHeader().setLsAge(MAX_AGE);
00456                 FloodLSA(lsa);
00457                 lsa->IncrementInstallTime();
00458             } else {
00459                 long sequenceNumber = lsa->getHeader().getLsSequenceNumber();
00460                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00461                     lsa->getHeader().setLsAge(MAX_AGE);
00462                     FloodLSA(lsa);
00463                     lsa->IncrementInstallTime();
00464                 } else {
00465                     OSPF::NetworkLSA* newLSA = OriginateNetworkLSA(localIntf);
00466 
00467                     if (newLSA != NULL) {
00468                         newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00469                         newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00470                         rebuildRoutingTable |= lsa->Update(newLSA);
00471                         delete newLSA;
00472                     } else {    // no neighbors on the network -> old NetworkLSA must be flushed
00473                         lsa->getHeader().setLsAge(MAX_AGE);
00474                         lsa->IncrementInstallTime();
00475                     }
00476 
00477                     FloodLSA(lsa);
00478                 }
00479             }
00480         }
00481         if (!selfOriginated && (lsAge == MAX_AGE - 1)) {
00482             lsa->getHeader().setLsAge(MAX_AGE);
00483             FloodLSA(lsa);
00484             lsa->IncrementInstallTime();
00485         }
00486         if (lsAge == MAX_AGE) {
00487             OSPF::LSAKeyType lsaKey;
00488 
00489             lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00490             lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00491 
00492             if (!IsOnAnyRetransmissionList(lsaKey) &&
00493                 !HasAnyNeighborInStates(OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState))
00494             {
00495                 if (!selfOriginated || unreachable) {
00496                     networkLSAsByID.erase(lsa->getHeader().getLinkStateID());
00497                     delete lsa;
00498                     networkLSAs[i] = NULL;
00499                     rebuildRoutingTable = true;
00500                 } else {
00501                     OSPF::NetworkLSA* newLSA              = OriginateNetworkLSA(localIntf);
00502                     long              sequenceNumber      = lsa->getHeader().getLsSequenceNumber();
00503 
00504                     if (newLSA != NULL) {
00505                         newLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
00506                         newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00507                         rebuildRoutingTable |= lsa->Update(newLSA);
00508                         delete newLSA;
00509 
00510                         FloodLSA(lsa);
00511                     } else {    // no neighbors on the network -> old NetworkLSA must be deleted
00512                         delete networkLSAs[i];
00513                     }
00514                 }
00515             }
00516         }
00517     }
00518 
00519     std::vector<NetworkLSA*>::iterator networkIt = networkLSAs.begin();
00520     while (networkIt != networkLSAs.end()) {
00521         if ((*networkIt) == NULL) {
00522             networkIt = networkLSAs.erase(networkIt);
00523         } else {
00524             networkIt++;
00525         }
00526     }
00527 
00528     lsaCount = summaryLSAs.size();
00529     for (i = 0; i < lsaCount; i++) {
00530         unsigned short    lsAge          = summaryLSAs[i]->getHeader().getLsAge();
00531         bool              selfOriginated = (summaryLSAs[i]->getHeader().getAdvertisingRouter().getInt() == parentRouter->GetRouterID());
00532         bool              unreachable    = parentRouter->IsDestinationUnreachable(summaryLSAs[i]);
00533         OSPF::SummaryLSA* lsa            = summaryLSAs[i];
00534 
00535         if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) {
00536             lsa->getHeader().setLsAge(lsAge + 1);
00537             if ((lsAge + 1) % CHECK_AGE == 0) {
00538                 if (!lsa->ValidateLSChecksum()) {
00539                     EV << "Invalid LS checksum. Memory error detected!\n";
00540                 }
00541             }
00542             lsa->IncrementInstallTime();
00543         }
00544         if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) {
00545             if (unreachable) {
00546                 lsa->getHeader().setLsAge(MAX_AGE);
00547                 FloodLSA(lsa);
00548                 lsa->IncrementInstallTime();
00549             } else {
00550                 long sequenceNumber = lsa->getHeader().getLsSequenceNumber();
00551                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00552                     lsa->getHeader().setLsAge(MAX_AGE);
00553                     FloodLSA(lsa);
00554                     lsa->IncrementInstallTime();
00555                 } else {
00556                     OSPF::SummaryLSA* newLSA = OriginateSummaryLSA(lsa);
00557 
00558                     if (newLSA != NULL) {
00559                         newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00560                         newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00561                         rebuildRoutingTable |= lsa->Update(newLSA);
00562                         delete newLSA;
00563 
00564                         FloodLSA(lsa);
00565                     } else {
00566                         lsa->getHeader().setLsAge(MAX_AGE);
00567                         FloodLSA(lsa);
00568                         lsa->IncrementInstallTime();
00569                     }
00570                 }
00571             }
00572         }
00573         if (!selfOriginated && (lsAge == MAX_AGE - 1)) {
00574             lsa->getHeader().setLsAge(MAX_AGE);
00575             FloodLSA(lsa);
00576             lsa->IncrementInstallTime();
00577         }
00578         if (lsAge == MAX_AGE) {
00579             OSPF::LSAKeyType lsaKey;
00580 
00581             lsaKey.linkStateID = lsa->getHeader().getLinkStateID();
00582             lsaKey.advertisingRouter = lsa->getHeader().getAdvertisingRouter().getInt();
00583 
00584             if (!IsOnAnyRetransmissionList(lsaKey) &&
00585                 !HasAnyNeighborInStates(OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState))
00586             {
00587                 if (!selfOriginated || unreachable) {
00588                     summaryLSAsByID.erase(lsaKey);
00589                     delete lsa;
00590                     summaryLSAs[i] = NULL;
00591                     rebuildRoutingTable = true;
00592                 } else {
00593                     OSPF::SummaryLSA* newLSA = OriginateSummaryLSA(lsa);
00594                     if (newLSA != NULL) {
00595                         long sequenceNumber = lsa->getHeader().getLsSequenceNumber();
00596 
00597                         newLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
00598                         newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00599                         rebuildRoutingTable |= lsa->Update(newLSA);
00600                         delete newLSA;
00601 
00602                         FloodLSA(lsa);
00603                     } else {
00604                         summaryLSAsByID.erase(lsaKey);
00605                         delete lsa;
00606                         summaryLSAs[i] = NULL;
00607                         rebuildRoutingTable = true;
00608                     }
00609                 }
00610             }
00611         }
00612     }
00613 
00614     std::vector<SummaryLSA*>::iterator summaryIt = summaryLSAs.begin();
00615     while (summaryIt != summaryLSAs.end()) {
00616         if ((*summaryIt) == NULL) {
00617             summaryIt = summaryLSAs.erase(summaryIt);
00618         } else {
00619             summaryIt++;
00620         }
00621     }
00622 
00623     long interfaceCount = associatedInterfaces.size();
00624     for (long m = 0; m < interfaceCount; m++) {
00625         associatedInterfaces[m]->AgeTransmittedLSALists();
00626     }
00627 
00628     if (rebuildRoutingTable) {
00629         parentRouter->RebuildRoutingTable();
00630     }
00631 }
00632 
00633 bool OSPF::Area::HasAnyNeighborInStates(int states) const
00634 {
00635     long interfaceCount = associatedInterfaces.size();
00636     for (long i = 0; i < interfaceCount; i++) {
00637         if (associatedInterfaces[i]->HasAnyNeighborInStates(states)) {
00638             return true;
00639         }
00640     }
00641     return false;
00642 }
00643 
00644 void OSPF::Area::RemoveFromAllRetransmissionLists(OSPF::LSAKeyType lsaKey)
00645 {
00646     long interfaceCount = associatedInterfaces.size();
00647     for (long i = 0; i < interfaceCount; i++) {
00648         associatedInterfaces[i]->RemoveFromAllRetransmissionLists(lsaKey);
00649     }
00650 }
00651 
00652 bool OSPF::Area::IsOnAnyRetransmissionList(OSPF::LSAKeyType lsaKey) const
00653 {
00654     long interfaceCount = associatedInterfaces.size();
00655     for (long i = 0; i < interfaceCount; i++) {
00656         if (associatedInterfaces[i]->IsOnAnyRetransmissionList(lsaKey)) {
00657             return true;
00658         }
00659     }
00660     return false;
00661 }
00662 
00663 bool OSPF::Area::FloodLSA(OSPFLSA* lsa, OSPF::Interface* intf, OSPF::Neighbor* neighbor)
00664 {
00665     bool floodedBackOut  = false;
00666     long interfaceCount = associatedInterfaces.size();
00667 
00668     for (long i = 0; i < interfaceCount; i++) {
00669         if (associatedInterfaces[i]->FloodLSA(lsa, intf, neighbor)) {
00670             floodedBackOut = true;
00671         }
00672     }
00673 
00674     return floodedBackOut;
00675 }
00676 
00677 bool OSPF::Area::IsLocalAddress(OSPF::IPv4Address address) const
00678 {
00679     long interfaceCount = associatedInterfaces.size();
00680     for (long i = 0; i < interfaceCount; i++) {
00681         if (associatedInterfaces[i]->GetAddressRange().address == address) {
00682             return true;
00683         }
00684     }
00685     return false;
00686 }
00687 
00688 OSPF::RouterLSA* OSPF::Area::OriginateRouterLSA(void)
00689 {
00690     OSPF::RouterLSA* routerLSA      = new OSPF::RouterLSA;
00691     OSPFLSAHeader&   lsaHeader      = routerLSA->getHeader();
00692     long             interfaceCount = associatedInterfaces.size();
00693     OSPFOptions      lsOptions;
00694     long             i;
00695 
00696     lsaHeader.setLsAge(0);
00697     memset(&lsOptions, 0, sizeof(OSPFOptions));
00698     lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
00699     lsaHeader.setLsOptions(lsOptions);
00700     lsaHeader.setLsType(RouterLSAType);
00701     lsaHeader.setLinkStateID(parentRouter->GetRouterID());
00702     lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
00703     lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
00704 
00705     routerLSA->setB_AreaBorderRouter(parentRouter->GetAreaCount() > 1);
00706     routerLSA->setE_ASBoundaryRouter((externalRoutingCapability && parentRouter->GetASBoundaryRouter()) ? true : false);
00707     OSPF::Area* backbone = parentRouter->GetArea(OSPF::BackboneAreaID);
00708     routerLSA->setV_VirtualLinkEndpoint((backbone == NULL) ? false : backbone->HasVirtualLink(areaID));
00709 
00710     routerLSA->setNumberOfLinks(0);
00711     routerLSA->setLinksArraySize(0);
00712     for (i = 0; i < interfaceCount; i++) {
00713         OSPF::Interface* intf = associatedInterfaces[i];
00714 
00715         if (intf->GetState() == OSPF::Interface::DownState) {
00716             continue;
00717         }
00718         if ((intf->GetState() == OSPF::Interface::LoopbackState) &&
00719             ((intf->GetType() != OSPF::Interface::PointToPoint) ||
00720              (intf->GetAddressRange().address != OSPF::NullIPv4Address)))
00721         {
00722             Link stubLink;
00723             stubLink.setType(StubLink);
00724             stubLink.setLinkID(ULongFromIPv4Address(intf->GetAddressRange().address));
00725             stubLink.setLinkData(0xFFFFFFFF);
00726             stubLink.setLinkCost(0);
00727             stubLink.setNumberOfTOS(0);
00728             stubLink.setTosDataArraySize(0);
00729 
00730             unsigned short linkIndex = routerLSA->getLinksArraySize();
00731             routerLSA->setLinksArraySize(linkIndex + 1);
00732             routerLSA->setNumberOfLinks(linkIndex + 1);
00733             routerLSA->setLinks(linkIndex, stubLink);
00734         }
00735         if (intf->GetState() > OSPF::Interface::LoopbackState) {
00736             switch (intf->GetType()) {
00737                 case OSPF::Interface::PointToPoint:
00738                     {
00739                         OSPF::Neighbor* neighbor = (intf->GetNeighborCount() > 0) ? intf->GetNeighbor(0) : NULL;
00740                         if (neighbor != NULL) {
00741                             if (neighbor->GetState() == OSPF::Neighbor::FullState) {
00742                                 Link link;
00743                                 link.setType(PointToPointLink);
00744                                 link.setLinkID(neighbor->GetNeighborID());
00745                                 if (intf->GetAddressRange().address != OSPF::NullIPv4Address) {
00746                                     link.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().address));
00747                                 } else {
00748                                     link.setLinkData(intf->GetIfIndex());
00749                                 }
00750                                 link.setLinkCost(intf->GetOutputCost());
00751                                 link.setNumberOfTOS(0);
00752                                 link.setTosDataArraySize(0);
00753 
00754                                 unsigned short linkIndex = routerLSA->getLinksArraySize();
00755                                 routerLSA->setLinksArraySize(linkIndex + 1);
00756                                 routerLSA->setNumberOfLinks(linkIndex + 1);
00757                                 routerLSA->setLinks(linkIndex, link);
00758                             }
00759                             if (intf->GetState() == OSPF::Interface::PointToPointState) {
00760                                 if (neighbor->GetAddress() != OSPF::NullIPv4Address) {
00761                                     Link stubLink;
00762                                     stubLink.setType(StubLink);
00763                                     stubLink.setLinkID(ULongFromIPv4Address(neighbor->GetAddress()));
00764                                     stubLink.setLinkData(0xFFFFFFFF);
00765                                     stubLink.setLinkCost(intf->GetOutputCost());
00766                                     stubLink.setNumberOfTOS(0);
00767                                     stubLink.setTosDataArraySize(0);
00768 
00769                                     unsigned short linkIndex = routerLSA->getLinksArraySize();
00770                                     routerLSA->setLinksArraySize(linkIndex + 1);
00771                                     routerLSA->setNumberOfLinks(linkIndex + 1);
00772                                     routerLSA->setLinks(linkIndex, stubLink);
00773                                 } else {
00774                                     if (ULongFromIPv4Address(intf->GetAddressRange().mask) != 0xFFFFFFFF) {
00775                                         Link stubLink;
00776                                         stubLink.setType(StubLink);
00777                                         stubLink.setLinkID(ULongFromIPv4Address(intf->GetAddressRange().address &
00778                                                                                   intf->GetAddressRange().mask));
00779                                         stubLink.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().mask));
00780                                         stubLink.setLinkCost(intf->GetOutputCost());
00781                                         stubLink.setNumberOfTOS(0);
00782                                         stubLink.setTosDataArraySize(0);
00783 
00784                                         unsigned short linkIndex = routerLSA->getLinksArraySize();
00785                                         routerLSA->setLinksArraySize(linkIndex + 1);
00786                                         routerLSA->setNumberOfLinks(linkIndex + 1);
00787                                         routerLSA->setLinks(linkIndex, stubLink);
00788                                     }
00789                                 }
00790                             }
00791                         }
00792                     }
00793                     break;
00794                 case OSPF::Interface::Broadcast:
00795                 case OSPF::Interface::NBMA:
00796                     {
00797                         if (intf->GetState() == OSPF::Interface::WaitingState) {
00798                             Link stubLink;
00799                             stubLink.setType(StubLink);
00800                             stubLink.setLinkID(ULongFromIPv4Address(intf->GetAddressRange().address &
00801                                                                       intf->GetAddressRange().mask));
00802                             stubLink.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().mask));
00803                             stubLink.setLinkCost(intf->GetOutputCost());
00804                             stubLink.setNumberOfTOS(0);
00805                             stubLink.setTosDataArraySize(0);
00806 
00807                             unsigned short linkIndex = routerLSA->getLinksArraySize();
00808                             routerLSA->setLinksArraySize(linkIndex + 1);
00809                             routerLSA->setNumberOfLinks(linkIndex + 1);
00810                             routerLSA->setLinks(linkIndex, stubLink);
00811                         } else {
00812                             OSPF::Neighbor* dRouter = intf->GetNeighborByAddress(intf->GetDesignatedRouter().ipInterfaceAddress);
00813                             if (((dRouter != NULL) && (dRouter->GetState() == OSPF::Neighbor::FullState)) ||
00814                                 ((intf->GetDesignatedRouter().routerID == parentRouter->GetRouterID()) &&
00815                                  (intf->HasAnyNeighborInStates(OSPF::Neighbor::FullState))))
00816                             {
00817                                 Link link;
00818                                 link.setType(TransitLink);
00819                                 link.setLinkID(ULongFromIPv4Address(intf->GetDesignatedRouter().ipInterfaceAddress));
00820                                 link.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().address));
00821                                 link.setLinkCost(intf->GetOutputCost());
00822                                 link.setNumberOfTOS(0);
00823                                 link.setTosDataArraySize(0);
00824 
00825                                 unsigned short linkIndex = routerLSA->getLinksArraySize();
00826                                 routerLSA->setLinksArraySize(linkIndex + 1);
00827                                 routerLSA->setNumberOfLinks(linkIndex + 1);
00828                                 routerLSA->setLinks(linkIndex, link);
00829                             } else {
00830                                 Link stubLink;
00831                                 stubLink.setType(StubLink);
00832                                 stubLink.setLinkID(ULongFromIPv4Address(intf->GetAddressRange().address &
00833                                                                           intf->GetAddressRange().mask));
00834                                 stubLink.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().mask));
00835                                 stubLink.setLinkCost(intf->GetOutputCost());
00836                                 stubLink.setNumberOfTOS(0);
00837                                 stubLink.setTosDataArraySize(0);
00838 
00839                                 unsigned short linkIndex = routerLSA->getLinksArraySize();
00840                                 routerLSA->setLinksArraySize(linkIndex + 1);
00841                                 routerLSA->setNumberOfLinks(linkIndex + 1);
00842                                 routerLSA->setLinks(linkIndex, stubLink);
00843                             }
00844                         }
00845                     }
00846                     break;
00847                 case OSPF::Interface::Virtual:
00848                     {
00849                         OSPF::Neighbor* neighbor = (intf->GetNeighborCount() > 0) ? intf->GetNeighbor(0) : NULL;
00850                         if ((neighbor != NULL) && (neighbor->GetState() == OSPF::Neighbor::FullState)) {
00851                             Link link;
00852                             link.setType(VirtualLink);
00853                             link.setLinkID(neighbor->GetNeighborID());
00854                             link.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().address));
00855                             link.setLinkCost(intf->GetOutputCost());
00856                             link.setNumberOfTOS(0);
00857                             link.setTosDataArraySize(0);
00858 
00859                             unsigned short linkIndex = routerLSA->getLinksArraySize();
00860                             routerLSA->setLinksArraySize(linkIndex + 1);
00861                             routerLSA->setNumberOfLinks(linkIndex + 1);
00862                             routerLSA->setLinks(linkIndex, link);
00863                         }
00864                     }
00865                     break;
00866                 case OSPF::Interface::PointToMultiPoint:
00867                     {
00868                         Link stubLink;
00869                         stubLink.setType(StubLink);
00870                         stubLink.setLinkID(ULongFromIPv4Address(intf->GetAddressRange().address));
00871                         stubLink.setLinkData(0xFFFFFFFF);
00872                         stubLink.setLinkCost(0);
00873                         stubLink.setNumberOfTOS(0);
00874                         stubLink.setTosDataArraySize(0);
00875 
00876                         unsigned short linkIndex = routerLSA->getLinksArraySize();
00877                         routerLSA->setLinksArraySize(linkIndex + 1);
00878                         routerLSA->setNumberOfLinks(linkIndex + 1);
00879                         routerLSA->setLinks(linkIndex, stubLink);
00880 
00881                         long neighborCount = intf->GetNeighborCount();
00882                         for (long i = 0; i < neighborCount; i++) {
00883                             OSPF::Neighbor* neighbor = intf->GetNeighbor(i);
00884                             if (neighbor->GetState() == OSPF::Neighbor::FullState) {
00885                                 Link link;
00886                                 link.setType(PointToPointLink);
00887                                 link.setLinkID(neighbor->GetNeighborID());
00888                                 link.setLinkData(ULongFromIPv4Address(intf->GetAddressRange().address));
00889                                 link.setLinkCost(intf->GetOutputCost());
00890                                 link.setNumberOfTOS(0);
00891                                 link.setTosDataArraySize(0);
00892 
00893                                 unsigned short linkIndex = routerLSA->getLinksArraySize();
00894                                 routerLSA->setLinksArraySize(linkIndex + 1);
00895                                 routerLSA->setNumberOfLinks(linkIndex + 1);
00896                                 routerLSA->setLinks(linkIndex, stubLink);
00897                             }
00898                         }
00899                     }
00900                     break;
00901                 default: break;
00902             }
00903         }
00904     }
00905 
00906     long hostRouteCount = hostRoutes.size();
00907     for (i = 0; i < hostRouteCount; i++) {
00908         Link stubLink;
00909         stubLink.setType(StubLink);
00910         stubLink.setLinkID(ULongFromIPv4Address(hostRoutes[i].address));
00911         stubLink.setLinkData(0xFFFFFFFF);
00912         stubLink.setLinkCost(hostRoutes[i].linkCost);
00913         stubLink.setNumberOfTOS(0);
00914         stubLink.setTosDataArraySize(0);
00915 
00916         unsigned short linkIndex = routerLSA->getLinksArraySize();
00917         routerLSA->setLinksArraySize(linkIndex + 1);
00918         routerLSA->setNumberOfLinks(linkIndex + 1);
00919         routerLSA->setLinks(linkIndex, stubLink);
00920     }
00921 
00922     lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
00923 
00924     routerLSA->SetSource(OSPF::LSATrackingInfo::Originated);
00925 
00926     return routerLSA;
00927 }
00928 
00929 OSPF::NetworkLSA* OSPF::Area::OriginateNetworkLSA(const OSPF::Interface* intf)
00930 {
00931     if (intf->HasAnyNeighborInStates(OSPF::Neighbor::FullState)) {
00932         OSPF::NetworkLSA* networkLSA      = new OSPF::NetworkLSA;
00933         OSPFLSAHeader&   lsaHeader        = networkLSA->getHeader();
00934         long             neighborCount    = intf->GetNeighborCount();
00935         OSPFOptions      lsOptions;
00936 
00937         lsaHeader.setLsAge(0);
00938         memset(&lsOptions, 0, sizeof(OSPFOptions));
00939         lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
00940         lsaHeader.setLsOptions(lsOptions);
00941         lsaHeader.setLsType(NetworkLSAType);
00942         lsaHeader.setLinkStateID(ULongFromIPv4Address(intf->GetAddressRange().address));
00943         lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
00944         lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
00945 
00946         networkLSA->setNetworkMask(ULongFromIPv4Address(intf->GetAddressRange().mask));
00947 
00948         for (long j = 0; j < neighborCount; j++) {
00949             const OSPF::Neighbor* neighbor = intf->GetNeighbor(j);
00950             if (neighbor->GetState() == OSPF::Neighbor::FullState) {
00951                 unsigned short netIndex = networkLSA->getAttachedRoutersArraySize();
00952                 networkLSA->setAttachedRoutersArraySize(netIndex + 1);
00953                 networkLSA->setAttachedRouters(netIndex, neighbor->GetNeighborID());
00954             }
00955         }
00956         unsigned short netIndex = networkLSA->getAttachedRoutersArraySize();
00957         networkLSA->setAttachedRoutersArraySize(netIndex + 1);
00958         networkLSA->setAttachedRouters(netIndex, parentRouter->GetRouterID());
00959 
00960         lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
00961 
00962         return networkLSA;
00963     } else {
00964         return NULL;
00965     }
00966 }
00967 
00989 OSPF::LinkStateID OSPF::Area::GetUniqueLinkStateID(OSPF::IPv4AddressRange destination,
00990                                                     OSPF::Metric destinationCost,
00991                                                     OSPF::SummaryLSA*& lsaToReoriginate) const
00992 {
00993     if (lsaToReoriginate != NULL) {
00994         delete lsaToReoriginate;
00995         lsaToReoriginate = NULL;
00996     }
00997 
00998     OSPF::LSAKeyType lsaKey;
00999 
01000     lsaKey.linkStateID = ULongFromIPv4Address(destination.address);
01001     lsaKey.advertisingRouter = parentRouter->GetRouterID();
01002 
01003     const OSPF::SummaryLSA* foundLSA = FindSummaryLSA(lsaKey);
01004 
01005     if (foundLSA == NULL) {
01006         return lsaKey.linkStateID;
01007     } else {
01008         OSPF::IPv4Address existingMask = IPv4AddressFromULong(foundLSA->getNetworkMask().getInt());
01009 
01010         if (destination.mask == existingMask) {
01011             return lsaKey.linkStateID;
01012         } else {
01013             if (destination.mask >= existingMask) {
01014                 return (lsaKey.linkStateID | (~(ULongFromIPv4Address(destination.mask))));
01015             } else {
01016                 OSPF::SummaryLSA* summaryLSA = new OSPF::SummaryLSA(*foundLSA);
01017 
01018                 long sequenceNumber = summaryLSA->getHeader().getLsSequenceNumber();
01019 
01020                 summaryLSA->getHeader().setLsAge(0);
01021                 summaryLSA->getHeader().setLsSequenceNumber((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
01022                 summaryLSA->setNetworkMask(ULongFromIPv4Address(destination.mask));
01023                 summaryLSA->setRouteCost(destinationCost);
01024                 summaryLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
01025 
01026                 lsaToReoriginate = summaryLSA;
01027 
01028                 return (lsaKey.linkStateID | (~(ULongFromIPv4Address(existingMask))));
01029             }
01030         }
01031     }
01032 }
01033 
01034 OSPF::SummaryLSA* OSPF::Area::OriginateSummaryLSA(const OSPF::RoutingTableEntry* entry,
01035                                                    const std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>& originatedLSAs,
01036                                                    OSPF::SummaryLSA*& lsaToReoriginate)
01037 {
01038     if (((entry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
01039         (entry->GetPathType() == OSPF::RoutingTableEntry::Type1External) ||
01040         (entry->GetPathType() == OSPF::RoutingTableEntry::Type2External) ||
01041         (entry->GetArea() == areaID))
01042     {
01043         return NULL;
01044     }
01045 
01046     bool         allNextHopsInThisArea = true;
01047     unsigned int nextHopCount          = entry->GetNextHopCount();
01048 
01049     for (unsigned int i = 0; i < nextHopCount; i++) {
01050         OSPF::Interface* nextHopInterface = parentRouter->GetNonVirtualInterface(entry->GetNextHop(i).ifIndex);
01051         if ((nextHopInterface != NULL) && (nextHopInterface->GetAreaID() != areaID)) {
01052             allNextHopsInThisArea = false;
01053             break;
01054         }
01055     }
01056     if ((allNextHopsInThisArea) || (entry->GetCost() >= LS_INFINITY)){
01057         return NULL;
01058     }
01059 
01060     if ((entry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) {
01061         OSPF::RoutingTableEntry* preferredEntry = parentRouter->GetPreferredEntry(*(entry->GetLinkStateOrigin()), false);
01062         if ((preferredEntry != NULL) && (*preferredEntry == *entry) && (externalRoutingCapability)) {
01063             OSPF::SummaryLSA* summaryLSA    = new OSPF::SummaryLSA;
01064             OSPFLSAHeader&    lsaHeader     = summaryLSA->getHeader();
01065             OSPFOptions       lsOptions;
01066 
01067             lsaHeader.setLsAge(0);
01068             memset(&lsOptions, 0, sizeof(OSPFOptions));
01069             lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
01070             lsaHeader.setLsOptions(lsOptions);
01071             lsaHeader.setLsType(SummaryLSA_ASBoundaryRoutersType);
01072             lsaHeader.setLinkStateID(entry->GetDestinationID().getInt());
01073             lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
01074             lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01075 
01076             summaryLSA->setNetworkMask(entry->GetAddressMask());
01077             summaryLSA->setRouteCost(entry->GetCost());
01078             summaryLSA->setTosDataArraySize(0);
01079 
01080             lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01081 
01082             summaryLSA->SetSource(OSPF::LSATrackingInfo::Originated);
01083 
01084             return summaryLSA;
01085         }
01086     } else {    // entry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination
01087         if (entry->GetPathType() == OSPF::RoutingTableEntry::InterArea) {
01088             OSPF::IPv4AddressRange destinationRange;
01089 
01090             destinationRange.address = IPv4AddressFromULong(entry->GetDestinationID().getInt());
01091             destinationRange.mask = IPv4AddressFromULong(entry->GetAddressMask().getInt());
01092 
01093             OSPF::LinkStateID newLinkStateID = GetUniqueLinkStateID(destinationRange, entry->GetCost(), lsaToReoriginate);
01094 
01095             if (lsaToReoriginate != NULL) {
01096                 OSPF::LSAKeyType lsaKey;
01097 
01098                 lsaKey.linkStateID = entry->GetDestinationID().getInt();
01099                 lsaKey.advertisingRouter = parentRouter->GetRouterID();
01100 
01101                 std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = summaryLSAsByID.find(lsaKey);
01102                 if (lsaIt == summaryLSAsByID.end()) {
01103                     delete(lsaToReoriginate);
01104                     lsaToReoriginate = NULL;
01105                     return NULL;
01106                 } else {
01107                     OSPF::SummaryLSA* summaryLSA = new OSPF::SummaryLSA(*(lsaIt->second));
01108                     OSPFLSAHeader&    lsaHeader  = summaryLSA->getHeader();
01109 
01110                     lsaHeader.setLsAge(0);
01111                     lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01112                     lsaHeader.setLinkStateID(newLinkStateID);
01113                     lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01114 
01115                     return summaryLSA;
01116                 }
01117             } else {
01118                 OSPF::SummaryLSA* summaryLSA    = new OSPF::SummaryLSA;
01119                 OSPFLSAHeader&    lsaHeader     = summaryLSA->getHeader();
01120                 OSPFOptions       lsOptions;
01121 
01122                 lsaHeader.setLsAge(0);
01123                 memset(&lsOptions, 0, sizeof(OSPFOptions));
01124                 lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
01125                 lsaHeader.setLsOptions(lsOptions);
01126                 lsaHeader.setLsType(SummaryLSA_NetworksType);
01127                 lsaHeader.setLinkStateID(newLinkStateID);
01128                 lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
01129                 lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01130 
01131                 summaryLSA->setNetworkMask(entry->GetAddressMask());
01132                 summaryLSA->setRouteCost(entry->GetCost());
01133                 summaryLSA->setTosDataArraySize(0);
01134 
01135                 lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01136 
01137                 summaryLSA->SetSource(OSPF::LSATrackingInfo::Originated);
01138 
01139                 return summaryLSA;
01140             }
01141         } else {    // entry->GetPathType() == OSPF::RoutingTableEntry::IntraArea
01142             OSPF::IPv4AddressRange destinationAddressRange;
01143 
01144             destinationAddressRange.address = IPv4AddressFromULong(entry->GetDestinationID().getInt());
01145             destinationAddressRange.mask = IPv4AddressFromULong(entry->GetAddressMask().getInt());
01146 
01147             bool doAdvertise = false;
01148             OSPF::IPv4AddressRange containingAddressRange = parentRouter->GetContainingAddressRange(destinationAddressRange, &doAdvertise);
01149             if (((entry->GetArea() == OSPF::BackboneAreaID) &&         // the backbone's configured ranges should be ignored
01150                  (transitCapability)) ||                                // when originating Summary LSAs into transit areas
01151                 (containingAddressRange == OSPF::NullIPv4AddressRange))
01152             {
01153                 OSPF::LinkStateID newLinkStateID = GetUniqueLinkStateID(destinationAddressRange, entry->GetCost(), lsaToReoriginate);
01154 
01155                 if (lsaToReoriginate != NULL) {
01156                     OSPF::LSAKeyType lsaKey;
01157 
01158                     lsaKey.linkStateID = entry->GetDestinationID().getInt();
01159                     lsaKey.advertisingRouter = parentRouter->GetRouterID();
01160 
01161                     std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = summaryLSAsByID.find(lsaKey);
01162                     if (lsaIt == summaryLSAsByID.end()) {
01163                         delete(lsaToReoriginate);
01164                         lsaToReoriginate = NULL;
01165                         return NULL;
01166                     } else {
01167                         OSPF::SummaryLSA* summaryLSA = new OSPF::SummaryLSA(*(lsaIt->second));
01168                         OSPFLSAHeader&    lsaHeader  = summaryLSA->getHeader();
01169 
01170                         lsaHeader.setLsAge(0);
01171                         lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01172                         lsaHeader.setLinkStateID(newLinkStateID);
01173                         lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01174 
01175                         return summaryLSA;
01176                     }
01177                 } else {
01178                     OSPF::SummaryLSA* summaryLSA    = new OSPF::SummaryLSA;
01179                     OSPFLSAHeader&    lsaHeader     = summaryLSA->getHeader();
01180                     OSPFOptions       lsOptions;
01181 
01182                     lsaHeader.setLsAge(0);
01183                     memset(&lsOptions, 0, sizeof(OSPFOptions));
01184                     lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
01185                     lsaHeader.setLsOptions(lsOptions);
01186                     lsaHeader.setLsType(SummaryLSA_NetworksType);
01187                     lsaHeader.setLinkStateID(newLinkStateID);
01188                     lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
01189                     lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01190 
01191                     summaryLSA->setNetworkMask(entry->GetAddressMask());
01192                     summaryLSA->setRouteCost(entry->GetCost());
01193                     summaryLSA->setTosDataArraySize(0);
01194 
01195                     lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01196 
01197                     summaryLSA->SetSource(OSPF::LSATrackingInfo::Originated);
01198 
01199                     return summaryLSA;
01200                 }
01201             } else {
01202                 if (doAdvertise) {
01203                     Metric        maxRangeCost = 0;
01204                     unsigned long entryCount   = parentRouter->GetRoutingTableEntryCount();
01205 
01206                     for (unsigned long i = 0; i < entryCount; i++) {
01207                         const OSPF::RoutingTableEntry* routingEntry = parentRouter->GetRoutingTableEntry(i);
01208 
01209                         if ((routingEntry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01210                             (routingEntry->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
01211                             ((routingEntry->GetDestinationID().getInt() & routingEntry->GetAddressMask().getInt() & ULongFromIPv4Address(containingAddressRange.mask)) ==
01212                              ULongFromIPv4Address(containingAddressRange.address & containingAddressRange.mask)) &&
01213                             (routingEntry->GetCost() > maxRangeCost))
01214                         {
01215                             maxRangeCost = routingEntry->GetCost();
01216                         }
01217                     }
01218 
01219                     OSPF::LinkStateID newLinkStateID = GetUniqueLinkStateID(containingAddressRange, maxRangeCost, lsaToReoriginate);
01220                     OSPF::LSAKeyType  lsaKey;
01221 
01222                     if (lsaToReoriginate != NULL) {
01223                         lsaKey.linkStateID = lsaToReoriginate->getHeader().getLinkStateID();
01224                         lsaKey.advertisingRouter = parentRouter->GetRouterID();
01225 
01226                         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator originatedIt = originatedLSAs.find(lsaKey);
01227                         if (originatedIt != originatedLSAs.end()) {
01228                             delete(lsaToReoriginate);
01229                             lsaToReoriginate = NULL;
01230                             return NULL;
01231                         }
01232 
01233                         lsaKey.linkStateID = entry->GetDestinationID().getInt();
01234                         lsaKey.advertisingRouter = parentRouter->GetRouterID();
01235 
01236                         std::map<OSPF::LSAKeyType, OSPF::SummaryLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = summaryLSAsByID.find(lsaKey);
01237                         if (lsaIt == summaryLSAsByID.end()) {
01238                             delete(lsaToReoriginate);
01239                             lsaToReoriginate = NULL;
01240                             return NULL;
01241                         }
01242 
01243                         OSPF::SummaryLSA* summaryLSA = new OSPF::SummaryLSA(*(lsaIt->second));
01244                         OSPFLSAHeader&    lsaHeader  = summaryLSA->getHeader();
01245 
01246                         lsaHeader.setLsAge(0);
01247                         lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01248                         lsaHeader.setLinkStateID(newLinkStateID);
01249                         lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01250 
01251                         return summaryLSA;
01252                     } else {
01253                         lsaKey.linkStateID = newLinkStateID;
01254                         lsaKey.advertisingRouter = parentRouter->GetRouterID();
01255 
01256                         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator originatedIt = originatedLSAs.find(lsaKey);
01257                         if (originatedIt != originatedLSAs.end()) {
01258                             return NULL;
01259                         }
01260 
01261                         OSPF::SummaryLSA* summaryLSA    = new OSPF::SummaryLSA;
01262                         OSPFLSAHeader&    lsaHeader     = summaryLSA->getHeader();
01263                         OSPFOptions       lsOptions;
01264 
01265                         lsaHeader.setLsAge(0);
01266                         memset(&lsOptions, 0, sizeof(OSPFOptions));
01267                         lsOptions.E_ExternalRoutingCapability = externalRoutingCapability;
01268                         lsaHeader.setLsOptions(lsOptions);
01269                         lsaHeader.setLsType(SummaryLSA_NetworksType);
01270                         lsaHeader.setLinkStateID(newLinkStateID);
01271                         lsaHeader.setAdvertisingRouter(parentRouter->GetRouterID());
01272                         lsaHeader.setLsSequenceNumber(INITIAL_SEQUENCE_NUMBER);
01273 
01274                         summaryLSA->setNetworkMask(entry->GetAddressMask());
01275                         summaryLSA->setRouteCost(entry->GetCost());
01276                         summaryLSA->setTosDataArraySize(0);
01277 
01278                         lsaHeader.setLsChecksum(0);    // TODO: calculate correct LS checksum
01279 
01280                         summaryLSA->SetSource(OSPF::LSATrackingInfo::Originated);
01281 
01282                         return summaryLSA;
01283                     }
01284                 }
01285             }
01286         }
01287     }
01288 
01289     return NULL;
01290 }
01291 
01292 OSPF::SummaryLSA* OSPF::Area::OriginateSummaryLSA(const OSPF::SummaryLSA* summaryLSA)
01293 {
01294     const std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less> emptyMap;
01295     OSPF::SummaryLSA*                                             dontReoriginate = NULL;
01296 
01297     const OSPFLSAHeader& lsaHeader   = summaryLSA->getHeader();
01298     unsigned long   entryCount = parentRouter->GetRoutingTableEntryCount();
01299 
01300     for (unsigned long i = 0; i < entryCount; i++) {
01301         const OSPF::RoutingTableEntry* entry = parentRouter->GetRoutingTableEntry(i);
01302 
01303         if ((lsaHeader.getLsType() == SummaryLSA_ASBoundaryRoutersType) &&
01304             ((((entry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
01305               ((entry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
01306              ((entry->GetDestinationID().getInt() == lsaHeader.getLinkStateID()) &&
01307               (entry->GetAddressMask() == summaryLSA->getNetworkMask()))))
01308         {
01309             OSPF::SummaryLSA* returnLSA = OriginateSummaryLSA(entry, emptyMap, dontReoriginate);
01310             if (dontReoriginate != NULL) {
01311                 delete dontReoriginate;
01312             }
01313             return returnLSA;
01314         }
01315 
01316         unsigned long lsaMask = summaryLSA->getNetworkMask().getInt();
01317 
01318         if ((lsaHeader.getLsType() == SummaryLSA_NetworksType) &&
01319             (entry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
01320             (entry->GetAddressMask().getInt() == lsaMask) &&
01321             ((entry->GetDestinationID().getInt() & lsaMask) == (lsaHeader.getLinkStateID() & lsaMask)))
01322         {
01323             OSPF::SummaryLSA* returnLSA = OriginateSummaryLSA(entry, emptyMap, dontReoriginate);
01324             if (dontReoriginate != NULL) {
01325                 delete dontReoriginate;
01326             }
01327             return returnLSA;
01328         }
01329     }
01330 
01331     return NULL;
01332 }
01333 
01334 void OSPF::Area::CalculateShortestPathTree(std::vector<OSPF::RoutingTableEntry*>& newRoutingTable)
01335 {
01336     OSPF::RouterID          routerID = parentRouter->GetRouterID();
01337     bool                    finished = false;
01338     std::vector<OSPFLSA*>   treeVertices;
01339     OSPFLSA*                justAddedVertex;
01340     std::vector<OSPFLSA*>   candidateVertices;
01341     unsigned long            i, j, k;
01342     unsigned long            lsaCount;
01343 
01344     if (spfTreeRoot == NULL) {
01345         OSPF::RouterLSA* newLSA = OriginateRouterLSA();
01346 
01347         InstallRouterLSA(newLSA);
01348 
01349         OSPF::RouterLSA* routerLSA = FindRouterLSA(routerID);
01350 
01351         spfTreeRoot = routerLSA;
01352         FloodLSA(newLSA);
01353         delete newLSA;
01354     }
01355     if (spfTreeRoot == NULL) {
01356         return;
01357     }
01358 
01359     lsaCount = routerLSAs.size();
01360     for (i = 0; i < lsaCount; i++) {
01361         routerLSAs[i]->ClearNextHops();
01362     }
01363     lsaCount = networkLSAs.size();
01364     for (i = 0; i < lsaCount; i++) {
01365         networkLSAs[i]->ClearNextHops();
01366     }
01367     spfTreeRoot->SetDistance(0);
01368     treeVertices.push_back(spfTreeRoot);
01369     justAddedVertex = spfTreeRoot;          // (1)
01370 
01371     do {
01372         LSAType vertexType = static_cast<LSAType> (justAddedVertex->getHeader().getLsType());
01373 
01374         if ((vertexType == RouterLSAType)) {
01375             OSPF::RouterLSA* routerVertex = check_and_cast<OSPF::RouterLSA*> (justAddedVertex);
01376             if (routerVertex->getV_VirtualLinkEndpoint()) {    // (2)
01377                 transitCapability = true;
01378             }
01379 
01380             unsigned int linkCount = routerVertex->getLinksArraySize();
01381             for (i = 0; i < linkCount; i++) {
01382                 Link&    link     = routerVertex->getLinks(i);
01383                 LinkType linkType = static_cast<LinkType> (link.getType());
01384                 OSPFLSA* joiningVertex;
01385                 LSAType  joiningVertexType;
01386 
01387                 if (linkType == StubLink) {     // (2) (a)
01388                     continue;
01389                 }
01390 
01391                 if (linkType == TransitLink) {
01392                     joiningVertex     = FindNetworkLSA(link.getLinkID().getInt());
01393                     joiningVertexType = NetworkLSAType;
01394                 } else {
01395                     joiningVertex     = FindRouterLSA(link.getLinkID().getInt());
01396                     joiningVertexType = RouterLSAType;
01397                 }
01398 
01399                 if ((joiningVertex == NULL) ||
01400                     (joiningVertex->getHeader().getLsAge() == MAX_AGE) ||
01401                     (!HasLink(joiningVertex, justAddedVertex)))  // (from, to)     (2) (b)
01402                 {
01403                     continue;
01404                 }
01405 
01406                 unsigned int treeSize      = treeVertices.size();
01407                 bool         alreadyOnTree = false;
01408 
01409                 for (j = 0; j < treeSize; j++) {
01410                     if (treeVertices[j] == joiningVertex) {
01411                         alreadyOnTree = true;
01412                         break;
01413                     }
01414                 }
01415                 if (alreadyOnTree) {    // (2) (c)
01416                     continue;
01417                 }
01418 
01419                 unsigned long linkStateCost  = routerVertex->GetDistance() + link.getLinkCost();
01420                 unsigned int  candidateCount = candidateVertices.size();
01421                 OSPFLSA*      candidate      = NULL;
01422 
01423                 for (j = 0; j < candidateCount; j++) {
01424                     if (candidateVertices[j] == joiningVertex) {
01425                         candidate = candidateVertices[j];
01426                     }
01427                 }
01428                 if (candidate != NULL) {    // (2) (d)
01429                     OSPF::RoutingInfo* routingInfo       = check_and_cast<OSPF::RoutingInfo*> (candidate);
01430                     unsigned long      candidateDistance = routingInfo->GetDistance();
01431 
01432                     if (linkStateCost > candidateDistance) {
01433                         continue;
01434                     }
01435                     if (linkStateCost < candidateDistance) {
01436                         routingInfo->SetDistance(linkStateCost);
01437                         routingInfo->ClearNextHops();
01438                     }
01439                     std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(joiningVertex, justAddedVertex); // (destination, parent)
01440                     unsigned int nextHopCount = newNextHops->size();
01441                     for (k = 0; k < nextHopCount; k++) {
01442                         routingInfo->AddNextHop((*newNextHops)[k]);
01443                     }
01444                     delete newNextHops;
01445                 } else {
01446                     if (joiningVertexType == RouterLSAType) {
01447                         OSPF::RouterLSA* joiningRouterVertex = check_and_cast<OSPF::RouterLSA*> (joiningVertex);
01448                         joiningRouterVertex->SetDistance(linkStateCost);
01449                         std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(joiningVertex, justAddedVertex); // (destination, parent)
01450                         unsigned int nextHopCount = newNextHops->size();
01451                         for (k = 0; k < nextHopCount; k++) {
01452                             joiningRouterVertex->AddNextHop((*newNextHops)[k]);
01453                         }
01454                         delete newNextHops;
01455                         OSPF::RoutingInfo* vertexRoutingInfo = check_and_cast<OSPF::RoutingInfo*> (joiningRouterVertex);
01456                         vertexRoutingInfo->SetParent(justAddedVertex);
01457 
01458                         candidateVertices.push_back(joiningRouterVertex);
01459                     } else {
01460                         OSPF::NetworkLSA* joiningNetworkVertex = check_and_cast<OSPF::NetworkLSA*> (joiningVertex);
01461                         joiningNetworkVertex->SetDistance(linkStateCost);
01462                         std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(joiningVertex, justAddedVertex); // (destination, parent)
01463                         unsigned int nextHopCount = newNextHops->size();
01464                         for (k = 0; k < nextHopCount; k++) {
01465                             joiningNetworkVertex->AddNextHop((*newNextHops)[k]);
01466                         }
01467                         delete newNextHops;
01468                         OSPF::RoutingInfo* vertexRoutingInfo = check_and_cast<OSPF::RoutingInfo*> (joiningNetworkVertex);
01469                         vertexRoutingInfo->SetParent(justAddedVertex);
01470 
01471                         candidateVertices.push_back(joiningNetworkVertex);
01472                     }
01473                 }
01474             }
01475         }
01476 
01477         if ((vertexType == NetworkLSAType)) {
01478             OSPF::NetworkLSA* networkVertex = check_and_cast<OSPF::NetworkLSA*> (justAddedVertex);
01479             unsigned int      routerCount   = networkVertex->getAttachedRoutersArraySize();
01480 
01481             for (i = 0; i < routerCount; i++) {     // (2)
01482                 OSPF::RouterLSA* joiningVertex = FindRouterLSA(networkVertex->getAttachedRouters(i).getInt());
01483                 if ((joiningVertex == NULL) ||
01484                     (joiningVertex->getHeader().getLsAge() == MAX_AGE) ||
01485                     (!HasLink(joiningVertex, justAddedVertex)))  // (from, to)     (2) (b)
01486                 {
01487                     continue;
01488                 }
01489 
01490                 unsigned int treeSize      = treeVertices.size();
01491                 bool         alreadyOnTree = false;
01492 
01493                 for (j = 0; j < treeSize; j++) {
01494                     if (treeVertices[j] == joiningVertex) {
01495                         alreadyOnTree = true;
01496                         break;
01497                     }
01498                 }
01499                 if (alreadyOnTree) {    // (2) (c)
01500                     continue;
01501                 }
01502 
01503                 unsigned long linkStateCost  = networkVertex->GetDistance();   // link cost from network to router is always 0
01504                 unsigned int  candidateCount = candidateVertices.size();
01505                 OSPFLSA*      candidate      = NULL;
01506 
01507                 for (j = 0; j < candidateCount; j++) {
01508                     if (candidateVertices[j] == joiningVertex) {
01509                         candidate = candidateVertices[j];
01510                     }
01511                 }
01512                 if (candidate != NULL) {    // (2) (d)
01513                     OSPF::RoutingInfo* routingInfo       = check_and_cast<OSPF::RoutingInfo*> (candidate);
01514                     unsigned long      candidateDistance = routingInfo->GetDistance();
01515 
01516                     if (linkStateCost > candidateDistance) {
01517                         continue;
01518                     }
01519                     if (linkStateCost < candidateDistance) {
01520                         routingInfo->SetDistance(linkStateCost);
01521                         routingInfo->ClearNextHops();
01522                     }
01523                     std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(joiningVertex, justAddedVertex); // (destination, parent)
01524                     unsigned int nextHopCount = newNextHops->size();
01525                     for (k = 0; k < nextHopCount; k++) {
01526                         routingInfo->AddNextHop((*newNextHops)[k]);
01527                     }
01528                     delete newNextHops;
01529                 } else {
01530                     joiningVertex->SetDistance(linkStateCost);
01531                     std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(joiningVertex, justAddedVertex); // (destination, parent)
01532                     unsigned int nextHopCount = newNextHops->size();
01533                     for (k = 0; k < nextHopCount; k++) {
01534                         joiningVertex->AddNextHop((*newNextHops)[k]);
01535                     }
01536                     delete newNextHops;
01537                     OSPF::RoutingInfo* vertexRoutingInfo = check_and_cast<OSPF::RoutingInfo*> (joiningVertex);
01538                     vertexRoutingInfo->SetParent(justAddedVertex);
01539 
01540                     candidateVertices.push_back(joiningVertex);
01541                 }
01542             }
01543         }
01544 
01545         if (candidateVertices.empty()) {  // (3)
01546             finished = true;
01547         } else {
01548             unsigned int  candidateCount = candidateVertices.size();
01549             unsigned long minDistance = LS_INFINITY;
01550             OSPFLSA*      closestVertex = candidateVertices[0];
01551 
01552             for (i = 0; i < candidateCount; i++) {
01553                 OSPF::RoutingInfo* routingInfo     = check_and_cast<OSPF::RoutingInfo*> (candidateVertices[i]);
01554                 unsigned long      currentDistance = routingInfo->GetDistance();
01555 
01556                 if (currentDistance < minDistance) {
01557                     closestVertex = candidateVertices[i];
01558                     minDistance = currentDistance;
01559                 } else {
01560                     if (currentDistance == minDistance) {
01561                         if ((closestVertex->getHeader().getLsType() == RouterLSAType) &&
01562                             (candidateVertices[i]->getHeader().getLsType() == NetworkLSAType))
01563                         {
01564                             closestVertex = candidateVertices[i];
01565                         }
01566                     }
01567                 }
01568             }
01569 
01570             treeVertices.push_back(closestVertex);
01571 
01572             for (std::vector<OSPFLSA*>::iterator it = candidateVertices.begin(); it != candidateVertices.end(); it++) {
01573                 if ((*it) == closestVertex) {
01574                     candidateVertices.erase(it);
01575                     break;
01576                 }
01577             }
01578 
01579             if (closestVertex->getHeader().getLsType() == RouterLSAType) {
01580                 OSPF::RouterLSA* routerLSA = check_and_cast<OSPF::RouterLSA*> (closestVertex);
01581                 if (routerLSA->getB_AreaBorderRouter() || routerLSA->getE_ASBoundaryRouter()) {
01582                     OSPF::RoutingTableEntry*                        entry           = new OSPF::RoutingTableEntry;
01583                     OSPF::RouterID                                  destinationID   = routerLSA->getHeader().getLinkStateID();
01584                     unsigned int                                    nextHopCount    = routerLSA->GetNextHopCount();
01585                     OSPF::RoutingTableEntry::RoutingDestinationType destinationType = OSPF::RoutingTableEntry::NetworkDestination;
01586 
01587                     entry->SetDestinationID(destinationID);
01588                     entry->SetLinkStateOrigin(routerLSA);
01589                     entry->SetArea(areaID);
01590                     entry->SetPathType(OSPF::RoutingTableEntry::IntraArea);
01591                     entry->SetCost(routerLSA->GetDistance());
01592                     if (routerLSA->getB_AreaBorderRouter()) {
01593                         destinationType |= OSPF::RoutingTableEntry::AreaBorderRouterDestination;
01594                     }
01595                     if (routerLSA->getE_ASBoundaryRouter()) {
01596                         destinationType |= OSPF::RoutingTableEntry::ASBoundaryRouterDestination;
01597                     }
01598                     entry->SetDestinationType(destinationType);
01599                     entry->SetOptionalCapabilities(routerLSA->getHeader().getLsOptions());
01600                     for (i = 0; i < nextHopCount; i++) {
01601                         entry->AddNextHop(routerLSA->GetNextHop(i));
01602                     }
01603 
01604                     newRoutingTable.push_back(entry);
01605 
01606                     OSPF::Area* backbone;
01607                     if (areaID != OSPF::BackboneAreaID) {
01608                         backbone = parentRouter->GetArea(OSPF::BackboneAreaID);
01609                     } else {
01610                         backbone = this;
01611                     }
01612                     if (backbone != NULL) {
01613                         OSPF::Interface* virtualIntf = backbone->FindVirtualLink(destinationID);
01614                         if ((virtualIntf != NULL) && (virtualIntf->GetTransitAreaID() == areaID)) {
01615                             OSPF::IPv4AddressRange range;
01616                             range.address = GetInterface(routerLSA->GetNextHop(0).ifIndex)->GetAddressRange().address;
01617                             range.mask    = IPv4AddressFromULong(0xFFFFFFFF);
01618                             virtualIntf->SetAddressRange(range);
01619                             virtualIntf->SetIfIndex(routerLSA->GetNextHop(0).ifIndex);
01620                             virtualIntf->SetOutputCost(routerLSA->GetDistance());
01621                             OSPF::Neighbor* virtualNeighbor = virtualIntf->GetNeighbor(0);
01622                             if (virtualNeighbor != NULL) {
01623                                 unsigned int     linkCount   = routerLSA->getLinksArraySize();
01624                                 OSPF::RouterLSA* toRouterLSA = dynamic_cast<OSPF::RouterLSA*> (justAddedVertex);
01625                                 if (toRouterLSA != NULL) {
01626                                     for (i = 0; i < linkCount; i++) {
01627                                         Link& link = routerLSA->getLinks(i);
01628 
01629                                         if ((link.getType() == PointToPointLink) &&
01630                                             (link.getLinkID() == toRouterLSA->getHeader().getLinkStateID()) &&
01631                                             (virtualIntf->GetState() < OSPF::Interface::WaitingState))
01632                                         {
01633                                             virtualNeighbor->SetAddress(IPv4AddressFromULong(link.getLinkData()));
01634                                             virtualIntf->ProcessEvent(OSPF::Interface::InterfaceUp);
01635                                             break;
01636                                         }
01637                                     }
01638                                 } else {
01639                                     OSPF::NetworkLSA* toNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (justAddedVertex);
01640                                     if (toNetworkLSA != NULL) {
01641                                         for (i = 0; i < linkCount; i++) {
01642                                             Link& link = routerLSA->getLinks(i);
01643 
01644                                             if ((link.getType() == TransitLink) &&
01645                                                 (link.getLinkID() == toNetworkLSA->getHeader().getLinkStateID()) &&
01646                                                 (virtualIntf->GetState() < OSPF::Interface::WaitingState))
01647                                             {
01648                                                 virtualNeighbor->SetAddress(IPv4AddressFromULong(link.getLinkData()));
01649                                                 virtualIntf->ProcessEvent(OSPF::Interface::InterfaceUp);
01650                                                 break;
01651                                             }
01652                                         }
01653                                     }
01654                                 }
01655                             }
01656                         }
01657                     }
01658                 }
01659             }
01660 
01661             if (closestVertex->getHeader().getLsType() == NetworkLSAType) {
01662                 OSPF::NetworkLSA*        networkLSA    = check_and_cast<OSPF::NetworkLSA*> (closestVertex);
01663                 unsigned long            destinationID = (networkLSA->getHeader().getLinkStateID() & networkLSA->getNetworkMask().getInt());
01664                 unsigned int             nextHopCount  = networkLSA->GetNextHopCount();
01665                 bool                     overWrite     = false;
01666                 OSPF::RoutingTableEntry* entry         = NULL;
01667                 unsigned long            routeCount    = newRoutingTable.size();
01668                 unsigned long            longestMatch  = 0;
01669 
01670                 for (i = 0; i < routeCount; i++) {
01671                     if (newRoutingTable[i]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) {
01672                         OSPF::RoutingTableEntry* routingEntry = newRoutingTable[i];
01673                         unsigned long            entryAddress = routingEntry->GetDestinationID().getInt();
01674                         unsigned long            entryMask    = routingEntry->GetAddressMask().getInt();
01675 
01676                         if ((entryAddress & entryMask) == (destinationID & entryMask)) {
01677                             if ((destinationID & entryMask) > longestMatch) {
01678                                 longestMatch = (destinationID & entryMask);
01679                                 entry        = routingEntry;
01680                             }
01681                         }
01682                     }
01683                 }
01684                 if (entry != NULL) {
01685                     const OSPFLSA* entryOrigin = entry->GetLinkStateOrigin();
01686                     if ((entry->GetCost() != networkLSA->GetDistance()) ||
01687                         (entryOrigin->getHeader().getLinkStateID() >= networkLSA->getHeader().getLinkStateID()))
01688                     {
01689                         overWrite = true;
01690                     }
01691                 }
01692 
01693                 if ((entry == NULL) || (overWrite)) {
01694                     if (entry == NULL) {
01695                         entry = new OSPF::RoutingTableEntry;
01696                     }
01697 
01698                     entry->SetDestinationID(destinationID);
01699                     entry->SetAddressMask(networkLSA->getNetworkMask());
01700                     entry->SetLinkStateOrigin(networkLSA);
01701                     entry->SetArea(areaID);
01702                     entry->SetPathType(OSPF::RoutingTableEntry::IntraArea);
01703                     entry->SetCost(networkLSA->GetDistance());
01704                     entry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
01705                     entry->SetOptionalCapabilities(networkLSA->getHeader().getLsOptions());
01706                     for (i = 0; i < nextHopCount; i++) {
01707                         entry->AddNextHop(networkLSA->GetNextHop(i));
01708                     }
01709 
01710                     if (!overWrite) {
01711                         newRoutingTable.push_back(entry);
01712                     }
01713                 }
01714             }
01715 
01716             justAddedVertex = closestVertex;
01717         }
01718     } while (!finished);
01719 
01720     unsigned int treeSize      = treeVertices.size();
01721     for (i = 0; i < treeSize; i++) {
01722         OSPF::RouterLSA* routerVertex = dynamic_cast<OSPF::RouterLSA*> (treeVertices[i]);
01723         if (routerVertex == NULL) {
01724             continue;
01725         }
01726 
01727         unsigned int linkCount = routerVertex->getLinksArraySize();
01728         for (j = 0; j < linkCount; j++) {
01729             Link&    link     = routerVertex->getLinks(j);
01730             if (link.getType() != StubLink) {
01731                 continue;
01732             }
01733 
01734             unsigned long            distance      = routerVertex->GetDistance() + link.getLinkCost();
01735             unsigned long            destinationID = (link.getLinkID().getInt() & link.getLinkData());
01736             OSPF::RoutingTableEntry* entry         = NULL;
01737             unsigned long            routeCount    = newRoutingTable.size();
01738             unsigned long            longestMatch  = 0;
01739 
01740             for (k = 0; k < routeCount; k++) {
01741                 if (newRoutingTable[k]->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) {
01742                     OSPF::RoutingTableEntry* routingEntry = newRoutingTable[k];
01743                     unsigned long            entryAddress = routingEntry->GetDestinationID().getInt();
01744                     unsigned long            entryMask    = routingEntry->GetAddressMask().getInt();
01745 
01746                     if ((entryAddress & entryMask) == (destinationID & entryMask)) {
01747                         if ((destinationID & entryMask) > longestMatch) {
01748                             longestMatch = (destinationID & entryMask);
01749                             entry        = routingEntry;
01750                         }
01751                     }
01752                 }
01753             }
01754 
01755             if (entry != NULL) {
01756                 Metric entryCost = entry->GetCost();
01757 
01758                 if (distance > entryCost) {
01759                     continue;
01760                 }
01761                 if (distance < entryCost) {
01762                     //FIXME remove
01763                     //if(parentRouter->GetRouterID() == 0xC0A80302) {
01764                     //    EV << "CHEAPER STUB LINK FOUND TO " << IPAddress(destinationID).str() << "\n";
01765                     //}
01766                     entry->SetCost(distance);
01767                     entry->ClearNextHops();
01768                     entry->SetLinkStateOrigin(routerVertex);
01769                 }
01770                 if (distance == entryCost) {
01771                     // no const version from check_and_cast
01772                     OSPF::RouterLSA* routerOrigin = check_and_cast<OSPF::RouterLSA*> (const_cast<OSPFLSA*> (entry->GetLinkStateOrigin()));
01773                     if (routerOrigin->getHeader().getLinkStateID() < routerVertex->getHeader().getLinkStateID()) {
01774                         entry->SetLinkStateOrigin(routerVertex);
01775                     }
01776                 }
01777                 std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(link, routerVertex); // (destination, parent)
01778                 unsigned int nextHopCount = newNextHops->size();
01779                 for (k = 0; k < nextHopCount; k++) {
01780                     entry->AddNextHop((*newNextHops)[k]);
01781                 }
01782                 delete newNextHops;
01783             } else {
01784                 //FIXME remove
01785                 //if(parentRouter->GetRouterID() == 0xC0A80302) {
01786                 //    EV << "STUB LINK FOUND TO " << IPAddress(destinationID).str() << "\n";
01787                 //}
01788                 entry = new OSPF::RoutingTableEntry;
01789 
01790                 entry->SetDestinationID(destinationID);
01791                 entry->SetAddressMask(link.getLinkData());
01792                 entry->SetLinkStateOrigin(routerVertex);
01793                 entry->SetArea(areaID);
01794                 entry->SetPathType(OSPF::RoutingTableEntry::IntraArea);
01795                 entry->SetCost(distance);
01796                 entry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
01797                 entry->SetOptionalCapabilities(routerVertex->getHeader().getLsOptions());
01798                 std::vector<OSPF::NextHop>* newNextHops = CalculateNextHops(link, routerVertex); // (destination, parent)
01799                 unsigned int nextHopCount = newNextHops->size();
01800                 for (k = 0; k < nextHopCount; k++) {
01801                     entry->AddNextHop((*newNextHops)[k]);
01802                 }
01803                 delete newNextHops;
01804 
01805                 newRoutingTable.push_back(entry);
01806             }
01807         }
01808     }
01809 }
01810 
01811 std::vector<OSPF::NextHop>* OSPF::Area::CalculateNextHops(OSPFLSA* destination, OSPFLSA* parent) const
01812 {
01813     std::vector<OSPF::NextHop>* hops = new std::vector<OSPF::NextHop>;
01814     unsigned long               i, j;
01815 
01816     OSPF::RouterLSA* routerLSA = dynamic_cast<OSPF::RouterLSA*> (parent);
01817     if (routerLSA != NULL) {
01818         if (routerLSA != spfTreeRoot) {
01819             unsigned int nextHopCount = routerLSA->GetNextHopCount();
01820             for (i = 0; i < nextHopCount; i++) {
01821                 hops->push_back(routerLSA->GetNextHop(i));
01822             }
01823             return hops;
01824         } else {
01825             OSPF::RouterLSA* destinationRouterLSA = dynamic_cast<OSPF::RouterLSA*> (destination);
01826             if (destinationRouterLSA != NULL) {
01827                 unsigned long interfaceNum   = associatedInterfaces.size();
01828                 for (i = 0; i < interfaceNum; i++) {
01829                     OSPF::Interface::OSPFInterfaceType intfType = associatedInterfaces[i]->GetType();
01830                     if ((intfType == OSPF::Interface::PointToPoint) ||
01831                         ((intfType == OSPF::Interface::Virtual) &&
01832                          (associatedInterfaces[i]->GetState() > OSPF::Interface::LoopbackState)))
01833                     {
01834                         OSPF::Neighbor* ptpNeighbor = associatedInterfaces[i]->GetNeighborCount() > 0 ? associatedInterfaces[i]->GetNeighbor(0) : NULL;
01835                         if (ptpNeighbor != NULL) {
01836                             if (ptpNeighbor->GetNeighborID() == destinationRouterLSA->getHeader().getLinkStateID()) {
01837                                 NextHop nextHop;
01838                                 nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
01839                                 nextHop.hopAddress        = ptpNeighbor->GetAddress();
01840                                 nextHop.advertisingRouter = destinationRouterLSA->getHeader().getAdvertisingRouter().getInt();
01841                                 hops->push_back(nextHop);
01842                                 break;
01843                             }
01844                         }
01845                     }
01846                     if (intfType == OSPF::Interface::PointToMultiPoint) {
01847                         OSPF::Neighbor* ptmpNeighbor = associatedInterfaces[i]->GetNeighborByID(destinationRouterLSA->getHeader().getLinkStateID());
01848                         if (ptmpNeighbor != NULL) {
01849                             unsigned int   linkCount = destinationRouterLSA->getLinksArraySize();
01850                             OSPF::RouterID rootID    = parentRouter->GetRouterID();
01851                             for (j = 0; j < linkCount; j++) {
01852                                 Link& link = destinationRouterLSA->getLinks(j);
01853                                 if (link.getLinkID() == rootID) {
01854                                     NextHop nextHop;
01855                                     nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
01856                                     nextHop.hopAddress        = IPv4AddressFromULong(link.getLinkData());
01857                                     nextHop.advertisingRouter = destinationRouterLSA->getHeader().getAdvertisingRouter().getInt();
01858                                     hops->push_back(nextHop);
01859                                 }
01860                             }
01861                             break;
01862                         }
01863                     }
01864                 }
01865             } else {
01866                 OSPF::NetworkLSA* destinationNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (destination);
01867                 if (destinationNetworkLSA != NULL) {
01868                     OSPF::IPv4Address networkDesignatedRouter = IPv4AddressFromULong(destinationNetworkLSA->getHeader().getLinkStateID());
01869                     unsigned long     interfaceNum            = associatedInterfaces.size();
01870                     for (i = 0; i < interfaceNum; i++) {
01871                         OSPF::Interface::OSPFInterfaceType intfType = associatedInterfaces[i]->GetType();
01872                         if (((intfType == OSPF::Interface::Broadcast) ||
01873                              (intfType == OSPF::Interface::NBMA)) &&
01874                             (associatedInterfaces[i]->GetDesignatedRouter().ipInterfaceAddress == networkDesignatedRouter))
01875                         {
01876                             OSPF::IPv4AddressRange range = associatedInterfaces[i]->GetAddressRange();
01877                             NextHop                nextHop;
01878 
01879                             nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
01880                             nextHop.hopAddress        = (range.address & range.mask);
01881                             nextHop.advertisingRouter = destinationNetworkLSA->getHeader().getAdvertisingRouter().getInt();
01882                             hops->push_back(nextHop);
01883                         }
01884                     }
01885                 }
01886             }
01887         }
01888     } else {
01889         OSPF::NetworkLSA* networkLSA = dynamic_cast<OSPF::NetworkLSA*> (parent);
01890         if (networkLSA != NULL) {
01891             if (networkLSA->GetParent() != spfTreeRoot) {
01892                 unsigned int nextHopCount = networkLSA->GetNextHopCount();
01893                 for (i = 0; i < nextHopCount; i++) {
01894                     hops->push_back(networkLSA->GetNextHop(i));
01895                 }
01896                 return hops;
01897             } else {
01898                 unsigned long parentLinkStateID = parent->getHeader().getLinkStateID();
01899 
01900                 OSPF::RouterLSA* destinationRouterLSA = dynamic_cast<OSPF::RouterLSA*> (destination);
01901                 if (destinationRouterLSA != NULL) {
01902                     OSPF::RouterID destinationRouterID = destinationRouterLSA->getHeader().getLinkStateID();
01903                     unsigned int   linkCount           = destinationRouterLSA->getLinksArraySize();
01904                     for (i = 0; i < linkCount; i++) {
01905                         Link&   link = destinationRouterLSA->getLinks(i);
01906                         NextHop nextHop;
01907 
01908                         if (((link.getType() == TransitLink) &&
01909                              (link.getLinkID().getInt() == parentLinkStateID)) ||
01910                             ((link.getType() == StubLink) &&
01911                              ((link.getLinkID().getInt() & link.getLinkData()) == (parentLinkStateID & networkLSA->getNetworkMask().getInt()))))
01912                         {
01913                             unsigned long interfaceNum   = associatedInterfaces.size();
01914                             for (j = 0; j < interfaceNum; j++) {
01915                                 OSPF::Interface::OSPFInterfaceType intfType = associatedInterfaces[j]->GetType();
01916                                 if (((intfType == OSPF::Interface::Broadcast) ||
01917                                      (intfType == OSPF::Interface::NBMA)) &&
01918                                     (associatedInterfaces[j]->GetDesignatedRouter().ipInterfaceAddress == IPv4AddressFromULong(parentLinkStateID)))
01919                                 {
01920                                     OSPF::Neighbor* nextHopNeighbor = associatedInterfaces[j]->GetNeighborByID(destinationRouterID);
01921                                     if (nextHopNeighbor != NULL) {
01922                                         nextHop.ifIndex           = associatedInterfaces[j]->GetIfIndex();
01923                                         nextHop.hopAddress        = nextHopNeighbor->GetAddress();
01924                                         nextHop.advertisingRouter = destinationRouterLSA->getHeader().getAdvertisingRouter().getInt();
01925                                         hops->push_back(nextHop);
01926                                     }
01927                                 }
01928                             }
01929                         }
01930                     }
01931                 }
01932             }
01933         }
01934     }
01935 
01936     return hops;
01937 }
01938 
01939 std::vector<OSPF::NextHop>* OSPF::Area::CalculateNextHops(Link& destination, OSPFLSA* parent) const
01940 {
01941     std::vector<OSPF::NextHop>* hops = new std::vector<OSPF::NextHop>;
01942     unsigned long                i;
01943 
01944     OSPF::RouterLSA* routerLSA = check_and_cast<OSPF::RouterLSA*> (parent);
01945     if (routerLSA != spfTreeRoot) {
01946         unsigned int nextHopCount = routerLSA->GetNextHopCount();
01947         for (i = 0; i < nextHopCount; i++) {
01948             hops->push_back(routerLSA->GetNextHop(i));
01949         }
01950         return hops;
01951     } else {
01952         unsigned long interfaceNum = associatedInterfaces.size();
01953         for (i = 0; i < interfaceNum; i++) {
01954             OSPF::Interface::OSPFInterfaceType intfType = associatedInterfaces[i]->GetType();
01955 
01956             if ((intfType == OSPF::Interface::PointToPoint) ||
01957                 ((intfType == OSPF::Interface::Virtual) &&
01958                  (associatedInterfaces[i]->GetState() > OSPF::Interface::LoopbackState)))
01959             {
01960                 OSPF::Neighbor* neighbor = (associatedInterfaces[i]->GetNeighborCount() > 0) ? associatedInterfaces[i]->GetNeighbor(0) : NULL;
01961                 if (neighbor != NULL) {
01962                     OSPF::IPv4Address neighborAddress = neighbor->GetAddress();
01963                     if (((neighborAddress != OSPF::NullIPv4Address) &&
01964                          (ULongFromIPv4Address(neighborAddress) == destination.getLinkID().getInt())) ||
01965                         ((neighborAddress == OSPF::NullIPv4Address) &&
01966                          (ULongFromIPv4Address(associatedInterfaces[i]->GetAddressRange().address) == destination.getLinkID().getInt()) &&
01967                          (ULongFromIPv4Address(associatedInterfaces[i]->GetAddressRange().mask) == destination.getLinkData())))
01968                     {
01969                         NextHop nextHop;
01970                         nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
01971                         nextHop.hopAddress        = neighborAddress;
01972                         nextHop.advertisingRouter = parentRouter->GetRouterID();
01973                         hops->push_back(nextHop);
01974                         break;
01975                     }
01976                 }
01977             }
01978             if ((intfType == OSPF::Interface::Broadcast) ||
01979                 (intfType == OSPF::Interface::NBMA))
01980             {
01981                 if ((destination.getLinkID().getInt() == ULongFromIPv4Address(associatedInterfaces[i]->GetAddressRange().address & associatedInterfaces[i]->GetAddressRange().mask)) &&
01982                     (destination.getLinkData() == ULongFromIPv4Address(associatedInterfaces[i]->GetAddressRange().mask)))
01983                 {
01984                     NextHop nextHop;
01985                     nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
01986                     nextHop.hopAddress        = IPv4AddressFromULong(destination.getLinkID().getInt());
01987                     nextHop.advertisingRouter = parentRouter->GetRouterID();
01988                     hops->push_back(nextHop);
01989                     break;
01990                 }
01991             }
01992             if (intfType == OSPF::Interface::PointToMultiPoint) {
01993                 if (destination.getType() == StubLink) {
01994                     if (destination.getLinkID().getInt() == ULongFromIPv4Address(associatedInterfaces[i]->GetAddressRange().address)) {
01995                         // The link contains the router's own interface address and a full mask,
01996                         // so we insert a next hop pointing to the interface itself. Kind of pointless, but
01997                         // not much else we could do...
01998                         // TODO: check what other OSPF implementations do in this situation
01999                         NextHop nextHop;
02000                         nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
02001                         nextHop.hopAddress        = associatedInterfaces[i]->GetAddressRange().address;
02002                         nextHop.advertisingRouter = parentRouter->GetRouterID();
02003                         hops->push_back(nextHop);
02004                         break;
02005                     }
02006                 }
02007                 if (destination.getType() == PointToPointLink) {
02008                     OSPF::Neighbor* neighbor = associatedInterfaces[i]->GetNeighborByID(destination.getLinkID().getInt());
02009                     if (neighbor != NULL) {
02010                         NextHop nextHop;
02011                         nextHop.ifIndex           = associatedInterfaces[i]->GetIfIndex();
02012                         nextHop.hopAddress        = neighbor->GetAddress();
02013                         nextHop.advertisingRouter = parentRouter->GetRouterID();
02014                         hops->push_back(nextHop);
02015                         break;
02016                     }
02017                 }
02018             }
02019             // next hops for virtual links are generated later, after examining transit areas' SummaryLSAs
02020         }
02021 
02022         if (hops->size() == 0) {
02023             unsigned long hostRouteCount = hostRoutes.size();
02024             for (i = 0; i < hostRouteCount; i++) {
02025                 if ((destination.getLinkID().getInt() == ULongFromIPv4Address(hostRoutes[i].address)) &&
02026                     (destination.getLinkData() == 0xFFFFFFFF))
02027                 {
02028                     NextHop nextHop;
02029                     nextHop.ifIndex           = hostRoutes[i].ifIndex;
02030                     nextHop.hopAddress        = hostRoutes[i].address;
02031                     nextHop.advertisingRouter = parentRouter->GetRouterID();
02032                     hops->push_back(nextHop);
02033                     break;
02034                 }
02035             }
02036         }
02037     }
02038 
02039     return hops;
02040 }
02041 
02042 bool OSPF::Area::HasLink(OSPFLSA* fromLSA, OSPFLSA* toLSA) const
02043 {
02044     unsigned int i;
02045 
02046     OSPF::RouterLSA* fromRouterLSA = dynamic_cast<OSPF::RouterLSA*> (fromLSA);
02047     if (fromRouterLSA != NULL) {
02048         unsigned int     linkCount   = fromRouterLSA->getLinksArraySize();
02049         OSPF::RouterLSA* toRouterLSA = dynamic_cast<OSPF::RouterLSA*> (toLSA);
02050         if (toRouterLSA != NULL) {
02051             for (i = 0; i < linkCount; i++) {
02052                 Link&    link     = fromRouterLSA->getLinks(i);
02053                 LinkType linkType = static_cast<LinkType> (link.getType());
02054 
02055                 if (((linkType == PointToPointLink) ||
02056                      (linkType == VirtualLink)) &&
02057                     (link.getLinkID().getInt() == toRouterLSA->getHeader().getLinkStateID()))
02058                 {
02059                     return true;
02060                 }
02061             }
02062         } else {
02063             OSPF::NetworkLSA* toNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (toLSA);
02064             if (toNetworkLSA != NULL) {
02065                 for (i = 0; i < linkCount; i++) {
02066                     Link&    link     = fromRouterLSA->getLinks(i);
02067 
02068                     if ((link.getType() == TransitLink) &&
02069                         (link.getLinkID().getInt() == toNetworkLSA->getHeader().getLinkStateID()))
02070                     {
02071                         return true;
02072                     }
02073                     if ((link.getType() == StubLink) &&
02074                         ((link.getLinkID().getInt() & link.getLinkData()) == (toNetworkLSA->getHeader().getLinkStateID() & toNetworkLSA->getNetworkMask().getInt())))
02075                     {
02076                         return true;
02077                     }
02078                 }
02079             }
02080         }
02081     } else {
02082         OSPF::NetworkLSA* fromNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (fromLSA);
02083         if (fromNetworkLSA != NULL) {
02084             unsigned int     routerCount   = fromNetworkLSA->getAttachedRoutersArraySize();
02085             OSPF::RouterLSA* toRouterLSA = dynamic_cast<OSPF::RouterLSA*> (toLSA);
02086             if (toRouterLSA != NULL) {
02087                 for (i = 0; i < routerCount; i++) {
02088                     if (fromNetworkLSA->getAttachedRouters(i).getInt() == toRouterLSA->getHeader().getLinkStateID()) {
02089                         return true;
02090                     }
02091                 }
02092             }
02093         }
02094     }
02095 
02096     return false;
02097 }
02098 
02104 bool OSPF::Area::FindSameOrWorseCostRoute(const std::vector<OSPF::RoutingTableEntry*>& newRoutingTable,
02105                                            const OSPF::SummaryLSA&                      summaryLSA,
02106                                            unsigned short                               currentCost,
02107                                            bool&                                        destinationInRoutingTable,
02108                                            std::list<OSPF::RoutingTableEntry*>&         sameOrWorseCost) const
02109 {
02110     destinationInRoutingTable = false;
02111     sameOrWorseCost.clear();
02112 
02113     long                   routeCount = newRoutingTable.size();
02114     OSPF::IPv4AddressRange destination;
02115 
02116     destination.address = IPv4AddressFromULong(summaryLSA.getHeader().getLinkStateID());
02117     destination.mask    = IPv4AddressFromULong(summaryLSA.getNetworkMask().getInt());
02118 
02119     for (long j = 0; j < routeCount; j++) {
02120         OSPF::RoutingTableEntry* routingEntry  = newRoutingTable[j];
02121         bool                     foundMatching = false;
02122 
02123         if (summaryLSA.getHeader().getLsType() == SummaryLSA_NetworksType) {
02124             if ((routingEntry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
02125                 (ULongFromIPv4Address(destination.address & destination.mask) == routingEntry->GetDestinationID().getInt()))
02126             {
02127                 foundMatching = true;
02128             }
02129         } else {
02130             if ((((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
02131                  ((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
02132                 (ULongFromIPv4Address(destination.address) == routingEntry->GetDestinationID().getInt()))
02133             {
02134                 foundMatching = true;
02135             }
02136         }
02137 
02138         if (foundMatching) {
02139             destinationInRoutingTable = true;
02140 
02141             /* If the matching entry is an IntraArea getRoute(intra-area paths are
02142                 * always preferred to other paths of any cost), or it's a cheaper InterArea
02143                 * route, then skip this LSA.
02144                 */
02145             if ((routingEntry->GetPathType() == OSPF::RoutingTableEntry::IntraArea) ||
02146                 ((routingEntry->GetPathType() == OSPF::RoutingTableEntry::InterArea) &&
02147                  (routingEntry->GetCost() < currentCost)))
02148             {
02149                 return true;
02150             } else {
02151                 // if it's an other InterArea path
02152                 if ((routingEntry->GetPathType() == OSPF::RoutingTableEntry::InterArea) &&
02153                     (routingEntry->GetCost() >= currentCost))
02154                 {
02155                     sameOrWorseCost.push_back(routingEntry);
02156                 }   // else it's external -> same as if not in the table
02157             }
02158         }
02159     }
02160     return false;
02161 }
02162 
02167 OSPF::RoutingTableEntry* OSPF::Area::CreateRoutingTableEntryFromSummaryLSA(const OSPF::SummaryLSA&        summaryLSA,
02168                                                                             unsigned short                 entryCost,
02169                                                                             const OSPF::RoutingTableEntry& borderRouterEntry) const
02170 {
02171     OSPF::IPv4AddressRange destination;
02172 
02173     destination.address = IPv4AddressFromULong(summaryLSA.getHeader().getLinkStateID());
02174     destination.mask    = IPv4AddressFromULong(summaryLSA.getNetworkMask().getInt());
02175 
02176     OSPF::RoutingTableEntry* newEntry = new OSPF::RoutingTableEntry;
02177 
02178     if (summaryLSA.getHeader().getLsType() == SummaryLSA_NetworksType) {
02179         newEntry->SetDestinationID(ULongFromIPv4Address(destination.address & destination.mask));
02180         newEntry->SetAddressMask(ULongFromIPv4Address(destination.mask));
02181         newEntry->SetDestinationType(OSPF::RoutingTableEntry::NetworkDestination);
02182     } else {
02183         newEntry->SetDestinationID(ULongFromIPv4Address(destination.address));
02184         newEntry->SetAddressMask(0xFFFFFFFF);
02185         newEntry->SetDestinationType(OSPF::RoutingTableEntry::ASBoundaryRouterDestination);
02186     }
02187     newEntry->SetArea(areaID);
02188     newEntry->SetPathType(OSPF::RoutingTableEntry::InterArea);
02189     newEntry->SetCost(entryCost);
02190     newEntry->SetOptionalCapabilities(summaryLSA.getHeader().getLsOptions());
02191     newEntry->SetLinkStateOrigin(&summaryLSA);
02192 
02193     unsigned int nextHopCount = borderRouterEntry.GetNextHopCount();
02194     for (unsigned int j = 0; j < nextHopCount; j++) {
02195         newEntry->AddNextHop(borderRouterEntry.GetNextHop(j));
02196     }
02197 
02198     return newEntry;
02199 }
02200 
02207 void OSPF::Area::CalculateInterAreaRoutes(std::vector<OSPF::RoutingTableEntry*>& newRoutingTable)
02208 {
02209     unsigned long i = 0;
02210     unsigned long j = 0;
02211     unsigned long lsaCount = summaryLSAs.size();
02212 
02213     for (i = 0; i < lsaCount; i++) {
02214         OSPF::SummaryLSA* currentLSA        = summaryLSAs[i];
02215         OSPFLSAHeader&    currentHeader     = currentLSA->getHeader();
02216 
02217         unsigned long     routeCost         = currentLSA->getRouteCost();
02218         unsigned short    lsAge             = currentHeader.getLsAge();
02219         RouterID          originatingRouter = currentHeader.getAdvertisingRouter().getInt();
02220         bool              selfOriginated    = (originatingRouter == parentRouter->GetRouterID());
02221 
02222         if ((routeCost == LS_INFINITY) || (lsAge == MAX_AGE) || (selfOriginated)) { // (1) and(2)
02223             continue;
02224         }
02225 
02226         char                   lsType     = currentHeader.getLsType();
02227         unsigned long          routeCount = newRoutingTable.size();
02228         OSPF::IPv4AddressRange destination;
02229 
02230         destination.address = IPv4AddressFromULong(currentHeader.getLinkStateID());
02231         destination.mask    = IPv4AddressFromULong(currentLSA->getNetworkMask().getInt());
02232 
02233         if ((lsType == SummaryLSA_NetworksType) && (parentRouter->HasAddressRange(destination))) { // (3)
02234             bool foundIntraAreaRoute = false;
02235 
02236             // look for an "Active" IntraArea route
02237             for (j = 0; j < routeCount; j++) {
02238                 OSPF::RoutingTableEntry* routingEntry = newRoutingTable[j];
02239 
02240                 if ((routingEntry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
02241                     (routingEntry->GetPathType() == OSPF::RoutingTableEntry::IntraArea) &&
02242                     ((routingEntry->GetDestinationID().getInt() &
02243                       routingEntry->GetAddressMask().getInt()   &
02244                       ULongFromIPv4Address(destination.mask)       ) == ULongFromIPv4Address(destination.address &
02245                                                                                                destination.mask)))
02246                 {
02247                     foundIntraAreaRoute = true;
02248                     break;
02249                 }
02250             }
02251             if (foundIntraAreaRoute) {
02252                 continue;
02253             }
02254         }
02255 
02256         OSPF::RoutingTableEntry* borderRouterEntry = NULL;
02257 
02258         // The routingEntry describes a route to an other area -> look for the border router originating it
02259         for (j = 0; j < routeCount; j++) {     // (4) N == destination, BR == borderRouterEntry
02260             OSPF::RoutingTableEntry* routingEntry = newRoutingTable[j];
02261 
02262             if ((routingEntry->GetArea() == areaID) &&
02263                 (((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
02264                  ((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
02265                 (routingEntry->GetDestinationID().getInt() == originatingRouter))
02266             {
02267                 borderRouterEntry = routingEntry;
02268                 break;
02269             }
02270         }
02271         if (borderRouterEntry == NULL) {
02272             continue;
02273         } else {    // (5)
02274             /* "Else, this LSA describes an inter-area path to destination N,
02275              * whose cost is the distance to BR plus the cost specified in the LSA.
02276              * Call the cost of this inter-area path IAC."
02277              */
02278             bool                                destinationInRoutingTable = true;
02279             unsigned short                      currentCost               = routeCost + borderRouterEntry->GetCost();
02280             std::list<OSPF::RoutingTableEntry*> sameOrWorseCost;
02281 
02282             if (FindSameOrWorseCostRoute(newRoutingTable,
02283                                           *currentLSA,
02284                                           currentCost,
02285                                           destinationInRoutingTable,
02286                                           sameOrWorseCost))
02287             {
02288                 continue;
02289             }
02290 
02291             if (destinationInRoutingTable && (sameOrWorseCost.size() > 0)) {
02292                 OSPF::RoutingTableEntry* equalEntry = NULL;
02293 
02294                 /* Look for an equal cost entry in the sameOrWorseCost list, and
02295                  * also clear the more expensive entries from the newRoutingTable.
02296                  */
02297                 for (std::list<OSPF::RoutingTableEntry*>::iterator it = sameOrWorseCost.begin(); it != sameOrWorseCost.end(); it++) {
02298                     OSPF::RoutingTableEntry* checkedEntry = (*it);
02299 
02300                     if (checkedEntry->GetCost() > currentCost) {
02301                         for (std::vector<OSPF::RoutingTableEntry*>::iterator entryIt = newRoutingTable.begin(); entryIt != newRoutingTable.end(); entryIt++) {
02302                             if (checkedEntry == (*entryIt)) {
02303                                 newRoutingTable.erase(entryIt);
02304                                 break;
02305                             }
02306                         }
02307                     } else {    // EntryCost == currentCost
02308                         equalEntry = checkedEntry;  // should be only one - if there are more they are ignored
02309                     }
02310                 }
02311 
02312                 unsigned long nextHopCount = borderRouterEntry->GetNextHopCount();
02313 
02314                 if (equalEntry != NULL) {
02315                     /* Add the next hops of the border router advertising this destination
02316                      * to the equal entry.
02317                      */
02318                     for (unsigned long j = 0; j < nextHopCount; j++) {
02319                         equalEntry->AddNextHop(borderRouterEntry->GetNextHop(j));
02320                     }
02321                 } else {
02322                     OSPF::RoutingTableEntry* newEntry = CreateRoutingTableEntryFromSummaryLSA(*currentLSA, currentCost, *borderRouterEntry);
02323                     ASSERT(newEntry != NULL);
02324                     newRoutingTable.push_back(newEntry);
02325                 }
02326             } else {
02327                 OSPF::RoutingTableEntry* newEntry = CreateRoutingTableEntryFromSummaryLSA(*currentLSA, currentCost, *borderRouterEntry);
02328                 ASSERT(newEntry != NULL);
02329                 newRoutingTable.push_back(newEntry);
02330             }
02331         }
02332     }
02333 }
02334 
02335 void OSPF::Area::ReCheckSummaryLSAs(std::vector<OSPF::RoutingTableEntry*>& newRoutingTable)
02336 {
02337     unsigned long i = 0;
02338     unsigned long j = 0;
02339     unsigned long lsaCount = summaryLSAs.size();
02340 
02341     for (i = 0; i < lsaCount; i++) {
02342         OSPF::SummaryLSA* currentLSA        = summaryLSAs[i];
02343         OSPFLSAHeader&    currentHeader     = currentLSA->getHeader();
02344 
02345         unsigned long     routeCost         = currentLSA->getRouteCost();
02346         unsigned short    lsAge             = currentHeader.getLsAge();
02347         RouterID          originatingRouter = currentHeader.getAdvertisingRouter().getInt();
02348         bool              selfOriginated    = (originatingRouter == parentRouter->GetRouterID());
02349 
02350         if ((routeCost == LS_INFINITY) || (lsAge == MAX_AGE) || (selfOriginated)) { // (1) and(2)
02351             continue;
02352         }
02353 
02354         unsigned long            routeCount       = newRoutingTable.size();
02355         char                     lsType           = currentHeader.getLsType();
02356         OSPF::RoutingTableEntry* destinationEntry = NULL;
02357         OSPF::IPv4AddressRange   destination;
02358 
02359         destination.address = IPv4AddressFromULong(currentHeader.getLinkStateID());
02360         destination.mask    = IPv4AddressFromULong(currentLSA->getNetworkMask().getInt());
02361 
02362         for (j = 0; j < routeCount; j++) {  // (3)
02363             OSPF::RoutingTableEntry* routingEntry  = newRoutingTable[j];
02364             bool                     foundMatching = false;
02365 
02366             if (lsType == SummaryLSA_NetworksType) {
02367                 if ((routingEntry->GetDestinationType() == OSPF::RoutingTableEntry::NetworkDestination) &&
02368                     (ULongFromIPv4Address(destination.address & destination.mask) == routingEntry->GetDestinationID().getInt()))
02369                 {
02370                     foundMatching = true;
02371                 }
02372             } else {
02373                 if ((((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
02374                      ((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
02375                     (ULongFromIPv4Address(destination.address) == routingEntry->GetDestinationID().getInt()))
02376                 {
02377                     foundMatching = true;
02378                 }
02379             }
02380 
02381             if (foundMatching) {
02382                 OSPF::RoutingTableEntry::RoutingPathType pathType = routingEntry->GetPathType();
02383 
02384                 if ((pathType == OSPF::RoutingTableEntry::Type1External) ||
02385                     (pathType == OSPF::RoutingTableEntry::Type2External) ||
02386                     (routingEntry->GetArea() != OSPF::BackboneAreaID))
02387                 {
02388                     break;
02389                 } else {
02390                     destinationEntry = routingEntry;
02391                     break;
02392                 }
02393             }
02394         }
02395         if (destinationEntry == NULL) {
02396             continue;
02397         }
02398 
02399         OSPF::RoutingTableEntry* borderRouterEntry = NULL;
02400         unsigned short           currentCost       = routeCost;
02401 
02402         for (j = 0; j < routeCount; j++) {     // (4) BR == borderRouterEntry
02403             OSPF::RoutingTableEntry* routingEntry = newRoutingTable[j];
02404 
02405             if ((routingEntry->GetArea() == areaID) &&
02406                 (((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
02407                  ((routingEntry->GetDestinationType() & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
02408                 (routingEntry->GetDestinationID().getInt() == originatingRouter))
02409             {
02410                 borderRouterEntry = routingEntry;
02411                 currentCost += borderRouterEntry->GetCost();
02412                 break;
02413             }
02414         }
02415         if (borderRouterEntry == NULL) {
02416             continue;
02417         } else {    // (5)
02418             if (currentCost <= destinationEntry->GetCost()) {
02419                 if (currentCost < destinationEntry->GetCost()) {
02420                     destinationEntry->ClearNextHops();
02421                 }
02422 
02423                 unsigned long nextHopCount = borderRouterEntry->GetNextHopCount();
02424 
02425                 for (j = 0; j < nextHopCount; j++) {
02426                     destinationEntry->AddNextHop(borderRouterEntry->GetNextHop(j));
02427                 }
02428             }
02429         }
02430     }
02431 }