INET Framework for OMNeT++/OMNEST
AnsaLinkStateUpdateHandler.cc
Go to the documentation of this file.
00001 #include "AnsaLinkStateUpdateHandler.h"
00002 #include "AnsaOSPFcommon.h"
00003 #include "AnsaOSPFRouter.h"
00004 #include "AnsaOSPFArea.h"
00005 #include "AnsaOSPFNeighbor.h"
00006 
00007 class LSAProcessingMarker
00008 {
00009 private:
00010     unsigned int index;
00011 
00012 public:
00013     LSAProcessingMarker(unsigned int counter) : index(counter) { EV << "    --> Processing LSA(" << index << ")\n"; }
00014     ~LSAProcessingMarker()                                      { EV << "    <-- LSA(" << index << ") processed.\n"; }
00015 };
00016 
00017 
00018 AnsaOSPF::LinkStateUpdateHandler::LinkStateUpdateHandler(AnsaOSPF::Router* containingRouter) :
00019     AnsaOSPF::IMessageHandler(containingRouter)
00020 {
00021 }
00022 
00026 void AnsaOSPF::LinkStateUpdateHandler::ProcessPacket(OSPFPacket* packet, AnsaOSPF::Interface* intf, AnsaOSPF::Neighbor* neighbor)
00027 {
00028     router->GetMessageHandler()->PrintEvent("Link State Update packet received", intf, neighbor);
00029 
00030     OSPFLinkStateUpdatePacket* lsUpdatePacket      = check_and_cast<OSPFLinkStateUpdatePacket*> (packet);
00031     bool                       rebuildRoutingTable = false;
00032 
00033     if (neighbor->GetState() >= AnsaOSPF::Neighbor::ExchangeState) {
00034         AnsaOSPF::AreaID areaID          = lsUpdatePacket->getAreaID().getInt();
00035         AnsaOSPF::Area*  area            = router->GetArea(areaID);
00036         LSAType      currentType     = RouterLSAType;
00037         unsigned int currentLSAIndex = 0;
00038 
00039         EV << "  Processing packet contents:\n";
00040 
00041         while (currentType <= ASExternalLSAType) {
00042             unsigned int lsaCount = 0;
00043 
00044             switch (currentType) {
00045                 case RouterLSAType:
00046                     lsaCount = lsUpdatePacket->getRouterLSAsArraySize();
00047                     break;
00048                 case NetworkLSAType:
00049                     lsaCount = lsUpdatePacket->getNetworkLSAsArraySize();
00050                     break;
00051                 case SummaryLSA_NetworksType:
00052                 case SummaryLSA_ASBoundaryRoutersType:
00053                     lsaCount = lsUpdatePacket->getSummaryLSAsArraySize();
00054                     break;
00055                 case ASExternalLSAType:
00056                     lsaCount = lsUpdatePacket->getAsExternalLSAsArraySize();
00057                     break;
00058                 default: break;
00059             }
00060 
00061             for (unsigned int i = 0; i < lsaCount; i++) {
00062                 OSPFLSA* currentLSA;
00063 
00064                 switch (currentType) {
00065                     case RouterLSAType:
00066                         currentLSA = (&(lsUpdatePacket->getRouterLSAs(i)));
00067                         break;
00068                     case NetworkLSAType:
00069                         currentLSA = (&(lsUpdatePacket->getNetworkLSAs(i)));
00070                         break;
00071                     case SummaryLSA_NetworksType:
00072                     case SummaryLSA_ASBoundaryRoutersType:
00073                         currentLSA = (&(lsUpdatePacket->getSummaryLSAs(i)));
00074                         break;
00075                     case ASExternalLSAType:
00076                         currentLSA = (&(lsUpdatePacket->getAsExternalLSAs(i)));
00077                         break;
00078                     default: break;
00079                 }
00080 
00081                 if (!ValidateLSChecksum(currentLSA)) {
00082                     continue;
00083                 }
00084 
00085                 LSAType lsaType = static_cast<LSAType> (currentLSA->getHeader().getLsType());
00086                 if ((lsaType != RouterLSAType) &&
00087                     (lsaType != NetworkLSAType) &&
00088                     (lsaType != SummaryLSA_NetworksType) &&
00089                     (lsaType != SummaryLSA_ASBoundaryRoutersType) &&
00090                     (lsaType != ASExternalLSAType))
00091                 {
00092                     continue;
00093                 }
00094 
00095                 LSAProcessingMarker marker(currentLSAIndex++);
00096                 EV << "    ";
00097                 PrintLSAHeader(currentLSA->getHeader(), ev.getOStream());
00098                 EV << "\n";
00099 
00100                 if ((lsaType == ASExternalLSAType) && (!area->GetExternalRoutingCapability())) {
00101                     continue;
00102                 }
00103                 AnsaOSPF::LSAKeyType lsaKey;
00104 
00105                 lsaKey.linkStateID = currentLSA->getHeader().getLinkStateID();
00106                 lsaKey.advertisingRouter = currentLSA->getHeader().getAdvertisingRouter().getInt();
00107 
00108                 OSPFLSA*                lsaInDatabase = router->FindLSA(lsaType, lsaKey, areaID);
00109                 unsigned short          lsAge         = currentLSA->getHeader().getLsAge();
00110                 AcknowledgementFlags    ackFlags;
00111 
00112                 ackFlags.floodedBackOut = false;
00113                 ackFlags.lsaIsNewer = false;
00114                 ackFlags.lsaIsDuplicate = false;
00115                 ackFlags.impliedAcknowledgement = false;
00116                 ackFlags.lsaReachedMaxAge = (lsAge == MAX_AGE);
00117                 ackFlags.noLSAInstanceInDatabase = (lsaInDatabase == NULL);
00118                 ackFlags.anyNeighborInExchangeOrLoadingState = router->HasAnyNeighborInStates(AnsaOSPF::Neighbor::ExchangeState | AnsaOSPF::Neighbor::LoadingState);
00119 
00120 
00121                 if ((ackFlags.lsaReachedMaxAge) && (ackFlags.noLSAInstanceInDatabase) && (!ackFlags.anyNeighborInExchangeOrLoadingState)) {
00122                     if (intf->GetType() == AnsaOSPF::Interface::Broadcast) {
00123                         if ((intf->GetState() == AnsaOSPF::Interface::DesignatedRouterState) ||
00124                             (intf->GetState() == AnsaOSPF::Interface::BackupState) ||
00125                             (intf->GetDesignatedRouter() == AnsaOSPF::NullDesignatedRouterID))
00126                         {
00127                             intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOSPF::AllSPFRouters);
00128                         } else {
00129                             intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOSPF::AllDRouters);
00130                         }
00131                     } else {
00132                         if (intf->GetType() == AnsaOSPF::Interface::PointToPoint) {
00133                             intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOSPF::AllSPFRouters);
00134                         } else {
00135                             intf->SendLSAcknowledgement(&(currentLSA->getHeader()), neighbor->GetAddress());
00136                         }
00137                     }
00138                     continue;
00139                 }
00140 
00141                 if (!ackFlags.noLSAInstanceInDatabase) {
00142                     // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
00143                     ackFlags.lsaIsNewer = (lsaInDatabase->getHeader() < currentLSA->getHeader());
00144                     ackFlags.lsaIsDuplicate = (operator== (lsaInDatabase->getHeader(), currentLSA->getHeader()));
00145                 }
00146                 if ((ackFlags.noLSAInstanceInDatabase) || (ackFlags.lsaIsNewer)) {
00147                     LSATrackingInfo* info = (!ackFlags.noLSAInstanceInDatabase) ? dynamic_cast<LSATrackingInfo*> (lsaInDatabase) : NULL;
00148                     if ((!ackFlags.noLSAInstanceInDatabase) &&
00149                         (info != NULL) &&
00150                         (info->GetSource() == LSATrackingInfo::Flooded) &&
00151                         (info->GetInstallTime() < MIN_LS_ARRIVAL))
00152                     {
00153                         //continue;
00154                     }
00155                     ackFlags.floodedBackOut = router->FloodLSA(currentLSA, areaID, intf, neighbor);
00156                     if (!ackFlags.noLSAInstanceInDatabase) {
00157                         AnsaOSPF::LSAKeyType lsaKey;
00158 
00159                         lsaKey.linkStateID = lsaInDatabase->getHeader().getLinkStateID();
00160                         lsaKey.advertisingRouter = lsaInDatabase->getHeader().getAdvertisingRouter().getInt();
00161 
00162                         router->RemoveFromAllRetransmissionLists(lsaKey);
00163                     }
00164                     rebuildRoutingTable |= router->InstallLSA(currentLSA, areaID);
00165 
00166                     EV << "    (update installed)\n";
00167 
00168                     AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID().getInt());
00169                     if ((currentLSA->getHeader().getAdvertisingRouter().getInt() == router->GetRouterID()) ||
00170                         ((lsaType == NetworkLSAType) &&
00171                          (router->IsLocalAddress(IPv4AddressFromULong(currentLSA->getHeader().getLinkStateID())))))
00172                     {
00173                         if (ackFlags.noLSAInstanceInDatabase) {
00174                             currentLSA->getHeader().setLsAge(MAX_AGE);
00175                             router->FloodLSA(currentLSA, areaID);
00176                         } else {
00177                             if (ackFlags.lsaIsNewer) {
00178                                 long sequenceNumber = currentLSA->getHeader().getLsSequenceNumber();
00179                                 if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00180                                     lsaInDatabase->getHeader().setLsAge(MAX_AGE);
00181                                     router->FloodLSA(lsaInDatabase, areaID);
00182                                 } else {
00183                                     lsaInDatabase->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00184                                     router->FloodLSA(lsaInDatabase, areaID);
00185                                 }
00186                             }
00187                         }
00188                     }
00189                     continue;
00190                 }
00191                 if (neighbor->IsLSAOnRequestList(lsaKey)) {
00192                     neighbor->ProcessEvent(AnsaOSPF::Neighbor::BadLinkStateRequest);
00193                     break;
00194                 }
00195                 if (ackFlags.lsaIsDuplicate) {
00196                     if (neighbor->IsLSAOnRetransmissionList(lsaKey)) {
00197                         neighbor->RemoveFromRetransmissionList(lsaKey);
00198                         ackFlags.impliedAcknowledgement = true;
00199                     }
00200                     AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID().getInt());
00201                     continue;
00202                 }
00203                 if ((lsaInDatabase->getHeader().getLsAge() == MAX_AGE) &&
00204                     (lsaInDatabase->getHeader().getLsSequenceNumber() == MAX_SEQUENCE_NUMBER))
00205                 {
00206                     continue;
00207                 }
00208                 if (!neighbor->IsOnTransmittedLSAList(lsaKey)) {
00209                     OSPFLinkStateUpdatePacket* updatePacket = intf->CreateUpdatePacket(lsaInDatabase);
00210                     if (updatePacket != NULL) {
00211                         int ttl = (intf->GetType() == AnsaOSPF::Interface::Virtual) ? VIRTUAL_LINK_TTL : 1;
00212 
00213                         if (intf->GetType() == AnsaOSPF::Interface::Broadcast) {
00214                             if ((intf->GetState() == AnsaOSPF::Interface::DesignatedRouterState) ||
00215                                 (intf->GetState() == AnsaOSPF::Interface::BackupState) ||
00216                                 (intf->GetDesignatedRouter() == AnsaOSPF::NullDesignatedRouterID))
00217                             {
00218                                 router->GetMessageHandler()->SendPacket(updatePacket, AnsaOSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
00219                             } else {
00220                                 router->GetMessageHandler()->SendPacket(updatePacket, AnsaOSPF::AllDRouters, intf->GetIfIndex(), ttl);
00221                             }
00222                         } else {
00223                             if (intf->GetType() == AnsaOSPF::Interface::PointToPoint) {
00224                                 router->GetMessageHandler()->SendPacket(updatePacket, AnsaOSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
00225                             } else {
00226                                 router->GetMessageHandler()->SendPacket(updatePacket, neighbor->GetAddress(), intf->GetIfIndex(), ttl);
00227                             }
00228                         }
00229                     }
00230                 }
00231             }
00232             currentType = static_cast<LSAType> (currentType + 1);
00233             if (currentType == SummaryLSA_NetworksType) {
00234                 currentType = static_cast<LSAType> (currentType + 1);
00235             }
00236         }
00237     }
00238 
00239     if (rebuildRoutingTable) {
00240         router->RebuildRoutingTable();
00241     }
00242 }
00243 
00244 void AnsaOSPF::LinkStateUpdateHandler::AcknowledgeLSA(OSPFLSAHeader& lsaHeader,
00245                                                    AnsaOSPF::Interface* intf,
00246                                                    AnsaOSPF::LinkStateUpdateHandler::AcknowledgementFlags acknowledgementFlags,
00247                                                    AnsaOSPF::RouterID lsaSource)
00248 {
00249     bool sendDirectAcknowledgment = false;
00250 
00251     if (!acknowledgementFlags.floodedBackOut) {
00252         if (intf->GetState() == AnsaOSPF::Interface::BackupState) {
00253             if ((acknowledgementFlags.lsaIsNewer && (lsaSource == intf->GetDesignatedRouter().routerID)) ||
00254                 (acknowledgementFlags.lsaIsDuplicate && acknowledgementFlags.impliedAcknowledgement))
00255             {
00256                 intf->AddDelayedAcknowledgement(lsaHeader);
00257             } else {
00258                 if ((acknowledgementFlags.lsaIsDuplicate && !acknowledgementFlags.impliedAcknowledgement) ||
00259                     (acknowledgementFlags.lsaReachedMaxAge &&
00260                      acknowledgementFlags.noLSAInstanceInDatabase &&
00261                      acknowledgementFlags.anyNeighborInExchangeOrLoadingState))
00262                 {
00263                     sendDirectAcknowledgment = true;
00264                 }
00265             }
00266         } else {
00267             if (acknowledgementFlags.lsaIsNewer) {
00268                 intf->AddDelayedAcknowledgement(lsaHeader);
00269             } else {
00270                 if ((acknowledgementFlags.lsaIsDuplicate && !acknowledgementFlags.impliedAcknowledgement) ||
00271                     (acknowledgementFlags.lsaReachedMaxAge &&
00272                      acknowledgementFlags.noLSAInstanceInDatabase &&
00273                      acknowledgementFlags.anyNeighborInExchangeOrLoadingState))
00274                 {
00275                     sendDirectAcknowledgment = true;
00276                 }
00277             }
00278         }
00279     }
00280 
00281     if (sendDirectAcknowledgment) {
00282         OSPFLinkStateAcknowledgementPacket* ackPacket = new OSPFLinkStateAcknowledgementPacket;
00283 
00284         ackPacket->setType(LinkStateAcknowledgementPacket);
00285         ackPacket->setRouterID(router->GetRouterID());
00286         ackPacket->setAreaID(intf->GetArea()->GetAreaID());
00287         ackPacket->setAuthenticationType(intf->GetAuthenticationType());
00288         AnsaOSPF::AuthenticationKeyType authKey = intf->GetAuthenticationKey();
00289         for (int i = 0; i < 8; i++) {
00290             ackPacket->setAuthentication(i, authKey.bytes[i]);
00291         }
00292 
00293         ackPacket->setLsaHeadersArraySize(1);
00294         ackPacket->setLsaHeaders(0, lsaHeader);
00295 
00296         ackPacket->setPacketLength(0); // TODO: Calculate correct length
00297         ackPacket->setChecksum(0); // TODO: Calculate correct cheksum(16-bit one's complement of the entire packet)
00298 
00299         int ttl = (intf->GetType() == AnsaOSPF::Interface::Virtual) ? VIRTUAL_LINK_TTL : 1;
00300 
00301         if (intf->GetType() == AnsaOSPF::Interface::Broadcast) {
00302             if ((intf->GetState() == AnsaOSPF::Interface::DesignatedRouterState) ||
00303                 (intf->GetState() == AnsaOSPF::Interface::BackupState) ||
00304                 (intf->GetDesignatedRouter() == AnsaOSPF::NullDesignatedRouterID))
00305             {
00306                 router->GetMessageHandler()->SendPacket(ackPacket, AnsaOSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
00307             } else {
00308                 router->GetMessageHandler()->SendPacket(ackPacket, AnsaOSPF::AllDRouters, intf->GetIfIndex(), ttl);
00309             }
00310         } else {
00311             if (intf->GetType() == AnsaOSPF::Interface::PointToPoint) {
00312                 router->GetMessageHandler()->SendPacket(ackPacket, AnsaOSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
00313             } else {
00314                 router->GetMessageHandler()->SendPacket(ackPacket, intf->GetNeighborByID(lsaSource)->GetAddress(), intf->GetIfIndex(), ttl);
00315             }
00316         }
00317     }
00318 }