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