usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / zebra / ospf6d / ospf6_flood.c
blobe9ba52b0cf221b555ce30c1f17d0fa59d8e2559c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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.
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.
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.
22 #include <zebra.h>
24 #include "log.h"
25 #include "thread.h"
26 #include "linklist.h"
27 #include "vty.h"
28 #include "command.h"
30 #include "ospf6d.h"
31 #include "ospf6_proto.h"
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_message.h"
35 #include "ospf6_route.h"
36 #include "ospf6_spf.h"
38 #include "ospf6_top.h"
39 #include "ospf6_area.h"
40 #include "ospf6_interface.h"
41 #include "ospf6_neighbor.h"
43 #include "ospf6_flood.h"
45 unsigned char conf_debug_ospf6_flooding;
47 struct ospf6_lsdb *
48 ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
50 struct ospf6_lsdb *lsdb = NULL;
51 switch (OSPF6_LSA_SCOPE (lsa->header->type))
53 case OSPF6_SCOPE_LINKLOCAL:
54 lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
55 break;
56 case OSPF6_SCOPE_AREA:
57 lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
58 break;
59 case OSPF6_SCOPE_AS:
60 lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
61 break;
62 default:
63 assert (0);
64 break;
66 return lsdb;
69 struct ospf6_lsdb *
70 ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
72 struct ospf6_lsdb *lsdb_self = NULL;
73 switch (OSPF6_LSA_SCOPE (lsa->header->type))
75 case OSPF6_SCOPE_LINKLOCAL:
76 lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
77 break;
78 case OSPF6_SCOPE_AREA:
79 lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
80 break;
81 case OSPF6_SCOPE_AS:
82 lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
83 break;
84 default:
85 assert (0);
86 break;
88 return lsdb_self;
91 void
92 ospf6_lsa_originate (struct ospf6_lsa *lsa)
94 struct ospf6_lsa *old;
95 struct ospf6_lsdb *lsdb_self;
97 /* find previous LSA */
98 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
99 lsa->header->adv_router, lsa->lsdb);
101 /* if the new LSA does not differ from previous,
102 suppress this update of the LSA */
103 if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
105 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
106 zlog_info ("Suppress updating LSA: %s", lsa->name);
107 ospf6_lsa_delete (lsa);
108 return;
111 /* store it in the LSDB for self-originated LSAs */
112 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
113 ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
115 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
116 LS_REFRESH_TIME);
118 if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
119 IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
121 zlog_info ("LSA Originate:");
122 ospf6_lsa_header_print (lsa);
125 if (old)
126 ospf6_flood_clear (old);
127 ospf6_flood (NULL, lsa);
128 ospf6_install_lsa (lsa);
131 void
132 ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
133 struct ospf6 *process)
135 lsa->lsdb = process->lsdb;
136 ospf6_lsa_originate (lsa);
139 void
140 ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
141 struct ospf6_area *oa)
143 lsa->lsdb = oa->lsdb;
144 ospf6_lsa_originate (lsa);
147 void
148 ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
149 struct ospf6_interface *oi)
151 lsa->lsdb = oi->lsdb;
152 ospf6_lsa_originate (lsa);
155 void
156 ospf6_lsa_purge (struct ospf6_lsa *lsa)
158 struct ospf6_lsa *self;
159 struct ospf6_lsdb *lsdb_self;
161 /* remove it from the LSDB for self-originated LSAs */
162 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
163 self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
164 lsa->header->adv_router, lsdb_self);
165 if (self)
167 THREAD_OFF (self->expire);
168 THREAD_OFF (self->refresh);
169 ospf6_lsdb_remove (self, lsdb_self);
172 ospf6_lsa_premature_aging (lsa);
176 void
177 ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
179 /* The LSA must be the original one (see the description
180 in ospf6_decrement_retrans_count () below) */
181 lsa->retrans_count++;
184 void
185 ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
187 struct ospf6_lsdb *lsdb;
188 struct ospf6_lsa *orig;
190 /* The LSA must be on the retrans-list of a neighbor. It means
191 the "lsa" is a copied one, and we have to decrement the
192 retransmission count of the original one (instead of this "lsa"'s).
193 In order to find the original LSA, first we have to find
194 appropriate LSDB that have the original LSA. */
195 lsdb = ospf6_get_scoped_lsdb (lsa);
197 /* Find the original LSA of which the retrans_count should be decremented */
198 orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
199 lsa->header->adv_router, lsdb);
200 if (orig)
202 orig->retrans_count--;
203 assert (orig->retrans_count >= 0);
207 /* RFC2328 section 13.2 Installing LSAs in the database */
208 void
209 ospf6_install_lsa (struct ospf6_lsa *lsa)
211 struct ospf6_lsa *old;
212 struct timeval now;
214 if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
215 IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
216 zlog_info ("Install LSA: %s", lsa->name);
218 /* Remove the old instance from all neighbors' Link state
219 retransmission list (RFC2328 13.2 last paragraph) */
220 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
221 lsa->header->adv_router, lsa->lsdb);
222 if (old)
224 THREAD_OFF (old->expire);
225 ospf6_flood_clear (old);
228 gettimeofday (&now, (struct timezone *) NULL);
229 if (! OSPF6_LSA_IS_MAXAGE (lsa))
230 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
231 MAXAGE + lsa->birth.tv_sec - now.tv_sec);
232 else
233 lsa->expire = NULL;
235 /* actually install */
236 lsa->installed = now;
237 ospf6_lsdb_add (lsa, lsa->lsdb);
239 return;
242 /* RFC2740 section 3.5.2. Sending Link State Update packets */
243 /* RFC2328 section 13.3 Next step in the flooding procedure */
244 void
245 ospf6_flood_interface (struct ospf6_neighbor *from,
246 struct ospf6_lsa *lsa, struct ospf6_interface *oi)
248 listnode node;
249 struct ospf6_neighbor *on;
250 struct ospf6_lsa *req;
251 int retrans_added = 0;
252 int is_debug = 0;
254 if (IS_OSPF6_DEBUG_FLOODING ||
255 IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
257 is_debug++;
258 zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
261 /* (1) For each neighbor */
262 for (node = listhead (oi->neighbor_list); node; nextnode (node))
264 on = (struct ospf6_neighbor *) getdata (node);
266 if (is_debug)
267 zlog_info ("To neighbor %s", on->name);
269 /* (a) if neighbor state < Exchange, examin next */
270 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
272 if (is_debug)
273 zlog_info ("Neighbor state less than ExChange, next neighbor");
274 continue;
277 /* (b) if neighbor not yet Full, check request-list */
278 if (on->state != OSPF6_NEIGHBOR_FULL)
280 if (is_debug)
281 zlog_info ("Neighbor not yet Full");
283 req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
284 lsa->header->adv_router, on->request_list);
285 if (req == NULL)
287 if (is_debug)
288 zlog_info ("Not on request-list for this neighbor");
289 /* fall through */
291 else
293 /* If new LSA less recent, examin next neighbor */
294 if (ospf6_lsa_compare (lsa, req) > 0)
296 if (is_debug)
297 zlog_info ("Requesting is newer, next neighbor");
298 continue;
301 /* If the same instance, delete from request-list and
302 examin next neighbor */
303 if (ospf6_lsa_compare (lsa, req) == 0)
305 if (is_debug)
306 zlog_info ("Requesting the same, remove it, next neighbor");
307 ospf6_lsdb_remove (req, on->request_list);
308 continue;
311 /* If the new LSA is more recent, delete from request-list */
312 if (ospf6_lsa_compare (lsa, req) < 0)
314 if (is_debug)
315 zlog_info ("Received is newer, remove requesting");
316 ospf6_lsdb_remove (req, on->request_list);
317 /* fall through */
322 /* (c) If the new LSA was received from this neighbor,
323 examin next neighbor */
324 if (from == on)
326 if (is_debug)
327 zlog_info ("Received is from the neighbor, next neighbor");
328 continue;
331 /* (d) add retrans-list, schedule retransmission */
332 if (is_debug)
333 zlog_info ("Add retrans-list of this neighbor");
334 ospf6_increment_retrans_count (lsa);
335 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
336 if (on->thread_send_lsupdate == NULL)
337 on->thread_send_lsupdate =
338 thread_add_event (master, ospf6_lsupdate_send_neighbor,
339 on, on->ospf6_if->rxmt_interval);
340 retrans_added++;
343 /* (2) examin next interface if not added to retrans-list */
344 if (retrans_added == 0)
346 if (is_debug)
347 zlog_info ("No retransmission scheduled, next interface");
348 return;
351 /* (3) If the new LSA was received on this interface,
352 and it was from DR or BDR, examin next interface */
353 if (from && from->ospf6_if == oi &&
354 (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
356 if (is_debug)
357 zlog_info ("Received is from the I/F's DR or BDR, next interface");
358 return;
361 /* (4) If the new LSA was received on this interface,
362 and the interface state is BDR, examin next interface */
363 if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
365 if (is_debug)
366 zlog_info ("Received is from the I/F, itself BDR, next interface");
367 return;
370 /* (5) flood the LSA out the interface. */
371 if (is_debug)
372 zlog_info ("Schedule flooding for the interface");
373 if (if_is_broadcast (oi->interface))
375 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
376 if (oi->thread_send_lsupdate == NULL)
377 oi->thread_send_lsupdate =
378 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
380 else
382 /* reschedule retransmissions to all neighbors */
383 for (node = listhead (oi->neighbor_list); node; nextnode (node))
385 on = (struct ospf6_neighbor *) getdata (node);
386 THREAD_OFF (on->thread_send_lsupdate);
387 on->thread_send_lsupdate =
388 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
393 void
394 ospf6_flood_area (struct ospf6_neighbor *from,
395 struct ospf6_lsa *lsa, struct ospf6_area *oa)
397 listnode node;
398 struct ospf6_interface *oi;
400 for (node = listhead (oa->if_list); node; nextnode (node))
402 oi = OSPF6_INTERFACE (getdata (node));
404 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
405 oi != OSPF6_INTERFACE (lsa->lsdb->data))
406 continue;
408 #if 0
409 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
410 ospf6_is_interface_virtual_link (oi))
411 continue;
412 #endif/*0*/
414 ospf6_flood_interface (from, lsa, oi);
418 void
419 ospf6_flood_process (struct ospf6_neighbor *from,
420 struct ospf6_lsa *lsa, struct ospf6 *process)
422 listnode node;
423 struct ospf6_area *oa;
425 for (node = listhead (process->area_list); node; nextnode (node))
427 oa = OSPF6_AREA (getdata (node));
429 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
430 oa != OSPF6_AREA (lsa->lsdb->data))
431 continue;
432 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
433 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
434 continue;
436 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
437 IS_AREA_STUB (oa))
438 continue;
440 ospf6_flood_area (from, lsa, oa);
444 void
445 ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
447 ospf6_flood_process (from, lsa, ospf6);
450 void
451 ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
453 listnode node;
454 struct ospf6_neighbor *on;
455 struct ospf6_lsa *rem;
457 for (node = listhead (oi->neighbor_list); node; nextnode (node))
459 on = OSPF6_NEIGHBOR (getdata (node));
460 rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
461 lsa->header->adv_router, on->retrans_list);
462 if (rem && ! ospf6_lsa_compare (rem, lsa))
464 if (IS_OSPF6_DEBUG_FLOODING ||
465 IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
466 zlog_info ("Remove %s from retrans_list of %s",
467 rem->name, on->name);
468 ospf6_decrement_retrans_count (rem);
469 ospf6_lsdb_remove (rem, on->retrans_list);
474 void
475 ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
477 listnode node;
478 struct ospf6_interface *oi;
480 for (node = listhead (oa->if_list); node; nextnode (node))
482 oi = OSPF6_INTERFACE (getdata (node));
484 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
485 oi != OSPF6_INTERFACE (lsa->lsdb->data))
486 continue;
488 #if 0
489 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
490 ospf6_is_interface_virtual_link (oi))
491 continue;
492 #endif/*0*/
494 ospf6_flood_clear_interface (lsa, oi);
498 void
499 ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
501 listnode node;
502 struct ospf6_area *oa;
504 for (node = listhead (process->area_list); node; nextnode (node))
506 oa = OSPF6_AREA (getdata (node));
508 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
509 oa != OSPF6_AREA (lsa->lsdb->data))
510 continue;
511 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
512 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
513 continue;
515 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
516 IS_AREA_STUB (oa))
517 continue;
519 ospf6_flood_clear_area (lsa, oa);
523 void
524 ospf6_flood_clear (struct ospf6_lsa *lsa)
526 ospf6_flood_clear_process (lsa, ospf6);
530 /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
531 static void
532 ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
533 struct ospf6_neighbor *from)
535 struct ospf6_interface *oi;
536 int is_debug = 0;
538 if (IS_OSPF6_DEBUG_FLOODING ||
539 IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
540 is_debug++;
542 assert (from && from->ospf6_if);
543 oi = from->ospf6_if;
545 /* LSA has been flood back out receiving interface.
546 No acknowledgement sent. */
547 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
549 if (is_debug)
550 zlog_info ("No acknowledgement (BDR & FloodBack)");
551 return;
554 /* LSA is more recent than database copy, but was not flooded
555 back out receiving interface. Delayed acknowledgement sent
556 if advertisement received from Designated Router,
557 otherwide do nothing. */
558 if (ismore_recent < 0)
560 if (oi->drouter == from->router_id)
562 if (is_debug)
563 zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
564 /* Delayed acknowledgement */
565 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
566 if (oi->thread_send_lsack == NULL)
567 oi->thread_send_lsack =
568 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
570 else
572 if (is_debug)
573 zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
575 return;
578 /* LSA is a duplicate, and was treated as an implied acknowledgement.
579 Delayed acknowledgement sent if advertisement received from
580 Designated Router, otherwise do nothing */
581 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
582 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
584 if (oi->drouter == from->router_id)
586 if (is_debug)
587 zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
588 /* Delayed acknowledgement */
589 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
590 if (oi->thread_send_lsack == NULL)
591 oi->thread_send_lsack =
592 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
594 else
596 if (is_debug)
597 zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
599 return;
602 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
603 Direct acknowledgement sent */
604 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
605 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
607 if (is_debug)
608 zlog_info ("Direct acknowledgement (BDR & Duplicate)");
609 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
610 if (from->thread_send_lsack == NULL)
611 from->thread_send_lsack =
612 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
613 return;
616 /* LSA's LS age is equal to Maxage, and there is no current instance
617 of the LSA in the link state database, and none of router's
618 neighbors are in states Exchange or Loading */
619 /* Direct acknowledgement sent, but this case is handled in
620 early of ospf6_receive_lsa () */
623 static void
624 ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
625 struct ospf6_neighbor *from)
627 struct ospf6_interface *oi;
628 int is_debug = 0;
630 if (IS_OSPF6_DEBUG_FLOODING ||
631 IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
632 is_debug++;
634 assert (from && from->ospf6_if);
635 oi = from->ospf6_if;
637 /* LSA has been flood back out receiving interface.
638 No acknowledgement sent. */
639 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
641 if (is_debug)
642 zlog_info ("No acknowledgement (AllOther & FloodBack)");
643 return;
646 /* LSA is more recent than database copy, but was not flooded
647 back out receiving interface. Delayed acknowledgement sent. */
648 if (ismore_recent < 0)
650 if (is_debug)
651 zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
652 /* Delayed acknowledgement */
653 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
654 if (oi->thread_send_lsack == NULL)
655 oi->thread_send_lsack =
656 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
657 return;
660 /* LSA is a duplicate, and was treated as an implied acknowledgement.
661 No acknowledgement sent. */
662 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
663 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
665 if (is_debug)
666 zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
667 return;
670 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
671 Direct acknowledgement sent */
672 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
673 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
675 if (is_debug)
676 zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
677 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
678 if (from->thread_send_lsack == NULL)
679 from->thread_send_lsack =
680 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
681 return;
684 /* LSA's LS age is equal to Maxage, and there is no current instance
685 of the LSA in the link state database, and none of router's
686 neighbors are in states Exchange or Loading */
687 /* Direct acknowledgement sent, but this case is handled in
688 early of ospf6_receive_lsa () */
691 void
692 ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
693 struct ospf6_neighbor *from)
695 struct ospf6_interface *oi;
697 assert (from && from->ospf6_if);
698 oi = from->ospf6_if;
700 if (oi->state == OSPF6_INTERFACE_BDR)
701 ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
702 else
703 ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
706 /* RFC2328 section 13 (4):
707 if MaxAge LSA and if we have no instance, and no neighbor
708 is in states Exchange or Loading
709 returns 1 if match this case, else returns 0 */
710 static int
711 ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
713 struct ospf6_neighbor *on;
714 struct ospf6_interface *oi;
715 struct ospf6_area *oa;
716 struct ospf6 *process = NULL;
717 listnode i, j, k;
718 int count = 0;
720 if (! OSPF6_LSA_IS_MAXAGE (lsa))
721 return 0;
723 if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
724 lsa->header->adv_router, lsa->lsdb))
725 return 0;
727 process = from->ospf6_if->area->ospf6;
728 for (i = listhead (process->area_list); i; nextnode (i))
730 oa = OSPF6_AREA (getdata (i));
731 for (j = listhead (oa->if_list); j; nextnode (j))
733 oi = OSPF6_INTERFACE (getdata (j));
734 for (k = listhead (oi->neighbor_list); k; nextnode (k))
736 on = OSPF6_NEIGHBOR (getdata (k));
737 if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
738 on->state == OSPF6_NEIGHBOR_LOADING)
739 count++;
744 if (count == 0)
745 return 1;
746 return 0;
749 /* RFC2328 section 13 The Flooding Procedure */
750 void
751 ospf6_receive_lsa (struct ospf6_neighbor *from,
752 struct ospf6_lsa_header *lsa_header)
754 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
755 int ismore_recent;
756 unsigned short cksum;
757 int is_debug = 0;
759 ismore_recent = 1;
760 assert (from);
762 /* make lsa structure for received lsa */
763 new = ospf6_lsa_create (lsa_header);
765 if (IS_OSPF6_DEBUG_FLOODING ||
766 IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type))
768 is_debug++;
769 zlog_info ("LSA Receive from %s", from->name);
770 ospf6_lsa_header_print (new);
773 /* (1) LSA Checksum */
774 cksum = ntohs (new->header->checksum);
775 if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
777 if (is_debug)
778 zlog_info ("Wrong LSA Checksum, discard");
779 ospf6_lsa_delete (new);
780 return;
783 /* (2) Examine the LSA's LS type.
784 RFC2470 3.5.1. Receiving Link State Update packets */
785 if (IS_AREA_STUB (from->ospf6_if->area) &&
786 OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
788 if (is_debug)
789 zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
790 ospf6_lsa_delete (new);
791 return;
794 /* (3) LSA which have reserved scope is discarded
795 RFC2470 3.5.1. Receiving Link State Update packets */
796 /* Flooding scope check. LSAs with unknown scope are discarded here.
797 Set appropriate LSDB for the LSA */
798 switch (OSPF6_LSA_SCOPE (new->header->type))
800 case OSPF6_SCOPE_LINKLOCAL:
801 new->lsdb = from->ospf6_if->lsdb;
802 break;
803 case OSPF6_SCOPE_AREA:
804 new->lsdb = from->ospf6_if->area->lsdb;
805 break;
806 case OSPF6_SCOPE_AS:
807 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
808 break;
809 default:
810 if (is_debug)
811 zlog_info ("LSA has reserved scope, discard");
812 ospf6_lsa_delete (new);
813 return;
816 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
817 is in states Exchange or Loading */
818 if (ospf6_is_maxage_lsa_drop (new, from))
820 /* log */
821 if (is_debug)
822 zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
824 /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
825 ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
826 if (from->thread_send_lsack == NULL)
827 from->thread_send_lsack =
828 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
830 /* b) Discard */
831 ospf6_lsa_delete (new);
832 return;
835 /* (5) */
836 /* lookup the same database copy in lsdb */
837 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
838 new->header->adv_router, new->lsdb);
839 if (old)
841 ismore_recent = ospf6_lsa_compare (new, old);
842 if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
844 if (is_debug)
845 zlog_info ("Received is duplicated LSA");
846 SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
850 /* if no database copy or received is more recent */
851 if (old == NULL || ismore_recent < 0)
853 /* in case we have no database copy */
854 ismore_recent = -1;
856 /* (a) MinLSArrival check */
857 if (old)
859 struct timeval now, res;
860 gettimeofday (&now, (struct timezone *) NULL);
861 timersub (&now, &old->installed, &res);
862 if (res.tv_sec < MIN_LS_ARRIVAL)
864 if (is_debug)
865 zlog_info ("LSA can't be updated within MinLSArrival, discard");
866 ospf6_lsa_delete (new);
867 return; /* examin next lsa */
871 gettimeofday (&new->received, (struct timezone *) NULL);
873 if (is_debug)
874 zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
876 /* (b) immediately flood and (c) remove from all retrans-list */
877 /* Prevent self-originated LSA to be flooded. this is to make
878 reoriginated instance of the LSA not to be rejected by other routers
879 due to MinLSArrival. */
880 if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
881 ospf6_flood (from, new);
883 /* (c) Remove the current database copy from all neighbors' Link
884 state retransmission lists. */
885 /* XXX, flood_clear ? */
887 /* (d), installing lsdb, which may cause routing
888 table calculation (replacing database copy) */
889 ospf6_install_lsa (new);
891 /* (e) possibly acknowledge */
892 ospf6_acknowledge_lsa (new, ismore_recent, from);
894 /* (f) Self Originated LSA, section 13.4 */
895 if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
897 /* Self-originated LSA (newer than ours) is received from
898 another router. We have to make a new instance of the LSA
899 or have to flush this LSA. */
900 if (is_debug)
902 zlog_info ("Newer instance of the self-originated LSA");
903 zlog_info ("Schedule reorigination");
905 new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
908 return;
911 /* (6) if there is instance on sending neighbor's request list */
912 if (ospf6_lsdb_lookup (new->header->type, new->header->id,
913 new->header->adv_router, from->request_list))
915 /* if no database copy, should go above state (5) */
916 assert (old);
918 if (is_debug)
920 zlog_info ("Received is not newer, on the neighbor's request-list");
921 zlog_info ("BadLSReq, discard the received LSA");
924 /* BadLSReq */
925 thread_add_event (master, bad_lsreq, from, 0);
927 ospf6_lsa_delete (new);
928 return;
931 /* (7) if neither one is more recent */
932 if (ismore_recent == 0)
934 if (is_debug)
935 zlog_info ("The same instance as database copy (neither recent)");
937 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
938 rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
939 new->header->adv_router, from->retrans_list);
940 if (rem)
942 if (is_debug)
944 zlog_info ("It is on the neighbor's retrans-list.");
945 zlog_info ("Treat as an Implied acknowledgement");
947 SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
948 ospf6_decrement_retrans_count (rem);
949 ospf6_lsdb_remove (rem, from->retrans_list);
952 if (is_debug)
953 zlog_info ("Possibly acknowledge and then discard");
955 /* (b) possibly acknowledge */
956 ospf6_acknowledge_lsa (new, ismore_recent, from);
958 ospf6_lsa_delete (new);
959 return;
962 /* (8) previous database copy is more recent */
964 assert (old);
966 /* If database copy is in 'Seqnumber Wrapping',
967 simply discard the received LSA */
968 if (OSPF6_LSA_IS_MAXAGE (old) &&
969 old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
971 if (is_debug)
973 zlog_info ("The LSA is in Seqnumber Wrapping");
974 zlog_info ("MaxAge & MaxSeqNum, discard");
976 ospf6_lsa_delete (new);
977 return;
980 /* Otherwise, Send database copy of this LSA to this neighbor */
982 if (is_debug)
984 zlog_info ("Database copy is more recent.");
985 zlog_info ("Send back directly and then discard");
988 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
990 ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
991 if (from->thread_send_lsupdate == NULL)
992 from->thread_send_lsupdate =
993 thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
994 ospf6_lsa_delete (new);
995 return;
997 return;
1002 DEFUN (debug_ospf6_flooding,
1003 debug_ospf6_flooding_cmd,
1004 "debug ospf6 flooding",
1005 DEBUG_STR
1006 OSPF6_STR
1007 "Debug OSPFv3 flooding function\n"
1010 OSPF6_DEBUG_FLOODING_ON ();
1011 return CMD_SUCCESS;
1014 DEFUN (no_debug_ospf6_flooding,
1015 no_debug_ospf6_flooding_cmd,
1016 "no debug ospf6 flooding",
1017 NO_STR
1018 DEBUG_STR
1019 OSPF6_STR
1020 "Debug OSPFv3 flooding function\n"
1023 OSPF6_DEBUG_FLOODING_OFF ();
1024 return CMD_SUCCESS;
1028 config_write_ospf6_debug_flood (struct vty *vty)
1030 if (IS_OSPF6_DEBUG_FLOODING)
1031 vty_out (vty, "debug ospf6 flooding%s", VNL);
1032 return 0;
1035 void
1036 install_element_ospf6_debug_flood ()
1038 install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd);
1039 install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
1040 install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd);
1041 install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd);