15#include "NetSim_utility.h"
19#include "OSPF_Interface.h"
20#include "OSPF_Neighbor.h"
23void OSPF_DD_MSG_NEW(ptrOSPFPACKETHDR hdr)
25 ptrOSPFDD dd = calloc(1,
sizeof* dd);
32ptrOSPFDD OSPF_DD_MSG_COPY(ptrOSPFDD dd)
34 ptrOSPFDD d = calloc(1,
sizeof* d);
35 memcpy(d, dd,
sizeof* d);
37 d->LSAHeader = calloc(dd->numLSA,
sizeof* d->LSAHeader);
39 for (i = 0; i < dd->numLSA; i++)
40 d->LSAHeader[i] = OSPF_LSA_HDR_COPY(dd->LSAHeader[i]);
44void OSPF_DD_MSG_FREE(ptrOSPFDD dd)
47 for (i = 0; i < dd->numLSA; i++)
48 OSPF_LSA_HDR_FREE(dd->LSAHeader[i]);
53static void set_DD_param_in_exstart(ptrOSPFPACKETHDR hdr,
55 ptrOSPF_NEIGHBOR neigh)
57 ptrOSPFDD dd = OSPF_HDR_GET_MSG(hdr);
58 if (ospf->Type == OSPFIFTYPE_VIRTUALLINK)
61 dd->InterfaceMTU = INTERFACE_MTU_DEFAULT;
62 dd->DDSequenceNumber = neigh->DDSeqNo;
66 neigh->IMMS = dd->IMMS;
69static ptrOSPFLSAHDR* ospf_DD_getTopLSAFromList(ptrOSPFLIST list,
73 ptrOSPFLSAHDR* ret = NULL;
76 while ((lsa = ospf_list_get_mem(list)) != NULL)
79 ret = realloc(ret, (c + 1) *
sizeof* ret);
81 ret = calloc(1,
sizeof* ret);
91static void set_DD_param_in_exchange(NetSim_PACKET* packet,
93 ptrOSPF_NEIGHBOR neigh)
95 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
96 ptrOSPFDD dd = OSPF_HDR_GET_MSG(hdr);
97 if (ospf->Type == OSPFIFTYPE_VIRTUALLINK)
100 dd->InterfaceMTU = INTERFACE_MTU_DEFAULT;
101 dd->DDSequenceNumber = neigh->DDSeqNo;
103 UINT maxLSAHdrCount = OSPF_DD_MAX_LSA_COUNT();
104 ptrOSPFLSAHDR* lsahdr = ospf_DD_getTopLSAFromList(neigh->neighDBSummaryList,
108 dd->LSAHeader = lsahdr;
109 if (!ospf_list_is_empty(neigh->neighDBSummaryList))
114 neigh->IMMS = dd->IMMS;
116 OSPF_HDR_INCREASE_LEN(packet, dd->numLSA*OSPFLSAHDR_LEN);
119static void ospf_DD_update_dst(NetSim_PACKET* packet,
120 ptrOSPF_NEIGHBOR neigh)
122 add_dest_to_packet(packet, neigh->devId);
123 packet->pstruNetworkData->szDestIP = neigh->neighborIPAddr;
124 packet->pstruNetworkData->nTTL = 2;
127static void send_DD_msg(ptrOSPF_IF ospf,
128 ptrOSPF_NEIGHBOR neigh)
130 OSPFMSG type = OSPFMSG_DD;
131 NetSim_PACKET* packet = OSPF_PACKET_NEW(pstruEventDetails->dEventTime,
133 pstruEventDetails->nDeviceId,
134 pstruEventDetails->nInterfaceId);
136 ospf_DD_update_dst(packet, neigh);
137 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
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);
144 OSPF_SEND_PACKET(packet);
146 if (neigh->lastSentDDPacket)
147 OSPF_HDR_FREE(neigh->lastSentDDPacket);
148 neigh->lastSentDDPacket = OSPF_HDR_COPY(hdr);
149 neigh->lastDDMsgSentTime = pstruEventDetails->dEventTime;
152static void copy_DD_param(ptrOSPFPACKETHDR hdr,
153 ptrOSPF_NEIGHBOR neigh)
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;
163 dd->numLSA = old->numLSA;
164 dd->LSAHeader = calloc(dd->numLSA,
sizeof* dd->LSAHeader);
166 for (i = 0; i < old->numLSA; i++)
167 dd->LSAHeader[i] = OSPF_LSA_HDR_COPY(old->LSAHeader[i]);
170 dd->IMMS = old->IMMS;
173static void resend_DD_msg(ptrOSPF_IF ospf,
174 ptrOSPF_NEIGHBOR neigh)
178 OSPFMSG type = OSPFMSG_DD;
179 NetSim_PACKET* packet = OSPF_PACKET_NEW(pstruEventDetails->dEventTime,
181 pstruEventDetails->nDeviceId,
182 pstruEventDetails->nInterfaceId);
184 ospf_DD_update_dst(packet, neigh);
185 ptrOSPFPACKETHDR hdr = OSPF_PACKET_GET_HDR(packet);
187 copy_DD_param(hdr, neigh);
188 OSPF_SEND_PACKET(packet);
190 if (neigh->lastSentDDPacket)
191 OSPF_HDR_FREE(neigh->lastSentDDPacket);
192 neigh->lastSentDDPacket = OSPF_HDR_COPY(hdr);
193 neigh->lastDDMsgSentTime = pstruEventDetails->dEventTime;
196static void add_DD_rxmt_timer_in_exstart_state(ptrOSPF_IF ospf,
197 ptrOSPF_NEIGHBOR neigh)
199 ospf_event_add(pstruEventDetails->dEventTime + ospf->RxmtInterval*SECOND,
200 pstruEventDetails->nDeviceId,
201 pstruEventDetails->nInterfaceId,
202 OSPF_DD_RXMT_IN_EXSTART,
207void start_sending_dd_msg()
209 ptrOSPF_IF ospf = OSPF_IF_CURRENT();
210 ptrOSPF_NEIGHBOR neigh = pstruEventDetails->szOtherDetails;
211 if (neigh->state != OSPFNEIGHSTATE_ExStart)
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");
226static void ospf_process_DD(ptrOSPF_PDS ospf,
227 ptrOSPF_IF thisInterface,
228 ptrOSPF_NEIGHBOR neigh,
229 ptrOSPFPACKETHDR hdr)
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;
236 for (i = 0; i < numLSA; i++)
238 ptrOSPFLSAHDR lsa = dd->LSAHeader[i];
239 ptrOSPFLSAHDR oldLsa = NULL;
242 if (lsa->LSType < LSTYPE_ROUTERLSA ||
243 lsa->LSType >= LSTYPE_UNDEFINED)
245 print_ospf_log(OSPF_LOG,
"Unknown LSA type %d. Discard DD packet",
248 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
253 oldLsa = ospf_lsdb_lookup(ospf, area, lsa->LSType,
254 lsa->AdvertisingRouter, lsa->LinkStateID);
260 ospf_lsa_compare(ospf, oldLsa, lsa) > 0)
262 print_ospf_log(OSPF_LOG,
"Adding LSA to request list");
263 ospf_lsreq_insertToList(neigh, lsa, OSPF_CURR_TIME());
270 if (!isBitSet(neigh->IMMS, DD_MORE_BIT_INDEX) &&
273 print_ospf_log(OSPF_LOG,
"Scheduling event Exchange_Done");
274 ospf_event_add(pstruEventDetails->dEventTime,
275 pstruEventDetails->nDeviceId,
276 pstruEventDetails->nInterfaceId,
283 print_ospf_log(OSPF_LOG,
"More bit is set. Sending DD msg");
284 send_DD_msg(thisInterface, neigh);
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))
295 print_ospf_log(OSPF_LOG,
"Scheduling event Exchange_Done");
296 ospf_event_add(pstruEventDetails->dEventTime,
297 pstruEventDetails->nDeviceId,
298 pstruEventDetails->nInterfaceId,
306static bool validate_dd_msg(ptrOSPF_IF ospf,
307 ptrOSPF_NEIGHBOR neigh,
312 if (dd->InterfaceMTU > INTERFACE_MTU_DEFAULT)
318 if (neigh->state == OSPFNEIGHSTATE_DOWN)
321 if (neigh->state == OSPFNEIGHSTATE_Attempt)
327static bool ospf_dd_check_duplicate(ptrOSPF_NEIGHBOR neigh,
328 ptrOSPFPACKETHDR hdr)
330 if (!neigh->lastrecvDDPacket)
332 ptrOSPFDD n = hdr->ospfMSG;
333 ptrOSPFDD o = neigh->lastrecvDDPacket->ospfMSG;
335 if (n->DDSequenceNumber == o->DDSequenceNumber &&
336 n->IMMS == o->IMMS &&
337 n->Option == o->Option)
343static void ospf_process_dd_in_exstart_state(ptrOSPF_PDS ospf,
345 ptrOSPF_NEIGHBOR neigh,
346 ptrOSPFPACKETHDR hdr)
348 ptrOSPFDD dd = hdr->ospfMSG;
349 if (DD_IS_INIT(dd) &&
353 OSPFID_ISGREATER(hdr->RouterId,ospf->routerId))
355 neigh->DDSeqNo = dd->DDSequenceNumber;
356 neigh->isMaster =
false;
357 print_ospf_log(OSPF_LOG,
"I am now slave.");
359 else if (!DD_IS_INIT(dd) &&
361 dd->DDSequenceNumber == neigh->DDSeqNo &&
362 OSPFID_ISSMALLER(hdr->RouterId,ospf->routerId))
364 neigh->isMaster =
true;
365 print_ospf_log(OSPF_LOG,
"I am now master.");
369 print_ospf_log(OSPF_LOG,
"Neither master nor slave. Who i am? Ignoring DD msg.");
373 ospf_event_set_and_call(OSPF_NegotiationDone, neigh);
374 neigh->neighborOption = dd->Option;
375 ospf_process_DD(ospf, ospfif, neigh, hdr);
378static void ospf_process_dd_in_init_state(ptrOSPF_NEIGHBOR neigh,
379 ptrOSPFPACKETHDR hdr)
383 ospf_event_set_and_call(OSPF_2WayReceived, neigh);
386static void ospf_process_dd_in_exchange_state_for_duplicate(ptrOSPF_IF ospf,
387 ptrOSPF_NEIGHBOR neigh,
388 ptrOSPFPACKETHDR hdr)
393 print_ospf_log(OSPF_LOG,
"I am master. Discarding duplicate DD");
395 resend_DD_msg(ospf, neigh);
398static void ospf_process_dd_in_exchange_state(ptrOSPF_PDS ospf,
399 ptrOSPF_IF thisInterface,
400 ptrOSPF_NEIGHBOR neigh,
401 ptrOSPFPACKETHDR hdr,
406 ospf_process_dd_in_exchange_state_for_duplicate(thisInterface, neigh, hdr);
410 ptrOSPFDD dd = hdr->ospfMSG;
418 if ((DD_IS_MASTER(dd) && neigh->isMaster) ||
419 (!DD_IS_MASTER(dd) && !neigh->isMaster))
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);
433 print_ospf_log(OSPF_LOG,
"Initialize(I) bit is set");
434 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
446 if (dd->Option != neigh->neighborOption)
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);
468 if ((neigh->isMaster &&
469 neigh->DDSeqNo != dd->DDSequenceNumber) ||
471 dd->DDSequenceNumber != neigh->DDSeqNo + 1))
473 print_ospf_log(OSPF_LOG,
"DD seq number mismatch");
474 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
478 ospf_process_DD(ospf, thisInterface, neigh, hdr);
481static void ospf_process_dd_in_loading_or_full_state(ptrOSPF_IF ospf,
482 ptrOSPF_NEIGHBOR neigh,
483 ptrOSPFPACKETHDR hdr,
492 print_ospf_log(OSPF_LOG,
"Duplicate DD msg received. I am master. Discarding packet");
497 if (pstruEventDetails->dEventTime - neigh->lastDDMsgSentTime <
498 ospf->routerDeadInterval*SECOND)
500 resend_DD_msg(ospf, neigh);
506 print_ospf_log(OSPF_LOG,
"DD seq number mismatch");
507 ospf_event_set_and_call(OSPF_SeqNumberMismatch, neigh);
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);
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,
526 DEVICE_NWADDRESS(d, in)->str_ip,
527 hdr->RouterId->str_ip);
529 if (!validate_dd_msg(thisInterface, neigh, dd))
531 print_ospf_log(OSPF_LOG,
"DD msg is not validated. Deleting DD msg...");
532 goto TERMINATE_PROCESSING_DD;
535 bool isDuplicate = ospf_dd_check_duplicate(neigh, hdr);
537 OSPF_HDR_FREE(neigh->lastrecvDDPacket);
538 neigh->lastrecvDDPacket = OSPF_HDR_COPY(hdr);
540 print_ospf_log(OSPF_LOG,
"Neighbor state is %s", strNeighborState[neigh->state]);
542 switch (neigh->state)
544 case OSPFNEIGHSTATE_DOWN:
545 case OSPFNEIGHSTATE_Attempt:
546 case OSPFNEIGHSTATE_2Way:
547 print_ospf_log(OSPF_LOG,
"Ignoring DD msg");
549 case OSPFNEIGHSTATE_Init:
550 ospf_process_dd_in_init_state(neigh, hdr);
551 if (neigh->state != OSPFNEIGHSTATE_ExStart)
553 case OSPFNEIGHSTATE_ExStart:
554 ospf_process_dd_in_exstart_state(ospf,
559 case OSPFNEIGHSTATE_Exchange:
560 ospf_process_dd_in_exchange_state(ospf, thisInterface, neigh, hdr, isDuplicate);
562 case OSPFNEIGHSTATE_Loading:
563 case OSPFNEIGHSTATE_Full:
564 ospf_process_dd_in_loading_or_full_state(thisInterface, neigh, hdr, isDuplicate);
567 fnNetSimError(
"Unknown neighbor state %s in %s.",
568 strNeighborState[neigh->state],
573TERMINATE_PROCESSING_DD:
574 fn_NetSim_Packet_FreePacket(packet);
575 pstruEventDetails->pPacket = NULL;
576 print_ospf_log(OSPF_LOG,
"\n");