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