NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
OSPF_Hello.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* Author: Shashi Kant Suman *
12* *
13* ---------------------------------------------------------------------------------*/
14#include "main.h"
15#include "OSPF.h"
16#include "OSPF_enum.h"
17#include "OSPF_Msg.h"
18#include "OSPF_Neighbor.h"
19#include "OSPF_Interface.h"
20
21#define OSPF_HELLO_GET_DR_FROM_IF(i) (i->designaterRouter?i->designaterRouter:NullID)
22#define OSPF_HELLO_GET_BDR_FROM_IF(i) (i->backupDesignaterRouter?i->backupDesignaterRouter:NullID)
23
24void OSPF_HELLO_MSG_NEW(ptrOSPFPACKETHDR hdr)
25{
26 ptrOSPFHELLO hello = calloc(1, sizeof* hello);
27 OSPF_HDR_SET_MSG(hdr,
28 OSPFMSG_HELLO,
29 hello,
30 OSPFHELLO_LEN_FIXED);
31}
32
33ptrOSPFHELLO OSPF_HELLO_MSG_COPY(ptrOSPFHELLO hello)
34{
35 ptrOSPFHELLO h = calloc(1, sizeof* hello);
36 memcpy(h, hello, sizeof* hello);
37 UINT i;
38 if (hello->neighCount)
39 h->Neighbor = calloc(hello->neighCount, sizeof* h->Neighbor);
40 for (i = 0; i < hello->neighCount; i++)
41 h->Neighbor[i] = IP_COPY(hello->Neighbor[i]);
42 return h;
43}
44
45void OSPF_HELLO_MSG_FREE(ptrOSPFHELLO hello)
46{
47 free(hello);
48}
49
50void start_interval_hello_timer()
51{
52 double delay = NETSIM_RAND_01()*OSPF_BROADCAST_JITTER;
53
54 NetSim_EVENTDETAILS pevent;
55 memset(&pevent, 0, sizeof pevent);
56 pevent.dEventTime = pstruEventDetails->dEventTime + delay;
57 pevent.nDeviceId = pstruEventDetails->nDeviceId;
58 pevent.nDeviceType = DEVICE_TYPE(pevent.nDeviceId);
59 pevent.nEventType = TIMER_EVENT;
60 pevent.nInterfaceId = pstruEventDetails->nInterfaceId;
61 pevent.nProtocolId = APP_PROTOCOL_OSPF;
62 pevent.nSubEventType = OSPF_HELLO_TIMER;
63 fnpAddEvent(&pevent);
64
65 print_ospf_log(OSPF_HELLO_LOG, "Starting interval hello timer for router %d-%d at time %lf",
66 pstruEventDetails->nDeviceId,
67 pstruEventDetails->nInterfaceId,
68 pstruEventDetails->dEventTime);
69}
70
71static void add_next_hello_timer()
72{
73 ptrOSPF_IF ospfIf = OSPF_IF_CURRENT();
74 double delay = NETSIM_RAND_01()*OSPF_BROADCAST_JITTER;
75 NetSim_EVENTDETAILS pevent;
76 memset(&pevent, 0, sizeof pevent);
77 pevent.dEventTime = pstruEventDetails->dEventTime +
78 ospfIf->helloInterval*SECOND + delay;
79 pevent.nDeviceId = pstruEventDetails->nDeviceId;
80 pevent.nDeviceType = DEVICE_TYPE(pevent.nDeviceId);
81 pevent.nEventType = TIMER_EVENT;
82 pevent.nInterfaceId = pstruEventDetails->nInterfaceId;
83 pevent.nProtocolId = APP_PROTOCOL_OSPF;
84 pevent.nSubEventType = OSPF_HELLO_TIMER;
85 fnpAddEvent(&pevent);
86
87 print_ospf_log(OSPF_HELLO_LOG, "Scheduling next interval hello timer for router %d-%d at time %lf",
88 pstruEventDetails->nDeviceId,
89 pstruEventDetails->nInterfaceId,
90 pstruEventDetails->dEventTime);
91}
92
93static UINT16 add_neighborToHello(ptrOSPFHELLO hello, ptrOSPF_IF ospf)
94{
95 UINT16 c = 0;
96 UINT i;
97 print_ospf_log(OSPF_HELLO_LOG, "Adding neighbor to hello message");
98 for (i = 0; i < ospf->neighborRouterCount; i++)
99 {
100 if (ospf->neighborRouterList[i]->state >= OSPFNEIGHSTATE_Init)
101 {
102 if (hello->Neighbor)
103 hello->Neighbor = realloc(hello->Neighbor, (c + 1) * sizeof* hello->Neighbor);
104 else
105 hello->Neighbor = calloc(1, sizeof* hello->Neighbor);
106 hello->Neighbor[c] = ospf->neighborRouterList[i]->neighborId;
107 print_ospf_log(OSPF_HELLO_LOG, "%s neighbor is added",
108 ospf->neighborRouterList[i]->neighborId->str_ip);
109 hello->neighCount++;
110 c++;
111 }
112 }
113 print_ospf_log(OSPF_HELLO_LOG, "%d neighbor is added out of %d", c, ospf->neighborRouterCount);
114 return c;
115}
116
117static void set_hello_param(NetSim_PACKET* packet, ptrOSPFPACKETHDR hdr)
118{
119 ptrOSPFHELLO hello = OSPF_HDR_GET_MSG(hdr);
120 ptrOSPF_IF thisInterface = OSPF_IF_CURRENT();
121 hello->NetworkMask = DEVICE_CURR_MASK;
122 hello->HelloInterval = OSPFTIME_TO_UINT16(thisInterface->helloInterval);
123 hello->RtrPri = thisInterface->RouterPriority;
124 hello->RouterDeadInterval = OSPFTIME_TO_UINT16(thisInterface->routerDeadInterval);
125 hello->DesignatedRouter = OSPF_HELLO_GET_DR_FROM_IF(thisInterface);
126 hello->BackupDesignatedRouter = OSPF_HELLO_GET_BDR_FROM_IF(thisInterface);
127 UINT16 count = add_neighborToHello(hello, thisInterface);
128 OSPF_HDR_INCREASE_LEN(packet, count * 4);
129}
130
131static void ospf_hello_update_dst(NetSim_PACKET* packet)
132{
133 add_dest_to_packet(packet, 0);
134 packet->pstruNetworkData->szDestIP = AllSPFRouters;
135 packet->pstruNetworkData->szNextHopIp = AllSPFRouters;
136 packet->pstruNetworkData->nTTL = 2;
137}
138
139static void send_hello()
140{
141 OSPFMSG type = OSPFMSG_HELLO;
142 NetSim_PACKET* packet = OSPF_PACKET_NEW(pstruEventDetails->dEventTime,
143 type,
144 pstruEventDetails->nDeviceId,
145 pstruEventDetails->nInterfaceId);
146
147 ospf_hello_update_dst(packet);
148 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
149
150 set_hello_param(packet, hdr);
151
152 OSPF_SEND_PACKET(packet);
153}
154
155void ospf_handle_helloTimer_event()
156{
157 ptrOSPF_IF thisInterface = OSPF_IF_CURRENT();
158 if (thisInterface->State == OSPFIFSTATE_DOWN)
159 return; // No hello is send if interface state is down.
160
161 add_next_hello_timer();
162
163 print_ospf_log(OSPF_HELLO_LOG, "Time %0.4lf, Router %d, interface %d (%s) is sending hello msg",
164 pstruEventDetails->dEventTime / MILLISECOND,
165 pstruEventDetails->nDeviceId,
166 pstruEventDetails->nInterfaceId,
167 DEVICE_MYIP()->str_ip);
168 send_hello();
169 print_ospf_log(OSPF_HELLO_LOG, "\n");
170}
171
172static bool validate_hello_msg()
173{
174 NetSim_PACKET* packet = pstruEventDetails->pPacket;
175 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
176 ptrOSPFHELLO hello = OSPF_HDR_GET_MSG(hdr);
177 ptrOSPF_IF thisInterface = OSPF_IF_CURRENT();
178
179 if (thisInterface->Type != OSPFIFTYPE_P2P &&
180 thisInterface->Type != OSPFIFTYPE_VIRTUALLINK)
181 {
182 if (IP_COMPARE(thisInterface->IPIfMask, hello->NetworkMask))
183 {
184 fnNetSimError("Router %d-%d received hello packet with different net mask than configured\n",
185 pstruEventDetails->nDeviceId,
186 pstruEventDetails->nInterfaceId);
187 return false;
188 }
189 }
190
191 if (thisInterface->helloInterval != hello->HelloInterval)
192 {
193 fnNetSimError("Router %d-%d received hello packet with different hello interval than configured\n",
194 pstruEventDetails->nDeviceId,
195 pstruEventDetails->nInterfaceId);
196 return false;
197 }
198
199 if (thisInterface->routerDeadInterval != hello->RouterDeadInterval)
200 {
201 fnNetSimError("Router %d-%d received hello packet with different router dead interval than configured\n",
202 pstruEventDetails->nDeviceId,
203 pstruEventDetails->nInterfaceId);
204 return false;
205 }
206 return true;
207}
208
209static bool is_ip_present_in_hello(ptrOSPFHELLO hello, NETSIM_IPAddress ip)
210{
211 UINT i;
212 for (i = 0; i < hello->neighCount; i++)
213 {
214 if (!IP_COMPARE(hello->Neighbor[i], ip))
215 return true;
216 }
217 return false;
218}
219
220static bool ospf_hello_findNeighbor(ptrOSPF_IF thisInterface,
221 NETSIM_IPAddress srcAddr,
222 OSPFID rid,
223 ptrOSPF_NEIGHBOR* neighbor)
224{
225 UINT i;
226 for (i = 0; i < thisInterface->neighborRouterCount; i++)
227 {
228 ptrOSPF_NEIGHBOR neigh = thisInterface->neighborRouterList[i];
229 if (thisInterface->Type == OSPFIFTYPE_BROADCAST ||
230 thisInterface->Type == OSPFIFTYPE_P2MP)
231 {
232 if (!IP_COMPARE(neigh->neighborIPAddr, srcAddr))
233 {
234 *neighbor = neigh;
235 return true;
236 }
237 }
238 else
239 {
240 if (!OSPFID_COMPARE(neigh->neighborId, rid))
241 {
242 if (IP_COMPARE(neigh->neighborIPAddr, srcAddr))
243 {
244 *neighbor = NULL;
245 return false;
246 }
247 *neighbor = neigh;
248 return true;
249 }
250 }
251 }
252 *neighbor = NULL;
253 return true;
254}
255
256void ospf_process_hello()
257{
258 NETSIM_ID d = pstruEventDetails->nDeviceId;
259 NETSIM_ID in = pstruEventDetails->nInterfaceId;
260 NetSim_PACKET* packet = pstruEventDetails->pPacket;
261 NETSIM_IPAddress src = packet->pstruNetworkData->szSourceIP;
262 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
263 NETSIM_IPAddress rid = hdr->RouterId;
264 ptrOSPFHELLO hello = OSPF_HDR_GET_MSG(hdr);
265 ptrOSPF_PDS ospf = OSPF_PDS_CURRENT();
266 ptrOSPF_IF thisIntf = OSPF_IF_CURRENT();
267 ptrOSPFAREA_DS thisArea = OSPF_AREA_GET_ID(ospf, thisIntf->areaId);
268 thisArea;
269 ptrOSPF_NEIGHBOR tempNeighborInfo = NULL;
270 BOOL neighborFound = false;
271 UINT numNeighbor;
272 print_ospf_log(OSPF_HELLO_LOG, "Time %0.4lf ms, Router %d interface %d (%s) received hello msg from neighbor %s",
273 pstruEventDetails->dEventTime / MILLISECOND,
274 d,
275 in,
276 DEVICE_NWADDRESS(d, in)->str_ip,
277 hdr->RouterId->str_ip);
278
279 if (!validate_hello_msg())
280 {
281 print_ospf_log(OSPF_HELLO_LOG, "Hello msg is not validated. Deleting hello msg...");
282 goto TERMINATE_PROCESSING_HELLO;
283 }
284
285 NETSIM_IPAddress nbrPrevDR = NULL;
286 NETSIM_IPAddress nbrPrevBDR = NULL;
287 UINT8 nbrPrevPriority = 0;
288 bool routerIdInHelloPktBody = false;
289
290 numNeighbor = hello->neighCount;
291 print_ospf_log(OSPF_HELLO_LOG, "%d neighbor is present in hello message", numNeighbor);
292
293 if (!ospf_hello_findNeighbor(thisIntf, src, rid, &tempNeighborInfo))
294 goto TERMINATE_PROCESSING_HELLO;
295
296 if (tempNeighborInfo)
297 neighborFound = true;
298
299 if (!neighborFound)
300 {
301 print_ospf_log(OSPF_HELLO_LOG, "Neighbor is not found in neighbor list");
302 print_ospf_log(OSPF_HELLO_LOG, "Adding new neighbor of RID %s, IP addr %s",
303 rid->str_ip, src->str_ip);
304 tempNeighborInfo = ospf_neighbor_new(src, rid);
305 ospf_neighbor_add(thisIntf, tempNeighborInfo);
306 tempNeighborInfo->neighborDesignateRouter = hello->DesignatedRouter;
307 tempNeighborInfo->neighborDesignateBackupRouter = hello->BackupDesignatedRouter;
308 }
309 nbrPrevDR = tempNeighborInfo->neighborDesignateRouter;
310 nbrPrevBDR = tempNeighborInfo->neighborDesignateBackupRouter;
311
312 if (thisIntf->Type == OSPFIFTYPE_BROADCAST ||
313 thisIntf->Type == OSPFIFTYPE_P2MP)
314 {
315 nbrPrevPriority = tempNeighborInfo->neighborPriority;
316 tempNeighborInfo->neighborDesignateRouter = hello->DesignatedRouter;
317 tempNeighborInfo->neighborDesignateBackupRouter = hello->BackupDesignatedRouter;
318 tempNeighborInfo->neighborPriority = hello->RtrPri;
319 }
320 else if (thisIntf->Type == OSPFIFTYPE_P2P)
321 {
322 nbrPrevPriority = tempNeighborInfo->neighborPriority;
323 tempNeighborInfo->neighborIPAddr = src;
324 tempNeighborInfo->neighborPriority = hello->RtrPri;
325 }
326 else
327 {
328 nbrPrevPriority = tempNeighborInfo->neighborPriority;
329 tempNeighborInfo->neighborPriority = hello->RtrPri;
330 }
331
332 // Handle neighbor event
333 ospf_event_set_and_call(OSPF_HelloReceived,
334 tempNeighborInfo);
335
336 // Check whether this router itself appear in the
337 // list of neighbor contained in Hello packet.
338 if (is_ip_present_in_hello(hello, ospf->routerId))
339 {
340 print_ospf_log(OSPF_HELLO_LOG, "My ip is present in neighbor list. Setting 2-way received event");
341 ospf_event_set_and_call(OSPF_2WayReceived, tempNeighborInfo);
342 routerIdInHelloPktBody = true;
343 }
344 else
345 {
346 print_ospf_log(OSPF_HELLO_LOG, "My ip is not present in neighbor list. Set 1-way event & terminating further processing");
347 ospf_event_set_and_call(OSPF_1Way, tempNeighborInfo);
348 goto TERMINATE_PROCESSING_HELLO;
349 }
350
351 // If a change in the neighbor's Router Priority field was noted,
352 // the receiving interface's state machine is scheduled with
353 // the event NeighborChange.
354 if (nbrPrevPriority != tempNeighborInfo->neighborPriority)
355 {
356 print_ospf_log(OSPF_HELLO_LOG, "Neighbor priority is changed. Adding neighbor change event");
357 ospf_event_add(pstruEventDetails->dEventTime,
358 d,
359 in,
360 OSPF_NEIGHBORCHANGE,
361 NULL,
362 tempNeighborInfo);
363 }
364
365 // If the neighbor is both declaring itself to be Designated Router and
366 // the Backup Designated Router field in the packet is equal to 0.0.0.0
367 // and the receiving interface is in state Waiting, the receiving
368 // interface's state machine is scheduled with the event BackupSeen.
369 // Otherwise, if the neighbor is declaring itself to be Designated Router
370 // and it had not previously, or the neighbor is not declaring itself
371 // Designated Router where it had previously, the receiving interface's
372 // state machine is scheduled with the event NeighborChange.
373 if (!IP_COMPARE(hello->DesignatedRouter, tempNeighborInfo->neighborIPAddr) &&
374 !hello->BackupDesignatedRouter->int_ip[0] &&
375 thisIntf->State == OSPFIFSTATE_WAITING)
376 {
377 print_ospf_log(OSPF_HELLO_LOG, "Neighbor is declaring itself as DR and BDR is NULL");
378 ospf_event_add(pstruEventDetails->dEventTime,
379 d,
380 in,
381 OSPF_BACKUPSEEN,
382 NULL,
383 tempNeighborInfo);
384 }
385 else if ((!IP_COMPARE(hello->DesignatedRouter, tempNeighborInfo->neighborIPAddr) &&
386 IP_COMPARE(nbrPrevDR, tempNeighborInfo->neighborIPAddr)) ||
387 (IP_COMPARE(hello->DesignatedRouter, tempNeighborInfo->neighborIPAddr) &&
388 !IP_COMPARE(nbrPrevDR, tempNeighborInfo->neighborIPAddr)))
389 {
390 ospf_event_add(pstruEventDetails->dEventTime,
391 d,
392 in,
393 OSPF_NEIGHBORCHANGE,
394 NULL,
395 tempNeighborInfo);
396 }
397
398
399 // If the neighbor is declaring itself to be Backup Designated Router and
400 // the receiving interface is in state Waiting, the receiving interface's
401 // state machine is scheduled with the event BackupSeen. Otherwise, if
402 // neighbor is declaring itself to be Backup Designated Router and it had
403 // not previously, or the neighbor is not declaring itself Backup
404 // Designated Router where it had previously, the receiving interface's
405 // state machine is scheduled with the event NeighborChange.
406 if (hello->BackupDesignatedRouter->int_ip[0] ==
407 tempNeighborInfo->neighborIPAddr->int_ip[0] &&
408 thisIntf->State == OSPFIFSTATE_WAITING)
409 {
410 ospf_event_add(pstruEventDetails->dEventTime,
411 d,
412 in,
413 OSPF_BACKUPSEEN,
414 NULL,
415 tempNeighborInfo);
416 }
417 else if ((hello->BackupDesignatedRouter->int_ip[0] == tempNeighborInfo->neighborIPAddr->int_ip[0] &&
418 nbrPrevBDR->int_ip[0] != tempNeighborInfo->neighborIPAddr->int_ip[0]) ||
419 (hello->BackupDesignatedRouter->int_ip[0] != tempNeighborInfo->neighborIPAddr->int_ip[0] &&
420 nbrPrevBDR->int_ip[0] == tempNeighborInfo->neighborIPAddr->int_ip[0]))
421 {
422 ospf_event_add(pstruEventDetails->dEventTime,
423 d,
424 in,
425 OSPF_NEIGHBORCHANGE,
426 NULL,
427 tempNeighborInfo);
428 }
429
430TERMINATE_PROCESSING_HELLO:
431 fn_NetSim_Packet_FreePacket(packet);
432 pstruEventDetails->pPacket = NULL;
433 print_ospf_log(OSPF_HELLO_LOG, "\n\n");
434}
435