INET Framework for OMNeT++/OMNEST
inet::ospfv2::LinkStateUpdateHandler Class Reference

#include <LinkStateUpdateHandler.h>

Inheritance diagram for inet::ospfv2::LinkStateUpdateHandler:
inet::ospfv2::IMessageHandler

Classes

struct  AcknowledgementFlags
 

Public Member Functions

 LinkStateUpdateHandler (Router *containingRouter)
 
void processPacket (Packet *packet, Ospfv2Interface *intf, Neighbor *neighbor) override
 
- Public Member Functions inherited from inet::ospfv2::IMessageHandler
 IMessageHandler (Router *containingRouter)
 
virtual ~IMessageHandler ()
 

Private Member Functions

bool validateLSChecksum (const Ospfv2Lsa *lsa)
 
void acknowledgeLSA (const Ospfv2LsaHeader &lsaHeader, Ospfv2Interface *intf, AcknowledgementFlags acknowledgementFlags, RouterId lsaSource)
 

Additional Inherited Members

- Protected Attributes inherited from inet::ospfv2::IMessageHandler
Routerrouter
 

Constructor & Destructor Documentation

◆ LinkStateUpdateHandler()

inet::ospfv2::LinkStateUpdateHandler::LinkStateUpdateHandler ( Router containingRouter)
31  :
32  IMessageHandler(containingRouter)
33 {
34 }

Member Function Documentation

◆ acknowledgeLSA()

void inet::ospfv2::LinkStateUpdateHandler::acknowledgeLSA ( const Ospfv2LsaHeader lsaHeader,
Ospfv2Interface intf,
LinkStateUpdateHandler::AcknowledgementFlags  acknowledgementFlags,
RouterId  lsaSource 
)
private
223 {
224  bool sendDirectAcknowledgment = false;
225 
226  if (!acknowledgementFlags.floodedBackOut) {
227  if (intf->getState() == Ospfv2Interface::BACKUP_STATE) {
228  if ((acknowledgementFlags.lsaIsNewer && (lsaSource == intf->getDesignatedRouter().routerID)) ||
229  (acknowledgementFlags.lsaIsDuplicate && acknowledgementFlags.impliedAcknowledgement))
230  {
231  intf->addDelayedAcknowledgement(lsaHeader);
232  }
233  else {
234  if ((acknowledgementFlags.lsaIsDuplicate && !acknowledgementFlags.impliedAcknowledgement) ||
235  (acknowledgementFlags.lsaReachedMaxAge &&
236  acknowledgementFlags.noLSAInstanceInDatabase &&
237  acknowledgementFlags.anyNeighborInExchangeOrLoadingState))
238  {
239  sendDirectAcknowledgment = true;
240  }
241  }
242  }
243  else {
244  if (acknowledgementFlags.lsaIsNewer) {
245  intf->addDelayedAcknowledgement(lsaHeader);
246  }
247  else {
248  if ((acknowledgementFlags.lsaIsDuplicate && !acknowledgementFlags.impliedAcknowledgement) ||
249  (acknowledgementFlags.lsaReachedMaxAge &&
250  acknowledgementFlags.noLSAInstanceInDatabase &&
251  acknowledgementFlags.anyNeighborInExchangeOrLoadingState))
252  {
253  sendDirectAcknowledgment = true;
254  }
255  }
256  }
257  }
258 
259  if (sendDirectAcknowledgment) {
260  const auto& ackPacket = makeShared<Ospfv2LinkStateAcknowledgementPacket>();
261 
262  ackPacket->setType(LINKSTATE_ACKNOWLEDGEMENT_PACKET);
263  ackPacket->setRouterID(Ipv4Address(router->getRouterID()));
264  ackPacket->setAreaID(Ipv4Address(intf->getArea()->getAreaID()));
265  ackPacket->setAuthenticationType(intf->getAuthenticationType());
266 
267  ackPacket->setLsaHeadersArraySize(1);
268  ackPacket->setLsaHeaders(0, lsaHeader);
269 
270  ackPacket->setPacketLengthField(B(OSPFv2_HEADER_LENGTH + OSPFv2_LSA_HEADER_LENGTH).get());
271  ackPacket->setChunkLength(B(ackPacket->getPacketLengthField()));
272 
273  AuthenticationKeyType authKey = intf->getAuthenticationKey();
274  for (int i = 0; i < 8; i++) {
275  ackPacket->setAuthentication(i, authKey.bytes[i]);
276  }
277 
278  setOspfCrc(ackPacket, intf->getCrcMode());
279 
280  Packet *pk = new Packet();
281  pk->insertAtBack(ackPacket);
282 
283  int ttl = (intf->getType() == Ospfv2Interface::VIRTUAL) ? VIRTUAL_LINK_TTL : 1;
284 
285  if (intf->getType() == Ospfv2Interface::BROADCAST) {
286  if ((intf->getState() == Ospfv2Interface::DESIGNATED_ROUTER_STATE) ||
287  (intf->getState() == Ospfv2Interface::BACKUP_STATE) ||
288  (intf->getDesignatedRouter() == NULL_DESIGNATEDROUTERID))
289  {
291  }
292  else {
294  }
295  }
296  else {
297  if (intf->getType() == Ospfv2Interface::POINTTOPOINT) {
299  }
300  else {
301  Neighbor *neighbor = intf->getNeighborById(lsaSource);
302  ASSERT(neighbor);
303  router->getMessageHandler()->sendPacket(pk, neighbor->getAddress(), intf, ttl);
304  }
305  }
306  }
307 }

Referenced by processPacket().

◆ processPacket()

void inet::ospfv2::LinkStateUpdateHandler::processPacket ( Packet packet,
Ospfv2Interface intf,
Neighbor neighbor 
)
overridevirtual
See also
RFC2328 Section 13.

Implements inet::ospfv2::IMessageHandler.

40 {
41  router->getMessageHandler()->printEvent("Link State update packet received", intf, neighbor);
42 
43  const auto& lsUpdatePacket = packet->peekAtFront<Ospfv2LinkStateUpdatePacket>();
44  bool shouldRebuildRoutingTable = false;
45 
46  if (neighbor->getState() >= Neighbor::EXCHANGE_STATE) {
47  AreaId areaID = lsUpdatePacket->getAreaID();
48  Ospfv2Area *area = router->getAreaByID(areaID);
49 
50  EV_INFO << " Processing packet contents:\n";
51 
52  for (unsigned int i = 0; i < lsUpdatePacket->getOspfLSAsArraySize(); i++) {
53  const Ospfv2Lsa *currentLSA = lsUpdatePacket->getOspfLSAs(i);
54 
55  if (!validateLSChecksum(currentLSA)) {
56  continue;
57  }
58 
59  Ospfv2LsaType lsaType = static_cast<Ospfv2LsaType>(currentLSA->getHeader().getLsType());
60  if ((lsaType != ROUTERLSA_TYPE) &&
61  (lsaType != NETWORKLSA_TYPE) &&
62  (lsaType != SUMMARYLSA_NETWORKS_TYPE) &&
63  (lsaType != SUMMARYLSA_ASBOUNDARYROUTERS_TYPE) &&
64  (lsaType != AS_EXTERNAL_LSA_TYPE))
65  {
66  continue;
67  }
68 
69  LsaProcessingMarker marker(i);
70  EV_DETAIL << " " << currentLSA->getHeader() << "\n";
71 
72  // FIXME area maybe nullptr
73  if ((lsaType == AS_EXTERNAL_LSA_TYPE) && !(area != nullptr && area->getExternalRoutingCapability())) {
74  continue;
75  }
76  LsaKeyType lsaKey;
77 
78  lsaKey.linkStateID = currentLSA->getHeader().getLinkStateID();
79  lsaKey.advertisingRouter = currentLSA->getHeader().getAdvertisingRouter();
80 
81  Ospfv2Lsa *lsaInDatabase = router->findLSA(lsaType, lsaKey, areaID);
82  unsigned short lsAge = currentLSA->getHeader().getLsAge();
83  AcknowledgementFlags ackFlags;
84 
85  ackFlags.floodedBackOut = false;
86  ackFlags.lsaIsNewer = false;
87  ackFlags.lsaIsDuplicate = false;
88  ackFlags.impliedAcknowledgement = false;
89  ackFlags.lsaReachedMaxAge = (lsAge == MAX_AGE);
90  ackFlags.noLSAInstanceInDatabase = (lsaInDatabase == nullptr);
91  ackFlags.anyNeighborInExchangeOrLoadingState = router->hasAnyNeighborInStates(Neighbor::EXCHANGE_STATE | Neighbor::LOADING_STATE);
92 
93  if ((ackFlags.lsaReachedMaxAge) && (ackFlags.noLSAInstanceInDatabase) && (!ackFlags.anyNeighborInExchangeOrLoadingState)) {
94  if (intf->getType() == Ospfv2Interface::BROADCAST) {
95  if ((intf->getState() == Ospfv2Interface::DESIGNATED_ROUTER_STATE) ||
96  (intf->getState() == Ospfv2Interface::BACKUP_STATE) ||
97  (intf->getDesignatedRouter() == NULL_DESIGNATEDROUTERID))
98  {
99  intf->sendLsAcknowledgement(&(currentLSA->getHeader()), Ipv4Address::ALL_OSPF_ROUTERS_MCAST);
100  }
101  else {
102  intf->sendLsAcknowledgement(&(currentLSA->getHeader()), Ipv4Address::ALL_OSPF_DESIGNATED_ROUTERS_MCAST);
103  }
104  }
105  else {
106  if (intf->getType() == Ospfv2Interface::POINTTOPOINT) {
107  intf->sendLsAcknowledgement(&(currentLSA->getHeader()), Ipv4Address::ALL_OSPF_ROUTERS_MCAST);
108  }
109  else {
110  intf->sendLsAcknowledgement(&(currentLSA->getHeader()), neighbor->getAddress());
111  }
112  }
113  continue;
114  }
115 
116  if (!ackFlags.noLSAInstanceInDatabase) {
117  // operator< and operator== on OSPFLSAHeaders determines which one is newer(less means older)
118  ackFlags.lsaIsNewer = (lsaInDatabase->getHeader() < currentLSA->getHeader());
119  ackFlags.lsaIsDuplicate = (operator==(lsaInDatabase->getHeader(), currentLSA->getHeader()));
120  }
121  if ((ackFlags.noLSAInstanceInDatabase) || (ackFlags.lsaIsNewer)) {
122  LsaTrackingInfo *info = (!ackFlags.noLSAInstanceInDatabase) ? dynamic_cast<LsaTrackingInfo *>(lsaInDatabase) : nullptr;
123  if ((!ackFlags.noLSAInstanceInDatabase) &&
124  (info != nullptr) &&
125  (info->getSource() == LsaTrackingInfo::FLOODED) &&
126  (info->getInstallTime() < MIN_LS_ARRIVAL))
127  {
128  continue;
129  }
130  ackFlags.floodedBackOut = router->floodLSA(currentLSA, areaID, intf, neighbor);
131  if (!ackFlags.noLSAInstanceInDatabase) {
132  LsaKeyType lsaKey;
133 
134  lsaKey.linkStateID = lsaInDatabase->getHeader().getLinkStateID();
135  lsaKey.advertisingRouter = lsaInDatabase->getHeader().getAdvertisingRouter();
136 
138  }
139  shouldRebuildRoutingTable |= router->installLSA(currentLSA, areaID);
140 
141  EV_INFO << " (update installed)\n";
142 
143  acknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID());
144  if ((currentLSA->getHeader().getAdvertisingRouter() == router->getRouterID()) ||
145  ((lsaType == NETWORKLSA_TYPE) &&
146  (router->isLocalAddress(currentLSA->getHeader().getLinkStateID()))))
147  {
148  if (ackFlags.noLSAInstanceInDatabase) {
149  auto lsaCopy = currentLSA->dup();
150  lsaCopy->getHeaderForUpdate().setLsAge(MAX_AGE);
151  router->floodLSA(lsaCopy, areaID);
152  }
153  else {
154  if (ackFlags.lsaIsNewer) {
155  long sequenceNumber = currentLSA->getHeader().getLsSequenceNumber();
156  if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
157  lsaInDatabase->getHeaderForUpdate().setLsAge(MAX_AGE);
158  router->floodLSA(lsaInDatabase, areaID);
159  }
160  else {
161  lsaInDatabase->getHeaderForUpdate().setLsSequenceNumber(sequenceNumber + 1);
162  router->floodLSA(lsaInDatabase, areaID);
163  }
164  }
165  }
166  }
167  continue;
168  }
169  if (neighbor->isLSAOnRequestList(lsaKey)) {
170  neighbor->processEvent(Neighbor::BAD_LINK_STATE_REQUEST);
171  break;
172  }
173  if (ackFlags.lsaIsDuplicate) {
174  if (neighbor->isLinkStateRequestListEmpty(lsaKey)) {
175  neighbor->removeFromRetransmissionList(lsaKey);
176  ackFlags.impliedAcknowledgement = true;
177  }
178  acknowledgeLSA(currentLSA->getHeader(), intf, ackFlags, lsUpdatePacket->getRouterID());
179  continue;
180  }
181  if ((lsaInDatabase->getHeader().getLsAge() == MAX_AGE) &&
182  (lsaInDatabase->getHeader().getLsSequenceNumber() == MAX_SEQUENCE_NUMBER))
183  {
184  continue;
185  }
186  if (!neighbor->isOnTransmittedLSAList(lsaKey)) {
187  Packet *updatePacket = intf->createUpdatePacket(lsaInDatabase);
188  if (updatePacket != nullptr) {
189  int ttl = (intf->getType() == Ospfv2Interface::VIRTUAL) ? VIRTUAL_LINK_TTL : 1;
190 
191  if (intf->getType() == Ospfv2Interface::BROADCAST) {
192  if ((intf->getState() == Ospfv2Interface::DESIGNATED_ROUTER_STATE) ||
193  (intf->getState() == Ospfv2Interface::BACKUP_STATE) ||
194  (intf->getDesignatedRouter() == NULL_DESIGNATEDROUTERID))
195  {
197  }
198  else {
200  }
201  }
202  else {
203  if (intf->getType() == Ospfv2Interface::POINTTOPOINT) {
205  }
206  else {
207  router->getMessageHandler()->sendPacket(updatePacket, neighbor->getAddress(), intf, ttl);
208  }
209  }
210  }
211  }
212  }
213  }
214 
215  if (shouldRebuildRoutingTable)
217 }

Referenced by inet::ospfv2::MessageHandler::processPacket().

◆ validateLSChecksum()

bool inet::ospfv2::LinkStateUpdateHandler::validateLSChecksum ( const Ospfv2Lsa lsa)
inlineprivate
31 { return true; } // not implemented

Referenced by processPacket().


The documentation for this class was generated from the following files:
VIRTUAL_LINK_TTL
#define VIRTUAL_LINK_TTL
Definition: Ospfv2Common.h:36
inet::ospfv2::MessageHandler::printEvent
void printEvent(const char *eventString, const Ospfv2Interface *onInterface=nullptr, const Neighbor *forNeighbor=nullptr) const
Definition: MessageHandler.cc:380
inet::ospf::LINKSTATE_ACKNOWLEDGEMENT_PACKET
@ LINKSTATE_ACKNOWLEDGEMENT_PACKET
Definition: OspfPacketBase_m.h:69
inet::ospfv2::Ospfv2Interface::POINTTOPOINT
@ POINTTOPOINT
Definition: Ospfv2Interface.h:32
inet::ospfv2::Router::removeFromAllRetransmissionLists
void removeFromAllRetransmissionLists(LsaKeyType lsaKey)
Removes all LSAs from all Neighbor's retransmission lists which are identified by the input lsaKey.
Definition: Ospfv2Router.cc:393
MAX_SEQUENCE_NUMBER
#define MAX_SEQUENCE_NUMBER
Definition: Ospfv2Common.h:34
inet::ospfv2::SUMMARYLSA_NETWORKS_TYPE
@ SUMMARYLSA_NETWORKS_TYPE
Definition: Ospfv2Packet_m.h:285
inet::ospfv2::Router::installLSA
bool installLSA(const Ospfv2Lsa *lsa, AreaId areaID=BACKBONE_AREAID)
Installs a new LSA into the Router database.
Definition: Ospfv2Router.cc:102
inet::ospfv2::Ospfv2Interface::DESIGNATED_ROUTER_STATE
@ DESIGNATED_ROUTER_STATE
Definition: Ospfv2Interface.h:58
inet::ospfv2::setOspfCrc
void setOspfCrc(const Ptr< Ospfv2Packet > &ospfPacket, CrcMode crcMode)
Definition: Ospfv2Crc.cc:17
inet::ospfv2::Ospfv2LsaType
Ospfv2LsaType
Enum generated from inet/routing/ospfv2/Ospfv2Packet.msg:78 by opp_msgtool.
Definition: Ospfv2Packet_m.h:282
inet::ospfv2::Router::getMessageHandler
MessageHandler * getMessageHandler()
Definition: Ospfv2Router.h:66
inet::ospfv2::ROUTERLSA_TYPE
@ ROUTERLSA_TYPE
Definition: Ospfv2Packet_m.h:283
MAX_AGE
#define MAX_AGE
Definition: Ospfv2Common.h:27
inet::ospfv2::LsaTrackingInfo::FLOODED
@ FLOODED
Definition: Lsa.h:55
inet::ospfv2::Router::isLocalAddress
bool isLocalAddress(Ipv4Address address) const
Returns true if the input Ipv4 address falls into any of the Router's Areas' configured Ipv4 address ...
Definition: Ospfv2Router.cc:446
inet::ospfv2::NULL_DESIGNATEDROUTERID
const DesignatedRouterId NULL_DESIGNATEDROUTERID
Definition: Ospfv2Common.h:156
inet::ospfv2::Neighbor::BAD_LINK_STATE_REQUEST
@ BAD_LINK_STATE_REQUEST
Definition: Ospfv2Neighbor.h:35
inet::ospfv2::Router::rebuildRoutingTable
void rebuildRoutingTable()
Rebuilds the routing table from scratch(based on the LSA database).
Definition: Ospfv2Router.cc:663
inet::ospfv2::SUMMARYLSA_ASBOUNDARYROUTERS_TYPE
@ SUMMARYLSA_ASBOUNDARYROUTERS_TYPE
Definition: Ospfv2Packet_m.h:286
inet::ospfv2::Router::getAreaByID
Ospfv2Area * getAreaByID(AreaId areaID)
Returns the pointer to the Area identified by the input areaID, if it's on the Area list,...
Definition: Ospfv2Router.cc:63
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::ospfv2::Router::floodLSA
bool floodLSA(const Ospfv2Lsa *lsa, AreaId areaID=BACKBONE_AREAID, Ospfv2Interface *intf=nullptr, Neighbor *neighbor=nullptr)
Floods out the input lsa on a set of Interfaces.
Definition: Ospfv2Router.cc:408
inet::ospfv2::Ospfv2Interface::VIRTUAL
@ VIRTUAL
Definition: Ospfv2Interface.h:36
inet::ospfv2::AS_EXTERNAL_LSA_TYPE
@ AS_EXTERNAL_LSA_TYPE
Definition: Ospfv2Packet_m.h:287
inet::Ipv4Address::ALL_OSPF_DESIGNATED_ROUTERS_MCAST
static const Ipv4Address ALL_OSPF_DESIGNATED_ROUTERS_MCAST
224.0.0.6 All OSPF Designated Routers
Definition: Ipv4Address.h:100
inet::ospfv2::OSPFv2_LSA_HEADER_LENGTH
const B OSPFv2_LSA_HEADER_LENGTH
Definition: Ospfv2Common.h:40
inet::ospfv2::OSPFv2_HEADER_LENGTH
const B OSPFv2_HEADER_LENGTH
Definition: Ospfv2Common.h:39
inet::ospfv2::MessageHandler::sendPacket
void sendPacket(Packet *packet, Ipv4Address destination, Ospfv2Interface *outputIf, short ttl=1)
Definition: MessageHandler.cc:303
inet::ospfv2::Neighbor::EXCHANGE_STATE
@ EXCHANGE_STATE
Definition: Ospfv2Neighbor.h:55
inet::ospfv2::Router::findLSA
Ospfv2Lsa * findLSA(Ospfv2LsaType lsaType, LsaKeyType lsaKey, AreaId areaID)
Find the LSA identified by the input lsaKey in the database.
Definition: Ospfv2Router.cc:226
inet::ospfv2::IMessageHandler::IMessageHandler
IMessageHandler(Router *containingRouter)
Definition: IMessageHandler.h:27
inet::ospfv2::Router::getRouterID
RouterId getRouterID() const
Definition: Ospfv2Router.h:60
inet::ospfv2::Ospfv2LsaHeader::getLsAge
virtual unsigned short getLsAge() const
inet::ospfv2::Router::hasAnyNeighborInStates
bool hasAnyNeighborInStates(int states) const
Returns true if any Neighbor on any Interface in any of the Router's Areas is in any of the input sta...
Definition: Ospfv2Router.cc:384
inet::ospfv2::operator==
bool operator==(Neighbor::DdPacketId leftID, Neighbor::DdPacketId rightID)
Definition: Ospfv2Neighbor.h:189
inet::ospfv2::NETWORKLSA_TYPE
@ NETWORKLSA_TYPE
Definition: Ospfv2Packet_m.h:284
MIN_LS_ARRIVAL
#define MIN_LS_ARRIVAL
Definition: Ospfv2Common.h:26
inet::ospfv2::Neighbor::LOADING_STATE
@ LOADING_STATE
Definition: Ospfv2Neighbor.h:56
inet::ospfv2::Ospfv2Interface::BROADCAST
@ BROADCAST
Definition: Ospfv2Interface.h:33
inet::ospfv2::AreaId
Ipv4Address AreaId
Definition: Ospfv2Common.h:130
inet::ospfv2::IMessageHandler::router
Router * router
Definition: IMessageHandler.h:24
inet::ospfv2::Ospfv2Lsa::getHeader
virtual const Ospfv2LsaHeader & getHeader() const
inet::ospfv2::Ospfv2Interface::BACKUP_STATE
@ BACKUP_STATE
Definition: Ospfv2Interface.h:57
inet::Ipv4Address::ALL_OSPF_ROUTERS_MCAST
static const Ipv4Address ALL_OSPF_ROUTERS_MCAST
224.0.0.5 All OSPF routers (DR Others)
Definition: Ipv4Address.h:99