blob: ec5c1c6833fa927bc6d6b9282fbbd032d3a3fa2f [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)
hasso6861b302004-08-26 18:19:59 +0000197 {
198 orig->retrans_count--;
199 assert (orig->retrans_count >= 0);
200 }
hasso48454372004-05-18 19:14:52 +0000201}
202
203/* RFC2328 section 13.2 Installing LSAs in the database */
204void
hasso6452df02004-08-15 05:52:07 +0000205ospf6_install_lsa (struct ospf6_lsa *lsa)
hasso48454372004-05-18 19:14:52 +0000206{
207 struct ospf6_lsa *old;
hasso3b687352004-08-19 06:56:53 +0000208 struct timeval now;
hasso48454372004-05-18 19:14:52 +0000209
210 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
211 zlog_info ("Install LSA: %s", lsa->name);
212
213 /* Remove the old instance from all neighbors' Link state
214 retransmission list (RFC2328 13.2 last paragraph) */
215 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000216 lsa->header->adv_router, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000217 if (old)
hasso3b687352004-08-19 06:56:53 +0000218 {
219 THREAD_OFF (old->expire);
220 ospf6_flood_clear (old);
221 }
222
223 gettimeofday (&now, (struct timezone *) NULL);
hassoccb59b12004-08-25 09:10:37 +0000224 if (! OSPF6_LSA_IS_MAXAGE (lsa))
hasso3b687352004-08-19 06:56:53 +0000225 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
226 MAXAGE + lsa->birth.tv_sec - now.tv_sec);
227 else
228 lsa->expire = NULL;
hasso48454372004-05-18 19:14:52 +0000229
230 /* actually install */
hasso3b687352004-08-19 06:56:53 +0000231 lsa->installed = now;
hasso6452df02004-08-15 05:52:07 +0000232 ospf6_lsdb_add (lsa, lsa->lsdb);
hasso48454372004-05-18 19:14:52 +0000233
234 return;
235}
236
hasso6452df02004-08-15 05:52:07 +0000237/* RFC2740 section 3.5.2. Sending Link State Update packets */
hasso48454372004-05-18 19:14:52 +0000238/* RFC2328 section 13.3 Next step in the flooding procedure */
239void
hasso6452df02004-08-15 05:52:07 +0000240ospf6_flood_interface (struct ospf6_neighbor *from,
241 struct ospf6_lsa *lsa, struct ospf6_interface *oi)
hasso48454372004-05-18 19:14:52 +0000242{
hasso6452df02004-08-15 05:52:07 +0000243 listnode node;
hasso48454372004-05-18 19:14:52 +0000244 struct ospf6_neighbor *on;
hasso48454372004-05-18 19:14:52 +0000245 struct ospf6_lsa *req;
246 int retrans_added = 0;
247
hasso48454372004-05-18 19:14:52 +0000248 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso6452df02004-08-15 05:52:07 +0000249 zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
hasso48454372004-05-18 19:14:52 +0000250
hasso6452df02004-08-15 05:52:07 +0000251 /* (1) For each neighbor */
252 for (node = listhead (oi->neighbor_list); node; nextnode (node))
hasso48454372004-05-18 19:14:52 +0000253 {
hasso6452df02004-08-15 05:52:07 +0000254 on = (struct ospf6_neighbor *) getdata (node);
hasso48454372004-05-18 19:14:52 +0000255
hasso6452df02004-08-15 05:52:07 +0000256 if (IS_OSPF6_DEBUG_LSA (SEND))
257 zlog_info ("To neighbor %s", on->name);
258
259 /* (a) if neighbor state < Exchange, examin next */
260 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
hasso48454372004-05-18 19:14:52 +0000261 {
hasso6452df02004-08-15 05:52:07 +0000262 if (IS_OSPF6_DEBUG_LSA (SEND))
263 zlog_info ("Neighbor state less than ExChange, next neighbor");
264 continue;
hasso48454372004-05-18 19:14:52 +0000265 }
hasso48454372004-05-18 19:14:52 +0000266
hasso6452df02004-08-15 05:52:07 +0000267 /* (b) if neighbor not yet Full, check request-list */
268 if (on->state != OSPF6_NEIGHBOR_FULL)
hasso48454372004-05-18 19:14:52 +0000269 {
hasso6452df02004-08-15 05:52:07 +0000270 if (IS_OSPF6_DEBUG_LSA (SEND))
271 zlog_info ("Neighbor not yet Full");
hasso48454372004-05-18 19:14:52 +0000272
hasso6452df02004-08-15 05:52:07 +0000273 req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
274 lsa->header->adv_router, on->request_list);
275 if (req == NULL)
hasso48454372004-05-18 19:14:52 +0000276 {
hasso6452df02004-08-15 05:52:07 +0000277 if (IS_OSPF6_DEBUG_LSA (SEND))
278 zlog_info ("Not on request-list for this neighbor");
279 /* fall through */
280 }
281 else
282 {
283 /* If new LSA less recent, examin next neighbor */
284 if (ospf6_lsa_compare (lsa, req) > 0)
hasso48454372004-05-18 19:14:52 +0000285 {
hasso6452df02004-08-15 05:52:07 +0000286 if (IS_OSPF6_DEBUG_LSA (SEND))
287 zlog_info ("Requesting is newer, next neighbor");
288 continue;
289 }
hasso48454372004-05-18 19:14:52 +0000290
hasso6452df02004-08-15 05:52:07 +0000291 /* If the same instance, delete from request-list and
292 examin next neighbor */
293 if (ospf6_lsa_compare (lsa, req) == 0)
294 {
295 if (IS_OSPF6_DEBUG_LSA (SEND))
296 zlog_info ("Requesting the same, remove it, next neighbor");
297 ospf6_lsdb_remove (req, on->request_list);
298 continue;
299 }
hasso48454372004-05-18 19:14:52 +0000300
hasso6452df02004-08-15 05:52:07 +0000301 /* If the new LSA is more recent, delete from request-list */
302 if (ospf6_lsa_compare (lsa, req) < 0)
303 {
304 if (IS_OSPF6_DEBUG_LSA (SEND))
305 zlog_info ("Received is newer, remove requesting");
306 ospf6_lsdb_remove (req, on->request_list);
307 /* fall through */
hasso48454372004-05-18 19:14:52 +0000308 }
309 }
hasso48454372004-05-18 19:14:52 +0000310 }
311
hasso6452df02004-08-15 05:52:07 +0000312 /* (c) If the new LSA was received from this neighbor,
313 examin next neighbor */
314 if (from == on)
hasso48454372004-05-18 19:14:52 +0000315 {
hasso6452df02004-08-15 05:52:07 +0000316 if (IS_OSPF6_DEBUG_LSA (SEND))
317 zlog_info ("Received is from the neighbor, next neighbor");
318 continue;
hasso48454372004-05-18 19:14:52 +0000319 }
hasso6452df02004-08-15 05:52:07 +0000320
321 /* (d) add retrans-list, schedule retransmission */
322 if (IS_OSPF6_DEBUG_LSA (SEND))
323 zlog_info ("Add retrans-list of this neighbor");
324 ospf6_increment_retrans_count (lsa);
325 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
326 if (on->thread_send_lsupdate == NULL)
327 on->thread_send_lsupdate =
328 thread_add_event (master, ospf6_lsupdate_send_neighbor,
329 on, on->ospf6_if->rxmt_interval);
330 retrans_added++;
hasso48454372004-05-18 19:14:52 +0000331 }
332
hasso6452df02004-08-15 05:52:07 +0000333 /* (2) examin next interface if not added to retrans-list */
334 if (retrans_added == 0)
335 {
336 if (IS_OSPF6_DEBUG_LSA (SEND))
337 zlog_info ("No retransmission scheduled, next interface");
338 return;
339 }
340
341 /* (3) If the new LSA was received on this interface,
342 and it was from DR or BDR, examin next interface */
343 if (from && from->ospf6_if == oi &&
344 (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
345 {
346 if (IS_OSPF6_DEBUG_LSA (SEND))
347 zlog_info ("Received is from the I/F's DR or BDR, next interface");
348 return;
349 }
350
351 /* (4) If the new LSA was received on this interface,
352 and the interface state is BDR, examin next interface */
353 if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
354 {
355 if (IS_OSPF6_DEBUG_LSA (SEND))
356 zlog_info ("Received is from the I/F, itself BDR, next interface");
357 return;
358 }
359
360 /* (5) flood the LSA out the interface. */
361 if (IS_OSPF6_DEBUG_LSA (SEND))
362 zlog_info ("Schedule flooding for the interface");
363 if (if_is_broadcast (oi->interface))
364 {
365 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
366 if (oi->thread_send_lsupdate == NULL)
367 oi->thread_send_lsupdate =
368 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
369 }
370 else
371 {
372 /* reschedule retransmissions to all neighbors */
373 for (node = listhead (oi->neighbor_list); node; nextnode (node))
374 {
375 on = (struct ospf6_neighbor *) getdata (node);
376 THREAD_OFF (on->thread_send_lsupdate);
377 on->thread_send_lsupdate =
378 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
379 }
380 }
hasso48454372004-05-18 19:14:52 +0000381}
382
hasso6452df02004-08-15 05:52:07 +0000383void
384ospf6_flood_area (struct ospf6_neighbor *from,
385 struct ospf6_lsa *lsa, struct ospf6_area *oa)
386{
387 listnode node;
388 struct ospf6_interface *oi;
389
390 for (node = listhead (oa->if_list); node; nextnode (node))
391 {
392 oi = OSPF6_INTERFACE (getdata (node));
393
394 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
395 oi != OSPF6_INTERFACE (lsa->lsdb->data))
396 continue;
397
398#if 0
399 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
400 ospf6_is_interface_virtual_link (oi))
401 continue;
402#endif/*0*/
403
404 ospf6_flood_interface (from, lsa, oi);
405 }
406}
407
408void
409ospf6_flood_process (struct ospf6_neighbor *from,
410 struct ospf6_lsa *lsa, struct ospf6 *process)
411{
412 listnode node;
413 struct ospf6_area *oa;
414
415 for (node = listhead (process->area_list); node; nextnode (node))
416 {
417 oa = OSPF6_AREA (getdata (node));
418
419 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
420 oa != OSPF6_AREA (lsa->lsdb->data))
421 continue;
422 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
423 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
424 continue;
425
426 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
427 IS_AREA_STUB (oa))
428 continue;
429
430 ospf6_flood_area (from, lsa, oa);
431 }
432}
433
434void
435ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
436{
437 ospf6_flood_process (from, lsa, ospf6);
438}
439
440void
441ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
442{
443 listnode node;
444 struct ospf6_neighbor *on;
445 struct ospf6_lsa *rem;
446
447 for (node = listhead (oi->neighbor_list); node; nextnode (node))
448 {
449 on = OSPF6_NEIGHBOR (getdata (node));
450 rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
451 lsa->header->adv_router, on->retrans_list);
452 if (rem && ! ospf6_lsa_compare (rem, lsa))
453 {
454 if (IS_OSPF6_DEBUG_LSA (DATABASE))
455 zlog_info ("Remove %s from retrans_list of %s",
456 rem->name, on->name);
457 ospf6_decrement_retrans_count (rem);
458 ospf6_lsdb_remove (rem, on->retrans_list);
459 }
460 }
461}
462
463void
464ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
465{
466 listnode node;
467 struct ospf6_interface *oi;
468
469 for (node = listhead (oa->if_list); node; nextnode (node))
470 {
471 oi = OSPF6_INTERFACE (getdata (node));
472
473 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
474 oi != OSPF6_INTERFACE (lsa->lsdb->data))
475 continue;
476
477#if 0
478 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
479 ospf6_is_interface_virtual_link (oi))
480 continue;
481#endif/*0*/
482
483 ospf6_flood_clear_interface (lsa, oi);
484 }
485}
486
487void
488ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
489{
490 listnode node;
491 struct ospf6_area *oa;
492
493 for (node = listhead (process->area_list); node; nextnode (node))
494 {
495 oa = OSPF6_AREA (getdata (node));
496
497 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
498 oa != OSPF6_AREA (lsa->lsdb->data))
499 continue;
500 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
501 oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
502 continue;
503
504 if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
505 IS_AREA_STUB (oa))
506 continue;
507
508 ospf6_flood_clear_area (lsa, oa);
509 }
510}
511
512void
513ospf6_flood_clear (struct ospf6_lsa *lsa)
514{
515 ospf6_flood_clear_process (lsa, ospf6);
516}
517
518
hasso48454372004-05-18 19:14:52 +0000519/* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
520static void
521ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
522 struct ospf6_neighbor *from)
523{
524 struct ospf6_interface *oi;
525
526 assert (from && from->ospf6_if);
527 oi = from->ospf6_if;
528
529 /* LSA has been flood back out receiving interface.
530 No acknowledgement sent. */
531 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
532 {
533 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000534 zlog_info ("No acknowledgement (BDR & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000535 return;
536 }
537
538 /* LSA is more recent than database copy, but was not flooded
539 back out receiving interface. Delayed acknowledgement sent
540 if advertisement received from Designated Router,
541 otherwide do nothing. */
542 if (ismore_recent < 0)
543 {
hasso48454372004-05-18 19:14:52 +0000544 if (oi->drouter == from->router_id)
545 {
546 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000547 zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
hasso48454372004-05-18 19:14:52 +0000548 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000549 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
550 if (oi->thread_send_lsack == NULL)
551 oi->thread_send_lsack =
552 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
553 }
554 else
555 {
556 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000557 zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000558 }
559 return;
560 }
561
562 /* LSA is a duplicate, and was treated as an implied acknowledgement.
563 Delayed acknowledgement sent if advertisement received from
564 Designated Router, otherwise do nothing */
565 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
566 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
567 {
hasso48454372004-05-18 19:14:52 +0000568 if (oi->drouter == from->router_id)
569 {
570 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000571 zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
hasso48454372004-05-18 19:14:52 +0000572 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000573 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
574 if (oi->thread_send_lsack == NULL)
575 oi->thread_send_lsack =
576 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
577 }
578 else
579 {
580 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000581 zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
hasso48454372004-05-18 19:14:52 +0000582 }
583 return;
584 }
585
586 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
587 Direct acknowledgement sent */
588 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
589 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
590 {
591 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000592 zlog_info ("Direct acknowledgement (BDR & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000593 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
594 if (from->thread_send_lsack == NULL)
595 from->thread_send_lsack =
596 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
597 return;
598 }
599
600 /* LSA's LS age is equal to Maxage, and there is no current instance
601 of the LSA in the link state database, and none of router's
602 neighbors are in states Exchange or Loading */
603 /* Direct acknowledgement sent, but this case is handled in
604 early of ospf6_receive_lsa () */
605}
606
607static void
608ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
609 struct ospf6_neighbor *from)
610{
611 struct ospf6_interface *oi;
612
613 assert (from && from->ospf6_if);
614 oi = from->ospf6_if;
615
616 /* LSA has been flood back out receiving interface.
617 No acknowledgement sent. */
618 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
619 {
620 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000621 zlog_info ("No acknowledgement (AllOther & FloodBack)");
hasso48454372004-05-18 19:14:52 +0000622 return;
623 }
624
625 /* LSA is more recent than database copy, but was not flooded
626 back out receiving interface. Delayed acknowledgement sent. */
627 if (ismore_recent < 0)
628 {
629 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000630 zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
hasso48454372004-05-18 19:14:52 +0000631 /* Delayed acknowledgement */
hasso48454372004-05-18 19:14:52 +0000632 ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
633 if (oi->thread_send_lsack == NULL)
634 oi->thread_send_lsack =
635 thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
636 return;
637 }
638
639 /* LSA is a duplicate, and was treated as an implied acknowledgement.
640 No acknowledgement sent. */
641 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
642 CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
643 {
644 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000645 zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
hasso48454372004-05-18 19:14:52 +0000646 return;
647 }
648
649 /* LSA is a duplicate, and was not treated as an implied acknowledgement.
650 Direct acknowledgement sent */
651 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
652 ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
653 {
654 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000655 zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
hasso48454372004-05-18 19:14:52 +0000656 ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
657 if (from->thread_send_lsack == NULL)
658 from->thread_send_lsack =
659 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
660 return;
661 }
662
663 /* LSA's LS age is equal to Maxage, and there is no current instance
664 of the LSA in the link state database, and none of router's
665 neighbors are in states Exchange or Loading */
666 /* Direct acknowledgement sent, but this case is handled in
667 early of ospf6_receive_lsa () */
668}
669
670void
671ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
672 struct ospf6_neighbor *from)
673{
674 struct ospf6_interface *oi;
675
676 assert (from && from->ospf6_if);
677 oi = from->ospf6_if;
678
679 if (oi->state == OSPF6_INTERFACE_BDR)
680 ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
681 else
682 ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
683}
684
685/* RFC2328 section 13 (4):
686 if MaxAge LSA and if we have no instance, and no neighbor
687 is in states Exchange or Loading
688 returns 1 if match this case, else returns 0 */
689static int
hasso6452df02004-08-15 05:52:07 +0000690ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
hasso48454372004-05-18 19:14:52 +0000691{
hasso48454372004-05-18 19:14:52 +0000692 struct ospf6_neighbor *on;
hasso6452df02004-08-15 05:52:07 +0000693 struct ospf6_interface *oi;
694 struct ospf6_area *oa;
695 struct ospf6 *process = NULL;
696 listnode i, j, k;
hasso48454372004-05-18 19:14:52 +0000697 int count = 0;
698
699 if (! OSPF6_LSA_IS_MAXAGE (lsa))
700 return 0;
701
hasso48454372004-05-18 19:14:52 +0000702 if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso6452df02004-08-15 05:52:07 +0000703 lsa->header->adv_router, lsa->lsdb))
hasso48454372004-05-18 19:14:52 +0000704 return 0;
705
hasso6452df02004-08-15 05:52:07 +0000706 process = from->ospf6_if->area->ospf6;
707 for (i = listhead (process->area_list); i; nextnode (i))
hasso48454372004-05-18 19:14:52 +0000708 {
hasso6452df02004-08-15 05:52:07 +0000709 oa = OSPF6_AREA (getdata (i));
hasso48454372004-05-18 19:14:52 +0000710 for (j = listhead (oa->if_list); j; nextnode (j))
711 {
hasso6452df02004-08-15 05:52:07 +0000712 oi = OSPF6_INTERFACE (getdata (j));
713 for (k = listhead (oi->neighbor_list); k; nextnode (k))
714 {
715 on = OSPF6_NEIGHBOR (getdata (k));
716 if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
717 on->state == OSPF6_NEIGHBOR_LOADING)
718 count++;
719 }
hasso48454372004-05-18 19:14:52 +0000720 }
721 }
722
hasso48454372004-05-18 19:14:52 +0000723 if (count == 0)
724 return 1;
hasso48454372004-05-18 19:14:52 +0000725 return 0;
726}
727
728/* RFC2328 section 13 The Flooding Procedure */
729void
hasso6452df02004-08-15 05:52:07 +0000730ospf6_receive_lsa (struct ospf6_neighbor *from,
731 struct ospf6_lsa_header *lsa_header)
hasso48454372004-05-18 19:14:52 +0000732{
733 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
734 int ismore_recent;
735 unsigned short cksum;
hasso48454372004-05-18 19:14:52 +0000736
737 ismore_recent = 1;
hasso6452df02004-08-15 05:52:07 +0000738 assert (from);
hasso48454372004-05-18 19:14:52 +0000739
740 /* make lsa structure for received lsa */
741 new = ospf6_lsa_create (lsa_header);
742
743 if (IS_OSPF6_DEBUG_LSA (RECV))
744 {
745 zlog_info ("LSA Receive from %s", from->name);
746 ospf6_lsa_header_print (new);
747 }
748
hasso48454372004-05-18 19:14:52 +0000749 /* (1) LSA Checksum */
750 cksum = ntohs (new->header->checksum);
751 if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
752 {
753 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000754 zlog_info ("Wrong LSA Checksum, discard");
hasso48454372004-05-18 19:14:52 +0000755 ospf6_lsa_delete (new);
756 return;
757 }
758
hasso6452df02004-08-15 05:52:07 +0000759 /* (2) Examine the LSA's LS type.
760 RFC2470 3.5.1. Receiving Link State Update packets */
761 if (IS_AREA_STUB (from->ospf6_if->area) &&
762 OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
hasso48454372004-05-18 19:14:52 +0000763 {
764 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000765 zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
766 ospf6_lsa_delete (new);
767 return;
768 }
769
770 /* (3) LSA which have reserved scope is discarded
771 RFC2470 3.5.1. Receiving Link State Update packets */
772 /* Flooding scope check. LSAs with unknown scope are discarded here.
773 Set appropriate LSDB for the LSA */
774 switch (OSPF6_LSA_SCOPE (new->header->type))
775 {
776 case OSPF6_SCOPE_LINKLOCAL:
777 new->lsdb = from->ospf6_if->lsdb;
778 break;
779 case OSPF6_SCOPE_AREA:
780 new->lsdb = from->ospf6_if->area->lsdb;
781 break;
782 case OSPF6_SCOPE_AS:
783 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
784 break;
785 default:
786 if (IS_OSPF6_DEBUG_LSA (RECV))
787 zlog_info ("LSA has reserved scope, discard");
hasso48454372004-05-18 19:14:52 +0000788 ospf6_lsa_delete (new);
789 return;
790 }
791
792 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
793 is in states Exchange or Loading */
794 if (ospf6_is_maxage_lsa_drop (new, from))
795 {
796 /* log */
797 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000798 zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
hasso48454372004-05-18 19:14:52 +0000799
800 /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
hasso6452df02004-08-15 05:52:07 +0000801 ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
hasso48454372004-05-18 19:14:52 +0000802 if (from->thread_send_lsack == NULL)
803 from->thread_send_lsack =
804 thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
805
806 /* b) Discard */
hasso6452df02004-08-15 05:52:07 +0000807 ospf6_lsa_delete (new);
hasso48454372004-05-18 19:14:52 +0000808 return;
809 }
810
811 /* (5) */
812 /* lookup the same database copy in lsdb */
hasso48454372004-05-18 19:14:52 +0000813 old = ospf6_lsdb_lookup (new->header->type, new->header->id,
hasso6452df02004-08-15 05:52:07 +0000814 new->header->adv_router, new->lsdb);
hasso48454372004-05-18 19:14:52 +0000815 if (old)
816 {
817 ismore_recent = ospf6_lsa_compare (new, old);
818 if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
819 {
820 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000821 zlog_info ("Received is duplicated LSA");
hasso48454372004-05-18 19:14:52 +0000822 SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
823 }
824 }
825
826 /* if no database copy or received is more recent */
827 if (old == NULL || ismore_recent < 0)
828 {
829 /* in case we have no database copy */
830 ismore_recent = -1;
831
832 /* (a) MinLSArrival check */
833 if (old)
834 {
835 struct timeval now, res;
836 gettimeofday (&now, (struct timezone *) NULL);
837 timersub (&now, &old->installed, &res);
838 if (res.tv_sec < MIN_LS_ARRIVAL)
839 {
840 if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
hasso6452df02004-08-15 05:52:07 +0000841 zlog_info ("LSA can't be updated within MinLSArrival, discard");
hasso48454372004-05-18 19:14:52 +0000842 ospf6_lsa_delete (new);
843 return; /* examin next lsa */
844 }
845 }
846
hassoccb59b12004-08-25 09:10:37 +0000847 gettimeofday (&new->received, (struct timezone *) NULL);
848
hasso6452df02004-08-15 05:52:07 +0000849 if (IS_OSPF6_DEBUG_LSA (RECV))
850 zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
851
hasso48454372004-05-18 19:14:52 +0000852 /* (b) immediately flood and (c) remove from all retrans-list */
hassoccb59b12004-08-25 09:10:37 +0000853 /* Prevent self-originated LSA to be flooded. this is to make
854 reoriginated instance of the LSA not to be rejected by other routers
855 due to MinLSArrival. */
856 if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
857 ospf6_flood (from, new);
hasso6452df02004-08-15 05:52:07 +0000858
859 /* (c) Remove the current database copy from all neighbors' Link
860 state retransmission lists. */
861 /* XXX, flood_clear ? */
hasso48454372004-05-18 19:14:52 +0000862
863 /* (d), installing lsdb, which may cause routing
864 table calculation (replacing database copy) */
hasso6452df02004-08-15 05:52:07 +0000865 ospf6_install_lsa (new);
hasso48454372004-05-18 19:14:52 +0000866
867 /* (e) possibly acknowledge */
868 ospf6_acknowledge_lsa (new, ismore_recent, from);
869
hasso6452df02004-08-15 05:52:07 +0000870 /* (f) Self Originated LSA, section 13.4 */
871 if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
hasso48454372004-05-18 19:14:52 +0000872 {
hasso6452df02004-08-15 05:52:07 +0000873 /* Self-originated LSA (newer than ours) is received from
874 another router. We have to make a new instance of the LSA
hasso48454372004-05-18 19:14:52 +0000875 or have to flush this LSA. */
876 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000877 {
878 zlog_info ("Newer instance of the self-originated LSA");
879 zlog_info ("Schedule reorigination");
880 }
881 new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
hasso48454372004-05-18 19:14:52 +0000882 }
hasso6452df02004-08-15 05:52:07 +0000883
hasso48454372004-05-18 19:14:52 +0000884 return;
885 }
886
887 /* (6) if there is instance on sending neighbor's request list */
888 if (ospf6_lsdb_lookup (new->header->type, new->header->id,
889 new->header->adv_router, from->request_list))
890 {
891 /* if no database copy, should go above state (5) */
892 assert (old);
893
894 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000895 {
896 zlog_info ("Received is not newer, on the neighbor's request-list");
897 zlog_info ("BadLSReq, discard the received LSA");
898 }
hasso48454372004-05-18 19:14:52 +0000899
900 /* BadLSReq */
901 thread_add_event (master, bad_lsreq, from, 0);
902
903 ospf6_lsa_delete (new);
904 return;
905 }
906
907 /* (7) if neither one is more recent */
908 if (ismore_recent == 0)
909 {
910 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000911 zlog_info ("The same instance as database copy (neither recent)");
hasso48454372004-05-18 19:14:52 +0000912
913 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
914 rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
915 new->header->adv_router, from->retrans_list);
916 if (rem)
917 {
918 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000919 {
920 zlog_info ("It is on the neighbor's retrans-list.");
921 zlog_info ("Treat as an Implied acknowledgement");
922 }
hasso48454372004-05-18 19:14:52 +0000923 SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
hasso6452df02004-08-15 05:52:07 +0000924 ospf6_decrement_retrans_count (rem);
hasso48454372004-05-18 19:14:52 +0000925 ospf6_lsdb_remove (rem, from->retrans_list);
926 }
927
hasso6452df02004-08-15 05:52:07 +0000928 if (IS_OSPF6_DEBUG_LSA (RECV))
929 zlog_info ("Possibly acknowledge and then discard");
930
hasso48454372004-05-18 19:14:52 +0000931 /* (b) possibly acknowledge */
932 ospf6_acknowledge_lsa (new, ismore_recent, from);
933
934 ospf6_lsa_delete (new);
935 return;
936 }
937
938 /* (8) previous database copy is more recent */
939 {
940 assert (old);
941
942 /* If database copy is in 'Seqnumber Wrapping',
943 simply discard the received LSA */
944 if (OSPF6_LSA_IS_MAXAGE (old) &&
945 old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
946 {
947 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000948 {
949 zlog_info ("The LSA is in Seqnumber Wrapping");
950 zlog_info ("MaxAge & MaxSeqNum, discard");
951 }
hasso48454372004-05-18 19:14:52 +0000952 ospf6_lsa_delete (new);
953 return;
954 }
955
956 /* Otherwise, Send database copy of this LSA to this neighbor */
957 {
958 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso6452df02004-08-15 05:52:07 +0000959 {
960 zlog_info ("Database copy is more recent.");
961 zlog_info ("Send back directly and then discard");
962 }
hasso48454372004-05-18 19:14:52 +0000963
964 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
965
hasso48454372004-05-18 19:14:52 +0000966 ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
967 if (from->thread_send_lsupdate == NULL)
968 from->thread_send_lsupdate =
969 thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
970 ospf6_lsa_delete (new);
971 return;
972 }
973 return;
974 }
975}
976
977
978