INET Framework for OMNeT++/OMNEST
ansaDatabaseDescriptionHandler6.cc
Go to the documentation of this file.
00001 //
00002 // This program is free software: you can redistribute it and/or modify
00003 // it under the terms of the GNU Lesser General Public License as published by
00004 // the Free Software Foundation, either version 3 of the License, or
00005 // (at your option) any later version.
00006 // 
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU Lesser General Public License for more details.
00011 // 
00012 // You should have received a copy of the GNU Lesser General Public License
00013 // along with this program.  If not, see http://www.gnu.org/licenses/.
00014 // 
00015 
00016 #include "ansaOspfArea6.h"
00017 #include "ansaOspfInterface6.h"
00018 #include "ansaLsa6.h"
00019 #include "ansaOspfNeighbor6.h"
00020 #include "ansaOspfRouter6.h"
00021 
00022 #include "ansaDatabaseDescriptionHandler6.h"
00023 
00024 AnsaOspf6::DatabaseDescriptionHandler::DatabaseDescriptionHandler(AnsaOspf6::Router* containingRouter) :
00025       AnsaOspf6::IMessageHandler(containingRouter) {
00026 }
00027 
00028 void AnsaOspf6::DatabaseDescriptionHandler::ProcessPacket(OspfPacket6* packet, AnsaOspf6::Interface* intf, AnsaOspf6::Neighbor* neighbor) {
00029 
00030    router->GetMessageHandler()->PrintEvent("Database Description packet received", intf, neighbor);
00031 
00032    OspfDatabaseDescriptionPacket6* ddPacket = check_and_cast<OspfDatabaseDescriptionPacket6*> (packet);
00033 
00034    AnsaOspf6::Neighbor::NeighborStateType neighborState = neighbor->GetState();
00035 
00036    if ((ddPacket->getInterfaceMtu() <= intf->GetMtu()) && (neighborState > AnsaOspf6::Neighbor::AttemptState)){
00037 
00038       switch (neighborState){
00039 
00040          case AnsaOspf6::Neighbor::TwoWayState:
00041             break;
00042 
00043          case AnsaOspf6::Neighbor::InitState:
00044             neighbor->ProcessEvent(AnsaOspf6::Neighbor::TwoWayReceived);
00045             break;
00046 
00047          case AnsaOspf6::Neighbor::ExchangeStartState: {
00048             OspfDdOptions6& ddOptions = ddPacket->getDdOptions();
00049 
00050             if (  ddOptions.I_Init
00051                && ddOptions.M_More
00052                && ddOptions.MS_MasterSlave
00053                && (ddPacket->getLsaHeadersArraySize() == 0)){
00054 
00055                if (neighbor->GetNeighborID() > router->GetRouterID()){
00056                   AnsaOspf6::Neighbor::DDPacketID packetID;
00057                   packetID.ddOptions = ddOptions;
00058                   packetID.options = ddPacket->getOptions();
00059                   packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00060 
00061                   neighbor->SetOptions(packetID.options);
00062                   neighbor->SetDatabaseExchangeRelationship(AnsaOspf6::Neighbor::Slave);
00063                   neighbor->SetDDSequenceNumber(packetID.sequenceNumber);
00064                   neighbor->SetLastReceivedDDPacket(packetID);
00065 
00066                   if (!ProcessDDPacket(ddPacket, intf, neighbor, true)){
00067                      break;
00068                   }
00069 
00070                   neighbor->ProcessEvent(AnsaOspf6::Neighbor::NegotiationDone);
00071                   if (!neighbor->IsLinkStateRequestListEmpty()
00072                         && !neighbor->IsRequestRetransmissionTimerActive()){
00073                      neighbor->SendLinkStateRequestPacket();
00074                      neighbor->ClearRequestRetransmissionTimer();
00075                      neighbor->StartRequestRetransmissionTimer();
00076                   }
00077                }else{
00078                   neighbor->SendDatabaseDescriptionPacket(true);
00079                }
00080             }
00081             if (  !ddOptions.I_Init
00082                && !ddOptions.MS_MasterSlave
00083                && (ddPacket->getDdSequenceNumber() == neighbor->GetDDSequenceNumber())
00084                && (neighbor->GetNeighborID() < router->GetRouterID())){
00085 
00086                AnsaOspf6::Neighbor::DDPacketID packetID;
00087                packetID.ddOptions = ddOptions;
00088                packetID.options = ddPacket->getOptions();
00089                packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00090 
00091                neighbor->SetOptions(packetID.options);
00092                neighbor->SetDatabaseExchangeRelationship(AnsaOspf6::Neighbor::Master);
00093                neighbor->SetLastReceivedDDPacket(packetID);
00094 
00095                if (!ProcessDDPacket(ddPacket, intf, neighbor, true)){
00096                   break;
00097                }
00098 
00099                neighbor->ProcessEvent(AnsaOspf6::Neighbor::NegotiationDone);
00100                if (  !neighbor->IsLinkStateRequestListEmpty()
00101                   && !neighbor->IsRequestRetransmissionTimerActive()){
00102 
00103                   neighbor->SendLinkStateRequestPacket();
00104                   neighbor->ClearRequestRetransmissionTimer();
00105                   neighbor->StartRequestRetransmissionTimer();
00106                }
00107             }}
00108             break;
00109 
00110          case AnsaOspf6::Neighbor::ExchangeState: {
00111             AnsaOspf6::Neighbor::DDPacketID packetID;
00112             packetID.ddOptions = ddPacket->getDdOptions();
00113             packetID.options = ddPacket->getOptions();
00114             packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00115 
00116             if (packetID != neighbor->GetLastReceivedDDPacket()){
00117                if (  (packetID.ddOptions.MS_MasterSlave
00118                         && (neighbor->GetDatabaseExchangeRelationship() != AnsaOspf6::Neighbor::Slave))
00119                      || (!packetID.ddOptions.MS_MasterSlave
00120                         && (neighbor->GetDatabaseExchangeRelationship() != AnsaOspf6::Neighbor::Master))
00121                      || packetID.ddOptions.I_Init
00122                      || (packetID.options != neighbor->GetLastReceivedDDPacket().options)){
00123 
00124                   neighbor->ProcessEvent(AnsaOspf6::Neighbor::SequenceNumberMismatch);
00125 
00126                }else{
00127                   if (  ((neighbor->GetDatabaseExchangeRelationship() == AnsaOspf6::Neighbor::Master)
00128                            && (packetID.sequenceNumber == neighbor->GetDDSequenceNumber()))
00129                         || ((neighbor->GetDatabaseExchangeRelationship() == AnsaOspf6::Neighbor::Slave)
00130                               && (packetID.sequenceNumber == (neighbor->GetDDSequenceNumber() + 1)))){
00131 
00132                      neighbor->SetLastReceivedDDPacket(packetID);
00133 
00134                      if (!ProcessDDPacket(ddPacket, intf, neighbor, false)){
00135                         break;
00136                      }
00137 
00138                      if (  !neighbor->IsLinkStateRequestListEmpty()
00139                            && !neighbor->IsRequestRetransmissionTimerActive()){
00140 
00141                         neighbor->SendLinkStateRequestPacket();
00142                         neighbor->ClearRequestRetransmissionTimer();
00143                         neighbor->StartRequestRetransmissionTimer();
00144                      }
00145 
00146                   }else{
00147                      neighbor->ProcessEvent(AnsaOspf6::Neighbor::SequenceNumberMismatch);
00148                   }
00149                }
00150             }else{
00151                if (neighbor->GetDatabaseExchangeRelationship() == AnsaOspf6::Neighbor::Slave){
00152                   neighbor->RetransmitDatabaseDescriptionPacket();
00153                }
00154             }}
00155             break;
00156 
00157 
00158          case AnsaOspf6::Neighbor::LoadingState:
00159          case AnsaOspf6::Neighbor::FullState: {
00160             AnsaOspf6::Neighbor::DDPacketID packetID;
00161             packetID.ddOptions = ddPacket->getDdOptions();
00162             packetID.options = ddPacket->getOptions();
00163             packetID.sequenceNumber = ddPacket->getDdSequenceNumber();
00164 
00165             if (  (packetID != neighbor->GetLastReceivedDDPacket())
00166                   || (packetID.ddOptions.I_Init)){
00167                neighbor->ProcessEvent(AnsaOspf6::Neighbor::SequenceNumberMismatch);
00168             }else{
00169                if (neighbor->GetDatabaseExchangeRelationship() == AnsaOspf6::Neighbor::Slave){
00170                   if (!neighbor->RetransmitDatabaseDescriptionPacket()){
00171                      neighbor->ProcessEvent(AnsaOspf6::Neighbor::SequenceNumberMismatch);
00172                   }
00173                }
00174             }}
00175             break;
00176          default:
00177             break;
00178       }
00179    }
00180 }
00181 
00182 bool AnsaOspf6::DatabaseDescriptionHandler::ProcessDDPacket(
00183       OspfDatabaseDescriptionPacket6* ddPacket,
00184       AnsaOspf6::Interface* intf,
00185       AnsaOspf6::Neighbor* neighbor,
00186       bool inExchangeStart) {
00187 
00188    EV << "  Processing packet contents(ddOptions="
00189    << ((ddPacket->getDdOptions().I_Init) ? "I " : "_ ")
00190    << ((ddPacket->getDdOptions().M_More) ? "M " : "_ ")
00191    << ((ddPacket->getDdOptions().MS_MasterSlave) ? "MS" : "__")
00192    << "; seqNumber="
00193    << ddPacket->getDdSequenceNumber()
00194    << "):\n";
00195 
00196    unsigned int headerCount = ddPacket->getLsaHeadersArraySize();
00197 
00198    for (unsigned int i = 0; i < headerCount; i++){
00199       OspfLsaHeader6& currentHeader = ddPacket->getLsaHeaders(i);
00200       LsaType6 lsaType = static_cast<LsaType6> (currentHeader.getLsType());
00201 
00202       EV << "    ";
00203       PrintLsaHeader6(currentHeader, ev.getOStream());
00204 
00205       if ((lsaType < RouterLsaType) || (lsaType > AsExternalLsaType)
00206             || ((lsaType == AsExternalLsaType) && (!intf->GetArea()->GetExternalRoutingCapability()))){
00207 
00208          EV << " Error!\n";
00209          neighbor->ProcessEvent(AnsaOspf6::Neighbor::SequenceNumberMismatch);
00210          return false;
00211       }else{
00212          AnsaOspf6::LsaKeyType6 lsaKey;
00213 
00214          lsaKey.linkStateID = currentHeader.getLinkStateID();
00215          lsaKey.advertisingRouter = currentHeader.getAdvertisingRouter();
00216 
00217          OspfLsa6* lsaInDatabase = router->FindLSA(lsaType, lsaKey, intf->GetArea()->GetAreaID());
00218 
00219          // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
00220          if ((lsaInDatabase == NULL) || (lsaInDatabase->getHeader() < currentHeader)){
00221             EV << " (newer)";
00222             neighbor->AddToRequestList(&currentHeader);
00223          }
00224       }
00225       EV << "\n";
00226    }
00227 
00228    if (neighbor->GetDatabaseExchangeRelationship() == AnsaOspf6::Neighbor::Master){
00229       neighbor->IncrementDDSequenceNumber();
00230       if ((neighbor->GetDatabaseSummaryListCount() == 0) && !ddPacket->getDdOptions().M_More){
00231          neighbor->ProcessEvent(AnsaOspf6::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
00232       }else{
00233          if (!inExchangeStart){
00234             neighbor->SendDatabaseDescriptionPacket();
00235          }
00236       }
00237    }else{
00238       neighbor->SetDDSequenceNumber(ddPacket->getDdSequenceNumber());
00239       if (!inExchangeStart) {
00240          neighbor->SendDatabaseDescriptionPacket();
00241       }
00242       if (!ddPacket->getDdOptions().M_More && (neighbor->GetDatabaseSummaryListCount() == 0)){
00243          neighbor->ProcessEvent(AnsaOspf6::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
00244       }
00245    }
00246    return true;
00247 }