NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
OSPF_LSA.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_Neighbor.h"
20#include "OSPF_Interface.h"
21#include "OSPF_RoutingTable.h"
22#include "OSPF_List.h"
23
24static void ospf_lsa_printHdr(char* logid,
25 ptrOSPFLSAHDR LSHeader)
26{
27 print_ospf_Dlog(logid, "Age = %d\tType = %s",
28 LSHeader->LSAge,
29 strLSTYPE[LSHeader->LSType]);
30 print_ospf_Dlog(logid, "Link state id = %s",
31 LSHeader->LinkStateID->str_ip);
32 print_ospf_Dlog(logid, "Advertising router = %s",
33 LSHeader->AdvertisingRouter->str_ip);
34 print_ospf_Dlog(logid, "seq number = %d",
35 LSHeader->LSSequenceNumber);
36}
37
38void ospf_lsa_print(char* logid,
39 ptrOSPFLSAHDR LSHeader,
40 char* msg)
41{
42 if (!ospf_dlog_isEnable(logid))
43 return;
44
45 print_ospf_Dlog(logid, "\n.....Time %lf.........\n",
46 OSPF_CURR_TIME());
47 print_ospf_Dlog(logid, msg);
48 ospf_lsa_printHdr(logid, LSHeader);
49 switch (LSHeader->LSType)
50 {
51 case LSTYPE_ROUTERLSA:
52 ospf_lsa_printRLSA(logid, LSHeader->lsaInfo);
53 break;
54 default:
55 fnNetSimError("Unknown LS Type %s in %s",
56 strLSTYPE[LSHeader->LSType], __FUNCTION__);
57 break;
58 }
59}
60
61void ospf_lsa_printList(char* logid,
62 ptrOSPFLIST list,
63 char* name)
64{
65 if (!ospf_dlog_isEnable(logid))
66 return;
67
68 print_ospf_Dlog(logid, "\n.......Time = %lf, %s..........",
69 OSPF_CURR_TIME(),
70 name);
71 print_ospf_Dlog(logid, "Item Count = %d", ospf_list_get_size(list));
72 ptrOSPFLSAHDR lsa = NULL;
73 void* pass = ospf_list_newIterator();
74 while ((lsa=ospf_list_iterate_mem(list,pass))!=NULL)
75 {
76 ospf_lsa_print(logid, lsa, name);
77 }
78 ospf_list_deleteIterator(pass);
79}
80
81void ospf_lsa_schedule_routerLSA(ptrOSPF_PDS ospf,
82 ptrOSPFAREA_DS area,
83 bool isFlush)
84{
85 double delay = 0;
86
87 if (area->isRouterLSTimer)
88 return; // LS Timer is already schedule
89
90 area->isRouterLSTimer = true;
91
92 //Calculate delay
93 if (!area->lastLSAOriginateTime)
94 delay = NETSIM_RAND_01() * OSPF_BROADCAST_JITTER + 1;
95 else if (OSPF_CURR_TIME() - area->lastLSAOriginateTime >=
96 ospf->minLSInterval)
97 delay = NETSIM_RAND_01() * OSPF_BROADCAST_JITTER;
98 else
99 delay = ospf->minLSInterval -
100 (OSPF_CURR_TIME() - area->lastLSAOriginateTime);
101
102 ptrEVENTLSDB lsdb = calloc(1, sizeof* lsdb);
103 lsdb->lsType = LSTYPE_ROUTERLSA;
104 lsdb->area = area;
105 lsdb->isFlush = isFlush;
106 ospf_event_add(pstruEventDetails->dEventTime + delay,
107 pstruEventDetails->nDeviceId,
108 pstruEventDetails->nInterfaceId,
109 OSPF_SCHEDULELSDB,
110 NULL,
111 lsdb);
112}
113
114void ospf_lsa_scheduleNWLSA(ptrOSPF_PDS ospf,
115 ptrOSPF_IF thisInterface,
116 ptrOSPFAREA_DS area,
117 bool isFlush)
118{
119 double delay;
120 ptrOSPFLSAHDR oldLSA = ospf_lsdb_lookup_lsaList(area->nwLSAList,
121 ospf->routerId,
122 thisInterface->IPIfAddr);
123
124 bool isHaveAdjNeigh = false;
125 isHaveAdjNeigh = ospf_is_dr_router_fulladjacentwithAnother(thisInterface);
126
127 if (isHaveAdjNeigh && !isFlush)
128 {
129 }
130 else if (oldLSA && (!isHaveAdjNeigh || isFlush))
131 isFlush = true;
132 else
133 return;
134
135 if (thisInterface->networkLSTimer && !isFlush)
136 return;
137
138 thisInterface->networkLSTimerSeqNumber++;
139
140 if (thisInterface->networkLSAOriginateTime == 0 ||
141 OSPF_CURR_TIME() - thisInterface->networkLSAOriginateTime >=
142 ospf->minLSInterval)
143 {
144 delay = NETSIM_RAND_01()*OSPF_BROADCAST_JITTER;
145 }
146 else
147 {
148 delay = ospf->minLSInterval -
149 (OSPF_CURR_TIME() - thisInterface->networkLSAOriginateTime);
150 }
151
152 thisInterface->networkLSTimer = true;
153 ptrEVENTLSDB l = calloc(1, sizeof* l);
154 l->area = area;
155 l->isFlush = isFlush;
156 l->lsType = LSTYPE_NETWORKLSA;
157 l->nwLSASeqNum = thisInterface->networkLSTimerSeqNumber;
158
159 ospf_event_add(OSPF_CURR_TIME() + delay,
160 ospf->myId,
161 thisInterface->id,
162 OSPF_SCHEDULELSDB,
163 NULL,
164 l);
165}
166
167void ospf_lsa_scheduleSummaryLSA(ptrOSPF_PDS ospf,
168 ptrOSPF_IF thisInterface,
169 ptrOSPFAREA_DS area,
170 NETSIM_IPAddress destAddr,
171 NETSIM_IPAddress destMask,
172 OSPFDESTTYPE destType,
173 bool isFlush)
174{
175 ptrEVENTLSDB l = calloc(1, sizeof* l);
176 l->area = area;
177 l->destAddr = destAddr;
178 l->destMask = destMask;
179 l->isFlush = isFlush;
180 l->destType = destType;
181 if (destType == OSPFDESTTYPE_NETWORK)
182 l->lsType = LSTYPE_SUMMARYLSA_NETWORK;
183 else if (destType == OSPFDESTTYPE_ROUTER)
184 l->lsType = LSTYPE_SUMMARYLSA_ROUTER;
185
186 ospf_event_add(OSPF_CURR_TIME() + ospf->minLSInterval,
187 ospf->myId,
188 thisInterface->id,
189 OSPF_SCHEDULELSDB,
190 NULL,
191 l);
192}
193
194void OSPFLSAINFO_FREE(ptrOSPFLSAHDR lsa)
195{
196 switch (lsa->LSType)
197 {
198 case LSTYPE_ROUTERLSA:
199 OSPFLSAINFO_FREE_RLSA(lsa->lsaInfo);
200 break;
201 case LSTYPE_NETWORKLSA:
202 case LSTYPE_SUMMARYLSA_NETWORK:
203 case LSTYPE_SUMMARYLSA_ROUTER:
204 default:
205 fnNetSimError("Unknown LSTYPE %d in %s",
206 lsa->LSType,
207 __FUNCTION__);
208 break;
209 }
210}
211
212void* OSPFLSAINFO_COPY(ptrOSPFLSAHDR lsa)
213{
214 switch (lsa->LSType)
215 {
216 case LSTYPE_ROUTERLSA:
217 return OSPFLSAINFO_COPY_RLSA(lsa->lsaInfo);
218 break;
219 case LSTYPE_NETWORKLSA:
220 case LSTYPE_SUMMARYLSA_NETWORK:
221 case LSTYPE_SUMMARYLSA_ROUTER:
222 default:
223 fnNetSimError("Unknown LSTYPE %d in %s",
224 lsa->LSType,
225 __FUNCTION__);
226 break;
227 }
228 return NULL;
229}
230
231void OSPF_LSA_MSG_FREE(ptrOSPFLSAHDR hdr)
232{
233 OSPFLSAINFO_FREE(hdr);
234 free(hdr);
235}
236
237ptrOSPFLSAHDR OSPF_LSA_MSG_COPY(ptrOSPFLSAHDR hdr)
238{
239 ptrOSPFLSAHDR lsa = calloc(1, sizeof* lsa);
240 memcpy(lsa, hdr, sizeof* lsa);
241 lsa->lsaInfo = OSPFLSAINFO_COPY(hdr);
242 return lsa;
243}
244
245ptrOSPFLSAHDR OSPF_LSA_HDR_COPY(ptrOSPFLSAHDR lsa)
246{
247 ptrOSPFLSAHDR l = calloc(1, sizeof* l);
248 memcpy(l, lsa, sizeof* l);
249 l->lsaInfo = NULL;
250 return l;
251}
252
253void OSPF_LSA_HDR_FREE(ptrOSPFLSAHDR lsa)
254{
255 free(lsa);
256}
257
258ptrOSPFLSAHDR ospf_lsa_find_old_lsa(ptrOSPFLIST list,
259 OSPFID rid,
260 OSPFID lid)
261{
262 void* pass = ospf_list_newIterator();
263 ptrOSPFLSAHDR hdr = NULL;
264 while ((hdr = ospf_list_iterate_mem(list, pass)) != NULL)
265 {
266 if (!OSPFID_COMPARE(hdr->AdvertisingRouter, rid) &&
267 !OSPFID_COMPARE(hdr->LinkStateID, lid))
268 {
269 ospf_list_deleteIterator(pass);
270 return hdr;
271 }
272 }
273 ospf_list_deleteIterator(pass);
274 return NULL;
275}
276
277bool ospf_lsa_update_lsahdr(ptrOSPF_PDS ospf,
278 ptrOSPFAREA_DS area,
279 ptrOSPFLSAHDR lsa,
280 ptrOSPFLSAHDR old,
281 LSTYPE lstype)
282{
283 lsa->LSType = lstype;
284 lsa->length = OSPFLSAHDR_LEN;
285 if (old)
286 {
287 if (old->LSSequenceNumber == OSPF_MAX_SEQUENCE_NUMBER &&
288 ospf_lsa_maskDoNotAge(ospf,old->LSAge) < ospf->LSAMaxAge)
289 {
290 ospf_lsa_flush(ospf, area, old);
291 return false;
292 }
293 else if (ospf_lsa_maskDoNotAge(ospf,old->LSAge) == ospf->LSAMaxAge)
294 {
295 // Max Age LSA is still in the Retransmission List.
296 // New LSA will be originated after removal from list.
297 return false;
298 }
299 lsa->LSSequenceNumber = old->LSSequenceNumber + 1;
300 }
301 else
302 {
303 lsa->LSSequenceNumber = OSPF_INITIAL_SEQUENCE_NUMBER;
304 }
305 return true;
306}
307
308void ospf_lsahdr_add_lsa(ptrOSPFLSAHDR lhdr,
309 void* lsa,
310 UINT16 len)
311{
312 lhdr->lsaInfo = lsa;
313 lhdr->length += len;
314}
315
316static void ospf_lsa_removeFromRxtList(ptrOSPF_PDS ospf,
317 OSPFID area,
318 ptrOSPFLSAHDR lsa)
319{
320 UINT i;
321 for (i = 0; i < ospf->ifCount; i++)
322 {
323 ptrOSPF_IF ospfIf = ospf->ospfIf[i];
324 if (OSPFID_COMPARE(area, ospfIf->areaId))
325 continue;
326 UINT n;
327 for (n = 0; n < ospfIf->neighborRouterCount; n++)
328 {
329 ptrOSPF_NEIGHBOR neigh = ospfIf->neighborRouterList[n];
330 ptrOSPFLSAHDR hdr;
331 ospf_lsa_printList(form_dlogId("RXTLIST", ospf->myId), neigh->neighLSRxtList, "before Rxlist remove");
332 void* pass = ospf_list_newIterator();
333 while ((hdr = ospf_list_iterate_mem(neigh->neighLSRxtList, pass)) != NULL)
334 {
335 if (!OSPFID_COMPARE(lsa->LinkStateID, hdr->LinkStateID) &&
336 lsa->LSType == hdr->LSType &&
337 !OSPFID_COMPARE(lsa->AdvertisingRouter, hdr->AdvertisingRouter))
338 {
339 ospf_list_delete_mem(neigh->neighLSRxtList, hdr, pass);
340 }
341 }
342 ospf_list_deleteIterator(pass);
343 ospf_lsa_printList(form_dlogId("RXTLIST", ospf->myId), neigh->neighLSRxtList, "after Rxlist remove");
344 if (ospf_list_is_empty(neigh->neighLSRxtList) &&
345 neigh->LSRxtTimer)
346 {
347 neigh->LSRxtTimer = false;
348 neigh->LSRxtSeqNum++;
349 }
350 }
351 }
352}
353
354bool ospf_lsa_checkForDoNotAge(ptrOSPF_PDS ospf,
355 UINT16 routerLSAAge)
356{
357 if (ospf->supportDC)
358 {
359 if (routerLSAAge & OSPF_DO_NOT_AGE)
360 return true;
361 else
362 return false;
363 }
364 else
365 {
366 return false;
367 }
368}
369
370UINT16 ospf_lsa_maskDoNotAge(ptrOSPF_PDS ospf,
371 UINT16 routerLSAAge)
372{
373 if (ospf_lsa_checkForDoNotAge(ospf, routerLSAAge))
374 return routerLSAAge & ~OSPF_DO_NOT_AGE;
375 else
376 return routerLSAAge;
377}
378
379void ospf_lsa_assignNewLSAge(ptrOSPF_PDS ospf,
380 UINT16* routerLSAAge,
381 UINT16 newLSAAge)
382{
383 if (ospf_lsa_checkForDoNotAge(ospf, *routerLSAAge))
384 {
385 *routerLSAAge = OSPF_DO_NOT_AGE | newLSAAge;
386 }
387 else
388 {
389 *routerLSAAge = newLSAAge;
390 }
391}
392
393static INT16 ospf_lsa_DiffOfAge(ptrOSPF_PDS ospf,
394 UINT16 a1,
395 UINT16 a2)
396{
397 a1 = ospf_lsa_maskDoNotAge(ospf, a1);
398 a2 = ospf_lsa_maskDoNotAge(ospf, a2);
399
400 return (a1 - a2);
401}
402
403int ospf_lsa_compare(ptrOSPF_PDS ospf,
404 ptrOSPFLSAHDR oldLS,
405 ptrOSPFLSAHDR newLS)
406{
407 /// RFC 2328: Section 13.1
408 if (newLS->LSSequenceNumber > oldLS->LSSequenceNumber)
409 return 1;
410
411 if (oldLS->LSSequenceNumber > newLS->LSSequenceNumber)
412 return -1;
413
414 if (ospf_lsa_maskDoNotAge(ospf, newLS->LSAge) >= ospf->LSAMaxAge &&
415 ospf_lsa_maskDoNotAge(ospf, oldLS->LSAge) < ospf->LSAMaxAge)
416 return 1;
417
418 if (ospf_lsa_maskDoNotAge(ospf, oldLS->LSAge) >= ospf->LSAMaxAge &&
419 ospf_lsa_maskDoNotAge(ospf, newLS->LSAge) < ospf->LSAMaxAge)
420 return -1;
421
422 if ((abs(ospf_lsa_DiffOfAge(ospf, newLS->LSAge, oldLS->LSAge)) >
423 OSPF_LSA_MAX_AGE_DIFF / SECOND) &&
424 (ospf_lsa_maskDoNotAge(ospf, newLS->LSAge) <
425 ospf_lsa_maskDoNotAge(ospf, oldLS->LSAge)))
426 return 1;
427
428 if ((abs(ospf_lsa_DiffOfAge(ospf, newLS->LSAge, oldLS->LSAge)) >
429 OSPF_LSA_MAX_AGE_DIFF / SECOND) &&
430 (ospf_lsa_maskDoNotAge(ospf, newLS->LSAge) >
431 ospf_lsa_maskDoNotAge(ospf, oldLS->LSAge)))
432 return -1;
433
434 return 0;
435}
436
437bool ospf_lsa_compareToListMem(ptrOSPF_PDS ospf,
438 ptrOSPFLSAHDR oldLS,
439 ptrOSPFLSAHDR newLS)
440{
441 if (oldLS->LSType == newLS->LSType &&
442 !OSPFID_COMPARE(oldLS->AdvertisingRouter, newLS->AdvertisingRouter) &&
443 !OSPFID_COMPARE(oldLS->LinkStateID, newLS->LinkStateID) &&
444 !ospf_lsa_compare(ospf, oldLS, newLS))
445 return true;
446 return false;
447}
448
449void ospf_lsa_queueToFlood(ptrOSPF_PDS ospf,
450 ptrOSPF_IF thisInterface,
451 ptrOSPFLSAHDR lsa)
452{
453 void* item = ospf_list_newIterator();
454 ptrOSPFLSAHDR hdr = NULL;
455 ptrOSPFLSAHDR updateLSA = OSPF_LSA_MSG_COPY(lsa);
456 while ((hdr = ospf_list_iterate_mem(thisInterface->updateLSAList, item)) != NULL)
457 {
458 if (hdr->LSAge == lsa->LSAge &&
459 !OSPFID_COMPARE(hdr->LinkStateID, lsa->LinkStateID) &&
460 !OSPFID_COMPARE(hdr->AdvertisingRouter, lsa->AdvertisingRouter))
461 {
462 if (ospf_lsa_compare(ospf, hdr, lsa) > 0)
463 {
464 ospf_list_delete_mem(thisInterface->updateLSAList, hdr, item);
465 ospf_list_add_mem(thisInterface->updateLSAList, updateLSA);
466 }
467 return;
468 }
469 }
470 ospf_list_deleteIterator(item);
471 ospf_list_add_mem(thisInterface->updateLSAList, updateLSA);
472}
473
474bool ospf_lsa_flood(ptrOSPF_PDS pds,
475 OSPFID area,
476 ptrOSPFLSAHDR lsa,
477 NETSIM_IPAddress srcAddr,
478 NETSIM_ID in)
479{
480 bool floodBack = false;
481 ptrOSPFLIST list = ospf_list_init(NULL, NULL);
482
483 ospf_lsa_removeFromRxtList(pds, area, lsa);
484 UINT i;
485 for (i = 0; i < pds->ifCount; i++)
486 {
487 bool isAddedToRxtList = false;
488 ptrOSPF_IF ospf = pds->ospfIf[i];
489
490 if (ospf->State == OSPFIFSTATE_DOWN)
491 continue;
492
493 if (OSPFID_COMPARE(ospf->areaId, area))
494 continue;
495
496 UINT n;
497 for (n = 0; n < ospf->neighborRouterCount; n++)
498 {
499 ptrOSPF_NEIGHBOR neigh = ospf->neighborRouterList[n];
500 if(neigh->state <OSPFNEIGHSTATE_Exchange)
501 continue;
502
503 if (neigh->state != OSPFNEIGHSTATE_Full)
504 {
505 ptrOSPFLSAHDR lsHdr = ospf_lsReq_searchFromList(neigh, lsa);
506
507 if (lsHdr)
508 {
509 int isRecent = ospf_lsa_compare(pds, lsHdr, lsa);
510 if (isRecent < 0)
511 continue;
512 if (isRecent == 0)
513 {
514 ospf_lsreq_removeFromReqList(neigh->neighLSReqList, lsHdr);
515
516 if (ospf_list_is_empty(neigh->neighLSReqList) &&
517 neigh->state == OSPFNEIGHSTATE_Loading)
518 {
519 // Cancel retransmission timer
520 neigh->LSRxtSeqNum += 1;
521 ospf_event_set_and_call(OSPF_LoadingDone,
522 neigh);
523 continue;
524 }
525 }
526 else
527 {
528 ospf_lsreq_removeFromReqList(neigh->neighLSReqList, lsHdr);
529
530 if (ospf_list_is_empty(neigh->neighLSReqList) &&
531 neigh->state == OSPFNEIGHSTATE_Loading)
532 {
533 // Cancel retransmission timer
534 neigh->LSRxtSeqNum += 1;
535 ospf_list_add_mem(list, neigh);
536 }
537 }
538 }
539 }
540
541 if (!srcAddr || !IP_COMPARE(srcAddr, neigh->neighborIPAddr))
542 continue;
543
544 ptrOSPFLSAHDR rxtlsa = OSPF_LSA_MSG_COPY(lsa);
545 ospf_list_add_mem(neigh->neighLSRxtList, rxtlsa);
546 ospf_lsa_printList(form_dlogId("RXTLIST", pds->myId), neigh->neighLSRxtList, "add Rxlist");
547 isAddedToRxtList = true;
548 }
549 if (!isAddedToRxtList)
550 continue;
551
552 if (ospf->Type == OSPFIFTYPE_BROADCAST &&
553 IP_COMPARE(srcAddr, ANY_DEST) &&
554 ospf->id == in)
555 {
556 if (!IP_COMPARE(srcAddr, ospf->designaterRouter) ||
557 !IP_COMPARE(srcAddr, ospf->backupDesignaterRouter))
558 continue;
559
560 if (ospf->State == OSPFIFSTATE_BACKUP)
561 continue;
562 }
563
564 if (IP_COMPARE(srcAddr, ANY_DEST) &&
565 ospf->id == in)
566 floodBack = true;
567
568 ospf_lsa_queueToFlood(pds, ospf, lsa);
569
570 if (!ospf->isFloodTimerSet)
571 {
572 double t = pstruEventDetails->dEventTime;
573 t = max(t, ospf->lastFloodTimer + pds->minLSInterval);
574 t += pds->dFloodTimer*NETSIM_RAND_01();
575 ospf_event_add(t,
576 pstruEventDetails->nDeviceId,
577 ospf->id,
578 OSPF_FLOODTIMER,
579 NULL,
580 NULL);
581 ospf->lastFloodTimer = t;
582 ospf->isFloodTimerSet = true;
583 }
584 }
585
586 void* pass = ospf_list_newIterator();
587 ptrOSPF_NEIGHBOR neigh;
588 while ((neigh = ospf_list_iterate_mem(list, pass)) != NULL)
589 ospf_event_set_and_call(OSPF_LoadingDone, neigh);
590 ospf_list_deleteIterator(pass);
591 ospf_list_destroy(list);
592 return floodBack;
593}
594
595static bool ospf_lsa_isBodyChanged(ptrOSPFLSAHDR newLSA,
596 ptrOSPFLSAHDR oldLSA)
597{
598 switch (newLSA->LSType)
599 {
600 case LSTYPE_ROUTERLSA:
601 return ospf_rlsa_isBodyChanged(newLSA, oldLSA);
602 case LSTYPE_NETWORKLSA:
603 case LSTYPE_SUMMARYLSA_ROUTER:
604 case LSTYPE_SUMMARYLSA_NETWORK:
605 case LSTYPE_ASEXTERNALLSA:
606 fnNetSimError("Implement lsa_isbodychange function");
607#pragma message(__LOC__"Implement lsa_isbodychange function")
608 break;
609 default:
610 fnNetSimError("Unknown LS Type %d in %s\n",
611 newLSA->LSType, __FUNCTION__);
612 return false;
613 }
614 return false;
615}
616
617bool ospf_lsa_is_content_changed(ptrOSPF_PDS ospf,
618 ptrOSPFLSAHDR newLSA,
619 ptrOSPFLSAHDR oldLSA)
620{
621 if (newLSA->Options != oldLSA->Options)
622 return true;
623
624 if ((ospf_lsa_maskDoNotAge(ospf, newLSA->LSAge) == ospf->LSAMaxAge &&
625 ospf_lsa_maskDoNotAge(ospf, oldLSA->LSAge) != ospf->LSAMaxAge) ||
626 (ospf_lsa_maskDoNotAge(ospf, newLSA->LSAge) != ospf->LSAMaxAge &&
627 ospf_lsa_maskDoNotAge(ospf, oldLSA->LSAge) == ospf->LSAMaxAge))
628 return true;
629
630 if (newLSA->length != oldLSA->length)
631 return true;
632
633 if (ospf_lsa_isBodyChanged(newLSA, oldLSA))
634 return true;
635
636 return false;
637}
638
639void ospf_lsa_assignNewLSAIntoLSOrigin(ptrOSPF_PDS ospf,
640 ptrOSPFLSAHDR LSA,
641 ptrOSPFLSAHDR newLSA)
642{
643 UINT i;
644 ptrOSPFROUTINGTABLE rtTable = ospf->routingTable;
645
646 for (i = 0; i < rtTable->numRow; i++)
647 {
648 ptrOSPFROUTINGTABLEROW row = rtTable->rows[i];
649 if (row->LSOrigin == LSA)
650 row->LSOrigin = newLSA;
651 }
652}
653
654bool ospf_lsa_hasMaxAge(ptrOSPF_PDS ospf,
655 ptrOSPFLSAHDR lsa)
656{
657 return ospf_lsa_maskDoNotAge(ospf, lsa->LSAge) == ospf->LSAMaxAge;
658}
659
660static bool ospf_lsa_isPresentInMaxAgeList(ptrOSPF_PDS ospf,
661 ptrOSPFLIST list,
662 ptrOSPFLSAHDR lsa)
663{
664 ptrOSPFLSAHDR hdr;
665 void* pass = ospf_list_newIterator();
666 while ((hdr = ospf_list_iterate_mem(list, pass)) != NULL)
667 {
668 if (hdr->LSType == lsa->LSType &&
669 !OSPFID_COMPARE(hdr->LinkStateID, lsa->LinkStateID) &&
670 !OSPFID_COMPARE(hdr->AdvertisingRouter, lsa->AdvertisingRouter) &&
671 !ospf_lsa_compare(ospf, lsa, hdr))
672 {
673 ospf_list_deleteIterator(pass);
674 return true;
675 }
676 }
677 ospf_list_deleteIterator(pass);
678 return false;
679}
680
681void ospf_lsa_addToMaxAgeLSAList(ptrOSPF_PDS ospf,
682 OSPFID areaId,
683 ptrOSPFLSAHDR lsa)
684{
685 ptrOSPFAREA_DS area = OSPF_AREA_GET_ID(ospf, areaId);
686
687 if (!ospf_lsa_isPresentInMaxAgeList(ospf, area->maxAgeList, lsa))
688 {
689 ptrOSPFLSAHDR newLSA = OSPF_LSA_MSG_COPY(lsa);
690 ospf_list_add_mem(area->maxAgeList, newLSA);
691
692 if (!ospf->isMaxAgeRemovalTimerSet)
693 {
694 ospf_lsdb_scheduleMaxAgeRemovalTimer(ospf);
695 }
696 }
697}
698
699void ospf_lsa_ScheduleLSDB()
700{
701 ptrEVENTLSDB lsdb = pstruEventDetails->szOtherDetails;
702 LSTYPE lsType = lsdb->lsType;
703
704 if (lsType == LSTYPE_ROUTERLSA)
705 {
706 ospf_rlsa_originateRouterLSA(lsdb->area, lsdb->isFlush);
707 }
708 else
709 {
710 fnNetSimError("write other condition for different LSA type");
711#pragma message(__LOC__"write other condition for different LSA type")
712 }
713 free(lsdb);
714}
715
716void ospf_lsa_handle_floodTimer_event()
717{
718 ptrOSPF_IF ospf = OSPF_IF_CURRENT();
719 if (!ospf->isFloodTimerSet)
720 return;
721 ospf_lsupdate_send();
722 ospf->isFloodTimerSet = false;
723}
724
725int ospf_lsa_isMoreRecent(ptrOSPF_PDS ospf, ptrOSPFLSAHDR newLSA, ptrOSPFLSAHDR oldLSA)
726{
727 if (!oldLSA)
728 return 1;
729 if (!newLSA)
730 return 0;
731 return ospf_lsa_compare(ospf, oldLSA, newLSA);
732}
733
734bool ospf_lsa_isSelfOriginated(ptrOSPF_PDS ospf,
735 ptrOSPFLSAHDR lsa)
736{
737 if (!OSPFID_COMPARE(lsa->AdvertisingRouter, ospf->routerId) ||
738 (ospf_isMyAddr(ospf->myId, lsa->LinkStateID) &&
739 lsa->LSType == LSTYPE_NETWORKLSA))
740 return true;
741 else
742 return false;
743}
744
745void ospf_lsa_flush(ptrOSPF_PDS ospf,
746 ptrOSPFAREA_DS area,
747 ptrOSPFLSAHDR lsa)
748{
749 if (lsa->LSAge == ospf->LSAMaxAge)
750 return;
751
752 lsa->LSAge = ospf->LSAMaxAge;
753
754 ospf_lsa_flood(ospf, area->areaId, lsa, ANY_DEST, 0);
755 ospf_lsa_addToMaxAgeLSAList(ospf, area->areaId, lsa);
756 ospf_spf_scheduleCalculation(ospf);
757}
758
759void ospf_lsa_schedule(ptrOSPF_PDS ospf,
760 ptrOSPF_IF thisInterface,
761 ptrOSPFAREA_DS area,
762 ptrOSPFLSAHDR lsa)
763{
764 switch (lsa->LSType)
765 {
766 case LSTYPE_ROUTERLSA:
767 ospf_lsa_schedule_routerLSA(ospf,
768 area,
769 false);
770 break;
771 case LSTYPE_NETWORKLSA:
772 ospf_lsa_scheduleNWLSA(ospf,
773 thisInterface,
774 area,
775 false);
776 break;
777 case LSTYPE_SUMMARYLSA_NETWORK:
778 ospf_lsa_scheduleSummaryLSA(ospf,
779 thisInterface,
780 area,
781 lsa->LinkStateID,
782 DEVICE_MYMASK(),
783 OSPFDESTTYPE_NETWORK,
784 false);
785 break;
786 case LSTYPE_SUMMARYLSA_ROUTER:
787 ospf_lsa_scheduleSummaryLSA(ospf,
788 thisInterface,
789 area,
790 lsa->LinkStateID,
791 ANY_DEST,
792 OSPFDESTTYPE_ASBR,
793 false);
794 break;
795 default:
796 fnNetSimError("Unknown LS type %s in %s",
797 strLSTYPE[lsa->LSType],
798 __FUNCTION__);
799 }
800}
801
802static bool ospf_nwlsa_hasLink(ptrOSPF_PDS ospf,
803 ptrOSPFLSAHDR wlsa,
804 ptrOSPFLSAHDR vlsa)
805{
806 ospf;
807 wlsa;
808 vlsa;
809#pragma message(__LOC__"Implement after NW LSA implementation")
810 fnNetSimError("Implement after NW LSA implementation");
811 return false;
812}
813
814bool ospf_lsa_hasLink(ptrOSPF_PDS ospf,
815 ptrOSPFLSAHDR wlsa,
816 ptrOSPFLSAHDR vlsa)
817{
818 if (wlsa->LSType == LSTYPE_ROUTERLSA)
819 return ospf_rlsa_hasLink(ospf, wlsa, vlsa);
820 else if (wlsa->LSType == LSTYPE_NETWORKLSA)
821 return ospf_nwlsa_hasLink(ospf, wlsa, vlsa);
822 return false;
823}