blob: 05112021c9c914e982017d66996593846c627f1b [file] [log] [blame]
hasso48454372004-05-18 19:14:52 +00001/*
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
hasso6452df02004-08-15 05:52:07 +000042#include "ospf6_flood.h"
hasso48454372004-05-18 19:14:52 +000043
44struct ospf6_lsdb *
hasso6452df02004-08-15 05:52:07 +000045ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +000046{
47 struct ospf6_lsdb *lsdb = NULL;
hasso6452df02004-08-15 05:52:07 +000048 switch (OSPF6_LSA_SCOPE (lsa->header->type))
hasso48454372004-05-18 19:14:52 +000049 {
hasso6452df02004-08-15 05:52:07 +000050 case OSPF6_SCOPE_LINKLOCAL:
51 lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
52 break;
53 case OSPF6_SCOPE_AREA:
54 lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
55 break;
56 case OSPF6_SCOPE_AS:
57 lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
58 break;
59 default:
60 assert (0);
61 break;
hasso48454372004-05-18 19:14:52 +000062 }
hasso48454372004-05-18 19:14:52 +000063 return lsdb;
64}
65
hasso6452df02004-08-15 05:52:07 +000066struct ospf6_lsdb *
67ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
hasso3b4cd3a2004-05-18 19:28:32 +000068{
hasso6452df02004-08-15 05:52:07 +000069 struct ospf6_lsdb *lsdb_self = NULL;
70 switch (OSPF6_LSA_SCOPE (lsa->header->type))
hasso3b4cd3a2004-05-18 19:28:32 +000071 {
hasso6452df02004-08-15 05:52:07 +000072 case OSPF6_SCOPE_LINKLOCAL:
73 lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
74 break;
75 case OSPF6_SCOPE_AREA:
76 lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
77 break;
78 case OSPF6_SCOPE_AS:
79 lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
80 break;
81 default:
82 assert (0);
83 break;
hasso3b4cd3a2004-05-18 19:28:32 +000084 }
hasso6452df02004-08-15 05:52:07 +000085 return lsdb_self;
hasso3b4cd3a2004-05-18 19:28:32 +000086}
87
88void
hasso6452df02004-08-15 05:52:07 +000089ospf6_lsa_originate (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +000090{
hasso6452df02004-08-15 05:52:07 +000091 struct ospf6_lsa *old;
92 struct ospf6_lsdb *lsdb_self;
hasso48454372004-05-18 19:14:52 +000093
hasso6452df02004-08-15 05:52:07 +000094 /* find previous LSA */
95 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
96 lsa->header->adv_router, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +000097
hasso6452df02004-08-15 05:52:07 +000098 /* if the new LSA does not differ from previous,
99 suppress this update of the LSA */
100 if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
hasso48454372004-05-18 19:14:52 +0000101 {
hasso6452df02004-08-15 05:52:07 +0000102 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
103 zlog_info ("Suppress updating LSA: %s", lsa->name);
104 ospf6_lsa_delete (lsa);
hasso48454372004-05-18 19:14:52 +0000105 return;
106 }
107
hasso6452df02004-08-15 05:52:07 +0000108 /* store it in the LSDB for self-originated LSAs */
109 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
110 ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
111
112 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
113 LS_REFRESH_TIME);
114
115 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
hasso48454372004-05-18 19:14:52 +0000116 {
hasso6452df02004-08-15 05:52:07 +0000117 zlog_info ("LSA Originate:");
118 ospf6_lsa_header_print (lsa);
hasso48454372004-05-18 19:14:52 +0000119 }
120
hasso6452df02004-08-15 05:52:07 +0000121 if (old)
122 ospf6_flood_clear (old);
123 ospf6_flood (NULL, lsa);
124 ospf6_install_lsa (lsa);
125}
126
127void
128ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
129 struct ospf6 *process)
130{
131 lsa->lsdb = process->lsdb;
132 ospf6_lsa_originate (lsa);
133}
134
135void
136ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
137 struct ospf6_area *oa)
138{
139 lsa->lsdb = oa->lsdb;
140 ospf6_lsa_originate (lsa);
141}
142
143void
144ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
145 struct ospf6_interface *oi)
146{
147 lsa->lsdb = oi->lsdb;
148 ospf6_lsa_originate (lsa);
149}
150
151void
152ospf6_lsa_purge (struct ospf6_lsa *lsa)
153{
154 struct ospf6_lsa *self;
155 struct ospf6_lsdb *lsdb_self;
156
157 /* remove it from the LSDB for self-originated LSAs */
158 lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
159 self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
160 lsa->header->adv_router, lsdb_self);
161 if (self)
hasso48454372004-05-18 19:14:52 +0000162 {
hasso6452df02004-08-15 05:52:07 +0000163 THREAD_OFF (self->expire);
164 THREAD_OFF (self->refresh);
165 ospf6_lsdb_remove (self, lsdb_self);
hasso48454372004-05-18 19:14:52 +0000166 }
167
hasso6452df02004-08-15 05:52:07 +0000168 ospf6_lsa_premature_aging (lsa);
169}
170
171
172void
173ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
174{
175 /* The LSA must be the original one (see the description
176 in ospf6_decrement_retrans_count () below) */
177 lsa->retrans_count++;
178}
179
180void
181ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
182{
183 struct ospf6_lsdb *lsdb;
184 struct ospf6_lsa *orig;
185
186 /* The LSA must be on the retrans-list of a neighbor. It means
187 the "lsa" is a copied one, and we have to decrement the
188 retransmission count of the original one (instead of "lsa"'s).
189 In order to find the original LSA, first we have to find
190 appropriate LSDB that have the original LSA. */
191 lsdb = ospf6_get_scoped_lsdb (lsa);
192
193 /* Find the original LSA of which the retrans_count should be decremented */
194 orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
195 lsa->header->adv_router, lsdb);
196 if (orig)
197 orig->retrans_count--;
198
199 assert (orig->retrans_count >= 0);
hasso48454372004-05-18 19:14:52 +0000200}
201
202/* RFC2328 section 13.2 Installing LSAs in the database */
203void
hasso6452df02004-08-15 05:52:07 +0000204ospf6_install_lsa (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +0000205{
206 struct ospf6_lsa *old;
hasso3b687352004-08-19 06:56:53 +0000207 struct timeval now;
hasso48454372004-05-18 19:14:52 +0000208
209 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
210 zlog_info ("Install LSA: %s", lsa->name);
211
212 /* Remove the old instance from all neighbors' Link state
213 retransmission list (RFC2328 13.2 last paragraph) */
214 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000215 lsa->header->adv_router, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000216 if (old)
hasso3b687352004-08-19 06:56:53 +0000217 {
218 THREAD_OFF (old->expire);
219 ospf6_flood_clear (old);
220 }
221
222 gettimeofday (&now, (struct timezone *) NULL);
223 if (ospf6_lsa_age_current (lsa) != MAXAGE)
224 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
225 MAXAGE + lsa->birth.tv_sec - now.tv_sec);
226 else
227 lsa->expire = NULL;
hasso48454372004-05-18 19:14:52 +0000228
229 /* actually install */
hasso3b687352004-08-19 06:56:53 +0000230 lsa->installed = now;
hasso6452df02004-08-15 05:52:07 +0000231 ospf6_lsdb_add (lsa, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000232
233 return;
234}
235
hasso6452df02004-08-15 05:52:07 +0000236/* RFC2740 section 3.5.2. Sending Link State Update packets */
hasso48454372004-05-18 19:14:52 +0000237/* RFC2328 section 13.3 Next step in the flooding procedure */
238void
hasso6452df02004-08-15 05:52:07 +0000239ospf6_flood_interface (struct ospf6_neighbor *from,
240 struct ospf6_lsa *lsa, struct ospf6_interface *oi)
hasso48454372004-05-18 19:14:52 +0000241{
hasso6452df02004-08-15 05:52:07 +0000242 listnode node;
hasso48454372004-05-18 19:14:52 +0000243 struct ospf6_neighbor *on;
hasso48454372004-05-18 19:14:52 +0000244 struct ospf6_lsa *req;
245 int retrans_added = 0;
246
hasso48454372004-05-18 19:14:52 +0000247 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso6452df02004-08-15 05:52:07 +0000248 zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
hasso48454372004-05-18 19:14:52 +0000249
hasso6452df02004-08-15 05:52:07 +0000250 /* (1) For each neighbor */
251 for (node = listhead (oi->neighbor_list); node; nextnode (node))
hasso48454372004-05-18 19:14:52 +0000252 {
hasso6452df02004-08-15 05:52:07 +0000253 on = (struct ospf6_neighbor *) getdata (node);
hasso48454372004-05-18 19:14:52 +0000254
hasso6452df02004-08-15 05:52:07 +0000255 if (IS_OSPF6_DEBUG_LSA (SEND))
256 zlog_info ("To neighbor %s", on->name);
257
258 /* (a) if neighbor state < Exchange, examin next */
259 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
hasso48454372004-05-18 19:14:52 +0000260 {
hasso6452df02004-08-15 05:52:07 +0000261 if (IS_OSPF6_DEBUG_LSA (SEND))
262 zlog_info ("Neighbor state less than ExChange, next neighbor");
263 continue;
hasso48454372004-05-18 19:14:52 +0000264 }
hasso48454372004-05-18 19:14:52 +0000265
hasso6452df02004-08-15 05:52:07 +0000266 /* (b) if neighbor not yet Full, check request-list */
267 if (on->state != OSPF6_NEIGHBOR_FULL)
hasso48454372004-05-18 19:14:52 +0000268 {
hasso6452df02004-08-15 05:52:07 +0000269 if (IS_OSPF6_DEBUG_LSA (SEND))
270 zlog_info ("Neighbor not yet Full");
hasso48454372004-05-18 19:14:52 +0000271
hasso6452df02004-08-15 05:52:07 +0000272 req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
273 lsa->header->adv_router, on->request_list);
274 if (req == NULL)
hasso48454372004-05-18 19:14:52 +0000275 {
hasso6452df02004-08-15 05:52:07 +0000276 if (IS_OSPF6_DEBUG_LSA (SEND))
277 zlog_info ("Not on request-list for this neighbor");
278 /* fall through */
279 }
280 else
281 {
282 /* If new LSA less recent, examin next neighbor */
283 if (ospf6_lsa_compare (lsa, req) > 0)
hasso48454372004-05-18 19:14:52 +0000284 {
hasso6452df02004-08-15 05:52:07 +0000285 if (IS_OSPF6_DEBUG_LSA (SEND))
286 zlog_info ("Requesting is newer, next neighbor");
287 continue;
288 }
hasso48454372004-05-18 19:14:52 +0000289
hasso6452df02004-08-15 05:52:07 +0000290 /* If the same instance, delete from request-list and
291 examin next neighbor */
292 if (ospf6_lsa_compare (lsa, req) == 0)
293 {
294 if (IS_OSPF6_DEBUG_LSA (SEND))
295 zlog_info ("Requesting the same, remove it, next neighbor");
296 ospf6_lsdb_remove (req, on->request_list);
297 continue;
298 }
hasso48454372004-05-18 19:14:52 +0000299
hasso6452df02004-08-15 05:52:07 +0000300 /* If the new LSA is more recent, delete from request-list */
301 if (ospf6_lsa_compare (lsa, req) < 0)
302 {
303 if (IS_OSPF6_DEBUG_LSA (SEND))
304 zlog_info ("Received is newer, remove requesting");
305 ospf6_lsdb_remove (req, on->request_list);
306 /* fall through */
hasso48454372004-05-18 19:14:52 +0000307 }
308 }
hasso48454372004-05-18 19:14:52 +0000309 }
310
hasso6452df02004-08-15 05:52:07 +0000311 /* (c) If the new LSA was received from this neighbor,
312 examin next neighbor */
313 if (from == on)
hasso48454372004-05-18 19:14:52 +0000314 {
hasso6452df02004-08-15 05:52:07 +0000315 if (IS_OSPF6_DEBUG_LSA (SEND))
316 zlog_info ("Received is from the neighbor, next neighbor");
317 continue;
hasso48454372004-05-18 19:14:52 +0000318 }
hasso6452df02004-08-15 05:52:07 +0000319
320 /* (d) add retrans-list, schedule retransmission */
321 if (IS_OSPF6_DEBUG_LSA (SEND))
322 zlog_info ("Add retrans-list of this neighbor");
323 ospf6_increment_retrans_count (lsa);
324 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
325 if (on->thread_send_lsupdate == NULL)
326 on->thread_send_lsupdate =
327 thread_add_event (master, ospf6_lsupdate_send_neighbor,
328 on, on->ospf6_if->rxmt_interval);
329 retrans_added++;
hasso48454372004-05-18 19:14:52 +0000330 }
331
hasso6452df02004-08-15 05:52:07 +0000332 /* (2) examin next interface if not added to retrans-list */
333 if (retrans_added == 0)
334 {
335 if (IS_OSPF6_DEBUG_LSA (SEND))
336 zlog_info ("No retransmission scheduled, next interface");
337 return;
338 }
339
340 /* (3) If the new LSA was received on this interface,
341 and it was from DR or BDR, examin next interface */
342 if (from && from->ospf6_if == oi &&
343 (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
344 {
345 if (IS_OSPF6_DEBUG_LSA (SEND))
346 zlog_info ("Received is from the I/F's DR or BDR, next interface");
347 return;
348 }
349
350 /* (4) If the new LSA was received on this interface,
351 and the interface state is BDR, examin next interface */
352 if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
353 {
354 if (IS_OSPF6_DEBUG_LSA (SEND))
355 zlog_info ("Received is from the I/F, itself BDR, next interface");
356 return;
357 }
358
359 /* (5) flood the LSA out the interface. */
360 if (IS_OSPF6_DEBUG_LSA (SEND))
361 zlog_info ("Schedule flooding for the interface");
362 if (if_is_broadcast (oi->interface))
363 {
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 /* reschedule retransmissions to all neighbors */
372 for (node = listhead (oi->neighbor_list); node; nextnode (node))
373 {
374 on = (struct ospf6_neighbor *) getdata (node);
375 THREAD_OFF (on->thread_send_lsupdate);
376 on->thread_send_lsupdate =
377 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
378 }
379 }
hasso48454372004-05-18 19:14:52 +0000380}
381
hasso6452df02004-08-15 05:52:07 +0000382void
383ospf6_flood_area (struct ospf6_neighbor *from,
384 struct ospf6_lsa *lsa, struct ospf6_area *oa)
385{
386 listnode node;
387 struct ospf6_interface *oi;
388
389 for (node = listhead (oa->if_list); node; nextnode (node))
390 {
391 oi = OSPF6_INTERFACE (getdata (node));
392
393 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
394 oi != OSPF6_INTERFACE (lsa->lsdb->data))
395 continue;
396
397#if 0
398 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
399 ospf6_is_interface_virtual_link (oi))
400 continue;
401#endif/*0*/
402
403 ospf6_flood_interface (from, lsa, oi);
404 }
405}
406
407void
408ospf6_flood_process (struct ospf6_neighbor *from,
409 struct ospf6_lsa *lsa, struct ospf6 *process)
410{
411 listnode node;
412 struct ospf6_area *oa;
413
414 for (node = listhead (process->area_list); node; nextnode (node))
415 {
416 oa = OSPF6_AREA (getdata (node));
417
418 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
419 oa != OSPF6_AREA (lsa->lsdb->data))
420 continue;
421 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
422 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
423 continue;
424
425 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
426 IS_AREA_STUB (oa))
427 continue;
428
429 ospf6_flood_area (from, lsa, oa);
430 }
431}
432
433void
434ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
435{
436 ospf6_flood_process (from, lsa, ospf6);
437}
438
439void
440ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
441{
442 listnode node;
443 struct ospf6_neighbor *on;
444 struct ospf6_lsa *rem;
445
446 for (node = listhead (oi->neighbor_list); node; nextnode (node))
447 {
448 on = OSPF6_NEIGHBOR (getdata (node));
449 rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
450 lsa->header->adv_router, on->retrans_list);
451 if (rem && ! ospf6_lsa_compare (rem, lsa))
452 {
453 if (IS_OSPF6_DEBUG_LSA (DATABASE))
454 zlog_info ("Remove %s from retrans_list of %s",
455 rem->name, on->name);
456 ospf6_decrement_retrans_count (rem);
457 ospf6_lsdb_remove (rem, on->retrans_list);
458 }
459 }
460}
461
462void
463ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
464{
465 listnode node;
466 struct ospf6_interface *oi;
467
468 for (node = listhead (oa->if_list); node; nextnode (node))
469 {
470 oi = OSPF6_INTERFACE (getdata (node));
471
472 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
473 oi != OSPF6_INTERFACE (lsa->lsdb->data))
474 continue;
475
476#if 0
477 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
478 ospf6_is_interface_virtual_link (oi))
479 continue;
480#endif/*0*/
481
482 ospf6_flood_clear_interface (lsa, oi);
483 }
484}
485
486void
487ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
488{
489 listnode node;
490 struct ospf6_area *oa;
491
492 for (node = listhead (process->area_list); node; nextnode (node))
493 {
494 oa = OSPF6_AREA (getdata (node));
495
496 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
497 oa != OSPF6_AREA (lsa->lsdb->data))
498 continue;
499 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
500 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
501 continue;
502
503 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
504 IS_AREA_STUB (oa))
505 continue;
506
507 ospf6_flood_clear_area (lsa, oa);
508 }
509}
510
511void
512ospf6_flood_clear (struct ospf6_lsa *lsa)
513{
514 ospf6_flood_clear_process (lsa, ospf6);
515}
516
517
hasso48454372004-05-18 19:14:52 +0000518/* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
519static void
520ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
521 struct ospf6_neighbor *from)
522{
523 struct ospf6_interface *oi;
524
525 assert (from && from->ospf6_if);
526 oi = from->ospf6_if;
527
528 /* LSA has been flood back out receiving interface.
529 No acknowledgement sent. */
530 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
531 {
532 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000533 zlog_info ("No acknowledgement (BDR & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000534 return;
535 }
536
537 /* LSA is more recent than database copy, but was not flooded
538 back out receiving interface. Delayed acknowledgement sent
539 if advertisement received from Designated Router,
540 otherwide do nothing. */
541 if (ismore_recent < 0)
542 {
hasso48454372004-05-18 19:14:52 +0000543 if (oi->drouter == from->router_id)
544 {
545 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000546 zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
hasso48454372004-05-18 19:14:52 +0000547 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000548 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
549 if (oi->thread_send_lsack == NULL)
550 oi->thread_send_lsack =
551 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
552 }
553 else
554 {
555 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000556 zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000557 }
558 return;
559 }
560
561 /* LSA is a duplicate, and was treated as an implied acknowledgement.
562 Delayed acknowledgement sent if advertisement received from
563 Designated Router, otherwise do nothing */
564 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
565 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
566 {
hasso48454372004-05-18 19:14:52 +0000567 if (oi->drouter == from->router_id)
568 {
569 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000570 zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
hasso48454372004-05-18 19:14:52 +0000571 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000572 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
573 if (oi->thread_send_lsack == NULL)
574 oi->thread_send_lsack =
575 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
576 }
577 else
578 {
579 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000580 zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000581 }
582 return;
583 }
584
585 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
586 Direct acknowledgement sent */
587 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
588 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
589 {
590 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000591 zlog_info ("Direct acknowledgement (BDR & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000592 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
593 if (from->thread_send_lsack == NULL)
594 from->thread_send_lsack =
595 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
596 return;
597 }
598
599 /* LSA's LS age is equal to Maxage, and there is no current instance
600 of the LSA in the link state database, and none of router's
601 neighbors are in states Exchange or Loading */
602 /* Direct acknowledgement sent, but this case is handled in
603 early of ospf6_receive_lsa () */
604}
605
606static void
607ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
608 struct ospf6_neighbor *from)
609{
610 struct ospf6_interface *oi;
611
612 assert (from && from->ospf6_if);
613 oi = from->ospf6_if;
614
615 /* LSA has been flood back out receiving interface.
616 No acknowledgement sent. */
617 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
618 {
619 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000620 zlog_info ("No acknowledgement (AllOther & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000621 return;
622 }
623
624 /* LSA is more recent than database copy, but was not flooded
625 back out receiving interface. Delayed acknowledgement sent. */
626 if (ismore_recent < 0)
627 {
628 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000629 zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
hasso48454372004-05-18 19:14:52 +0000630 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000631 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
632 if (oi->thread_send_lsack == NULL)
633 oi->thread_send_lsack =
634 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
635 return;
636 }
637
638 /* LSA is a duplicate, and was treated as an implied acknowledgement.
639 No acknowledgement sent. */
640 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
641 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
642 {
643 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000644 zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
hasso48454372004-05-18 19:14:52 +0000645 return;
646 }
647
648 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
649 Direct acknowledgement sent */
650 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
651 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
652 {
653 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000654 zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000655 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
656 if (from->thread_send_lsack == NULL)
657 from->thread_send_lsack =
658 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
659 return;
660 }
661
662 /* LSA's LS age is equal to Maxage, and there is no current instance
663 of the LSA in the link state database, and none of router's
664 neighbors are in states Exchange or Loading */
665 /* Direct acknowledgement sent, but this case is handled in
666 early of ospf6_receive_lsa () */
667}
668
669void
670ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
671 struct ospf6_neighbor *from)
672{
673 struct ospf6_interface *oi;
674
675 assert (from && from->ospf6_if);
676 oi = from->ospf6_if;
677
678 if (oi->state == OSPF6_INTERFACE_BDR)
679 ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
680 else
681 ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
682}
683
684/* RFC2328 section 13 (4):
685 if MaxAge LSA and if we have no instance, and no neighbor
686 is in states Exchange or Loading
687 returns 1 if match this case, else returns 0 */
688static int
hasso6452df02004-08-15 05:52:07 +0000689ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
hasso48454372004-05-18 19:14:52 +0000690{
hasso48454372004-05-18 19:14:52 +0000691 struct ospf6_neighbor *on;
hasso6452df02004-08-15 05:52:07 +0000692 struct ospf6_interface *oi;
693 struct ospf6_area *oa;
694 struct ospf6 *process = NULL;
695 listnode i, j, k;
hasso48454372004-05-18 19:14:52 +0000696 int count = 0;
697
698 if (! OSPF6_LSA_IS_MAXAGE (lsa))
699 return 0;
700
hasso48454372004-05-18 19:14:52 +0000701 if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000702 lsa->header->adv_router, lsa->lsdb))
hasso48454372004-05-18 19:14:52 +0000703 return 0;
704
hasso6452df02004-08-15 05:52:07 +0000705 process = from->ospf6_if->area->ospf6;
706 for (i = listhead (process->area_list); i; nextnode (i))
hasso48454372004-05-18 19:14:52 +0000707 {
hasso6452df02004-08-15 05:52:07 +0000708 oa = OSPF6_AREA (getdata (i));
hasso48454372004-05-18 19:14:52 +0000709 for (j = listhead (oa->if_list); j; nextnode (j))
710 {
hasso6452df02004-08-15 05:52:07 +0000711 oi = OSPF6_INTERFACE (getdata (j));
712 for (k = listhead (oi->neighbor_list); k; nextnode (k))
713 {
714 on = OSPF6_NEIGHBOR (getdata (k));
715 if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
716 on->state == OSPF6_NEIGHBOR_LOADING)
717 count++;
718 }
hasso48454372004-05-18 19:14:52 +0000719 }
720 }
721
hasso48454372004-05-18 19:14:52 +0000722 if (count == 0)
723 return 1;
hasso48454372004-05-18 19:14:52 +0000724 return 0;
725}
726
727/* RFC2328 section 13 The Flooding Procedure */
728void
hasso6452df02004-08-15 05:52:07 +0000729ospf6_receive_lsa (struct ospf6_neighbor *from,
730 struct ospf6_lsa_header *lsa_header)
hasso48454372004-05-18 19:14:52 +0000731{
732 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
733 int ismore_recent;
734 unsigned short cksum;
hasso48454372004-05-18 19:14:52 +0000735
736 ismore_recent = 1;
hasso6452df02004-08-15 05:52:07 +0000737 assert (from);
hasso48454372004-05-18 19:14:52 +0000738
739 /* make lsa structure for received lsa */
740 new = ospf6_lsa_create (lsa_header);
741
742 if (IS_OSPF6_DEBUG_LSA (RECV))
743 {
744 zlog_info ("LSA Receive from %s", from->name);
745 ospf6_lsa_header_print (new);
746 }
747
hasso48454372004-05-18 19:14:52 +0000748 /* (1) LSA Checksum */
749 cksum = ntohs (new->header->checksum);
750 if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
751 {
752 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000753 zlog_info ("Wrong LSA Checksum, discard");
hasso48454372004-05-18 19:14:52 +0000754 ospf6_lsa_delete (new);
755 return;
756 }
757
hasso6452df02004-08-15 05:52:07 +0000758 /* (2) Examine the LSA's LS type.
759 RFC2470 3.5.1. Receiving Link State Update packets */
760 if (IS_AREA_STUB (from->ospf6_if->area) &&
761 OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
hasso48454372004-05-18 19:14:52 +0000762 {
763 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000764 zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
765 ospf6_lsa_delete (new);
766 return;
767 }
768
769 /* (3) LSA which have reserved scope is discarded
770 RFC2470 3.5.1. Receiving Link State Update packets */
771 /* Flooding scope check. LSAs with unknown scope are discarded here.
772 Set appropriate LSDB for the LSA */
773 switch (OSPF6_LSA_SCOPE (new->header->type))
774 {
775 case OSPF6_SCOPE_LINKLOCAL:
776 new->lsdb = from->ospf6_if->lsdb;
777 break;
778 case OSPF6_SCOPE_AREA:
779 new->lsdb = from->ospf6_if->area->lsdb;
780 break;
781 case OSPF6_SCOPE_AS:
782 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
783 break;
784 default:
785 if (IS_OSPF6_DEBUG_LSA (RECV))
786 zlog_info ("LSA has reserved scope, discard");
hasso48454372004-05-18 19:14:52 +0000787 ospf6_lsa_delete (new);
788 return;
789 }
790
791 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
792 is in states Exchange or Loading */
793 if (ospf6_is_maxage_lsa_drop (new, from))
794 {
795 /* log */
796 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000797 zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
hasso48454372004-05-18 19:14:52 +0000798
799 /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
hasso6452df02004-08-15 05:52:07 +0000800 ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
hasso48454372004-05-18 19:14:52 +0000801 if (from->thread_send_lsack == NULL)
802 from->thread_send_lsack =
803 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
804
805 /* b) Discard */
hasso6452df02004-08-15 05:52:07 +0000806 ospf6_lsa_delete (new);
hasso48454372004-05-18 19:14:52 +0000807 return;
808 }
809
810 /* (5) */
811 /* lookup the same database copy in lsdb */
hasso48454372004-05-18 19:14:52 +0000812 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
hasso6452df02004-08-15 05:52:07 +0000813 new->header->adv_router, new->lsdb);
hasso48454372004-05-18 19:14:52 +0000814 if (old)
815 {
816 ismore_recent = ospf6_lsa_compare (new, old);
817 if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
818 {
819 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000820 zlog_info ("Received is duplicated LSA");
hasso48454372004-05-18 19:14:52 +0000821 SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
822 }
823 }
824
825 /* if no database copy or received is more recent */
826 if (old == NULL || ismore_recent < 0)
827 {
828 /* in case we have no database copy */
829 ismore_recent = -1;
830
831 /* (a) MinLSArrival check */
832 if (old)
833 {
834 struct timeval now, res;
835 gettimeofday (&now, (struct timezone *) NULL);
836 timersub (&now, &old->installed, &res);
837 if (res.tv_sec < MIN_LS_ARRIVAL)
838 {
839 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
hasso6452df02004-08-15 05:52:07 +0000840 zlog_info ("LSA can't be updated within MinLSArrival, discard");
hasso48454372004-05-18 19:14:52 +0000841 ospf6_lsa_delete (new);
842 return; /* examin next lsa */
843 }
844 }
845
hasso6452df02004-08-15 05:52:07 +0000846 if (IS_OSPF6_DEBUG_LSA (RECV))
847 zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
848
hasso48454372004-05-18 19:14:52 +0000849 /* (b) immediately flood and (c) remove from all retrans-list */
hasso6452df02004-08-15 05:52:07 +0000850 ospf6_flood (from, new);
851
852 /* (c) Remove the current database copy from all neighbors' Link
853 state retransmission lists. */
854 /* XXX, flood_clear ? */
hasso48454372004-05-18 19:14:52 +0000855
856 /* (d), installing lsdb, which may cause routing
857 table calculation (replacing database copy) */
hasso6452df02004-08-15 05:52:07 +0000858 ospf6_install_lsa (new);
hasso48454372004-05-18 19:14:52 +0000859
860 /* (e) possibly acknowledge */
861 ospf6_acknowledge_lsa (new, ismore_recent, from);
862
hasso6452df02004-08-15 05:52:07 +0000863 /* (f) Self Originated LSA, section 13.4 */
864 if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
hasso48454372004-05-18 19:14:52 +0000865 {
hasso6452df02004-08-15 05:52:07 +0000866 /* Self-originated LSA (newer than ours) is received from
867 another router. We have to make a new instance of the LSA
hasso48454372004-05-18 19:14:52 +0000868 or have to flush this LSA. */
869 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000870 {
871 zlog_info ("Newer instance of the self-originated LSA");
872 zlog_info ("Schedule reorigination");
873 }
874 new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
hasso48454372004-05-18 19:14:52 +0000875 }
hasso6452df02004-08-15 05:52:07 +0000876
hasso48454372004-05-18 19:14:52 +0000877 return;
878 }
879
880 /* (6) if there is instance on sending neighbor's request list */
881 if (ospf6_lsdb_lookup (new->header->type, new->header->id,
882 new->header->adv_router, from->request_list))
883 {
884 /* if no database copy, should go above state (5) */
885 assert (old);
886
887 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000888 {
889 zlog_info ("Received is not newer, on the neighbor's request-list");
890 zlog_info ("BadLSReq, discard the received LSA");
891 }
hasso48454372004-05-18 19:14:52 +0000892
893 /* BadLSReq */
894 thread_add_event (master, bad_lsreq, from, 0);
895
896 ospf6_lsa_delete (new);
897 return;
898 }
899
900 /* (7) if neither one is more recent */
901 if (ismore_recent == 0)
902 {
903 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000904 zlog_info ("The same instance as database copy (neither recent)");
hasso48454372004-05-18 19:14:52 +0000905
906 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
907 rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
908 new->header->adv_router, from->retrans_list);
909 if (rem)
910 {
911 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000912 {
913 zlog_info ("It is on the neighbor's retrans-list.");
914 zlog_info ("Treat as an Implied acknowledgement");
915 }
hasso48454372004-05-18 19:14:52 +0000916 SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
hasso6452df02004-08-15 05:52:07 +0000917 ospf6_decrement_retrans_count (rem);
hasso48454372004-05-18 19:14:52 +0000918 ospf6_lsdb_remove (rem, from->retrans_list);
919 }
920
hasso6452df02004-08-15 05:52:07 +0000921 if (IS_OSPF6_DEBUG_LSA (RECV))
922 zlog_info ("Possibly acknowledge and then discard");
923
hasso48454372004-05-18 19:14:52 +0000924 /* (b) possibly acknowledge */
925 ospf6_acknowledge_lsa (new, ismore_recent, from);
926
927 ospf6_lsa_delete (new);
928 return;
929 }
930
931 /* (8) previous database copy is more recent */
932 {
933 assert (old);
934
935 /* If database copy is in 'Seqnumber Wrapping',
936 simply discard the received LSA */
937 if (OSPF6_LSA_IS_MAXAGE (old) &&
938 old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
939 {
940 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000941 {
942 zlog_info ("The LSA is in Seqnumber Wrapping");
943 zlog_info ("MaxAge & MaxSeqNum, discard");
944 }
hasso48454372004-05-18 19:14:52 +0000945 ospf6_lsa_delete (new);
946 return;
947 }
948
949 /* Otherwise, Send database copy of this LSA to this neighbor */
950 {
951 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000952 {
953 zlog_info ("Database copy is more recent.");
954 zlog_info ("Send back directly and then discard");
955 }
hasso48454372004-05-18 19:14:52 +0000956
957 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
958
hasso48454372004-05-18 19:14:52 +0000959 ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
960 if (from->thread_send_lsupdate == NULL)
961 from->thread_send_lsupdate =
962 thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
963 ospf6_lsa_delete (new);
964 return;
965 }
966 return;
967 }
968}
969
970
971