|
INET Framework for OMNeT++/OMNEST
|
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 }