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