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

#include <HelloHandler.h>

Inheritance diagram for inet::ospf::HelloHandler:
inet::ospf::IMessageHandler

Public Member Functions

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

Additional Inherited Members

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

Constructor & Destructor Documentation

inet::ospf::HelloHandler::HelloHandler ( Router containingRouter)
29  :
30  IMessageHandler(containingRouter)
31 {
32 }
IMessageHandler(Router *containingRouter)
Definition: IMessageHandler.h:38

Member Function Documentation

void inet::ospf::HelloHandler::processPacket ( OSPFPacket packet,
Interface intf,
Neighbor unused = nullptr 
)
overridevirtual

Implements inet::ospf::IMessageHandler.

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

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

The documentation for this class was generated from the following files: