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
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.
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
*ospf6_get_scoped_lsdb(struct ospf6_lsa
*lsa
)
49 struct ospf6_lsdb
*lsdb
= NULL
;
50 switch (OSPF6_LSA_SCOPE(lsa
->header
->type
)) {
51 case OSPF6_SCOPE_LINKLOCAL
:
52 lsdb
= OSPF6_INTERFACE(lsa
->lsdb
->data
)->lsdb
;
54 case OSPF6_SCOPE_AREA
:
55 lsdb
= OSPF6_AREA(lsa
->lsdb
->data
)->lsdb
;
58 lsdb
= OSPF6_PROCESS(lsa
->lsdb
->data
)->lsdb
;
67 struct ospf6_lsdb
*ospf6_get_scoped_lsdb_self(struct ospf6_lsa
*lsa
)
69 struct ospf6_lsdb
*lsdb_self
= NULL
;
70 switch (OSPF6_LSA_SCOPE(lsa
->header
->type
)) {
71 case OSPF6_SCOPE_LINKLOCAL
:
72 lsdb_self
= OSPF6_INTERFACE(lsa
->lsdb
->data
)->lsdb_self
;
74 case OSPF6_SCOPE_AREA
:
75 lsdb_self
= OSPF6_AREA(lsa
->lsdb
->data
)->lsdb_self
;
78 lsdb_self
= OSPF6_PROCESS(lsa
->lsdb
->data
)->lsdb_self
;
87 void ospf6_lsa_originate(struct ospf6_lsa
*lsa
)
89 struct ospf6_lsa
*old
;
90 struct ospf6_lsdb
*lsdb_self
;
92 /* find previous LSA */
93 old
= ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
94 lsa
->header
->adv_router
, lsa
->lsdb
);
96 /* if the new LSA does not differ from previous,
97 suppress this update of the LSA */
98 if (old
&& !OSPF6_LSA_IS_DIFFER(lsa
, old
)) {
99 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa
->header
->type
))
100 zlog_debug("Suppress updating LSA: %s", lsa
->name
);
101 ospf6_lsa_delete(lsa
);
105 /* store it in the LSDB for self-originated LSAs */
106 lsdb_self
= ospf6_get_scoped_lsdb_self(lsa
);
107 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), lsdb_self
);
109 lsa
->refresh
= thread_add_timer(master
, ospf6_lsa_refresh
, lsa
,
110 OSPF_LS_REFRESH_TIME
);
112 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)
113 || IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa
->header
->type
)) {
114 zlog_debug("LSA Originate:");
115 ospf6_lsa_header_print(lsa
);
118 ospf6_install_lsa(lsa
);
119 ospf6_flood(NULL
, lsa
);
122 void ospf6_lsa_originate_process(struct ospf6_lsa
*lsa
, struct ospf6
*process
)
124 lsa
->lsdb
= process
->lsdb
;
125 ospf6_lsa_originate(lsa
);
128 void ospf6_lsa_originate_area(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
130 lsa
->lsdb
= oa
->lsdb
;
131 ospf6_lsa_originate(lsa
);
134 void ospf6_lsa_originate_interface(struct ospf6_lsa
*lsa
,
135 struct ospf6_interface
*oi
)
137 lsa
->lsdb
= oi
->lsdb
;
138 ospf6_lsa_originate(lsa
);
141 void ospf6_lsa_purge(struct ospf6_lsa
*lsa
)
143 struct ospf6_lsa
*self
;
144 struct ospf6_lsdb
*lsdb_self
;
146 /* remove it from the LSDB for self-originated LSAs */
147 lsdb_self
= ospf6_get_scoped_lsdb_self(lsa
);
148 self
= ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
149 lsa
->header
->adv_router
, lsdb_self
);
151 THREAD_OFF(self
->expire
);
152 THREAD_OFF(self
->refresh
);
153 ospf6_lsdb_remove(self
, lsdb_self
);
156 ospf6_lsa_premature_aging(lsa
);
160 void ospf6_increment_retrans_count(struct ospf6_lsa
*lsa
)
162 /* The LSA must be the original one (see the description
163 in ospf6_decrement_retrans_count () below) */
164 lsa
->retrans_count
++;
167 void ospf6_decrement_retrans_count(struct ospf6_lsa
*lsa
)
169 struct ospf6_lsdb
*lsdb
;
170 struct ospf6_lsa
*orig
;
172 /* The LSA must be on the retrans-list of a neighbor. It means
173 the "lsa" is a copied one, and we have to decrement the
174 retransmission count of the original one (instead of this "lsa"'s).
175 In order to find the original LSA, first we have to find
176 appropriate LSDB that have the original LSA. */
177 lsdb
= ospf6_get_scoped_lsdb(lsa
);
179 /* Find the original LSA of which the retrans_count should be
181 orig
= ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
182 lsa
->header
->adv_router
, lsdb
);
184 orig
->retrans_count
--;
185 assert(orig
->retrans_count
>= 0);
189 /* RFC2328 section 13.2 Installing LSAs in the database */
190 void ospf6_install_lsa(struct ospf6_lsa
*lsa
)
193 struct ospf6_lsa
*old
;
195 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)
196 || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa
->header
->type
))
197 zlog_debug("Install LSA: %s", lsa
->name
);
199 /* Remove the old instance from all neighbors' Link state
200 retransmission list (RFC2328 13.2 last paragraph) */
201 old
= ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
202 lsa
->header
->adv_router
, lsa
->lsdb
);
204 THREAD_OFF(old
->expire
);
205 THREAD_OFF(old
->refresh
);
206 ospf6_flood_clear(old
);
210 if (!OSPF6_LSA_IS_MAXAGE(lsa
))
211 lsa
->expire
= thread_add_timer(
212 master
, ospf6_lsa_expire
, lsa
,
213 OSPF_LSA_MAXAGE
+ lsa
->birth
.tv_sec
- now
.tv_sec
);
217 if (OSPF6_LSA_IS_SEQWRAP(lsa
)
218 && !(CHECK_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
)
219 && lsa
->header
->seqnum
== htonl(OSPF_MAX_SEQUENCE_NUMBER
))) {
220 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa
->header
->type
))
221 zlog_debug("lsa install wrapping: sequence 0x%x",
222 ntohl(lsa
->header
->seqnum
));
223 SET_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
);
224 /* in lieu of premature_aging, since we do not want to recreate
226 * and/or mess with timers etc, we just want to wrap the
228 * and reflood the lsa before continuing.
229 * NOTE: Flood needs to be called right after this function
233 lsa
->header
->seqnum
= htonl(OSPF_MAX_SEQUENCE_NUMBER
);
234 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
235 ospf6_lsa_checksum(lsa
->header
);
238 /* actually install */
239 lsa
->installed
= now
;
240 ospf6_lsdb_add(lsa
, lsa
->lsdb
);
245 /* RFC2740 section 3.5.2. Sending Link State Update packets */
246 /* RFC2328 section 13.3 Next step in the flooding procedure */
247 static void ospf6_flood_interface(struct ospf6_neighbor
*from
,
248 struct ospf6_lsa
*lsa
,
249 struct ospf6_interface
*oi
)
251 struct listnode
*node
, *nnode
;
252 struct ospf6_neighbor
*on
;
253 struct ospf6_lsa
*req
;
254 int retrans_added
= 0;
257 if (IS_OSPF6_DEBUG_FLOODING
258 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa
->header
->type
)) {
260 zlog_debug("Flooding on %s: %s", oi
->interface
->name
,
264 /* (1) For each neighbor */
265 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
267 zlog_debug("To neighbor %s", on
->name
);
269 /* (a) if neighbor state < Exchange, examin next */
270 if (on
->state
< OSPF6_NEIGHBOR_EXCHANGE
) {
273 "Neighbor state less than ExChange, next neighbor");
277 /* (b) if neighbor not yet Full, check request-list */
278 if (on
->state
!= OSPF6_NEIGHBOR_FULL
) {
280 zlog_debug("Neighbor not yet Full");
282 req
= ospf6_lsdb_lookup(
283 lsa
->header
->type
, lsa
->header
->id
,
284 lsa
->header
->adv_router
, on
->request_list
);
288 "Not on request-list for this neighbor");
291 /* If new LSA less recent, examin next neighbor
293 if (ospf6_lsa_compare(lsa
, req
) > 0) {
296 "Requesting is older, next neighbor");
300 /* If the same instance, delete from
302 examin next neighbor */
303 if (ospf6_lsa_compare(lsa
, req
) == 0) {
306 "Requesting the same, remove it, next neighbor");
307 if (req
== on
->last_ls_req
) {
308 ospf6_lsa_unlock(req
);
309 on
->last_ls_req
= NULL
;
311 ospf6_lsdb_remove(req
,
313 ospf6_check_nbr_loading(on
);
317 /* If the new LSA is more recent, delete from
319 if (ospf6_lsa_compare(lsa
, req
) < 0) {
322 "Received is newer, remove requesting");
323 if (req
== on
->last_ls_req
) {
324 ospf6_lsa_unlock(req
);
325 on
->last_ls_req
= NULL
;
327 ospf6_lsdb_remove(req
,
329 ospf6_check_nbr_loading(on
);
335 /* (c) If the new LSA was received from this neighbor,
336 examin next neighbor */
340 "Received is from the neighbor, next neighbor");
344 /* (d) add retrans-list, schedule retransmission */
346 zlog_debug("Add retrans-list of this neighbor");
347 ospf6_increment_retrans_count(lsa
);
348 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), on
->retrans_list
);
349 if (on
->thread_send_lsupdate
== NULL
)
350 on
->thread_send_lsupdate
= thread_add_timer(
351 master
, ospf6_lsupdate_send_neighbor
, on
,
352 on
->ospf6_if
->rxmt_interval
);
356 /* (2) examin next interface if not added to retrans-list */
357 if (retrans_added
== 0) {
360 "No retransmission scheduled, next interface");
364 /* (3) If the new LSA was received on this interface,
365 and it was from DR or BDR, examin next interface */
366 if (from
&& from
->ospf6_if
== oi
367 && (from
->router_id
== oi
->drouter
368 || from
->router_id
== oi
->bdrouter
)) {
371 "Received is from the I/F's DR or BDR, next interface");
375 /* (4) If the new LSA was received on this interface,
376 and the interface state is BDR, examin next interface */
377 if (from
&& from
->ospf6_if
== oi
) {
378 if (oi
->state
== OSPF6_INTERFACE_BDR
) {
381 "Received is from the I/F, itself BDR, next interface");
384 SET_FLAG(lsa
->flag
, OSPF6_LSA_FLOODBACK
);
387 /* (5) flood the LSA out the interface. */
389 zlog_debug("Schedule flooding for the interface");
390 if ((oi
->type
== OSPF_IFTYPE_BROADCAST
)
391 || (oi
->type
== OSPF_IFTYPE_POINTOPOINT
)) {
392 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), oi
->lsupdate_list
);
393 if (oi
->thread_send_lsupdate
== NULL
)
394 oi
->thread_send_lsupdate
= thread_add_event(
395 master
, ospf6_lsupdate_send_interface
, oi
, 0);
397 /* reschedule retransmissions to all neighbors */
398 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
399 THREAD_OFF(on
->thread_send_lsupdate
);
400 on
->thread_send_lsupdate
= thread_add_event(
401 master
, ospf6_lsupdate_send_neighbor
, on
, 0);
406 void ospf6_flood_area(struct ospf6_neighbor
*from
, struct ospf6_lsa
*lsa
,
407 struct ospf6_area
*oa
)
409 struct listnode
*node
, *nnode
;
410 struct ospf6_interface
*oi
;
412 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
413 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_LINKLOCAL
414 && oi
!= OSPF6_INTERFACE(lsa
->lsdb
->data
))
418 if (OSPF6_LSA_SCOPE (lsa
->header
->type
) == OSPF6_SCOPE_AS
&&
419 ospf6_is_interface_virtual_link (oi
))
423 ospf6_flood_interface(from
, lsa
, oi
);
427 static void ospf6_flood_process(struct ospf6_neighbor
*from
,
428 struct ospf6_lsa
*lsa
, struct ospf6
*process
)
430 struct listnode
*node
, *nnode
;
431 struct ospf6_area
*oa
;
433 for (ALL_LIST_ELEMENTS(process
->area_list
, node
, nnode
, oa
)) {
434 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_AREA
435 && oa
!= OSPF6_AREA(lsa
->lsdb
->data
))
437 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_LINKLOCAL
438 && oa
!= OSPF6_INTERFACE(lsa
->lsdb
->data
)->area
)
441 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
445 ospf6_flood_area(from
, lsa
, oa
);
449 void ospf6_flood(struct ospf6_neighbor
*from
, struct ospf6_lsa
*lsa
)
451 ospf6_flood_process(from
, lsa
, ospf6
);
454 static void ospf6_flood_clear_interface(struct ospf6_lsa
*lsa
,
455 struct ospf6_interface
*oi
)
457 struct listnode
*node
, *nnode
;
458 struct ospf6_neighbor
*on
;
459 struct ospf6_lsa
*rem
;
461 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
462 rem
= ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
463 lsa
->header
->adv_router
,
465 if (rem
&& !ospf6_lsa_compare(rem
, lsa
)) {
466 if (IS_OSPF6_DEBUG_FLOODING
467 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa
->header
->type
))
468 zlog_debug("Remove %s from retrans_list of %s",
469 rem
->name
, on
->name
);
470 ospf6_decrement_retrans_count(rem
);
471 ospf6_lsdb_remove(rem
, on
->retrans_list
);
476 static void ospf6_flood_clear_area(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
478 struct listnode
*node
, *nnode
;
479 struct ospf6_interface
*oi
;
481 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
482 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_LINKLOCAL
483 && oi
!= OSPF6_INTERFACE(lsa
->lsdb
->data
))
487 if (OSPF6_LSA_SCOPE (lsa
->header
->type
) == OSPF6_SCOPE_AS
&&
488 ospf6_is_interface_virtual_link (oi
))
492 ospf6_flood_clear_interface(lsa
, oi
);
496 static void ospf6_flood_clear_process(struct ospf6_lsa
*lsa
,
497 struct ospf6
*process
)
499 struct listnode
*node
, *nnode
;
500 struct ospf6_area
*oa
;
502 for (ALL_LIST_ELEMENTS(process
->area_list
, node
, nnode
, oa
)) {
503 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_AREA
504 && oa
!= OSPF6_AREA(lsa
->lsdb
->data
))
506 if (OSPF6_LSA_SCOPE(lsa
->header
->type
) == OSPF6_SCOPE_LINKLOCAL
507 && oa
!= OSPF6_INTERFACE(lsa
->lsdb
->data
)->area
)
510 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
514 ospf6_flood_clear_area(lsa
, oa
);
518 void ospf6_flood_clear(struct ospf6_lsa
*lsa
)
520 ospf6_flood_clear_process(lsa
, ospf6
);
524 /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
525 static void ospf6_acknowledge_lsa_bdrouter(struct ospf6_lsa
*lsa
,
527 struct ospf6_neighbor
*from
)
529 struct ospf6_interface
*oi
;
532 if (IS_OSPF6_DEBUG_FLOODING
533 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa
->header
->type
))
536 assert(from
&& from
->ospf6_if
);
539 /* LSA is more recent than database copy, but was not flooded
540 back out receiving interface. Delayed acknowledgement sent
541 if advertisement received from Designated Router,
542 otherwide do nothing. */
543 if (ismore_recent
< 0) {
544 if (oi
->drouter
== from
->router_id
) {
547 "Delayed acknowledgement (BDR & MoreRecent & from DR)");
548 /* Delayed acknowledgement */
549 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), oi
->lsack_list
);
550 if (oi
->thread_send_lsack
== NULL
)
551 oi
->thread_send_lsack
= thread_add_timer(
552 master
, ospf6_lsack_send_interface
, oi
,
557 "No acknowledgement (BDR & MoreRecent & ! from DR)");
562 /* LSA is a duplicate, and was treated as an implied acknowledgement.
563 Delayed acknowledgement sent if advertisement received from
564 Designated Router, otherwise do nothing */
565 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_DUPLICATE
)
566 && CHECK_FLAG(lsa
->flag
, OSPF6_LSA_IMPLIEDACK
)) {
567 if (oi
->drouter
== from
->router_id
) {
570 "Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
571 /* Delayed acknowledgement */
572 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), oi
->lsack_list
);
573 if (oi
->thread_send_lsack
== NULL
)
574 oi
->thread_send_lsack
= thread_add_timer(
575 master
, ospf6_lsack_send_interface
, oi
,
580 "No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
585 /* LSA is a duplicate, and was not treated as an implied
587 Direct acknowledgement sent */
588 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_DUPLICATE
)
589 && !CHECK_FLAG(lsa
->flag
, OSPF6_LSA_IMPLIEDACK
)) {
591 zlog_debug("Direct acknowledgement (BDR & Duplicate)");
592 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), from
->lsack_list
);
593 if (from
->thread_send_lsack
== NULL
)
594 from
->thread_send_lsack
= thread_add_event(
595 master
, ospf6_lsack_send_neighbor
, from
, 0);
599 /* LSA's LS age is equal to Maxage, and there is no current instance
600 of the LSA in the link state database, and none of router's
601 neighbors are in states Exchange or Loading */
602 /* Direct acknowledgement sent, but this case is handled in
603 early of ospf6_receive_lsa () */
606 static void ospf6_acknowledge_lsa_allother(struct ospf6_lsa
*lsa
,
608 struct ospf6_neighbor
*from
)
610 struct ospf6_interface
*oi
;
613 if (IS_OSPF6_DEBUG_FLOODING
614 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa
->header
->type
))
617 assert(from
&& from
->ospf6_if
);
620 /* LSA has been flood back out receiving interface.
621 No acknowledgement sent. */
622 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_FLOODBACK
)) {
624 zlog_debug("No acknowledgement (AllOther & FloodBack)");
628 /* LSA is more recent than database copy, but was not flooded
629 back out receiving interface. Delayed acknowledgement sent. */
630 if (ismore_recent
< 0) {
633 "Delayed acknowledgement (AllOther & MoreRecent)");
634 /* Delayed acknowledgement */
635 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), oi
->lsack_list
);
636 if (oi
->thread_send_lsack
== NULL
)
637 oi
->thread_send_lsack
= thread_add_timer(
638 master
, ospf6_lsack_send_interface
, oi
, 3);
642 /* LSA is a duplicate, and was treated as an implied acknowledgement.
643 No acknowledgement sent. */
644 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_DUPLICATE
)
645 && CHECK_FLAG(lsa
->flag
, OSPF6_LSA_IMPLIEDACK
)) {
648 "No acknowledgement (AllOther & Duplicate & ImpliedAck)");
652 /* LSA is a duplicate, and was not treated as an implied
654 Direct acknowledgement sent */
655 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_DUPLICATE
)
656 && !CHECK_FLAG(lsa
->flag
, OSPF6_LSA_IMPLIEDACK
)) {
659 "Direct acknowledgement (AllOther & Duplicate)");
660 ospf6_lsdb_add(ospf6_lsa_copy(lsa
), from
->lsack_list
);
661 if (from
->thread_send_lsack
== NULL
)
662 from
->thread_send_lsack
= thread_add_event(
663 master
, ospf6_lsack_send_neighbor
, from
, 0);
667 /* LSA's LS age is equal to Maxage, and there is no current instance
668 of the LSA in the link state database, and none of router's
669 neighbors are in states Exchange or Loading */
670 /* Direct acknowledgement sent, but this case is handled in
671 early of ospf6_receive_lsa () */
674 static void ospf6_acknowledge_lsa(struct ospf6_lsa
*lsa
, int ismore_recent
,
675 struct ospf6_neighbor
*from
)
677 struct ospf6_interface
*oi
;
679 assert(from
&& from
->ospf6_if
);
682 if (oi
->state
== OSPF6_INTERFACE_BDR
)
683 ospf6_acknowledge_lsa_bdrouter(lsa
, ismore_recent
, from
);
685 ospf6_acknowledge_lsa_allother(lsa
, ismore_recent
, from
);
688 /* RFC2328 section 13 (4):
689 if MaxAge LSA and if we have no instance, and no neighbor
690 is in states Exchange or Loading
691 returns 1 if match this case, else returns 0 */
692 static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa
*lsa
,
693 struct ospf6_neighbor
*from
)
695 struct ospf6_neighbor
*on
;
696 struct ospf6_interface
*oi
;
697 struct ospf6_area
*oa
;
698 struct ospf6
*process
= NULL
;
699 struct listnode
*i
, *j
, *k
;
702 if (!OSPF6_LSA_IS_MAXAGE(lsa
))
705 if (ospf6_lsdb_lookup(lsa
->header
->type
, lsa
->header
->id
,
706 lsa
->header
->adv_router
, lsa
->lsdb
))
709 process
= from
->ospf6_if
->area
->ospf6
;
711 for (ALL_LIST_ELEMENTS_RO(process
->area_list
, i
, oa
))
712 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, j
, oi
))
713 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, k
, on
))
714 if (on
->state
== OSPF6_NEIGHBOR_EXCHANGE
715 || on
->state
== OSPF6_NEIGHBOR_LOADING
)
723 /* RFC2328 section 13 The Flooding Procedure */
724 void ospf6_receive_lsa(struct ospf6_neighbor
*from
,
725 struct ospf6_lsa_header
*lsa_header
)
727 struct ospf6_lsa
*new = NULL
, *old
= NULL
, *rem
= NULL
;
730 unsigned int time_delta_ms
;
735 /* make lsa structure for received lsa */
736 new = ospf6_lsa_create(lsa_header
);
738 if (IS_OSPF6_DEBUG_FLOODING
739 || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header
->type
)) {
741 zlog_debug("LSA Receive from %s", from
->name
);
742 ospf6_lsa_header_print(new);
745 /* (1) LSA Checksum */
746 if (!ospf6_lsa_checksum_valid(new->header
)) {
748 zlog_debug("Wrong LSA Checksum, discard");
749 ospf6_lsa_delete(new);
753 /* (2) Examine the LSA's LS type.
754 RFC2470 3.5.1. Receiving Link State Update packets */
755 if (IS_AREA_STUB(from
->ospf6_if
->area
)
756 && OSPF6_LSA_SCOPE(new->header
->type
) == OSPF6_SCOPE_AS
) {
759 "AS-External-LSA (or AS-scope LSA) in stub area, discard");
760 ospf6_lsa_delete(new);
764 /* (3) LSA which have reserved scope is discarded
765 RFC2470 3.5.1. Receiving Link State Update packets */
766 /* Flooding scope check. LSAs with unknown scope are discarded here.
767 Set appropriate LSDB for the LSA */
768 switch (OSPF6_LSA_SCOPE(new->header
->type
)) {
769 case OSPF6_SCOPE_LINKLOCAL
:
770 new->lsdb
= from
->ospf6_if
->lsdb
;
772 case OSPF6_SCOPE_AREA
:
773 new->lsdb
= from
->ospf6_if
->area
->lsdb
;
776 new->lsdb
= from
->ospf6_if
->area
->ospf6
->lsdb
;
780 zlog_debug("LSA has reserved scope, discard");
781 ospf6_lsa_delete(new);
785 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
786 is in states Exchange or Loading */
787 if (ospf6_is_maxage_lsa_drop(new, from
)) {
791 "Drop MaxAge LSA with direct acknowledgement.");
793 /* a) Acknowledge back to neighbor (Direct acknowledgement,
795 ospf6_lsdb_add(ospf6_lsa_copy(new), from
->lsack_list
);
796 if (from
->thread_send_lsack
== NULL
)
797 from
->thread_send_lsack
= thread_add_event(
798 master
, ospf6_lsack_send_neighbor
, from
, 0);
801 ospf6_lsa_delete(new);
806 /* lookup the same database copy in lsdb */
807 old
= ospf6_lsdb_lookup(new->header
->type
, new->header
->id
,
808 new->header
->adv_router
, new->lsdb
);
810 ismore_recent
= ospf6_lsa_compare(new, old
);
811 if (ntohl(new->header
->seqnum
) == ntohl(old
->header
->seqnum
)) {
813 zlog_debug("Received is duplicated LSA");
814 SET_FLAG(new->flag
, OSPF6_LSA_DUPLICATE
);
818 /* if no database copy or received is more recent */
819 if (old
== NULL
|| ismore_recent
< 0) {
820 /* in case we have no database copy */
823 /* (a) MinLSArrival check */
825 struct timeval now
, res
;
827 timersub(&now
, &old
->installed
, &res
);
829 (res
.tv_sec
* 1000) + (int)(res
.tv_usec
/ 1000);
831 < from
->ospf6_if
->area
->ospf6
->lsa_minarrival
) {
834 "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
836 from
->ospf6_if
->area
->ospf6
838 ospf6_lsa_delete(new);
839 return; /* examin next lsa */
843 monotime(&new->received
);
847 "Install, Flood, Possibly acknowledge the received LSA");
849 /* Remove older copies of this LSA from retx lists */
851 ospf6_flood_clear(old
);
853 /* (b) immediately flood and (c) remove from all retrans-list */
854 /* Prevent self-originated LSA to be flooded. this is to make
855 reoriginated instance of the LSA not to be rejected by other
857 due to MinLSArrival. */
858 if (new->header
->adv_router
859 != from
->ospf6_if
->area
->ospf6
->router_id
)
860 ospf6_flood(from
, new);
862 /* (d), installing lsdb, which may cause routing
863 table calculation (replacing database copy) */
864 ospf6_install_lsa(new);
866 if (OSPF6_LSA_IS_MAXAGE(new))
867 ospf6_maxage_remove(from
->ospf6_if
->area
->ospf6
);
869 /* (e) possibly acknowledge */
870 ospf6_acknowledge_lsa(new, ismore_recent
, from
);
872 /* (f) Self Originated LSA, section 13.4 */
873 if (new->header
->adv_router
874 == from
->ospf6_if
->area
->ospf6
->router_id
) {
875 /* Self-originated LSA (newer than ours) is received
877 another router. We have to make a new instance of the
879 or have to flush this LSA. */
882 "Newer instance of the self-originated LSA");
883 zlog_debug("Schedule reorigination");
885 new->refresh
= thread_add_event(
886 master
, ospf6_lsa_refresh
, new, 0);
892 /* (6) if there is instance on sending neighbor's request list */
893 if (ospf6_lsdb_lookup(new->header
->type
, new->header
->id
,
894 new->header
->adv_router
, from
->request_list
)) {
895 /* if no database copy, should go above state (5) */
900 "Received is not newer, on the neighbor's request-list");
901 zlog_debug("BadLSReq, discard the received LSA");
905 thread_add_event(master
, bad_lsreq
, from
, 0);
907 ospf6_lsa_delete(new);
911 /* (7) if neither one is more recent */
912 if (ismore_recent
== 0) {
915 "The same instance as database copy (neither recent)");
917 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack
919 rem
= ospf6_lsdb_lookup(new->header
->type
, new->header
->id
,
920 new->header
->adv_router
,
925 "It is on the neighbor's retrans-list.");
927 "Treat as an Implied acknowledgement");
929 SET_FLAG(new->flag
, OSPF6_LSA_IMPLIEDACK
);
930 ospf6_decrement_retrans_count(rem
);
931 ospf6_lsdb_remove(rem
, from
->retrans_list
);
935 zlog_debug("Possibly acknowledge and then discard");
937 /* (b) possibly acknowledge */
938 ospf6_acknowledge_lsa(new, ismore_recent
, from
);
940 ospf6_lsa_delete(new);
944 /* (8) previous database copy is more recent */
948 /* If database copy is in 'Seqnumber Wrapping',
949 simply discard the received LSA */
950 if (OSPF6_LSA_IS_MAXAGE(old
)
951 && old
->header
->seqnum
== htonl(OSPF_MAX_SEQUENCE_NUMBER
)) {
953 zlog_debug("The LSA is in Seqnumber Wrapping");
954 zlog_debug("MaxAge & MaxSeqNum, discard");
956 ospf6_lsa_delete(new);
960 /* Otherwise, Send database copy of this LSA to this neighbor */
963 zlog_debug("Database copy is more recent.");
965 "Send back directly and then discard");
968 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
970 ospf6_lsdb_add(ospf6_lsa_copy(old
),
971 from
->lsupdate_list
);
972 if (from
->thread_send_lsupdate
== NULL
)
973 from
->thread_send_lsupdate
= thread_add_event(
974 master
, ospf6_lsupdate_send_neighbor
,
976 ospf6_lsa_delete(new);
984 DEFUN (debug_ospf6_flooding
,
985 debug_ospf6_flooding_cmd
,
986 "debug ospf6 flooding",
989 "Debug OSPFv3 flooding function\n"
992 OSPF6_DEBUG_FLOODING_ON();
996 DEFUN (no_debug_ospf6_flooding
,
997 no_debug_ospf6_flooding_cmd
,
998 "no debug ospf6 flooding",
1002 "Debug OSPFv3 flooding function\n"
1005 OSPF6_DEBUG_FLOODING_OFF();
1009 int config_write_ospf6_debug_flood(struct vty
*vty
)
1011 if (IS_OSPF6_DEBUG_FLOODING
)
1012 vty_out(vty
, "debug ospf6 flooding%s", VNL
);
1016 void install_element_ospf6_debug_flood(void)
1018 install_element(ENABLE_NODE
, &debug_ospf6_flooding_cmd
);
1019 install_element(ENABLE_NODE
, &no_debug_ospf6_flooding_cmd
);
1020 install_element(CONFIG_NODE
, &debug_ospf6_flooding_cmd
);
1021 install_element(CONFIG_NODE
, &no_debug_ospf6_flooding_cmd
);