]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_flood.c
Merge pull request #12645 from gpnaveen/ospf_error_msg_enhancements
[mirror_frr.git] / ospf6d / ospf6_flood.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2003 Yasuhiro Ohara
4 */
5
6 #include <zebra.h>
7
8 #include "log.h"
9 #include "frrevent.h"
10 #include "linklist.h"
11 #include "vty.h"
12 #include "command.h"
13
14 #include "ospf6d.h"
15 #include "ospf6_proto.h"
16 #include "ospf6_lsa.h"
17 #include "ospf6_lsdb.h"
18 #include "ospf6_message.h"
19 #include "ospf6_route.h"
20 #include "ospf6_spf.h"
21
22 #include "ospf6_top.h"
23 #include "ospf6_area.h"
24 #include "ospf6_interface.h"
25 #include "ospf6_neighbor.h"
26
27 #include "ospf6_flood.h"
28 #include "ospf6_nssa.h"
29 #include "ospf6_gr.h"
30
31 unsigned char conf_debug_ospf6_flooding;
32
33 struct ospf6_lsdb *ospf6_get_scoped_lsdb(struct ospf6_lsa *lsa)
34 {
35 struct ospf6_lsdb *lsdb = NULL;
36 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
37 case OSPF6_SCOPE_LINKLOCAL:
38 lsdb = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb;
39 break;
40 case OSPF6_SCOPE_AREA:
41 lsdb = OSPF6_AREA(lsa->lsdb->data)->lsdb;
42 break;
43 case OSPF6_SCOPE_AS:
44 lsdb = OSPF6_PROCESS(lsa->lsdb->data)->lsdb;
45 break;
46 default:
47 assert(0);
48 break;
49 }
50 return lsdb;
51 }
52
53 struct ospf6_lsdb *ospf6_get_scoped_lsdb_self(struct ospf6_lsa *lsa)
54 {
55 struct ospf6_lsdb *lsdb_self = NULL;
56 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
57 case OSPF6_SCOPE_LINKLOCAL:
58 lsdb_self = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb_self;
59 break;
60 case OSPF6_SCOPE_AREA:
61 lsdb_self = OSPF6_AREA(lsa->lsdb->data)->lsdb_self;
62 break;
63 case OSPF6_SCOPE_AS:
64 lsdb_self = OSPF6_PROCESS(lsa->lsdb->data)->lsdb_self;
65 break;
66 default:
67 assert(0);
68 break;
69 }
70 return lsdb_self;
71 }
72
73 void ospf6_lsa_originate(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
74 {
75 struct ospf6_lsa *old;
76 struct ospf6_lsdb *lsdb_self;
77
78 if (lsa->header->adv_router == INADDR_ANY) {
79 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type))
80 zlog_debug(
81 "Refusing to originate LSA (zero router ID): %s",
82 lsa->name);
83
84 ospf6_lsa_delete(lsa);
85 return;
86 }
87
88 /* find previous LSA */
89 old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
90 lsa->header->adv_router, lsa->lsdb);
91
92 /* if the new LSA does not differ from previous,
93 suppress this update of the LSA */
94 if (old && !OSPF6_LSA_IS_DIFFER(lsa, old)
95 && !ospf6->gr_info.finishing_restart) {
96 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type))
97 zlog_debug("Suppress updating LSA: %s", lsa->name);
98 ospf6_lsa_delete(lsa);
99 return;
100 }
101
102 /* store it in the LSDB for self-originated LSAs */
103 lsdb_self = ospf6_get_scoped_lsdb_self(lsa);
104 ospf6_lsdb_add(ospf6_lsa_copy(lsa), lsdb_self);
105
106 EVENT_OFF(lsa->refresh);
107 event_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME,
108 &lsa->refresh);
109
110 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
111 || IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) {
112 zlog_debug("LSA Originate:");
113 ospf6_lsa_header_print(lsa);
114 }
115
116 ospf6_install_lsa(lsa);
117 ospf6_flood(NULL, lsa);
118 }
119
120 void ospf6_lsa_originate_process(struct ospf6_lsa *lsa, struct ospf6 *process)
121 {
122 lsa->lsdb = process->lsdb;
123 ospf6_lsa_originate(process, lsa);
124 }
125
126 void ospf6_lsa_originate_area(struct ospf6_lsa *lsa, struct ospf6_area *oa)
127 {
128 lsa->lsdb = oa->lsdb;
129 ospf6_lsa_originate(oa->ospf6, lsa);
130 }
131
132 void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
133 struct ospf6_interface *oi)
134 {
135 lsa->lsdb = oi->lsdb;
136 ospf6_lsa_originate(oi->area->ospf6, lsa);
137 }
138
139 void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
140 {
141 uint32_t id = lsa->header->id;
142 struct ospf6_area *oa;
143 struct listnode *lnode;
144
145 ospf6_lsa_purge(lsa);
146
147 /* Delete the corresponding NSSA LSA */
148 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, lnode, oa)) {
149 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), id,
150 ospf6->router_id, oa->lsdb);
151 if (lsa) {
152 if (IS_OSPF6_DEBUG_NSSA)
153 zlog_debug("withdraw type 7 lsa, LS ID: %u",
154 htonl(id));
155
156 ospf6_lsa_purge(lsa);
157 }
158 }
159 }
160
161 void ospf6_lsa_purge(struct ospf6_lsa *lsa)
162 {
163 struct ospf6_lsa *self;
164 struct ospf6_lsdb *lsdb_self;
165
166 /* remove it from the LSDB for self-originated LSAs */
167 lsdb_self = ospf6_get_scoped_lsdb_self(lsa);
168 self = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
169 lsa->header->adv_router, lsdb_self);
170 if (self) {
171 EVENT_OFF(self->expire);
172 EVENT_OFF(self->refresh);
173 ospf6_lsdb_remove(self, lsdb_self);
174 }
175
176 ospf6_lsa_premature_aging(lsa);
177 }
178
179 /* Puring Multi Link-State IDs LSAs:
180 * Same Advertising Router with Multiple Link-State IDs
181 * LSAs, purging require to traverse all Link-State IDs
182 */
183 void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, struct ospf6_lsa *lsa)
184 {
185 int ls_id = 0;
186 struct ospf6_lsa *lsa_next;
187 uint16_t type;
188
189 type = lsa->header->type;
190
191 ospf6_lsa_purge(lsa);
192
193 lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
194 oa->ospf6->router_id, oa->lsdb);
195 while (lsa_next) {
196 ospf6_lsa_purge(lsa_next);
197 lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
198 oa->ospf6->router_id, oa->lsdb);
199 }
200 }
201
202 void ospf6_increment_retrans_count(struct ospf6_lsa *lsa)
203 {
204 /* The LSA must be the original one (see the description
205 in ospf6_decrement_retrans_count () below) */
206 lsa->retrans_count++;
207 }
208
209 void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa)
210 {
211 struct ospf6_lsdb *lsdb;
212 struct ospf6_lsa *orig;
213
214 /* The LSA must be on the retrans-list of a neighbor. It means
215 the "lsa" is a copied one, and we have to decrement the
216 retransmission count of the original one (instead of this "lsa"'s).
217 In order to find the original LSA, first we have to find
218 appropriate LSDB that have the original LSA. */
219 lsdb = ospf6_get_scoped_lsdb(lsa);
220
221 /* Find the original LSA of which the retrans_count should be
222 * decremented */
223 orig = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
224 lsa->header->adv_router, lsdb);
225 if (orig) {
226 orig->retrans_count--;
227 assert(orig->retrans_count >= 0);
228 }
229 }
230
231 /* RFC2328 section 13.2 Installing LSAs in the database */
232 void ospf6_install_lsa(struct ospf6_lsa *lsa)
233 {
234 struct ospf6 *ospf6;
235 struct timeval now;
236 struct ospf6_lsa *old;
237 struct ospf6_area *area = NULL;
238
239 ospf6 = ospf6_get_by_lsdb(lsa);
240 assert(ospf6);
241
242 /* Remove the old instance from all neighbors' Link state
243 retransmission list (RFC2328 13.2 last paragraph) */
244 old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
245 lsa->header->adv_router, lsa->lsdb);
246 if (old) {
247 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
248 if (IS_OSPF6_DEBUG_NSSA)
249 zlog_debug("%s : old LSA %s", __func__,
250 lsa->name);
251 lsa->external_lsa_id = old->external_lsa_id;
252 }
253 EVENT_OFF(old->expire);
254 EVENT_OFF(old->refresh);
255 ospf6_flood_clear(old);
256 }
257
258 monotime(&now);
259 if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
260 event_add_timer(master, ospf6_lsa_expire, lsa,
261 OSPF_LSA_MAXAGE + lsa->birth.tv_sec -
262 now.tv_sec,
263 &lsa->expire);
264 } else
265 lsa->expire = NULL;
266
267 if (OSPF6_LSA_IS_SEQWRAP(lsa)
268 && !(CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)
269 && lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) {
270 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
271 zlog_debug("lsa install wrapping: sequence 0x%x",
272 ntohl(lsa->header->seqnum));
273 SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
274 /* in lieu of premature_aging, since we do not want to recreate
275 * this lsa
276 * and/or mess with timers etc, we just want to wrap the
277 * sequence number
278 * and reflood the lsa before continuing.
279 * NOTE: Flood needs to be called right after this function
280 * call, by the
281 * caller
282 */
283 lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER);
284 lsa->header->age = htons(OSPF_LSA_MAXAGE);
285 ospf6_lsa_checksum(lsa->header);
286 }
287
288 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
289 || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
290 zlog_debug("%s Install LSA: %s age %d seqnum %x in LSDB.",
291 __func__, lsa->name, ntohs(lsa->header->age),
292 ntohl(lsa->header->seqnum));
293
294 /* actually install */
295 lsa->installed = now;
296
297 /* Topo change handling */
298 if (CHECK_LSA_TOPO_CHG_ELIGIBLE(ntohs(lsa->header->type))
299 && !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) {
300
301 /* check if it is new lsa ? or existing lsa got modified ?*/
302 if (!old || OSPF6_LSA_IS_CHANGED(old, lsa))
303 ospf6_helper_handle_topo_chg(ospf6, lsa);
304 }
305
306 ospf6_lsdb_add(lsa, lsa->lsdb);
307
308 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
309 && lsa->header->adv_router != ospf6->router_id) {
310 area = OSPF6_AREA(lsa->lsdb->data);
311 ospf6_translated_nssa_refresh(area, lsa, NULL);
312 ospf6_schedule_abr_task(area->ospf6);
313 }
314
315 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
316 area = OSPF6_AREA(lsa->lsdb->data);
317 if (old == NULL) {
318 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
319 || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
320 zlog_debug("%s: New router LSA %s", __func__,
321 lsa->name);
322 ospf6_abr_nssa_check_status(area->ospf6);
323 }
324 }
325 return;
326 }
327
328 /* RFC2740 section 3.5.2. Sending Link State Update packets */
329 /* RFC2328 section 13.3 Next step in the flooding procedure */
330 void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
331 struct ospf6_interface *oi)
332 {
333 struct listnode *node, *nnode;
334 struct ospf6_neighbor *on;
335 struct ospf6_lsa *req, *old;
336 int retrans_added = 0;
337 int is_debug = 0;
338
339 if (IS_OSPF6_DEBUG_FLOODING
340 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) {
341 is_debug++;
342 zlog_debug("Flooding on %s: %s", oi->interface->name,
343 lsa->name);
344 }
345
346 /* (1) For each neighbor */
347 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
348 if (is_debug)
349 zlog_debug("To neighbor %s", on->name);
350
351 /* (a) if neighbor state < Exchange, examin next */
352 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
353 if (is_debug)
354 zlog_debug(
355 "Neighbor state less than ExChange, next neighbor");
356 continue;
357 }
358
359 /* (b) if neighbor not yet Full, check request-list */
360 if (on->state != OSPF6_NEIGHBOR_FULL) {
361 if (is_debug)
362 zlog_debug("Neighbor not yet Full");
363
364 req = ospf6_lsdb_lookup(
365 lsa->header->type, lsa->header->id,
366 lsa->header->adv_router, on->request_list);
367 if (req == NULL) {
368 if (is_debug)
369 zlog_debug(
370 "Not on request-list for this neighbor");
371 /* fall through */
372 } else {
373 /* If new LSA less recent, examin next neighbor
374 */
375 if (ospf6_lsa_compare(lsa, req) > 0) {
376 if (is_debug)
377 zlog_debug(
378 "Requesting is older, next neighbor");
379 continue;
380 }
381
382 /* If the same instance, delete from
383 request-list and
384 examin next neighbor */
385 if (ospf6_lsa_compare(lsa, req) == 0) {
386 if (is_debug)
387 zlog_debug(
388 "Requesting the same, remove it, next neighbor");
389 if (req == on->last_ls_req) {
390 /* sanity check refcount */
391 assert(req->lock >= 2);
392 req = ospf6_lsa_unlock(req);
393 on->last_ls_req = NULL;
394 }
395 if (req)
396 ospf6_lsdb_remove(
397 req, on->request_list);
398 ospf6_check_nbr_loading(on);
399 continue;
400 }
401
402 /* If the new LSA is more recent, delete from
403 * request-list */
404 if (ospf6_lsa_compare(lsa, req) < 0) {
405 if (is_debug)
406 zlog_debug(
407 "Received is newer, remove requesting");
408 if (req == on->last_ls_req) {
409 req = ospf6_lsa_unlock(req);
410 on->last_ls_req = NULL;
411 }
412 if (req)
413 ospf6_lsdb_remove(req,
414 on->request_list);
415 ospf6_check_nbr_loading(on);
416 /* fall through */
417 }
418 }
419 }
420
421 /* (c) If the new LSA was received from this neighbor,
422 examin next neighbor */
423 if (from == on) {
424 if (is_debug)
425 zlog_debug(
426 "Received is from the neighbor, next neighbor");
427 continue;
428 }
429
430 if ((oi->area->ospf6->inst_shutdown)
431 || CHECK_FLAG(lsa->flag, OSPF6_LSA_FLUSH)) {
432 if (is_debug)
433 zlog_debug(
434 "%s: Send LSA %s (age %d) update now",
435 __func__, lsa->name,
436 ntohs(lsa->header->age));
437 ospf6_lsupdate_send_neighbor_now(on, lsa);
438 continue;
439 } else {
440 /* (d) add retrans-list, schedule retransmission */
441 if (is_debug)
442 zlog_debug("Add retrans-list of neighbor %s ",
443 on->name);
444
445 /* Do not increment the retrans count if the lsa is
446 * already present in the retrans list.
447 */
448 old = ospf6_lsdb_lookup(
449 lsa->header->type, lsa->header->id,
450 lsa->header->adv_router, on->retrans_list);
451 if (!old) {
452 struct ospf6_lsa *orig;
453 struct ospf6_lsdb *lsdb;
454
455 if (is_debug)
456 zlog_debug(
457 "Increment %s from retrans_list of %s",
458 lsa->name, on->name);
459
460 /* Increment the retrans count on the original
461 * copy of LSA if present, to maintain the
462 * counter consistency.
463 */
464
465 lsdb = ospf6_get_scoped_lsdb(lsa);
466 orig = ospf6_lsdb_lookup(
467 lsa->header->type, lsa->header->id,
468 lsa->header->adv_router, lsdb);
469 if (orig)
470 ospf6_increment_retrans_count(orig);
471 else
472 ospf6_increment_retrans_count(lsa);
473
474 ospf6_lsdb_add(ospf6_lsa_copy(lsa),
475 on->retrans_list);
476 event_add_timer(master,
477 ospf6_lsupdate_send_neighbor,
478 on, on->ospf6_if->rxmt_interval,
479 &on->thread_send_lsupdate);
480 retrans_added++;
481 }
482 }
483 }
484
485 /* (2) examin next interface if not added to retrans-list */
486 if (retrans_added == 0) {
487 if (is_debug)
488 zlog_debug(
489 "No retransmission scheduled, next interface %s",
490 oi->interface->name);
491 return;
492 }
493
494 /* (3) If the new LSA was received on this interface,
495 and it was from DR or BDR, examin next interface */
496 if (from && from->ospf6_if == oi
497 && (from->router_id == oi->drouter
498 || from->router_id == oi->bdrouter)) {
499 if (is_debug)
500 zlog_debug(
501 "Received is from the I/F's DR or BDR, next interface");
502 return;
503 }
504
505 /* (4) If the new LSA was received on this interface,
506 and the interface state is BDR, examin next interface */
507 if (from && from->ospf6_if == oi) {
508 if (oi->state == OSPF6_INTERFACE_BDR) {
509 if (is_debug)
510 zlog_debug(
511 "Received is from the I/F, itself BDR, next interface");
512 return;
513 }
514 SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK);
515 }
516
517 /* (5) flood the LSA out the interface. */
518 if (is_debug)
519 zlog_debug("Schedule flooding for the interface");
520 if ((oi->type == OSPF_IFTYPE_BROADCAST)
521 || (oi->type == OSPF_IFTYPE_POINTOPOINT)) {
522 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsupdate_list);
523 event_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
524 &oi->thread_send_lsupdate);
525 } else {
526 /* reschedule retransmissions to all neighbors */
527 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
528 EVENT_OFF(on->thread_send_lsupdate);
529 event_add_event(master, ospf6_lsupdate_send_neighbor,
530 on, 0, &on->thread_send_lsupdate);
531 }
532 }
533 }
534
535 void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
536 struct ospf6_area *oa)
537 {
538 struct listnode *node, *nnode;
539 struct ospf6_interface *oi;
540
541 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
542 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
543 && oi != OSPF6_INTERFACE(lsa->lsdb->data))
544 continue;
545
546 ospf6_flood_interface(from, lsa, oi);
547 }
548 }
549
550 static void ospf6_flood_process(struct ospf6_neighbor *from,
551 struct ospf6_lsa *lsa, struct ospf6 *process)
552 {
553 struct listnode *node, *nnode;
554 struct ospf6_area *oa;
555
556 for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) {
557
558 /* If unknown LSA and U-bit clear, treat as link local
559 * flooding scope
560 */
561 if (!OSPF6_LSA_IS_KNOWN(lsa->header->type)
562 && !(ntohs(lsa->header->type) & OSPF6_LSTYPE_UBIT_MASK)
563 && (oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)) {
564
565 if (IS_OSPF6_DEBUG_FLOODING)
566 zlog_debug("Unknown LSA, do not flood");
567 continue;
568 }
569
570 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA
571 && oa != OSPF6_AREA(lsa->lsdb->data))
572 continue;
573 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
574 && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)
575 continue;
576
577 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
578 && (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)))
579 continue;
580
581 /* Check for NSSA LSA */
582 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
583 && !IS_AREA_NSSA(oa) && !OSPF6_LSA_IS_MAXAGE(lsa))
584 continue;
585
586 ospf6_flood_area(from, lsa, oa);
587 }
588 }
589
590 void ospf6_flood(struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
591 {
592 struct ospf6 *ospf6;
593
594 ospf6 = ospf6_get_by_lsdb(lsa);
595 if (ospf6 == NULL)
596 return;
597
598 ospf6_flood_process(from, lsa, ospf6);
599 }
600
601 static void ospf6_flood_clear_interface(struct ospf6_lsa *lsa,
602 struct ospf6_interface *oi)
603 {
604 struct listnode *node, *nnode;
605 struct ospf6_neighbor *on;
606 struct ospf6_lsa *rem;
607
608 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
609 rem = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
610 lsa->header->adv_router,
611 on->retrans_list);
612 if (rem && !ospf6_lsa_compare(rem, lsa)) {
613 if (IS_OSPF6_DEBUG_FLOODING
614 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
615 zlog_debug("Remove %s from retrans_list of %s",
616 rem->name, on->name);
617 ospf6_decrement_retrans_count(rem);
618 ospf6_lsdb_remove(rem, on->retrans_list);
619 }
620 }
621 }
622
623 void ospf6_flood_clear_area(struct ospf6_lsa *lsa, struct ospf6_area *oa)
624 {
625 struct listnode *node, *nnode;
626 struct ospf6_interface *oi;
627
628 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
629 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
630 && oi != OSPF6_INTERFACE(lsa->lsdb->data))
631 continue;
632
633 ospf6_flood_clear_interface(lsa, oi);
634 }
635 }
636
637 static void ospf6_flood_clear_process(struct ospf6_lsa *lsa,
638 struct ospf6 *process)
639 {
640 struct listnode *node, *nnode;
641 struct ospf6_area *oa;
642
643 for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) {
644 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA
645 && oa != OSPF6_AREA(lsa->lsdb->data))
646 continue;
647 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
648 && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)
649 continue;
650
651 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
652 && (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa))))
653 continue;
654 /* Check for NSSA LSA */
655 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
656 && !IS_AREA_NSSA(oa))
657 continue;
658
659 ospf6_flood_clear_area(lsa, oa);
660 }
661 }
662
663 void ospf6_flood_clear(struct ospf6_lsa *lsa)
664 {
665 struct ospf6 *ospf6;
666
667 ospf6 = ospf6_get_by_lsdb(lsa);
668 if (ospf6 == NULL)
669 return;
670 ospf6_flood_clear_process(lsa, ospf6);
671 }
672
673
674 /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
675 static void ospf6_acknowledge_lsa_bdrouter(struct ospf6_lsa *lsa,
676 int ismore_recent,
677 struct ospf6_neighbor *from)
678 {
679 struct ospf6_interface *oi;
680 int is_debug = 0;
681
682 if (IS_OSPF6_DEBUG_FLOODING
683 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
684 is_debug++;
685
686 assert(from && from->ospf6_if);
687 oi = from->ospf6_if;
688
689 /* LSA is more recent than database copy, but was not flooded
690 back out receiving interface. Delayed acknowledgement sent
691 if advertisement received from Designated Router,
692 otherwide do nothing. */
693 if (ismore_recent < 0) {
694 if (oi->drouter == from->router_id) {
695 if (is_debug)
696 zlog_debug(
697 "Delayed acknowledgement (BDR & MoreRecent & from DR)");
698 /* Delayed acknowledgement */
699 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
700 event_add_timer(master, ospf6_lsack_send_interface, oi,
701 3, &oi->thread_send_lsack);
702 } else {
703 if (is_debug)
704 zlog_debug(
705 "No acknowledgement (BDR & MoreRecent & ! from DR)");
706 }
707 return;
708 }
709
710 /* LSA is a duplicate, and was treated as an implied acknowledgement.
711 Delayed acknowledgement sent if advertisement received from
712 Designated Router, otherwise do nothing */
713 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
714 && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
715 if (oi->drouter == from->router_id) {
716 if (is_debug)
717 zlog_debug(
718 "Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
719 /* Delayed acknowledgement */
720 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
721 event_add_timer(master, ospf6_lsack_send_interface, oi,
722 3, &oi->thread_send_lsack);
723 } else {
724 if (is_debug)
725 zlog_debug(
726 "No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
727 }
728 return;
729 }
730
731 /* LSA is a duplicate, and was not treated as an implied
732 acknowledgement.
733 Direct acknowledgement sent */
734 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
735 && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
736 if (is_debug)
737 zlog_debug("Direct acknowledgement (BDR & Duplicate)");
738 ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list);
739 event_add_event(master, ospf6_lsack_send_neighbor, from, 0,
740 &from->thread_send_lsack);
741 return;
742 }
743
744 /* LSA's LS age is equal to Maxage, and there is no current instance
745 of the LSA in the link state database, and none of router's
746 neighbors are in states Exchange or Loading */
747 /* Direct acknowledgement sent, but this case is handled in
748 early of ospf6_receive_lsa () */
749 }
750
751 static void ospf6_acknowledge_lsa_allother(struct ospf6_lsa *lsa,
752 int ismore_recent,
753 struct ospf6_neighbor *from)
754 {
755 struct ospf6_interface *oi;
756 int is_debug = 0;
757
758 if (IS_OSPF6_DEBUG_FLOODING
759 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
760 is_debug++;
761
762 assert(from && from->ospf6_if);
763 oi = from->ospf6_if;
764
765 /* LSA has been flood back out receiving interface.
766 No acknowledgement sent. */
767 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK)) {
768 if (is_debug)
769 zlog_debug("No acknowledgement (AllOther & FloodBack)");
770 return;
771 }
772
773 /* LSA is more recent than database copy, but was not flooded
774 back out receiving interface. Delayed acknowledgement sent. */
775 if (ismore_recent < 0) {
776 if (is_debug)
777 zlog_debug(
778 "Delayed acknowledgement (AllOther & MoreRecent)");
779 /* Delayed acknowledgement */
780 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
781 event_add_timer(master, ospf6_lsack_send_interface, oi, 3,
782 &oi->thread_send_lsack);
783 return;
784 }
785
786 /* LSA is a duplicate, and was treated as an implied acknowledgement.
787 No acknowledgement sent. */
788 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
789 && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
790 if (is_debug)
791 zlog_debug(
792 "No acknowledgement (AllOther & Duplicate & ImpliedAck)");
793 return;
794 }
795
796 /* LSA is a duplicate, and was not treated as an implied
797 acknowledgement.
798 Direct acknowledgement sent */
799 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
800 && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
801 if (is_debug)
802 zlog_debug(
803 "Direct acknowledgement (AllOther & Duplicate)");
804 ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list);
805 event_add_event(master, ospf6_lsack_send_neighbor, from, 0,
806 &from->thread_send_lsack);
807 return;
808 }
809
810 /* LSA's LS age is equal to Maxage, and there is no current instance
811 of the LSA in the link state database, and none of router's
812 neighbors are in states Exchange or Loading */
813 /* Direct acknowledgement sent, but this case is handled in
814 early of ospf6_receive_lsa () */
815 }
816
817 static void ospf6_acknowledge_lsa(struct ospf6_lsa *lsa, int ismore_recent,
818 struct ospf6_neighbor *from)
819 {
820 struct ospf6_interface *oi;
821
822 assert(from && from->ospf6_if);
823 oi = from->ospf6_if;
824
825 if (oi->state == OSPF6_INTERFACE_BDR)
826 ospf6_acknowledge_lsa_bdrouter(lsa, ismore_recent, from);
827 else
828 ospf6_acknowledge_lsa_allother(lsa, ismore_recent, from);
829 }
830
831 /* RFC2328 section 13 (4):
832 if MaxAge LSA and if we have no instance, and no neighbor
833 is in states Exchange or Loading
834 returns 1 if match this case, else returns 0 */
835 static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa,
836 struct ospf6_neighbor *from)
837 {
838 struct ospf6_neighbor *on;
839 struct ospf6_interface *oi;
840 struct ospf6_area *oa;
841 struct ospf6 *process = NULL;
842 struct listnode *i, *j, *k;
843 int count = 0;
844
845 if (!OSPF6_LSA_IS_MAXAGE(lsa))
846 return 0;
847
848 if (ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
849 lsa->header->adv_router, lsa->lsdb))
850 return 0;
851
852 process = from->ospf6_if->area->ospf6;
853
854 for (ALL_LIST_ELEMENTS_RO(process->area_list, i, oa))
855 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
856 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on))
857 if (on->state == OSPF6_NEIGHBOR_EXCHANGE
858 || on->state == OSPF6_NEIGHBOR_LOADING)
859 count++;
860
861 if (count == 0)
862 return 1;
863 return 0;
864 }
865
866 static bool ospf6_lsa_check_min_arrival(struct ospf6_lsa *lsa,
867 struct ospf6_neighbor *from)
868 {
869 struct timeval now, res;
870 unsigned int time_delta_ms;
871
872 monotime(&now);
873 timersub(&now, &lsa->installed, &res);
874 time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
875
876 if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) {
877 if (IS_OSPF6_DEBUG_FLOODING ||
878 IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
879 zlog_debug(
880 "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
881 time_delta_ms,
882 from->ospf6_if->area->ospf6->lsa_minarrival);
883 return true;
884 }
885 return false;
886 }
887
888 /* RFC2328 section 13 The Flooding Procedure */
889 void ospf6_receive_lsa(struct ospf6_neighbor *from,
890 struct ospf6_lsa_header *lsa_header)
891 {
892 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
893 int ismore_recent;
894 int is_debug = 0;
895
896 ismore_recent = 1;
897 assert(from);
898
899 /* if we receive a LSA with invalid seqnum drop it */
900 if (ntohl(lsa_header->seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) {
901 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa_header->type)) {
902 zlog_debug(
903 "received lsa [%s Id:%pI4 Adv:%pI4] with invalid seqnum 0x%x, ignore",
904 ospf6_lstype_name(lsa_header->type),
905 &lsa_header->id, &lsa_header->adv_router,
906 ntohl(lsa_header->seqnum));
907 }
908 return;
909 }
910
911 /* make lsa structure for received lsa */
912 new = ospf6_lsa_create(lsa_header);
913
914 if (IS_OSPF6_DEBUG_FLOODING
915 || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header->type)) {
916 is_debug++;
917 zlog_debug("LSA Receive from %s", from->name);
918 ospf6_lsa_header_print(new);
919 }
920
921 /* (1) LSA Checksum */
922 if (!ospf6_lsa_checksum_valid(new->header)) {
923 if (is_debug)
924 zlog_debug(
925 "Wrong LSA Checksum %s (Router-ID: %pI4) [Type:%s Checksum:%#06hx), discard",
926 from->name, &from->router_id,
927 ospf6_lstype_name(new->header->type),
928 ntohs(new->header->checksum));
929 ospf6_lsa_delete(new);
930 return;
931 }
932
933 /* (2) Examine the LSA's LS type.
934 RFC2470 3.5.1. Receiving Link State Update packets */
935 if (IS_AREA_STUB(from->ospf6_if->area)
936 && OSPF6_LSA_SCOPE(new->header->type) == OSPF6_SCOPE_AS) {
937 if (is_debug)
938 zlog_debug(
939 "AS-External-LSA (or AS-scope LSA) in stub area, discard");
940 ospf6_lsa_delete(new);
941 return;
942 }
943
944 /* (3) LSA which have reserved scope is discarded
945 RFC2470 3.5.1. Receiving Link State Update packets */
946 /* Flooding scope check. LSAs with unknown scope are discarded here.
947 Set appropriate LSDB for the LSA */
948 switch (OSPF6_LSA_SCOPE(new->header->type)) {
949 case OSPF6_SCOPE_LINKLOCAL:
950 new->lsdb = from->ospf6_if->lsdb;
951 break;
952 case OSPF6_SCOPE_AREA:
953 new->lsdb = from->ospf6_if->area->lsdb;
954 break;
955 case OSPF6_SCOPE_AS:
956 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
957 break;
958 default:
959 if (is_debug)
960 zlog_debug("LSA has reserved scope, discard");
961 ospf6_lsa_delete(new);
962 return;
963 }
964
965 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
966 is in states Exchange or Loading */
967 if (ospf6_is_maxage_lsa_drop(new, from)) {
968 /* log */
969 if (is_debug)
970 zlog_debug(
971 "Drop MaxAge LSA with direct acknowledgement.");
972
973 /* a) Acknowledge back to neighbor (Direct acknowledgement,
974 * 13.5) */
975 ospf6_lsdb_add(ospf6_lsa_copy(new), from->lsack_list);
976 event_add_event(master, ospf6_lsack_send_neighbor, from, 0,
977 &from->thread_send_lsack);
978
979 /* b) Discard */
980 ospf6_lsa_delete(new);
981 return;
982 }
983
984 /* (5) */
985 /* lookup the same database copy in lsdb */
986 old = ospf6_lsdb_lookup(new->header->type, new->header->id,
987 new->header->adv_router, new->lsdb);
988 if (old) {
989 ismore_recent = ospf6_lsa_compare(new, old);
990 if (ntohl(new->header->seqnum) == ntohl(old->header->seqnum)) {
991 if (is_debug)
992 zlog_debug("Received is duplicated LSA");
993 SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE);
994 }
995 }
996
997 /* if no database copy or received is more recent */
998 if (old == NULL || ismore_recent < 0) {
999 bool self_originated;
1000
1001 /* in case we have no database copy */
1002 ismore_recent = -1;
1003
1004 /* (a) MinLSArrival check */
1005 if (old) {
1006 if (ospf6_lsa_check_min_arrival(old, from)) {
1007 ospf6_lsa_delete(new);
1008 return; /* examin next lsa */
1009 }
1010 }
1011
1012 monotime(&new->received);
1013
1014 if (is_debug)
1015 zlog_debug(
1016 "Install, Flood, Possibly acknowledge the received LSA");
1017
1018 /* Remove older copies of this LSA from retx lists */
1019 if (old)
1020 ospf6_flood_clear(old);
1021
1022 self_originated = (new->header->adv_router
1023 == from->ospf6_if->area->ospf6->router_id);
1024
1025 /* Received non-self-originated Grace LSA. */
1026 if (IS_GRACE_LSA(new) && !self_originated) {
1027 struct ospf6 *ospf6;
1028
1029 ospf6 = ospf6_get_by_lsdb(new);
1030
1031 assert(ospf6);
1032
1033 if (OSPF6_LSA_IS_MAXAGE(new)) {
1034
1035 if (IS_DEBUG_OSPF6_GR)
1036 zlog_debug(
1037 "%s, Received a maxage GraceLSA from router %pI4",
1038 __func__,
1039 &new->header->adv_router);
1040 if (old) {
1041 ospf6_process_maxage_grace_lsa(
1042 ospf6, new, from);
1043 } else {
1044 if (IS_DEBUG_OSPF6_GR)
1045 zlog_debug(
1046 "%s, GraceLSA doesn't exist in lsdb, so discarding GraceLSA",
1047 __func__);
1048 return;
1049 }
1050 } else {
1051
1052 if (IS_DEBUG_OSPF6_GR)
1053 zlog_debug(
1054 "%s, Received a GraceLSA from router %pI4",
1055 __func__,
1056 &new->header->adv_router);
1057
1058 if (ospf6_process_grace_lsa(ospf6, new, from)
1059 == OSPF6_GR_NOT_HELPER) {
1060 if (IS_DEBUG_OSPF6_GR)
1061 zlog_debug(
1062 "%s, Not moving to HELPER role, So dicarding GraceLSA",
1063 __func__);
1064 return;
1065 }
1066 }
1067 }
1068
1069 /* (b) immediately flood and (c) remove from all retrans-list */
1070 /* Prevent self-originated LSA to be flooded. this is to make
1071 * reoriginated instance of the LSA not to be rejected by other
1072 * routers due to MinLSArrival.
1073 */
1074 if (!self_originated)
1075 ospf6_flood(from, new);
1076
1077 /* (d), installing lsdb, which may cause routing
1078 table calculation (replacing database copy) */
1079 ospf6_install_lsa(new);
1080
1081 if (OSPF6_LSA_IS_MAXAGE(new))
1082 ospf6_maxage_remove(from->ospf6_if->area->ospf6);
1083
1084 /* (e) possibly acknowledge */
1085 ospf6_acknowledge_lsa(new, ismore_recent, from);
1086
1087 /* (f) Self Originated LSA, section 13.4 */
1088 if (self_originated) {
1089 if (from->ospf6_if->area->ospf6->gr_info
1090 .restart_in_progress) {
1091 if (IS_DEBUG_OSPF6_GR)
1092 zlog_debug(
1093 "Graceful Restart in progress -- not flushing self-originated LSA: %s",
1094 new->name);
1095 return;
1096 }
1097
1098 /* Self-originated LSA (newer than ours) is received
1099 from
1100 another router. We have to make a new instance of the
1101 LSA
1102 or have to flush this LSA. */
1103 if (is_debug) {
1104 zlog_debug(
1105 "Newer instance of the self-originated LSA");
1106 zlog_debug("Schedule reorigination");
1107 }
1108 event_add_event(master, ospf6_lsa_refresh, new, 0,
1109 &new->refresh);
1110 }
1111
1112 /* GR: check for network topology change. */
1113 struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
1114 struct ospf6_area *area = from->ospf6_if->area;
1115 if (ospf6->gr_info.restart_in_progress &&
1116 (new->header->type == ntohs(OSPF6_LSTYPE_ROUTER) ||
1117 new->header->type == ntohs(OSPF6_LSTYPE_NETWORK)))
1118 ospf6_gr_check_lsdb_consistency(ospf6, area);
1119
1120 return;
1121 }
1122
1123 /* (6) if there is instance on sending neighbor's request list */
1124 if (ospf6_lsdb_lookup(new->header->type, new->header->id,
1125 new->header->adv_router, from->request_list)) {
1126 /* if no database copy, should go above state (5) */
1127 assert(old);
1128
1129 zlog_warn(
1130 "Received is not newer, on the neighbor %s request-list",
1131 from->name);
1132 zlog_warn(
1133 "BadLSReq, discard the received LSA lsa %s send badLSReq",
1134 new->name);
1135
1136 /* BadLSReq */
1137 event_add_event(master, bad_lsreq, from, 0, NULL);
1138
1139 ospf6_lsa_delete(new);
1140 return;
1141 }
1142
1143 /* (7) if neither one is more recent */
1144 if (ismore_recent == 0) {
1145 if (is_debug)
1146 zlog_debug(
1147 "The same instance as database copy (neither recent)");
1148
1149 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack
1150 */
1151 rem = ospf6_lsdb_lookup(new->header->type, new->header->id,
1152 new->header->adv_router,
1153 from->retrans_list);
1154 if (rem) {
1155 if (is_debug) {
1156 zlog_debug(
1157 "It is on the neighbor's retrans-list.");
1158 zlog_debug(
1159 "Treat as an Implied acknowledgement");
1160 }
1161 SET_FLAG(new->flag, OSPF6_LSA_IMPLIEDACK);
1162 ospf6_decrement_retrans_count(rem);
1163 ospf6_lsdb_remove(rem, from->retrans_list);
1164 }
1165
1166 if (is_debug)
1167 zlog_debug("Possibly acknowledge and then discard");
1168
1169 /* (b) possibly acknowledge */
1170 ospf6_acknowledge_lsa(new, ismore_recent, from);
1171
1172 ospf6_lsa_delete(new);
1173 return;
1174 }
1175
1176 /* (8) previous database copy is more recent */
1177 {
1178 assert(old);
1179
1180 /* If database copy is in 'Seqnumber Wrapping',
1181 simply discard the received LSA */
1182 if (OSPF6_LSA_IS_MAXAGE(old)
1183 && old->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) {
1184 if (is_debug) {
1185 zlog_debug("The LSA is in Seqnumber Wrapping");
1186 zlog_debug("MaxAge & MaxSeqNum, discard");
1187 }
1188 ospf6_lsa_delete(new);
1189 return;
1190 }
1191
1192 /* Otherwise, Send database copy of this LSA to this neighbor */
1193 {
1194 if (is_debug) {
1195 zlog_debug("Database copy is more recent.");
1196 zlog_debug(
1197 "Send back directly and then discard");
1198 }
1199
1200 /* Neighbor router sent recent age for LSA,
1201 * Router could be restarted while current copy is
1202 * MAXAGEd and not removed.*/
1203 if (OSPF6_LSA_IS_MAXAGE(old)
1204 && !OSPF6_LSA_IS_MAXAGE(new)) {
1205 if (new->header->adv_router
1206 != from->ospf6_if->area->ospf6->router_id) {
1207 if (is_debug)
1208 zlog_debug(
1209 "%s: Current copy of LSA %s is MAXAGE, but new has recent age, flooding/installing.",
1210 __PRETTY_FUNCTION__, old->name);
1211 ospf6_lsa_purge(old);
1212 ospf6_flood(from, new);
1213 ospf6_install_lsa(new);
1214 return;
1215 }
1216 /* For self-originated LSA, only trust
1217 * ourselves. Fall through and send
1218 * LS Update with our current copy.
1219 */
1220 if (is_debug)
1221 zlog_debug(
1222 "%s: Current copy of self-originated LSA %s is MAXAGE, but new has recent age, re-sending current one.",
1223 __PRETTY_FUNCTION__, old->name);
1224 }
1225
1226 /* MinLSArrival check as per RFC 2328 13 (8) */
1227 if (ospf6_lsa_check_min_arrival(old, from)) {
1228 ospf6_lsa_delete(new);
1229 return; /* examin next lsa */
1230 }
1231
1232 ospf6_lsdb_add(ospf6_lsa_copy(old),
1233 from->lsupdate_list);
1234 event_add_event(master, ospf6_lsupdate_send_neighbor,
1235 from, 0, &from->thread_send_lsupdate);
1236
1237 ospf6_lsa_delete(new);
1238 return;
1239 }
1240 }
1241 }
1242
1243 DEFUN (debug_ospf6_flooding,
1244 debug_ospf6_flooding_cmd,
1245 "debug ospf6 flooding",
1246 DEBUG_STR
1247 OSPF6_STR
1248 "Debug OSPFv3 flooding function\n"
1249 )
1250 {
1251 OSPF6_DEBUG_FLOODING_ON();
1252 return CMD_SUCCESS;
1253 }
1254
1255 DEFUN (no_debug_ospf6_flooding,
1256 no_debug_ospf6_flooding_cmd,
1257 "no debug ospf6 flooding",
1258 NO_STR
1259 DEBUG_STR
1260 OSPF6_STR
1261 "Debug OSPFv3 flooding function\n"
1262 )
1263 {
1264 OSPF6_DEBUG_FLOODING_OFF();
1265 return CMD_SUCCESS;
1266 }
1267
1268 int config_write_ospf6_debug_flood(struct vty *vty)
1269 {
1270 if (IS_OSPF6_DEBUG_FLOODING)
1271 vty_out(vty, "debug ospf6 flooding\n");
1272 return 0;
1273 }
1274
1275 void install_element_ospf6_debug_flood(void)
1276 {
1277 install_element(ENABLE_NODE, &debug_ospf6_flooding_cmd);
1278 install_element(ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
1279 install_element(CONFIG_NODE, &debug_ospf6_flooding_cmd);
1280 install_element(CONFIG_NODE, &no_debug_ospf6_flooding_cmd);
1281 }