#include <OSPFRouter.h>
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 |
MessageHandler * | GetMessageHandler (void) |
unsigned long | GetASExternalLSACount (void) const |
ASExternalLSA * | GetASExternalLSA (unsigned long i) |
const ASExternalLSA * | GetASExternalLSA (unsigned long i) const |
bool | GetASBoundaryRouter (void) const |
unsigned long | GetRoutingTableEntryCount (void) const |
RoutingTableEntry * | GetRoutingTableEntry (unsigned long i) |
const RoutingTableEntry * | GetRoutingTableEntry (unsigned long i) const |
void | AddRoutingTableEntry (RoutingTableEntry *entry) |
void | AddWatches (void) |
void | AddArea (Area *area) |
Area * | GetArea (AreaID areaID) |
Area * | GetArea (IPv4Address address) |
Interface * | GetNonVirtualInterface (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 |
RoutingTableEntry * | Lookup (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) |
RoutingTableEntry * | GetPreferredEntry (const OSPFLSA &lsa, bool skipSelfOriginated, std::vector< RoutingTableEntry * > *fromRoutingTable=NULL) |
Private Member Functions | |
bool | InstallASExternalLSA (OSPFASExternalLSA *lsa) |
ASExternalLSA * | FindASExternalLSA (LSAKeyType lsaKey) |
const ASExternalLSA * | FindASExternalLSA (LSAKeyType lsaKey) const |
ASExternalLSA * | OriginateASExternalLSA (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 |
RoutingTableEntry * | SelectLeastCostRoutingEntry (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. | |
MessageHandler * | messageHandler |
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. |
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 }
void OSPF::Router::AddArea | ( | OSPF::Area * | area | ) |
void OSPF::Router::AddRoutingTableEntry | ( | RoutingTableEntry * | entry | ) | [inline] |
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).
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.
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] |
bool OSPF::Router::DestinationIsUnreachable | ( | OSPFLSA * | lsa | ) | const |
Returns true if the destination described by the input lsa is in the routing table, false otherwise.
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.
lsaKey | [in] Look for the AS External LSA which is identified by this key. |
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.
lsaKey | [in] Look for the AS External LSA which is identified by this key. |
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.
lsaType | [in] Look for an LSA of this type. | |
lsaKey | [in] Look for the LSA which is identified by this key. | |
areaID | [in] In case of Router, Network and Summary LSAs, look in the Area's database identified by this parameter. |
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.
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. |
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.
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.
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] |
bool OSPF::Router::GetASBoundaryRouter | ( | void | ) | const [inline] |
const ASExternalLSA* OSPF::Router::GetASExternalLSA | ( | unsigned long | i | ) | const [inline] |
ASExternalLSA* OSPF::Router::GetASExternalLSA | ( | unsigned long | i | ) | [inline] |
unsigned long OSPF::Router::GetASExternalLSACount | ( | void | ) | const [inline] |
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.
addressRange | [in] The address range to look for. | |
advertise | [out] Whether the advertise flag is set in the returned preconfigured address range. |
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] |
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.
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 }
RoutingTableEntry* OSPF::Router::GetPreferredEntry | ( | const OSPFLSA & | lsa, | |
bool | skipSelfOriginated, | |||
std::vector< RoutingTableEntry * > * | fromRoutingTable = NULL | |||
) |
bool OSPF::Router::GetRFC1583Compatibility | ( | void | ) | const [inline] |
std::vector<RoutingTableEntry*> OSPF::Router::GetRoutesToASBoundaryRouter | ( | const std::vector< RoutingTableEntry * > & | fromRoutingTable, | |
OSPF::RouterID | routerID | |||
) | const [private] |
const RoutingTableEntry* OSPF::Router::GetRoutingTableEntry | ( | unsigned long | i | ) | const [inline] |
RoutingTableEntry* OSPF::Router::GetRoutingTableEntry | ( | unsigned long | i | ) | [inline] |
unsigned long OSPF::Router::GetRoutingTableEntryCount | ( | void | ) | const [inline] |
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).
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. |
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.
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 | routerID | |||
) | const [private] |
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.)
lsa | [in] The LSA to install. It will be copied into the database. |
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.
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. |
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.
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.
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 }
RoutingTableEntry* OSPF::Router::Lookup | ( | IPAddress | destination, | |
std::vector< RoutingTableEntry * > * | table = NULL | |||
) | const |
void OSPF::Router::NotifyAboutRoutingTableChanges | ( | std::vector< RoutingTableEntry * > & | oldRoutingTable | ) | [private] |
OSPF::ASExternalLSA * OSPF::Router::OriginateASExternalLSA | ( | OSPF::ASExternalLSA * | lsa | ) | [private] |
Originates a new AS External LSA based on the input lsa.
lsa | [in] The LSA whose contents should be copied into 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] |
void OSPF::Router::RebuildRoutingTable | ( | void | ) |
Rebuilds the routing table from scratch (based on the LSA database).
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.
networkAddress | [in] The network address of the external route which needs to be removed. |
01582 { 01583 OSPF::LSAKeyType lsaKey; 01584 01585 lsaKey.linkStateID = ULongFromIPv4Address (networkAddress); 01586 lsaKey.advertisingRouter = routerID; 01587 01588 std::map<OSPF::LSAKeyType, OSPF::ASExternalLSA*, OSPF::LSAKeyType_Less>::iterator lsaIt = asExternalLSAsByID.find (lsaKey); 01589 if (lsaIt != asExternalLSAsByID.end ()) { 01590 lsaIt->second->getHeader ().setLsAge (MAX_AGE); 01591 lsaIt->second->SetPurgeable (); 01592 FloodLSA (lsaIt->second, OSPF::BackboneAreaID); 01593 } 01594 01595 std::map<OSPF::IPv4Address, OSPFASExternalLSAContents, OSPF::IPv4Address_Less>::iterator externalIt = externalRoutes.find (networkAddress); 01596 if (externalIt != externalRoutes.end ()) { 01597 externalRoutes.erase (externalIt); 01598 } 01599 }
void OSPF::Router::RemoveFromAllRetransmissionLists | ( | OSPF::LSAKeyType | lsaKey | ) |
Removes all LSAs from all Neighbor's retransmission lists which are identified by the input lsaKey.
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 }
RoutingTableEntry* OSPF::Router::SelectLeastCostRoutingEntry | ( | std::vector< RoutingTableEntry * > & | entries | ) | const [private] |
void OSPF::Router::SetRFC1583Compatibility | ( | bool | compatibility | ) | [inline] |
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.
networkAddress | [in] The external route's network address. | |
externalRouteContents | [in] Route configuration data for the external route. | |
ifIndex | [in] |
01519 { 01520 OSPF::ASExternalLSA* asExternalLSA = new OSPF::ASExternalLSA; 01521 OSPFLSAHeader& lsaHeader = asExternalLSA->getHeader (); 01522 OSPFOptions lsaOptions; 01523 //OSPF::LSAKeyType lsaKey; 01524 01525 RoutingTable* simRoutingTable = RoutingTableAccess ().get (); 01526 unsigned long routingEntryNumber = simRoutingTable->numRoutingEntries (); 01527 bool inRoutingTable = false; 01528 // add the external route to the routing table if it was not added by another module 01529 for (unsigned long i = 0; i < routingEntryNumber; i++) { 01530 RoutingEntry* entry = simRoutingTable->routingEntry (i); 01531 if ((entry->host.getInt () & entry->netmask.getInt ()) == 01532 (ULongFromIPv4Address (networkAddress) & externalRouteContents.getNetworkMask ().getInt ())) 01533 { 01534 inRoutingTable = true; 01535 } 01536 } 01537 if (!inRoutingTable) { 01538 RoutingEntry* entry = new RoutingEntry; 01539 entry->host = ULongFromIPv4Address (networkAddress); 01540 entry->netmask = externalRouteContents.getNetworkMask (); 01541 entry->interfacePtr = InterfaceTableAccess ().get ()->interfaceAt (ifIndex); 01542 entry->interfaceName = entry->interfacePtr->name (); 01543 entry->type = RoutingEntry::REMOTE; 01544 entry->source = RoutingEntry::MANUAL; 01545 entry->metric = externalRouteContents.getRouteCost (); 01546 simRoutingTable->addRoutingEntry (entry); // RoutingTable deletes entry pointer 01547 } 01548 01549 lsaHeader.setLsAge (0); 01550 memset (&lsaOptions, 0, sizeof (OSPFOptions)); 01551 lsaOptions.E_ExternalRoutingCapability = true; 01552 lsaHeader.setLsOptions (lsaOptions); 01553 lsaHeader.setLsType (ASExternalLSAType); 01554 lsaHeader.setLinkStateID (ULongFromIPv4Address (networkAddress)); // TODO: get unique LinkStateID 01555 lsaHeader.setAdvertisingRouter (routerID); 01556 lsaHeader.setLsSequenceNumber (INITIAL_SEQUENCE_NUMBER); 01557 01558 asExternalLSA->setContents (externalRouteContents); 01559 01560 lsaHeader.setLsChecksum (0); // TODO: calculate correct LS checksum 01561 01562 asExternalLSA->SetSource (OSPF::LSATrackingInfo::Originated); 01563 01564 externalRoutes[networkAddress] = externalRouteContents; 01565 01566 bool rebuild = InstallASExternalLSA (asExternalLSA); 01567 FloodLSA (asExternalLSA, OSPF::BackboneAreaID); 01568 delete asExternalLSA; 01569 01570 if (rebuild) { 01571 RebuildRoutingTable (); 01572 } 01573 }
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] |