HelloHandler.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Andras Babos and Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include "HelloHandler.h"
00019 #include "IPControlInfo.h"
00020 #include "OSPFRouter.h"
00021 #include "OSPFArea.h"
00022 #include "OSPFInterface.h"
00023 #include "OSPFNeighbor.h"
00024 
00025 OSPF::HelloHandler::HelloHandler(OSPF::Router* containingRouter) :
00026     OSPF::IMessageHandler(containingRouter)
00027 {
00028 }
00029 
00030 void OSPF::HelloHandler::ProcessPacket(OSPFPacket* packet, OSPF::Interface* intf, OSPF::Neighbor* unused)
00031 {
00032     OSPFHelloPacket* helloPacket         = check_and_cast<OSPFHelloPacket*> (packet);
00033     bool             rebuildRoutingTable = false;
00034 
00035     /* The values of the Network Mask, HelloInterval,
00036        and RouterDeadInterval fields in the received Hello packet must
00037        be checked against the values configured for the receiving
00038        interface.  Any mismatch causes processing to stop and the
00039        packet to be dropped.
00040      */
00041     if ((intf->GetHelloInterval() == helloPacket->getHelloInterval()) &&
00042         (intf->GetRouterDeadInterval() == helloPacket->getRouterDeadInterval()))
00043     {
00044         OSPF::Interface::OSPFInterfaceType interfaceType = intf->GetType();
00045         /* There is one exception to the above rule: on point-to-point
00046            networks and on virtual links, the Network Mask in the received
00047            Hello Packet should be ignored.
00048          */
00049         if (!((interfaceType != OSPF::Interface::PointToPoint) &&
00050               (interfaceType != OSPF::Interface::Virtual) &&
00051               (intf->GetAddressRange().mask != IPv4AddressFromULong(helloPacket->getNetworkMask().getInt()))
00052              )
00053            )
00054         {
00055             /* The setting of the E-bit found in the Hello Packet's Options field must match this area's
00056                ExternalRoutingCapability.
00057              */
00058             if (intf->GetArea()->GetExternalRoutingCapability() == helloPacket->getOptions().E_ExternalRoutingCapability) {
00059                 IPControlInfo*      controlInfo             = check_and_cast<IPControlInfo *> (helloPacket->getControlInfo());
00060                 OSPF::IPv4Address   srcAddress              = IPv4AddressFromULong(controlInfo->getSrcAddr().getInt());
00061                 bool                neighborChanged         = false;
00062                 bool                neighborsDRStateChanged = false;
00063                 bool                drChanged               = false;
00064                 bool                backupSeen              = false;
00065                 OSPF::Neighbor*     neighbor;
00066 
00067                 /* If the receiving interface connects to a broadcast, Point-to-
00068                    MultiPoint or NBMA network the source is identified by the IP
00069                    source address found in the Hello's IP header.
00070                  */
00071                 if ((interfaceType == OSPF::Interface::Broadcast) ||
00072                     (interfaceType == OSPF::Interface::PointToMultiPoint) ||
00073                     (interfaceType == OSPF::Interface::NBMA))
00074                 {
00075                     neighbor = intf->GetNeighborByAddress(srcAddress);
00076                 } else {
00077                     /* If the receiving interface connects to a point-to-point link or a virtual link,
00078                        the source is identified by the Router ID found in the Hello's OSPF packet header.
00079                      */
00080                     neighbor = intf->GetNeighborByID(helloPacket->getRouterID().getInt());
00081                 }
00082 
00083                 if (neighbor != NULL) {
00084                     router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);
00085 
00086                     IPv4Address                 designatedAddress   = neighbor->GetDesignatedRouter().ipInterfaceAddress;
00087                     IPv4Address                 backupAddress       = neighbor->GetBackupDesignatedRouter().ipInterfaceAddress;
00088                     char                        newPriority         = helloPacket->getRouterPriority();
00089                     unsigned long               source              = controlInfo->getSrcAddr().getInt();
00090                     unsigned long               newDesignatedRouter = helloPacket->getDesignatedRouter().getInt();
00091                     unsigned long               newBackupRouter     = helloPacket->getBackupDesignatedRouter().getInt();
00092                     OSPF::DesignatedRouterID    dRouterID;
00093 
00094                     if ((interfaceType == OSPF::Interface::Virtual) &&
00095                         (neighbor->GetState() == OSPF::Neighbor::DownState))
00096                     {
00097                         neighbor->SetPriority(helloPacket->getRouterPriority());
00098                         neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());
00099                     }
00100 
00101                     /* If a change in the neighbor's Router Priority field
00102                        was noted, the receiving interface's state machine is
00103                        scheduled with the event NeighborChange.
00104                      */
00105                     if (neighbor->GetPriority() != newPriority) {
00106                         neighborChanged = true;
00107                     }
00108 
00109                     /* If the neighbor is both declaring itself to be Designated
00110                        Router(Hello Packet's Designated Router field = Neighbor IP
00111                        address) and the Backup Designated Router field in the
00112                        packet is equal to 0.0.0.0 and the receiving interface is in
00113                        state Waiting, the receiving interface's state machine is
00114                        scheduled with the event BackupSeen.
00115                      */
00116                     if ((newDesignatedRouter == source) &&
00117                         (newBackupRouter == 0) &&
00118                         (intf->GetState() == OSPF::Interface::WaitingState))
00119                     {
00120                         backupSeen = true;
00121                     } else {
00122                         /* Otherwise, if the neighbor is declaring itself to be Designated Router and it
00123                            had not previously, or the neighbor is not declaring itself
00124                            Designated Router where it had previously, the receiving
00125                            interface's state machine is scheduled with the event
00126                            NeighborChange.
00127                          */
00128                         if (((newDesignatedRouter == source) &&
00129                              (newDesignatedRouter != ULongFromIPv4Address(designatedAddress))) ||
00130                             ((newDesignatedRouter != source) &&
00131                              (source == ULongFromIPv4Address(designatedAddress))))
00132                         {
00133                             neighborChanged = true;
00134                             neighborsDRStateChanged = true;
00135                         }
00136                     }
00137 
00138                     /* If the neighbor is declaring itself to be Backup Designated
00139                        Router(Hello Packet's Backup Designated Router field =
00140                        Neighbor IP address) and the receiving interface is in state
00141                        Waiting, the receiving interface's state machine is
00142                        scheduled with the event BackupSeen.
00143                      */
00144                     if ((newBackupRouter == source) &&
00145                         (intf->GetState() == OSPF::Interface::WaitingState))
00146                     {
00147                         backupSeen = true;
00148                     } else {
00149                         /* Otherwise, if the neighbor is declaring itself to be Backup Designated Router
00150                            and it had not previously, or the neighbor is not declaring
00151                            itself Backup Designated Router where it had previously, the
00152                            receiving interface's state machine is scheduled with the
00153                            event NeighborChange.
00154                          */
00155                         if (((newBackupRouter == source) &&
00156                              (newBackupRouter != ULongFromIPv4Address(backupAddress))) ||
00157                             ((newBackupRouter != source) &&
00158                              (source == ULongFromIPv4Address(backupAddress))))
00159                         {
00160                             neighborChanged = true;
00161                         }
00162                     }
00163 
00164                     neighbor->SetNeighborID(helloPacket->getRouterID().getInt());
00165                     neighbor->SetPriority(newPriority);
00166                     neighbor->SetAddress(srcAddress);
00167                     dRouterID.routerID = newDesignatedRouter;
00168                     dRouterID.ipInterfaceAddress = IPv4AddressFromULong(newDesignatedRouter);
00169                     if (newDesignatedRouter != ULongFromIPv4Address(designatedAddress)) {
00170                         designatedAddress = dRouterID.ipInterfaceAddress;
00171                         drChanged = true;
00172                     }
00173                     neighbor->SetDesignatedRouter(dRouterID);
00174                     dRouterID.routerID = newBackupRouter;
00175                     dRouterID.ipInterfaceAddress = IPv4AddressFromULong(newBackupRouter);
00176                     if (newBackupRouter != ULongFromIPv4Address(backupAddress)) {
00177                         backupAddress = dRouterID.ipInterfaceAddress;
00178                         drChanged = true;
00179                     }
00180                     neighbor->SetBackupDesignatedRouter(dRouterID);
00181                     if (drChanged) {
00182                         neighbor->SetUpDesignatedRouters(false);
00183                     }
00184 
00185                     /* If the neighbor router's Designated or Backup Designated Router
00186                        has changed it's necessary to look up the Router IDs belonging to the
00187                        new addresses.
00188                      */
00189                     if (!neighbor->DesignatedRoutersAreSetUp()) {
00190                         OSPF::Neighbor* designated = intf->GetNeighborByAddress(designatedAddress);
00191                         OSPF::Neighbor* backup     = intf->GetNeighborByAddress(backupAddress);
00192 
00193                         if (designated != NULL) {
00194                             dRouterID.routerID = designated->GetNeighborID();
00195                             dRouterID.ipInterfaceAddress = designated->GetAddress();
00196                             neighbor->SetDesignatedRouter(dRouterID);
00197                         }
00198                         if (backup != NULL) {
00199                             dRouterID.routerID = backup->GetNeighborID();
00200                             dRouterID.ipInterfaceAddress = backup->GetAddress();
00201                             neighbor->SetBackupDesignatedRouter(dRouterID);
00202                         }
00203                         if ((designated != NULL) && (backup != NULL)) {
00204                             neighbor->SetUpDesignatedRouters(true);
00205                         }
00206                     }
00207                 } else {
00208                     OSPF::DesignatedRouterID    dRouterID;
00209                     bool                        designatedSetUp = false;
00210                     bool                        backupSetUp     = false;
00211 
00212                     neighbor = new OSPF::Neighbor(helloPacket->getRouterID().getInt());
00213                     neighbor->SetPriority(helloPacket->getRouterPriority());
00214                     neighbor->SetAddress(srcAddress);
00215                     neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval());
00216 
00217                     router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor);
00218 
00219                     dRouterID.routerID = helloPacket->getDesignatedRouter().getInt();
00220                     dRouterID.ipInterfaceAddress = IPv4AddressFromULong(dRouterID.routerID);
00221 
00222                     OSPF::Neighbor* designated = intf->GetNeighborByAddress(dRouterID.ipInterfaceAddress);
00223 
00224                     // Get the Designated Router ID from the corresponding Neighbor Object.
00225                     if (designated != NULL) {
00226                         if (designated->GetNeighborID() != dRouterID.routerID) {
00227                             dRouterID.routerID = designated->GetNeighborID();
00228                         }
00229                         designatedSetUp = true;
00230                     }
00231                     neighbor->SetDesignatedRouter(dRouterID);
00232 
00233                     dRouterID.routerID = helloPacket->getBackupDesignatedRouter().getInt();
00234                     dRouterID.ipInterfaceAddress = IPv4AddressFromULong(dRouterID.routerID);
00235 
00236                     OSPF::Neighbor* backup = intf->GetNeighborByAddress(dRouterID.ipInterfaceAddress);
00237 
00238                     // Get the Backup Designated Router ID from the corresponding Neighbor Object.
00239                     if (backup != NULL) {
00240                         if (backup->GetNeighborID() != dRouterID.routerID) {
00241                             dRouterID.routerID = backup->GetNeighborID();
00242                         }
00243                         backupSetUp = true;
00244                     }
00245                     neighbor->SetBackupDesignatedRouter(dRouterID);
00246                     if (designatedSetUp && backupSetUp) {
00247                         neighbor->SetUpDesignatedRouters(true);
00248                     }
00249                     intf->AddNeighbor(neighbor);
00250                 }
00251 
00252                 neighbor->ProcessEvent(OSPF::Neighbor::HelloReceived);
00253                 if ((interfaceType == OSPF::Interface::NBMA) &&
00254                     (intf->GetRouterPriority() == 0) &&
00255                     (neighbor->GetState() >= OSPF::Neighbor::InitState))
00256                 {
00257                     intf->SendHelloPacket(neighbor->GetAddress());
00258                 }
00259 
00260                 unsigned long   interfaceAddress       = ULongFromIPv4Address(intf->GetAddressRange().address);
00261                 unsigned int    neighborsNeighborCount = helloPacket->getNeighborArraySize();
00262                 unsigned int    i;
00263                 /* The list of neighbors contained in the Hello Packet is
00264                    examined.  If the router itself appears in this list, the
00265                    neighbor state machine should be executed with the event TwoWayReceived.
00266                  */
00267                 for (i = 0; i < neighborsNeighborCount; i++) {
00268                     if (helloPacket->getNeighbor(i).getInt() == interfaceAddress) {
00269                         neighbor->ProcessEvent(OSPF::Neighbor::TwoWayReceived);
00270                         break;
00271                     }
00272                 }
00273                 /* Otherwise, the neighbor state machine should
00274                    be executed with the event OneWayReceived, and the processing
00275                    of the packet stops.
00276                  */
00277                 if (i == neighborsNeighborCount) {
00278                     neighbor->ProcessEvent(OSPF::Neighbor::OneWayReceived);
00279                 }
00280 
00281                 if (neighborChanged) {
00282                     intf->ProcessEvent(OSPF::Interface::NeighborChange);
00283                     /* In some cases neighbors get stuck in TwoWay state after a DR
00284                        or Backup change. (CalculateDesignatedRouter runs before the
00285                        neighbors' signal of DR change + this router does not become
00286                        neither DR nor backup -> IsAdjacencyOK does not get called.)
00287                        So to make it work(workaround) we'll call IsAdjacencyOK for
00288                        all neighbors in TwoWay state from here. This shouldn't break
00289                        anything because if the neighbor state doesn't have to change
00290                        then NeedAdjacency returns false and nothing happnes in
00291                        IsAdjacencyOK.
00292                      */
00293                     unsigned int neighborCount = intf->GetNeighborCount();
00294                     for (i = 0; i < neighborCount; i++) {
00295                         OSPF::Neighbor* stuckNeighbor = intf->GetNeighbor(i);
00296                         if (stuckNeighbor->GetState() == OSPF::Neighbor::TwoWayState) {
00297                             stuckNeighbor->ProcessEvent(OSPF::Neighbor::IsAdjacencyOK);
00298                         }
00299                     }
00300 
00301                     if (neighborsDRStateChanged) {
00302                         OSPF::RouterLSA* routerLSA = intf->GetArea()->FindRouterLSA(router->GetRouterID());
00303 
00304                         if (routerLSA != NULL) {
00305                             long sequenceNumber = routerLSA->getHeader().getLsSequenceNumber();
00306                             if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
00307                                 routerLSA->getHeader().setLsAge(MAX_AGE);
00308                                 intf->GetArea()->FloodLSA(routerLSA);
00309                                 routerLSA->IncrementInstallTime();
00310                             } else {
00311                                 OSPF::RouterLSA* newLSA = intf->GetArea()->OriginateRouterLSA();
00312 
00313                                 newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00314                                 newLSA->getHeader().setLsChecksum(0);    // TODO: calculate correct LS checksum
00315                                 rebuildRoutingTable |= routerLSA->Update(newLSA);
00316                                 delete newLSA;
00317 
00318                                 intf->GetArea()->FloodLSA(routerLSA);
00319                             }
00320                         }
00321                     }
00322                 }
00323 
00324                 if (backupSeen) {
00325                     intf->ProcessEvent(OSPF::Interface::BackupSeen);
00326                 }
00327             }
00328         }
00329     }
00330 
00331     if (rebuildRoutingTable) {
00332         router->RebuildRoutingTable();
00333     }
00334 }