]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_flood.c
Merge pull request #12982 from opensourcerouting/fix/commmitlint_condition
[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 "thread.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 THREAD_OFF(lsa->refresh);
107 thread_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 THREAD_OFF(self->expire);
172 THREAD_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 THREAD_OFF(old->expire);
254 THREAD_OFF(old->refresh);
255 ospf6_flood_clear(old);
256 }
257
258 monotime(&now);
259 if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
260 thread_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 thread_add_timer(
477 master, 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 thread_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 THREAD_OFF(on->thread_send_lsupdate);
529 thread_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 thread_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 thread_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 thread_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 thread_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 thread_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("Wrong LSA Checksum, discard");
925 ospf6_lsa_delete(new);
926 return;
927 }
928
929 /* (2) Examine the LSA's LS type.
930 RFC2470 3.5.1. Receiving Link State Update packets */
931 if (IS_AREA_STUB(from->ospf6_if->area)
932 && OSPF6_LSA_SCOPE(new->header->type) == OSPF6_SCOPE_AS) {
933 if (is_debug)
934 zlog_debug(
935 "AS-External-LSA (or AS-scope LSA) in stub area, discard");
936 ospf6_lsa_delete(new);
937 return;
938 }
939
940 /* (3) LSA which have reserved scope is discarded
941 RFC2470 3.5.1. Receiving Link State Update packets */
942 /* Flooding scope check. LSAs with unknown scope are discarded here.
943 Set appropriate LSDB for the LSA */
944 switch (OSPF6_LSA_SCOPE(new->header->type)) {
945 case OSPF6_SCOPE_LINKLOCAL:
946 new->lsdb = from->ospf6_if->lsdb;
947 break;
948 case OSPF6_SCOPE_AREA:
949 new->lsdb = from->ospf6_if->area->lsdb;
950 break;
951 case OSPF6_SCOPE_AS:
952 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
953 break;
954 default:
955 if (is_debug)
956 zlog_debug("LSA has reserved scope, discard");
957 ospf6_lsa_delete(new);
958 return;
959 }
960
961 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
962 is in states Exchange or Loading */
963 if (ospf6_is_maxage_lsa_drop(new, from)) {
964 /* log */
965 if (is_debug)
966 zlog_debug(
967 "Drop MaxAge LSA with direct acknowledgement.");
968
969 /* a) Acknowledge back to neighbor (Direct acknowledgement,
970 * 13.5) */
971 ospf6_lsdb_add(ospf6_lsa_copy(new), from->lsack_list);
972 thread_add_event(master, ospf6_lsack_send_neighbor, from, 0,
973 &from->thread_send_lsack);
974
975 /* b) Discard */
976 ospf6_lsa_delete(new);
977 return;
978 }
979
980 /* (5) */
981 /* lookup the same database copy in lsdb */
982 old = ospf6_lsdb_lookup(new->header->type, new->header->id,
983 new->header->adv_router, new->lsdb);
984 if (old) {
985 ismore_recent = ospf6_lsa_compare(new, old);
986 if (ntohl(new->header->seqnum) == ntohl(old->header->seqnum)) {
987 if (is_debug)
988 zlog_debug("Received is duplicated LSA");
989 SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE);
990 }
991 }
992
993 /* if no database copy or received is more recent */
994 if (old == NULL || ismore_recent < 0) {
995 bool self_originated;
996
997 /* in case we have no database copy */
998 ismore_recent = -1;
999
1000 /* (a) MinLSArrival check */
1001 if (old) {
1002 if (ospf6_lsa_check_min_arrival(old, from)) {
1003 ospf6_lsa_delete(new);
1004 return; /* examin next lsa */
1005 }
1006 }
1007
1008 monotime(&new->received);
1009
1010 if (is_debug)
1011 zlog_debug(
1012 "Install, Flood, Possibly acknowledge the received LSA");
1013
1014 /* Remove older copies of this LSA from retx lists */
1015 if (old)
1016 ospf6_flood_clear(old);
1017
1018 self_originated = (new->header->adv_router
1019 == from->ospf6_if->area->ospf6->router_id);
1020
1021 /* Received non-self-originated Grace LSA. */
1022 if (IS_GRACE_LSA(new) && !self_originated) {
1023 struct ospf6 *ospf6;
1024
1025 ospf6 = ospf6_get_by_lsdb(new);
1026
1027 assert(ospf6);
1028
1029 if (OSPF6_LSA_IS_MAXAGE(new)) {
1030
1031 if (IS_DEBUG_OSPF6_GR)
1032 zlog_debug(
1033 "%s, Received a maxage GraceLSA from router %pI4",
1034 __func__,
1035 &new->header->adv_router);
1036 if (old) {
1037 ospf6_process_maxage_grace_lsa(
1038 ospf6, new, from);
1039 } else {
1040 if (IS_DEBUG_OSPF6_GR)
1041 zlog_debug(
1042 "%s, GraceLSA doesn't exist in lsdb, so discarding GraceLSA",
1043 __func__);
1044 return;
1045 }
1046 } else {
1047
1048 if (IS_DEBUG_OSPF6_GR)
1049 zlog_debug(
1050 "%s, Received a GraceLSA from router %pI4",
1051 __func__,
1052 &new->header->adv_router);
1053
1054 if (ospf6_process_grace_lsa(ospf6, new, from)
1055 == OSPF6_GR_NOT_HELPER) {
1056 if (IS_DEBUG_OSPF6_GR)
1057 zlog_debug(
1058 "%s, Not moving to HELPER role, So dicarding GraceLSA",
1059 __func__);
1060 return;
1061 }
1062 }
1063 }
1064
1065 /* (b) immediately flood and (c) remove from all retrans-list */
1066 /* Prevent self-originated LSA to be flooded. this is to make
1067 * reoriginated instance of the LSA not to be rejected by other
1068 * routers due to MinLSArrival.
1069 */
1070 if (!self_originated)
1071 ospf6_flood(from, new);
1072
1073 /* (d), installing lsdb, which may cause routing
1074 table calculation (replacing database copy) */
1075 ospf6_install_lsa(new);
1076
1077 if (OSPF6_LSA_IS_MAXAGE(new))
1078 ospf6_maxage_remove(from->ospf6_if->area->ospf6);
1079
1080 /* (e) possibly acknowledge */
1081 ospf6_acknowledge_lsa(new, ismore_recent, from);
1082
1083 /* (f) Self Originated LSA, section 13.4 */
1084 if (self_originated) {
1085 if (from->ospf6_if->area->ospf6->gr_info
1086 .restart_in_progress) {
1087 if (IS_DEBUG_OSPF6_GR)
1088 zlog_debug(
1089 "Graceful Restart in progress -- not flushing self-originated LSA: %s",
1090 new->name);
1091 return;
1092 }
1093
1094 /* Self-originated LSA (newer than ours) is received
1095 from
1096 another router. We have to make a new instance of the
1097 LSA
1098 or have to flush this LSA. */
1099 if (is_debug) {
1100 zlog_debug(
1101 "Newer instance of the self-originated LSA");
1102 zlog_debug("Schedule reorigination");
1103 }
1104 thread_add_event(master, ospf6_lsa_refresh, new, 0,
1105 &new->refresh);
1106 }
1107
1108 /* GR: check for network topology change. */
1109 struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
1110 struct ospf6_area *area = from->ospf6_if->area;
1111 if (ospf6->gr_info.restart_in_progress &&
1112 (new->header->type == ntohs(OSPF6_LSTYPE_ROUTER) ||
1113 new->header->type == ntohs(OSPF6_LSTYPE_NETWORK)))
1114 ospf6_gr_check_lsdb_consistency(ospf6, area);
1115
1116 return;
1117 }
1118
1119 /* (6) if there is instance on sending neighbor's request list */
1120 if (ospf6_lsdb_lookup(new->header->type, new->header->id,
1121 new->header->adv_router, from->request_list)) {
1122 /* if no database copy, should go above state (5) */
1123 assert(old);
1124
1125 zlog_warn(
1126 "Received is not newer, on the neighbor %s request-list",
1127 from->name);
1128 zlog_warn(
1129 "BadLSReq, discard the received LSA lsa %s send badLSReq",
1130 new->name);
1131
1132 /* BadLSReq */
1133 thread_add_event(master, bad_lsreq, from, 0, NULL);
1134
1135 ospf6_lsa_delete(new);
1136 return;
1137 }
1138
1139 /* (7) if neither one is more recent */
1140 if (ismore_recent == 0) {
1141 if (is_debug)
1142 zlog_debug(
1143 "The same instance as database copy (neither recent)");
1144
1145 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack
1146 */
1147 rem = ospf6_lsdb_lookup(new->header->type, new->header->id,
1148 new->header->adv_router,
1149 from->retrans_list);
1150 if (rem) {
1151 if (is_debug) {
1152 zlog_debug(
1153 "It is on the neighbor's retrans-list.");
1154 zlog_debug(
1155 "Treat as an Implied acknowledgement");
1156 }
1157 SET_FLAG(new->flag, OSPF6_LSA_IMPLIEDACK);
1158 ospf6_decrement_retrans_count(rem);
1159 ospf6_lsdb_remove(rem, from->retrans_list);
1160 }
1161
1162 if (is_debug)
1163 zlog_debug("Possibly acknowledge and then discard");
1164
1165 /* (b) possibly acknowledge */
1166 ospf6_acknowledge_lsa(new, ismore_recent, from);
1167
1168 ospf6_lsa_delete(new);
1169 return;
1170 }
1171
1172 /* (8) previous database copy is more recent */
1173 {
1174 assert(old);
1175
1176 /* If database copy is in 'Seqnumber Wrapping',
1177 simply discard the received LSA */
1178 if (OSPF6_LSA_IS_MAXAGE(old)
1179 && old->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) {
1180 if (is_debug) {
1181 zlog_debug("The LSA is in Seqnumber Wrapping");
1182 zlog_debug("MaxAge & MaxSeqNum, discard");
1183 }
1184 ospf6_lsa_delete(new);
1185 return;
1186 }
1187
1188 /* Otherwise, Send database copy of this LSA to this neighbor */
1189 {
1190 if (is_debug) {
1191 zlog_debug("Database copy is more recent.");
1192 zlog_debug(
1193 "Send back directly and then discard");
1194 }
1195
1196 /* Neighbor router sent recent age for LSA,
1197 * Router could be restarted while current copy is
1198 * MAXAGEd and not removed.*/
1199 if (OSPF6_LSA_IS_MAXAGE(old)
1200 && !OSPF6_LSA_IS_MAXAGE(new)) {
1201 if (new->header->adv_router
1202 != from->ospf6_if->area->ospf6->router_id) {
1203 if (is_debug)
1204 zlog_debug(
1205 "%s: Current copy of LSA %s is MAXAGE, but new has recent age, flooding/installing.",
1206 __PRETTY_FUNCTION__, old->name);
1207 ospf6_lsa_purge(old);
1208 ospf6_flood(from, new);
1209 ospf6_install_lsa(new);
1210 return;
1211 }
1212 /* For self-originated LSA, only trust
1213 * ourselves. Fall through and send
1214 * LS Update with our current copy.
1215 */
1216 if (is_debug)
1217 zlog_debug(
1218 "%s: Current copy of self-originated LSA %s is MAXAGE, but new has recent age, re-sending current one.",
1219 __PRETTY_FUNCTION__, old->name);
1220 }
1221
1222 /* MinLSArrival check as per RFC 2328 13 (8) */
1223 if (ospf6_lsa_check_min_arrival(old, from)) {
1224 ospf6_lsa_delete(new);
1225 return; /* examin next lsa */
1226 }
1227
1228 ospf6_lsdb_add(ospf6_lsa_copy(old),
1229 from->lsupdate_list);
1230 thread_add_event(master, ospf6_lsupdate_send_neighbor,
1231 from, 0, &from->thread_send_lsupdate);
1232
1233 ospf6_lsa_delete(new);
1234 return;
1235 }
1236 }
1237 }
1238
1239 DEFUN (debug_ospf6_flooding,
1240 debug_ospf6_flooding_cmd,
1241 "debug ospf6 flooding",
1242 DEBUG_STR
1243 OSPF6_STR
1244 "Debug OSPFv3 flooding function\n"
1245 )
1246 {
1247 OSPF6_DEBUG_FLOODING_ON();
1248 return CMD_SUCCESS;
1249 }
1250
1251 DEFUN (no_debug_ospf6_flooding,
1252 no_debug_ospf6_flooding_cmd,
1253 "no debug ospf6 flooding",
1254 NO_STR
1255 DEBUG_STR
1256 OSPF6_STR
1257 "Debug OSPFv3 flooding function\n"
1258 )
1259 {
1260 OSPF6_DEBUG_FLOODING_OFF();
1261 return CMD_SUCCESS;
1262 }
1263
1264 int config_write_ospf6_debug_flood(struct vty *vty)
1265 {
1266 if (IS_OSPF6_DEBUG_FLOODING)
1267 vty_out(vty, "debug ospf6 flooding\n");
1268 return 0;
1269 }
1270
1271 void install_element_ospf6_debug_flood(void)
1272 {
1273 install_element(ENABLE_NODE, &debug_ospf6_flooding_cmd);
1274 install_element(ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
1275 install_element(CONFIG_NODE, &debug_ospf6_flooding_cmd);
1276 install_element(CONFIG_NODE, &no_debug_ospf6_flooding_cmd);
1277 }