INET Framework for OMNeT++/OMNEST
ansaLinkStateUpdateHandler6.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 "ansaOspfArea6.h"
00017 #include "ansaOspfCommon6.h"
00018 #include "ansaOspfNeighbor6.h"
00019 #include "ansaOspfRouter6.h"
00020 
00021 #include "ansaLinkStateUpdateHandler6.h"
00022 
00023 class LsaProcessingMarker {
00024    private:
00025       unsigned int index;
00026 
00027    public:
00028       LsaProcessingMarker(unsigned int counter) : index(counter) { EV<< "    --> Processing LSA(" << index << ")\n"; }
00029       ~LsaProcessingMarker() { EV << "    <-- LSA(" << index << ") processed.\n"; }
00030    };
00031 
00032 AnsaOspf6::LinkStateUpdateHandler::LinkStateUpdateHandler(AnsaOspf6::Router* containingRouter) :
00033    AnsaOspf6::IMessageHandler(containingRouter) {
00034 }
00035 
00036 void AnsaOspf6::LinkStateUpdateHandler::ProcessPacket(OspfPacket6* packet,
00037       AnsaOspf6::Interface* intf, AnsaOspf6::Neighbor* neighbor) {
00038 
00039    router->GetMessageHandler()->PrintEvent("Link State Update packet received", intf, neighbor);
00040 
00041    OspfLinkStateUpdatePacket6* lsUpdatePacket = check_and_cast<OspfLinkStateUpdatePacket6*> (packet);
00042    bool rebuildRoutingTable = false;
00043 
00044    if (neighbor->GetState() >= AnsaOspf6::Neighbor::ExchangeState){
00045       AnsaOspf6::AreaID areaID = lsUpdatePacket->getAreaID();
00046       AnsaOspf6::Area* area = router->GetArea(areaID);
00047       LsaType6 currentType = RouterLsaType;
00048       unsigned int currentLSAIndex = 0;
00049 
00050       EV<< "  Processing packet contents:\n";
00051 
00052       while (currentType <= IntraAreaPrefixLsaType){
00053          unsigned int lsaCount = 0;
00054 
00055          switch (currentType){
00056             case RouterLsaType:
00057                lsaCount = lsUpdatePacket->getRouterLsasArraySize();
00058                break;
00059             case NetworkLsaType:
00060                lsaCount = lsUpdatePacket->getNetworkLsasArraySize();
00061                break;
00062             case InterAreaPrefixLsaType:
00063                lsaCount = lsUpdatePacket->getInterAreaPrefixLsasArraySize();
00064                break;
00065             case InterAreaRouterLsaType:
00066                lsaCount = lsUpdatePacket->getInterAreaRouterLsasArraySize();
00067                break;
00068             case AsExternalLsaType:
00069                lsaCount = lsUpdatePacket->getAsExternalLsasArraySize();
00070                break;
00071             case LinkLsaType:
00072                lsaCount = lsUpdatePacket->getLinkLsasArraySize();
00073                break;
00074             case IntraAreaPrefixLsaType:
00075                lsaCount = lsUpdatePacket->getIntraAreaPrefixLsasArraySize();
00076                break;
00077             default:
00078                break;
00079          }
00080 
00081          for (unsigned int i = 0; i < lsaCount; i++){
00082             OspfLsa6* currentLSA;
00083 
00084             switch (currentType){
00085                case RouterLsaType:
00086                   currentLSA = (&(lsUpdatePacket->getRouterLsas(i)));
00087                   break;
00088                case NetworkLsaType:
00089                   currentLSA = (&(lsUpdatePacket->getNetworkLsas(i)));
00090                   break;
00091                case InterAreaPrefixLsaType:
00092                   currentLSA = (&(lsUpdatePacket->getInterAreaPrefixLsas(i)));
00093                   break;
00094                case InterAreaRouterLsaType:
00095                   currentLSA = (&(lsUpdatePacket->getInterAreaRouterLsas(i)));
00096                   break;
00097                case AsExternalLsaType:
00098                   currentLSA = (&(lsUpdatePacket->getAsExternalLsas(i)));
00099                   break;
00100                case LinkLsaType:
00101                   currentLSA = (&(lsUpdatePacket->getLinkLsas(i)));
00102                   break;
00103                case IntraAreaPrefixLsaType:
00104                   currentLSA = (&(lsUpdatePacket->getIntraAreaPrefixLsas(i)));
00105                   break;
00106                default:
00107                   break;
00108             }
00109 
00110             LsaType6 lsaType = static_cast<LsaType6> (currentLSA->getHeader().getLsType());
00111             if (  (lsaType != RouterLsaType) &&
00112                   (lsaType != NetworkLsaType) &&
00113                   (lsaType != InterAreaPrefixLsaType) &&
00114                   (lsaType != InterAreaRouterLsaType) &&
00115                   (lsaType != AsExternalLsaType) &&
00116                   (lsaType != LinkLsaType) &&
00117                   (lsaType != IntraAreaPrefixLsaType)){
00118                continue;
00119             }
00120 
00121             LsaProcessingMarker marker(currentLSAIndex++);
00122             EV << "    ";
00123             PrintLsaHeader6(currentLSA->getHeader(), ev.getOStream());
00124             EV << "\n";
00125 
00126             if ((lsaType == AsExternalLsaType) && (!area->GetExternalRoutingCapability())){
00127                continue;
00128             }
00129             AnsaOspf6::LsaKeyType6 lsaKey;
00130 
00131             lsaKey.linkStateID = currentLSA->getHeader().getLinkStateID();
00132             lsaKey.advertisingRouter = currentLSA->getHeader().getAdvertisingRouter();
00133 
00134             OspfLsa6* lsaInDatabase = router->FindLSA(lsaType, lsaKey, areaID);
00135             unsigned short lsAge = currentLSA->getHeader().getLsAge();
00136             AcknowledgementFlags ackFlags;
00137 
00138             ackFlags.floodedBackOut = false;
00139             ackFlags.lsaIsNewer = false;
00140             ackFlags.lsaIsDuplicate = false;
00141             ackFlags.impliedAcknowledgement = false;
00142             ackFlags.lsaReachedMaxAge = (lsAge == MAX_AGE);
00143             ackFlags.noLSAInstanceInDatabase = (lsaInDatabase == NULL);
00144             ackFlags.anyNeighborInExchangeOrLoadingState = router->HasAnyNeighborInStates(AnsaOspf6::Neighbor::ExchangeState | AnsaOspf6::Neighbor::LoadingState);
00145 
00146 
00147             if ((ackFlags.lsaReachedMaxAge) && (ackFlags.noLSAInstanceInDatabase) && (!ackFlags.anyNeighborInExchangeOrLoadingState)){
00148                if (intf->GetType() == AnsaOspf6::Interface::Broadcast){
00149                   if (  (intf->GetState() == AnsaOspf6::Interface::DesignatedRouterState) ||
00150                         (intf->GetState() == AnsaOspf6::Interface::BackupState) ||
00151                         (intf->GetDesignatedRouter() == AnsaOspf6::NullDesignatedRouterID)){
00152                            intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOspf6::AllSPFRouters);
00153                         }else{
00154                            intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOspf6::AllDRouters);
00155                         }
00156                }else{
00157                   if (intf->GetType() == AnsaOspf6::Interface::PointToPoint){
00158                      intf->SendLSAcknowledgement(&(currentLSA->getHeader()), AnsaOspf6::AllSPFRouters);
00159                   }else{
00160                      intf->SendLSAcknowledgement(&(currentLSA->getHeader()), neighbor->GetAddress());
00161                   }
00162                }
00163                continue;
00164             }
00165 
00166             if (!ackFlags.noLSAInstanceInDatabase){
00167                // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
00168                ackFlags.lsaIsNewer = (lsaInDatabase->getHeader() < currentLSA->getHeader());
00169                ackFlags.lsaIsDuplicate = (operator== (lsaInDatabase->getHeader(), currentLSA->getHeader()));
00170             }
00171             if ((ackFlags.noLSAInstanceInDatabase) || (ackFlags.lsaIsNewer)){
00172                LsaTrackingInfo* info = (!ackFlags.noLSAInstanceInDatabase) ? dynamic_cast<LsaTrackingInfo*> (lsaInDatabase) : NULL;
00173                if (  (!ackFlags.noLSAInstanceInDatabase) &&
00174                      (info != NULL) &&
00175                      (info->GetSource() == LsaTrackingInfo::Flooded) &&
00176                      (info->GetInstallTime() < MIN_LS_ARRIVAL)){
00177                   //continue; TODO
00178                }
00179                ackFlags.floodedBackOut = router->FloodLSA(currentLSA, areaID, intf, neighbor);
00180                if (!ackFlags.noLSAInstanceInDatabase){
00181                   AnsaOspf6::LsaKeyType6 lsaKey;
00182 
00183                   lsaKey.linkStateID = lsaInDatabase->getHeader().getLinkStateID();
00184                   lsaKey.advertisingRouter = lsaInDatabase->getHeader().getAdvertisingRouter();
00185 
00186                   router->RemoveFromAllRetransmissionLists(lsaKey);
00187                }
00188                rebuildRoutingTable |= router->InstallLSA(currentLSA, areaID);
00189 
00190                EV << "    (update installed)\n";
00191 
00192                AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID());
00193 
00194                // TODO: verify
00195                if (currentLSA->getHeader().getAdvertisingRouter() == router->GetRouterID()){
00196 
00197                   if (ackFlags.noLSAInstanceInDatabase){
00198                      currentLSA->getHeader().setLsAge(MAX_AGE);
00199                      router->FloodLSA(currentLSA, areaID);
00200                   }else{
00201                      if (ackFlags.lsaIsNewer){
00202                         long sequenceNumber = currentLSA->getHeader().getLsSequenceNumber();
00203                         if (sequenceNumber == MAX_SEQUENCE_NUMBER){
00204                            lsaInDatabase->getHeader().setLsAge(MAX_AGE);
00205                            router->FloodLSA(lsaInDatabase, areaID);
00206                         }else{
00207                            lsaInDatabase->getHeader().setLsSequenceNumber(sequenceNumber + 1);
00208                            router->FloodLSA(lsaInDatabase, areaID);
00209                         }
00210                      }
00211                   }
00212                }
00213                continue;
00214             }
00215 
00216 
00217             if (neighbor->IsLSAOnRequestList(lsaKey)){
00218                neighbor->ProcessEvent(AnsaOspf6::Neighbor::BadLinkStateRequest);
00219                break;
00220             }
00221 
00222             if (ackFlags.lsaIsDuplicate){
00223                if (neighbor->IsLSAOnRetransmissionList(lsaKey)){
00224                   neighbor->RemoveFromRetransmissionList(lsaKey);
00225                   ackFlags.impliedAcknowledgement = true;
00226                }
00227                AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID());
00228                continue;
00229             }
00230 
00231             if (  (lsaInDatabase->getHeader().getLsAge() == MAX_AGE) &&
00232                   (lsaInDatabase->getHeader().getLsSequenceNumber() == MAX_SEQUENCE_NUMBER)){
00233                continue;
00234             }
00235 
00236             if (!neighbor->IsOnTransmittedLSAList(lsaKey)){
00237                OspfLinkStateUpdatePacket6* updatePacket = intf->CreateUpdatePacket(lsaInDatabase);
00238                if (updatePacket != NULL){
00239                   int ttl = (intf->GetType() == AnsaOspf6::Interface::Virtual) ? VIRTUAL_LINK_TTL : 1;
00240 
00241                   if (intf->GetType() == AnsaOspf6::Interface::Broadcast){
00242                      if (  (intf->GetState() == AnsaOspf6::Interface::DesignatedRouterState) ||
00243                            (intf->GetState() == AnsaOspf6::Interface::BackupState) ||
00244                            (intf->GetDesignatedRouter() == AnsaOspf6::NullDesignatedRouterID)){
00245                         router->GetMessageHandler()->SendPacket(updatePacket, AnsaOspf6::AllSPFRouters, intf->GetIfIndex(), ttl);
00246                      }else{
00247                         router->GetMessageHandler()->SendPacket(updatePacket, AnsaOspf6::AllDRouters, intf->GetIfIndex(), ttl);
00248                      }
00249                   }else{
00250                      if (intf->GetType() == AnsaOspf6::Interface::PointToPoint){
00251                         router->GetMessageHandler()->SendPacket(updatePacket, AnsaOspf6::AllSPFRouters, intf->GetIfIndex(), ttl);
00252                      }else{
00253                         router->GetMessageHandler()->SendPacket(updatePacket, neighbor->GetAddress(), intf->GetIfIndex(), ttl);
00254                      }
00255                   }
00256                }
00257             }
00258 
00259          } // for each LSA of a type
00260 
00261          currentType = static_cast<LsaType6> (currentType + 1);
00262 
00263       } // for each LSA type
00264    }
00265 
00266    if (rebuildRoutingTable){
00267       router->RebuildRoutingTable();
00268    }
00269 }
00270 
00271 void AnsaOspf6::LinkStateUpdateHandler::AcknowledgeLSA(OspfLsaHeader6& lsaHeader,
00272       AnsaOspf6::Interface* intf,
00273       AnsaOspf6::LinkStateUpdateHandler::AcknowledgementFlags acknowledgementFlags,
00274       AnsaOspf6::RouterID lsaSource){
00275 
00276    bool sendDirectAcknowledgment = false;
00277 
00278    if (!acknowledgementFlags.floodedBackOut){
00279       if (intf->GetState() == AnsaOspf6::Interface::BackupState){
00280          if ((acknowledgementFlags.lsaIsNewer
00281                && (lsaSource == intf->GetDesignatedRouter()))
00282                || (acknowledgementFlags.lsaIsDuplicate
00283                      && acknowledgementFlags.impliedAcknowledgement)){
00284             intf->AddDelayedAcknowledgement(lsaHeader);
00285          }else{
00286             if ((acknowledgementFlags.lsaIsDuplicate
00287                   && !acknowledgementFlags.impliedAcknowledgement)
00288                   || (acknowledgementFlags.lsaReachedMaxAge
00289                         && acknowledgementFlags.noLSAInstanceInDatabase
00290                         && acknowledgementFlags.anyNeighborInExchangeOrLoadingState)){
00291                sendDirectAcknowledgment = true;
00292             }
00293          }
00294       }else{
00295          if (acknowledgementFlags.lsaIsNewer){
00296             intf->AddDelayedAcknowledgement(lsaHeader);
00297          }else{
00298             if ((acknowledgementFlags.lsaIsDuplicate
00299                   && !acknowledgementFlags.impliedAcknowledgement)
00300                   || (acknowledgementFlags.lsaReachedMaxAge
00301                         && acknowledgementFlags.noLSAInstanceInDatabase
00302                         && acknowledgementFlags.anyNeighborInExchangeOrLoadingState)){
00303                sendDirectAcknowledgment = true;
00304             }
00305          }
00306       }
00307    }
00308 
00309    if (sendDirectAcknowledgment){
00310       OspfLinkStateAcknowledgementPacket6* ackPacket = new OspfLinkStateAcknowledgementPacket6;
00311 
00312       ackPacket->setType(LinkStateAcknowledgementPacket);
00313       ackPacket->setRouterID(router->GetRouterID());
00314       ackPacket->setAreaID(intf->GetArea()->GetAreaID());
00315 
00316       ackPacket->setLsaHeadersArraySize(1);
00317       ackPacket->setLsaHeaders(0, lsaHeader);
00318 
00319       int ttl = (intf->GetType() == AnsaOspf6::Interface::Virtual) ? VIRTUAL_LINK_TTL : 1;
00320 
00321       if (intf->GetType() == AnsaOspf6::Interface::Broadcast){
00322          if ((intf->GetState() == AnsaOspf6::Interface::DesignatedRouterState) || (intf->GetState()
00323                == AnsaOspf6::Interface::BackupState) || (intf->GetDesignatedRouter()
00324                == AnsaOspf6::NullDesignatedRouterID)){
00325             router->GetMessageHandler()->SendPacket(ackPacket, AnsaOspf6::AllSPFRouters, intf->GetIfIndex(), ttl);
00326          }else{
00327             router->GetMessageHandler()->SendPacket(ackPacket, AnsaOspf6::AllDRouters, intf->GetIfIndex(), ttl);
00328          }
00329       }else{
00330          if (intf->GetType() == AnsaOspf6::Interface::PointToPoint){
00331             router->GetMessageHandler()->SendPacket(ackPacket, AnsaOspf6::AllSPFRouters, intf->GetIfIndex(), ttl);
00332          }else{
00333             router->GetMessageHandler()->SendPacket(ackPacket, intf->GetNeighborByID(lsaSource)->GetAddress(), intf->GetIfIndex(), ttl);
00334          }
00335       }
00336    }
00337 }