INET Framework for OMNeT++/OMNEST
ansaHelloHandler6.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 "IPv6ControlInfo.h"
00017 
00018 #include "ansaOspfArea6.h"
00019 #include "ansaOspfInterface6.h"
00020 #include "ansaOspfNeighbor6.h"
00021 #include "ansaOspfRouter6.h"
00022 
00023 #include "ansaHelloHandler6.h"
00024 
00025 AnsaOspf6::HelloHandler::HelloHandler(AnsaOspf6::Router* containingRouter) :
00026       AnsaOspf6::IMessageHandler(containingRouter) {
00027 }
00028 
00029 void AnsaOspf6::HelloHandler::ProcessPacket(OspfPacket6* packet, AnsaOspf6::Interface* intf, AnsaOspf6::Neighbor* unused) {
00030 
00031    OspfHelloPacket6* helloPacket = check_and_cast<OspfHelloPacket6*> (packet);
00032    bool rebuildRoutingTable = false;
00033 
00034    /* The values of the HelloInterval and RouterDeadInterval fields in the received
00035     * Hello packet must be checked against the values configured for the receiving
00036       interface. Any mismatch causes processing to stop and the packet to be dropped.
00037     */
00038    if (intf->GetHelloInterval() != helloPacket->getHelloInterval()){
00039       ev << "Hello interval mismatch" << endl;
00040       return;
00041    }
00042 
00043    if (intf->GetRouterDeadInterval() != helloPacket->getRouterDeadInterval()){
00044       ev << "Router dead interval mismatch" << endl;
00045       return;
00046    }
00047 
00048    AnsaOspf6::Interface::OspfInterfaceType interfaceType = intf->GetType();
00049 
00050    /* The setting of the E-bit found in the Hello Packet's Options field
00051     * must match this area's ExternalRoutingCapability.
00052     */
00053    if (intf->GetArea()->GetExternalRoutingCapability() != helloPacket->getOptions().E_ExternalRoutingCapability){
00054       ev << "External routing capability mismatch" << endl;
00055       return;
00056    }
00057 
00058    IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo *> (helloPacket->getControlInfo());
00059    IPv6Address srcAddress = controlInfo->getSrcAddr();
00060    bool neighborChanged = false;
00061    bool neighborsDRStateChanged = false;
00062    bool backupSeen = false;
00063    AnsaOspf6::Neighbor* neighbor;
00064 
00065    /* On all link types (e.g., broadcast, NBMA, point-to-point, etc.),
00066       neighbors are identified solely by their OSPF Router ID.
00067    */
00068    neighbor = intf->GetNeighborByID(helloPacket->getRouterID());
00069 
00070    // neighbor is known
00071    if (neighbor != NULL){
00072 
00073       router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);
00074 
00075       char newPriority = helloPacket->getRtrPriority();
00076       DesignatedRouterID newDesignatedRouter = helloPacket->getDesignatedRouterID();
00077       DesignatedRouterID newBackupRouter = helloPacket->getBackupDesignatedRouterID();
00078 
00079       if (  (interfaceType == AnsaOspf6::Interface::Virtual)
00080          && (neighbor->GetState() == AnsaOspf6::Neighbor::DownState)){
00081          neighbor->SetPriority(helloPacket->getRtrPriority());
00082          neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());
00083       }
00084 
00085       /* If a change in the neighbor's Router Priority field
00086        was noted, the receiving interface's state machine is
00087        scheduled with the event NeighborChange.
00088        */
00089       if (neighbor->GetPriority() != newPriority){
00090          neighborChanged = true;
00091       }
00092 
00093       /* If the neighbor is both declaring itself to be Designated
00094        Router(Hello Packet's Designated Router field = Neighbor IP
00095        address) and the Backup Designated Router field in the
00096        packet is equal to 0.0.0.0 and the receiving interface is in
00097        state Waiting, the receiving interface's state machine is
00098        scheduled with the event BackupSeen.
00099        */
00100       if (  (newDesignatedRouter == neighbor->GetNeighborID())
00101          && (newBackupRouter == 0)
00102          && (intf->GetState() == AnsaOspf6::Interface::WaitingState)){
00103          backupSeen = true;
00104 
00105       /* Otherwise, if the neighbor is declaring itself to be Designated Router and it
00106        had not previously, or the neighbor is not declaring itself
00107        Designated Router where it had previously, the receiving
00108        interface's state machine is scheduled with the event
00109        NeighborChange.
00110        */
00111       }else if (  (  (newDesignatedRouter == neighbor->GetNeighborID())
00112                   && (newDesignatedRouter != neighbor->GetDesignatedRouter()))
00113                || (  (newDesignatedRouter != neighbor->GetNeighborID())
00114                   && (neighbor->GetNeighborID() == neighbor->GetDesignatedRouter()))){
00115          neighborChanged = true;
00116          neighborsDRStateChanged = true;
00117       }
00118 
00119 
00120       /* If the neighbor is declaring itself to be Backup Designated
00121        Router(Hello Packet's Backup Designated Router field =
00122        Neighbor IP address) and the receiving interface is in state
00123        Waiting, the receiving interface's state machine is
00124        scheduled with the event BackupSeen.
00125        */
00126       if (  (newBackupRouter == neighbor->GetNeighborID())
00127          && (intf->GetState() == AnsaOspf6::Interface::WaitingState)){
00128          backupSeen = true;
00129 
00130       /* Otherwise, if the neighbor is declaring itself to be Backup Designated Router
00131        and it had not previously, or the neighbor is not declaring
00132        itself Backup Designated Router where it had previously, the
00133        receiving interface's state machine is scheduled with the
00134        event NeighborChange.
00135        */
00136       }else if (  (  (newBackupRouter == neighbor->GetNeighborID())
00137                   && (newBackupRouter != neighbor->GetBackupDesignatedRouter()))
00138                || (  (newBackupRouter != neighbor->GetNeighborID())
00139                   && (neighbor->GetNeighborID() == neighbor->GetBackupDesignatedRouter()))){
00140          neighborChanged = true;
00141       }
00142 
00143       neighbor->SetPriority(newPriority);
00144       neighbor->SetAddress(srcAddress);
00145       if (newDesignatedRouter != neighbor->GetDesignatedRouter()){
00146          neighbor->SetDesignatedRouter(newDesignatedRouter);
00147       }
00148 
00149       if (newBackupRouter != neighbor->GetBackupDesignatedRouter()){
00150          neighbor->SetBackupDesignatedRouter(newBackupRouter);
00151       }
00152 
00153 
00154    // neighbor is unknown
00155    }else{
00156       AnsaOspf6::DesignatedRouterID dRouterID;
00157 
00158       neighbor = new AnsaOspf6::Neighbor(helloPacket->getRouterID());
00159       neighbor->SetPriority(helloPacket->getRtrPriority());
00160       neighbor->SetAddress(srcAddress);
00161       neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());
00162 
00163       router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);
00164 
00165       DesignatedRouterID newDesignatedRouter = helloPacket->getDesignatedRouterID();
00166       DesignatedRouterID newBackupRouter = helloPacket->getBackupDesignatedRouterID();
00167 
00168       neighbor->SetDesignatedRouter(newDesignatedRouter);
00169       neighbor->SetBackupDesignatedRouter(newBackupRouter);
00170 
00171       intf->AddNeighbor(neighbor);
00172    }
00173 
00174    neighbor->ProcessEvent(AnsaOspf6::Neighbor::HelloReceived);
00175    if (  (interfaceType == AnsaOspf6::Interface::NBMA)
00176       && (intf->GetRouterPriority() == 0)
00177       && (neighbor->GetState() >= AnsaOspf6::Neighbor::InitState)){
00178       intf->SendHelloPacket(neighbor->GetAddress());
00179    }
00180 
00181    unsigned int neighborsNeighborCount = helloPacket->getNeighborIDArraySize();
00182    unsigned int i;
00183    /* The list of neighbors contained in the Hello Packet is
00184     examined.  If the router itself appears in this list, the
00185     neighbor state machine should be executed with the event TwoWayReceived.
00186     */
00187    for (i = 0; i < neighborsNeighborCount; i++){
00188       if (helloPacket->getNeighborID(i) == router->GetRouterID()){
00189          neighbor->ProcessEvent(AnsaOspf6::Neighbor::TwoWayReceived);
00190          break;
00191       }
00192    }
00193    /* Otherwise, the neighbor state machine should
00194     be executed with the event OneWayReceived, and the processing
00195     of the packet stops.
00196     */
00197    if (i == neighborsNeighborCount){
00198       neighbor->ProcessEvent(AnsaOspf6::Neighbor::OneWayReceived);
00199    }
00200 
00201 
00202    /* In some cases neighbors get stuck in TwoWay state after a DR
00203     or Backup change. (CalculateDesignatedRouter runs before the
00204     neighbors' signal of DR change + this router does not become
00205     neither DR nor backup -> IsAdjacencyOK does not get called.)
00206     So to make it work(workaround) we'll call IsAdjacencyOK for
00207     all neighbors in TwoWay state from here. This shouldn't break
00208     anything because if the neighbor state doesn't have to change
00209     then NeedAdjacency returns false and nothing happnes in
00210     IsAdjacencyOK.
00211     */
00212    if (neighborChanged){
00213       intf->ProcessEvent(AnsaOspf6::Interface::NeighborChange);
00214 
00215       unsigned int neighborCount = intf->GetNeighborCount();
00216       for (i = 0; i < neighborCount; i++){
00217          AnsaOspf6::Neighbor* stuckNeighbor = intf->GetNeighbor(i);
00218          if (stuckNeighbor->GetState() == AnsaOspf6::Neighbor::TwoWayState){
00219             stuckNeighbor->ProcessEvent(AnsaOspf6::Neighbor::IsAdjacencyOK);
00220          }
00221       }
00222 
00223       /* TODO:
00224       if (neighborsDRStateChanged){
00225          AnsaOspf6::RouterLsa* routerLSA = intf->GetArea()->FindRouterLSA(router->GetRouterID());
00226 
00227          if (routerLSA != NULL){
00228             long sequenceNumber = routerLSA->getHeader().getLsSequenceNumber();
00229             if (sequenceNumber == MAX_SEQUENCE_NUMBER){
00230                routerLSA->getHeader().setLsAge(MAX_AGE);
00231                intf->GetArea()->FloodLSA(routerLSA);
00232                routerLSA->IncrementInstallTime();
00233             }else{
00234                AnsaOspf6::RouterLsa *newLSA = intf->GetArea()->OriginateRouterLSA();
00235 
00236                newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00237                rebuildRoutingTable |= routerLSA->Update(newLSA);
00238                delete newLSA;
00239 
00240                intf->GetArea()->FloodLSA(routerLSA);
00241             }
00242          }
00243       }
00244       */
00245    }
00246 
00247    if (backupSeen){
00248       intf->ProcessEvent(AnsaOspf6::Interface::BackupSeen);
00249    }
00250 
00251    if (rebuildRoutingTable){
00252       router->RebuildRoutingTable();
00253    }
00254 }