]>
Commit | Line | Data |
---|---|---|
48454375 | 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 | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the | |
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | * Boston, MA 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "log.h" | |
25 | #include "thread.h" | |
26 | #include "linklist.h" | |
27 | #include "vty.h" | |
1e05838a | 28 | #include "command.h" |
48454375 | 29 | |
30 | #include "ospf6d.h" | |
31 | #include "ospf6_proto.h" | |
32 | #include "ospf6_lsa.h" | |
33 | #include "ospf6_lsdb.h" | |
34 | #include "ospf6_message.h" | |
35 | #include "ospf6_route.h" | |
36 | #include "ospf6_spf.h" | |
37 | ||
38 | #include "ospf6_top.h" | |
39 | #include "ospf6_area.h" | |
40 | #include "ospf6_interface.h" | |
41 | #include "ospf6_neighbor.h" | |
42 | ||
6452df09 | 43 | #include "ospf6_flood.h" |
48454375 | 44 | |
1e05838a | 45 | unsigned char conf_debug_ospf6_flooding; |
46 | ||
6452df09 | 47 | struct ospf6_lsdb * |
48 | ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa) | |
48454375 | 49 | { |
6452df09 | 50 | struct ospf6_lsdb *lsdb = NULL; |
51 | switch (OSPF6_LSA_SCOPE (lsa->header->type)) | |
52 | { | |
53 | case OSPF6_SCOPE_LINKLOCAL: | |
54 | lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb; | |
55 | break; | |
56 | case OSPF6_SCOPE_AREA: | |
57 | lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb; | |
58 | break; | |
59 | case OSPF6_SCOPE_AS: | |
60 | lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb; | |
61 | break; | |
62 | default: | |
63 | assert (0); | |
64 | break; | |
48454375 | 65 | } |
6452df09 | 66 | return lsdb; |
48454375 | 67 | } |
68 | ||
69 | struct ospf6_lsdb * | |
6452df09 | 70 | ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa) |
48454375 | 71 | { |
6452df09 | 72 | struct ospf6_lsdb *lsdb_self = NULL; |
73 | switch (OSPF6_LSA_SCOPE (lsa->header->type)) | |
74 | { | |
75 | case OSPF6_SCOPE_LINKLOCAL: | |
76 | lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self; | |
77 | break; | |
78 | case OSPF6_SCOPE_AREA: | |
79 | lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self; | |
80 | break; | |
81 | case OSPF6_SCOPE_AS: | |
82 | lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self; | |
83 | break; | |
84 | default: | |
85 | assert (0); | |
86 | break; | |
87 | } | |
88 | return lsdb_self; | |
89 | } | |
90 | ||
91 | void | |
92 | ospf6_lsa_originate (struct ospf6_lsa *lsa) | |
93 | { | |
94 | struct ospf6_lsa *old; | |
95 | struct ospf6_lsdb *lsdb_self; | |
48454375 | 96 | |
6452df09 | 97 | /* find previous LSA */ |
98 | old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, | |
99 | lsa->header->adv_router, lsa->lsdb); | |
48454375 | 100 | |
6452df09 | 101 | /* if the new LSA does not differ from previous, |
102 | suppress this update of the LSA */ | |
103 | if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old)) | |
48454375 | 104 | { |
1e05838a | 105 | if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) |
c6487d61 | 106 | zlog_debug ("Suppress updating LSA: %s", lsa->name); |
6452df09 | 107 | ospf6_lsa_delete (lsa); |
108 | return; | |
48454375 | 109 | } |
110 | ||
6452df09 | 111 | /* store it in the LSDB for self-originated LSAs */ |
112 | lsdb_self = ospf6_get_scoped_lsdb_self (lsa); | |
113 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); | |
48454375 | 114 | |
6452df09 | 115 | lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, |
116 | LS_REFRESH_TIME); | |
3b4cd3a9 | 117 | |
1e05838a | 118 | if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) || |
119 | IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) | |
3b4cd3a9 | 120 | { |
c6487d61 | 121 | zlog_debug ("LSA Originate:"); |
6452df09 | 122 | ospf6_lsa_header_print (lsa); |
3b4cd3a9 | 123 | } |
124 | ||
6452df09 | 125 | if (old) |
126 | ospf6_flood_clear (old); | |
127 | ospf6_flood (NULL, lsa); | |
128 | ospf6_install_lsa (lsa); | |
129 | } | |
3b4cd3a9 | 130 | |
6452df09 | 131 | void |
132 | ospf6_lsa_originate_process (struct ospf6_lsa *lsa, | |
133 | struct ospf6 *process) | |
134 | { | |
135 | lsa->lsdb = process->lsdb; | |
136 | ospf6_lsa_originate (lsa); | |
3b4cd3a9 | 137 | } |
138 | ||
48454375 | 139 | void |
6452df09 | 140 | ospf6_lsa_originate_area (struct ospf6_lsa *lsa, |
141 | struct ospf6_area *oa) | |
48454375 | 142 | { |
6452df09 | 143 | lsa->lsdb = oa->lsdb; |
144 | ospf6_lsa_originate (lsa); | |
145 | } | |
146 | ||
147 | void | |
148 | ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, | |
149 | struct ospf6_interface *oi) | |
150 | { | |
151 | lsa->lsdb = oi->lsdb; | |
152 | ospf6_lsa_originate (lsa); | |
153 | } | |
48454375 | 154 | |
6452df09 | 155 | void |
156 | ospf6_lsa_purge (struct ospf6_lsa *lsa) | |
157 | { | |
158 | struct ospf6_lsa *self; | |
159 | struct ospf6_lsdb *lsdb_self; | |
48454375 | 160 | |
6452df09 | 161 | /* remove it from the LSDB for self-originated LSAs */ |
162 | lsdb_self = ospf6_get_scoped_lsdb_self (lsa); | |
163 | self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, | |
164 | lsa->header->adv_router, lsdb_self); | |
165 | if (self) | |
48454375 | 166 | { |
6452df09 | 167 | THREAD_OFF (self->expire); |
168 | THREAD_OFF (self->refresh); | |
169 | ospf6_lsdb_remove (self, lsdb_self); | |
48454375 | 170 | } |
171 | ||
6452df09 | 172 | ospf6_lsa_premature_aging (lsa); |
173 | } | |
48454375 | 174 | |
48454375 | 175 | |
6452df09 | 176 | void |
177 | ospf6_increment_retrans_count (struct ospf6_lsa *lsa) | |
178 | { | |
179 | /* The LSA must be the original one (see the description | |
180 | in ospf6_decrement_retrans_count () below) */ | |
181 | lsa->retrans_count++; | |
182 | } | |
48454375 | 183 | |
6452df09 | 184 | void |
185 | ospf6_decrement_retrans_count (struct ospf6_lsa *lsa) | |
186 | { | |
187 | struct ospf6_lsdb *lsdb; | |
188 | struct ospf6_lsa *orig; | |
189 | ||
190 | /* The LSA must be on the retrans-list of a neighbor. It means | |
191 | the "lsa" is a copied one, and we have to decrement the | |
1e05838a | 192 | retransmission count of the original one (instead of this "lsa"'s). |
6452df09 | 193 | In order to find the original LSA, first we have to find |
194 | appropriate LSDB that have the original LSA. */ | |
195 | lsdb = ospf6_get_scoped_lsdb (lsa); | |
196 | ||
197 | /* Find the original LSA of which the retrans_count should be decremented */ | |
198 | orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, | |
1e05838a | 199 | lsa->header->adv_router, lsdb); |
6452df09 | 200 | if (orig) |
6861b307 | 201 | { |
202 | orig->retrans_count--; | |
203 | assert (orig->retrans_count >= 0); | |
204 | } | |
48454375 | 205 | } |
206 | ||
207 | /* RFC2328 section 13.2 Installing LSAs in the database */ | |
208 | void | |
6452df09 | 209 | ospf6_install_lsa (struct ospf6_lsa *lsa) |
48454375 | 210 | { |
211 | struct ospf6_lsa *old; | |
3b68735f | 212 | struct timeval now; |
48454375 | 213 | |
1e05838a | 214 | if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) || |
215 | IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) | |
c6487d61 | 216 | zlog_debug ("Install LSA: %s", lsa->name); |
48454375 | 217 | |
218 | /* Remove the old instance from all neighbors' Link state | |
219 | retransmission list (RFC2328 13.2 last paragraph) */ | |
220 | old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, | |
6452df09 | 221 | lsa->header->adv_router, lsa->lsdb); |
48454375 | 222 | if (old) |
3b68735f | 223 | { |
224 | THREAD_OFF (old->expire); | |
225 | ospf6_flood_clear (old); | |
226 | } | |
227 | ||
86f72dcb | 228 | quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); |
ccb59b11 | 229 | if (! OSPF6_LSA_IS_MAXAGE (lsa)) |
3b68735f | 230 | lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, |
231 | MAXAGE + lsa->birth.tv_sec - now.tv_sec); | |
232 | else | |
233 | lsa->expire = NULL; | |
48454375 | 234 | |
235 | /* actually install */ | |
3b68735f | 236 | lsa->installed = now; |
6452df09 | 237 | ospf6_lsdb_add (lsa, lsa->lsdb); |
48454375 | 238 | |
239 | return; | |
240 | } | |
241 | ||
6452df09 | 242 | /* RFC2740 section 3.5.2. Sending Link State Update packets */ |
48454375 | 243 | /* RFC2328 section 13.3 Next step in the flooding procedure */ |
6ac29a51 | 244 | static void |
6452df09 | 245 | ospf6_flood_interface (struct ospf6_neighbor *from, |
246 | struct ospf6_lsa *lsa, struct ospf6_interface *oi) | |
48454375 | 247 | { |
1eb8ef25 | 248 | struct listnode *node, *nnode; |
48454375 | 249 | struct ospf6_neighbor *on; |
48454375 | 250 | struct ospf6_lsa *req; |
251 | int retrans_added = 0; | |
1e05838a | 252 | int is_debug = 0; |
48454375 | 253 | |
1e05838a | 254 | if (IS_OSPF6_DEBUG_FLOODING || |
255 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
256 | { | |
257 | is_debug++; | |
c6487d61 | 258 | zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); |
1e05838a | 259 | } |
48454375 | 260 | |
6452df09 | 261 | /* (1) For each neighbor */ |
1eb8ef25 | 262 | for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) |
48454375 | 263 | { |
1e05838a | 264 | if (is_debug) |
c6487d61 | 265 | zlog_debug ("To neighbor %s", on->name); |
48454375 | 266 | |
6452df09 | 267 | /* (a) if neighbor state < Exchange, examin next */ |
268 | if (on->state < OSPF6_NEIGHBOR_EXCHANGE) | |
269 | { | |
1e05838a | 270 | if (is_debug) |
c6487d61 | 271 | zlog_debug ("Neighbor state less than ExChange, next neighbor"); |
6452df09 | 272 | continue; |
48454375 | 273 | } |
48454375 | 274 | |
6452df09 | 275 | /* (b) if neighbor not yet Full, check request-list */ |
276 | if (on->state != OSPF6_NEIGHBOR_FULL) | |
48454375 | 277 | { |
1e05838a | 278 | if (is_debug) |
c6487d61 | 279 | zlog_debug ("Neighbor not yet Full"); |
48454375 | 280 | |
6452df09 | 281 | req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, |
282 | lsa->header->adv_router, on->request_list); | |
283 | if (req == NULL) | |
48454375 | 284 | { |
1e05838a | 285 | if (is_debug) |
c6487d61 | 286 | zlog_debug ("Not on request-list for this neighbor"); |
6452df09 | 287 | /* fall through */ |
288 | } | |
289 | else | |
290 | { | |
291 | /* If new LSA less recent, examin next neighbor */ | |
292 | if (ospf6_lsa_compare (lsa, req) > 0) | |
293 | { | |
1e05838a | 294 | if (is_debug) |
c6487d61 | 295 | zlog_debug ("Requesting is newer, next neighbor"); |
6452df09 | 296 | continue; |
297 | } | |
298 | ||
299 | /* If the same instance, delete from request-list and | |
300 | examin next neighbor */ | |
301 | if (ospf6_lsa_compare (lsa, req) == 0) | |
48454375 | 302 | { |
1e05838a | 303 | if (is_debug) |
c6487d61 | 304 | zlog_debug ("Requesting the same, remove it, next neighbor"); |
6452df09 | 305 | ospf6_lsdb_remove (req, on->request_list); |
306 | continue; | |
307 | } | |
308 | ||
309 | /* If the new LSA is more recent, delete from request-list */ | |
310 | if (ospf6_lsa_compare (lsa, req) < 0) | |
311 | { | |
1e05838a | 312 | if (is_debug) |
c6487d61 | 313 | zlog_debug ("Received is newer, remove requesting"); |
6452df09 | 314 | ospf6_lsdb_remove (req, on->request_list); |
315 | /* fall through */ | |
48454375 | 316 | } |
317 | } | |
6452df09 | 318 | } |
48454375 | 319 | |
6452df09 | 320 | /* (c) If the new LSA was received from this neighbor, |
321 | examin next neighbor */ | |
322 | if (from == on) | |
323 | { | |
1e05838a | 324 | if (is_debug) |
c6487d61 | 325 | zlog_debug ("Received is from the neighbor, next neighbor"); |
6452df09 | 326 | continue; |
48454375 | 327 | } |
328 | ||
6452df09 | 329 | /* (d) add retrans-list, schedule retransmission */ |
1e05838a | 330 | if (is_debug) |
c6487d61 | 331 | zlog_debug ("Add retrans-list of this neighbor"); |
6452df09 | 332 | ospf6_increment_retrans_count (lsa); |
333 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); | |
334 | if (on->thread_send_lsupdate == NULL) | |
335 | on->thread_send_lsupdate = | |
6639a04d | 336 | thread_add_timer (master, ospf6_lsupdate_send_neighbor, |
6452df09 | 337 | on, on->ospf6_if->rxmt_interval); |
338 | retrans_added++; | |
339 | } | |
340 | ||
341 | /* (2) examin next interface if not added to retrans-list */ | |
342 | if (retrans_added == 0) | |
343 | { | |
1e05838a | 344 | if (is_debug) |
c6487d61 | 345 | zlog_debug ("No retransmission scheduled, next interface"); |
6452df09 | 346 | return; |
347 | } | |
348 | ||
349 | /* (3) If the new LSA was received on this interface, | |
350 | and it was from DR or BDR, examin next interface */ | |
351 | if (from && from->ospf6_if == oi && | |
352 | (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) | |
353 | { | |
1e05838a | 354 | if (is_debug) |
c6487d61 | 355 | zlog_debug ("Received is from the I/F's DR or BDR, next interface"); |
6452df09 | 356 | return; |
357 | } | |
358 | ||
359 | /* (4) If the new LSA was received on this interface, | |
360 | and the interface state is BDR, examin next interface */ | |
361 | if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR) | |
362 | { | |
1e05838a | 363 | if (is_debug) |
c6487d61 | 364 | zlog_debug ("Received is from the I/F, itself BDR, next interface"); |
6452df09 | 365 | return; |
366 | } | |
367 | ||
368 | /* (5) flood the LSA out the interface. */ | |
1e05838a | 369 | if (is_debug) |
c6487d61 | 370 | zlog_debug ("Schedule flooding for the interface"); |
6452df09 | 371 | if (if_is_broadcast (oi->interface)) |
372 | { | |
373 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); | |
374 | if (oi->thread_send_lsupdate == NULL) | |
375 | oi->thread_send_lsupdate = | |
376 | thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); | |
377 | } | |
378 | else | |
379 | { | |
380 | /* reschedule retransmissions to all neighbors */ | |
1eb8ef25 | 381 | for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) |
6452df09 | 382 | { |
6452df09 | 383 | THREAD_OFF (on->thread_send_lsupdate); |
384 | on->thread_send_lsupdate = | |
385 | thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); | |
386 | } | |
387 | } | |
388 | } | |
389 | ||
6ac29a51 | 390 | static void |
6452df09 | 391 | ospf6_flood_area (struct ospf6_neighbor *from, |
392 | struct ospf6_lsa *lsa, struct ospf6_area *oa) | |
393 | { | |
1eb8ef25 | 394 | struct listnode *node, *nnode; |
6452df09 | 395 | struct ospf6_interface *oi; |
396 | ||
1eb8ef25 | 397 | for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) |
6452df09 | 398 | { |
6452df09 | 399 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && |
400 | oi != OSPF6_INTERFACE (lsa->lsdb->data)) | |
48454375 | 401 | continue; |
402 | ||
6452df09 | 403 | #if 0 |
404 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && | |
405 | ospf6_is_interface_virtual_link (oi)) | |
48454375 | 406 | continue; |
6452df09 | 407 | #endif/*0*/ |
408 | ||
409 | ospf6_flood_interface (from, lsa, oi); | |
410 | } | |
411 | } | |
412 | ||
6ac29a51 | 413 | static void |
6452df09 | 414 | ospf6_flood_process (struct ospf6_neighbor *from, |
415 | struct ospf6_lsa *lsa, struct ospf6 *process) | |
416 | { | |
1eb8ef25 | 417 | struct listnode *node, *nnode; |
6452df09 | 418 | struct ospf6_area *oa; |
48454375 | 419 | |
1eb8ef25 | 420 | for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) |
6452df09 | 421 | { |
6452df09 | 422 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && |
423 | oa != OSPF6_AREA (lsa->lsdb->data)) | |
424 | continue; | |
425 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && | |
426 | oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) | |
48454375 | 427 | continue; |
428 | ||
6452df09 | 429 | if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && |
430 | IS_AREA_STUB (oa)) | |
431 | continue; | |
432 | ||
433 | ospf6_flood_area (from, lsa, oa); | |
434 | } | |
435 | } | |
436 | ||
437 | void | |
438 | ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa) | |
439 | { | |
440 | ospf6_flood_process (from, lsa, ospf6); | |
441 | } | |
442 | ||
6ac29a51 | 443 | static void |
6452df09 | 444 | ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi) |
445 | { | |
1eb8ef25 | 446 | struct listnode *node, *nnode; |
6452df09 | 447 | struct ospf6_neighbor *on; |
448 | struct ospf6_lsa *rem; | |
449 | ||
1eb8ef25 | 450 | for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) |
6452df09 | 451 | { |
6452df09 | 452 | rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, |
453 | lsa->header->adv_router, on->retrans_list); | |
454 | if (rem && ! ospf6_lsa_compare (rem, lsa)) | |
48454375 | 455 | { |
1e05838a | 456 | if (IS_OSPF6_DEBUG_FLOODING || |
457 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
c6487d61 | 458 | zlog_debug ("Remove %s from retrans_list of %s", |
6452df09 | 459 | rem->name, on->name); |
460 | ospf6_decrement_retrans_count (rem); | |
461 | ospf6_lsdb_remove (rem, on->retrans_list); | |
48454375 | 462 | } |
463 | } | |
6452df09 | 464 | } |
465 | ||
6ac29a51 | 466 | static void |
6452df09 | 467 | ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa) |
468 | { | |
1eb8ef25 | 469 | struct listnode *node, *nnode; |
6452df09 | 470 | struct ospf6_interface *oi; |
471 | ||
1eb8ef25 | 472 | for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) |
6452df09 | 473 | { |
6452df09 | 474 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && |
475 | oi != OSPF6_INTERFACE (lsa->lsdb->data)) | |
476 | continue; | |
477 | ||
478 | #if 0 | |
479 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && | |
480 | ospf6_is_interface_virtual_link (oi)) | |
481 | continue; | |
482 | #endif/*0*/ | |
483 | ||
484 | ospf6_flood_clear_interface (lsa, oi); | |
485 | } | |
486 | } | |
487 | ||
6ac29a51 | 488 | static void |
6452df09 | 489 | ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process) |
490 | { | |
1eb8ef25 | 491 | struct listnode *node, *nnode; |
6452df09 | 492 | struct ospf6_area *oa; |
493 | ||
1eb8ef25 | 494 | for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) |
6452df09 | 495 | { |
6452df09 | 496 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && |
497 | oa != OSPF6_AREA (lsa->lsdb->data)) | |
498 | continue; | |
499 | if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && | |
500 | oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) | |
501 | continue; | |
502 | ||
503 | if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && | |
504 | IS_AREA_STUB (oa)) | |
505 | continue; | |
506 | ||
507 | ospf6_flood_clear_area (lsa, oa); | |
508 | } | |
509 | } | |
510 | ||
511 | void | |
512 | ospf6_flood_clear (struct ospf6_lsa *lsa) | |
513 | { | |
514 | ospf6_flood_clear_process (lsa, ospf6); | |
48454375 | 515 | } |
516 | ||
6452df09 | 517 | |
48454375 | 518 | /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */ |
519 | static void | |
520 | ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, | |
521 | struct ospf6_neighbor *from) | |
522 | { | |
523 | struct ospf6_interface *oi; | |
1e05838a | 524 | int is_debug = 0; |
525 | ||
526 | if (IS_OSPF6_DEBUG_FLOODING || | |
527 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
528 | is_debug++; | |
48454375 | 529 | |
530 | assert (from && from->ospf6_if); | |
531 | oi = from->ospf6_if; | |
532 | ||
533 | /* LSA has been flood back out receiving interface. | |
534 | No acknowledgement sent. */ | |
535 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) | |
536 | { | |
1e05838a | 537 | if (is_debug) |
c6487d61 | 538 | zlog_debug ("No acknowledgement (BDR & FloodBack)"); |
48454375 | 539 | return; |
540 | } | |
541 | ||
542 | /* LSA is more recent than database copy, but was not flooded | |
543 | back out receiving interface. Delayed acknowledgement sent | |
544 | if advertisement received from Designated Router, | |
545 | otherwide do nothing. */ | |
546 | if (ismore_recent < 0) | |
547 | { | |
48454375 | 548 | if (oi->drouter == from->router_id) |
549 | { | |
1e05838a | 550 | if (is_debug) |
c6487d61 | 551 | zlog_debug ("Delayed acknowledgement (BDR & MoreRecent & from DR)"); |
48454375 | 552 | /* Delayed acknowledgement */ |
48454375 | 553 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); |
554 | if (oi->thread_send_lsack == NULL) | |
555 | oi->thread_send_lsack = | |
556 | thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); | |
557 | } | |
558 | else | |
559 | { | |
1e05838a | 560 | if (is_debug) |
c6487d61 | 561 | zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)"); |
48454375 | 562 | } |
563 | return; | |
564 | } | |
565 | ||
566 | /* LSA is a duplicate, and was treated as an implied acknowledgement. | |
567 | Delayed acknowledgement sent if advertisement received from | |
568 | Designated Router, otherwise do nothing */ | |
569 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
570 | CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
571 | { | |
48454375 | 572 | if (oi->drouter == from->router_id) |
573 | { | |
1e05838a | 574 | if (is_debug) |
c6487d61 | 575 | zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); |
48454375 | 576 | /* Delayed acknowledgement */ |
48454375 | 577 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); |
578 | if (oi->thread_send_lsack == NULL) | |
579 | oi->thread_send_lsack = | |
580 | thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); | |
581 | } | |
582 | else | |
583 | { | |
1e05838a | 584 | if (is_debug) |
c6487d61 | 585 | zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); |
48454375 | 586 | } |
587 | return; | |
588 | } | |
589 | ||
590 | /* LSA is a duplicate, and was not treated as an implied acknowledgement. | |
591 | Direct acknowledgement sent */ | |
592 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
593 | ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
594 | { | |
1e05838a | 595 | if (is_debug) |
c6487d61 | 596 | zlog_debug ("Direct acknowledgement (BDR & Duplicate)"); |
48454375 | 597 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); |
598 | if (from->thread_send_lsack == NULL) | |
599 | from->thread_send_lsack = | |
600 | thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); | |
601 | return; | |
602 | } | |
603 | ||
604 | /* LSA's LS age is equal to Maxage, and there is no current instance | |
605 | of the LSA in the link state database, and none of router's | |
606 | neighbors are in states Exchange or Loading */ | |
607 | /* Direct acknowledgement sent, but this case is handled in | |
608 | early of ospf6_receive_lsa () */ | |
609 | } | |
610 | ||
611 | static void | |
612 | ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, | |
613 | struct ospf6_neighbor *from) | |
614 | { | |
615 | struct ospf6_interface *oi; | |
1e05838a | 616 | int is_debug = 0; |
617 | ||
618 | if (IS_OSPF6_DEBUG_FLOODING || | |
619 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
620 | is_debug++; | |
48454375 | 621 | |
622 | assert (from && from->ospf6_if); | |
623 | oi = from->ospf6_if; | |
624 | ||
625 | /* LSA has been flood back out receiving interface. | |
626 | No acknowledgement sent. */ | |
627 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) | |
628 | { | |
1e05838a | 629 | if (is_debug) |
c6487d61 | 630 | zlog_debug ("No acknowledgement (AllOther & FloodBack)"); |
48454375 | 631 | return; |
632 | } | |
633 | ||
634 | /* LSA is more recent than database copy, but was not flooded | |
635 | back out receiving interface. Delayed acknowledgement sent. */ | |
636 | if (ismore_recent < 0) | |
637 | { | |
1e05838a | 638 | if (is_debug) |
c6487d61 | 639 | zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)"); |
48454375 | 640 | /* Delayed acknowledgement */ |
48454375 | 641 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); |
642 | if (oi->thread_send_lsack == NULL) | |
643 | oi->thread_send_lsack = | |
644 | thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); | |
645 | return; | |
646 | } | |
647 | ||
648 | /* LSA is a duplicate, and was treated as an implied acknowledgement. | |
649 | No acknowledgement sent. */ | |
650 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
651 | CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
652 | { | |
1e05838a | 653 | if (is_debug) |
c6487d61 | 654 | zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)"); |
48454375 | 655 | return; |
656 | } | |
657 | ||
658 | /* LSA is a duplicate, and was not treated as an implied acknowledgement. | |
659 | Direct acknowledgement sent */ | |
660 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
661 | ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
662 | { | |
1e05838a | 663 | if (is_debug) |
c6487d61 | 664 | zlog_debug ("Direct acknowledgement (AllOther & Duplicate)"); |
48454375 | 665 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); |
666 | if (from->thread_send_lsack == NULL) | |
667 | from->thread_send_lsack = | |
668 | thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); | |
669 | return; | |
670 | } | |
671 | ||
672 | /* LSA's LS age is equal to Maxage, and there is no current instance | |
673 | of the LSA in the link state database, and none of router's | |
674 | neighbors are in states Exchange or Loading */ | |
675 | /* Direct acknowledgement sent, but this case is handled in | |
676 | early of ospf6_receive_lsa () */ | |
677 | } | |
678 | ||
6ac29a51 | 679 | static void |
48454375 | 680 | ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, |
681 | struct ospf6_neighbor *from) | |
682 | { | |
683 | struct ospf6_interface *oi; | |
684 | ||
685 | assert (from && from->ospf6_if); | |
686 | oi = from->ospf6_if; | |
687 | ||
688 | if (oi->state == OSPF6_INTERFACE_BDR) | |
689 | ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); | |
690 | else | |
691 | ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from); | |
692 | } | |
693 | ||
694 | /* RFC2328 section 13 (4): | |
695 | if MaxAge LSA and if we have no instance, and no neighbor | |
696 | is in states Exchange or Loading | |
697 | returns 1 if match this case, else returns 0 */ | |
698 | static int | |
6452df09 | 699 | ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) |
48454375 | 700 | { |
48454375 | 701 | struct ospf6_neighbor *on; |
6452df09 | 702 | struct ospf6_interface *oi; |
703 | struct ospf6_area *oa; | |
704 | struct ospf6 *process = NULL; | |
52dc7ee6 | 705 | struct listnode *i, *j, *k; |
48454375 | 706 | int count = 0; |
707 | ||
708 | if (! OSPF6_LSA_IS_MAXAGE (lsa)) | |
709 | return 0; | |
710 | ||
48454375 | 711 | if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, |
6452df09 | 712 | lsa->header->adv_router, lsa->lsdb)) |
48454375 | 713 | return 0; |
714 | ||
6452df09 | 715 | process = from->ospf6_if->area->ospf6; |
1eb8ef25 | 716 | |
717 | for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa)) | |
718 | for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) | |
719 | for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) | |
720 | if (on->state == OSPF6_NEIGHBOR_EXCHANGE || | |
721 | on->state == OSPF6_NEIGHBOR_LOADING) | |
722 | count++; | |
48454375 | 723 | |
48454375 | 724 | if (count == 0) |
725 | return 1; | |
48454375 | 726 | return 0; |
727 | } | |
728 | ||
729 | /* RFC2328 section 13 The Flooding Procedure */ | |
730 | void | |
6452df09 | 731 | ospf6_receive_lsa (struct ospf6_neighbor *from, |
732 | struct ospf6_lsa_header *lsa_header) | |
48454375 | 733 | { |
734 | struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; | |
735 | int ismore_recent; | |
1e05838a | 736 | int is_debug = 0; |
48454375 | 737 | |
738 | ismore_recent = 1; | |
6452df09 | 739 | assert (from); |
48454375 | 740 | |
741 | /* make lsa structure for received lsa */ | |
742 | new = ospf6_lsa_create (lsa_header); | |
743 | ||
1e05838a | 744 | if (IS_OSPF6_DEBUG_FLOODING || |
745 | IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) | |
48454375 | 746 | { |
1e05838a | 747 | is_debug++; |
c6487d61 | 748 | zlog_debug ("LSA Receive from %s", from->name); |
48454375 | 749 | ospf6_lsa_header_print (new); |
750 | } | |
751 | ||
6452df09 | 752 | /* (1) LSA Checksum */ |
d8a4e42b | 753 | if (! ospf6_lsa_checksum_valid (new->header)) |
48454375 | 754 | { |
1e05838a | 755 | if (is_debug) |
c6487d61 | 756 | zlog_debug ("Wrong LSA Checksum, discard"); |
48454375 | 757 | ospf6_lsa_delete (new); |
758 | return; | |
759 | } | |
760 | ||
6452df09 | 761 | /* (2) Examine the LSA's LS type. |
762 | RFC2470 3.5.1. Receiving Link State Update packets */ | |
763 | if (IS_AREA_STUB (from->ospf6_if->area) && | |
764 | OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) | |
48454375 | 765 | { |
1e05838a | 766 | if (is_debug) |
c6487d61 | 767 | zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); |
48454375 | 768 | ospf6_lsa_delete (new); |
769 | return; | |
770 | } | |
771 | ||
6452df09 | 772 | /* (3) LSA which have reserved scope is discarded |
773 | RFC2470 3.5.1. Receiving Link State Update packets */ | |
774 | /* Flooding scope check. LSAs with unknown scope are discarded here. | |
775 | Set appropriate LSDB for the LSA */ | |
776 | switch (OSPF6_LSA_SCOPE (new->header->type)) | |
777 | { | |
778 | case OSPF6_SCOPE_LINKLOCAL: | |
779 | new->lsdb = from->ospf6_if->lsdb; | |
780 | break; | |
781 | case OSPF6_SCOPE_AREA: | |
782 | new->lsdb = from->ospf6_if->area->lsdb; | |
783 | break; | |
784 | case OSPF6_SCOPE_AS: | |
785 | new->lsdb = from->ospf6_if->area->ospf6->lsdb; | |
786 | break; | |
787 | default: | |
1e05838a | 788 | if (is_debug) |
c6487d61 | 789 | zlog_debug ("LSA has reserved scope, discard"); |
48454375 | 790 | ospf6_lsa_delete (new); |
791 | return; | |
792 | } | |
793 | ||
794 | /* (4) if MaxAge LSA and if we have no instance, and no neighbor | |
795 | is in states Exchange or Loading */ | |
796 | if (ospf6_is_maxage_lsa_drop (new, from)) | |
797 | { | |
798 | /* log */ | |
1e05838a | 799 | if (is_debug) |
c6487d61 | 800 | zlog_debug ("Drop MaxAge LSA with direct acknowledgement."); |
48454375 | 801 | |
802 | /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ | |
6452df09 | 803 | ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); |
48454375 | 804 | if (from->thread_send_lsack == NULL) |
805 | from->thread_send_lsack = | |
806 | thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); | |
807 | ||
808 | /* b) Discard */ | |
6452df09 | 809 | ospf6_lsa_delete (new); |
48454375 | 810 | return; |
811 | } | |
812 | ||
813 | /* (5) */ | |
814 | /* lookup the same database copy in lsdb */ | |
48454375 | 815 | old = ospf6_lsdb_lookup (new->header->type, new->header->id, |
6452df09 | 816 | new->header->adv_router, new->lsdb); |
48454375 | 817 | if (old) |
818 | { | |
819 | ismore_recent = ospf6_lsa_compare (new, old); | |
820 | if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) | |
821 | { | |
1e05838a | 822 | if (is_debug) |
c6487d61 | 823 | zlog_debug ("Received is duplicated LSA"); |
48454375 | 824 | SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); |
825 | } | |
826 | } | |
827 | ||
828 | /* if no database copy or received is more recent */ | |
829 | if (old == NULL || ismore_recent < 0) | |
830 | { | |
831 | /* in case we have no database copy */ | |
832 | ismore_recent = -1; | |
833 | ||
834 | /* (a) MinLSArrival check */ | |
835 | if (old) | |
836 | { | |
837 | struct timeval now, res; | |
86f72dcb | 838 | quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); |
48454375 | 839 | timersub (&now, &old->installed, &res); |
840 | if (res.tv_sec < MIN_LS_ARRIVAL) | |
841 | { | |
1e05838a | 842 | if (is_debug) |
c6487d61 | 843 | zlog_debug ("LSA can't be updated within MinLSArrival, discard"); |
48454375 | 844 | ospf6_lsa_delete (new); |
845 | return; /* examin next lsa */ | |
846 | } | |
847 | } | |
848 | ||
86f72dcb | 849 | quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received); |
ccb59b11 | 850 | |
1e05838a | 851 | if (is_debug) |
c6487d61 | 852 | zlog_debug ("Flood, Install, Possibly acknowledge the received LSA"); |
6452df09 | 853 | |
48454375 | 854 | /* (b) immediately flood and (c) remove from all retrans-list */ |
ccb59b11 | 855 | /* Prevent self-originated LSA to be flooded. this is to make |
856 | reoriginated instance of the LSA not to be rejected by other routers | |
857 | due to MinLSArrival. */ | |
858 | if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) | |
859 | ospf6_flood (from, new); | |
6452df09 | 860 | |
861 | /* (c) Remove the current database copy from all neighbors' Link | |
862 | state retransmission lists. */ | |
863 | /* XXX, flood_clear ? */ | |
48454375 | 864 | |
865 | /* (d), installing lsdb, which may cause routing | |
866 | table calculation (replacing database copy) */ | |
6452df09 | 867 | ospf6_install_lsa (new); |
48454375 | 868 | |
869 | /* (e) possibly acknowledge */ | |
870 | ospf6_acknowledge_lsa (new, ismore_recent, from); | |
871 | ||
6452df09 | 872 | /* (f) Self Originated LSA, section 13.4 */ |
873 | if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) | |
48454375 | 874 | { |
6452df09 | 875 | /* Self-originated LSA (newer than ours) is received from |
876 | another router. We have to make a new instance of the LSA | |
48454375 | 877 | or have to flush this LSA. */ |
1e05838a | 878 | if (is_debug) |
6452df09 | 879 | { |
c6487d61 | 880 | zlog_debug ("Newer instance of the self-originated LSA"); |
881 | zlog_debug ("Schedule reorigination"); | |
6452df09 | 882 | } |
883 | new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0); | |
48454375 | 884 | } |
6452df09 | 885 | |
48454375 | 886 | return; |
887 | } | |
888 | ||
889 | /* (6) if there is instance on sending neighbor's request list */ | |
890 | if (ospf6_lsdb_lookup (new->header->type, new->header->id, | |
891 | new->header->adv_router, from->request_list)) | |
892 | { | |
893 | /* if no database copy, should go above state (5) */ | |
894 | assert (old); | |
895 | ||
1e05838a | 896 | if (is_debug) |
6452df09 | 897 | { |
c6487d61 | 898 | zlog_debug ("Received is not newer, on the neighbor's request-list"); |
899 | zlog_debug ("BadLSReq, discard the received LSA"); | |
6452df09 | 900 | } |
48454375 | 901 | |
902 | /* BadLSReq */ | |
903 | thread_add_event (master, bad_lsreq, from, 0); | |
904 | ||
905 | ospf6_lsa_delete (new); | |
906 | return; | |
907 | } | |
908 | ||
909 | /* (7) if neither one is more recent */ | |
910 | if (ismore_recent == 0) | |
911 | { | |
1e05838a | 912 | if (is_debug) |
c6487d61 | 913 | zlog_debug ("The same instance as database copy (neither recent)"); |
48454375 | 914 | |
915 | /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ | |
916 | rem = ospf6_lsdb_lookup (new->header->type, new->header->id, | |
917 | new->header->adv_router, from->retrans_list); | |
918 | if (rem) | |
919 | { | |
1e05838a | 920 | if (is_debug) |
6452df09 | 921 | { |
c6487d61 | 922 | zlog_debug ("It is on the neighbor's retrans-list."); |
923 | zlog_debug ("Treat as an Implied acknowledgement"); | |
6452df09 | 924 | } |
48454375 | 925 | SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); |
6452df09 | 926 | ospf6_decrement_retrans_count (rem); |
48454375 | 927 | ospf6_lsdb_remove (rem, from->retrans_list); |
928 | } | |
929 | ||
1e05838a | 930 | if (is_debug) |
c6487d61 | 931 | zlog_debug ("Possibly acknowledge and then discard"); |
6452df09 | 932 | |
48454375 | 933 | /* (b) possibly acknowledge */ |
934 | ospf6_acknowledge_lsa (new, ismore_recent, from); | |
935 | ||
936 | ospf6_lsa_delete (new); | |
937 | return; | |
938 | } | |
939 | ||
940 | /* (8) previous database copy is more recent */ | |
941 | { | |
942 | assert (old); | |
943 | ||
944 | /* If database copy is in 'Seqnumber Wrapping', | |
945 | simply discard the received LSA */ | |
946 | if (OSPF6_LSA_IS_MAXAGE (old) && | |
947 | old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER)) | |
948 | { | |
1e05838a | 949 | if (is_debug) |
6452df09 | 950 | { |
c6487d61 | 951 | zlog_debug ("The LSA is in Seqnumber Wrapping"); |
952 | zlog_debug ("MaxAge & MaxSeqNum, discard"); | |
6452df09 | 953 | } |
48454375 | 954 | ospf6_lsa_delete (new); |
955 | return; | |
956 | } | |
957 | ||
958 | /* Otherwise, Send database copy of this LSA to this neighbor */ | |
959 | { | |
1e05838a | 960 | if (is_debug) |
6452df09 | 961 | { |
c6487d61 | 962 | zlog_debug ("Database copy is more recent."); |
963 | zlog_debug ("Send back directly and then discard"); | |
6452df09 | 964 | } |
48454375 | 965 | |
966 | /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ | |
967 | ||
48454375 | 968 | ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); |
969 | if (from->thread_send_lsupdate == NULL) | |
970 | from->thread_send_lsupdate = | |
971 | thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0); | |
972 | ospf6_lsa_delete (new); | |
973 | return; | |
974 | } | |
975 | return; | |
976 | } | |
977 | } | |
978 | ||
979 | ||
1e05838a | 980 | DEFUN (debug_ospf6_flooding, |
981 | debug_ospf6_flooding_cmd, | |
982 | "debug ospf6 flooding", | |
983 | DEBUG_STR | |
984 | OSPF6_STR | |
985 | "Debug OSPFv3 flooding function\n" | |
986 | ) | |
987 | { | |
988 | OSPF6_DEBUG_FLOODING_ON (); | |
989 | return CMD_SUCCESS; | |
990 | } | |
991 | ||
992 | DEFUN (no_debug_ospf6_flooding, | |
993 | no_debug_ospf6_flooding_cmd, | |
994 | "no debug ospf6 flooding", | |
995 | NO_STR | |
996 | DEBUG_STR | |
997 | OSPF6_STR | |
998 | "Debug OSPFv3 flooding function\n" | |
999 | ) | |
1000 | { | |
1001 | OSPF6_DEBUG_FLOODING_OFF (); | |
1002 | return CMD_SUCCESS; | |
1003 | } | |
1004 | ||
1005 | int | |
1006 | config_write_ospf6_debug_flood (struct vty *vty) | |
1007 | { | |
1008 | if (IS_OSPF6_DEBUG_FLOODING) | |
1009 | vty_out (vty, "debug ospf6 flooding%s", VNL); | |
1010 | return 0; | |
1011 | } | |
1012 | ||
1013 | void | |
6ac29a51 | 1014 | install_element_ospf6_debug_flood (void) |
1e05838a | 1015 | { |
1016 | install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd); | |
1017 | install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd); | |
1018 | install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); | |
1019 | install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd); | |
1020 | } | |
1021 | ||
1022 | ||
1023 | ||
1024 | ||
48454375 | 1025 |