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