|
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 "ansaMessageHandler6.h" 00019 #include "ansaOspfRouter6.h" 00020 00021 AnsaOspf6::MessageHandler::MessageHandler(AnsaOspf6::Router* containingRouter, cSimpleModule* containingModule) : 00022 AnsaOspf6::IMessageHandler(containingRouter), 00023 ospfModule(containingModule), 00024 helloHandler(containingRouter), 00025 ddHandler(containingRouter), 00026 lsRequestHandler(containingRouter), 00027 lsUpdateHandler(containingRouter), 00028 lsAckHandler(containingRouter){ 00029 } 00030 00031 void AnsaOspf6::MessageHandler::MessageReceived(cMessage* message) { 00032 if (message->isSelfMessage()){ 00033 HandleTimer(check_and_cast<OspfTimer6*> (message)); 00034 }else{ 00035 OspfPacket6* packet = check_and_cast<OspfPacket6*> (message); 00036 EV << "Received packet: (" << packet->getClassName() << ")" << packet->getName() << "\n"; 00037 if (packet->getRouterID() == router->GetRouterID()){ 00038 EV << "This packet is from ourselves, discarding.\n"; 00039 delete message; 00040 }else{ 00041 ProcessPacket(packet); 00042 } 00043 } 00044 } 00045 00046 void AnsaOspf6::MessageHandler::HandleTimer(OspfTimer6* timer){ 00047 switch (timer->getTimerKind()){ 00048 case InterfaceHelloTimer: { 00049 AnsaOspf6::Interface* intf; 00050 if (!(intf = reinterpret_cast<AnsaOspf6::Interface*> (timer->getContextPointer()))){ 00051 // should not reach this point 00052 EV<< "Discarding invalid InterfaceHelloTimer.\n"; 00053 delete timer; 00054 }else{ 00055 PrintEvent("Hello Timer expired", intf); 00056 intf->ProcessEvent(AnsaOspf6::Interface::HelloTimer); 00057 }} 00058 break; 00059 case InterfaceWaitTimer: { 00060 AnsaOspf6::Interface* intf; 00061 if (! (intf = reinterpret_cast <AnsaOspf6::Interface*> (timer->getContextPointer()))){ 00062 // should not reach this point 00063 EV << "Discarding invalid InterfaceWaitTimer.\n"; 00064 delete timer; 00065 }else{ 00066 PrintEvent("Wait Timer expired", intf); 00067 intf->ProcessEvent(AnsaOspf6::Interface::WaitTimer); 00068 }} 00069 break; 00070 case InterfaceAcknowledgementTimer: { 00071 AnsaOspf6::Interface* intf; 00072 if (! (intf = reinterpret_cast <AnsaOspf6::Interface*> (timer->getContextPointer()))){ 00073 // should not reach this point 00074 EV << "Discarding invalid InterfaceAcknowledgementTimer.\n"; 00075 delete timer; 00076 } else{ 00077 PrintEvent("Acknowledgement Timer expired", intf); 00078 intf->ProcessEvent(AnsaOspf6::Interface::AcknowledgementTimer); 00079 }} 00080 break; 00081 case NeighborInactivityTimer: { 00082 AnsaOspf6::Neighbor* neighbor; 00083 if (! (neighbor = reinterpret_cast <AnsaOspf6::Neighbor*> (timer->getContextPointer()))){ 00084 // should not reach this point 00085 EV << "Discarding invalid NeighborInactivityTimer.\n"; 00086 delete timer; 00087 } else{ 00088 PrintEvent("Inactivity Timer expired", neighbor->GetInterface(), neighbor); 00089 neighbor->ProcessEvent(AnsaOspf6::Neighbor::InactivityTimer); 00090 }} 00091 break; 00092 case NeighborPollTimer: { 00093 AnsaOspf6::Neighbor* neighbor; 00094 if (! (neighbor = reinterpret_cast <AnsaOspf6::Neighbor*> (timer->getContextPointer()))){ 00095 // should not reach this point 00096 EV << "Discarding invalid NeighborInactivityTimer.\n"; 00097 delete timer; 00098 } else{ 00099 PrintEvent("Poll Timer expired", neighbor->GetInterface(), neighbor); 00100 //neighbor->ProcessEvent(AnsaOspf6::Neighbor::PollTimer); 00101 }} 00102 break; 00103 case NeighborDDRetransmissionTimer: { 00104 AnsaOspf6::Neighbor* neighbor; 00105 if (! (neighbor = reinterpret_cast <AnsaOspf6::Neighbor*> (timer->getContextPointer()))){ 00106 // should not reach this point 00107 EV << "Discarding invalid NeighborDDRetransmissionTimer.\n"; 00108 delete timer; 00109 } else{ 00110 PrintEvent("Database Description Retransmission Timer expired", neighbor->GetInterface(), neighbor); 00111 //neighbor->ProcessEvent(AnsaOspf6::Neighbor::DDRetransmissionTimer); 00112 }} 00113 break; 00114 case NeighborUpdateRetransmissionTimer: { 00115 AnsaOspf6::Neighbor* neighbor; 00116 if (! (neighbor = reinterpret_cast <AnsaOspf6::Neighbor*> (timer->getContextPointer()))){ 00117 // should not reach this point 00118 EV << "Discarding invalid NeighborUpdateRetransmissionTimer.\n"; 00119 delete timer; 00120 } else{ 00121 PrintEvent("Update Retransmission Timer expired", neighbor->GetInterface(), neighbor); 00122 //neighbor->ProcessEvent(AnsaOspf6::Neighbor::UpdateRetransmissionTimer); 00123 }} 00124 break; 00125 case NeighborRequestRetransmissionTimer: { 00126 AnsaOspf6::Neighbor* neighbor; 00127 if (! (neighbor = reinterpret_cast <AnsaOspf6::Neighbor*> (timer->getContextPointer()))){ 00128 // should not reach this point 00129 EV << "Discarding invalid NeighborRequestRetransmissionTimer.\n"; 00130 delete timer; 00131 } else{ 00132 PrintEvent("Request Retransmission Timer expired", neighbor->GetInterface(), neighbor); 00133 //neighbor->ProcessEvent(AnsaOspf6::Neighbor::RequestRetransmissionTimer); 00134 }} 00135 break; 00136 case DatabaseAgeTimer: { 00137 PrintEvent("Ageing the database"); 00138 router->AgeDatabase(); 00139 } 00140 break; 00141 default: 00142 break; 00143 } 00144 } 00145 00146 void AnsaOspf6::MessageHandler::ProcessPacket(OspfPacket6* packet, AnsaOspf6::Interface* unused1, AnsaOspf6::Neighbor* unused2){ 00147 00148 // there is no loop 00149 do { 00150 00151 // The version number field MUST specify protocol version 3. 00152 if (packet->getVersion() != 3){ 00153 break; 00154 } 00155 00156 IPv6ControlInfo* controlInfo = check_and_cast<IPv6ControlInfo *> (packet->getControlInfo()); 00157 int interfaceId = controlInfo->getInterfaceId(); 00158 AnsaOspf6::AreaID areaID = packet->getAreaID(); 00159 AnsaOspf6::InstanceID instanceID = packet->getInstanceID(); 00160 AnsaOspf6::Area* area = router->GetArea(areaID); 00161 00162 // The Area ID and Instance ID found in the OSPF header must be verified. 00163 if (area == NULL){ 00164 break; 00165 } 00166 00167 // TODO: check instance ID 00168 // if (instanceId != ) 00169 00170 AnsaOspf6::Interface* intf = area->GetInterface(interfaceId); 00171 00172 if (intf != NULL && instanceID != intf->GetInstanceID()){ 00173 break; 00174 } 00175 00176 00177 /* Match the backbone area and other criteria for a configured 00178 virtual link. The receiving router must be an ABR (Area 00179 Border Router) and the Router ID specified in the packet (the 00180 source router) must be the other end of a configured virtual 00181 link. Additionally, the receiving link must have an OSPFv3 00182 interface that attaches to the virtual link's configured 00183 transit area and the Instance ID must match the virtual link's 00184 Instance ID. 00185 */ 00186 if (intf == NULL){ 00187 if (areaID != BackboneAreaID ){ 00188 break; 00189 } 00190 00191 intf = area->FindVirtualLink(packet->getRouterID()); 00192 if (intf == NULL){ 00193 break; 00194 } 00195 00196 AnsaOspf6::Area* virtualLinkTransitArea = router->GetArea(intf->GetTransitAreaID()); 00197 if (virtualLinkTransitArea == NULL){ 00198 intf = NULL; 00199 }else{ 00200 // the receiving interface must attach to the virtual link's configured transit area 00201 AnsaOspf6::Interface* virtualLinkInterface = virtualLinkTransitArea->GetInterface(interfaceId); 00202 00203 if (virtualLinkInterface == NULL) { 00204 intf = NULL; 00205 } 00206 } 00207 00208 // intf != NULL 00209 }else{ 00210 00211 IPv6Address destinationAddress = controlInfo->getDestAddr(); 00212 AnsaOspf6::Interface::InterfaceStateType interfaceState = intf->GetState(); 00213 00214 // if destination address is AllDRouters the receiving interface must be in DesignatedRouter or Backup state 00215 if (destinationAddress == AnsaOspf6::AllDRouters){ 00216 if ( (interfaceState != AnsaOspf6::Interface::DesignatedRouterState) 00217 && (interfaceState != AnsaOspf6::Interface::BackupState)){ 00218 break; 00219 } 00220 } 00221 00222 00223 OspfPacketType6 packetType = static_cast<OspfPacketType6> (packet->getType()); 00224 AnsaOspf6::Neighbor* neighbor = NULL; 00225 00226 // all packets except HelloPackets are sent only along adjacencies, so a Neighbor must exist 00227 if (packetType != HelloPacket){ 00228 00229 // On all link types (e.g., broadcast, NBMA, point-to-point, etc.), 00230 // neighbors are identified solely by their OSPF Router ID. 00231 neighbor = intf->GetNeighborByID(packet->getRouterID()); 00232 } 00233 00234 switch (packetType){ 00235 case HelloPacket: 00236 helloHandler.ProcessPacket(packet, intf); 00237 router->stat.AddHelloPacketReceived(); 00238 router->stat.AddOspfPacketReceived(); 00239 break; 00240 case DatabaseDescriptionPacket: 00241 if (neighbor != NULL){ 00242 ddHandler.ProcessPacket(packet, intf, neighbor); 00243 router->stat.AddOspfPacketReceived(); 00244 } 00245 break; 00246 case LinkStateRequestPacket: 00247 if (neighbor != NULL){ 00248 lsRequestHandler.ProcessPacket(packet, intf, neighbor); 00249 router->stat.AddOspfPacketReceived(); 00250 } 00251 break; 00252 case LinkStateUpdatePacket: 00253 if (neighbor != NULL){ 00254 lsUpdateHandler.ProcessPacket(packet, intf, neighbor); 00255 router->stat.AddOspfPacketReceived(); 00256 } 00257 break; 00258 case LinkStateAcknowledgementPacket: 00259 if (neighbor != NULL){ 00260 lsAckHandler.ProcessPacket(packet, intf, neighbor); 00261 router->stat.AddOspfPacketReceived(); 00262 } 00263 break; 00264 default: 00265 break; 00266 } 00267 } 00268 00269 // there is no loop 00270 } while(false); 00271 00272 delete packet; 00273 } 00274 00275 void AnsaOspf6::MessageHandler::SendPacket(OspfPacket6* packet, IPv6Address destination, int outputIfIndex, short hopLimit){ 00276 00277 IPv6ControlInfo *ipControlInfo = new IPv6ControlInfo(); 00278 ipControlInfo->setProtocol(IP_PROT_OSPF); 00279 ipControlInfo->setDestAddr(destination); 00280 ipControlInfo->setHopLimit(hopLimit); 00281 ipControlInfo->setInterfaceId(outputIfIndex); 00282 packet->setControlInfo(ipControlInfo); 00283 00284 switch (packet->getType()){ 00285 case HelloPacket: { 00286 packet->setKind(HelloPacket); 00287 packet->setName("OSPFv3_HelloPacket"); 00288 00289 OspfHelloPacket6* helloPacket = check_and_cast<OspfHelloPacket6*> (packet); 00290 PrintHelloPacket(helloPacket, destination, outputIfIndex); 00291 00292 router->stat.AddHelloPacketSend(); 00293 } 00294 break; 00295 case DatabaseDescriptionPacket: { 00296 packet->setKind(DatabaseDescriptionPacket); 00297 packet->setName("OSPFv3_DDPacket"); 00298 00299 OspfDatabaseDescriptionPacket6* ddPacket = check_and_cast<OspfDatabaseDescriptionPacket6*> (packet); 00300 PrintDatabaseDescriptionPacket(ddPacket, destination, outputIfIndex); 00301 } 00302 break; 00303 case LinkStateRequestPacket: { 00304 packet->setKind(LinkStateRequestPacket); 00305 packet->setName("OSPF_LSReqPacket"); 00306 00307 OspfLinkStateRequestPacket6* requestPacket = check_and_cast<OspfLinkStateRequestPacket6*> (packet); 00308 PrintLinkStateRequestPacket(requestPacket, destination, outputIfIndex); 00309 } 00310 break; 00311 case LinkStateUpdatePacket: { 00312 packet->setKind(LinkStateUpdatePacket); 00313 packet->setName("OSPFv3_LSUpdPacket"); 00314 00315 OspfLinkStateUpdatePacket6* updatePacket = check_and_cast<OspfLinkStateUpdatePacket6*> (packet); 00316 PrintLinkStateUpdatePacket(updatePacket, destination, outputIfIndex); 00317 } 00318 break; 00319 case LinkStateAcknowledgementPacket: { 00320 packet->setKind(LinkStateAcknowledgementPacket); 00321 packet->setName("OSPFv3_LSAckPacket"); 00322 00323 OspfLinkStateAcknowledgementPacket6* ackPacket = check_and_cast<OspfLinkStateAcknowledgementPacket6*> (packet); 00324 PrintLinkStateAcknowledgementPacket(ackPacket, destination, outputIfIndex); 00325 } 00326 break; 00327 default: 00328 break; 00329 } 00330 00331 ospfModule->send(packet, "ipv6Out"); 00332 router->stat.AddOspfPacketSend(); 00333 } 00334 00335 void AnsaOspf6::MessageHandler::ClearTimer(OspfTimer6* timer) { 00336 if (ospfModule != NULL && timer != NULL){ 00337 ospfModule->cancelEvent(timer); 00338 } 00339 } 00340 00341 void AnsaOspf6::MessageHandler::StartTimer(OspfTimer6* timer, simtime_t delay) { 00342 ospfModule->scheduleAt(simTime() + delay, timer); 00343 } 00344 00345 void AnsaOspf6::MessageHandler::PrintEvent(const char* eventString, 00346 const AnsaOspf6::Interface* onInterface, const AnsaOspf6::Neighbor* forNeighbor /*= NULL*/) const { 00347 00348 EV<< eventString; 00349 if ((onInterface != NULL) || (forNeighbor != NULL)){ 00350 EV << ": "; 00351 } 00352 if (forNeighbor != NULL){ 00353 char addressString[16]; 00354 EV << "neighbor[" 00355 << IPAddress(forNeighbor->GetNeighborID()) 00356 << "] (state: " 00357 << forNeighbor->GetStateString(forNeighbor->GetState()) 00358 << "); "; 00359 } 00360 if (onInterface != NULL){ 00361 EV << "interface[" 00362 << static_cast <short> (onInterface->GetIfIndex()) 00363 << "] "; 00364 switch (onInterface->GetType()){ 00365 case AnsaOspf6::Interface::PointToPoint: EV << "(PointToPoint)"; 00366 break; 00367 case AnsaOspf6::Interface::Broadcast: EV << "(Broadcast)"; 00368 break; 00369 case AnsaOspf6::Interface::NBMA: EV << "(NBMA).\n"; 00370 break; 00371 case AnsaOspf6::Interface::PointToMultiPoint: EV << "(PointToMultiPoint)"; 00372 break; 00373 case AnsaOspf6::Interface::Virtual: EV << "(Virtual)"; 00374 break; 00375 default: EV << "(Unknown)"; 00376 } 00377 EV << " (state: " 00378 << onInterface->GetStateString(onInterface->GetState()) 00379 << ")"; 00380 } 00381 EV << ".\n"; 00382 } 00383 00384 void AnsaOspf6::MessageHandler::PrintHelloPacket( 00385 const OspfHelloPacket6* helloPacket, 00386 IPv6Address destination, 00387 int outputIfIndex) const { 00388 00389 EV << "Sending Hello packet to " << destination 00390 << " via interface[" << outputIfIndex << "] with contents:" << endl; 00391 EV << " interfaceID=" << helloPacket->getInterfaceID() << endl; 00392 EV << " DR=" << IPAddress(helloPacket->getDesignatedRouterID()) << endl; 00393 EV << " BDR=" << IPAddress(helloPacket->getBackupDesignatedRouterID()) << endl; 00394 EV << " neighbors:" << endl; 00395 00396 unsigned int neighborCount = helloPacket->getNeighborIDArraySize(); 00397 for (unsigned int i = 0; i < neighborCount; i++) { 00398 EV << " " << IPAddress(helloPacket->getNeighborID(i)) << endl; 00399 } 00400 } 00401 00402 void AnsaOspf6::MessageHandler::PrintDatabaseDescriptionPacket( 00403 const OspfDatabaseDescriptionPacket6* ddPacket, 00404 IPv6Address destination, 00405 int outputIfIndex) const { 00406 00407 EV << "Sending Database Description packet to " << destination 00408 << " via interface[" << outputIfIndex << "] with contents:" << endl; 00409 00410 const OspfDdOptions6& ddOptions = ddPacket->getDdOptions(); 00411 EV << " ddOptions=" 00412 << ((ddOptions.I_Init) ? "I " : "_ ") 00413 << ((ddOptions.M_More) ? "M " : "_ ") 00414 << ((ddOptions.MS_MasterSlave) ? "MS" : "__") << endl; 00415 00416 EV << " seqNumber=" 00417 << ddPacket->getDdSequenceNumber() << endl; 00418 00419 EV << " LSA headers:" << endl; 00420 00421 unsigned int lsaCount = ddPacket->getLsaHeadersArraySize(); 00422 for (unsigned int i = 0; i < lsaCount; i++) { 00423 EV << " "; 00424 PrintLsaHeader6(ddPacket->getLsaHeaders(i), ev.getOStream()); 00425 EV << endl; 00426 } 00427 } 00428 00429 void AnsaOspf6::MessageHandler::PrintLinkStateRequestPacket( 00430 const OspfLinkStateRequestPacket6* requestPacket, 00431 IPv6Address destination, 00432 int outputIfIndex) const { 00433 00434 00435 EV << "Sending Link State Request packet to " << destination 00436 << " via interface[" << outputIfIndex << "] with contents:" << endl; 00437 00438 unsigned int requestCount = requestPacket->getRequestsArraySize(); 00439 for (unsigned int i = 0; i < requestCount; i++){ 00440 const OspfLsaRequest6& request = requestPacket->getRequests(i); 00441 EV << " type=" << request.lsType << ", LSID=" << request.linkStateID; 00442 EV << ", advertisingRouter=" << IPAddress(request.advertisingRouter) << endl; 00443 } 00444 } 00445 00446 void AnsaOspf6::MessageHandler::PrintLinkStateUpdatePacket( 00447 const OspfLinkStateUpdatePacket6* updatePacket, 00448 IPv6Address destination, 00449 int outputIfIndex) const { 00450 00451 EV << "Sending Link State Update packet to " << destination 00452 << " via interface[" << outputIfIndex << "] with contents:" << endl; 00453 00454 // RouterLSA 00455 unsigned int lsaCount = updatePacket->getRouterLsasArraySize(); 00456 if (lsaCount > 0){ 00457 ev << "RouterLsa (" << lsaCount << "):" << endl; 00458 } 00459 for (int i = 0; i < lsaCount; i++){ 00460 const OspfRouterLsa6& lsa = updatePacket->getRouterLsas(i); 00461 ev << " "; 00462 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00463 ev << endl; 00464 PrintRouterLsa(lsa, ev.getOStream()); 00465 } 00466 00467 // NetworkLSA 00468 lsaCount = updatePacket->getNetworkLsasArraySize(); 00469 if (lsaCount > 0){ 00470 ev << "NetworkLsa (" << lsaCount << "):" << endl; 00471 } 00472 for (int i = 0; i < lsaCount; i++){ 00473 const OspfNetworkLsa6& lsa = updatePacket->getNetworkLsas(i); 00474 ev << " "; 00475 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00476 ev << endl; 00477 PrintNetworkLsa(lsa, ev.getOStream()); 00478 } 00479 00480 // InterAreaPrefixLSA 00481 lsaCount = updatePacket->getInterAreaPrefixLsasArraySize(); 00482 if (lsaCount > 0){ 00483 ev << "InterAreaPrefixLsa (" << lsaCount << "):" << endl; 00484 } 00485 for (int i = 0; i < lsaCount; i++){ 00486 const OspfInterAreaPrefixLsa6& lsa = updatePacket->getInterAreaPrefixLsas(i); 00487 ev << " "; 00488 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00489 ev << endl; 00490 PrintInterAreaPrefixLsa(lsa, ev.getOStream()); 00491 } 00492 00493 // InterAreaRouterLSA 00494 lsaCount = updatePacket->getInterAreaRouterLsasArraySize(); 00495 if (lsaCount > 0){ 00496 ev << "InterAreaRouterLsa (" << lsaCount << "):" << endl; 00497 } 00498 for (int i = 0; i < lsaCount; i++){ 00499 const OspfInterAreaRouterLsa6& lsa = updatePacket->getInterAreaRouterLsas(i); 00500 ev << " "; 00501 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00502 ev << endl; 00503 PrintInterAreaRouterLsa(lsa, ev.getOStream()); 00504 } 00505 00506 // AsExternalLSA 00507 lsaCount = updatePacket->getAsExternalLsasArraySize(); 00508 if (lsaCount > 0){ 00509 ev << "AsExternalLsa (" << lsaCount << "):" << endl; 00510 } 00511 for (int i = 0; i < lsaCount; i++){ 00512 const OspfAsExternalLsa6& lsa = updatePacket->getAsExternalLsas(i); 00513 ev << " "; 00514 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00515 ev << endl; 00516 PrintAsExternalLsa(lsa, ev.getOStream()); 00517 } 00518 00519 // LinkLSA 00520 lsaCount = updatePacket->getLinkLsasArraySize(); 00521 if (lsaCount > 0){ 00522 ev << "LinkLsa (" << lsaCount << "):" << endl; 00523 } 00524 for (int i = 0; i < lsaCount; i++){ 00525 const OspfLinkLsa6& lsa = updatePacket->getLinkLsas(i); 00526 ev << " "; 00527 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00528 ev << endl; 00529 PrintLinkLsa(lsa, ev.getOStream()); 00530 } 00531 00532 // IntraAreaPrefix LSA 00533 lsaCount = updatePacket->getIntraAreaPrefixLsasArraySize(); 00534 if (lsaCount > 0){ 00535 ev << "IntraAreaPrefixLsa (" << lsaCount << "):" << endl; 00536 } 00537 for (int i = 0; i < lsaCount; i++){ 00538 const OspfIntraAreaPrefixLsa6& lsa = updatePacket->getIntraAreaPrefixLsas(i); 00539 ev << " "; 00540 PrintLsaHeader6(lsa.getHeader(), ev.getOStream()); 00541 ev << endl; 00542 PrintIntraAreaPrefixLsa(lsa, ev.getOStream()); 00543 } 00544 } 00545 00546 void AnsaOspf6::MessageHandler::PrintLinkStateAcknowledgementPacket( 00547 const OspfLinkStateAcknowledgementPacket6* ackPacket, 00548 IPv6Address destination, 00549 int outputIfIndex) const { 00550 00551 EV << "Sending Link State Acknowledgement packet to " << destination 00552 << " via interface[" << outputIfIndex << "] with contents:" << endl; 00553 00554 unsigned int lsaCount = ackPacket->getLsaHeadersArraySize(); 00555 for (unsigned int i = 0; i < lsaCount; i++) { 00556 EV << " "; 00557 PrintLsaHeader6(ackPacket->getLsaHeaders(i), ev.getOStream()); 00558 EV << "\n"; 00559 } 00560 }