Public Member Functions | Private Member Functions

OSPF::DatabaseDescriptionHandler Class Reference

#include <DatabaseDescriptionHandler.h>

Inheritance diagram for OSPF::DatabaseDescriptionHandler:
OSPF::IMessageHandler

List of all members.

Public Member Functions

 DatabaseDescriptionHandler (Router *containingRouter)
void ProcessPacket (OSPFPacket *packet, Interface *intf, Neighbor *neighbor)

Private Member Functions

bool ProcessDDPacket (OSPFDatabaseDescriptionPacket *ddPacket, Interface *intf, Neighbor *neighbor, bool inExchangeStart)

Detailed Description

Definition at line 25 of file DatabaseDescriptionHandler.h.


Constructor & Destructor Documentation

OSPF::DatabaseDescriptionHandler::DatabaseDescriptionHandler ( OSPF::Router containingRouter  ) 

Definition at line 24 of file DatabaseDescriptionHandler.cc.

                                                                                       :
    OSPF::IMessageHandler(containingRouter)
{
}


Member Function Documentation

bool OSPF::DatabaseDescriptionHandler::ProcessDDPacket ( OSPFDatabaseDescriptionPacket *  ddPacket,
OSPF::Interface intf,
OSPF::Neighbor neighbor,
bool  inExchangeStart 
) [private]

Definition at line 178 of file DatabaseDescriptionHandler.cc.

Referenced by ProcessPacket().

{
    EV << "  Processing packet contents(ddOptions="
       << ((ddPacket->getDdOptions().I_Init) ? "I " : "_ ")
       << ((ddPacket->getDdOptions().M_More) ? "M " : "_ ")
       << ((ddPacket->getDdOptions().MS_MasterSlave) ? "MS" : "__")
       << "; seqNumber="
       << ddPacket->getDdSequenceNumber()
       << "):\n";

    unsigned int headerCount = ddPacket->getLsaHeadersArraySize();

    for (unsigned int i = 0; i < headerCount; i++) {
        OSPFLSAHeader& currentHeader = ddPacket->getLsaHeaders(i);
        LSAType        lsaType       = static_cast<LSAType> (currentHeader.getLsType());

        EV << "    ";
        PrintLSAHeader(currentHeader, ev.getOStream());

        if ((lsaType < RouterLSAType) || (lsaType > ASExternalLSAType) ||
            ((lsaType == ASExternalLSAType) && (!intf->GetArea()->GetExternalRoutingCapability())))
        {
            EV << " Error!\n";
            neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
            return false;
        } else {
            OSPF::LSAKeyType lsaKey;

            lsaKey.linkStateID = currentHeader.getLinkStateID();
            lsaKey.advertisingRouter = currentHeader.getAdvertisingRouter().getInt();

            OSPFLSA* lsaInDatabase = router->FindLSA(lsaType, lsaKey, intf->GetArea()->GetAreaID());

            // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
            if ((lsaInDatabase == NULL) || (lsaInDatabase->getHeader() < currentHeader)) {
                EV << " (newer)";
                neighbor->AddToRequestList(&currentHeader);
            }
        }
        EV << "\n";
    }

    if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Master) {
        neighbor->IncrementDDSequenceNumber();
        if ((neighbor->GetDatabaseSummaryListCount() == 0) && !ddPacket->getDdOptions().M_More) {
            neighbor->ProcessEvent(OSPF::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
        } else {
            if (!inExchangeStart) {
                neighbor->SendDatabaseDescriptionPacket();
            }
        }
    } else {
        neighbor->SetDDSequenceNumber(ddPacket->getDdSequenceNumber());
        if (!inExchangeStart) {
            neighbor->SendDatabaseDescriptionPacket();
        }
        if (!ddPacket->getDdOptions().M_More &&
            (neighbor->GetDatabaseSummaryListCount() == 0))
        {
            neighbor->ProcessEvent(OSPF::Neighbor::ExchangeDone);  // does nothing in ExchangeStart
        }
    }
    return true;
}

void OSPF::DatabaseDescriptionHandler::ProcessPacket ( OSPFPacket *  packet,
OSPF::Interface intf,
OSPF::Neighbor neighbor 
) [virtual]

Implements OSPF::IMessageHandler.

Definition at line 29 of file DatabaseDescriptionHandler.cc.

Referenced by OSPF::MessageHandler::ProcessPacket().

{
    router->GetMessageHandler()->PrintEvent("Database Description packet received", intf, neighbor);

    OSPFDatabaseDescriptionPacket* ddPacket = check_and_cast<OSPFDatabaseDescriptionPacket*> (packet);

    OSPF::Neighbor::NeighborStateType neighborState = neighbor->GetState();

    if ((ddPacket->getInterfaceMTU() <= intf->GetMTU()) &&
        (neighborState > OSPF::Neighbor::AttemptState))
    {
        switch (neighborState) {
            case OSPF::Neighbor::TwoWayState:
                break;
            case OSPF::Neighbor::InitState:
                neighbor->ProcessEvent(OSPF::Neighbor::TwoWayReceived);
                break;
            case OSPF::Neighbor::ExchangeStartState:
                {
                    OSPFDDOptions& ddOptions = ddPacket->getDdOptions();

                    if (ddOptions.I_Init && ddOptions.M_More && ddOptions.MS_MasterSlave &&
                        (ddPacket->getLsaHeadersArraySize() == 0))
                    {
                        if (neighbor->GetNeighborID() > router->GetRouterID()) {
                            OSPF::Neighbor::DDPacketID packetID;
                            packetID.ddOptions      = ddOptions;
                            packetID.options        = ddPacket->getOptions();
                            packetID.sequenceNumber = ddPacket->getDdSequenceNumber();

                            neighbor->SetOptions(packetID.options);
                            neighbor->SetDatabaseExchangeRelationship(OSPF::Neighbor::Slave);
                            neighbor->SetDDSequenceNumber(packetID.sequenceNumber);
                            neighbor->SetLastReceivedDDPacket(packetID);

                            if (!ProcessDDPacket(ddPacket, intf, neighbor, true)) {
                                break;
                            }

                            neighbor->ProcessEvent(OSPF::Neighbor::NegotiationDone);
                            if (!neighbor->IsLinkStateRequestListEmpty() &&
                                !neighbor->IsRequestRetransmissionTimerActive())
                            {
                                neighbor->SendLinkStateRequestPacket();
                                neighbor->ClearRequestRetransmissionTimer();
                                neighbor->StartRequestRetransmissionTimer();
                            }
                        } else {
                            neighbor->SendDatabaseDescriptionPacket(true);
                        }
                    }
                    if (!ddOptions.I_Init && !ddOptions.MS_MasterSlave &&
                        (ddPacket->getDdSequenceNumber() == neighbor->GetDDSequenceNumber()) &&
                        (neighbor->GetNeighborID() < router->GetRouterID()))
                    {
                        OSPF::Neighbor::DDPacketID packetID;
                        packetID.ddOptions      = ddOptions;
                        packetID.options        = ddPacket->getOptions();
                        packetID.sequenceNumber = ddPacket->getDdSequenceNumber();

                        neighbor->SetOptions(packetID.options);
                        neighbor->SetDatabaseExchangeRelationship(OSPF::Neighbor::Master);
                        neighbor->SetLastReceivedDDPacket(packetID);

                        if (!ProcessDDPacket(ddPacket, intf, neighbor, true)) {
                            break;
                        }

                        neighbor->ProcessEvent(OSPF::Neighbor::NegotiationDone);
                        if (!neighbor->IsLinkStateRequestListEmpty() &&
                            !neighbor->IsRequestRetransmissionTimerActive())
                        {
                            neighbor->SendLinkStateRequestPacket();
                            neighbor->ClearRequestRetransmissionTimer();
                            neighbor->StartRequestRetransmissionTimer();
                        }
                    }
                }
                break;
            case OSPF::Neighbor::ExchangeState:
                {
                    OSPF::Neighbor::DDPacketID packetID;
                    packetID.ddOptions      = ddPacket->getDdOptions();
                    packetID.options        = ddPacket->getOptions();
                    packetID.sequenceNumber = ddPacket->getDdSequenceNumber();

                    if (packetID != neighbor->GetLastReceivedDDPacket()) {
                        if ((packetID.ddOptions.MS_MasterSlave &&
                             (neighbor->GetDatabaseExchangeRelationship() != OSPF::Neighbor::Slave)) ||
                            (!packetID.ddOptions.MS_MasterSlave &&
                             (neighbor->GetDatabaseExchangeRelationship() != OSPF::Neighbor::Master)) ||
                            packetID.ddOptions.I_Init ||
                            (packetID.options != neighbor->GetLastReceivedDDPacket().options))
                        {
                            neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
                        } else {
                            if (((neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Master) &&
                                 (packetID.sequenceNumber == neighbor->GetDDSequenceNumber())) ||
                                ((neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) &&
                                 (packetID.sequenceNumber == (neighbor->GetDDSequenceNumber() + 1))))
                            {
                                neighbor->SetLastReceivedDDPacket(packetID);
                                if (!ProcessDDPacket(ddPacket, intf, neighbor, false)) {
                                    break;
                                }
                                if (!neighbor->IsLinkStateRequestListEmpty() &&
                                    !neighbor->IsRequestRetransmissionTimerActive())
                                {
                                    neighbor->SendLinkStateRequestPacket();
                                    neighbor->ClearRequestRetransmissionTimer();
                                    neighbor->StartRequestRetransmissionTimer();
                                }
                            } else {
                                neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
                            }
                        }
                    } else {
                        if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) {
                            neighbor->RetransmitDatabaseDescriptionPacket();
                        }
                    }
                }
                break;
            case OSPF::Neighbor::LoadingState:
            case OSPF::Neighbor::FullState:
                {
                    OSPF::Neighbor::DDPacketID packetID;
                    packetID.ddOptions      = ddPacket->getDdOptions();
                    packetID.options        = ddPacket->getOptions();
                    packetID.sequenceNumber = ddPacket->getDdSequenceNumber();

                    if ((packetID != neighbor->GetLastReceivedDDPacket()) ||
                        (packetID.ddOptions.I_Init))
                    {
                        neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
                    } else {
                        if (neighbor->GetDatabaseExchangeRelationship() == OSPF::Neighbor::Slave) {
                            if (!neighbor->RetransmitDatabaseDescriptionPacket()) {
                                neighbor->ProcessEvent(OSPF::Neighbor::SequenceNumberMismatch);
                            }
                        }
                    }
                }
                break;
            default: break;
        }
    }
}


The documentation for this class was generated from the following files: