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