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