LinkStateUpdateHandler.cc

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