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