blob: aeff15bcbecce02eaa89abbb250d19e7d16bd5b0 [file] [log] [blame]
hasso48454372004-05-18 19:14:52 +00001/*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "log.h"
25#include "thread.h"
26#include "linklist.h"
27#include "vty.h"
28
29#include "ospf6d.h"
30#include "ospf6_proto.h"
31#include "ospf6_lsa.h"
32#include "ospf6_lsdb.h"
33#include "ospf6_message.h"
34#include "ospf6_route.h"
35#include "ospf6_spf.h"
36
37#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_interface.h"
40#include "ospf6_neighbor.h"
41
hasso6452df02004-08-15 05:52:07 +000042#include "ospf6_flood.h"
hasso48454372004-05-18 19:14:52 +000043
44struct ospf6_lsdb *
hasso6452df02004-08-15 05:52:07 +000045ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +000046{
47 struct ospf6_lsdb *lsdb = NULL;
hasso6452df02004-08-15 05:52:07 +000048 switch (OSPF6_LSA_SCOPE (lsa->header->type))
hasso48454372004-05-18 19:14:52 +000049 {
hasso6452df02004-08-15 05:52:07 +000050 case OSPF6_SCOPE_LINKLOCAL:
51 lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
52 break;
53 case OSPF6_SCOPE_AREA:
54 lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
55 break;
56 case OSPF6_SCOPE_AS:
57 lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
58 break;
59 default:
60 assert (0);
61 break;
hasso48454372004-05-18 19:14:52 +000062 }
hasso48454372004-05-18 19:14:52 +000063 return lsdb;
64}
65
hasso6452df02004-08-15 05:52:07 +000066struct ospf6_lsdb *
67ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
hasso3b4cd3a2004-05-18 19:28:32 +000068{
hasso6452df02004-08-15 05:52:07 +000069 struct ospf6_lsdb *lsdb_self = NULL;
70 switch (OSPF6_LSA_SCOPE (lsa->header->type))
hasso3b4cd3a2004-05-18 19:28:32 +000071 {
hasso6452df02004-08-15 05:52:07 +000072 case OSPF6_SCOPE_LINKLOCAL:
73 lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
74 break;
75 case OSPF6_SCOPE_AREA:
76 lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
77 break;
78 case OSPF6_SCOPE_AS:
79 lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
80 break;
81 default:
82 assert (0);
83 break;
hasso3b4cd3a2004-05-18 19:28:32 +000084 }
hasso6452df02004-08-15 05:52:07 +000085 return lsdb_self;
hasso3b4cd3a2004-05-18 19:28:32 +000086}
87
88void
hasso6452df02004-08-15 05:52:07 +000089ospf6_lsa_originate (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +000090{
hasso6452df02004-08-15 05:52:07 +000091 struct ospf6_lsa *old;
92 struct ospf6_lsdb *lsdb_self;
hasso48454372004-05-18 19:14:52 +000093
hasso6452df02004-08-15 05:52:07 +000094 /* find previous LSA */
95 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
96 lsa->header->adv_router, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +000097
hasso6452df02004-08-15 05:52:07 +000098 /* if the new LSA does not differ from previous,
99 suppress this update of the LSA */
100 if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
hasso48454372004-05-18 19:14:52 +0000101 {
hasso6452df02004-08-15 05:52:07 +0000102 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
103 zlog_info ("Suppress updating LSA: %s", lsa->name);
104 ospf6_lsa_delete (lsa);
hasso48454372004-05-18 19:14:52 +0000105 return;
106 }
107
hasso6452df02004-08-15 05:52:07 +0000108 /* store it in the LSDB for self-originated LSAs */
109 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
110 ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
111
112 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
113 LS_REFRESH_TIME);
114
115 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
hasso48454372004-05-18 19:14:52 +0000116 {
hasso6452df02004-08-15 05:52:07 +0000117 zlog_info ("LSA Originate:");
118 ospf6_lsa_header_print (lsa);
hasso48454372004-05-18 19:14:52 +0000119 }
120
hasso6452df02004-08-15 05:52:07 +0000121 if (old)
122 ospf6_flood_clear (old);
123 ospf6_flood (NULL, lsa);
124 ospf6_install_lsa (lsa);
125}
126
127void
128ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
129 struct ospf6 *process)
130{
131 lsa->lsdb = process->lsdb;
132 ospf6_lsa_originate (lsa);
133}
134
135void
136ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
137 struct ospf6_area *oa)
138{
139 lsa->lsdb = oa->lsdb;
140 ospf6_lsa_originate (lsa);
141}
142
143void
144ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
145 struct ospf6_interface *oi)
146{
147 lsa->lsdb = oi->lsdb;
148 ospf6_lsa_originate (lsa);
149}
150
151void
152ospf6_lsa_purge (struct ospf6_lsa *lsa)
153{
154 struct ospf6_lsa *self;
155 struct ospf6_lsdb *lsdb_self;
156
157 /* remove it from the LSDB for self-originated LSAs */
158 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
159 self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
160 lsa->header->adv_router, lsdb_self);
161 if (self)
hasso48454372004-05-18 19:14:52 +0000162 {
hasso6452df02004-08-15 05:52:07 +0000163 THREAD_OFF (self->expire);
164 THREAD_OFF (self->refresh);
165 ospf6_lsdb_remove (self, lsdb_self);
hasso48454372004-05-18 19:14:52 +0000166 }
167
hasso6452df02004-08-15 05:52:07 +0000168 ospf6_lsa_premature_aging (lsa);
169}
170
171
172void
173ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
174{
175 /* The LSA must be the original one (see the description
176 in ospf6_decrement_retrans_count () below) */
177 lsa->retrans_count++;
178}
179
180void
181ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
182{
183 struct ospf6_lsdb *lsdb;
184 struct ospf6_lsa *orig;
185
186 /* The LSA must be on the retrans-list of a neighbor. It means
187 the "lsa" is a copied one, and we have to decrement the
188 retransmission count of the original one (instead of "lsa"'s).
189 In order to find the original LSA, first we have to find
190 appropriate LSDB that have the original LSA. */
191 lsdb = ospf6_get_scoped_lsdb (lsa);
192
193 /* Find the original LSA of which the retrans_count should be decremented */
194 orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
195 lsa->header->adv_router, lsdb);
196 if (orig)
197 orig->retrans_count--;
198
199 assert (orig->retrans_count >= 0);
hasso48454372004-05-18 19:14:52 +0000200}
201
202/* RFC2328 section 13.2 Installing LSAs in the database */
203void
hasso6452df02004-08-15 05:52:07 +0000204ospf6_install_lsa (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +0000205{
206 struct ospf6_lsa *old;
207
208 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
209 zlog_info ("Install LSA: %s", lsa->name);
210
211 /* Remove the old instance from all neighbors' Link state
212 retransmission list (RFC2328 13.2 last paragraph) */
213 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000214 lsa->header->adv_router, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000215 if (old)
216 ospf6_flood_clear (old);
217
218 /* actually install */
219 gettimeofday (&lsa->installed, (struct timezone *) NULL);
hasso6452df02004-08-15 05:52:07 +0000220 ospf6_lsdb_add (lsa, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000221
222 return;
223}
224
hasso6452df02004-08-15 05:52:07 +0000225/* RFC2740 section 3.5.2. Sending Link State Update packets */
hasso48454372004-05-18 19:14:52 +0000226/* RFC2328 section 13.3 Next step in the flooding procedure */
227void
hasso6452df02004-08-15 05:52:07 +0000228ospf6_flood_interface (struct ospf6_neighbor *from,
229 struct ospf6_lsa *lsa, struct ospf6_interface *oi)
hasso48454372004-05-18 19:14:52 +0000230{
hasso6452df02004-08-15 05:52:07 +0000231 listnode node;
hasso48454372004-05-18 19:14:52 +0000232 struct ospf6_neighbor *on;
hasso48454372004-05-18 19:14:52 +0000233 struct ospf6_lsa *req;
234 int retrans_added = 0;
235
hasso48454372004-05-18 19:14:52 +0000236 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso6452df02004-08-15 05:52:07 +0000237 zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
hasso48454372004-05-18 19:14:52 +0000238
hasso6452df02004-08-15 05:52:07 +0000239 /* (1) For each neighbor */
240 for (node = listhead (oi->neighbor_list); node; nextnode (node))
hasso48454372004-05-18 19:14:52 +0000241 {
hasso6452df02004-08-15 05:52:07 +0000242 on = (struct ospf6_neighbor *) getdata (node);
hasso48454372004-05-18 19:14:52 +0000243
hasso6452df02004-08-15 05:52:07 +0000244 if (IS_OSPF6_DEBUG_LSA (SEND))
245 zlog_info ("To neighbor %s", on->name);
246
247 /* (a) if neighbor state < Exchange, examin next */
248 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
hasso48454372004-05-18 19:14:52 +0000249 {
hasso6452df02004-08-15 05:52:07 +0000250 if (IS_OSPF6_DEBUG_LSA (SEND))
251 zlog_info ("Neighbor state less than ExChange, next neighbor");
252 continue;
hasso48454372004-05-18 19:14:52 +0000253 }
hasso48454372004-05-18 19:14:52 +0000254
hasso6452df02004-08-15 05:52:07 +0000255 /* (b) if neighbor not yet Full, check request-list */
256 if (on->state != OSPF6_NEIGHBOR_FULL)
hasso48454372004-05-18 19:14:52 +0000257 {
hasso6452df02004-08-15 05:52:07 +0000258 if (IS_OSPF6_DEBUG_LSA (SEND))
259 zlog_info ("Neighbor not yet Full");
hasso48454372004-05-18 19:14:52 +0000260
hasso6452df02004-08-15 05:52:07 +0000261 req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
262 lsa->header->adv_router, on->request_list);
263 if (req == NULL)
hasso48454372004-05-18 19:14:52 +0000264 {
hasso6452df02004-08-15 05:52:07 +0000265 if (IS_OSPF6_DEBUG_LSA (SEND))
266 zlog_info ("Not on request-list for this neighbor");
267 /* fall through */
268 }
269 else
270 {
271 /* If new LSA less recent, examin next neighbor */
272 if (ospf6_lsa_compare (lsa, req) > 0)
hasso48454372004-05-18 19:14:52 +0000273 {
hasso6452df02004-08-15 05:52:07 +0000274 if (IS_OSPF6_DEBUG_LSA (SEND))
275 zlog_info ("Requesting is newer, next neighbor");
276 continue;
277 }
hasso48454372004-05-18 19:14:52 +0000278
hasso6452df02004-08-15 05:52:07 +0000279 /* If the same instance, delete from request-list and
280 examin next neighbor */
281 if (ospf6_lsa_compare (lsa, req) == 0)
282 {
283 if (IS_OSPF6_DEBUG_LSA (SEND))
284 zlog_info ("Requesting the same, remove it, next neighbor");
285 ospf6_lsdb_remove (req, on->request_list);
286 continue;
287 }
hasso48454372004-05-18 19:14:52 +0000288
hasso6452df02004-08-15 05:52:07 +0000289 /* If the new LSA is more recent, delete from request-list */
290 if (ospf6_lsa_compare (lsa, req) < 0)
291 {
292 if (IS_OSPF6_DEBUG_LSA (SEND))
293 zlog_info ("Received is newer, remove requesting");
294 ospf6_lsdb_remove (req, on->request_list);
295 /* fall through */
hasso48454372004-05-18 19:14:52 +0000296 }
297 }
hasso48454372004-05-18 19:14:52 +0000298 }
299
hasso6452df02004-08-15 05:52:07 +0000300 /* (c) If the new LSA was received from this neighbor,
301 examin next neighbor */
302 if (from == on)
hasso48454372004-05-18 19:14:52 +0000303 {
hasso6452df02004-08-15 05:52:07 +0000304 if (IS_OSPF6_DEBUG_LSA (SEND))
305 zlog_info ("Received is from the neighbor, next neighbor");
306 continue;
hasso48454372004-05-18 19:14:52 +0000307 }
hasso6452df02004-08-15 05:52:07 +0000308
309 /* (d) add retrans-list, schedule retransmission */
310 if (IS_OSPF6_DEBUG_LSA (SEND))
311 zlog_info ("Add retrans-list of this neighbor");
312 ospf6_increment_retrans_count (lsa);
313 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
314 if (on->thread_send_lsupdate == NULL)
315 on->thread_send_lsupdate =
316 thread_add_event (master, ospf6_lsupdate_send_neighbor,
317 on, on->ospf6_if->rxmt_interval);
318 retrans_added++;
hasso48454372004-05-18 19:14:52 +0000319 }
320
hasso6452df02004-08-15 05:52:07 +0000321 /* (2) examin next interface if not added to retrans-list */
322 if (retrans_added == 0)
323 {
324 if (IS_OSPF6_DEBUG_LSA (SEND))
325 zlog_info ("No retransmission scheduled, next interface");
326 return;
327 }
328
329 /* (3) If the new LSA was received on this interface,
330 and it was from DR or BDR, examin next interface */
331 if (from && from->ospf6_if == oi &&
332 (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
333 {
334 if (IS_OSPF6_DEBUG_LSA (SEND))
335 zlog_info ("Received is from the I/F's DR or BDR, next interface");
336 return;
337 }
338
339 /* (4) If the new LSA was received on this interface,
340 and the interface state is BDR, examin next interface */
341 if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
342 {
343 if (IS_OSPF6_DEBUG_LSA (SEND))
344 zlog_info ("Received is from the I/F, itself BDR, next interface");
345 return;
346 }
347
348 /* (5) flood the LSA out the interface. */
349 if (IS_OSPF6_DEBUG_LSA (SEND))
350 zlog_info ("Schedule flooding for the interface");
351 if (if_is_broadcast (oi->interface))
352 {
353 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
354 if (oi->thread_send_lsupdate == NULL)
355 oi->thread_send_lsupdate =
356 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
357 }
358 else
359 {
360 /* reschedule retransmissions to all neighbors */
361 for (node = listhead (oi->neighbor_list); node; nextnode (node))
362 {
363 on = (struct ospf6_neighbor *) getdata (node);
364 THREAD_OFF (on->thread_send_lsupdate);
365 on->thread_send_lsupdate =
366 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
367 }
368 }
hasso48454372004-05-18 19:14:52 +0000369}
370
hasso6452df02004-08-15 05:52:07 +0000371void
372ospf6_flood_area (struct ospf6_neighbor *from,
373 struct ospf6_lsa *lsa, struct ospf6_area *oa)
374{
375 listnode node;
376 struct ospf6_interface *oi;
377
378 for (node = listhead (oa->if_list); node; nextnode (node))
379 {
380 oi = OSPF6_INTERFACE (getdata (node));
381
382 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
383 oi != OSPF6_INTERFACE (lsa->lsdb->data))
384 continue;
385
386#if 0
387 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
388 ospf6_is_interface_virtual_link (oi))
389 continue;
390#endif/*0*/
391
392 ospf6_flood_interface (from, lsa, oi);
393 }
394}
395
396void
397ospf6_flood_process (struct ospf6_neighbor *from,
398 struct ospf6_lsa *lsa, struct ospf6 *process)
399{
400 listnode node;
401 struct ospf6_area *oa;
402
403 for (node = listhead (process->area_list); node; nextnode (node))
404 {
405 oa = OSPF6_AREA (getdata (node));
406
407 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
408 oa != OSPF6_AREA (lsa->lsdb->data))
409 continue;
410 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
411 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
412 continue;
413
414 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
415 IS_AREA_STUB (oa))
416 continue;
417
418 ospf6_flood_area (from, lsa, oa);
419 }
420}
421
422void
423ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
424{
425 ospf6_flood_process (from, lsa, ospf6);
426}
427
428void
429ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
430{
431 listnode node;
432 struct ospf6_neighbor *on;
433 struct ospf6_lsa *rem;
434
435 for (node = listhead (oi->neighbor_list); node; nextnode (node))
436 {
437 on = OSPF6_NEIGHBOR (getdata (node));
438 rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
439 lsa->header->adv_router, on->retrans_list);
440 if (rem && ! ospf6_lsa_compare (rem, lsa))
441 {
442 if (IS_OSPF6_DEBUG_LSA (DATABASE))
443 zlog_info ("Remove %s from retrans_list of %s",
444 rem->name, on->name);
445 ospf6_decrement_retrans_count (rem);
446 ospf6_lsdb_remove (rem, on->retrans_list);
447 }
448 }
449}
450
451void
452ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
453{
454 listnode node;
455 struct ospf6_interface *oi;
456
457 for (node = listhead (oa->if_list); node; nextnode (node))
458 {
459 oi = OSPF6_INTERFACE (getdata (node));
460
461 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
462 oi != OSPF6_INTERFACE (lsa->lsdb->data))
463 continue;
464
465#if 0
466 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
467 ospf6_is_interface_virtual_link (oi))
468 continue;
469#endif/*0*/
470
471 ospf6_flood_clear_interface (lsa, oi);
472 }
473}
474
475void
476ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
477{
478 listnode node;
479 struct ospf6_area *oa;
480
481 for (node = listhead (process->area_list); node; nextnode (node))
482 {
483 oa = OSPF6_AREA (getdata (node));
484
485 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
486 oa != OSPF6_AREA (lsa->lsdb->data))
487 continue;
488 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
489 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
490 continue;
491
492 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
493 IS_AREA_STUB (oa))
494 continue;
495
496 ospf6_flood_clear_area (lsa, oa);
497 }
498}
499
500void
501ospf6_flood_clear (struct ospf6_lsa *lsa)
502{
503 ospf6_flood_clear_process (lsa, ospf6);
504}
505
506
hasso48454372004-05-18 19:14:52 +0000507/* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
508static void
509ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
510 struct ospf6_neighbor *from)
511{
512 struct ospf6_interface *oi;
513
514 assert (from && from->ospf6_if);
515 oi = from->ospf6_if;
516
517 /* LSA has been flood back out receiving interface.
518 No acknowledgement sent. */
519 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
520 {
521 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000522 zlog_info ("No acknowledgement (BDR & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000523 return;
524 }
525
526 /* LSA is more recent than database copy, but was not flooded
527 back out receiving interface. Delayed acknowledgement sent
528 if advertisement received from Designated Router,
529 otherwide do nothing. */
530 if (ismore_recent < 0)
531 {
hasso48454372004-05-18 19:14:52 +0000532 if (oi->drouter == from->router_id)
533 {
534 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000535 zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
hasso48454372004-05-18 19:14:52 +0000536 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000537 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
538 if (oi->thread_send_lsack == NULL)
539 oi->thread_send_lsack =
540 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
541 }
542 else
543 {
544 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000545 zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000546 }
547 return;
548 }
549
550 /* LSA is a duplicate, and was treated as an implied acknowledgement.
551 Delayed acknowledgement sent if advertisement received from
552 Designated Router, otherwise do nothing */
553 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
554 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
555 {
hasso48454372004-05-18 19:14:52 +0000556 if (oi->drouter == from->router_id)
557 {
558 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000559 zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
hasso48454372004-05-18 19:14:52 +0000560 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000561 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
562 if (oi->thread_send_lsack == NULL)
563 oi->thread_send_lsack =
564 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
565 }
566 else
567 {
568 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000569 zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000570 }
571 return;
572 }
573
574 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
575 Direct acknowledgement sent */
576 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
577 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
578 {
579 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000580 zlog_info ("Direct acknowledgement (BDR & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000581 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
582 if (from->thread_send_lsack == NULL)
583 from->thread_send_lsack =
584 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
585 return;
586 }
587
588 /* LSA's LS age is equal to Maxage, and there is no current instance
589 of the LSA in the link state database, and none of router's
590 neighbors are in states Exchange or Loading */
591 /* Direct acknowledgement sent, but this case is handled in
592 early of ospf6_receive_lsa () */
593}
594
595static void
596ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
597 struct ospf6_neighbor *from)
598{
599 struct ospf6_interface *oi;
600
601 assert (from && from->ospf6_if);
602 oi = from->ospf6_if;
603
604 /* LSA has been flood back out receiving interface.
605 No acknowledgement sent. */
606 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
607 {
608 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000609 zlog_info ("No acknowledgement (AllOther & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000610 return;
611 }
612
613 /* LSA is more recent than database copy, but was not flooded
614 back out receiving interface. Delayed acknowledgement sent. */
615 if (ismore_recent < 0)
616 {
617 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000618 zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
hasso48454372004-05-18 19:14:52 +0000619 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000620 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
621 if (oi->thread_send_lsack == NULL)
622 oi->thread_send_lsack =
623 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
624 return;
625 }
626
627 /* LSA is a duplicate, and was treated as an implied acknowledgement.
628 No acknowledgement sent. */
629 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
630 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
631 {
632 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000633 zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
hasso48454372004-05-18 19:14:52 +0000634 return;
635 }
636
637 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
638 Direct acknowledgement sent */
639 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
640 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
641 {
642 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000643 zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000644 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
645 if (from->thread_send_lsack == NULL)
646 from->thread_send_lsack =
647 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
648 return;
649 }
650
651 /* LSA's LS age is equal to Maxage, and there is no current instance
652 of the LSA in the link state database, and none of router's
653 neighbors are in states Exchange or Loading */
654 /* Direct acknowledgement sent, but this case is handled in
655 early of ospf6_receive_lsa () */
656}
657
658void
659ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
660 struct ospf6_neighbor *from)
661{
662 struct ospf6_interface *oi;
663
664 assert (from && from->ospf6_if);
665 oi = from->ospf6_if;
666
667 if (oi->state == OSPF6_INTERFACE_BDR)
668 ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
669 else
670 ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
671}
672
673/* RFC2328 section 13 (4):
674 if MaxAge LSA and if we have no instance, and no neighbor
675 is in states Exchange or Loading
676 returns 1 if match this case, else returns 0 */
677static int
hasso6452df02004-08-15 05:52:07 +0000678ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
hasso48454372004-05-18 19:14:52 +0000679{
hasso48454372004-05-18 19:14:52 +0000680 struct ospf6_neighbor *on;
hasso6452df02004-08-15 05:52:07 +0000681 struct ospf6_interface *oi;
682 struct ospf6_area *oa;
683 struct ospf6 *process = NULL;
684 listnode i, j, k;
hasso48454372004-05-18 19:14:52 +0000685 int count = 0;
686
687 if (! OSPF6_LSA_IS_MAXAGE (lsa))
688 return 0;
689
hasso48454372004-05-18 19:14:52 +0000690 if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000691 lsa->header->adv_router, lsa->lsdb))
hasso48454372004-05-18 19:14:52 +0000692 return 0;
693
hasso6452df02004-08-15 05:52:07 +0000694 process = from->ospf6_if->area->ospf6;
695 for (i = listhead (process->area_list); i; nextnode (i))
hasso48454372004-05-18 19:14:52 +0000696 {
hasso6452df02004-08-15 05:52:07 +0000697 oa = OSPF6_AREA (getdata (i));
hasso48454372004-05-18 19:14:52 +0000698 for (j = listhead (oa->if_list); j; nextnode (j))
699 {
hasso6452df02004-08-15 05:52:07 +0000700 oi = OSPF6_INTERFACE (getdata (j));
701 for (k = listhead (oi->neighbor_list); k; nextnode (k))
702 {
703 on = OSPF6_NEIGHBOR (getdata (k));
704 if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
705 on->state == OSPF6_NEIGHBOR_LOADING)
706 count++;
707 }
hasso48454372004-05-18 19:14:52 +0000708 }
709 }
710
hasso48454372004-05-18 19:14:52 +0000711 if (count == 0)
712 return 1;
hasso48454372004-05-18 19:14:52 +0000713 return 0;
714}
715
716/* RFC2328 section 13 The Flooding Procedure */
717void
hasso6452df02004-08-15 05:52:07 +0000718ospf6_receive_lsa (struct ospf6_neighbor *from,
719 struct ospf6_lsa_header *lsa_header)
hasso48454372004-05-18 19:14:52 +0000720{
721 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
722 int ismore_recent;
723 unsigned short cksum;
hasso48454372004-05-18 19:14:52 +0000724
725 ismore_recent = 1;
hasso6452df02004-08-15 05:52:07 +0000726 assert (from);
hasso48454372004-05-18 19:14:52 +0000727
728 /* make lsa structure for received lsa */
729 new = ospf6_lsa_create (lsa_header);
730
731 if (IS_OSPF6_DEBUG_LSA (RECV))
732 {
733 zlog_info ("LSA Receive from %s", from->name);
734 ospf6_lsa_header_print (new);
735 }
736
hasso48454372004-05-18 19:14:52 +0000737 /* (1) LSA Checksum */
738 cksum = ntohs (new->header->checksum);
739 if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
740 {
741 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000742 zlog_info ("Wrong LSA Checksum, discard");
hasso48454372004-05-18 19:14:52 +0000743 ospf6_lsa_delete (new);
744 return;
745 }
746
hasso6452df02004-08-15 05:52:07 +0000747 /* (2) Examine the LSA's LS type.
748 RFC2470 3.5.1. Receiving Link State Update packets */
749 if (IS_AREA_STUB (from->ospf6_if->area) &&
750 OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
hasso48454372004-05-18 19:14:52 +0000751 {
752 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000753 zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
754 ospf6_lsa_delete (new);
755 return;
756 }
757
758 /* (3) LSA which have reserved scope is discarded
759 RFC2470 3.5.1. Receiving Link State Update packets */
760 /* Flooding scope check. LSAs with unknown scope are discarded here.
761 Set appropriate LSDB for the LSA */
762 switch (OSPF6_LSA_SCOPE (new->header->type))
763 {
764 case OSPF6_SCOPE_LINKLOCAL:
765 new->lsdb = from->ospf6_if->lsdb;
766 break;
767 case OSPF6_SCOPE_AREA:
768 new->lsdb = from->ospf6_if->area->lsdb;
769 break;
770 case OSPF6_SCOPE_AS:
771 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
772 break;
773 default:
774 if (IS_OSPF6_DEBUG_LSA (RECV))
775 zlog_info ("LSA has reserved scope, discard");
hasso48454372004-05-18 19:14:52 +0000776 ospf6_lsa_delete (new);
777 return;
778 }
779
780 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
781 is in states Exchange or Loading */
782 if (ospf6_is_maxage_lsa_drop (new, from))
783 {
784 /* log */
785 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000786 zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
hasso48454372004-05-18 19:14:52 +0000787
788 /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
hasso6452df02004-08-15 05:52:07 +0000789 ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
hasso48454372004-05-18 19:14:52 +0000790 if (from->thread_send_lsack == NULL)
791 from->thread_send_lsack =
792 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
793
794 /* b) Discard */
hasso6452df02004-08-15 05:52:07 +0000795 ospf6_lsa_delete (new);
hasso48454372004-05-18 19:14:52 +0000796 return;
797 }
798
799 /* (5) */
800 /* lookup the same database copy in lsdb */
hasso48454372004-05-18 19:14:52 +0000801 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
hasso6452df02004-08-15 05:52:07 +0000802 new->header->adv_router, new->lsdb);
hasso48454372004-05-18 19:14:52 +0000803 if (old)
804 {
805 ismore_recent = ospf6_lsa_compare (new, old);
806 if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
807 {
808 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000809 zlog_info ("Received is duplicated LSA");
hasso48454372004-05-18 19:14:52 +0000810 SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
811 }
812 }
813
814 /* if no database copy or received is more recent */
815 if (old == NULL || ismore_recent < 0)
816 {
817 /* in case we have no database copy */
818 ismore_recent = -1;
819
820 /* (a) MinLSArrival check */
821 if (old)
822 {
823 struct timeval now, res;
824 gettimeofday (&now, (struct timezone *) NULL);
825 timersub (&now, &old->installed, &res);
826 if (res.tv_sec < MIN_LS_ARRIVAL)
827 {
828 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
hasso6452df02004-08-15 05:52:07 +0000829 zlog_info ("LSA can't be updated within MinLSArrival, discard");
hasso48454372004-05-18 19:14:52 +0000830 ospf6_lsa_delete (new);
831 return; /* examin next lsa */
832 }
833 }
834
hasso6452df02004-08-15 05:52:07 +0000835 if (IS_OSPF6_DEBUG_LSA (RECV))
836 zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
837
hasso48454372004-05-18 19:14:52 +0000838 /* (b) immediately flood and (c) remove from all retrans-list */
hasso6452df02004-08-15 05:52:07 +0000839 ospf6_flood (from, new);
840
841 /* (c) Remove the current database copy from all neighbors' Link
842 state retransmission lists. */
843 /* XXX, flood_clear ? */
hasso48454372004-05-18 19:14:52 +0000844
845 /* (d), installing lsdb, which may cause routing
846 table calculation (replacing database copy) */
hasso6452df02004-08-15 05:52:07 +0000847 ospf6_install_lsa (new);
hasso48454372004-05-18 19:14:52 +0000848
849 /* (e) possibly acknowledge */
850 ospf6_acknowledge_lsa (new, ismore_recent, from);
851
hasso6452df02004-08-15 05:52:07 +0000852 /* (f) Self Originated LSA, section 13.4 */
853 if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
hasso48454372004-05-18 19:14:52 +0000854 {
hasso6452df02004-08-15 05:52:07 +0000855 /* Self-originated LSA (newer than ours) is received from
856 another router. We have to make a new instance of the LSA
hasso48454372004-05-18 19:14:52 +0000857 or have to flush this LSA. */
858 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000859 {
860 zlog_info ("Newer instance of the self-originated LSA");
861 zlog_info ("Schedule reorigination");
862 }
863 new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
hasso48454372004-05-18 19:14:52 +0000864 }
hasso6452df02004-08-15 05:52:07 +0000865
hasso48454372004-05-18 19:14:52 +0000866 return;
867 }
868
869 /* (6) if there is instance on sending neighbor's request list */
870 if (ospf6_lsdb_lookup (new->header->type, new->header->id,
871 new->header->adv_router, from->request_list))
872 {
873 /* if no database copy, should go above state (5) */
874 assert (old);
875
876 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000877 {
878 zlog_info ("Received is not newer, on the neighbor's request-list");
879 zlog_info ("BadLSReq, discard the received LSA");
880 }
hasso48454372004-05-18 19:14:52 +0000881
882 /* BadLSReq */
883 thread_add_event (master, bad_lsreq, from, 0);
884
885 ospf6_lsa_delete (new);
886 return;
887 }
888
889 /* (7) if neither one is more recent */
890 if (ismore_recent == 0)
891 {
892 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000893 zlog_info ("The same instance as database copy (neither recent)");
hasso48454372004-05-18 19:14:52 +0000894
895 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
896 rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
897 new->header->adv_router, from->retrans_list);
898 if (rem)
899 {
900 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000901 {
902 zlog_info ("It is on the neighbor's retrans-list.");
903 zlog_info ("Treat as an Implied acknowledgement");
904 }
hasso48454372004-05-18 19:14:52 +0000905 SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
hasso6452df02004-08-15 05:52:07 +0000906 ospf6_decrement_retrans_count (rem);
hasso48454372004-05-18 19:14:52 +0000907 ospf6_lsdb_remove (rem, from->retrans_list);
908 }
909
hasso6452df02004-08-15 05:52:07 +0000910 if (IS_OSPF6_DEBUG_LSA (RECV))
911 zlog_info ("Possibly acknowledge and then discard");
912
hasso48454372004-05-18 19:14:52 +0000913 /* (b) possibly acknowledge */
914 ospf6_acknowledge_lsa (new, ismore_recent, from);
915
916 ospf6_lsa_delete (new);
917 return;
918 }
919
920 /* (8) previous database copy is more recent */
921 {
922 assert (old);
923
924 /* If database copy is in 'Seqnumber Wrapping',
925 simply discard the received LSA */
926 if (OSPF6_LSA_IS_MAXAGE (old) &&
927 old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
928 {
929 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000930 {
931 zlog_info ("The LSA is in Seqnumber Wrapping");
932 zlog_info ("MaxAge & MaxSeqNum, discard");
933 }
hasso48454372004-05-18 19:14:52 +0000934 ospf6_lsa_delete (new);
935 return;
936 }
937
938 /* Otherwise, Send database copy of this LSA to this neighbor */
939 {
940 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000941 {
942 zlog_info ("Database copy is more recent.");
943 zlog_info ("Send back directly and then discard");
944 }
hasso48454372004-05-18 19:14:52 +0000945
946 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
947
hasso48454372004-05-18 19:14:52 +0000948 ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
949 if (from->thread_send_lsupdate == NULL)
950 from->thread_send_lsupdate =
951 thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
952 ospf6_lsa_delete (new);
953 return;
954 }
955 return;
956 }
957}
958
959
960