DatabaseDescriptionHandler.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 "DatabaseDescriptionHandler.h"
00019 #include "OSPFNeighbor.h"
00020 #include "OSPFInterface.h"
00021 #include "OSPFRouter.h"
00022 #include "OSPFArea.h"
00023 
00024 OSPF::DatabaseDescriptionHandler::DatabaseDescriptionHandler(OSPF::Router* containingRouter) :
00025     OSPF::IMessageHandler(containingRouter)
00026 {
00027 }
00028 
00029 void OSPF::DatabaseDescriptionHandler::ProcessPacket(OSPFPacket* packet, OSPF::Interface* intf, OSPF::Neighbor* neighbor)
00030 {
00031     router->GetMessageHandler()->PrintEvent("Database Description packet received", intf, neighbor);
00032 
00033     OSPFDatabaseDescriptionPacket* ddPacket = check_and_cast<OSPFDatabaseDescriptionPacket*> (packet);
00034 
00035     OSPF::Neighbor::NeighborStateType neighborState = neighbor->GetState();
00036 
00037     if ((ddPacket->getInterfaceMTU() <= intf->GetMTU()) &&
00038         (neighborState > OSPF::Neighbor::AttemptState))
00039     {
00040         switch (neighborState) {
00041             case OSPF::Neighbor::TwoWayState:
00042                 break;
00043             case OSPF::Neighbor::InitState:
00044                 neighbor->ProcessEvent(OSPF::Neighbor::TwoWayReceived);
00045                 break;
00046             case OSPF::Neighbor::ExchangeStartState:
00047                 {
00048                     OSPFDDOptions& ddOptions = ddPacket->getDdOptions();
00049 
00050                     if (ddOptions.I_Init && ddOptions.M_More && ddOptions.MS_MasterSlave &&
00051                         (ddPacket->getLsaHeadersArraySize() == 0))
00052                     {
00053                         if (neighbor->GetNeighborID() > router->GetRouterID()) {
00054                             OSPF::Neighbor::DDPacketID packetID;
00055                             packetID.ddOptions      = ddOptions;
00056                             packetID.options        = ddPacket->getOptions();
00057                             packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00058 
00059                             neighbor->SetOptions(packetID.options);
00060                             neighbor->SetDatabaseExchangeRelationship(OSPF::Neighbor::Slave);
00061                             neighbor->SetDDSequenceNumber(packetID.sequenceNumber);
00062                             neighbor->SetLastReceivedDDPacket(packetID);
00063 
00064                             if (!ProcessDDPacket(ddPacket, intf, neighbor, true)) {
00065                                 break;
00066                             }
00067 
00068                             neighbor->ProcessEvent(OSPF::Neighbor::NegotiationDone);
00069                             if (!neighbor->IsLinkStateRequestListEmpty() &&
00070                                 !neighbor->IsRequestRetransmissionTimerActive())
00071                             {
00072                                 neighbor->SendLinkStateRequestPacket();
00073                                 neighbor->ClearRequestRetransmissionTimer();
00074                                 neighbor->StartRequestRetransmissionTimer();
00075                             }
00076                         } else {
00077                             neighbor->SendDatabaseDescriptionPacket(true);
00078                         }
00079                     }
00080                     if (!ddOptions.I_Init && !ddOptions.MS_MasterSlave &&
00081                         (ddPacket->getDdSequenceNumber() == neighbor->GetDDSequenceNumber()) &&
00082                         (neighbor->GetNeighborID() < router->GetRouterID()))
00083                     {
00084                         OSPF::Neighbor::DDPacketID packetID;
00085                         packetID.ddOptions      = ddOptions;
00086                         packetID.options        = ddPacket->getOptions();
00087                         packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00088 
00089                         neighbor->SetOptions(packetID.options);
00090                         neighbor->SetDatabaseExchangeRelationship(OSPF::Neighbor::Master);
00091                         neighbor->SetLastReceivedDDPacket(packetID);
00092 
00093                         if (!ProcessDDPacket(ddPacket, intf, neighbor, true)) {
00094                             break;
00095                         }
00096 
00097                         neighbor->ProcessEvent(OSPF::Neighbor::NegotiationDone);
00098                         if (!neighbor->IsLinkStateRequestListEmpty() &&
00099                             !neighbor->IsRequestRetransmissionTimerActive())
00100                         {
00101                             neighbor->SendLinkStateRequestPacket();
00102                             neighbor->ClearRequestRetransmissionTimer();
00103                             neighbor->StartRequestRetransmissionTimer();
00104                         }
00105                     }
00106                 }
00107                 break;
00108             case OSPF::Neighbor::ExchangeState:
00109                 {
00110                     OSPF::Neighbor::DDPacketID packetID;
00111                     packetID.ddOptions      = ddPacket->getDdOptions();
00112                     packetID.options        = ddPacket->getOptions();
00113                     packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00114 
00115                     if (packetID != neighbor->GetLastReceivedDDPacket()) {
00116                         if ((packetID.ddOptions.MS_MasterSlave &&
00117                              (neighbor->GetDatabaseExchangeRelationship() != OSPF::Neighbor::Slave)) ||
00118                             (!packetID.ddOptions.MS_MasterSlave &&
00119                              (neighbor->GetDatabaseExchangeRelationship() != OSPF::Neighbor::Master)) ||
00120                             packetID.ddOptions.I_Init ||
00121                             (packetID.options != neighbor->GetLastReceivedDDPacket().options))
00122                         {
00123                             neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
00124                         } else {
00125                             if (((neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Master) &&
00126                                  (packetID.sequenceNumber == neighbor->GetDDSequenceNumber())) ||
00127                                 ((neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) &&
00128                                  (packetID.sequenceNumber == (neighbor->GetDDSequenceNumber() + 1))))
00129                             {
00130                                 neighbor->SetLastReceivedDDPacket(packetID);
00131                                 if (!ProcessDDPacket(ddPacket, intf, neighbor, false)) {
00132                                     break;
00133                                 }
00134                                 if (!neighbor->IsLinkStateRequestListEmpty() &&
00135                                     !neighbor->IsRequestRetransmissionTimerActive())
00136                                 {
00137                                     neighbor->SendLinkStateRequestPacket();
00138                                     neighbor->ClearRequestRetransmissionTimer();
00139                                     neighbor->StartRequestRetransmissionTimer();
00140                                 }
00141                             } else {
00142                                 neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
00143                             }
00144                         }
00145                     } else {
00146                         if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) {
00147                             neighbor->RetransmitDatabaseDescriptionPacket();
00148                         }
00149                     }
00150                 }
00151                 break;
00152             case OSPF::Neighbor::LoadingState:
00153             case OSPF::Neighbor::FullState:
00154                 {
00155                     OSPF::Neighbor::DDPacketID packetID;
00156                     packetID.ddOptions      = ddPacket->getDdOptions();
00157                     packetID.options        = ddPacket->getOptions();
00158                     packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00159 
00160                     if ((packetID != neighbor->GetLastReceivedDDPacket()) ||
00161                         (packetID.ddOptions.I_Init))
00162                     {
00163                         neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
00164                     } else {
00165                         if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) {
00166                             if (!neighbor->RetransmitDatabaseDescriptionPacket()) {
00167                                 neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
00168                             }
00169                         }
00170                     }
00171                 }
00172                 break;
00173             default: break;
00174         }
00175     }
00176 }
00177 
00178 bool OSPF::DatabaseDescriptionHandler::ProcessDDPacket(OSPFDatabaseDescriptionPacket* ddPacket, OSPF::Interface* intf, OSPF::Neighbor* neighbor, bool inExchangeStart)
00179 {
00180     EV << "  Processing packet contents(ddOptions="
00181        << ((ddPacket->getDdOptions().I_Init) ? "I " : "_ ")
00182        << ((ddPacket->getDdOptions().M_More) ? "M " : "_ ")
00183        << ((ddPacket->getDdOptions().MS_MasterSlave) ? "MS" : "__")
00184        << "; seqNumber="
00185        << ddPacket->getDdSequenceNumber()
00186        << "):\n";
00187 
00188     unsigned int headerCount = ddPacket->getLsaHeadersArraySize();
00189 
00190     for (unsigned int i = 0; i < headerCount; i++) {
00191         OSPFLSAHeader& currentHeader = ddPacket->getLsaHeaders(i);
00192         LSAType        lsaType       = static_cast<LSAType> (currentHeader.getLsType());
00193 
00194         EV << "    ";
00195         PrintLSAHeader(currentHeader, ev.getOStream());
00196 
00197         if ((lsaType < RouterLSAType) || (lsaType > ASExternalLSAType) ||
00198             ((lsaType == ASExternalLSAType) && (!intf->GetArea()->GetExternalRoutingCapability())))
00199         {
00200             EV << " Error!\n";
00201             neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
00202             return false;
00203         } else {
00204             OSPF::LSAKeyType lsaKey;
00205 
00206             lsaKey.linkStateID = currentHeader.getLinkStateID();
00207             lsaKey.advertisingRouter = currentHeader.getAdvertisingRouter().getInt();
00208 
00209             OSPFLSA* lsaInDatabase = router->FindLSA(lsaType, lsaKey, intf->GetArea()->GetAreaID());
00210 
00211             // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
00212             if ((lsaInDatabase == NULL) || (lsaInDatabase->getHeader() < currentHeader)) {
00213                 EV << " (newer)";
00214                 neighbor->AddToRequestList(&currentHeader);
00215             }
00216         }
00217         EV << "\n";
00218     }
00219 
00220     if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Master) {
00221         neighbor->IncrementDDSequenceNumber();
00222         if ((neighbor->GetDatabaseSummaryListCount() == 0) && !ddPacket->getDdOptions().M_More) {
00223             neighbor->ProcessEvent(OSPF::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
00224         } else {
00225             if (!inExchangeStart) {
00226                 neighbor->SendDatabaseDescriptionPacket();
00227             }
00228         }
00229     } else {
00230         neighbor->SetDDSequenceNumber(ddPacket->getDdSequenceNumber());
00231         if (!inExchangeStart) {
00232             neighbor->SendDatabaseDescriptionPacket();
00233         }
00234         if (!ddPacket->getDdOptions().M_More &&
00235             (neighbor->GetDatabaseSummaryListCount() == 0))
00236         {
00237             neighbor->ProcessEvent(OSPF::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
00238         }
00239     }
00240     return true;
00241 }