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