{
router->GetMessageHandler()->PrintEvent("Link State Update packet received", intf, neighbor);
OSPFLinkStateUpdatePacket* lsUpdatePacket = check_and_cast<OSPFLinkStateUpdatePacket*> (packet);
bool rebuildRoutingTable = false;
if (neighbor->GetState() >= OSPF::Neighbor::ExchangeState) {
OSPF::AreaID areaID = lsUpdatePacket->getAreaID().getInt();
OSPF::Area* area = router->GetArea(areaID);
LSAType currentType = RouterLSAType;
unsigned int currentLSAIndex = 0;
EV << " Processing packet contents:\n";
while (currentType <= ASExternalLSAType) {
unsigned int lsaCount = 0;
switch (currentType) {
case RouterLSAType:
lsaCount = lsUpdatePacket->getRouterLSAsArraySize();
break;
case NetworkLSAType:
lsaCount = lsUpdatePacket->getNetworkLSAsArraySize();
break;
case SummaryLSA_NetworksType:
case SummaryLSA_ASBoundaryRoutersType:
lsaCount = lsUpdatePacket->getSummaryLSAsArraySize();
break;
case ASExternalLSAType:
lsaCount = lsUpdatePacket->getAsExternalLSAsArraySize();
break;
default: break;
}
for (unsigned int i = 0; i < lsaCount; i++) {
OSPFLSA* currentLSA;
switch (currentType) {
case RouterLSAType:
currentLSA = (&(lsUpdatePacket->getRouterLSAs(i)));
break;
case NetworkLSAType:
currentLSA = (&(lsUpdatePacket->getNetworkLSAs(i)));
break;
case SummaryLSA_NetworksType:
case SummaryLSA_ASBoundaryRoutersType:
currentLSA = (&(lsUpdatePacket->getSummaryLSAs(i)));
break;
case ASExternalLSAType:
currentLSA = (&(lsUpdatePacket->getAsExternalLSAs(i)));
break;
default: break;
}
if (!ValidateLSChecksum(currentLSA)) {
continue;
}
LSAType lsaType = static_cast<LSAType> (currentLSA->getHeader().getLsType());
if ((lsaType != RouterLSAType) &&
(lsaType != NetworkLSAType) &&
(lsaType != SummaryLSA_NetworksType) &&
(lsaType != SummaryLSA_ASBoundaryRoutersType) &&
(lsaType != ASExternalLSAType))
{
continue;
}
LSAProcessingMarker marker(currentLSAIndex++);
EV << " ";
PrintLSAHeader(currentLSA->getHeader(), ev.getOStream());
EV << "\n";
if ((lsaType == ASExternalLSAType) && (!area->GetExternalRoutingCapability())) {
continue;
}
OSPF::LSAKeyType lsaKey;
lsaKey.linkStateID = currentLSA->getHeader().getLinkStateID();
lsaKey.advertisingRouter = currentLSA->getHeader().getAdvertisingRouter().getInt();
OSPFLSA* lsaInDatabase = router->FindLSA(lsaType, lsaKey, areaID);
unsigned short lsAge = currentLSA->getHeader().getLsAge();
AcknowledgementFlags ackFlags;
ackFlags.floodedBackOut = false;
ackFlags.lsaIsNewer = false;
ackFlags.lsaIsDuplicate = false;
ackFlags.impliedAcknowledgement = false;
ackFlags.lsaReachedMaxAge = (lsAge == MAX_AGE);
ackFlags.noLSAInstanceInDatabase = (lsaInDatabase == NULL);
ackFlags.anyNeighborInExchangeOrLoadingState = router->HasAnyNeighborInStates(OSPF::Neighbor::ExchangeState | OSPF::Neighbor::LoadingState);
if ((ackFlags.lsaReachedMaxAge) && (ackFlags.noLSAInstanceInDatabase) && (!ackFlags.anyNeighborInExchangeOrLoadingState)) {
if (intf->GetType() == OSPF::Interface::Broadcast) {
if ((intf->GetState() == OSPF::Interface::DesignatedRouterState) ||
(intf->GetState() == OSPF::Interface::BackupState) ||
(intf->GetDesignatedRouter() == OSPF::NullDesignatedRouterID))
{
intf->SendLSAcknowledgement(&(currentLSA->getHeader()), OSPF::AllSPFRouters);
} else {
intf->SendLSAcknowledgement(&(currentLSA->getHeader()), OSPF::AllDRouters);
}
} else {
if (intf->GetType() == OSPF::Interface::PointToPoint) {
intf->SendLSAcknowledgement(&(currentLSA->getHeader()), OSPF::AllSPFRouters);
} else {
intf->SendLSAcknowledgement(&(currentLSA->getHeader()), neighbor->GetAddress());
}
}
continue;
}
if (!ackFlags.noLSAInstanceInDatabase) {
ackFlags.lsaIsNewer = (lsaInDatabase->getHeader() < currentLSA->getHeader());
ackFlags.lsaIsDuplicate = (operator== (lsaInDatabase->getHeader(), currentLSA->getHeader()));
}
if ((ackFlags.noLSAInstanceInDatabase) || (ackFlags.lsaIsNewer)) {
LSATrackingInfo* info = (!ackFlags.noLSAInstanceInDatabase) ? dynamic_cast<LSATrackingInfo*> (lsaInDatabase) : NULL;
if ((!ackFlags.noLSAInstanceInDatabase) &&
(info != NULL) &&
(info->GetSource() == LSATrackingInfo::Flooded) &&
(info->GetInstallTime() < MIN_LS_ARRIVAL))
{
continue;
}
ackFlags.floodedBackOut = router->FloodLSA(currentLSA, areaID, intf, neighbor);
if (!ackFlags.noLSAInstanceInDatabase) {
OSPF::LSAKeyType lsaKey;
lsaKey.linkStateID = lsaInDatabase->getHeader().getLinkStateID();
lsaKey.advertisingRouter = lsaInDatabase->getHeader().getAdvertisingRouter().getInt();
router->RemoveFromAllRetransmissionLists(lsaKey);
}
rebuildRoutingTable |= router->InstallLSA(currentLSA, areaID);
EV << " (update installed)\n";
AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID().getInt());
if ((currentLSA->getHeader().getAdvertisingRouter().getInt() == router->GetRouterID()) ||
((lsaType == NetworkLSAType) &&
(router->IsLocalAddress(IPv4AddressFromULong(currentLSA->getHeader().getLinkStateID())))))
{
if (ackFlags.noLSAInstanceInDatabase) {
currentLSA->getHeader().setLsAge(MAX_AGE);
router->FloodLSA(currentLSA, areaID);
} else {
if (ackFlags.lsaIsNewer) {
long sequenceNumber = currentLSA->getHeader().getLsSequenceNumber();
if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
lsaInDatabase->getHeader().setLsAge(MAX_AGE);
router->FloodLSA(lsaInDatabase, areaID);
} else {
lsaInDatabase->getHeader().setLsSequenceNumber(sequenceNumber + 1);
router->FloodLSA(lsaInDatabase, areaID);
}
}
}
}
continue;
}
if (neighbor->IsLSAOnRequestList(lsaKey)) {
neighbor->ProcessEvent(OSPF::Neighbor::BadLinkStateRequest);
break;
}
if (ackFlags.lsaIsDuplicate) {
if (neighbor->IsLSAOnRetransmissionList(lsaKey)) {
neighbor->RemoveFromRetransmissionList(lsaKey);
ackFlags.impliedAcknowledgement = true;
}
AcknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID().getInt());
continue;
}
if ((lsaInDatabase->getHeader().getLsAge() == MAX_AGE) &&
(lsaInDatabase->getHeader().getLsSequenceNumber() == MAX_SEQUENCE_NUMBER))
{
continue;
}
if (!neighbor->IsOnTransmittedLSAList(lsaKey)) {
OSPFLinkStateUpdatePacket* updatePacket = intf->CreateUpdatePacket(lsaInDatabase);
if (updatePacket != NULL) {
int ttl = (intf->GetType() == OSPF::Interface::Virtual) ? VIRTUAL_LINK_TTL : 1;
if (intf->GetType() == OSPF::Interface::Broadcast) {
if ((intf->GetState() == OSPF::Interface::DesignatedRouterState) ||
(intf->GetState() == OSPF::Interface::BackupState) ||
(intf->GetDesignatedRouter() == OSPF::NullDesignatedRouterID))
{
router->GetMessageHandler()->SendPacket(updatePacket, OSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
} else {
router->GetMessageHandler()->SendPacket(updatePacket, OSPF::AllDRouters, intf->GetIfIndex(), ttl);
}
} else {
if (intf->GetType() == OSPF::Interface::PointToPoint) {
router->GetMessageHandler()->SendPacket(updatePacket, OSPF::AllSPFRouters, intf->GetIfIndex(), ttl);
} else {
router->GetMessageHandler()->SendPacket(updatePacket, neighbor->GetAddress(), intf->GetIfIndex(), ttl);
}
}
}
}
}
currentType = static_cast<LSAType> (currentType + 1);
if (currentType == SummaryLSA_NetworksType) {
currentType = static_cast<LSAType> (currentType + 1);
}
}
}
if (rebuildRoutingTable) {
router->RebuildRoutingTable();
}
}