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

#include <HelloHandler.h>

Inheritance diagram for inet::ospfv2::HelloHandler:
inet::ospfv2::IMessageHandler

Public Member Functions

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

Additional Inherited Members

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

Constructor & Destructor Documentation

◆ HelloHandler()

inet::ospfv2::HelloHandler::HelloHandler ( Router containingRouter)
18  :
19  IMessageHandler(containingRouter)
20 {
21 }

Member Function Documentation

◆ processPacket()

void inet::ospfv2::HelloHandler::processPacket ( Packet packet,
Ospfv2Interface intf,
Neighbor unused = nullptr 
)
overridevirtual

Implements inet::ospfv2::IMessageHandler.

24 {
25  const auto& helloPacket = packet->peekAtFront<Ospfv2HelloPacket>();
26  bool shouldRebuildRoutingTable = false;
27 
28  /* The values of the Network Mask, HelloInterval,
29  and RouterDeadInterval fields in the received Hello packet must
30  be checked against the values configured for the receiving
31  interface. Any mismatch causes processing to stop and the
32  packet to be dropped.
33  */
34  if ((intf->getHelloInterval() == helloPacket->getHelloInterval()) &&
35  (intf->getRouterDeadInterval() == helloPacket->getRouterDeadInterval()))
36  {
37  Ospfv2Interface::Ospfv2InterfaceType interfaceType = intf->getType();
38  /* There is one exception to the above rule: on point-to-point
39  networks and on virtual links, the Network Mask in the received
40  Hello Packet should be ignored.
41  */
42  if (!((interfaceType != Ospfv2Interface::POINTTOPOINT) &&
43  (interfaceType != Ospfv2Interface::VIRTUAL) &&
44  (intf->getAddressRange().mask != helloPacket->getNetworkMask())
45  )
46  )
47  {
48  /* The setting of the E-bit found in the Hello Packet's Options field must match this area's
49  ExternalRoutingCapability.
50  */
51  if (intf->getArea()->getExternalRoutingCapability() == helloPacket->getOptions().E_ExternalRoutingCapability) {
52  Ipv4Address srcAddress = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv4();
53  bool neighborChanged = false;
54  bool neighborsDRStateChanged = false;
55  bool drChanged = false;
56  bool backupSeen = false;
57  Neighbor *neighbor;
58 
59  /* If the receiving interface connects to a broadcast, Point-to-
60  MultiPoint or NBMA network the source is identified by the IP
61  source address found in the Hello's IP header.
62  */
63  if ((interfaceType == Ospfv2Interface::BROADCAST) ||
64  (interfaceType == Ospfv2Interface::POINTTOMULTIPOINT) ||
65  (interfaceType == Ospfv2Interface::NBMA))
66  {
67  neighbor = intf->getNeighborByAddress(srcAddress);
68  }
69  else {
70  /* If the receiving interface connects to a point-to-point link or a virtual link,
71  the source is identified by the Router ID found in the Hello's OSPF packet header.
72  */
73  neighbor = intf->getNeighborById(helloPacket->getRouterID());
74  }
75 
76  if (neighbor != nullptr) {
77  router->getMessageHandler()->printEvent("Hello packet received", intf, neighbor);
78 
79  Ipv4Address designatedAddress = neighbor->getDesignatedRouter().ipInterfaceAddress;
80  Ipv4Address backupAddress = neighbor->getBackupDesignatedRouter().ipInterfaceAddress;
81  char newPriority = helloPacket->getRouterPriority();
82  Ipv4Address source = srcAddress;
83  Ipv4Address newDesignatedRouter = helloPacket->getDesignatedRouter();
84  Ipv4Address newBackupRouter = helloPacket->getBackupDesignatedRouter();
85  DesignatedRouterId dRouterID;
86 
87  if ((interfaceType == Ospfv2Interface::VIRTUAL) &&
88  (neighbor->getState() == Neighbor::DOWN_STATE))
89  {
90  neighbor->setPriority(helloPacket->getRouterPriority());
91  neighbor->setRouterDeadInterval(helloPacket->getRouterDeadInterval());
92  }
93 
94  /* If a change in the neighbor's Router Priority field
95  was noted, the receiving interface's state machine is
96  scheduled with the event NEIGHBOR_CHANGE.
97  */
98  if (neighbor->getPriority() != newPriority) {
99  neighborChanged = true;
100  }
101 
102  /* If the neighbor is both declaring itself to be Designated
103  Router(Hello Packet's Designated Router field = Neighbor IP
104  address) and the Backup Designated Router field in the
105  packet is equal to 0.0.0.0 and the receiving interface is in
106  state Waiting, the receiving interface's state machine is
107  scheduled with the event BACKUP_SEEN.
108  */
109  if ((newDesignatedRouter == source) &&
110  (newBackupRouter == NULL_IPV4ADDRESS) &&
111  (intf->getState() == Ospfv2Interface::WAITING_STATE))
112  {
113  backupSeen = true;
114  }
115  else {
116  /* Otherwise, if the neighbor is declaring itself to be Designated Router and it
117  had not previously, or the neighbor is not declaring itself
118  Designated Router where it had previously, the receiving
119  interface's state machine is scheduled with the event
120  NEIGHBOR_CHANGE.
121  */
122  if (((newDesignatedRouter == source) &&
123  (newDesignatedRouter != designatedAddress)) ||
124  ((newDesignatedRouter != source) &&
125  (source == designatedAddress)))
126  {
127  neighborChanged = true;
128  neighborsDRStateChanged = true;
129  }
130  }
131 
132  /* If the neighbor is declaring itself to be Backup Designated
133  Router(Hello Packet's Backup Designated Router field =
134  Neighbor IP address) and the receiving interface is in state
135  Waiting, the receiving interface's state machine is
136  scheduled with the event BACKUP_SEEN.
137  */
138  if ((newBackupRouter == source) &&
139  (intf->getState() == Ospfv2Interface::WAITING_STATE))
140  {
141  backupSeen = true;
142  }
143  else {
144  /* Otherwise, if the neighbor is declaring itself to be Backup Designated Router
145  and it had not previously, or the neighbor is not declaring
146  itself Backup Designated Router where it had previously, the
147  receiving interface's state machine is scheduled with the
148  event NEIGHBOR_CHANGE.
149  */
150  if (((newBackupRouter == source) &&
151  (newBackupRouter != backupAddress)) ||
152  ((newBackupRouter != source) &&
153  (source == backupAddress)))
154  {
155  neighborChanged = true;
156  }
157  }
158 
159  neighbor->setNeighborID(helloPacket->getRouterID());
160  neighbor->setPriority(newPriority);
161  neighbor->setAddress(srcAddress);
162  dRouterID.routerID = newDesignatedRouter;
163  dRouterID.ipInterfaceAddress = newDesignatedRouter;
164  if (newDesignatedRouter != designatedAddress) {
165  designatedAddress = dRouterID.ipInterfaceAddress;
166  drChanged = true;
167  }
168  neighbor->setDesignatedRouter(dRouterID);
169  dRouterID.routerID = newBackupRouter;
170  dRouterID.ipInterfaceAddress = newBackupRouter;
171  if (newBackupRouter != backupAddress) {
172  backupAddress = dRouterID.ipInterfaceAddress;
173  drChanged = true;
174  }
175  neighbor->setBackupDesignatedRouter(dRouterID);
176  if (drChanged) {
177  neighbor->setupDesignatedRouters(false);
178  }
179 
180  /* If the neighbor router's Designated or Backup Designated Router
181  has changed it's necessary to look up the Router IDs belonging to the
182  new addresses.
183  */
184  if (!neighbor->designatedRoutersAreSetUp()) {
185  Neighbor *designated = intf->getNeighborByAddress(designatedAddress);
186  Neighbor *backup = intf->getNeighborByAddress(backupAddress);
187 
188  if (designated != nullptr) {
189  dRouterID.routerID = designated->getNeighborID();
190  dRouterID.ipInterfaceAddress = designated->getAddress();
191  neighbor->setDesignatedRouter(dRouterID);
192  }
193  if (backup != nullptr) {
194  dRouterID.routerID = backup->getNeighborID();
195  dRouterID.ipInterfaceAddress = backup->getAddress();
196  neighbor->setBackupDesignatedRouter(dRouterID);
197  }
198  if ((designated != nullptr) && (backup != nullptr)) {
199  neighbor->setupDesignatedRouters(true);
200  }
201  }
202  }
203  else {
204  DesignatedRouterId dRouterID;
205  bool designatedSetUp = false;
206  bool backupSetUp = false;
207 
208  neighbor = new Neighbor(helloPacket->getRouterID());
209  neighbor->setPriority(helloPacket->getRouterPriority());
210  neighbor->setAddress(srcAddress);
211  neighbor->setRouterDeadInterval(helloPacket->getRouterDeadInterval());
212 
213  router->getMessageHandler()->printEvent("Hello packet received", intf, neighbor);
214 
215  dRouterID.routerID = helloPacket->getDesignatedRouter();
216  dRouterID.ipInterfaceAddress = dRouterID.routerID;
217 
218  Neighbor *designated = intf->getNeighborByAddress(dRouterID.ipInterfaceAddress);
219 
220  // Get the Designated Router ID from the corresponding Neighbor Object.
221  if (designated != nullptr) {
222  if (designated->getNeighborID() != dRouterID.routerID) {
223  dRouterID.routerID = designated->getNeighborID();
224  }
225  designatedSetUp = true;
226  }
227  neighbor->setDesignatedRouter(dRouterID);
228 
229  dRouterID.routerID = helloPacket->getBackupDesignatedRouter();
230  dRouterID.ipInterfaceAddress = dRouterID.routerID;
231 
232  Neighbor *backup = intf->getNeighborByAddress(dRouterID.ipInterfaceAddress);
233 
234  // Get the Backup Designated Router ID from the corresponding Neighbor Object.
235  if (backup != nullptr) {
236  if (backup->getNeighborID() != dRouterID.routerID) {
237  dRouterID.routerID = backup->getNeighborID();
238  }
239  backupSetUp = true;
240  }
241  neighbor->setBackupDesignatedRouter(dRouterID);
242  if (designatedSetUp && backupSetUp) {
243  neighbor->setupDesignatedRouters(true);
244  }
245  intf->addNeighbor(neighbor);
246  }
247 
248  neighbor->processEvent(Neighbor::HELLO_RECEIVED);
249  if ((interfaceType == Ospfv2Interface::NBMA) &&
250  (intf->getRouterPriority() == 0) &&
251  (neighbor->getState() >= Neighbor::INIT_STATE))
252  {
253  intf->sendHelloPacket(neighbor->getAddress());
254  }
255 
256  Ipv4Address interfaceAddress = intf->getAddressRange().address;
257  unsigned int neighborsNeighborCount = helloPacket->getNeighborArraySize();
258  unsigned int i;
259  /* The list of neighbors contained in the Hello Packet is
260  examined. If the router itself appears in this list, the
261  neighbor state machine should be executed with the event TWOWAY_RECEIVED.
262  */
263  for (i = 0; i < neighborsNeighborCount; i++) {
264  if (helloPacket->getNeighbor(i) == interfaceAddress) {
265  neighbor->processEvent(Neighbor::TWOWAY_RECEIVED);
266  break;
267  }
268  }
269  /* Otherwise, the neighbor state machine should
270  be executed with the event ONEWAY_RECEIVED, and the processing
271  of the packet stops.
272  */
273  if (i == neighborsNeighborCount) {
274  neighbor->processEvent(Neighbor::ONEWAY_RECEIVED);
275  }
276 
277  if (neighborChanged) {
278  intf->processEvent(Ospfv2Interface::NEIGHBOR_CHANGE);
279  /* In some cases neighbors get stuck in TwoWay state after a DR
280  or Backup change. (calculateDesignatedRouter runs before the
281  neighbors' signal of DR change + this router does not become
282  neither DR nor backup -> IS_ADJACENCY_OK does not get called.)
283  So to make it work(workaround) we'll call IS_ADJACENCY_OK for
284  all neighbors in TwoWay state from here. This shouldn't break
285  anything because if the neighbor state doesn't have to change
286  then needAdjacency returns false and nothing happnes in
287  IS_ADJACENCY_OK.
288  */
289  unsigned int neighborCount = intf->getNeighborCount();
290  for (i = 0; i < neighborCount; i++) {
291  Neighbor *stuckNeighbor = intf->getNeighbor(i);
292  if (stuckNeighbor->getState() == Neighbor::TWOWAY_STATE) {
293  stuckNeighbor->processEvent(Neighbor::IS_ADJACENCY_OK);
294  }
295  }
296 
297  if (neighborsDRStateChanged) {
298  RouterLsa *routerLSA = intf->getArea()->findRouterLSA(router->getRouterID());
299 
300  if (routerLSA != nullptr) {
301  long sequenceNumber = routerLSA->getHeader().getLsSequenceNumber();
302  if (sequenceNumber == MAX_SEQUENCE_NUMBER) {
303  routerLSA->getHeaderForUpdate().setLsAge(MAX_AGE);
304  intf->getArea()->floodLSA(routerLSA);
305  routerLSA->incrementInstallTime();
306  }
307  else {
308  RouterLsa *newLSA = intf->getArea()->originateRouterLSA();
309 
310  newLSA->getHeaderForUpdate().setLsSequenceNumber(sequenceNumber + 1);
311  shouldRebuildRoutingTable |= routerLSA->update(newLSA);
312  delete newLSA;
313 
314  intf->getArea()->floodLSA(routerLSA);
315  }
316  }
317  }
318  }
319 
320  if (backupSeen) {
321  intf->processEvent(Ospfv2Interface::BACKUP_SEEN);
322  }
323  }
324  }
325  }
326 
327  if (shouldRebuildRoutingTable) {
329  }
330 }

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


The documentation for this class was generated from the following files:
inet::ospfv2::Neighbor::INIT_STATE
@ INIT_STATE
Definition: Ospfv2Neighbor.h:52
inet::ospfv2::MessageHandler::printEvent
void printEvent(const char *eventString, const Ospfv2Interface *onInterface=nullptr, const Neighbor *forNeighbor=nullptr) const
Definition: MessageHandler.cc:380
inet::ospfv2::Ospfv2Interface::POINTTOPOINT
@ POINTTOPOINT
Definition: Ospfv2Interface.h:32
inet::ospfv2::Neighbor::HELLO_RECEIVED
@ HELLO_RECEIVED
Definition: Ospfv2Neighbor.h:30
inet::ospfv2::Ospfv2Interface::Ospfv2InterfaceType
Ospfv2InterfaceType
Definition: Ospfv2Interface.h:30
inet::ospfv2::Ospfv2Interface::WAITING_STATE
@ WAITING_STATE
Definition: Ospfv2Interface.h:54
inet::ospfv2::Neighbor::ONEWAY_RECEIVED
@ ONEWAY_RECEIVED
Definition: Ospfv2Neighbor.h:39
MAX_SEQUENCE_NUMBER
#define MAX_SEQUENCE_NUMBER
Definition: Ospfv2Common.h:34
inet::ospfv2::Ospfv2Interface::NEIGHBOR_CHANGE
@ NEIGHBOR_CHANGE
Definition: Ospfv2Interface.h:45
inet::ospfv2::Neighbor::TWOWAY_STATE
@ TWOWAY_STATE
Definition: Ospfv2Neighbor.h:53
inet::ospfv2::Router::getMessageHandler
MessageHandler * getMessageHandler()
Definition: Ospfv2Router.h:66
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::ospfv2::Neighbor::IS_ADJACENCY_OK
@ IS_ADJACENCY_OK
Definition: Ospfv2Neighbor.h:37
MAX_AGE
#define MAX_AGE
Definition: Ospfv2Common.h:27
inet::ospfv2::NULL_IPV4ADDRESS
const Ipv4Address NULL_IPV4ADDRESS(0, 0, 0, 0)
inet::ospfv2::Router::rebuildRoutingTable
void rebuildRoutingTable()
Rebuilds the routing table from scratch(based on the LSA database).
Definition: Ospfv2Router.cc:663
inet::ospfv2::Ospfv2Interface::BACKUP_SEEN
@ BACKUP_SEEN
Definition: Ospfv2Interface.h:44
inet::ospfv2::Ospfv2Interface::VIRTUAL
@ VIRTUAL
Definition: Ospfv2Interface.h:36
inet::ospfv2::Neighbor::DOWN_STATE
@ DOWN_STATE
Definition: Ospfv2Neighbor.h:50
inet::ospfv2::Ospfv2Interface::NBMA
@ NBMA
Definition: Ospfv2Interface.h:34
inet::ospfv2::Neighbor::TWOWAY_RECEIVED
@ TWOWAY_RECEIVED
Definition: Ospfv2Neighbor.h:32
inet::ospfv2::IMessageHandler::IMessageHandler
IMessageHandler(Router *containingRouter)
Definition: IMessageHandler.h:27
inet::ospfv2::Router::getRouterID
RouterId getRouterID() const
Definition: Ospfv2Router.h:60
inet::ospfv2::Ospfv2Interface::POINTTOMULTIPOINT
@ POINTTOMULTIPOINT
Definition: Ospfv2Interface.h:35
inet::ospfv2::Ospfv2Interface::BROADCAST
@ BROADCAST
Definition: Ospfv2Interface.h:33
inet::ospfv2::IMessageHandler::router
Router * router
Definition: IMessageHandler.h:24