NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
OSPF_DD.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 "NetSim_utility.h"
16#include "OSPF.h"
17#include "OSPF_enum.h"
18#include "OSPF_Msg.h"
19#include "OSPF_Interface.h"
20#include "OSPF_Neighbor.h"
21#include "OSPF_List.h"
22
23void OSPF_DD_MSG_NEW(ptrOSPFPACKETHDR hdr)
24{
25 ptrOSPFDD dd = calloc(1, sizeof* dd);
26 OSPF_HDR_SET_MSG(hdr,
27 OSPFMSG_DD,
28 dd,
29 OSPFDD_LEN_FIXED);
30}
31
32ptrOSPFDD OSPF_DD_MSG_COPY(ptrOSPFDD dd)
33{
34 ptrOSPFDD d = calloc(1, sizeof* d);
35 memcpy(d, dd, sizeof* d);
36 if (dd->numLSA)
37 d->LSAHeader = calloc(dd->numLSA, sizeof* d->LSAHeader);
38 UINT i;
39 for (i = 0; i < dd->numLSA; i++)
40 d->LSAHeader[i] = OSPF_LSA_HDR_COPY(dd->LSAHeader[i]);
41 return d;
42}
43
44void OSPF_DD_MSG_FREE(ptrOSPFDD dd)
45{
46 UINT i;
47 for (i = 0; i < dd->numLSA; i++)
48 OSPF_LSA_HDR_FREE(dd->LSAHeader[i]);
49 free(dd->LSAHeader);
50 free(dd);
51}
52
53static void set_DD_param_in_exstart(ptrOSPFPACKETHDR hdr,
54 ptrOSPF_IF ospf,
55 ptrOSPF_NEIGHBOR neigh)
56{
57 ptrOSPFDD dd = OSPF_HDR_GET_MSG(hdr);
58 if (ospf->Type == OSPFIFTYPE_VIRTUALLINK)
59 dd->InterfaceMTU = 0;
60 else
61 dd->InterfaceMTU = INTERFACE_MTU_DEFAULT;
62 dd->DDSequenceNumber = neigh->DDSeqNo;
63 DD_SET_INIT(dd);
64 DD_SET_MORE(dd);
65 DD_SET_MASTER(dd);
66 neigh->IMMS = dd->IMMS;
67}
68
69static ptrOSPFLSAHDR* ospf_DD_getTopLSAFromList(ptrOSPFLIST list,
70 UINT16* count,
71 UINT maxCount)
72{
73 ptrOSPFLSAHDR* ret = NULL;
74 UINT16 c = 0;
75 ptrOSPFLSAHDR lsa;
76 while ((lsa = ospf_list_get_mem(list)) != NULL)
77 {
78 if (ret)
79 ret = realloc(ret, (c + 1) * sizeof* ret);
80 else
81 ret = calloc(1, sizeof* ret);
82 ret[c] = lsa;
83 c++;
84 if (c >= maxCount)
85 break;
86 }
87 *count = c;
88 return ret;
89}
90
91static void set_DD_param_in_exchange(NetSim_PACKET* packet,
92 ptrOSPF_IF ospf,
93 ptrOSPF_NEIGHBOR neigh)
94{
95 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
96 ptrOSPFDD dd = OSPF_HDR_GET_MSG(hdr);
97 if (ospf->Type == OSPFIFTYPE_VIRTUALLINK)
98 dd->InterfaceMTU = 0;
99 else
100 dd->InterfaceMTU = INTERFACE_MTU_DEFAULT;
101 dd->DDSequenceNumber = neigh->DDSeqNo;
102
103 UINT maxLSAHdrCount = OSPF_DD_MAX_LSA_COUNT();
104 ptrOSPFLSAHDR* lsahdr = ospf_DD_getTopLSAFromList(neigh->neighDBSummaryList,
105 &dd->numLSA,
106 maxLSAHdrCount);
107
108 dd->LSAHeader = lsahdr;
109 if (!ospf_list_is_empty(neigh->neighDBSummaryList))
110 DD_SET_MORE(dd);
111
112 if (neigh->isMaster)
113 DD_SET_MASTER(dd);
114 neigh->IMMS = dd->IMMS;
115
116 OSPF_HDR_INCREASE_LEN(packet, dd->numLSA*OSPFLSAHDR_LEN);
117}
118
119static void ospf_DD_update_dst(NetSim_PACKET* packet,
120 ptrOSPF_NEIGHBOR neigh)
121{
122 add_dest_to_packet(packet, neigh->devId);
123 packet->pstruNetworkData->szDestIP = neigh->neighborIPAddr;
124 packet->pstruNetworkData->nTTL = 2;
125}
126
127static void send_DD_msg(ptrOSPF_IF ospf,
128 ptrOSPF_NEIGHBOR neigh)
129{
130 OSPFMSG type = OSPFMSG_DD;
131 NetSim_PACKET* packet = OSPF_PACKET_NEW(pstruEventDetails->dEventTime,
132 type,
133 pstruEventDetails->nDeviceId,
134 pstruEventDetails->nInterfaceId);
135
136 ospf_DD_update_dst(packet, neigh);
137 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
138
139 if (neigh->state == OSPFNEIGHSTATE_ExStart)
140 set_DD_param_in_exstart(hdr, ospf, neigh);
141 else if (neigh->state == OSPFNEIGHSTATE_Exchange)
142 set_DD_param_in_exchange(packet, ospf, neigh);
143
144 OSPF_SEND_PACKET(packet);
145
146 if (neigh->lastSentDDPacket)
147 OSPF_HDR_FREE(neigh->lastSentDDPacket);
148 neigh->lastSentDDPacket = OSPF_HDR_COPY(hdr);
149 neigh->lastDDMsgSentTime = pstruEventDetails->dEventTime;
150}
151
152static void copy_DD_param(ptrOSPFPACKETHDR hdr,
153 ptrOSPF_NEIGHBOR neigh)
154{
155 ptrOSPFDD dd = hdr->ospfMSG;
156 ptrOSPFDD old = neigh->lastrecvDDPacket->ospfMSG;
157 dd->DDSequenceNumber = old->DDSequenceNumber;
158 dd->Option = old->Option;
159 dd->InterfaceMTU = old->InterfaceMTU;
160
161 if (old->numLSA)
162 {
163 dd->numLSA = old->numLSA;
164 dd->LSAHeader = calloc(dd->numLSA, sizeof* dd->LSAHeader);
165 UINT i;
166 for (i = 0; i < old->numLSA; i++)
167 dd->LSAHeader[i] = OSPF_LSA_HDR_COPY(old->LSAHeader[i]);
168 }
169
170 dd->IMMS = old->IMMS;
171}
172
173static void resend_DD_msg(ptrOSPF_IF ospf,
174 ptrOSPF_NEIGHBOR neigh)
175{
176 ospf;
177
178 OSPFMSG type = OSPFMSG_DD;
179 NetSim_PACKET* packet = OSPF_PACKET_NEW(pstruEventDetails->dEventTime,
180 type,
181 pstruEventDetails->nDeviceId,
182 pstruEventDetails->nInterfaceId);
183
184 ospf_DD_update_dst(packet, neigh);
185 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
186
187 copy_DD_param(hdr, neigh);
188 OSPF_SEND_PACKET(packet);
189
190 if (neigh->lastSentDDPacket)
191 OSPF_HDR_FREE(neigh->lastSentDDPacket);
192 neigh->lastSentDDPacket = OSPF_HDR_COPY(hdr);
193 neigh->lastDDMsgSentTime = pstruEventDetails->dEventTime;
194}
195
196static void add_DD_rxmt_timer_in_exstart_state(ptrOSPF_IF ospf,
197 ptrOSPF_NEIGHBOR neigh)
198{
199 ospf_event_add(pstruEventDetails->dEventTime + ospf->RxmtInterval*SECOND,
200 pstruEventDetails->nDeviceId,
201 pstruEventDetails->nInterfaceId,
202 OSPF_DD_RXMT_IN_EXSTART,
203 NULL,
204 neigh);
205}
206
207void start_sending_dd_msg()
208{
209 ptrOSPF_IF ospf = OSPF_IF_CURRENT();
210 ptrOSPF_NEIGHBOR neigh = pstruEventDetails->szOtherDetails;
211 if (neigh->state != OSPFNEIGHSTATE_ExStart)
212 return;
213 print_ospf_log(OSPF_LOG, "Time %0.4lf, Router %d, interface %d (%s), Sending DD msg to neighbor %s",
214 pstruEventDetails->dEventTime/MILLISECOND,
215 pstruEventDetails->nDeviceId,
216 pstruEventDetails->nInterfaceId,
217 DEVICE_MYIP()->str_ip,
218 neigh->neighborId->str_ip);
219 print_ospf_log(OSPF_LOG, "Neighbor state is %s",
220 strNeighborState[neigh->state]);
221 send_DD_msg(ospf, neigh);
222 add_DD_rxmt_timer_in_exstart_state(ospf, neigh);
223 print_ospf_log(OSPF_LOG, "\n");
224}
225
226static void ospf_process_DD(ptrOSPF_PDS ospf,
227 ptrOSPF_IF thisInterface,
228 ptrOSPF_NEIGHBOR neigh,
229 ptrOSPFPACKETHDR hdr)
230{
231 print_ospf_log(OSPF_LOG, "Processing DD msg");
232 ptrOSPFDD dd = hdr->ospfMSG;
233 ptrOSPFAREA_DS area = OSPF_AREA_GET_ID(ospf, thisInterface->areaId);
234 UINT numLSA = dd->numLSA;
235 UINT i;
236 for (i = 0; i < numLSA; i++)
237 {
238 ptrOSPFLSAHDR lsa = dd->LSAHeader[i];
239 ptrOSPFLSAHDR oldLsa = NULL;
240
241 // Check for the validity of LSA
242 if (lsa->LSType < LSTYPE_ROUTERLSA ||
243 lsa->LSType >= LSTYPE_UNDEFINED)
244 {
245 print_ospf_log(OSPF_LOG, "Unknown LSA type %d. Discard DD packet",
246 lsa->LSType);
247
248 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
249 return;
250 }
251
252 // Looks up for the LSA in its own Database
253 oldLsa = ospf_lsdb_lookup(ospf, area, lsa->LSType,
254 lsa->AdvertisingRouter, lsa->LinkStateID);
255
256 // Add to request list if the LSA doesn't exist or if
257 // this instance is more recent one
258
259 if (!oldLsa ||
260 ospf_lsa_compare(ospf, oldLsa, lsa) > 0)
261 {
262 print_ospf_log(OSPF_LOG, "Adding LSA to request list");
263 ospf_lsreq_insertToList(neigh, lsa, OSPF_CURR_TIME());
264 }
265 }
266
267 if (neigh->isMaster)
268 {
269 neigh->DDSeqNo++;
270 if (!isBitSet(neigh->IMMS, DD_MORE_BIT_INDEX) &&
271 !DD_IS_MORE(dd))
272 {
273 print_ospf_log(OSPF_LOG, "Scheduling event Exchange_Done");
274 ospf_event_add(pstruEventDetails->dEventTime,
275 pstruEventDetails->nDeviceId,
276 pstruEventDetails->nInterfaceId,
277 OSPF_ExchangeDone,
278 NULL,
279 neigh);
280 }
281 else
282 {
283 print_ospf_log(OSPF_LOG, "More bit is set. Sending DD msg");
284 send_DD_msg(thisInterface, neigh);
285 }
286 }
287 else
288 {
289 neigh->DDSeqNo = dd->DDSequenceNumber;
290 print_ospf_log(OSPF_LOG, "I am slave. Sending DD msg");
291 send_DD_msg(thisInterface, neigh);
292 if (!DD_IS_MORE(dd) &&
293 ospf_list_is_empty(neigh->neighDBSummaryList))
294 {
295 print_ospf_log(OSPF_LOG, "Scheduling event Exchange_Done");
296 ospf_event_add(pstruEventDetails->dEventTime,
297 pstruEventDetails->nDeviceId,
298 pstruEventDetails->nInterfaceId,
299 OSPF_ExchangeDone,
300 NULL,
301 neigh);
302 }
303 }
304}
305
306static bool validate_dd_msg(ptrOSPF_IF ospf,
307 ptrOSPF_NEIGHBOR neigh,
308 ptrOSPFDD dd)
309{
310 ospf;
311
312 if (dd->InterfaceMTU > INTERFACE_MTU_DEFAULT)
313 return false;
314
315 if (!neigh)
316 return false;
317
318 if (neigh->state == OSPFNEIGHSTATE_DOWN)
319 return false;
320
321 if (neigh->state == OSPFNEIGHSTATE_Attempt)
322 return false;
323
324 return true;
325}
326
327static bool ospf_dd_check_duplicate(ptrOSPF_NEIGHBOR neigh,
328 ptrOSPFPACKETHDR hdr)
329{
330 if (!neigh->lastrecvDDPacket)
331 return false;
332 ptrOSPFDD n = hdr->ospfMSG;
333 ptrOSPFDD o = neigh->lastrecvDDPacket->ospfMSG;
334
335 if (n->DDSequenceNumber == o->DDSequenceNumber &&
336 n->IMMS == o->IMMS &&
337 n->Option == o->Option)
338 return true;
339
340 return false;
341}
342
343static void ospf_process_dd_in_exstart_state(ptrOSPF_PDS ospf,
344 ptrOSPF_IF ospfif,
345 ptrOSPF_NEIGHBOR neigh,
346 ptrOSPFPACKETHDR hdr)
347{
348 ptrOSPFDD dd = hdr->ospfMSG;
349 if (DD_IS_INIT(dd) &&
350 DD_IS_MORE(dd) &&
351 DD_IS_MASTER(dd) &&
352 !dd->LSAHeader &&
353 OSPFID_ISGREATER(hdr->RouterId,ospf->routerId))
354 {
355 neigh->DDSeqNo = dd->DDSequenceNumber;
356 neigh->isMaster = false;
357 print_ospf_log(OSPF_LOG, "I am now slave.");
358 }
359 else if (!DD_IS_INIT(dd) &&
360 !DD_IS_MASTER(dd) &&
361 dd->DDSequenceNumber == neigh->DDSeqNo &&
362 OSPFID_ISSMALLER(hdr->RouterId,ospf->routerId))
363 {
364 neigh->isMaster = true;
365 print_ospf_log(OSPF_LOG, "I am now master.");
366 }
367 else
368 {
369 print_ospf_log(OSPF_LOG, "Neither master nor slave. Who i am? Ignoring DD msg.");
370 return;
371 }
372
373 ospf_event_set_and_call(OSPF_NegotiationDone, neigh);
374 neigh->neighborOption = dd->Option;
375 ospf_process_DD(ospf, ospfif, neigh, hdr);
376}
377
378static void ospf_process_dd_in_init_state(ptrOSPF_NEIGHBOR neigh,
379 ptrOSPFPACKETHDR hdr)
380{
381 hdr;
382
383 ospf_event_set_and_call(OSPF_2WayReceived, neigh);
384}
385
386static void ospf_process_dd_in_exchange_state_for_duplicate(ptrOSPF_IF ospf,
387 ptrOSPF_NEIGHBOR neigh,
388 ptrOSPFPACKETHDR hdr)
389{
390 hdr;
391
392 if (neigh->isMaster)
393 print_ospf_log(OSPF_LOG, "I am master. Discarding duplicate DD");
394 else
395 resend_DD_msg(ospf, neigh);
396}
397
398static void ospf_process_dd_in_exchange_state(ptrOSPF_PDS ospf,
399 ptrOSPF_IF thisInterface,
400 ptrOSPF_NEIGHBOR neigh,
401 ptrOSPFPACKETHDR hdr,
402 bool isDuplicate)
403{
404 if (isDuplicate)
405 {
406 ospf_process_dd_in_exchange_state_for_duplicate(thisInterface, neigh, hdr);
407 return;
408 }
409
410 ptrOSPFDD dd = hdr->ospfMSG;
411
412 /*
413 If the state of the MS-bit is inconsistent with the
414 master/slave state of the connection, generate the
415 neighbor event SeqNumberMismatch and stop processing the
416 packet.
417 */
418 if ((DD_IS_MASTER(dd) && neigh->isMaster) ||
419 (!DD_IS_MASTER(dd) && !neigh->isMaster))
420 {
421 print_ospf_log(OSPF_LOG, "MS-bit is inconsistent with the "
422 "master / slave state of the connection");
423 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
424 return;
425 }
426
427 /*
428 If the initialize(I) bit is set, generate the neighbor
429 event SeqNumberMismatch and stop processing the packet
430 */
431 if (DD_IS_INIT(dd))
432 {
433 print_ospf_log(OSPF_LOG, "Initialize(I) bit is set");
434 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
435 return;
436 }
437
438 /*
439 If the packet's Options field indicates a different set
440 of optional OSPF capabilities than were previously
441 received from the neighbor (recorded in the Neighbor
442 Options field of the neighbor structure), generate the
443 neighbor event SeqNumberMismatch and stop processing the
444 packet
445 */
446 if (dd->Option != neigh->neighborOption)
447 {
448 print_ospf_log(OSPF_LOG, "packet's Options field indicates a different set "
449 "of optional OSPF capabilities than were previously "
450 "received from the neighbor(recorded in the Neighbor "
451 "Options field of the neighbor structure)");
452 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
453 return;
454 }
455
456 /*
457 Database Description packets must be processed in
458 sequence, as indicated by the packets' DD sequence
459 numbers. If the router is master, the next packet
460 received should have DD sequence number equal to the DD
461 sequence number in the neighbor data structure. If the
462 router is slave, the next packet received should have DD
463 sequence number equal to one more than the DD sequence
464 number stored in the neighbor data structure. In either
465 case, if the packet is the next in sequence it should be
466 accepted and its contents processed.
467 */
468 if ((neigh->isMaster &&
469 neigh->DDSeqNo != dd->DDSequenceNumber) ||
470 (!neigh->isMaster &&
471 dd->DDSequenceNumber != neigh->DDSeqNo + 1))
472 {
473 print_ospf_log(OSPF_LOG, "DD seq number mismatch");
474 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
475 return;
476 }
477
478 ospf_process_DD(ospf, thisInterface, neigh, hdr);
479}
480
481static void ospf_process_dd_in_loading_or_full_state(ptrOSPF_IF ospf,
482 ptrOSPF_NEIGHBOR neigh,
483 ptrOSPFPACKETHDR hdr,
484 bool isDuplicate)
485{
486 hdr;
487
488 if (isDuplicate)
489 {
490 if (neigh->isMaster)
491 {
492 print_ospf_log(OSPF_LOG, "Duplicate DD msg received. I am master. Discarding packet");
493 return;
494 }
495 else
496 {
497 if (pstruEventDetails->dEventTime - neigh->lastDDMsgSentTime <
498 ospf->routerDeadInterval*SECOND)
499 {
500 resend_DD_msg(ospf, neigh);
501 return;
502 }
503 }
504 }
505
506 print_ospf_log(OSPF_LOG, "DD seq number mismatch");
507 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
508}
509
510void ospf_handle_DD()
511{
512 NETSIM_ID d = pstruEventDetails->nDeviceId;
513 NETSIM_ID in = pstruEventDetails->nInterfaceId;
514 NetSim_PACKET* packet = pstruEventDetails->pPacket;
515 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
516 ptrOSPFDD dd = OSPF_HDR_GET_MSG(hdr);
517 ptrOSPF_PDS ospf = OSPF_PDS_CURRENT();
518 ptrOSPF_IF thisInterface = OSPF_IF_CURRENT();
519 OSPFID rid = hdr->RouterId;
520 ptrOSPF_NEIGHBOR neigh = OSPF_NEIGHBOR_FIND(thisInterface, rid);
521
522 print_ospf_log(OSPF_LOG, "Time %0.4lf ms, Router %d interface %d (%s) received DD msg from neighbor %s",
523 pstruEventDetails->dEventTime / MILLISECOND,
524 d,
525 in,
526 DEVICE_NWADDRESS(d, in)->str_ip,
527 hdr->RouterId->str_ip);
528
529 if (!validate_dd_msg(thisInterface, neigh, dd))
530 {
531 print_ospf_log(OSPF_LOG, "DD msg is not validated. Deleting DD msg...");
532 goto TERMINATE_PROCESSING_DD;
533 }
534
535 bool isDuplicate = ospf_dd_check_duplicate(neigh, hdr);
536
537 OSPF_HDR_FREE(neigh->lastrecvDDPacket);
538 neigh->lastrecvDDPacket = OSPF_HDR_COPY(hdr);
539
540 print_ospf_log(OSPF_LOG, "Neighbor state is %s", strNeighborState[neigh->state]);
541
542 switch (neigh->state)
543 {
544 case OSPFNEIGHSTATE_DOWN:
545 case OSPFNEIGHSTATE_Attempt:
546 case OSPFNEIGHSTATE_2Way:
547 print_ospf_log(OSPF_LOG, "Ignoring DD msg");
548 break;
549 case OSPFNEIGHSTATE_Init:
550 ospf_process_dd_in_init_state(neigh, hdr);
551 if (neigh->state != OSPFNEIGHSTATE_ExStart)
552 break;
553 case OSPFNEIGHSTATE_ExStart:
554 ospf_process_dd_in_exstart_state(ospf,
555 thisInterface,
556 neigh,
557 hdr);
558 break;
559 case OSPFNEIGHSTATE_Exchange:
560 ospf_process_dd_in_exchange_state(ospf, thisInterface, neigh, hdr, isDuplicate);
561 break;
562 case OSPFNEIGHSTATE_Loading:
563 case OSPFNEIGHSTATE_Full:
564 ospf_process_dd_in_loading_or_full_state(thisInterface, neigh, hdr, isDuplicate);
565 break;
566 default:
567 fnNetSimError("Unknown neighbor state %s in %s.",
568 strNeighborState[neigh->state],
569 __FUNCTION__);
570 break;
571 }
572
573TERMINATE_PROCESSING_DD:
574 fn_NetSim_Packet_FreePacket(packet);
575 pstruEventDetails->pPacket = NULL;
576 print_ospf_log(OSPF_LOG, "\n");
577}