INET Framework for OMNeT++/OMNEST
AnsaOspf6::HelloHandler Class Reference

#include <ansaHelloHandler6.h>

Inheritance diagram for AnsaOspf6::HelloHandler:
AnsaOspf6::IMessageHandler

List of all members.

Public Member Functions

 HelloHandler (Router *containingRouter)
void ProcessPacket (OspfPacket6 *packet, Interface *intf, Neighbor *unused=NULL)

Detailed Description

Definition at line 23 of file ansaHelloHandler6.h.


Constructor & Destructor Documentation

Definition at line 25 of file ansaHelloHandler6.cc.

                                                                     :
      AnsaOspf6::IMessageHandler(containingRouter) {
}

Member Function Documentation

void AnsaOspf6::HelloHandler::ProcessPacket ( OspfPacket6 packet,
AnsaOspf6::Interface intf,
AnsaOspf6::Neighbor unused = NULL 
) [virtual]

Implements AnsaOspf6::IMessageHandler.

Definition at line 29 of file ansaHelloHandler6.cc.

                                                                                                                  {

   OspfHelloPacket6* helloPacket = check_and_cast<OspfHelloPacket6*> (packet);
   bool rebuildRoutingTable = false;

   /* The values of the HelloInterval and RouterDeadInterval fields in the received
    * Hello packet must be checked against the values configured for the receiving
      interface. Any mismatch causes processing to stop and the packet to be dropped.
    */
   if (intf->GetHelloInterval() != helloPacket->getHelloInterval()){
      ev << "Hello interval mismatch" << endl;
      return;
   }

   if (intf->GetRouterDeadInterval() != helloPacket->getRouterDeadInterval()){
      ev << "Router dead interval mismatch" << endl;
      return;
   }

   AnsaOspf6::Interface::OspfInterfaceType interfaceType = intf->GetType();

   /* The setting of the E-bit found in the Hello Packet's Options field
    * must match this area's ExternalRoutingCapability.
    */
   if (intf->GetArea()->GetExternalRoutingCapability() != helloPacket->getOptions().E_ExternalRoutingCapability){
      ev << "External routing capability mismatch" << endl;
      return;
   }

   IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo *> (helloPacket->getControlInfo());
   IPv6Address srcAddress = controlInfo->getSrcAddr();
   bool neighborChanged = false;
   bool neighborsDRStateChanged = false;
   bool backupSeen = false;
   AnsaOspf6::Neighbor* neighbor;

   /* On all link types (e.g., broadcast, NBMA, point-to-point, etc.),
      neighbors are identified solely by their OSPF Router ID.
   */
   neighbor = intf->GetNeighborByID(helloPacket->getRouterID());

   // neighbor is known
   if (neighbor != NULL){

      router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);

      char newPriority = helloPacket->getRtrPriority();
      DesignatedRouterID newDesignatedRouter = helloPacket->getDesignatedRouterID();
      DesignatedRouterID newBackupRouter = helloPacket->getBackupDesignatedRouterID();

      if (  (interfaceType == AnsaOspf6::Interface::Virtual)
         && (neighbor->GetState() == AnsaOspf6::Neighbor::DownState)){
         neighbor->SetPriority(helloPacket->getRtrPriority());
         neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());
      }

      /* If a change in the neighbor's Router Priority field
       was noted, the receiving interface's state machine is
       scheduled with the event NeighborChange.
       */
      if (neighbor->GetPriority() != newPriority){
         neighborChanged = true;
      }

      /* If the neighbor is both declaring itself to be Designated
       Router(Hello Packet's Designated Router field = Neighbor IP
       address) and the Backup Designated Router field in the
       packet is equal to 0.0.0.0 and the receiving interface is in
       state Waiting, the receiving interface's state machine is
       scheduled with the event BackupSeen.
       */
      if (  (newDesignatedRouter == neighbor->GetNeighborID())
         && (newBackupRouter == 0)
         && (intf->GetState() == AnsaOspf6::Interface::WaitingState)){
         backupSeen = true;

      /* Otherwise, if the neighbor is declaring itself to be Designated Router and it
       had not previously, or the neighbor is not declaring itself
       Designated Router where it had previously, the receiving
       interface's state machine is scheduled with the event
       NeighborChange.
       */
      }else if (  (  (newDesignatedRouter == neighbor->GetNeighborID())
                  && (newDesignatedRouter != neighbor->GetDesignatedRouter()))
               || (  (newDesignatedRouter != neighbor->GetNeighborID())
                  && (neighbor->GetNeighborID() == neighbor->GetDesignatedRouter()))){
         neighborChanged = true;
         neighborsDRStateChanged = true;
      }


      /* If the neighbor is declaring itself to be Backup Designated
       Router(Hello Packet's Backup Designated Router field =
       Neighbor IP address) and the receiving interface is in state
       Waiting, the receiving interface's state machine is
       scheduled with the event BackupSeen.
       */
      if (  (newBackupRouter == neighbor->GetNeighborID())
         && (intf->GetState() == AnsaOspf6::Interface::WaitingState)){
         backupSeen = true;

      /* Otherwise, if the neighbor is declaring itself to be Backup Designated Router
       and it had not previously, or the neighbor is not declaring
       itself Backup Designated Router where it had previously, the
       receiving interface's state machine is scheduled with the
       event NeighborChange.
       */
      }else if (  (  (newBackupRouter == neighbor->GetNeighborID())
                  && (newBackupRouter != neighbor->GetBackupDesignatedRouter()))
               || (  (newBackupRouter != neighbor->GetNeighborID())
                  && (neighbor->GetNeighborID() == neighbor->GetBackupDesignatedRouter()))){
         neighborChanged = true;
      }

      neighbor->SetPriority(newPriority);
      neighbor->SetAddress(srcAddress);
      if (newDesignatedRouter != neighbor->GetDesignatedRouter()){
         neighbor->SetDesignatedRouter(newDesignatedRouter);
      }

      if (newBackupRouter != neighbor->GetBackupDesignatedRouter()){
         neighbor->SetBackupDesignatedRouter(newBackupRouter);
      }


   // neighbor is unknown
   }else{
      AnsaOspf6::DesignatedRouterID dRouterID;

      neighbor = new AnsaOspf6::Neighbor(helloPacket->getRouterID());
      neighbor->SetPriority(helloPacket->getRtrPriority());
      neighbor->SetAddress(srcAddress);
      neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());

      router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);

      DesignatedRouterID newDesignatedRouter = helloPacket->getDesignatedRouterID();
      DesignatedRouterID newBackupRouter = helloPacket->getBackupDesignatedRouterID();

      neighbor->SetDesignatedRouter(newDesignatedRouter);
      neighbor->SetBackupDesignatedRouter(newBackupRouter);

      intf->AddNeighbor(neighbor);
   }

   neighbor->ProcessEvent(AnsaOspf6::Neighbor::HelloReceived);
   if (  (interfaceType == AnsaOspf6::Interface::NBMA)
      && (intf->GetRouterPriority() == 0)
      && (neighbor->GetState() >= AnsaOspf6::Neighbor::InitState)){
      intf->SendHelloPacket(neighbor->GetAddress());
   }

   unsigned int neighborsNeighborCount = helloPacket->getNeighborIDArraySize();
   unsigned int i;
   /* The list of neighbors contained in the Hello Packet is
    examined.  If the router itself appears in this list, the
    neighbor state machine should be executed with the event TwoWayReceived.
    */
   for (i = 0; i < neighborsNeighborCount; i++){
      if (helloPacket->getNeighborID(i) == router->GetRouterID()){
         neighbor->ProcessEvent(AnsaOspf6::Neighbor::TwoWayReceived);
         break;
      }
   }
   /* Otherwise, the neighbor state machine should
    be executed with the event OneWayReceived, and the processing
    of the packet stops.
    */
   if (i == neighborsNeighborCount){
      neighbor->ProcessEvent(AnsaOspf6::Neighbor::OneWayReceived);
   }


   /* In some cases neighbors get stuck in TwoWay state after a DR
    or Backup change. (CalculateDesignatedRouter runs before the
    neighbors' signal of DR change + this router does not become
    neither DR nor backup -> IsAdjacencyOK does not get called.)
    So to make it work(workaround) we'll call IsAdjacencyOK for
    all neighbors in TwoWay state from here. This shouldn't break
    anything because if the neighbor state doesn't have to change
    then NeedAdjacency returns false and nothing happnes in
    IsAdjacencyOK.
    */
   if (neighborChanged){
      intf->ProcessEvent(AnsaOspf6::Interface::NeighborChange);

      unsigned int neighborCount = intf->GetNeighborCount();
      for (i = 0; i < neighborCount; i++){
         AnsaOspf6::Neighbor* stuckNeighbor = intf->GetNeighbor(i);
         if (stuckNeighbor->GetState() == AnsaOspf6::Neighbor::TwoWayState){
            stuckNeighbor->ProcessEvent(AnsaOspf6::Neighbor::IsAdjacencyOK);
         }
      }

      /* TODO:
      if (neighborsDRStateChanged){
         AnsaOspf6::RouterLsa* routerLSA = intf->GetArea()->FindRouterLSA(router->GetRouterID());

         if (routerLSA != NULL){
            long sequenceNumber = routerLSA->getHeader().getLsSequenceNumber();
            if (sequenceNumber == MAX_SEQUENCE_NUMBER){
               routerLSA->getHeader().setLsAge(MAX_AGE);
               intf->GetArea()->FloodLSA(routerLSA);
               routerLSA->IncrementInstallTime();
            }else{
               AnsaOspf6::RouterLsa *newLSA = intf->GetArea()->OriginateRouterLSA();

               newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
               rebuildRoutingTable |= routerLSA->Update(newLSA);
               delete newLSA;

               intf->GetArea()->FloodLSA(routerLSA);
            }
         }
      }
      */
   }

   if (backupSeen){
      intf->ProcessEvent(AnsaOspf6::Interface::BackupSeen);
   }

   if (rebuildRoutingTable){
      router->RebuildRoutingTable();
   }
}

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