]>
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 | * | |
896014f4 DL |
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 | |
48454375 | 19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "log.h" | |
24 | #include "thread.h" | |
25 | #include "linklist.h" | |
26 | #include "vty.h" | |
1e05838a | 27 | #include "command.h" |
48454375 | 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 | ||
6452df09 | 42 | #include "ospf6_flood.h" |
48454375 | 43 | |
1e05838a | 44 | unsigned char conf_debug_ospf6_flooding; |
45 | ||
6452df09 | 46 | struct ospf6_lsdb * |
47 | ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa) | |
48454375 | 48 | { |
6452df09 | 49 | struct ospf6_lsdb *lsdb = NULL; |
50 | switch (OSPF6_LSA_SCOPE (lsa->header->type)) | |
51 | { | |
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; | |
48454375 | 64 | } |
6452df09 | 65 | return lsdb; |
48454375 | 66 | } |
67 | ||
68 | struct ospf6_lsdb * | |
6452df09 | 69 | ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa) |
48454375 | 70 | { |
6452df09 | 71 | struct ospf6_lsdb *lsdb_self = NULL; |
72 | switch (OSPF6_LSA_SCOPE (lsa->header->type)) | |
73 | { | |
74 | case OSPF6_SCOPE_LINKLOCAL: | |
75 | lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self; | |
76 | break; | |
77 | case OSPF6_SCOPE_AREA: | |
78 | lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self; | |
79 | break; | |
80 | case OSPF6_SCOPE_AS: | |
81 | lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self; | |
82 | break; | |
83 | default: | |
84 | assert (0); | |
85 | break; | |
86 | } | |
87 | return lsdb_self; | |
88 | } | |
89 | ||
90 | void | |
91 | ospf6_lsa_originate (struct ospf6_lsa *lsa) | |
92 | { | |
93 | struct ospf6_lsa *old; | |
94 | struct ospf6_lsdb *lsdb_self; | |
48454375 | 95 | |
6452df09 | 96 | /* find previous LSA */ |
97 | old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, | |
98 | lsa->header->adv_router, lsa->lsdb); | |
48454375 | 99 | |
6452df09 | 100 | /* if the new LSA does not differ from previous, |
101 | suppress this update of the LSA */ | |
102 | if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old)) | |
48454375 | 103 | { |
1e05838a | 104 | if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) |
c6487d61 | 105 | zlog_debug ("Suppress updating LSA: %s", lsa->name); |
6452df09 | 106 | ospf6_lsa_delete (lsa); |
107 | return; | |
48454375 | 108 | } |
109 | ||
6452df09 | 110 | /* store it in the LSDB for self-originated LSAs */ |
111 | lsdb_self = ospf6_get_scoped_lsdb_self (lsa); | |
112 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); | |
48454375 | 113 | |
66e78ae6 QY |
114 | lsa->refresh = NULL; |
115 | thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME, | |
116 | &lsa->refresh); | |
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); |
66e78ae6 QY |
228 | if (! OSPF6_LSA_IS_MAXAGE (lsa)) { |
229 | lsa->expire = NULL; | |
230 | thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, | |
231 | &lsa->expire); | |
232 | } | |
3b68735f | 233 | else |
234 | lsa->expire = NULL; | |
48454375 | 235 | |
3b220289 DD |
236 | if (OSPF6_LSA_IS_SEQWRAP(lsa) && |
237 | ! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) && | |
238 | lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) | |
239 | { | |
240 | if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) | |
241 | zlog_debug("lsa install wrapping: sequence 0x%x", | |
242 | ntohl(lsa->header->seqnum)); | |
243 | SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); | |
244 | /* in lieu of premature_aging, since we do not want to recreate this lsa | |
245 | * and/or mess with timers etc, we just want to wrap the sequence number | |
246 | * and reflood the lsa before continuing. | |
247 | * NOTE: Flood needs to be called right after this function call, by the | |
248 | * caller | |
249 | */ | |
250 | lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER); | |
251 | lsa->header->age = htons (OSPF_LSA_MAXAGE); | |
252 | ospf6_lsa_checksum (lsa->header); | |
253 | } | |
254 | ||
48454375 | 255 | /* actually install */ |
3b68735f | 256 | lsa->installed = now; |
6452df09 | 257 | ospf6_lsdb_add (lsa, lsa->lsdb); |
48454375 | 258 | |
259 | return; | |
260 | } | |
261 | ||
6452df09 | 262 | /* RFC2740 section 3.5.2. Sending Link State Update packets */ |
48454375 | 263 | /* RFC2328 section 13.3 Next step in the flooding procedure */ |
6ac29a51 | 264 | static void |
6452df09 | 265 | ospf6_flood_interface (struct ospf6_neighbor *from, |
266 | struct ospf6_lsa *lsa, struct ospf6_interface *oi) | |
48454375 | 267 | { |
1eb8ef25 | 268 | struct listnode *node, *nnode; |
48454375 | 269 | struct ospf6_neighbor *on; |
48454375 | 270 | struct ospf6_lsa *req; |
271 | int retrans_added = 0; | |
1e05838a | 272 | int is_debug = 0; |
48454375 | 273 | |
1e05838a | 274 | if (IS_OSPF6_DEBUG_FLOODING || |
275 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
276 | { | |
277 | is_debug++; | |
c6487d61 | 278 | zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); |
1e05838a | 279 | } |
48454375 | 280 | |
6452df09 | 281 | /* (1) For each neighbor */ |
1eb8ef25 | 282 | for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) |
48454375 | 283 | { |
1e05838a | 284 | if (is_debug) |
c6487d61 | 285 | zlog_debug ("To neighbor %s", on->name); |
48454375 | 286 | |
6452df09 | 287 | /* (a) if neighbor state < Exchange, examin next */ |
288 | if (on->state < OSPF6_NEIGHBOR_EXCHANGE) | |
289 | { | |
1e05838a | 290 | if (is_debug) |
c6487d61 | 291 | zlog_debug ("Neighbor state less than ExChange, next neighbor"); |
6452df09 | 292 | continue; |
48454375 | 293 | } |
48454375 | 294 | |
6452df09 | 295 | /* (b) if neighbor not yet Full, check request-list */ |
296 | if (on->state != OSPF6_NEIGHBOR_FULL) | |
48454375 | 297 | { |
1e05838a | 298 | if (is_debug) |
c6487d61 | 299 | zlog_debug ("Neighbor not yet Full"); |
48454375 | 300 | |
6452df09 | 301 | req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, |
302 | lsa->header->adv_router, on->request_list); | |
303 | if (req == NULL) | |
48454375 | 304 | { |
1e05838a | 305 | if (is_debug) |
c6487d61 | 306 | zlog_debug ("Not on request-list for this neighbor"); |
6452df09 | 307 | /* fall through */ |
308 | } | |
309 | else | |
310 | { | |
311 | /* If new LSA less recent, examin next neighbor */ | |
312 | if (ospf6_lsa_compare (lsa, req) > 0) | |
313 | { | |
1e05838a | 314 | if (is_debug) |
eb82e9ee | 315 | zlog_debug ("Requesting is older, next neighbor"); |
6452df09 | 316 | continue; |
317 | } | |
318 | ||
319 | /* If the same instance, delete from request-list and | |
320 | examin next neighbor */ | |
321 | if (ospf6_lsa_compare (lsa, req) == 0) | |
48454375 | 322 | { |
eb82e9ee DD |
323 | if (is_debug) |
324 | zlog_debug ("Requesting the same, remove it, next neighbor"); | |
325 | if (req == on->last_ls_req) | |
326 | { | |
327 | ospf6_lsa_unlock (req); | |
328 | on->last_ls_req = NULL; | |
329 | } | |
6452df09 | 330 | ospf6_lsdb_remove (req, on->request_list); |
eb82e9ee | 331 | ospf6_check_nbr_loading (on); |
6452df09 | 332 | continue; |
333 | } | |
334 | ||
335 | /* If the new LSA is more recent, delete from request-list */ | |
336 | if (ospf6_lsa_compare (lsa, req) < 0) | |
337 | { | |
eb82e9ee DD |
338 | if (is_debug) |
339 | zlog_debug ("Received is newer, remove requesting"); | |
340 | if (req == on->last_ls_req) | |
341 | { | |
342 | ospf6_lsa_unlock (req); | |
343 | on->last_ls_req = NULL; | |
344 | } | |
6452df09 | 345 | ospf6_lsdb_remove (req, on->request_list); |
eb82e9ee | 346 | ospf6_check_nbr_loading (on); |
6452df09 | 347 | /* fall through */ |
48454375 | 348 | } |
349 | } | |
6452df09 | 350 | } |
48454375 | 351 | |
6452df09 | 352 | /* (c) If the new LSA was received from this neighbor, |
353 | examin next neighbor */ | |
354 | if (from == on) | |
355 | { | |
1e05838a | 356 | if (is_debug) |
c6487d61 | 357 | zlog_debug ("Received is from the neighbor, next neighbor"); |
6452df09 | 358 | continue; |
48454375 | 359 | } |
360 | ||
6452df09 | 361 | /* (d) add retrans-list, schedule retransmission */ |
1e05838a | 362 | if (is_debug) |
c6487d61 | 363 | zlog_debug ("Add retrans-list of this neighbor"); |
6452df09 | 364 | ospf6_increment_retrans_count (lsa); |
365 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); | |
66e78ae6 QY |
366 | thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval, |
367 | &on->thread_send_lsupdate); | |
6452df09 | 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); | |
66e78ae6 QY |
409 | thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, |
410 | &oi->thread_send_lsupdate); | |
6452df09 | 411 | } |
412 | else | |
413 | { | |
414 | /* reschedule retransmissions to all neighbors */ | |
1eb8ef25 | 415 | for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) |
6452df09 | 416 | { |
6452df09 | 417 | THREAD_OFF (on->thread_send_lsupdate); |
66e78ae6 QY |
418 | on->thread_send_lsupdate = NULL; |
419 | thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, | |
420 | &on->thread_send_lsupdate); | |
6452df09 | 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); |
66e78ae6 QY |
580 | thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, |
581 | &oi->thread_send_lsack); | |
48454375 | 582 | } |
583 | else | |
584 | { | |
1e05838a | 585 | if (is_debug) |
c6487d61 | 586 | zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)"); |
48454375 | 587 | } |
588 | return; | |
589 | } | |
590 | ||
591 | /* LSA is a duplicate, and was treated as an implied acknowledgement. | |
592 | Delayed acknowledgement sent if advertisement received from | |
593 | Designated Router, otherwise do nothing */ | |
594 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
595 | CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
596 | { | |
48454375 | 597 | if (oi->drouter == from->router_id) |
598 | { | |
1e05838a | 599 | if (is_debug) |
c6487d61 | 600 | zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); |
48454375 | 601 | /* Delayed acknowledgement */ |
48454375 | 602 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); |
66e78ae6 QY |
603 | thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, |
604 | &oi->thread_send_lsack); | |
48454375 | 605 | } |
606 | else | |
607 | { | |
1e05838a | 608 | if (is_debug) |
c6487d61 | 609 | zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); |
48454375 | 610 | } |
611 | return; | |
612 | } | |
613 | ||
614 | /* LSA is a duplicate, and was not treated as an implied acknowledgement. | |
615 | Direct acknowledgement sent */ | |
616 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
617 | ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
618 | { | |
1e05838a | 619 | if (is_debug) |
c6487d61 | 620 | zlog_debug ("Direct acknowledgement (BDR & Duplicate)"); |
48454375 | 621 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); |
66e78ae6 QY |
622 | thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, |
623 | &from->thread_send_lsack); | |
48454375 | 624 | return; |
625 | } | |
626 | ||
627 | /* LSA's LS age is equal to Maxage, and there is no current instance | |
628 | of the LSA in the link state database, and none of router's | |
629 | neighbors are in states Exchange or Loading */ | |
630 | /* Direct acknowledgement sent, but this case is handled in | |
631 | early of ospf6_receive_lsa () */ | |
632 | } | |
633 | ||
634 | static void | |
635 | ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, | |
636 | struct ospf6_neighbor *from) | |
637 | { | |
638 | struct ospf6_interface *oi; | |
1e05838a | 639 | int is_debug = 0; |
640 | ||
641 | if (IS_OSPF6_DEBUG_FLOODING || | |
642 | IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) | |
643 | is_debug++; | |
48454375 | 644 | |
645 | assert (from && from->ospf6_if); | |
646 | oi = from->ospf6_if; | |
647 | ||
648 | /* LSA has been flood back out receiving interface. | |
649 | No acknowledgement sent. */ | |
650 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) | |
651 | { | |
1e05838a | 652 | if (is_debug) |
c6487d61 | 653 | zlog_debug ("No acknowledgement (AllOther & FloodBack)"); |
48454375 | 654 | return; |
655 | } | |
656 | ||
657 | /* LSA is more recent than database copy, but was not flooded | |
658 | back out receiving interface. Delayed acknowledgement sent. */ | |
659 | if (ismore_recent < 0) | |
660 | { | |
1e05838a | 661 | if (is_debug) |
c6487d61 | 662 | zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)"); |
48454375 | 663 | /* Delayed acknowledgement */ |
48454375 | 664 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); |
66e78ae6 QY |
665 | thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, |
666 | &oi->thread_send_lsack); | |
48454375 | 667 | return; |
668 | } | |
669 | ||
670 | /* LSA is a duplicate, and was treated as an implied acknowledgement. | |
671 | No acknowledgement sent. */ | |
672 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
673 | CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
674 | { | |
1e05838a | 675 | if (is_debug) |
c6487d61 | 676 | zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)"); |
48454375 | 677 | return; |
678 | } | |
679 | ||
680 | /* LSA is a duplicate, and was not treated as an implied acknowledgement. | |
681 | Direct acknowledgement sent */ | |
682 | if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && | |
683 | ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) | |
684 | { | |
1e05838a | 685 | if (is_debug) |
c6487d61 | 686 | zlog_debug ("Direct acknowledgement (AllOther & Duplicate)"); |
48454375 | 687 | ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); |
66e78ae6 QY |
688 | thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, |
689 | &from->thread_send_lsack); | |
48454375 | 690 | return; |
691 | } | |
692 | ||
693 | /* LSA's LS age is equal to Maxage, and there is no current instance | |
694 | of the LSA in the link state database, and none of router's | |
695 | neighbors are in states Exchange or Loading */ | |
696 | /* Direct acknowledgement sent, but this case is handled in | |
697 | early of ospf6_receive_lsa () */ | |
698 | } | |
699 | ||
6ac29a51 | 700 | static void |
48454375 | 701 | ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, |
702 | struct ospf6_neighbor *from) | |
703 | { | |
704 | struct ospf6_interface *oi; | |
705 | ||
706 | assert (from && from->ospf6_if); | |
707 | oi = from->ospf6_if; | |
708 | ||
709 | if (oi->state == OSPF6_INTERFACE_BDR) | |
710 | ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); | |
711 | else | |
712 | ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from); | |
713 | } | |
714 | ||
715 | /* RFC2328 section 13 (4): | |
716 | if MaxAge LSA and if we have no instance, and no neighbor | |
717 | is in states Exchange or Loading | |
718 | returns 1 if match this case, else returns 0 */ | |
719 | static int | |
6452df09 | 720 | ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) |
48454375 | 721 | { |
48454375 | 722 | struct ospf6_neighbor *on; |
6452df09 | 723 | struct ospf6_interface *oi; |
724 | struct ospf6_area *oa; | |
725 | struct ospf6 *process = NULL; | |
52dc7ee6 | 726 | struct listnode *i, *j, *k; |
48454375 | 727 | int count = 0; |
728 | ||
729 | if (! OSPF6_LSA_IS_MAXAGE (lsa)) | |
730 | return 0; | |
731 | ||
48454375 | 732 | if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, |
6452df09 | 733 | lsa->header->adv_router, lsa->lsdb)) |
48454375 | 734 | return 0; |
735 | ||
6452df09 | 736 | process = from->ospf6_if->area->ospf6; |
1eb8ef25 | 737 | |
738 | for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa)) | |
739 | for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) | |
740 | for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) | |
741 | if (on->state == OSPF6_NEIGHBOR_EXCHANGE || | |
742 | on->state == OSPF6_NEIGHBOR_LOADING) | |
743 | count++; | |
48454375 | 744 | |
48454375 | 745 | if (count == 0) |
746 | return 1; | |
48454375 | 747 | return 0; |
748 | } | |
749 | ||
750 | /* RFC2328 section 13 The Flooding Procedure */ | |
751 | void | |
6452df09 | 752 | ospf6_receive_lsa (struct ospf6_neighbor *from, |
753 | struct ospf6_lsa_header *lsa_header) | |
48454375 | 754 | { |
755 | struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; | |
756 | int ismore_recent; | |
1e05838a | 757 | int is_debug = 0; |
ed2eb093 | 758 | unsigned int time_delta_ms; |
48454375 | 759 | |
760 | ismore_recent = 1; | |
6452df09 | 761 | assert (from); |
48454375 | 762 | |
763 | /* make lsa structure for received lsa */ | |
764 | new = ospf6_lsa_create (lsa_header); | |
765 | ||
1e05838a | 766 | if (IS_OSPF6_DEBUG_FLOODING || |
767 | IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) | |
48454375 | 768 | { |
1e05838a | 769 | is_debug++; |
c6487d61 | 770 | zlog_debug ("LSA Receive from %s", from->name); |
48454375 | 771 | ospf6_lsa_header_print (new); |
772 | } | |
773 | ||
6452df09 | 774 | /* (1) LSA Checksum */ |
d8a4e42b | 775 | if (! ospf6_lsa_checksum_valid (new->header)) |
48454375 | 776 | { |
1e05838a | 777 | if (is_debug) |
c6487d61 | 778 | zlog_debug ("Wrong LSA Checksum, discard"); |
48454375 | 779 | ospf6_lsa_delete (new); |
780 | return; | |
781 | } | |
782 | ||
6452df09 | 783 | /* (2) Examine the LSA's LS type. |
784 | RFC2470 3.5.1. Receiving Link State Update packets */ | |
785 | if (IS_AREA_STUB (from->ospf6_if->area) && | |
786 | OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) | |
48454375 | 787 | { |
1e05838a | 788 | if (is_debug) |
c6487d61 | 789 | zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); |
48454375 | 790 | ospf6_lsa_delete (new); |
791 | return; | |
792 | } | |
793 | ||
6452df09 | 794 | /* (3) LSA which have reserved scope is discarded |
795 | RFC2470 3.5.1. Receiving Link State Update packets */ | |
796 | /* Flooding scope check. LSAs with unknown scope are discarded here. | |
797 | Set appropriate LSDB for the LSA */ | |
798 | switch (OSPF6_LSA_SCOPE (new->header->type)) | |
799 | { | |
800 | case OSPF6_SCOPE_LINKLOCAL: | |
801 | new->lsdb = from->ospf6_if->lsdb; | |
802 | break; | |
803 | case OSPF6_SCOPE_AREA: | |
804 | new->lsdb = from->ospf6_if->area->lsdb; | |
805 | break; | |
806 | case OSPF6_SCOPE_AS: | |
807 | new->lsdb = from->ospf6_if->area->ospf6->lsdb; | |
808 | break; | |
809 | default: | |
1e05838a | 810 | if (is_debug) |
c6487d61 | 811 | zlog_debug ("LSA has reserved scope, discard"); |
48454375 | 812 | ospf6_lsa_delete (new); |
813 | return; | |
814 | } | |
815 | ||
816 | /* (4) if MaxAge LSA and if we have no instance, and no neighbor | |
817 | is in states Exchange or Loading */ | |
818 | if (ospf6_is_maxage_lsa_drop (new, from)) | |
819 | { | |
820 | /* log */ | |
1e05838a | 821 | if (is_debug) |
eb82e9ee | 822 | zlog_debug ("Drop MaxAge LSA with direct acknowledgement."); |
48454375 | 823 | |
824 | /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ | |
6452df09 | 825 | ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); |
66e78ae6 QY |
826 | thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, |
827 | &from->thread_send_lsack); | |
48454375 | 828 | |
829 | /* b) Discard */ | |
6452df09 | 830 | ospf6_lsa_delete (new); |
48454375 | 831 | return; |
832 | } | |
833 | ||
834 | /* (5) */ | |
835 | /* lookup the same database copy in lsdb */ | |
48454375 | 836 | old = ospf6_lsdb_lookup (new->header->type, new->header->id, |
6452df09 | 837 | new->header->adv_router, new->lsdb); |
48454375 | 838 | if (old) |
839 | { | |
840 | ismore_recent = ospf6_lsa_compare (new, old); | |
841 | if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) | |
842 | { | |
1e05838a | 843 | if (is_debug) |
c6487d61 | 844 | zlog_debug ("Received is duplicated LSA"); |
48454375 | 845 | SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); |
846 | } | |
847 | } | |
848 | ||
849 | /* if no database copy or received is more recent */ | |
850 | if (old == NULL || ismore_recent < 0) | |
851 | { | |
852 | /* in case we have no database copy */ | |
853 | ismore_recent = -1; | |
854 | ||
855 | /* (a) MinLSArrival check */ | |
856 | if (old) | |
857 | { | |
858 | struct timeval now, res; | |
cf672a86 | 859 | monotime(&now); |
48454375 | 860 | timersub (&now, &old->installed, &res); |
b6927875 DS |
861 | time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec/1000); |
862 | if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) | |
48454375 | 863 | { |
1e05838a | 864 | if (is_debug) |
b6927875 DS |
865 | zlog_debug ("LSA can't be updated within MinLSArrival, %dms < %dms, discard", |
866 | time_delta_ms, from->ospf6_if->area->ospf6->lsa_minarrival); | |
48454375 | 867 | ospf6_lsa_delete (new); |
868 | return; /* examin next lsa */ | |
869 | } | |
870 | } | |
871 | ||
cf672a86 | 872 | monotime(&new->received); |
ccb59b11 | 873 | |
1e05838a | 874 | if (is_debug) |
bf986da7 DD |
875 | zlog_debug ("Install, Flood, Possibly acknowledge the received LSA"); |
876 | ||
877 | /* Remove older copies of this LSA from retx lists */ | |
878 | if (old) | |
879 | ospf6_flood_clear (old); | |
6452df09 | 880 | |
48454375 | 881 | /* (b) immediately flood and (c) remove from all retrans-list */ |
ccb59b11 | 882 | /* Prevent self-originated LSA to be flooded. this is to make |
883 | reoriginated instance of the LSA not to be rejected by other routers | |
884 | due to MinLSArrival. */ | |
885 | if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) | |
886 | ospf6_flood (from, new); | |
6452df09 | 887 | |
48454375 | 888 | /* (d), installing lsdb, which may cause routing |
889 | table calculation (replacing database copy) */ | |
6452df09 | 890 | ospf6_install_lsa (new); |
48454375 | 891 | |
c3c0ac83 DS |
892 | if (OSPF6_LSA_IS_MAXAGE (new)) |
893 | ospf6_maxage_remove (from->ospf6_if->area->ospf6); | |
894 | ||
48454375 | 895 | /* (e) possibly acknowledge */ |
896 | ospf6_acknowledge_lsa (new, ismore_recent, from); | |
897 | ||
6452df09 | 898 | /* (f) Self Originated LSA, section 13.4 */ |
899 | if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) | |
48454375 | 900 | { |
6452df09 | 901 | /* Self-originated LSA (newer than ours) is received from |
902 | another router. We have to make a new instance of the LSA | |
48454375 | 903 | or have to flush this LSA. */ |
1e05838a | 904 | if (is_debug) |
6452df09 | 905 | { |
c6487d61 | 906 | zlog_debug ("Newer instance of the self-originated LSA"); |
907 | zlog_debug ("Schedule reorigination"); | |
6452df09 | 908 | } |
66e78ae6 QY |
909 | new->refresh = NULL; |
910 | thread_add_event(master, ospf6_lsa_refresh, new, 0, &new->refresh); | |
48454375 | 911 | } |
6452df09 | 912 | |
48454375 | 913 | return; |
914 | } | |
915 | ||
916 | /* (6) if there is instance on sending neighbor's request list */ | |
917 | if (ospf6_lsdb_lookup (new->header->type, new->header->id, | |
918 | new->header->adv_router, from->request_list)) | |
919 | { | |
920 | /* if no database copy, should go above state (5) */ | |
921 | assert (old); | |
922 | ||
1e05838a | 923 | if (is_debug) |
6452df09 | 924 | { |
c6487d61 | 925 | zlog_debug ("Received is not newer, on the neighbor's request-list"); |
926 | zlog_debug ("BadLSReq, discard the received LSA"); | |
6452df09 | 927 | } |
48454375 | 928 | |
929 | /* BadLSReq */ | |
ffa2c898 | 930 | thread_add_event(master, bad_lsreq, from, 0, NULL); |
48454375 | 931 | |
932 | ospf6_lsa_delete (new); | |
933 | return; | |
934 | } | |
935 | ||
936 | /* (7) if neither one is more recent */ | |
937 | if (ismore_recent == 0) | |
938 | { | |
1e05838a | 939 | if (is_debug) |
c6487d61 | 940 | zlog_debug ("The same instance as database copy (neither recent)"); |
48454375 | 941 | |
942 | /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ | |
943 | rem = ospf6_lsdb_lookup (new->header->type, new->header->id, | |
944 | new->header->adv_router, from->retrans_list); | |
945 | if (rem) | |
946 | { | |
1e05838a | 947 | if (is_debug) |
6452df09 | 948 | { |
c6487d61 | 949 | zlog_debug ("It is on the neighbor's retrans-list."); |
950 | zlog_debug ("Treat as an Implied acknowledgement"); | |
6452df09 | 951 | } |
48454375 | 952 | SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); |
6452df09 | 953 | ospf6_decrement_retrans_count (rem); |
48454375 | 954 | ospf6_lsdb_remove (rem, from->retrans_list); |
955 | } | |
956 | ||
1e05838a | 957 | if (is_debug) |
c6487d61 | 958 | zlog_debug ("Possibly acknowledge and then discard"); |
6452df09 | 959 | |
48454375 | 960 | /* (b) possibly acknowledge */ |
961 | ospf6_acknowledge_lsa (new, ismore_recent, from); | |
962 | ||
963 | ospf6_lsa_delete (new); | |
964 | return; | |
965 | } | |
966 | ||
967 | /* (8) previous database copy is more recent */ | |
968 | { | |
969 | assert (old); | |
970 | ||
971 | /* If database copy is in 'Seqnumber Wrapping', | |
972 | simply discard the received LSA */ | |
973 | if (OSPF6_LSA_IS_MAXAGE (old) && | |
8551e6da | 974 | old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER)) |
48454375 | 975 | { |
1e05838a | 976 | if (is_debug) |
6452df09 | 977 | { |
c6487d61 | 978 | zlog_debug ("The LSA is in Seqnumber Wrapping"); |
979 | zlog_debug ("MaxAge & MaxSeqNum, discard"); | |
6452df09 | 980 | } |
eb82e9ee DD |
981 | ospf6_lsa_delete (new); |
982 | return; | |
48454375 | 983 | } |
984 | ||
985 | /* Otherwise, Send database copy of this LSA to this neighbor */ | |
986 | { | |
1e05838a | 987 | if (is_debug) |
6452df09 | 988 | { |
c6487d61 | 989 | zlog_debug ("Database copy is more recent."); |
990 | zlog_debug ("Send back directly and then discard"); | |
6452df09 | 991 | } |
48454375 | 992 | |
993 | /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ | |
994 | ||
48454375 | 995 | ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); |
66e78ae6 QY |
996 | thread_add_event(master, ospf6_lsupdate_send_neighbor, from, 0, |
997 | &from->thread_send_lsupdate); | |
eb82e9ee DD |
998 | ospf6_lsa_delete (new); |
999 | return; | |
48454375 | 1000 | } |
1001 | return; | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | ||
1e05838a | 1006 | DEFUN (debug_ospf6_flooding, |
1007 | debug_ospf6_flooding_cmd, | |
1008 | "debug ospf6 flooding", | |
1009 | DEBUG_STR | |
1010 | OSPF6_STR | |
1011 | "Debug OSPFv3 flooding function\n" | |
1012 | ) | |
1013 | { | |
1014 | OSPF6_DEBUG_FLOODING_ON (); | |
1015 | return CMD_SUCCESS; | |
1016 | } | |
1017 | ||
1018 | DEFUN (no_debug_ospf6_flooding, | |
1019 | no_debug_ospf6_flooding_cmd, | |
1020 | "no debug ospf6 flooding", | |
1021 | NO_STR | |
1022 | DEBUG_STR | |
1023 | OSPF6_STR | |
1024 | "Debug OSPFv3 flooding function\n" | |
1025 | ) | |
1026 | { | |
1027 | OSPF6_DEBUG_FLOODING_OFF (); | |
1028 | return CMD_SUCCESS; | |
1029 | } | |
1030 | ||
1031 | int | |
1032 | config_write_ospf6_debug_flood (struct vty *vty) | |
1033 | { | |
1034 | if (IS_OSPF6_DEBUG_FLOODING) | |
1035 | vty_out (vty, "debug ospf6 flooding%s", VNL); | |
1036 | return 0; | |
1037 | } | |
1038 | ||
1039 | void | |
6ac29a51 | 1040 | install_element_ospf6_debug_flood (void) |
1e05838a | 1041 | { |
1042 | install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd); | |
1043 | install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd); | |
1044 | install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); | |
1045 | install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd); | |
1046 | } | |
1047 | ||
1048 | ||
1049 | ||
1050 | ||
48454375 | 1051 |