]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_flood.c
Update to latest (really :) ospf6d from Zebra repository and some tiny
[mirror_frr.git] / ospf6d / ospf6_flood.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 #include "log.h"
25 #include "thread.h"
26 #include "linklist.h"
27 #include "vty.h"
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
42
43 void *
44 ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from)
45 {
46 void *scope = NULL;
47
48 if (from == NULL)
49 return NULL;
50
51 switch (OSPF6_LSA_SCOPE (type))
52 {
53 case OSPF6_LSA_SCOPE_AS:
54 scope = (from)->ospf6_if->area->ospf6;
55 break;
56 case OSPF6_LSA_SCOPE_AREA:
57 scope = (from)->ospf6_if->area;
58 break;
59 case OSPF6_LSA_SCOPE_LINKLOCAL:
60 scope = (from)->ospf6_if;
61 break;
62 default:
63 break;
64 }
65
66 return scope;
67 }
68
69 struct ospf6_lsdb *
70 ospf6_get_scoped_lsdb (u_int16_t type, void *scope)
71 {
72 struct ospf6_lsdb *lsdb = NULL;
73
74 if (scope == NULL)
75 return NULL;
76
77 switch (OSPF6_LSA_SCOPE (type))
78 {
79 case OSPF6_LSA_SCOPE_AS:
80 lsdb = ((struct ospf6 *)(scope))->lsdb;
81 break;
82 case OSPF6_LSA_SCOPE_AREA:
83 lsdb = ((struct ospf6_area *)(scope))->lsdb;
84 break;
85 case OSPF6_LSA_SCOPE_LINKLOCAL:
86 lsdb = ((struct ospf6_interface *)(scope))->lsdb;
87 break;
88 default:
89 break;
90 }
91
92 return lsdb;
93 }
94
95 void
96 ospf6_decrement_onretrans (struct ospf6_lsa *lsa)
97 {
98 struct ospf6_lsdb *lsdb;
99 struct ospf6_lsa *src;
100
101 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
102 if (lsdb == NULL)
103 {
104 zlog_warn ("Decrement onretrans: no such scope: %s", lsa->name);
105 return;
106 }
107
108 src = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
109 lsa->header->adv_router, lsdb);
110 if (src && src != lsa)
111 src->onretrans--;
112
113 if (src->onretrans < 0)
114 zlog_warn ("internal error: onretrans");
115 }
116
117 void
118 ospf6_flood_clear (struct ospf6_lsa *lsa)
119 {
120 struct ospf6_neighbor *on;
121 struct ospf6_interface *oi, *ospf6_if = NULL;
122 struct ospf6_area *oa, *area = NULL;
123 struct ospf6 *ospf6 = NULL;
124 u_int16_t scope_type;
125 list scoped_interfaces;
126 struct ospf6_lsa *rxmt;
127 listnode i, j;
128
129 scoped_interfaces = list_new ();
130 scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
131
132 if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
133 {
134 ospf6_if = (struct ospf6_interface *) lsa->scope;
135 area = ospf6_if->area;
136 ospf6 = area->ospf6;
137 }
138 else if (scope_type == OSPF6_LSA_SCOPE_AREA)
139 {
140 area = (struct ospf6_area *) lsa->scope;
141 ospf6 = area->ospf6;
142 }
143 else if (scope_type == OSPF6_LSA_SCOPE_AS)
144 {
145 ospf6 = (struct ospf6 *) lsa->scope;
146 }
147 else
148 {
149 zlog_warn ("Can't decide LSA scope, quit ospf6_flood_clear ()");
150 return;
151 }
152
153 /* Collect eligible interfaces */
154 for (i = listhead (ospf6->area_list); i; nextnode (i))
155 {
156 oa = (struct ospf6_area *) getdata (i);
157 if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
158 continue;
159
160 for (j = listhead (oa->if_list); j; nextnode (j))
161 {
162 oi = (struct ospf6_interface *) getdata (j);
163 if (scope_type != OSPF6_LSA_SCOPE_AS &&
164 scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
165 continue;
166
167 listnode_add (scoped_interfaces, oi);
168 }
169 }
170
171 for (i = listhead (scoped_interfaces); i; nextnode (i))
172 {
173 oi = (struct ospf6_interface *) getdata (i);
174 for (j = listhead (oi->neighbor_list); j; nextnode (j))
175 {
176 on = (struct ospf6_neighbor *) getdata (j);
177 rxmt = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
178 lsa->header->adv_router, on->retrans_list);
179 if (rxmt && ! ospf6_lsa_compare (rxmt, lsa))
180 {
181 if (IS_OSPF6_DEBUG_LSA (DATABASE))
182 zlog_info ("Remove %s from retrans_list of %s",
183 rxmt->name, on->name);
184 ospf6_decrement_onretrans (rxmt);
185 ospf6_lsdb_remove (rxmt, on->retrans_list);
186 }
187 }
188 }
189
190 list_delete (scoped_interfaces);
191 }
192
193 /* RFC2328 section 13.2 Installing LSAs in the database */
194 void
195 ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
196 {
197 struct ospf6_lsa *old;
198
199 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
200 zlog_info ("Install LSA: %s", lsa->name);
201
202 /* Remove the old instance from all neighbors' Link state
203 retransmission list (RFC2328 13.2 last paragraph) */
204 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
205 lsa->header->adv_router, lsdb);
206 if (old)
207 ospf6_flood_clear (old);
208
209 /* actually install */
210 gettimeofday (&lsa->installed, (struct timezone *) NULL);
211 ospf6_lsdb_add (lsa, lsdb);
212
213 return;
214 }
215
216 /* RFC2328 section 13.3 Next step in the flooding procedure */
217 void
218 ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
219 {
220 struct ospf6 *scope_as = NULL;
221 struct ospf6_area *oa, *scope_area = NULL;
222 struct ospf6_interface *oi, *scope_linklocal = NULL;
223 struct ospf6_neighbor *on;
224 list eligible_interfaces;
225 listnode i, j;
226 u_int16_t scope_type;
227 struct ospf6_lsa *req;
228 int retrans_added = 0;
229
230 scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
231 switch (scope_type)
232 {
233 case OSPF6_LSA_SCOPE_AS:
234 scope_as = (struct ospf6 *) lsa->scope;
235 break;
236 case OSPF6_LSA_SCOPE_AREA:
237 scope_as = ((struct ospf6_area *) lsa->scope)->ospf6;
238 scope_area = (struct ospf6_area *) lsa->scope;
239 break;
240 case OSPF6_LSA_SCOPE_LINKLOCAL:
241 scope_as = ((struct ospf6_interface *) lsa->scope)->area->ospf6;
242 scope_area = ((struct ospf6_interface *) lsa->scope)->area;
243 scope_linklocal = (struct ospf6_interface *) lsa->scope;
244 break;
245 default:
246 if (IS_OSPF6_DEBUG_LSA (SEND))
247 zlog_info ("Can't decide LSA scope");
248 return;
249 }
250
251 if (IS_OSPF6_DEBUG_LSA (SEND))
252 zlog_info ("Flood %s", lsa->name);
253
254 /* Collect eligible interfaces */
255 eligible_interfaces = list_new ();
256 for (i = listhead (scope_as->area_list); i; nextnode (i))
257 {
258 oa = (struct ospf6_area *) getdata (i);
259 if (scope_type != OSPF6_LSA_SCOPE_AS &&
260 oa != scope_area)
261 continue;
262
263 for (j = listhead (oa->if_list); j; nextnode (j))
264 {
265 oi = (struct ospf6_interface *) getdata (j);
266 if (scope_type != OSPF6_LSA_SCOPE_AS &&
267 scope_type != OSPF6_LSA_SCOPE_AREA &&
268 oi != scope_linklocal)
269 continue;
270
271 listnode_add (eligible_interfaces, oi);
272 }
273 }
274
275 /* For each eligible interface: */
276 for (i = listhead (eligible_interfaces); i; nextnode (i))
277 {
278 oi = (struct ospf6_interface *) getdata (i);
279
280 /* (1) For each neighbor */
281 for (j = listhead (oi->neighbor_list); j; nextnode (j))
282 {
283 on = (struct ospf6_neighbor *) getdata (j);
284
285 /* (a) if neighbor state < Exchange, examin next */
286 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
287 continue;
288
289 /* (b) if neighbor not yet Full, check request-list */
290 if (on->state != OSPF6_NEIGHBOR_FULL)
291 {
292 req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
293 lsa->header->adv_router,
294 on->request_list);
295 if (req)
296 {
297 /* If new LSA less recent, examin next neighbor */
298 if (ospf6_lsa_compare (lsa, req) > 0)
299 continue;
300
301 /* If the same instance, delete from request-list and
302 examin next neighbor */
303 if (ospf6_lsa_compare (lsa, req) == 0)
304 {
305 if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
306 zlog_info ("Remove %s from request-list of %s: "
307 "the same instance", req->name, on->name);
308 ospf6_lsdb_remove (req, on->request_list);
309 continue;
310 }
311
312 /* If the new LSA is more recent, delete from
313 request-list */
314 if (ospf6_lsa_compare (lsa, req) < 0)
315 {
316 if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
317 zlog_info ("Remove %s from request-list of %s: "
318 "newer instance", req->name, on->name);
319 ospf6_lsdb_remove (req, on->request_list);
320 /* fall through */
321 }
322 }
323 }
324
325 /* (c) If the new LSA was received from this neighbor,
326 examin next neighbor */
327 if (from == on)
328 continue;
329
330 /* (d) add retrans-list, schedule retransmission */
331 if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
332 zlog_info (" Add copy of %s to retrans-list of %s",
333 lsa->name, on->name);
334 lsa->onretrans++;
335 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
336 if (on->thread_send_lsupdate == NULL)
337 on->thread_send_lsupdate =
338 thread_add_event (master, ospf6_lsupdate_send_neighbor,
339 on, on->ospf6_if->rxmt_interval);
340 retrans_added++;
341 }
342
343 /* (2) examin next interface if not added to retrans-list */
344 if (retrans_added == 0)
345 continue;
346
347 /* (3) If the new LSA was received on this interface,
348 and it was from DR or BDR, examin next interface */
349 if (from && from->ospf6_if == oi &&
350 (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
351 continue;
352
353 /* (4) If the new LSA was received on this interface,
354 and the interface state is BDR, examin next interface */
355 if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
356 continue;
357
358 /* (5) flood the LSA out the interface. */
359 if (if_is_broadcast (oi->interface))
360 {
361 if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
362 zlog_info (" Add copy of %s to lsupdate_list of %s",
363 lsa->name, oi->interface->name);
364 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
365 if (oi->thread_send_lsupdate == NULL)
366 oi->thread_send_lsupdate =
367 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
368 }
369 else
370 {
371 for (j = listhead (oi->neighbor_list); j; nextnode (j))
372 {
373 on = (struct ospf6_neighbor *) getdata (j);
374 THREAD_OFF (on->thread_send_lsupdate);
375 on->thread_send_lsupdate =
376 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
377 }
378 }
379 }
380
381 list_delete (eligible_interfaces);
382 }
383
384 /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
385 static void
386 ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
387 struct ospf6_neighbor *from)
388 {
389 struct ospf6_interface *oi;
390
391 assert (from && from->ospf6_if);
392 oi = from->ospf6_if;
393
394 /* LSA has been flood back out receiving interface.
395 No acknowledgement sent. */
396 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
397 {
398 if (IS_OSPF6_DEBUG_LSA (RECV))
399 zlog_info (" BDR, FloodBack, No acknowledgement.");
400 return;
401 }
402
403 /* LSA is more recent than database copy, but was not flooded
404 back out receiving interface. Delayed acknowledgement sent
405 if advertisement received from Designated Router,
406 otherwide do nothing. */
407 if (ismore_recent < 0)
408 {
409 if (IS_OSPF6_DEBUG_LSA (RECV))
410 zlog_info (" BDR, Not FloodBack, MoreRecent, ");
411 if (oi->drouter == from->router_id)
412 {
413 if (IS_OSPF6_DEBUG_LSA (RECV))
414 zlog_info (" From DR, Delayed acknowledgement.");
415 /* Delayed acknowledgement */
416 if (IS_OSPF6_DEBUG_LSA (DATABASE))
417 zlog_info (" Add copy of %s to lsack_list of %s",
418 lsa->name, oi->interface->name);
419 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
420 if (oi->thread_send_lsack == NULL)
421 oi->thread_send_lsack =
422 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
423 }
424 else
425 {
426 if (IS_OSPF6_DEBUG_LSA (RECV))
427 zlog_info (" Not From DR, No acknowledgement.");
428 }
429 return;
430 }
431
432 /* LSA is a duplicate, and was treated as an implied acknowledgement.
433 Delayed acknowledgement sent if advertisement received from
434 Designated Router, otherwise do nothing */
435 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
436 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
437 {
438 if (IS_OSPF6_DEBUG_LSA (RECV))
439 zlog_info (" BDR, Duplicate, ImpliedAck, ");
440 if (oi->drouter == from->router_id)
441 {
442 if (IS_OSPF6_DEBUG_LSA (RECV))
443 zlog_info (" From DR, Delayed acknowledgement.");
444 /* Delayed acknowledgement */
445 if (IS_OSPF6_DEBUG_LSA (DATABASE))
446 zlog_info (" Add copy of %s to lsack_list of %s",
447 lsa->name, oi->interface->name);
448 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
449 if (oi->thread_send_lsack == NULL)
450 oi->thread_send_lsack =
451 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
452 }
453 else
454 {
455 if (IS_OSPF6_DEBUG_LSA (RECV))
456 zlog_info (" Not From DR, No acknowledgement.");
457 }
458 return;
459 }
460
461 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
462 Direct acknowledgement sent */
463 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
464 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
465 {
466 if (IS_OSPF6_DEBUG_LSA (RECV))
467 zlog_info (" BDR, Duplicate, Not ImpliedAck, Direct acknowledgement.");
468 if (IS_OSPF6_DEBUG_LSA (DATABASE))
469 zlog_info (" Add copy of %s to lsack_list of %s",
470 lsa->name, from->name);
471 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
472 if (from->thread_send_lsack == NULL)
473 from->thread_send_lsack =
474 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
475 return;
476 }
477
478 /* LSA's LS age is equal to Maxage, and there is no current instance
479 of the LSA in the link state database, and none of router's
480 neighbors are in states Exchange or Loading */
481 /* Direct acknowledgement sent, but this case is handled in
482 early of ospf6_receive_lsa () */
483 }
484
485 static void
486 ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
487 struct ospf6_neighbor *from)
488 {
489 struct ospf6_interface *oi;
490
491 assert (from && from->ospf6_if);
492 oi = from->ospf6_if;
493
494 /* LSA has been flood back out receiving interface.
495 No acknowledgement sent. */
496 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
497 {
498 if (IS_OSPF6_DEBUG_LSA (RECV))
499 zlog_info (" AllOther, FloodBack, No acknowledgement.");
500 return;
501 }
502
503 /* LSA is more recent than database copy, but was not flooded
504 back out receiving interface. Delayed acknowledgement sent. */
505 if (ismore_recent < 0)
506 {
507 if (IS_OSPF6_DEBUG_LSA (RECV))
508 zlog_info (" AllOther, Not FloodBack, Delayed acknowledgement.");
509 /* Delayed acknowledgement */
510 if (IS_OSPF6_DEBUG_LSA (DATABASE))
511 zlog_info (" Add copy of %s to lsack_list of %s",
512 lsa->name, oi->interface->name);
513 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
514 if (oi->thread_send_lsack == NULL)
515 oi->thread_send_lsack =
516 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
517 return;
518 }
519
520 /* LSA is a duplicate, and was treated as an implied acknowledgement.
521 No acknowledgement sent. */
522 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
523 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
524 {
525 if (IS_OSPF6_DEBUG_LSA (RECV))
526 zlog_info (" AllOther, Duplicate, ImpliedAck, No acknowledgement.");
527 return;
528 }
529
530 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
531 Direct acknowledgement sent */
532 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
533 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
534 {
535 if (IS_OSPF6_DEBUG_LSA (RECV))
536 zlog_info (" AllOther, Duplicate, Not ImpliedAck, Direct acknowledgement.");
537 if (IS_OSPF6_DEBUG_LSA (DATABASE))
538 zlog_info (" Add copy of %s to lsack_list of %s",
539 lsa->name, from->name);
540 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
541 if (from->thread_send_lsack == NULL)
542 from->thread_send_lsack =
543 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
544 return;
545 }
546
547 /* LSA's LS age is equal to Maxage, and there is no current instance
548 of the LSA in the link state database, and none of router's
549 neighbors are in states Exchange or Loading */
550 /* Direct acknowledgement sent, but this case is handled in
551 early of ospf6_receive_lsa () */
552 }
553
554 void
555 ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
556 struct ospf6_neighbor *from)
557 {
558 struct ospf6_interface *oi;
559
560 assert (from && from->ospf6_if);
561 oi = from->ospf6_if;
562
563 if (oi->state == OSPF6_INTERFACE_BDR)
564 ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
565 else
566 ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
567 }
568
569 /* RFC2328 section 13 (4):
570 if MaxAge LSA and if we have no instance, and no neighbor
571 is in states Exchange or Loading
572 returns 1 if match this case, else returns 0 */
573 static int
574 ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa,
575 struct ospf6_neighbor *from)
576 {
577 struct ospf6_lsdb *lsdb = NULL;
578 struct ospf6_neighbor *on;
579 struct ospf6_interface *oi, *ospf6_if = NULL;
580 struct ospf6_area *oa, *area = NULL;
581 struct ospf6 *ospf6 = NULL;
582 u_int16_t scope_type;
583 list scoped_interfaces;
584 listnode i, j;
585 int count = 0;
586
587 if (! OSPF6_LSA_IS_MAXAGE (lsa))
588 return 0;
589
590 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
591 if (lsdb == NULL)
592 {
593 zlog_info ("Can't decide scoped LSDB");
594 return 0;
595 }
596
597 if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
598 lsa->header->adv_router, lsdb))
599 return 0;
600
601 scoped_interfaces = list_new ();
602 scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
603
604 if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
605 {
606 ospf6_if = (struct ospf6_interface *) lsa->scope;
607 area = ospf6_if->area;
608 ospf6 = area->ospf6;
609 }
610 else if (scope_type == OSPF6_LSA_SCOPE_AREA)
611 {
612 area = (struct ospf6_area *) lsa->scope;
613 ospf6 = area->ospf6;
614 }
615 else if (scope_type == OSPF6_LSA_SCOPE_AS)
616 {
617 ospf6 = (struct ospf6 *) lsa->scope;
618 }
619 else
620 {
621 zlog_info ("Can't decide LSA scope");
622 return 0;
623 }
624
625 /* Collect eligible interfaces */
626 for (i = listhead (ospf6->area_list); i; nextnode (i))
627 {
628 oa = (struct ospf6_area *) getdata (i);
629 if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
630 continue;
631
632 for (j = listhead (oa->if_list); j; nextnode (j))
633 {
634 oi = (struct ospf6_interface *) getdata (j);
635 if (scope_type != OSPF6_LSA_SCOPE_AS &&
636 scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
637 continue;
638
639 listnode_add (scoped_interfaces, oi);
640 }
641 }
642
643 for (i = listhead (scoped_interfaces); i; nextnode (i))
644 {
645 oi = (struct ospf6_interface *) getdata (i);
646 for (j = listhead (oi->neighbor_list); j; nextnode (j))
647 {
648 on = (struct ospf6_neighbor *) getdata (j);
649 if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
650 on->state == OSPF6_NEIGHBOR_LOADING)
651 count ++;
652 }
653 }
654
655 list_delete (scoped_interfaces);
656
657 if (count == 0)
658 return 1;
659
660 return 0;
661 }
662
663 /* RFC2328 section 13 The Flooding Procedure */
664 void
665 ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header,
666 struct ospf6_neighbor *from)
667 {
668 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
669 int ismore_recent;
670 unsigned short cksum;
671 struct ospf6_lsdb *lsdb = NULL;
672
673 ismore_recent = 1;
674
675 /* make lsa structure for received lsa */
676 new = ospf6_lsa_create (lsa_header);
677
678 if (IS_OSPF6_DEBUG_LSA (RECV))
679 {
680 zlog_info ("LSA Receive from %s", from->name);
681 ospf6_lsa_header_print (new);
682 }
683
684 new->scope = ospf6_get_lsa_scope (new->header->type, from);
685 if (new->scope == NULL)
686 {
687 zlog_warn ("Can't decide LSA scope, ignore");
688 ospf6_lsa_delete (new);
689 return;
690 }
691
692 /* (1) LSA Checksum */
693 cksum = ntohs (new->header->checksum);
694 if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
695 {
696 if (IS_OSPF6_DEBUG_LSA (RECV))
697 zlog_info ("Wrong LSA Checksum");
698 ospf6_lsa_delete (new);
699 return;
700 }
701
702 /* (3) Ebit Missmatch: AS-External-LSA */
703 if (ntohs (new->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
704 ospf6_area_is_stub (from->ospf6_if->area))
705 {
706 if (IS_OSPF6_DEBUG_LSA (RECV))
707 zlog_info ("AS-External-LSA in stub area");
708 ospf6_lsa_delete (new);
709 return;
710 }
711
712 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
713 is in states Exchange or Loading */
714 if (ospf6_is_maxage_lsa_drop (new, from))
715 {
716 /* log */
717 if (IS_OSPF6_DEBUG_LSA (RECV))
718 zlog_info ("Drop MaxAge LSA with Direct acknowledgement.");
719
720 /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
721 if (IS_OSPF6_DEBUG_LSA (DATABASE))
722 zlog_info (" Add %s to lsack_list of %s",
723 new->name, from->name);
724 ospf6_lsdb_add (new, from->lsack_list);
725 if (from->thread_send_lsack == NULL)
726 from->thread_send_lsack =
727 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
728
729 /* b) Discard */
730 /* "new" LSA will be discarded just after the LSAck sent */
731 return;
732 }
733
734 /* (5) */
735 /* lookup the same database copy in lsdb */
736 lsdb = ospf6_get_scoped_lsdb (new->header->type, new->scope);
737 if (lsdb == NULL)
738 {
739 zlog_warn ("Can't decide scoped LSDB, ignore");
740 ospf6_lsa_delete (new);
741 return;
742 }
743
744 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
745 new->header->adv_router, lsdb);
746 if (old)
747 {
748 ismore_recent = ospf6_lsa_compare (new, old);
749 if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
750 {
751 if (IS_OSPF6_DEBUG_LSA (RECV))
752 zlog_info ("Duplicated LSA");
753 SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
754 }
755 }
756
757 /* if no database copy or received is more recent */
758 if (old == NULL || ismore_recent < 0)
759 {
760 /* in case we have no database copy */
761 ismore_recent = -1;
762
763 /* (a) MinLSArrival check */
764 if (old)
765 {
766 struct timeval now, res;
767 gettimeofday (&now, (struct timezone *) NULL);
768 timersub (&now, &old->installed, &res);
769 if (res.tv_sec < MIN_LS_ARRIVAL)
770 {
771 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
772 zlog_info ("LSA can't be updated within MinLSArrival");
773 ospf6_lsa_delete (new);
774 return; /* examin next lsa */
775 }
776 }
777
778 /* (b) immediately flood and (c) remove from all retrans-list */
779 ospf6_flood_lsa (new, from);
780
781 /* (d), installing lsdb, which may cause routing
782 table calculation (replacing database copy) */
783 ospf6_install_lsa (new, lsdb);
784
785 /* (e) possibly acknowledge */
786 ospf6_acknowledge_lsa (new, ismore_recent, from);
787
788 /* (f) */
789 /* Self Originated LSA, section 13.4 */
790 if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id
791 && (! old || ismore_recent < 0))
792 {
793 /* We have to make a new instance of the LSA
794 or have to flush this LSA. */
795 if (IS_OSPF6_DEBUG_LSA (RECV))
796 zlog_info ("New instance of the self-originated LSA");
797
798 SET_FLAG (new->flag, OSPF6_LSA_REFRESH);
799 ospf6_lsa_re_originate (new);
800 }
801 return;
802 }
803
804 /* (6) if there is instance on sending neighbor's request list */
805 if (ospf6_lsdb_lookup (new->header->type, new->header->id,
806 new->header->adv_router, from->request_list))
807 {
808 /* if no database copy, should go above state (5) */
809 assert (old);
810
811 if (IS_OSPF6_DEBUG_LSA (RECV))
812 zlog_info ("LSA is not newer and on request-list of sending neighbor");
813
814 /* BadLSReq */
815 thread_add_event (master, bad_lsreq, from, 0);
816
817 ospf6_lsa_delete (new);
818 return;
819 }
820
821 /* (7) if neither one is more recent */
822 if (ismore_recent == 0)
823 {
824 if (IS_OSPF6_DEBUG_LSA (RECV))
825 zlog_info ("The same instance as database copy");
826
827 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
828 rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
829 new->header->adv_router, from->retrans_list);
830 if (rem)
831 {
832 if (IS_OSPF6_DEBUG_LSA (RECV))
833 zlog_info ("Treat as an Implied acknowledgement");
834 SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
835 if (IS_OSPF6_DEBUG_LSA (DATABASE))
836 zlog_info ("Remove %s from retrans_list of %s",
837 rem->name, from->name);
838 ospf6_decrement_onretrans (rem);
839 ospf6_lsdb_remove (rem, from->retrans_list);
840 }
841
842 /* (b) possibly acknowledge */
843 ospf6_acknowledge_lsa (new, ismore_recent, from);
844
845 ospf6_lsa_delete (new);
846 return;
847 }
848
849 /* (8) previous database copy is more recent */
850 {
851 assert (old);
852
853 /* If database copy is in 'Seqnumber Wrapping',
854 simply discard the received LSA */
855 if (OSPF6_LSA_IS_MAXAGE (old) &&
856 old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
857 {
858 if (IS_OSPF6_DEBUG_LSA (RECV))
859 zlog_info ("Database copy is in Seqnumber Wrapping");
860 ospf6_lsa_delete (new);
861 return;
862 }
863
864 /* Otherwise, Send database copy of this LSA to this neighbor */
865 {
866 if (IS_OSPF6_DEBUG_LSA (RECV))
867 zlog_info ("Database is more recent, send back directly");
868
869 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
870
871 if (IS_OSPF6_DEBUG_LSA (DATABASE))
872 zlog_info (" Add copy of %s to lsupdate_list of %s",
873 old->name, from->name);
874 ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
875 if (from->thread_send_lsupdate == NULL)
876 from->thread_send_lsupdate =
877 thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
878 ospf6_lsa_delete (new);
879 return;
880 }
881 return;
882 }
883 }
884
885
886