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