Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSPF::Router Class Reference

#include <OSPFRouter.h>

List of all members.


Detailed Description

Represents the full OSPF datastructure as laid out in RFC2328.


Public Member Functions

 Router (RouterID id, cSimpleModule *containingModule)
virtual ~Router (void)
void SetRouterID (RouterID id)
RouterID GetRouterID (void) const
void SetRFC1583Compatibility (bool compatibility)
bool GetRFC1583Compatibility (void) const
unsigned long GetAreaCount (void) const
MessageHandlerGetMessageHandler (void)
unsigned long GetASExternalLSACount (void) const
ASExternalLSAGetASExternalLSA (unsigned long i)
const ASExternalLSAGetASExternalLSA (unsigned long i) const
bool GetASBoundaryRouter (void) const
unsigned long GetRoutingTableEntryCount (void) const
RoutingTableEntryGetRoutingTableEntry (unsigned long i)
const RoutingTableEntryGetRoutingTableEntry (unsigned long i) const
void AddRoutingTableEntry (RoutingTableEntry *entry)
void AddWatches (void)
void AddArea (Area *area)
AreaGetArea (AreaID areaID)
AreaGetArea (IPv4Address address)
InterfaceGetNonVirtualInterface (unsigned char ifIndex)
bool InstallLSA (OSPFLSA *lsa, AreaID areaID=BackboneAreaID)
OSPFLSA * FindLSA (LSAType lsaType, LSAKeyType lsaKey, AreaID areaID)
void AgeDatabase (void)
bool AnyNeighborInStates (int states) const
void RemoveFromAllRetransmissionLists (LSAKeyType lsaKey)
bool IsOnAnyRetransmissionList (LSAKeyType lsaKey) const
bool FloodLSA (OSPFLSA *lsa, AreaID areaID=BackboneAreaID, Interface *intf=NULL, Neighbor *neighbor=NULL)
bool IsLocalAddress (IPv4Address address) const
bool HasAddressRange (IPv4AddressRange addressRange) const
bool DestinationIsUnreachable (OSPFLSA *lsa) const
RoutingTableEntryLookup (IPAddress destination, std::vector< RoutingTableEntry * > *table=NULL) const
void RebuildRoutingTable (void)
IPv4AddressRange GetContainingAddressRange (IPv4AddressRange addressRange, bool *advertise=NULL) const
void UpdateExternalRoute (IPv4Address networkAddress, const OSPFASExternalLSAContents &externalRouteContents, int ifIndex)
void RemoveExternalRoute (IPv4Address networkAddress)
RoutingTableEntryGetPreferredEntry (const OSPFLSA &lsa, bool skipSelfOriginated, std::vector< RoutingTableEntry * > *fromRoutingTable=NULL)

Private Member Functions

bool InstallASExternalLSA (OSPFASExternalLSA *lsa)
ASExternalLSAFindASExternalLSA (LSAKeyType lsaKey)
const ASExternalLSAFindASExternalLSA (LSAKeyType lsaKey) const
ASExternalLSAOriginateASExternalLSA (ASExternalLSA *lsa)
LinkStateID GetUniqueLinkStateID (IPv4AddressRange destination, Metric destinationCost, OSPF::ASExternalLSA *&lsaToReoriginate, bool externalMetricIsType2=false) const
void CalculateASExternalRoutes (std::vector< RoutingTableEntry * > &newRoutingTable)
void NotifyAboutRoutingTableChanges (std::vector< RoutingTableEntry * > &oldRoutingTable)
bool HasRouteToASBoundaryRouter (const std::vector< RoutingTableEntry * > &inRoutingTable, OSPF::RouterID routerID) const
std::vector< RoutingTableEntry * > GetRoutesToASBoundaryRouter (const std::vector< RoutingTableEntry * > &fromRoutingTable, OSPF::RouterID routerID) const
void PruneASBoundaryRouterEntries (std::vector< RoutingTableEntry * > &asbrEntries) const
RoutingTableEntrySelectLeastCostRoutingEntry (std::vector< RoutingTableEntry * > &entries) const

Private Attributes

RouterID routerID
 The router ID assigned by the IP layer.
std::map< AreaID, Area * > areasByID
 A map of the contained areas with the AreaID as key.
std::vector< Area * > areas
 A list of the contained areas.
std::map< LSAKeyType, ASExternalLSA *,
LSAKeyType_Less
asExternalLSAsByID
 A map of the ASExternalLSAs advertised by this router.
std::vector< ASExternalLSA * > asExternalLSAs
 A list of the ASExternalLSAs advertised by this router.
std::map< IPv4Address, OSPFASExternalLSAContents,
IPv4Address_Less
externalRoutes
 A map of the external route advertised by this router.
OSPFTimer * ageTimer
 Database age timer - fires every second.
std::vector< RoutingTableEntry * > routingTable
 The OSPF routing table - contains more information than the one in the IP layer.
MessageHandlermessageHandler
 The message dispatcher class.
bool rfc1583Compatibility
 Decides whether to handle the preferred routing table entry to an AS boundary router as defined in RFC1583 or not.


Constructor & Destructor Documentation

OSPF::Router::Router OSPF::RouterID  id,
cSimpleModule *  containingModule
 

Constructor. Initializes internal variables, adds a MessageHandler and starts the Database Age timer.

00011                                                                     :
00012     routerID (id),
00013     rfc1583Compatibility (false)
00014 {
00015     messageHandler = new OSPF::MessageHandler (this, containingModule);
00016     ageTimer = new OSPFTimer;
00017     ageTimer->setTimerKind (DatabaseAgeTimer);
00018     ageTimer->setContextPointer (this);
00019     ageTimer->setName ("OSPF::Router::DatabaseAgeTimer");
00020     messageHandler->StartTimer (ageTimer, 1.0);
00021 }

OSPF::Router::~Router void   )  [virtual]
 

Destructor. Clears all LSA lists and kills the Database Age timer.

00029 {
00030     long areaCount = areas.size ();
00031     for (long i = 0; i < areaCount; i++) {
00032         delete areas[i];
00033     }
00034     long lsaCount = asExternalLSAs.size ();
00035     for (long j = 0; j < lsaCount; j++) {
00036         delete asExternalLSAs[j];
00037     }
00038     long routeCount = routingTable.size ();
00039     for (long k = 0; k < routeCount; k++) {
00040         delete routingTable[k];
00041     }
00042     messageHandler->ClearTimer (ageTimer);
00043     delete ageTimer;
00044     delete messageHandler;
00045 }


Member Function Documentation

void OSPF::Router::AddArea OSPF::Area area  ) 
 

Adds a new Area to the Area list.

Parameters:
area [in] The Area to add.
00064 {
00065 
00066     area->SetRouter (this);
00067     areasByID[area->GetAreaID ()] = area;
00068     areas.push_back (area);
00069 }

void OSPF::Router::AddRoutingTableEntry RoutingTableEntry entry  )  [inline]
 

00053 { routingTable.push_back (entry); }

void OSPF::Router::AddWatches void   ) 
 

Adds OMNeT++ watches for the routerID, the list of Areas and the list of AS External LSAs.

00052 {
00053     WATCH (routerID);
00054     WATCH_PTRVECTOR (areas);
00055     WATCH_PTRVECTOR (asExternalLSAs);
00056 }

void OSPF::Router::AgeDatabase void   ) 
 

Ages the LSAs in the Router's database. This method is called on every firing of the DatabaseAgeTimer (every second).

See also:
RFC2328 Section 14.
00348 {
00349     long lsaCount            = asExternalLSAs.size ();
00350     bool rebuildRoutingTable = false;
00351 
00352     for (long i = 0; i < lsaCount; i++) {
00353         unsigned short       lsAge          = asExternalLSAs[i]->getHeader ().getLsAge ();
00354         bool                 selfOriginated = (asExternalLSAs[i]->getHeader ().getAdvertisingRouter ().getInt () == routerID);
00355         bool                 unreachable    = DestinationIsUnreachable (asExternalLSAs[i]);
00356         OSPF::ASExternalLSA* lsa            = asExternalLSAs[i];
00357 
00358         if ((selfOriginated && (lsAge < (LS_REFRESH_TIME - 1))) || (!selfOriginated && (lsAge < (MAX_AGE - 1)))) {
00359             lsa->getHeader ().setLsAge (lsAge + 1);
00360             if ((lsAge + 1) % CHECK_AGE == 0) {
00361                 if (!lsa->ValidateLSChecksum ()) {
00362                     EV << "Invalid LS checksum. Memory error detected!\n";
00363                 }
00364             }
00365             lsa->IncrementInstallTime ();
00366         }
00367         if (selfOriginated && (lsAge == (LS_REFRESH_TIME - 1))) {
00368             if (unreachable) {
00369                 lsa->getHeader ().setLsAge (MAX_AGE);
00370                 FloodLSA (lsa, OSPF::BackboneAreaID);
00371                 lsa->IncrementInstallTime ();
00372             } else {
00373                 long sequenceNumber = lsa->getHeader ().getLsSequenceNumber ();
00374                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00375                     lsa->getHeader ().setLsAge (MAX_AGE);
00376                     FloodLSA (lsa, OSPF::BackboneAreaID);
00377                     lsa->IncrementInstallTime ();
00378                 } else {
00379                     OSPF::ASExternalLSA* newLSA = OriginateASExternalLSA (lsa);
00380 
00381                     newLSA->getHeader ().setLsSequenceNumber (sequenceNumber + 1);
00382                     newLSA->getHeader ().setLsChecksum (0);    // TODO: calculate correct LS checksum
00383                     rebuildRoutingTable |= lsa->Update (newLSA);
00384                     delete newLSA;
00385 
00386                     FloodLSA (lsa, OSPF::BackboneAreaID);
00387                 }
00388             }
00389         }
00390         if (!selfOriginated && (lsAge == MAX_AGE - 1)) {
00391             lsa->getHeader ().setLsAge (MAX_AGE);
00392             FloodLSA (lsa, OSPF::BackboneAreaID);
00393             lsa->IncrementInstallTime ();
00394         }
00395         if (lsAge == MAX_AGE) {
00396             OSPF::LSAKeyType lsaKey;
00397 
00398             lsaKey.linkStateID       = lsa->getHeader ().getLinkStateID ();
00399             lsaKey.advertisingRouter = lsa->getHeader ().getAdvertisingRouter ().getInt ();
00400 
00401             if (!IsOnAnyRetransmissionList (lsaKey) &&
00402                 !AnyNeighborInStates (OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState))
00403             {
00404                 if (!selfOriginated || unreachable) {
00405                     asExternalLSAsByID.erase (lsaKey);
00406                     delete lsa;
00407                     asExternalLSAs[i] = NULL;
00408                     rebuildRoutingTable = true;
00409                 } else {
00410                     if (lsa->GetPurgeable ()) {
00411                         asExternalLSAsByID.erase (lsaKey);
00412                         delete lsa;
00413                         asExternalLSAs[i] = NULL;
00414                         rebuildRoutingTable = true;
00415                     } else {
00416                         OSPF::ASExternalLSA* newLSA              = OriginateASExternalLSA (lsa);
00417                         long                 sequenceNumber      = lsa->getHeader ().getLsSequenceNumber ();
00418 
00419                         newLSA->getHeader ().setLsSequenceNumber ((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
00420                         newLSA->getHeader ().setLsChecksum (0);    // TODO: calculate correct LS checksum
00421                         rebuildRoutingTable |= lsa->Update (newLSA);
00422                         delete newLSA;
00423 
00424                         FloodLSA (lsa, OSPF::BackboneAreaID);
00425                     }
00426                 }
00427             }
00428         }
00429     }
00430 
00431     std::vector<ASExternalLSA*>::iterator it = asExternalLSAs.begin ();
00432     while (it != asExternalLSAs.end ()) {
00433         if ((*it) == NULL) {
00434             it = asExternalLSAs.erase (it);
00435         } else {
00436             it++;
00437         }
00438     }
00439 
00440     long areaCount = areas.size ();
00441     for (long j = 0; j < areaCount; j++) {
00442         areas[j]->AgeDatabase ();
00443     }
00444     messageHandler->StartTimer (ageTimer, 1.0);
00445 
00446     if (rebuildRoutingTable) {
00447         RebuildRoutingTable ();
00448     }
00449 }

bool OSPF::Router::AnyNeighborInStates int  states  )  const
 

Returns true if any Neighbor on any Interface in any of the Router's Areas is in any of the input states, false otherwise.

Parameters:
states [in] A bitfield combination of NeighborStateType values.
00458 {
00459     long areaCount = areas.size ();
00460     for (long i = 0; i < areaCount; i++) {
00461         if (areas[i]->AnyNeighborInStates (states)) {
00462             return true;
00463         }
00464     }
00465     return false;
00466 }

void OSPF::Router::CalculateASExternalRoutes std::vector< RoutingTableEntry * > &  newRoutingTable  )  [private]
 

Calculate the AS External Routes from the ASExternalLSAs in the database.

Parameters:
newRoutingTable [in/out] Push the new RoutingTableEntries into this routing table, and also use this for path calculations.
See also:
RFC2328 Section 16.4.
01079 {
01080     unsigned long lsaCount = asExternalLSAs.size ();
01081     unsigned long i;
01082 
01083     for (i = 0; i < lsaCount; i++) {
01084         OSPF::ASExternalLSA* currentLSA        = asExternalLSAs[i];
01085         OSPFLSAHeader&       currentHeader     = currentLSA->getHeader ();
01086         unsigned short       externalCost      = currentLSA->getContents ().getRouteCost ();
01087         OSPF::RouterID       originatingRouter = currentHeader.getAdvertisingRouter ().getInt ();
01088 
01089         OSPF::RoutingTableEntry* preferredEntry = GetPreferredEntry (*currentLSA, true, &newRoutingTable);
01090         if (preferredEntry == NULL) {
01091             continue;
01092         }
01093 
01094         IPAddress destination = currentHeader.getLinkStateID () & currentLSA->getContents ().getNetworkMask ().getInt ();
01095 
01096         Metric                   preferredCost    = preferredEntry->GetCost ();
01097         OSPF::RoutingTableEntry* destinationEntry = Lookup (destination, &newRoutingTable);   // (5)
01098         if (destinationEntry == NULL) {
01099             bool                     type2ExternalMetric = currentLSA->getContents ().getE_ExternalMetricType ();
01100             unsigned int             nextHopCount        = preferredEntry->GetNextHopCount ();
01101             OSPF::RoutingTableEntry* newEntry            = new OSPF::RoutingTableEntry;
01102 
01103             newEntry->SetDestinationID (destination);
01104             newEntry->SetAddressMask (currentLSA->getContents ().getNetworkMask ().getInt ());
01105             newEntry->SetArea (preferredEntry->GetArea ());
01106             newEntry->SetPathType (type2ExternalMetric ? OSPF::RoutingTableEntry::Type2External : OSPF::RoutingTableEntry::Type1External);
01107             if (type2ExternalMetric) {
01108                 newEntry->SetCost (preferredCost);
01109                 newEntry->SetType2Cost (externalCost);
01110             } else {
01111                 newEntry->SetCost (preferredCost + externalCost);
01112             }
01113             newEntry->SetDestinationType (OSPF::RoutingTableEntry::NetworkDestination);
01114             newEntry->SetOptionalCapabilities (currentHeader.getLsOptions ());
01115             newEntry->SetLinkStateOrigin (currentLSA);
01116 
01117             for (unsigned int j = 0; j < nextHopCount; j++) {
01118                 NextHop nextHop = preferredEntry->GetNextHop (j);
01119 
01120                 nextHop.advertisingRouter = originatingRouter;
01121                 newEntry->AddNextHop (nextHop);
01122             }
01123 
01124             newRoutingTable.push_back (newEntry);
01125         } else {
01126             OSPF::RoutingTableEntry::RoutingPathType destinationPathType = destinationEntry->GetPathType ();
01127             bool                                     type2ExternalMetric = currentLSA->getContents ().getE_ExternalMetricType ();
01128             unsigned int                             nextHopCount        = preferredEntry->GetNextHopCount ();
01129 
01130             if ((destinationPathType == OSPF::RoutingTableEntry::IntraArea) ||
01131                 (destinationPathType == OSPF::RoutingTableEntry::InterArea))   // (6) (a)
01132             {
01133                 continue;
01134             }
01135 
01136             if (((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01137                  (type2ExternalMetric)) ||
01138                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01139                  (type2ExternalMetric) &&
01140                  (destinationEntry->GetType2Cost () < externalCost))) // (6) (b)
01141             {
01142                 continue;
01143             }
01144 
01145             OSPF::RoutingTableEntry* destinationPreferredEntry = GetPreferredEntry (*(destinationEntry->GetLinkStateOrigin ()), false, &newRoutingTable);
01146             if ((!rfc1583Compatibility) &&
01147                 (destinationPreferredEntry->GetPathType () == OSPF::RoutingTableEntry::IntraArea) &&
01148                 (destinationPreferredEntry->GetArea () != OSPF::BackboneAreaID) &&
01149                 ((preferredEntry->GetPathType () != OSPF::RoutingTableEntry::IntraArea) ||
01150                  (preferredEntry->GetArea () == OSPF::BackboneAreaID)))
01151             {
01152                 continue;
01153             }
01154 
01155             if ((((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01156                   (!type2ExternalMetric) &&
01157                   (destinationEntry->GetCost () < preferredCost + externalCost))) ||
01158                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01159                  (type2ExternalMetric) &&
01160                  (destinationEntry->GetType2Cost () == externalCost) &&
01161                  (destinationPreferredEntry->GetCost () < preferredCost)))
01162             {
01163                 continue;
01164             }
01165 
01166             if (((destinationPathType == OSPF::RoutingTableEntry::Type1External) &&
01167                  (!type2ExternalMetric) &&
01168                  (destinationEntry->GetCost () == (preferredCost + externalCost))) ||
01169                 ((destinationPathType == OSPF::RoutingTableEntry::Type2External) &&
01170                  (type2ExternalMetric) &&
01171                  (destinationEntry->GetType2Cost () == externalCost) &&
01172                  (destinationPreferredEntry->GetCost () == preferredCost)))   // equal cost
01173             {
01174                 for (unsigned int j = 0; j < nextHopCount; j++) {
01175                     // TODO: merge next hops, not add
01176                     NextHop nextHop = preferredEntry->GetNextHop (j);
01177 
01178                     nextHop.advertisingRouter = originatingRouter;
01179                     destinationEntry->AddNextHop (nextHop);
01180                 }
01181                 continue;
01182             }
01183 
01184             // LSA is better
01185             destinationEntry->SetArea (preferredEntry->GetArea ());
01186             destinationEntry->SetPathType (type2ExternalMetric ? OSPF::RoutingTableEntry::Type2External : OSPF::RoutingTableEntry::Type1External);
01187             if (type2ExternalMetric) {
01188                 destinationEntry->SetCost (preferredCost);
01189                 destinationEntry->SetType2Cost (externalCost);
01190             } else {
01191                 destinationEntry->SetCost (preferredCost + externalCost);
01192             }
01193             destinationEntry->SetDestinationType (OSPF::RoutingTableEntry::NetworkDestination);
01194             destinationEntry->SetOptionalCapabilities (currentHeader.getLsOptions ());
01195             destinationEntry->ClearNextHops ();
01196 
01197             for (unsigned int j = 0; j < nextHopCount; j++) {
01198                 NextHop nextHop = preferredEntry->GetNextHop (j);
01199 
01200                 nextHop.advertisingRouter = originatingRouter;
01201                 destinationEntry->AddNextHop (nextHop);
01202             }
01203         }
01204     }
01205 }

bool OSPF::Router::DestinationIsUnreachable OSPFLSA *  lsa  )  const
 

Returns true if the destination described by the input lsa is in the routing table, false otherwise.

Parameters:
lsa [in] The LSA which describes the destination to look for.
00596 {
00597     IPAddress destination = lsa->getHeader ().getLinkStateID ();
00598 
00599     OSPFRouterLSA* routerLSA         = dynamic_cast<OSPFRouterLSA*> (lsa);
00600     OSPFNetworkLSA* networkLSA       = dynamic_cast<OSPFNetworkLSA*> (lsa);
00601     OSPFSummaryLSA* summaryLSA       = dynamic_cast<OSPFSummaryLSA*> (lsa);
00602     OSPFASExternalLSA* asExternalLSA = dynamic_cast<OSPFASExternalLSA*> (lsa);
00603     // TODO: verify
00604     if (routerLSA != NULL) {
00605         OSPF::RoutingInfo* routingInfo = check_and_cast<OSPF::RoutingInfo*> (routerLSA);
00606         if (routerLSA->getHeader ().getLinkStateID () == routerID) { // this is spfTreeRoot
00607             return false;
00608         }
00609 
00610         // get the interface address pointing backwards on the shortest path tree
00611         unsigned int     linkCount   = routerLSA->getLinksArraySize ();
00612         OSPF::RouterLSA* toRouterLSA = dynamic_cast<OSPF::RouterLSA*> (routingInfo->GetParent ());
00613         if (toRouterLSA != NULL) {
00614             bool      destinationFound           = false;
00615             bool      unnumberedPointToPointLink = false;
00616             IPAddress firstNumberedIfAddress;
00617 
00618             for (unsigned int i = 0; i < linkCount; i++) {
00619                 Link& link = routerLSA->getLinks (i);
00620 
00621                 if (link.getType () == PointToPointLink) {
00622                     if (link.getLinkID () == toRouterLSA->getHeader ().getLinkStateID ()) {
00623                         if ((link.getLinkData () & 0xFF000000) == 0) {
00624                             unnumberedPointToPointLink = true;
00625                             if (!firstNumberedIfAddress.isUnspecified ()) {
00626                                 break;
00627                             }
00628                         } else {
00629                             destination = link.getLinkData ();
00630                             destinationFound = true;
00631                             break;
00632                         }
00633                     } else {
00634                         if (((link.getLinkData () & 0xFF000000) != 0) &&
00635                              firstNumberedIfAddress.isUnspecified ())
00636                         {
00637                             firstNumberedIfAddress = link.getLinkData ();
00638                         }
00639                     }
00640                 } else if (link.getType () == TransitLink) {
00641                     if (firstNumberedIfAddress.isUnspecified ()) {
00642                         firstNumberedIfAddress = link.getLinkData ();
00643                     }
00644                 } else if (link.getType () == VirtualLink) {
00645                     if (link.getLinkID () == toRouterLSA->getHeader ().getLinkStateID ()) {
00646                         destination = link.getLinkData ();
00647                         destinationFound = true;
00648                         break;
00649                     } else {
00650                         if (firstNumberedIfAddress.isUnspecified ()) {
00651                             firstNumberedIfAddress = link.getLinkData ();
00652                         }
00653                     }
00654                 }
00655                 // There's no way to get an interface address for the router from a StubLink
00656             }
00657             if (unnumberedPointToPointLink) {
00658                 if (!firstNumberedIfAddress.isUnspecified ()) {
00659                     destination = firstNumberedIfAddress;
00660                 } else {
00661                     return true;
00662                 }
00663             }
00664             if (!destinationFound) {
00665                 return true;
00666             }
00667         } else {
00668             OSPF::NetworkLSA* toNetworkLSA = dynamic_cast<OSPF::NetworkLSA*> (routingInfo->GetParent ());
00669             if (toNetworkLSA != NULL) {
00670                 // get the interface address pointing backwards on the shortest path tree
00671                 bool destinationFound = false;
00672                 for (unsigned int i = 0; i < linkCount; i++) {
00673                     Link& link = routerLSA->getLinks (i);
00674 
00675                     if ((link.getType () == TransitLink) &&
00676                         (link.getLinkID () == toNetworkLSA->getHeader ().getLinkStateID ()))
00677                     {
00678                         destination = link.getLinkData ();
00679                         destinationFound = true;
00680                         break;
00681                     }
00682                 }
00683                 if (!destinationFound) {
00684                     return true;
00685                 }
00686             } else {
00687                 return true;
00688             }
00689         }
00690     }
00691     if (networkLSA != NULL) {
00692         destination = networkLSA->getHeader ().getLinkStateID () & networkLSA->getNetworkMask ().getInt ();
00693     }
00694     if ((summaryLSA != NULL) && (summaryLSA->getHeader ().getLsType () == SummaryLSA_NetworksType)) {
00695         destination = summaryLSA->getHeader ().getLinkStateID () & summaryLSA->getNetworkMask ().getInt ();
00696     }
00697     if (asExternalLSA != NULL) {
00698         destination = asExternalLSA->getHeader ().getLinkStateID () & asExternalLSA->getContents ().getNetworkMask ().getInt ();
00699     }
00700 
00701     if (Lookup (destination) == NULL) {
00702         return true;
00703     } else {
00704         return false;
00705     }
00706 }

const OSPF::ASExternalLSA * OSPF::Router::FindASExternalLSA OSPF::LSAKeyType  lsaKey  )  const [private]
 

Find the AS External LSA identified by the input lsaKey in the database.

Parameters:
lsaKey [in] Look for the AS External LSA which is identified by this key.
Returns:
The const pointer to the AS External LSA if it was found, NULL otherwise.
00332 {
00333     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::const_iterator lsaIt = asExternalLSAsByID.find (lsaKey);
00334     if (lsaIt != asExternalLSAsByID.end ()) {
00335         return lsaIt->second;
00336     } else {
00337         return NULL;
00338     }
00339 }

OSPF::ASExternalLSA * OSPF::Router::FindASExternalLSA OSPF::LSAKeyType  lsaKey  )  [private]
 

Find the AS External LSA identified by the input lsaKey in the database.

Parameters:
lsaKey [in] Look for the AS External LSA which is identified by this key.
Returns:
The pointer to the AS External LSA if it was found, NULL otherwise.
00316 {
00317     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find (lsaKey);
00318     if (lsaIt != asExternalLSAsByID.end ()) {
00319         return lsaIt->second;
00320     } else {
00321         return NULL;
00322     }
00323 }

OSPFLSA * OSPF::Router::FindLSA LSAType  lsaType,
OSPF::LSAKeyType  lsaKey,
OSPF::AreaID  areaID
 

Find the LSA identified by the input lsaKey in the database.

Parameters:
lsaType [in] Look for an LSA of this type.
lsaKey [in] Look for the LSA which is identified by this key.
areID [in] In case of Router, Network and Summary LSAs, look in the Area's database identified by this parameter.
Returns:
The pointer to the LSA if it was found, NULL otherwise.
00270 {
00271     switch (lsaType) {
00272         case RouterLSAType:
00273             {
00274                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00275                 if (areaIt != areasByID.end ()) {
00276                     return areaIt->second->FindRouterLSA (lsaKey.linkStateID);
00277                 }
00278             }
00279             break;
00280         case NetworkLSAType:
00281             {
00282                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00283                 if (areaIt != areasByID.end ()) {
00284                     return areaIt->second->FindNetworkLSA (lsaKey.linkStateID);
00285                 }
00286             }
00287             break;
00288         case SummaryLSA_NetworksType:
00289         case SummaryLSA_ASBoundaryRoutersType:
00290             {
00291                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00292                 if (areaIt != areasByID.end ()) {
00293                     return areaIt->second->FindSummaryLSA (lsaKey);
00294                 }
00295             }
00296             break;
00297         case ASExternalLSAType:
00298             {
00299                 return FindASExternalLSA (lsaKey);
00300             }
00301             break;
00302         default:
00303             ASSERT (false);
00304             break;
00305     }
00306     return NULL;
00307 }

bool OSPF::Router::FloodLSA OSPFLSA *  lsa,
OSPF::AreaID  areaID = BackboneAreaID,
OSPF::Interface intf = NULL,
OSPF::Neighbor neighbor = NULL
 

Floods out the input lsa on a set of Interfaces.

See also:
RFC2328 Section 13.3.
Parameters:
lsa [in] The LSA to be flooded out.
areaID [in] If the lsa is a Router, Network or Summary LSA, then flood it only in this Area.
intf [in] The Interface this LSA arrived on.
neighbor [in] The Nieghbor this LSA arrived from.
Returns:
True if the LSA was floooded back out on the receiving Interface, false otherwise.
00510 {
00511     bool floodedBackOut = false;
00512 
00513     if (lsa != NULL) {
00514         if (lsa->getHeader ().getLsType () == ASExternalLSAType) {
00515             long areaCount = areas.size ();
00516             for (long i = 0; i < areaCount; i++) {
00517                 if (areas[i]->GetExternalRoutingCapability ()) {
00518                     if (areas[i]->FloodLSA (lsa, intf, neighbor)) {
00519                         floodedBackOut = true;
00520                     }
00521                 }
00522             }
00523         } else {
00524             std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00525             if (areaIt != areasByID.end ()) {
00526                 floodedBackOut = areaIt->second->FloodLSA (lsa, intf, neighbor);
00527             }
00528         }
00529     }
00530 
00531     return floodedBackOut;
00532 }

OSPF::Area * OSPF::Router::GetArea OSPF::IPv4Address  address  ) 
 

Returns the Area pointer from the Area list which contains the input IP address, NULL if there's no such area connected to the Router.

Parameters:
address [in] The IP address whose containing Area we're looking for.
00095 {
00096     long areaCount = areas.size ();
00097     for (long i = 0; i < areaCount; i++) {
00098         if (areas[i]->ContainsAddress (address)) {
00099             return areas[i];
00100         }
00101     }
00102     return NULL;
00103 }

OSPF::Area * OSPF::Router::GetArea OSPF::AreaID  areaID  ) 
 

Returns the pointer to the Area identified by the input areaID, if it's on the Area list, NULL otherwise.

Parameters:
areaID [in] The Area identifier.
00078 {
00079     std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00080     if (areaIt != areasByID.end ()) {
00081         return (areaIt->second);
00082     }
00083     else {
00084         return NULL;
00085     }
00086 }

unsigned long OSPF::Router::GetAreaCount void   )  const [inline]
 

00041 { return areas.size (); }

bool OSPF::Router::GetASBoundaryRouter void   )  const [inline]
 

00048 { return (externalRoutes.size () > 0); }

const ASExternalLSA* OSPF::Router::GetASExternalLSA unsigned long  i  )  const [inline]
 

00047 { return asExternalLSAs[i]; }

ASExternalLSA* OSPF::Router::GetASExternalLSA unsigned long  i  )  [inline]
 

00046 { return asExternalLSAs[i]; }

unsigned long OSPF::Router::GetASExternalLSACount void   )  const [inline]
 

00045 { return asExternalLSAs.size (); }

OSPF::IPv4AddressRange OSPF::Router::GetContainingAddressRange OSPF::IPv4AddressRange  addressRange,
bool *  advertise = NULL
const
 

Scans through the router's areas' preconfigured address ranges and returns the one containing the input addressRange.

Parameters:
addressRange [in] The address range to look for.
advertise [out] Whether the advertise flag is set in the returned preconfigured address range.
Returns:
The containing preconfigured address range if found, OSPF::NullIPv4AddressRange otherwise.
01218 {
01219     unsigned long areaCount = areas.size ();
01220     for (unsigned long i = 0; i < areaCount; i++) {
01221         OSPF::IPv4AddressRange containingAddressRange = areas[i]->GetContainingAddressRange (addressRange, advertise);
01222         if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01223             return containingAddressRange;
01224         }
01225     }
01226     if (advertise != NULL) {
01227         *advertise = false;
01228     }
01229     return OSPF::NullIPv4AddressRange;
01230 }

MessageHandler* OSPF::Router::GetMessageHandler void   )  [inline]
 

00043 { return messageHandler; }

OSPF::Interface * OSPF::Router::GetNonVirtualInterface unsigned char  ifIndex  ) 
 

Returns the pointer of the physical Interface identified by the input interface index, NULL if the Router doesn't have such an interface.

Parameters:
ifIndex [in] The interface index to look for.
00112 {
00113     long areaCount = areas.size ();
00114     for (long i = 0; i < areaCount; i++) {
00115         OSPF::Interface* intf = areas[i]->GetInterface (ifIndex);
00116         if (intf != NULL) {
00117             return intf;
00118         }
00119     }
00120     return NULL;
00121 }

OSPF::RoutingTableEntry * OSPF::Router::GetPreferredEntry const OSPFLSA &  lsa,
bool  skipSelfOriginated,
std::vector< RoutingTableEntry * > *  fromRoutingTable = NULL
 

Selects the preferred routing table entry for the input LSA (which is either an ASExternalLSA or a SummaryLSA) according to the algorithm defined in RFC2328 Section 16.4. points (1) through (3). This method is used when calculating the AS external routes and also when originating an SummaryLSA for an AS Boundary Router.

Parameters:
lsa [in] The LSA describing the destination for which the preferred Routing Entry is sought for.
skipSelfOriginated [in] Whether to disregard this LSA if it was self-originated.
fromRoutingTable [in] The Routing Table from which to select the preferred RoutingTableEntry. If it is NULL then the router's current routing table is used instead.
Returns:
The preferred RoutingTableEntry, or NULL if no such entry exists.
See also:
RFC2328 Section 16.4. points (1) through (3)

OSPF::Area::OriginateSummaryLSA

01020 {
01021     if (fromRoutingTable == NULL) {
01022         fromRoutingTable = &routingTable;
01023     }
01024 
01025     const OSPFLSAHeader&     lsaHeader         = lsa.getHeader ();
01026     const OSPFASExternalLSA* asExternalLSA     = dynamic_cast<const OSPFASExternalLSA*> (&lsa);
01027     unsigned long            externalCost      = (asExternalLSA != NULL) ? asExternalLSA->getContents ().getRouteCost () : 0;
01028     unsigned short           lsAge             = lsaHeader.getLsAge ();
01029     OSPF::RouterID           originatingRouter = lsaHeader.getAdvertisingRouter ().getInt ();
01030     bool                     selfOriginated    = (originatingRouter == routerID);
01031     IPAddress                forwardingAddress; // 0.0.0.0
01032 
01033     if (asExternalLSA != NULL) {
01034         forwardingAddress = asExternalLSA->getContents ().getForwardingAddress ();
01035     }
01036 
01037     if ((externalCost == LS_INFINITY) || (lsAge == MAX_AGE) || (skipSelfOriginated && selfOriginated)) { // (1) and (2)
01038         return NULL;
01039     }
01040 
01041     if (!HasRouteToASBoundaryRouter (*fromRoutingTable, originatingRouter)) { // (3)
01042         return NULL;
01043     }
01044 
01045     if (forwardingAddress.isUnspecified()) {   // (3)
01046         std::vector<OSPF::RoutingTableEntry*> asbrEntries = GetRoutesToASBoundaryRouter (*fromRoutingTable, originatingRouter);
01047         if (!rfc1583Compatibility) {
01048             PruneASBoundaryRouterEntries (asbrEntries);
01049         }
01050         return SelectLeastCostRoutingEntry (asbrEntries);
01051     } else {
01052         OSPF::RoutingTableEntry* forwardEntry = Lookup (forwardingAddress, fromRoutingTable);
01053 
01054         if (forwardEntry == NULL) {
01055             return NULL;
01056         }
01057 
01058         if ((forwardEntry->GetPathType () != OSPF::RoutingTableEntry::IntraArea) &&
01059             (forwardEntry->GetPathType () != OSPF::RoutingTableEntry::InterArea))
01060         {
01061             return NULL;
01062         }
01063 
01064         return forwardEntry;
01065     }
01066 
01067     return NULL;
01068 }

bool OSPF::Router::GetRFC1583Compatibility void   )  const [inline]
 

00040 { return rfc1583Compatibility; }

RouterID OSPF::Router::GetRouterID void   )  const [inline]
 

00038 { return routerID; }

std::vector< OSPF::RoutingTableEntry * > OSPF::Router::GetRoutesToASBoundaryRouter const std::vector< RoutingTableEntry * > &  fromRoutingTable,
OSPF::RouterID  asbrRouterID
const [private]
 

Returns an std::vector of routes leading to the AS Boundary Router identified by asbrRouterID from the input fromRoutingTable. If there are no routes leading to the AS Boundary Router, the returned std::vector is empty.

Parameters:
fromRoutingTable [in] The routing table to look in.
asbrRouterID [in] The ID of the AS Boundary Router to look for.
00921 {
00922     std::vector<OSPF::RoutingTableEntry*> results;
00923     long                                  routeCount = fromRoutingTable.size ();
00924 
00925     for (long i = 0; i < routeCount; i++) {
00926         OSPF::RoutingTableEntry* routingEntry = fromRoutingTable[i];
00927         if (((routingEntry->GetDestinationType () & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) &&
00928             (routingEntry->GetDestinationID ().getInt () == asbrRouterID))
00929         {
00930             results.push_back (routingEntry);
00931         }
00932     }
00933     return results;
00934 }

const RoutingTableEntry* OSPF::Router::GetRoutingTableEntry unsigned long  i  )  const [inline]
 

00052 { return routingTable[i]; }

RoutingTableEntry* OSPF::Router::GetRoutingTableEntry unsigned long  i  )  [inline]
 

00051 { return routingTable[i]; }

unsigned long OSPF::Router::GetRoutingTableEntryCount void   )  const [inline]
 

00050 { return routingTable.size (); }

OSPF::LinkStateID OSPF::Router::GetUniqueLinkStateID OSPF::IPv4AddressRange  destination,
OSPF::Metric  destinationCost,
OSPF::ASExternalLSA *&  lsaToReoriginate,
bool  externalMetricIsType2 = false
const [private]
 

Generates a unique LinkStateID for a given destination. This may require the reorigination of an LSA already in the database (with a different LinkStateID).

Parameters:
destination [in] The destination for which a unique LinkStateID is required.
destinationCost [in] The path cost to the destination.
lsaToReoriginate [out] The LSA to reoriginate (which was already in the database, and had to be changed).
externalMetricIsType2 [in] True if the destinationCost is given as a Type2 external metric.
Returns:
the LinkStateID for the destination.
See also:
RFC2328 Appendix E.

OSPF::Area::GetUniqueLinkStateID

01252 {
01253     if (lsaToReoriginate != NULL) {
01254         delete lsaToReoriginate;
01255         lsaToReoriginate = NULL;
01256     }
01257 
01258     OSPF::LSAKeyType lsaKey;
01259 
01260     lsaKey.linkStateID = ULongFromIPv4Address (destination.address);
01261     lsaKey.advertisingRouter = routerID;
01262 
01263     const OSPF::ASExternalLSA* foundLSA = FindASExternalLSA (lsaKey);
01264 
01265     if (foundLSA == NULL) {
01266         return lsaKey.linkStateID;
01267     } else {
01268         OSPF::IPv4Address existingMask = IPv4AddressFromULong (foundLSA->getContents ().getNetworkMask ().getInt ());
01269 
01270         if (destination.mask >= existingMask) {
01271             return (lsaKey.linkStateID | (~(ULongFromIPv4Address (destination.mask))));
01272         } else {
01273             OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA (*foundLSA);
01274 
01275             long sequenceNumber = asExternalLSA->getHeader ().getLsSequenceNumber ();
01276 
01277             asExternalLSA->getHeader ().setLsAge (0);
01278             asExternalLSA->getHeader ().setLsSequenceNumber ((sequenceNumber == MAX_SEQUENCE_NUMBER) ? INITIAL_SEQUENCE_NUMBER : sequenceNumber + 1);
01279             asExternalLSA->getContents ().setNetworkMask (ULongFromIPv4Address (destination.mask));
01280             asExternalLSA->getContents ().setE_ExternalMetricType (externalMetricIsType2);
01281             asExternalLSA->getContents ().setRouteCost (destinationCost);
01282             asExternalLSA->getHeader ().setLsChecksum (0);    // TODO: calculate correct LS checksum
01283 
01284             lsaToReoriginate = asExternalLSA;
01285 
01286             return (lsaKey.linkStateID | (~(ULongFromIPv4Address (existingMask))));
01287         }
01288     }
01289 }

bool OSPF::Router::HasAddressRange OSPF::IPv4AddressRange  addressRange  )  const
 

Returns true if one of the Router's Areas the same IP address range configured as the input IP address range, false otherwise.

Parameters:
addressRange [in] The IP address range to look for.
00558 {
00559     long areaCount = areas.size ();
00560     for (long i = 0; i < areaCount; i++) {
00561         if (areas[i]->HasAddressRange (addressRange)) {
00562             return true;
00563         }
00564     }
00565     return false;
00566 }

bool OSPF::Router::HasRouteToASBoundaryRouter const std::vector< RoutingTableEntry * > &  inRoutingTable,
OSPF::RouterID  asbrRouterID
const [private]
 

Returns true if there is a route to the AS Boundary Router identified by asbrRouterID in the input inRoutingTable, false otherwise.

Parameters:
inRoutingTable [in] The routing table to look in.
asbrRouterID [in] The ID of the AS Boundary Router to look for.
00899 {
00900     long routeCount = inRoutingTable.size ();
00901     for (long i = 0; i < routeCount; i++) {
00902         OSPF::RoutingTableEntry* routingEntry = inRoutingTable[i];
00903         if (((routingEntry->GetDestinationType () & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0) &&
00904             (routingEntry->GetDestinationID ().getInt () == asbrRouterID))
00905         {
00906             return true;
00907         }
00908     }
00909     return false;
00910 }

bool OSPF::Router::InstallASExternalLSA OSPFASExternalLSA *  lsa  )  [private]
 

Installs a new AS External LSA into the Router's database. It tries to install keep one of multiple functionally equivalent AS External LSAs in the database. (See the comment in the method implementation.)

Parameters:
lsa [in] The LSA to install. It will be copied into the database.
Returns:
True if the routing table needs to be updated, false otherwise.

From RFC2328 Section 12.4.4.1.: "If two routers, both reachable from one another, originate functionally equivalent AS-External-LSAs (i.e., same destination, cost and non-zero forwarding address), then the LSA originated by the router having the highest OSPF Router ID is used. The router having the lower OSPF Router ID can then flush its LSA." The problem is: how do we tell whether two routers are reachable from one another based on a Link State Update packet? 0. We can assume that if this LSA reached this router, then this router is reachable from the other router. But what about the other direction? 1. The update packet is most likely not sent by the router originating the functionally equivalent AS-External-LSA, so we cannot use the IP packet source address. 2. The AS-External-LSA contains only the Router ID of the advertising router, so we can only look up "router" type routing entries in the routing table (these contain the Router ID as their Destination ID). However these entries are only inserted into the routing table for intra-area routers...

00185 {
00203      // TODO: how to solve this problem?
00204 
00205     OSPF::RouterID advertisingRouter = lsa->getHeader ().getAdvertisingRouter ().getInt ();
00206     bool           reachable         = false;
00207     unsigned int   routeCount        = routingTable.size ();
00208 
00209     for (unsigned int i = 0; i < routeCount; i++) {
00210         if ((((routingTable[i]->GetDestinationType () & OSPF::RoutingTableEntry::AreaBorderRouterDestination) != 0) ||
00211              ((routingTable[i]->GetDestinationType () & OSPF::RoutingTableEntry::ASBoundaryRouterDestination) != 0)) &&
00212             (routingTable[i]->GetDestinationID ().getInt () == advertisingRouter))
00213         {
00214             reachable = true;
00215             break;
00216         }
00217     }
00218 
00219     bool             ownLSAFloodedOut = false;
00220     OSPF::LSAKeyType lsaKey;
00221 
00222     lsaKey.linkStateID = lsa->getHeader ().getLinkStateID ();
00223     lsaKey.advertisingRouter = routerID;
00224 
00225     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find (lsaKey);
00226     if ((lsaIt != asExternalLSAsByID.end ()) &&
00227         reachable &&
00228         (lsaIt->second->getContents ().getE_ExternalMetricType () == lsa->getContents ().getE_ExternalMetricType ()) &&
00229         (lsaIt->second->getContents ().getRouteCost () == lsa->getContents ().getRouteCost ()) &&
00230         (lsa->getContents ().getForwardingAddress ().getInt () != 0) &&   // forwarding address != 0.0.0.0
00231         (lsaIt->second->getContents ().getForwardingAddress () == lsa->getContents ().getForwardingAddress ()))
00232     {
00233         if (routerID > advertisingRouter) {
00234             return false;
00235         } else {
00236             lsaIt->second->getHeader ().setLsAge (MAX_AGE);
00237             FloodLSA (lsaIt->second, OSPF::BackboneAreaID);
00238             lsaIt->second->IncrementInstallTime ();
00239             ownLSAFloodedOut = true;
00240         }
00241     }
00242 
00243     lsaKey.advertisingRouter = advertisingRouter;
00244 
00245     lsaIt = asExternalLSAsByID.find (lsaKey);
00246     if (lsaIt != asExternalLSAsByID.end ()) {
00247         unsigned long areaCount = areas.size ();
00248         for (unsigned long i = 0; i < areaCount; i++) {
00249             areas[i]->RemoveFromAllRetransmissionLists (lsaKey);
00250         }
00251         return ((lsaIt->second->Update (lsa)) | ownLSAFloodedOut);
00252     } else {
00253         OSPF::ASExternalLSA* lsaCopy = new OSPF::ASExternalLSA (*lsa);
00254         asExternalLSAsByID[lsaKey] = lsaCopy;
00255         asExternalLSAs.push_back (lsaCopy);
00256         return true;
00257     }
00258 }

bool OSPF::Router::InstallLSA OSPFLSA *  lsa,
OSPF::AreaID  areaID = BackboneAreaID
 

Installs a new LSA into the Router database. Checks the input LSA's type and installs it into either the selected Area's database, or if it's an AS External LSA then into the Router's common asExternalLSAs list.

Parameters:
lsa [in] The LSA to install. It will be copied into the database.
areaID [in] Identifies the input Router, Network and Summary LSA's Area.
Returns:
True if the routing table needs to be updated, false otherwise.
00133 {
00134     switch (lsa->getHeader ().getLsType ()) {
00135         case RouterLSAType:
00136             {
00137                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00138                 if (areaIt != areasByID.end ()) {
00139                     OSPFRouterLSA* ospfRouterLSA = check_and_cast<OSPFRouterLSA*> (lsa);
00140                     return areaIt->second->InstallRouterLSA (ospfRouterLSA);
00141                 }
00142             }
00143             break;
00144         case NetworkLSAType:
00145             {
00146                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00147                 if (areaIt != areasByID.end ()) {
00148                     OSPFNetworkLSA* ospfNetworkLSA = check_and_cast<OSPFNetworkLSA*> (lsa);
00149                     return areaIt->second->InstallNetworkLSA (ospfNetworkLSA);
00150                 }
00151             }
00152             break;
00153         case SummaryLSA_NetworksType:
00154         case SummaryLSA_ASBoundaryRoutersType:
00155             {
00156                 std::map<OSPF::AreaID, OSPF::Area*>::iterator areaIt = areasByID.find (areaID);
00157                 if (areaIt != areasByID.end ()) {
00158                     OSPFSummaryLSA* ospfSummaryLSA = check_and_cast<OSPFSummaryLSA*> (lsa);
00159                     return areaIt->second->InstallSummaryLSA (ospfSummaryLSA);
00160                 }
00161             }
00162             break;
00163         case ASExternalLSAType:
00164             {
00165                 OSPFASExternalLSA* ospfASExternalLSA = check_and_cast<OSPFASExternalLSA*> (lsa);
00166                 return InstallASExternalLSA (ospfASExternalLSA);
00167             }
00168             break;
00169         default:
00170             ASSERT (false);
00171             break;
00172     }
00173     return false;
00174 }

bool OSPF::Router::IsLocalAddress OSPF::IPv4Address  address  )  const
 

Returns true if the input IP address falls into any of the Router's Areas' configured IP address ranges, false otherwise.

Parameters:
address [in] The IP address to look for.
00541 {
00542     long areaCount = areas.size ();
00543     for (long i = 0; i < areaCount; i++) {
00544         if (areas[i]->IsLocalAddress (address)) {
00545             return true;
00546         }
00547     }
00548     return false;
00549 }

bool OSPF::Router::IsOnAnyRetransmissionList OSPF::LSAKeyType  lsaKey  )  const
 

Returns true if there's at least one LSA on any Neighbor's retransmission list identified by the input lsaKey, false otherwise.

Parameters:
lsaKey [in] Identifies the LSAs to look for on the retransmission lists.
00489 {
00490     long areaCount = areas.size ();
00491     for (long i = 0; i < areaCount; i++) {
00492         if (areas[i]->IsOnAnyRetransmissionList (lsaKey)) {
00493             return true;
00494         }
00495     }
00496     return false;
00497 }

OSPF::RoutingTableEntry * OSPF::Router::Lookup IPAddress  destination,
std::vector< RoutingTableEntry * > *  table = NULL
const
 

Do a lookup in either the input OSPF routing table, or if it's NULL then in the Router's own routing table.

See also:
RFC2328 Section 11.1.
Parameters:
destination [in] The destination to look up in the routing table.
table [in] The routing table to do the lookup in.
Returns:
The RoutingTableEntry describing the input destination if there's one, false otherwise.
00717 {
00718     const std::vector<OSPF::RoutingTableEntry*>& rTable           = (table == NULL) ? routingTable : (*table);
00719     unsigned long                                dest             = destination.getInt ();
00720     unsigned long                                routingTableSize = rTable.size ();
00721     bool                                         unreachable      = false;
00722     std::vector<OSPF::RoutingTableEntry*>        discard;
00723     unsigned long                                i;
00724 
00725     unsigned long areaCount = areas.size ();
00726     for (i = 0; i < areaCount; i++) {
00727         unsigned int addressRangeCount = areas[i]->GetAddressRangeCount ();
00728         for (unsigned int j = 0; j < addressRangeCount; j++) {
00729             OSPF::IPv4AddressRange range = areas[i]->GetAddressRange (j);
00730 
00731             for (unsigned int k = 0; k < routingTableSize; k++) {
00732                 OSPF::RoutingTableEntry* entry = rTable[k];
00733 
00734                 if (entry->GetDestinationType () != OSPF::RoutingTableEntry::NetworkDestination) {
00735                     continue;
00736                 }
00737                 if (((entry->GetDestinationID ().getInt () & entry->GetAddressMask ().getInt () & ULongFromIPv4Address (range.mask)) == ULongFromIPv4Address (range.address & range.mask)) &&
00738                     (entry->GetPathType () == OSPF::RoutingTableEntry::IntraArea))
00739                 {
00740                     // active area address range
00741                     OSPF::RoutingTableEntry* discardEntry = new OSPF::RoutingTableEntry;
00742                     discardEntry->SetDestinationID (ULongFromIPv4Address (range.address));
00743                     discardEntry->SetAddressMask (ULongFromIPv4Address (range.mask));
00744                     discardEntry->SetDestinationType (OSPF::RoutingTableEntry::NetworkDestination);
00745                     discardEntry->SetPathType (OSPF::RoutingTableEntry::InterArea);
00746                     discardEntry->SetArea (areas[i]->GetAreaID ());
00747                     discard.push_back (discardEntry);
00748                     break;
00749                 }
00750             }
00751         }
00752     }
00753 
00754     OSPF::RoutingTableEntry* bestMatch = NULL;
00755     unsigned long            longestMatch = 0;
00756 
00757     for (i = 0; i < routingTableSize; i++) {
00758         if (rTable[i]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) {
00759             OSPF::RoutingTableEntry* entry        = rTable[i];
00760             unsigned long            entryAddress = entry->GetDestinationID ().getInt ();
00761             unsigned long            entryMask    = entry->GetAddressMask ().getInt ();
00762 
00763             if ((entryAddress & entryMask) == (dest & entryMask)) {
00764                 if ((dest & entryMask) > longestMatch) {
00765                     longestMatch = (dest & entryMask);
00766                     bestMatch    = entry;
00767                 }
00768             }
00769         }
00770     }
00771 
00772     unsigned int discardCount = discard.size ();
00773     if (bestMatch == NULL) {
00774         unreachable = true;
00775     } else {
00776         for (i = 0; i < discardCount; i++) {
00777             OSPF::RoutingTableEntry* entry        = discard[i];
00778             unsigned long            entryAddress = entry->GetDestinationID ().getInt ();
00779             unsigned long            entryMask    = entry->GetAddressMask ().getInt ();
00780 
00781             if ((entryAddress & entryMask) == (dest & entryMask)) {
00782                 if ((dest & entryMask) > longestMatch) {
00783                     unreachable = true;
00784                     break;
00785                 }
00786             }
00787         }
00788     }
00789 
00790     for (i = 0; i < discardCount; i++) {
00791         delete discard[i];
00792     }
00793 
00794     if (unreachable) {
00795         return NULL;
00796     } else {
00797         return bestMatch;
00798     }
00799 }

void OSPF::Router::NotifyAboutRoutingTableChanges std::vector< RoutingTableEntry * > &  oldRoutingTable  )  [private]
 

After a routing table rebuild the changes in the routing table are identified and new SummaryLSAs are originated or old ones are flooded out in each area as necessary.

Parameters:
oldRoutingTable [in] The previous version of the routing table (which is then compared with the one in routingTable).
See also:
RFC2328 Section 12.4. points (5) through (6).
01302 {
01303     if (areas.size () <= 1) {
01304         return;
01305     }
01306 
01307     unsigned long                                 routeCount = oldRoutingTable.size ();
01308     std::map<unsigned long, RoutingTableEntry*>   oldTableMap;
01309     std::map<unsigned long, RoutingTableEntry*>   newTableMap;
01310     unsigned long                                 i, j, k;
01311 
01312     for (i = 0; i < routeCount; i++) {
01313         unsigned long destination = oldRoutingTable[i]->GetDestinationID ().getInt () & oldRoutingTable[i]->GetAddressMask ().getInt ();
01314         oldTableMap[destination] = oldRoutingTable[i];
01315     }
01316 
01317     routeCount = routingTable.size ();
01318     for (i = 0; i < routeCount; i++) {
01319         unsigned long   destination = routingTable[i]->GetDestinationID ().getInt () & routingTable[i]->GetAddressMask ().getInt ();
01320         newTableMap[destination] = routingTable[i];
01321     }
01322 
01323     unsigned long areaCount = areas.size ();
01324     for (i = 0; i < areaCount; i++) {
01325         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less> originatedLSAMap;
01326         std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less> deletedLSAMap;
01327         OSPF::LSAKeyType                                        lsaKey;
01328 
01329         routeCount = routingTable.size ();
01330         for (j = 0; j < routeCount; j++) {
01331             unsigned long                                         destination = routingTable[j]->GetDestinationID ().getInt () & routingTable[j]->GetAddressMask ().getInt ();
01332             std::map<unsigned long, RoutingTableEntry*>::iterator destIt      = oldTableMap.find (destination);
01333             if (destIt == oldTableMap.end ()) { // new routing entry
01334                 OSPF::SummaryLSA* lsaToReoriginate = NULL;
01335                 OSPF::SummaryLSA* newLSA           = areas[i]->OriginateSummaryLSA (routingTable[j], originatedLSAMap, lsaToReoriginate);
01336 
01337                 if (newLSA != NULL) {
01338                     if (lsaToReoriginate != NULL) {
01339                         areas[i]->InstallSummaryLSA (lsaToReoriginate);
01340                         FloodLSA (lsaToReoriginate, OSPF::BackboneAreaID);
01341 
01342                         lsaKey.linkStateID       = lsaToReoriginate->getHeader ().getLinkStateID ();
01343                         lsaKey.advertisingRouter = routerID;
01344                         originatedLSAMap[lsaKey] = true;
01345 
01346                         delete lsaToReoriginate;
01347                     }
01348 
01349                     areas[i]->InstallSummaryLSA (newLSA);
01350                     FloodLSA (newLSA, OSPF::BackboneAreaID);
01351 
01352                     lsaKey.linkStateID       = newLSA->getHeader ().getLinkStateID ();
01353                     lsaKey.advertisingRouter = routerID;
01354                     originatedLSAMap[lsaKey] = true;
01355 
01356                     delete newLSA;
01357                 }
01358             } else {
01359                 if (*(routingTable[j]) != *(destIt->second)) {  // modified routing entry
01360                     OSPF::SummaryLSA* lsaToReoriginate = NULL;
01361                     OSPF::SummaryLSA* newLSA           = areas[i]->OriginateSummaryLSA (routingTable[j], originatedLSAMap, lsaToReoriginate);
01362 
01363                     if (newLSA != NULL) {
01364                         if (lsaToReoriginate != NULL) {
01365                             areas[i]->InstallSummaryLSA (lsaToReoriginate);
01366                             FloodLSA (lsaToReoriginate, OSPF::BackboneAreaID);
01367 
01368                             lsaKey.linkStateID       = lsaToReoriginate->getHeader ().getLinkStateID ();
01369                             lsaKey.advertisingRouter = routerID;
01370                             originatedLSAMap[lsaKey] = true;
01371 
01372                             delete lsaToReoriginate;
01373                         }
01374 
01375                         areas[i]->InstallSummaryLSA (newLSA);
01376                         FloodLSA (newLSA, OSPF::BackboneAreaID);
01377 
01378                         lsaKey.linkStateID       = newLSA->getHeader ().getLinkStateID ();
01379                         lsaKey.advertisingRouter = routerID;
01380                         originatedLSAMap[lsaKey] = true;
01381 
01382                         delete newLSA;
01383                     } else {
01384                         OSPF::IPv4AddressRange destinationAddressRange;
01385 
01386                         destinationAddressRange.address = IPv4AddressFromULong (routingTable[j]->GetDestinationID ().getInt ());
01387                         destinationAddressRange.mask = IPv4AddressFromULong (routingTable[j]->GetAddressMask ().getInt ());
01388 
01389                         if ((routingTable[j]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) &&
01390                             ((routingTable[j]->GetPathType () == OSPF::RoutingTableEntry::IntraArea) ||
01391                              (routingTable[j]->GetPathType () == OSPF::RoutingTableEntry::InterArea)))
01392                         {
01393                             OSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange (destinationAddressRange);
01394                             if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01395                                 destinationAddressRange = containingAddressRange;
01396                             }
01397                         }
01398 
01399                         Metric maxRangeCost = 0;
01400                         Metric oneLessCost  = 0;
01401 
01402                         for (k = 0; k < routeCount; k++) {
01403                             if ((routingTable[k]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) &&
01404                                 (routingTable[k]->GetPathType () == OSPF::RoutingTableEntry::IntraArea) &&
01405                                 ((routingTable[k]->GetDestinationID ().getInt () & routingTable[k]->GetAddressMask ().getInt () & ULongFromIPv4Address (destinationAddressRange.mask)) ==
01406                                  ULongFromIPv4Address (destinationAddressRange.address & destinationAddressRange.mask)) &&
01407                                 (routingTable[k]->GetCost () > maxRangeCost))
01408                             {
01409                                 oneLessCost  = maxRangeCost;
01410                                 maxRangeCost = routingTable[k]->GetCost ();
01411                             }
01412                         }
01413 
01414                         if (maxRangeCost == routingTable[j]->GetCost ()) {  // this entry gives the range's cost
01415                             lsaKey.linkStateID       = ULongFromIPv4Address (destinationAddressRange.address);
01416                             lsaKey.advertisingRouter = routerID;
01417 
01418                             OSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA (lsaKey);
01419 
01420                             if (summaryLSA != NULL) {
01421                                 if (oneLessCost != 0) { // there's an other entry in this range
01422                                     summaryLSA->setRouteCost (oneLessCost);
01423                                     FloodLSA (summaryLSA, OSPF::BackboneAreaID);
01424 
01425                                     originatedLSAMap[lsaKey] = true;
01426                                 } else {    // no more entries in this range -> delete it
01427                                     std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find (lsaKey);
01428                                     if (deletedIt == deletedLSAMap.end ()) {
01429                                         summaryLSA->getHeader ().setLsAge (MAX_AGE);
01430                                         FloodLSA (summaryLSA, OSPF::BackboneAreaID);
01431 
01432                                         deletedLSAMap[lsaKey]    = true;
01433                                     }
01434                                 }
01435                             }
01436                         }
01437                     }
01438                 }
01439             }
01440         }
01441 
01442         routeCount = oldRoutingTable.size ();
01443         for (j = 0; j < routeCount; j++) {
01444             unsigned long                                         destination = oldRoutingTable[j]->GetDestinationID ().getInt () & oldRoutingTable[j]->GetAddressMask ().getInt ();
01445             std::map<unsigned long, RoutingTableEntry*>::iterator destIt      = newTableMap.find (destination);
01446             if (destIt == newTableMap.end ()) { // deleted routing entry
01447                 OSPF::IPv4AddressRange destinationAddressRange;
01448 
01449                 destinationAddressRange.address = IPv4AddressFromULong (oldRoutingTable[j]->GetDestinationID ().getInt ());
01450                 destinationAddressRange.mask = IPv4AddressFromULong (oldRoutingTable[j]->GetAddressMask ().getInt ());
01451 
01452                 if ((oldRoutingTable[j]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) &&
01453                     ((oldRoutingTable[j]->GetPathType () == OSPF::RoutingTableEntry::IntraArea) ||
01454                      (oldRoutingTable[j]->GetPathType () == OSPF::RoutingTableEntry::InterArea)))
01455                 {
01456                     OSPF::IPv4AddressRange containingAddressRange = GetContainingAddressRange (destinationAddressRange);
01457                     if (containingAddressRange != OSPF::NullIPv4AddressRange) {
01458                         destinationAddressRange = containingAddressRange;
01459                     }
01460                 }
01461 
01462                 Metric maxRangeCost = 0;
01463 
01464                 unsigned long newRouteCount = routingTable.size ();
01465                 for (k = 0; k < newRouteCount; k++) {
01466                     if ((routingTable[k]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) &&
01467                         (routingTable[k]->GetPathType () == OSPF::RoutingTableEntry::IntraArea) &&
01468                         ((routingTable[k]->GetDestinationID ().getInt () & routingTable[k]->GetAddressMask ().getInt () & ULongFromIPv4Address (destinationAddressRange.mask)) ==
01469                          ULongFromIPv4Address (destinationAddressRange.address & destinationAddressRange.mask)) &&
01470                         (routingTable[k]->GetCost () > maxRangeCost))
01471                     {
01472                         maxRangeCost = routingTable[k]->GetCost ();
01473                     }
01474                 }
01475 
01476                 if (maxRangeCost < oldRoutingTable[j]->GetCost ()) {  // the range's cost will change
01477                     lsaKey.linkStateID       = ULongFromIPv4Address (destinationAddressRange.address);
01478                     lsaKey.advertisingRouter = routerID;
01479 
01480                     OSPF::SummaryLSA* summaryLSA = areas[i]->FindSummaryLSA (lsaKey);
01481 
01482                     if (summaryLSA != NULL) {
01483                         if (maxRangeCost > 0) { // there's an other entry in this range
01484                             summaryLSA->setRouteCost (maxRangeCost);
01485                             FloodLSA (summaryLSA, OSPF::BackboneAreaID);
01486 
01487                             originatedLSAMap[lsaKey] = true;
01488                         } else {    // no more entries in this range -> delete it
01489                             std::map<OSPF::LSAKeyType, bool, OSPF::LSAKeyType_Less>::const_iterator deletedIt = deletedLSAMap.find (lsaKey);
01490                             if (deletedIt == deletedLSAMap.end ()) {
01491                                 summaryLSA->getHeader ().setLsAge (MAX_AGE);
01492                                 FloodLSA (summaryLSA, OSPF::BackboneAreaID);
01493 
01494                                 deletedLSAMap[lsaKey]    = true;
01495                             }
01496                         }
01497                     }
01498                 }
01499             }
01500         }
01501     }
01502 }

OSPF::ASExternalLSA * OSPF::Router::OriginateASExternalLSA OSPF::ASExternalLSA lsa  )  [private]
 

Originates a new AS External LSA based on the input lsa.

Parameters:
lsa [in] The LSA whose contents should be copied into the newly originated LSA.
Returns:
The newly originated LSA.
00575 {
00576     OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA (*lsa);
00577     OSPFLSAHeader& lsaHeader = asExternalLSA->getHeader ();
00578     OSPFOptions    lsaOptions;
00579 
00580     lsaHeader.setLsAge (0);
00581     memset (&lsaOptions, 0, sizeof (OSPFOptions));
00582     lsaOptions.E_ExternalRoutingCapability = true;
00583     lsaHeader.setLsOptions (lsaOptions);
00584     lsaHeader.setLsSequenceNumber (INITIAL_SEQUENCE_NUMBER);
00585     asExternalLSA->SetSource (OSPF::LSATrackingInfo::Originated);
00586 
00587     return asExternalLSA;
00588 }

void OSPF::Router::PruneASBoundaryRouterEntries std::vector< RoutingTableEntry * > &  asbrEntries  )  const [private]
 

Prunes the input std::vector of RoutingTableEntries according to the RFC2328 Section 16.4.1.

Parameters:
asbrEntries [in/out] The list of RoutingTableEntries to prune.
See also:
RFC2328 Section 16.4.1.
00944 {
00945     bool hasNonBackboneIntraAreaPath = false;
00946     for (std::vector<OSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin (); it != asbrEntries.end (); it++) {
00947         OSPF::RoutingTableEntry* routingEntry = *it;
00948         if ((routingEntry->GetPathType () == OSPF::RoutingTableEntry::IntraArea) &&
00949             (routingEntry->GetArea () != OSPF::BackboneAreaID))
00950         {
00951             hasNonBackboneIntraAreaPath = true;
00952             break;
00953         }
00954     }
00955 
00956     if (hasNonBackboneIntraAreaPath) {
00957         std::vector<OSPF::RoutingTableEntry*>::iterator it = asbrEntries.begin ();
00958         while (it != asbrEntries.end ()) {
00959             if (((*it)->GetPathType () != OSPF::RoutingTableEntry::IntraArea) ||
00960                 ((*it)->GetArea () == OSPF::BackboneAreaID))
00961             {
00962                 it = asbrEntries.erase (it);
00963             } else {
00964                 it++;
00965             }
00966         }
00967     }
00968 }

void OSPF::Router::RebuildRoutingTable void   ) 
 

Rebuilds the routing table from scratch (based on the LSA database).

See also:
RFC2328 Section 16.
00807 {
00808     unsigned long                         areaCount       = areas.size ();
00809     bool                                  hasTransitAreas = false;
00810     std::vector<OSPF::RoutingTableEntry*> newTable;
00811     unsigned long                         i;
00812 
00813     EV << "Rebuilding routing table:\n";
00814 
00815     for (i = 0; i < areaCount; i++) {
00816         areas[i]->CalculateShortestPathTree (newTable);
00817         if (areas[i]->GetTransitCapability ()) {
00818             hasTransitAreas = true;
00819         }
00820     }
00821     if (areaCount > 1) {
00822         OSPF::Area* backbone = GetArea (OSPF::BackboneAreaID);
00823         if (backbone != NULL) {
00824             backbone->CalculateInterAreaRoutes (newTable);
00825         }
00826     } else {
00827         if (areaCount == 1) {
00828             areas[0]->CalculateInterAreaRoutes (newTable);
00829         }
00830     }
00831     if (hasTransitAreas) {
00832         for (i = 0; i < areaCount; i++) {
00833             if (areas[i]->GetTransitCapability ()) {
00834                 areas[i]->ReCheckSummaryLSAs (newTable);
00835             }
00836         }
00837     }
00838     CalculateASExternalRoutes (newTable);
00839 
00840     // backup the routing table
00841     unsigned long                         routeCount = routingTable.size ();
00842     std::vector<OSPF::RoutingTableEntry*> oldTable;
00843 
00844     oldTable.assign (routingTable.begin (), routingTable.end ());
00845     routingTable.clear ();
00846     routingTable.assign (newTable.begin (), newTable.end ());
00847 
00848     RoutingTableAccess         routingTableAccess;
00849     std::vector<RoutingEntry*> eraseEntries;
00850     RoutingTable*              simRoutingTable    = routingTableAccess.get ();
00851     unsigned long              routingEntryNumber = simRoutingTable->numRoutingEntries ();
00852     // remove entries from the IP routing table inserted by the OSPF module
00853     for (i = 0; i < routingEntryNumber; i++) {
00854         RoutingEntry*            entry     = simRoutingTable->routingEntry (i);
00855         OSPF::RoutingTableEntry* ospfEntry = dynamic_cast<OSPF::RoutingTableEntry*> (entry);
00856         if (ospfEntry != NULL) {
00857             eraseEntries.push_back (entry);
00858         }
00859     }
00860 
00861     unsigned int eraseCount = eraseEntries.size ();
00862     for (i = 0; i < eraseCount; i++) {
00863         simRoutingTable->deleteRoutingEntry (eraseEntries[i]);
00864     }
00865 
00866     // add the new routing entries
00867     routeCount = routingTable.size ();
00868     for (i = 0; i < routeCount; i++) {
00869         if (routingTable[i]->GetDestinationType () == OSPF::RoutingTableEntry::NetworkDestination) {
00870             simRoutingTable->addRoutingEntry (new OSPF::RoutingTableEntry (*(routingTable[i])));
00871         }
00872     }
00873 
00874     NotifyAboutRoutingTableChanges (oldTable);
00875 
00876     routeCount = oldTable.size ();
00877     for (i = 0; i < routeCount; i++) {
00878         delete (oldTable[i]);
00879     }
00880 
00881     EV << "Routing table was rebuilt.\n"
00882        << "Results:\n";
00883 
00884     routeCount = routingTable.size ();
00885     for (i = 0; i < routeCount; i++) {
00886         EV << *routingTable[i]
00887            << "\n";
00888     }
00889 }

void OSPF::Router::RemoveExternalRoute OSPF::IPv4Address  networkAddress  ) 
 

Removes an AS External Route from the database.

Parameters:
networkAddress [in] The network address of the external route which needs to be removed.
01576 {
01577     OSPF::LSAKeyType     lsaKey;
01578 
01579     lsaKey.linkStateID = ULongFromIPv4Address (networkAddress);
01580     lsaKey.advertisingRouter = routerID;
01581 
01582     std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find (lsaKey);
01583     if (lsaIt != asExternalLSAsByID.end ()) {
01584         lsaIt->second->getHeader ().setLsAge (MAX_AGE);
01585         lsaIt->second->SetPurgeable ();
01586         FloodLSA (lsaIt->second, OSPF::BackboneAreaID);
01587     }
01588 
01589     std::map<OSPF::IPv4Address, OSPFASExternalLSAContents, OSPF::IPv4Address_Less>::iterator externalIt = externalRoutes.find (networkAddress);
01590     if (externalIt != externalRoutes.end ()) {
01591         externalRoutes.erase (externalIt);
01592     }
01593 }

void OSPF::Router::RemoveFromAllRetransmissionLists OSPF::LSAKeyType  lsaKey  ) 
 

Removes all LSAs from all Neighbor's retransmission lists which are identified by the input lsaKey.

Parameters:
lsaKey [in] Identifies the LSAs to remove from the retransmission lists.
00475 {
00476     long areaCount = areas.size ();
00477     for (long i = 0; i < areaCount; i++) {
00478         areas[i]->RemoveFromAllRetransmissionLists (lsaKey);
00479     }
00480 }

OSPF::RoutingTableEntry * OSPF::Router::SelectLeastCostRoutingEntry std::vector< RoutingTableEntry * > &  entries  )  const [private]
 

Selects the least cost RoutingTableEntry from the input std::vector of RoutingTableEntries.

Parameters:
entries [in] The RoutingTableEntries to choose the least cost one from.
Returns:
The least cost entry or NULL if entries is empty.
00978 {
00979     if (entries.empty ()) {
00980         return NULL;
00981     }
00982 
00983     OSPF::RoutingTableEntry* leastCostEntry = entries[0];
00984     Metric                   leastCost      = leastCostEntry->GetCost ();
00985     long                     routeCount     = entries.size ();
00986 
00987     for (long i = 1; i < routeCount; i++) {
00988         Metric currentCost = entries[i]->GetCost ();
00989         if ((currentCost < leastCost) ||
00990             ((currentCost == leastCost) && (entries[i]->GetArea () > leastCostEntry->GetArea ())))
00991         {
00992             leastCostEntry = entries[i];
00993             leastCost = currentCost;
00994         }
00995     }
00996 
00997     return leastCostEntry;
00998 }

void OSPF::Router::SetRFC1583Compatibility bool  compatibility  )  [inline]
 

00039 { rfc1583Compatibility = compatibility; }

void OSPF::Router::SetRouterID RouterID  id  )  [inline]
 

00037 { routerID = id; }

void OSPF::Router::UpdateExternalRoute OSPF::IPv4Address  networkAddress,
const OSPFASExternalLSAContents &  externalRouteContents,
int  ifIndex
 

Stores information on an AS External Route in externalRoutes and intalls (or updates) a new ASExternalLSA into the database.

Parameters:
networkAddress [in] The external route's network address.
externalRouteContents [in] Route configuration data for the external route.
01513 {
01514     OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA;
01515     OSPFLSAHeader&       lsaHeader     = asExternalLSA->getHeader ();
01516     OSPFOptions          lsaOptions;
01517     //OSPF::LSAKeyType     lsaKey;
01518 
01519     RoutingTable*      simRoutingTable    = RoutingTableAccess ().get ();
01520     unsigned long      routingEntryNumber = simRoutingTable->numRoutingEntries ();
01521     bool               inRoutingTable     = false;
01522     // add the external route to the routing table if it was not added by another module
01523     for (unsigned long i = 0; i < routingEntryNumber; i++) {
01524         RoutingEntry* entry = simRoutingTable->routingEntry (i);
01525         if ((entry->host.getInt () & entry->netmask.getInt ()) ==
01526             (ULongFromIPv4Address (networkAddress) & externalRouteContents.getNetworkMask ().getInt ()))
01527         {
01528             inRoutingTable = true;
01529         }
01530     }
01531     if (!inRoutingTable) {
01532         RoutingEntry* entry = new RoutingEntry;
01533         entry->host = ULongFromIPv4Address (networkAddress);
01534         entry->netmask = externalRouteContents.getNetworkMask ();
01535         entry->interfacePtr = InterfaceTableAccess ().get ()->interfaceAt (ifIndex);
01536         entry->interfaceName = entry->interfacePtr->name ();
01537         entry->type = RoutingEntry::REMOTE;
01538         entry->source = RoutingEntry::MANUAL;
01539         entry->metric = externalRouteContents.getRouteCost ();
01540         simRoutingTable->addRoutingEntry (entry);   // RoutingTable deletes entry pointer
01541     }
01542 
01543     lsaHeader.setLsAge (0);
01544     memset (&lsaOptions, 0, sizeof (OSPFOptions));
01545     lsaOptions.E_ExternalRoutingCapability = true;
01546     lsaHeader.setLsOptions (lsaOptions);
01547     lsaHeader.setLsType (ASExternalLSAType);
01548     lsaHeader.setLinkStateID (ULongFromIPv4Address (networkAddress));   // TODO: get unique LinkStateID
01549     lsaHeader.setAdvertisingRouter (routerID);
01550     lsaHeader.setLsSequenceNumber (INITIAL_SEQUENCE_NUMBER);
01551 
01552     asExternalLSA->setContents (externalRouteContents);
01553 
01554     lsaHeader.setLsChecksum (0);    // TODO: calculate correct LS checksum
01555 
01556     asExternalLSA->SetSource (OSPF::LSATrackingInfo::Originated);
01557 
01558     externalRoutes[networkAddress] = externalRouteContents;
01559 
01560     bool rebuild = InstallASExternalLSA (asExternalLSA);
01561     FloodLSA (asExternalLSA, OSPF::BackboneAreaID);
01562     delete asExternalLSA;
01563 
01564     if (rebuild) {
01565         RebuildRoutingTable ();
01566     }
01567 }


Member Data Documentation

OSPFTimer* OSPF::Router::ageTimer [private]
 

Database age timer - fires every second.

std::vector<Area*> OSPF::Router::areas [private]
 

A list of the contained areas.

std::map<AreaID, Area*> OSPF::Router::areasByID [private]
 

A map of the contained areas with the AreaID as key.

std::vector<ASExternalLSA*> OSPF::Router::asExternalLSAs [private]
 

A list of the ASExternalLSAs advertised by this router.

std::map<LSAKeyType, ASExternalLSA*, LSAKeyType_Less> OSPF::Router::asExternalLSAsByID [private]
 

A map of the ASExternalLSAs advertised by this router.

std::map<IPv4Address, OSPFASExternalLSAContents, IPv4Address_Less> OSPF::Router::externalRoutes [private]
 

A map of the external route advertised by this router.

MessageHandler* OSPF::Router::messageHandler [private]
 

The message dispatcher class.

bool OSPF::Router::rfc1583Compatibility [private]
 

Decides whether to handle the preferred routing table entry to an AS boundary router as defined in RFC1583 or not.

RouterID OSPF::Router::routerID [private]
 

The router ID assigned by the IP layer.

std::vector<RoutingTableEntry*> OSPF::Router::routingTable [private]
 

The OSPF routing table - contains more information than the one in the IP layer.


The documentation for this class was generated from the following files:
Generated on Sat Apr 1 20:52:26 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.1