blob: 915f0fa7f7a268c5fb12291a2d08b681f02e38b6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF Link State Advertisement
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "linklist.h"
26#include "prefix.h"
27#include "if.h"
28#include "table.h"
29#include "memory.h"
30#include "stream.h"
31#include "log.h"
32#include "thread.h"
33#include "hash.h"
34#include "sockunion.h" /* for inet_aton() */
35
36#include "ospfd/ospfd.h"
37#include "ospfd/ospf_interface.h"
38#include "ospfd/ospf_ism.h"
39#include "ospfd/ospf_asbr.h"
40#include "ospfd/ospf_lsa.h"
41#include "ospfd/ospf_lsdb.h"
42#include "ospfd/ospf_neighbor.h"
43#include "ospfd/ospf_nsm.h"
44#include "ospfd/ospf_flood.h"
45#include "ospfd/ospf_packet.h"
46#include "ospfd/ospf_spf.h"
47#include "ospfd/ospf_dump.h"
48#include "ospfd/ospf_route.h"
49#include "ospfd/ospf_ase.h"
50#include "ospfd/ospf_zebra.h"
51
52
53u_int32_t
54get_metric (u_char *metric)
55{
56 u_int32_t m;
57 m = metric[0];
58 m = (m << 8) + metric[1];
59 m = (m << 8) + metric[2];
60 return m;
61}
62
63
64struct timeval
65tv_adjust (struct timeval a)
66{
67 while (a.tv_usec >= 1000000)
68 {
69 a.tv_usec -= 1000000;
70 a.tv_sec++;
71 }
72
73 while (a.tv_usec < 0)
74 {
75 a.tv_usec += 1000000;
76 a.tv_sec--;
77 }
78
79 return a;
80}
81
82int
83tv_ceil (struct timeval a)
84{
85 a = tv_adjust (a);
86
87 return (a.tv_usec ? a.tv_sec + 1 : a.tv_sec);
88}
89
90int
91tv_floor (struct timeval a)
92{
93 a = tv_adjust (a);
94
95 return a.tv_sec;
96}
97
98struct timeval
99int2tv (int a)
100{
101 struct timeval ret;
102
103 ret.tv_sec = a;
104 ret.tv_usec = 0;
105
106 return ret;
107}
108
109struct timeval
110tv_add (struct timeval a, struct timeval b)
111{
112 struct timeval ret;
113
114 ret.tv_sec = a.tv_sec + b.tv_sec;
115 ret.tv_usec = a.tv_usec + b.tv_usec;
116
117 return tv_adjust (ret);
118}
119
120struct timeval
121tv_sub (struct timeval a, struct timeval b)
122{
123 struct timeval ret;
124
125 ret.tv_sec = a.tv_sec - b.tv_sec;
126 ret.tv_usec = a.tv_usec - b.tv_usec;
127
128 return tv_adjust (ret);
129}
130
131int
132tv_cmp (struct timeval a, struct timeval b)
133{
134 return (a.tv_sec == b.tv_sec ?
135 a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
136}
137
138int
139ospf_lsa_refresh_delay (struct ospf_lsa *lsa)
140{
141 struct timeval delta, now;
142 int delay = 0;
143
144 gettimeofday (&now, NULL);
145 delta = tv_sub (now, lsa->tv_orig);
146
147 if (tv_cmp (delta, int2tv (OSPF_MIN_LS_INTERVAL)) < 0)
148 {
149 delay = tv_ceil (tv_sub (int2tv (OSPF_MIN_LS_INTERVAL), delta));
150
151 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
152 zlog_info ("LSA[Type%d:%s]: Refresh timer delay %d seconds",
153 lsa->data->type, inet_ntoa (lsa->data->id), delay);
154
155 assert (delay > 0);
156 }
157
158 return delay;
159}
160
161
162int
163get_age (struct ospf_lsa *lsa)
164{
165 int age;
166 struct timeval now;
167
168 gettimeofday (&now, NULL);
169 age = ntohs (lsa->data->ls_age) + tv_floor (tv_sub (now, lsa->tv_recv));
170
171 return age;
172}
173
174
175/* Fletcher Checksum -- Refer to RFC1008. */
176#define MODX 4102
177#define LSA_CHECKSUM_OFFSET 15
178
179u_int16_t
180ospf_lsa_checksum (struct lsa_header *lsa)
181{
182 u_char *sp, *ep, *p, *q;
183 int c0 = 0, c1 = 0;
184 int x, y;
185 u_int16_t length;
186
187 lsa->checksum = 0;
188 length = ntohs (lsa->length) - 2;
189 sp = (char *) &lsa->options;
190
191 for (ep = sp + length; sp < ep; sp = q)
192 {
193 q = sp + MODX;
194 if (q > ep)
195 q = ep;
196 for (p = sp; p < q; p++)
197 {
198 c0 += *p;
199 c1 += c0;
200 }
201 c0 %= 255;
202 c1 %= 255;
203 }
204
205 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
206 if (x <= 0)
207 x += 255;
208 y = 510 - c0 - x;
209 if (y > 255)
210 y -= 255;
211
212 /* take care endian issue. */
213 lsa->checksum = htons ((x << 8) + y);
214
215 return (lsa->checksum);
216}
217
218
219
220/* Create OSPF LSA. */
221struct ospf_lsa *
222ospf_lsa_new ()
223{
224 struct ospf_lsa *new;
225
226 new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
227 memset (new, 0, sizeof (struct ospf_lsa));
228
229 new->flags = 0;
230 new->lock = 1;
231 new->retransmit_counter = 0;
232 gettimeofday (&new->tv_recv, NULL);
233 new->tv_orig = new->tv_recv;
234 new->refresh_list = -1;
235
236 return new;
237}
238
239/* Duplicate OSPF LSA. */
240struct ospf_lsa *
241ospf_lsa_dup (struct ospf_lsa *lsa)
242{
243 struct ospf_lsa *new;
244
245 if (lsa == NULL)
246 return NULL;
247
248 new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
249
250 memcpy (new, lsa, sizeof (struct ospf_lsa));
251 UNSET_FLAG (new->flags, OSPF_LSA_DISCARD);
252 new->lock = 1;
253 new->retransmit_counter = 0;
254 new->data = ospf_lsa_data_dup (lsa->data);
255
paulf2c80652002-12-13 21:44:27 +0000256 /* kevinm: Clear the refresh_list, otherwise there are going
257 to be problems when we try to remove the LSA from the
258 queue (which it's not a member of.)
259 XXX: Should we add the LSA to the refresh_list queue? */
260 new->refresh_list = -1;
261
262 if (IS_DEBUG_OSPF (lsa, LSA))
263 zlog_info ("LSA: duplicated %p (new: %p)", lsa, new);
264
paul718e3742002-12-13 20:15:29 +0000265 return new;
266}
267
268/* Free OSPF LSA. */
269void
270ospf_lsa_free (struct ospf_lsa *lsa)
271{
272 assert (lsa->lock == 0);
273
274 if (IS_DEBUG_OSPF (lsa, LSA))
275 zlog_info ("LSA: freed %p", lsa);
276
277 /* Delete LSA data. */
278 if (lsa->data != NULL)
279 ospf_lsa_data_free (lsa->data);
280
281 assert (lsa->refresh_list < 0);
282
283 memset (lsa, 0, sizeof (struct ospf_lsa));
284 XFREE (MTYPE_OSPF_LSA, lsa);
285}
286
287/* Lock LSA. */
288struct ospf_lsa *
289ospf_lsa_lock (struct ospf_lsa *lsa)
290{
291 lsa->lock++;
292 return lsa;
293}
294
295/* Unlock LSA. */
296void
297ospf_lsa_unlock (struct ospf_lsa *lsa)
298{
299 /* This is sanity check. */
300 if (!lsa)
301 return;
302
303 lsa->lock--;
304
305 assert (lsa->lock >= 0);
306
307 if (lsa->lock == 0)
308 {
309 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD));
310 ospf_lsa_free (lsa);
311 }
312}
313
314/* Check discard flag. */
315void
316ospf_lsa_discard (struct ospf_lsa *lsa)
317{
318 if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
319 {
320 SET_FLAG (lsa->flags, OSPF_LSA_DISCARD);
321 ospf_lsa_unlock (lsa);
322 }
323}
324
325/* Create LSA data. */
326struct lsa_header *
327ospf_lsa_data_new (size_t size)
328{
329 struct lsa_header *new;
330
331 new = (struct lsa_header *) XMALLOC (MTYPE_OSPF_LSA_DATA, size);
332 memset (new, 0, size);
333
334 return new;
335}
336
337/* Duplicate LSA data. */
338struct lsa_header *
339ospf_lsa_data_dup (struct lsa_header *lsah)
340{
341 struct lsa_header *new;
342
343 new = ospf_lsa_data_new (ntohs (lsah->length));
344 memcpy (new, lsah, ntohs (lsah->length));
345
346 return new;
347}
348
349/* Free LSA data. */
350void
351ospf_lsa_data_free (struct lsa_header *lsah)
352{
353 if (IS_DEBUG_OSPF (lsa, LSA))
354 zlog_info ("LSA[Type%d:%s]: data freed %p",
355 lsah->type, inet_ntoa (lsah->id), lsah);
356
357 XFREE (MTYPE_OSPF_LSA_DATA, lsah);
358}
359
360
361/* LSA general functions. */
362
363const char *
364dump_lsa_key (struct ospf_lsa *lsa)
365{
366 static char buf[] = {
367 "Type255,id(255.255.255.255),ar(255.255.255.255)",
368 };
369 struct lsa_header *lsah;
370
371 if (lsa != NULL && (lsah = lsa->data) != NULL)
372 {
373 char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN];
374 strcpy (id, inet_ntoa (lsah->id));
375 strcpy (ar, inet_ntoa (lsah->adv_router));
376
377 sprintf (buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar);
378 }
379 else
380 strcpy (buf, "NULL");
381
382 return buf;
383}
384
385u_int32_t
386lsa_seqnum_increment (struct ospf_lsa *lsa)
387{
388 u_int32_t seqnum;
389
390 seqnum = ntohl (lsa->data->ls_seqnum) + 1;
391
392 return htonl (seqnum);
393}
394
395void
396lsa_header_set (struct stream *s, u_char options,
paul68980082003-03-25 05:07:42 +0000397 u_char type, struct in_addr id, struct in_addr router_id)
paul718e3742002-12-13 20:15:29 +0000398{
399 struct lsa_header *lsah;
400
401 lsah = (struct lsa_header *) STREAM_DATA (s);
402
403 lsah->ls_age = htons (0);
404 lsah->options = options;
405 lsah->type = type;
406 lsah->id = id;
paul68980082003-03-25 05:07:42 +0000407 lsah->adv_router = router_id;
paul718e3742002-12-13 20:15:29 +0000408 lsah->ls_seqnum = htonl (OSPF_INITIAL_SEQUENCE_NUMBER);
409
410 ospf_output_forward (s, OSPF_LSA_HEADER_SIZE);
411}
412
paul68980082003-03-25 05:07:42 +0000413
paul718e3742002-12-13 20:15:29 +0000414/* router-LSA related functions. */
415/* Get router-LSA flags. */
416u_char
417router_lsa_flags (struct ospf_area *area)
418{
419 u_char flags;
420
paul68980082003-03-25 05:07:42 +0000421 flags = area->ospf->flags;
paul718e3742002-12-13 20:15:29 +0000422
423 /* Set virtual link flag. */
424 if (ospf_full_virtual_nbrs (area))
425 SET_FLAG (flags, ROUTER_LSA_VIRTUAL);
426 else
427 /* Just sanity check */
428 UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL);
429
430 /* Set Shortcut ABR behabiour flag. */
431 UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT);
paul68980082003-03-25 05:07:42 +0000432 if (area->ospf->abr_type == OSPF_ABR_SHORTCUT)
paul718e3742002-12-13 20:15:29 +0000433 if (!OSPF_IS_AREA_BACKBONE (area))
434 if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
paul68980082003-03-25 05:07:42 +0000435 area->ospf->backbone == NULL) ||
paul718e3742002-12-13 20:15:29 +0000436 area->shortcut_configured == OSPF_SHORTCUT_ENABLE)
437 SET_FLAG (flags, ROUTER_LSA_SHORTCUT);
438
439 /* ASBR can't exit in stub area. */
440 if (area->external_routing == OSPF_AREA_STUB)
paul942b6c12003-06-22 08:22:18 +0000441 UNSET_FLAG (flags, ROUTER_LSA_EXTERNAL);
442 /* If ASBR set External flag */
443 else if (IS_OSPF_ASBR (area->ospf))
444 SET_FLAG (flags, ROUTER_LSA_EXTERNAL);
445
446 /* Set ABR dependent flags */
447 if (IS_OSPF_ABR (area->ospf))
448 {
449 SET_FLAG (flags, ROUTER_LSA_BORDER);
450#ifdef HAVE_NSSA
451 /* If Area is NSSA and we are both ABR and unconditional translator,
452 * set Nt bit
453 */
454 SET_FLAG (flags, ROUTER_LSA_NT);
455#endif /* HAVE_NSSA */
456 }
paul718e3742002-12-13 20:15:29 +0000457
458 return flags;
459}
460
461/* Lookup neighbor other than myself.
462 And check neighbor count,
463 Point-to-Point link must have only 1 neighbor. */
464struct ospf_neighbor *
paul68980082003-03-25 05:07:42 +0000465ospf_nbr_lookup_ptop (struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +0000466{
paul718e3742002-12-13 20:15:29 +0000467 struct ospf_neighbor *nbr = NULL;
paul68980082003-03-25 05:07:42 +0000468 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000469
470 /* Search neighbor, there must be one of two nbrs. */
paul68980082003-03-25 05:07:42 +0000471 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
472 if ((nbr = rn->info))
473 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +0000474 if (nbr->state == NSM_Full)
paul68980082003-03-25 05:07:42 +0000475 {
476 route_unlock_node (rn);
477 break;
478 }
paul718e3742002-12-13 20:15:29 +0000479
480 /* PtoP link must have only 1 neighbor. */
paul68980082003-03-25 05:07:42 +0000481 if (ospf_nbr_count (oi, 0) > 1)
paul718e3742002-12-13 20:15:29 +0000482 zlog_warn ("Point-to-Point link has more than 1 neighobrs.");
483
484 return nbr;
485}
486
487/* Set a link information. */
488void
489link_info_set (struct stream *s, struct in_addr id,
490 struct in_addr data, u_char type, u_char tos, u_int16_t cost)
491{
492 /* TOS based routing is not supported. */
493 stream_put_ipv4 (s, id.s_addr); /* Link ID. */
494 stream_put_ipv4 (s, data.s_addr); /* Link Data. */
495 stream_putc (s, type); /* Link Type. */
496 stream_putc (s, tos); /* TOS = 0. */
497 stream_putw (s, cost); /* Link Cost. */
498}
499
500/* Describe Point-to-Point link. */
501int
502lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
503{
504 int links = 0;
505 struct ospf_neighbor *nbr;
506 struct in_addr id, mask;
507
508 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
509 zlog_info ("LSA[Type1]: Set link Point-to-Point");
510
paul68980082003-03-25 05:07:42 +0000511 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000512 if (nbr->state == NSM_Full)
513 {
514 /* For unnumbered point-to-point networks, the Link Data field
515 should specify the interface's MIB-II ifIndex value. */
516 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
517 LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
518 links++;
519 }
520
521 if (oi->connected->destination != NULL)
522 {
523 /* Option 1:
524 link_type = LSA_LINK_TYPE_STUB;
525 link_id = nbr->address.u.prefix4;
526 link_data.s_addr = 0xffffffff;
527 link_cost = o->output_cost; */
528
529 id.s_addr = oi->connected->destination->u.prefix4.s_addr;
530 mask.s_addr = 0xffffffff;
531 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
532 }
533 else
534 {
535 /* Option 2: We need to include link to a stub
536 network regardless of the state of the neighbor */
537 masklen2ip (oi->address->prefixlen, &mask);
538 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
539 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
540 }
541 links++;
542
543 return links;
544}
545
546/* Describe Broadcast Link. */
547int
548lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
549{
550 struct ospf_neighbor *dr;
551 struct in_addr id, mask;
552
553 /* Describe Type 3 Link. */
554 if (oi->state == ISM_Waiting)
555 {
556 masklen2ip (oi->address->prefixlen, &mask);
557 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
558 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
559 return 1;
560 }
561
562 dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
563 /* Describe Type 2 link. */
564 if (dr && (dr->state == NSM_Full ||
565 IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
paul68980082003-03-25 05:07:42 +0000566 ospf_nbr_count (oi, NSM_Full) > 0)
paul718e3742002-12-13 20:15:29 +0000567 {
568 link_info_set (s, DR (oi), oi->address->u.prefix4,
569 LSA_LINK_TYPE_TRANSIT, 0, oi->output_cost);
570 }
571 /* Describe type 3 link. */
572 else
573 {
574 masklen2ip (oi->address->prefixlen, &mask);
575 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
576 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
577 }
578 return 1;
579}
580
581int
582lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
583{
584 struct in_addr id, mask;
585
586 /* Describe Type 3 Link. */
587 if (oi->state != ISM_Loopback)
588 return 0;
589
590 mask.s_addr = 0xffffffff;
591 id.s_addr = oi->address->u.prefix4.s_addr;
592 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
593 return 1;
594}
595
596/* Describe Virtual Link. */
597int
598lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
599{
600 struct ospf_neighbor *nbr;
601
paul718e3742002-12-13 20:15:29 +0000602 if (oi->state == ISM_PointToPoint)
paul68980082003-03-25 05:07:42 +0000603 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000604 if (nbr->state == NSM_Full)
605 {
606 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
607 LSA_LINK_TYPE_VIRTUALLINK, 0, oi->output_cost);
608 return 1;
609 }
610
611 return 0;
612}
613
614#define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O)
615
paul7afa08d2002-12-13 20:59:45 +0000616/* this function add for support point-to-multipoint ,see rfc2328
61712.4.1.4.*/
618/* from "edward rrr" <edward_rrr@hotmail.com>
619 http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
paul68980082003-03-25 05:07:42 +0000620int
621lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
paul7afa08d2002-12-13 20:59:45 +0000622{
623 int links = 0;
624 struct route_node *rn;
625 struct ospf_neighbor *nbr = NULL;
626 struct in_addr id, mask;
627
628 mask.s_addr = 0xffffffff;
629 id.s_addr = oi->address->u.prefix4.s_addr;
630 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
631 links++;
632
paul1cc8f762003-04-05 19:34:32 +0000633 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
634 zlog_info ("PointToMultipoint: running ptomultip_set");
paul7afa08d2002-12-13 20:59:45 +0000635
636 /* Search neighbor, */
637 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
638 if ((nbr = rn->info) != NULL)
639 /* Ignore myself. */
paul68980082003-03-25 05:07:42 +0000640 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul7afa08d2002-12-13 20:59:45 +0000641 if (nbr->state == NSM_Full)
642
643 {
paul7afa08d2002-12-13 20:59:45 +0000644 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
645 LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
646 links++;
paul1cc8f762003-04-05 19:34:32 +0000647 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
648 zlog_info ("PointToMultipoint: set link to %s",
649 inet_ntoa(oi->address->u.prefix4));
paul7afa08d2002-12-13 20:59:45 +0000650 }
651
652 return links;
paul7afa08d2002-12-13 20:59:45 +0000653}
654
paul718e3742002-12-13 20:15:29 +0000655/* Set router-LSA link information. */
656int
657router_lsa_link_set (struct stream *s, struct ospf_area *area)
658{
659 listnode node;
660 int links = 0;
661
662 for (node = listhead (area->oiflist); node; node = nextnode (node))
663 {
664 struct ospf_interface *oi = node->data;
665 struct interface *ifp = oi->ifp;
666
667 /* Check interface is up, OSPF is enable. */
paul2e3b2e42002-12-13 21:03:13 +0000668 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000669 {
670 if (oi->state != ISM_Down)
671 {
672 /* Describe each link. */
673 switch (oi->type)
674 {
675 case OSPF_IFTYPE_POINTOPOINT:
676 links += lsa_link_ptop_set (s, oi);
677 break;
678 case OSPF_IFTYPE_BROADCAST:
679 links += lsa_link_broadcast_set (s, oi);
680 break;
681 case OSPF_IFTYPE_NBMA:
682 links += lsa_link_nbma_set (s, oi);
683 break;
684 case OSPF_IFTYPE_POINTOMULTIPOINT:
paul68980082003-03-25 05:07:42 +0000685 links += lsa_link_ptomp_set (s, oi);
paul718e3742002-12-13 20:15:29 +0000686 break;
687 case OSPF_IFTYPE_VIRTUALLINK:
688 links += lsa_link_virtuallink_set (s, oi);
689 break;
690 case OSPF_IFTYPE_LOOPBACK:
691 links += lsa_link_loopback_set (s, oi);
692 }
693 }
694 }
695 }
696
697 return links;
698}
699
700/* Set router-LSA body. */
701void
702ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
703{
704 unsigned long putp;
705 u_int16_t cnt;
706
707 /* Set flags. */
708 stream_putc (s, router_lsa_flags (area));
709
710 /* Set Zero fields. */
711 stream_putc (s, 0);
712
713 /* Keep pointer to # links. */
714 putp = s->putp;
715
716 /* Forward word */
717 stream_putw(s, 0);
718
719 /* Set all link information. */
720 cnt = router_lsa_link_set (s, area);
721
722 /* Set # of links here. */
723 stream_putw_at (s, putp, cnt);
724}
725
726/* Create new router-LSA. */
727struct ospf_lsa *
728ospf_router_lsa_new (struct ospf_area *area)
729{
paul68980082003-03-25 05:07:42 +0000730 struct ospf *ospf = area->ospf;
paul718e3742002-12-13 20:15:29 +0000731 struct stream *s;
732 struct lsa_header *lsah;
733 struct ospf_lsa *new;
734 int length;
735
736 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
737 zlog_info ("LSA[Type1]: Create router-LSA instance");
738
739 /* Create a stream for LSA. */
740 s = stream_new (OSPF_MAX_LSA_SIZE);
741 lsah = (struct lsa_header *) STREAM_DATA (s);
742
743#ifdef HAVE_NSSA
744 /* Set LSA common header fields. */
745 lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_NSSA_GET (area),
paul68980082003-03-25 05:07:42 +0000746 OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000747#else /* ! HAVE_NSSA */
748 /* Set LSA common header fields. */
749 lsa_header_set (s, LSA_OPTIONS_GET (area),
paul68980082003-03-25 05:07:42 +0000750 OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000751#endif /* HAVE_NSSA */
752
753 /* Set router-LSA body fields. */
754 ospf_router_lsa_body_set (s, area);
755
756 /* Set length. */
757 length = stream_get_endp (s);
758 lsah->length = htons (length);
759
760 /* Now, create OSPF LSA instance. */
761 new = ospf_lsa_new ();
762 new->area = area;
763 SET_FLAG (new->flags, OSPF_LSA_SELF);
764
765 /* Copy LSA data to store, discard stream. */
766 new->data = ospf_lsa_data_new (length);
767 memcpy (new->data, lsah, length);
768 stream_free (s);
769
770 return new;
771}
772
773/* Originate Router-LSA. */
774struct ospf_lsa *
775ospf_router_lsa_originate (struct ospf_area *area)
776{
777 struct ospf_lsa *new;
778
779 /* Create new router-LSA instance. */
780 new = ospf_router_lsa_new (area);
781
782 /* Sanity check. */
783 if (new->data->adv_router.s_addr == 0)
784 {
785 if (IS_DEBUG_OSPF_EVENT)
786 zlog_info ("LSA[Type1]: AdvRouter is 0, discard");
787 ospf_lsa_discard (new);
788 return NULL;
789 }
790
791 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +0000792 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000793
794 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +0000795 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +0000796
797 /* Flooding new LSA through area. */
798 ospf_flood_through_area (area, NULL, new);
799
800 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
801 {
802 zlog_info ("LSA[Type%d:%s]: Originate router-LSA %p",
803 new->data->type, inet_ntoa (new->data->id), new);
804 ospf_lsa_header_dump (new->data);
805 }
806
807 return new;
808}
809
810/* Refresh router-LSA. */
811struct ospf_lsa *
812ospf_router_lsa_refresh (struct ospf_lsa *lsa)
813{
814 struct ospf_area *area = lsa->area;
815 struct ospf_lsa *new;
816
817 /* Sanity check. */
818 assert (lsa->data);
819
820 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +0000821 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +0000822
823 /* Create new router-LSA instance. */
824 new = ospf_router_lsa_new (area);
825 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
826
paul68980082003-03-25 05:07:42 +0000827 ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000828
829 /* Flood LSA through area. */
830 ospf_flood_through_area (area, NULL, new);
831
832 /* Debug logging. */
833 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
834 {
835 zlog_info ("LSA[Type%d:%s]: router-LSA refresh",
836 new->data->type, inet_ntoa (new->data->id));
837 ospf_lsa_header_dump (new->data);
838 }
839
840 return NULL;
841}
842
843int
844ospf_router_lsa_timer (struct thread *t)
845{
846 struct ospf_area *area;
847
848 if (IS_DEBUG_OSPF_EVENT)
849 zlog_info ("Timer[router-LSA]: (router-LSA Refresh expire)");
850
851 area = THREAD_ARG (t);
852 area->t_router_lsa_self = NULL;
853
854 /* Now refresh router-LSA. */
855 if (area->router_lsa_self)
856 ospf_router_lsa_refresh (area->router_lsa_self);
857 /* Newly originate router-LSA. */
858 else
859 ospf_router_lsa_originate (area);
860
861 return 0;
862}
863
864void
865ospf_router_lsa_timer_add (struct ospf_area *area)
866{
867 /* Keep area's self-originated router-LSA. */
868 struct ospf_lsa *lsa = area->router_lsa_self;
869
870 /* Cancel previously scheduled router-LSA timer. */
871 if (area->t_router_lsa_self)
872 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
873 zlog_info ("LSA[Type1]: Cancel previous router-LSA timer");
874
875 OSPF_TIMER_OFF (area->t_router_lsa_self);
876
877 /* If router-LSA is originated previously, check the interval time. */
878 if (lsa)
879 {
880 int delay;
881 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
882 {
883 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
884 ospf_router_lsa_timer, delay);
885 return;
886 }
887 }
888
889 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
890 zlog_info ("LSA[Type1]: Scheduling router-LSA origination right away");
891
892 /* Immediately refresh router-LSA. */
893 OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);
894}
895
896int
paul68980082003-03-25 05:07:42 +0000897ospf_router_lsa_update_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000898{
paul68980082003-03-25 05:07:42 +0000899 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000900 listnode node;
901
902 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
903 zlog_info ("Timer[router-LSA Update]: (timer expire)");
904
paul68980082003-03-25 05:07:42 +0000905 ospf->t_router_lsa_update = NULL;
paul718e3742002-12-13 20:15:29 +0000906
paul68980082003-03-25 05:07:42 +0000907 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000908 {
909 struct ospf_area *area = getdata (node);
910 struct ospf_lsa *lsa = area->router_lsa_self;
911 struct router_lsa *rl;
912 char *area_str;
913
914 /* Keep Area ID string. */
915 area_str = AREA_NAME (area);
916
917 /* If LSA not exist in this Area, originate new. */
918 if (lsa == NULL)
919 {
920 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
921 zlog_info("LSA[Type1]: Create router-LSA for Area %s", area_str);
922
923 ospf_router_lsa_originate (area);
924 }
925 /* If router-ID is changed, Link ID must change.
926 First flush old LSA, then originate new. */
paul68980082003-03-25 05:07:42 +0000927 else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +0000928 {
929 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
930 zlog_info("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
931 lsa->data->type, inet_ntoa (lsa->data->id), area_str);
932 ospf_lsa_flush_area (lsa, area);
933 ospf_lsa_unlock (area->router_lsa_self);
934 area->router_lsa_self = NULL;
935
936 /* Refresh router-LSA, (not install) and flood through area. */
937 ospf_router_lsa_timer_add (area);
938 }
939 else
940 {
941 rl = (struct router_lsa *) lsa->data;
942 /* Refresh router-LSA, (not install) and flood through area. */
paul68980082003-03-25 05:07:42 +0000943 if (rl->flags != ospf->flags)
paul718e3742002-12-13 20:15:29 +0000944 ospf_router_lsa_timer_add (area);
945 }
946 }
947
948 return 0;
949}
950
951
952/* network-LSA related functions. */
953/* Originate Network-LSA. */
954void
955ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi)
956{
957 struct in_addr mask;
958 struct route_node *rn;
959 struct ospf_neighbor *nbr;
960
961 masklen2ip (oi->address->prefixlen, &mask);
962 stream_put_ipv4 (s, mask.s_addr);
963
964 /* The network-LSA lists those routers that are fully adjacent to
965 the Designated Router; each fully adjacent router is identified by
966 its OSPF Router ID. The Designated Router includes itself in this
967 list. RFC2328, Section 12.4.2 */
968
969 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
970 if ((nbr = rn->info) != NULL)
971 if (nbr->state == NSM_Full || nbr == oi->nbr_self)
972 stream_put_ipv4 (s, nbr->router_id.s_addr);
973}
974
975struct ospf_lsa *
976ospf_network_lsa_new (struct ospf_interface *oi)
977{
978 struct stream *s;
979 struct ospf_lsa *new;
980 struct lsa_header *lsah;
981 int length;
982
983 /* If there are no neighbours on this network (the net is stub),
984 the router does not originate network-LSA (see RFC 12.4.2) */
985 if (oi->full_nbrs == 0)
986 return NULL;
987
988 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
989 zlog_info ("LSA[Type2]: Create network-LSA instance");
990
991 /* Create new stream for LSA. */
992 s = stream_new (OSPF_MAX_LSA_SIZE);
993 lsah = (struct lsa_header *) STREAM_DATA (s);
994
995 lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)),
paul68980082003-03-25 05:07:42 +0000996 OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000997
998 /* Set network-LSA body fields. */
999 ospf_network_lsa_body_set (s, oi);
1000
1001 /* Set length. */
1002 length = stream_get_endp (s);
1003 lsah->length = htons (length);
1004
1005 /* Create OSPF LSA instance. */
1006 new = ospf_lsa_new ();
1007 new->area = oi->area;
1008 SET_FLAG (new->flags, OSPF_LSA_SELF);
1009
1010 /* Copy LSA to store. */
1011 new->data = ospf_lsa_data_new (length);
1012 memcpy (new->data, lsah, length);
1013 stream_free (s);
1014
1015 return new;
1016}
1017
1018/* Originate network-LSA. */
1019struct ospf_lsa *
1020ospf_network_lsa_originate (struct ospf_interface *oi)
1021{
1022 struct ospf_lsa *new;
1023
1024 /* Create new network-LSA instance. */
1025 new = ospf_network_lsa_new (oi);
1026 if (new == NULL)
1027 return NULL;
1028
1029 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001030 new = ospf_lsa_install (oi->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001031
1032 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001033 oi->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001034
1035 /* Flooding new LSA through area. */
1036 ospf_flood_through_area (oi->area, NULL, new);
1037
1038 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1039 {
1040 zlog_info ("LSA[Type%d:%s]: Originate network-LSA %p",
1041 new->data->type, inet_ntoa (new->data->id), new);
1042 ospf_lsa_header_dump (new->data);
1043 }
1044
1045 return new;
1046}
1047
1048int
1049ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
1050{
1051 struct ospf_area *area = lsa->area;
1052 struct ospf_lsa *new;
1053
1054 assert (lsa->data);
1055
1056 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00001057 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +00001058
1059 /* Create new network-LSA instance. */
1060 new = ospf_network_lsa_new (oi);
1061 if (new == NULL)
1062 return -1;
1063 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1064
paul68980082003-03-25 05:07:42 +00001065 ospf_lsa_install (area->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001066
1067 /* Flood LSA through aera. */
1068 ospf_flood_through_area (area, NULL, new);
1069
1070 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1071 {
1072 zlog_info ("LSA[Type%d:%s]: network-LSA refresh",
1073 new->data->type, inet_ntoa (new->data->id));
1074 ospf_lsa_header_dump (new->data);
1075 }
1076
1077 return 0;
1078}
1079
1080int
1081ospf_network_lsa_refresh_timer (struct thread *t)
1082{
1083 struct ospf_interface *oi;
1084
1085 oi = THREAD_ARG (t);
1086 oi->t_network_lsa_self = NULL;
1087
1088 if (oi->network_lsa_self)
1089 /* Now refresh network-LSA. */
1090 ospf_network_lsa_refresh (oi->network_lsa_self, oi);
1091 else
1092 /* Newly create network-LSA. */
1093 ospf_network_lsa_originate (oi);
1094
1095 return 0;
1096}
1097
1098void
1099ospf_network_lsa_timer_add (struct ospf_interface *oi)
1100{
1101 /* Keep interface's self-originated network-LSA. */
1102 struct ospf_lsa *lsa = oi->network_lsa_self;
1103
1104 /* Cancel previously schedules network-LSA timer. */
1105 if (oi->t_network_lsa_self)
1106 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1107 zlog_info ("LSA[Type2]: Cancel previous network-LSA timer");
1108 OSPF_TIMER_OFF (oi->t_network_lsa_self);
1109
1110 /* If network-LSA is originated previously, check the interval time. */
1111 if (lsa)
1112 {
1113 int delay;
1114 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
1115 {
1116 oi->t_network_lsa_self =
1117 thread_add_timer (master, ospf_network_lsa_refresh_timer,
1118 oi, delay);
1119 return;
1120 }
1121 }
1122
1123 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1124 zlog_info ("Scheduling network-LSA origination right away");
1125
1126 /* Immediately refresh network-LSA. */
1127 oi->t_network_lsa_self =
1128 thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);
1129}
1130
1131
1132void
1133stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
1134{
1135 u_int32_t metric;
1136 char *mp;
1137
1138 /* Put 0 metric. TOS metric is not supported. */
1139 metric = htonl (metric_value);
1140 mp = (char *) &metric;
1141 mp++;
1142 stream_put (s, mp, 3);
1143}
1144
1145/* summary-LSA related functions. */
1146void
1147ospf_summary_lsa_body_set (struct stream *s, struct prefix *p,
1148 u_int32_t metric)
1149{
1150 struct in_addr mask;
1151
1152 masklen2ip (p->prefixlen, &mask);
1153
1154 /* Put Network Mask. */
1155 stream_put_ipv4 (s, mask.s_addr);
1156
1157 /* Set # TOS. */
1158 stream_putc (s, (u_char) 0);
1159
1160 /* Set metric. */
1161 stream_put_ospf_metric (s, metric);
1162}
1163
1164struct ospf_lsa *
1165ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p,
1166 u_int32_t metric, struct in_addr id)
1167{
1168 struct stream *s;
1169 struct ospf_lsa *new;
1170 struct lsa_header *lsah;
1171 int length;
1172
1173 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1174 zlog_info ("LSA[Type3]: Create summary-LSA instance");
1175
1176 /* Create new stream for LSA. */
1177 s = stream_new (OSPF_MAX_LSA_SIZE);
1178 lsah = (struct lsa_header *) STREAM_DATA (s);
1179
paul68980082003-03-25 05:07:42 +00001180 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA,
1181 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001182
1183 /* Set summary-LSA body fields. */
1184 ospf_summary_lsa_body_set (s, p, metric);
1185
1186 /* Set length. */
1187 length = stream_get_endp (s);
1188 lsah->length = htons (length);
1189
1190 /* Create OSPF LSA instance. */
1191 new = ospf_lsa_new ();
1192 new->area = area;
1193 SET_FLAG (new->flags, OSPF_LSA_SELF);
1194
1195 /* Copy LSA to store. */
1196 new->data = ospf_lsa_data_new (length);
1197 memcpy (new->data, lsah, length);
1198 stream_free (s);
1199
1200 return new;
1201}
1202
1203/* Originate Summary-LSA. */
1204struct ospf_lsa *
1205ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1206 struct ospf_area *area)
1207{
1208 struct ospf_lsa *new;
1209 struct in_addr id;
1210
paul68980082003-03-25 05:07:42 +00001211 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001212
1213 /* Create new summary-LSA instance. */
1214 new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id);
1215
1216 /* Instlal LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001217 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001218
1219 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001220 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001221
1222 /* Flooding new LSA through area. */
1223 ospf_flood_through_area (area, NULL, new);
1224
1225 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1226 {
1227 zlog_info ("LSA[Type%d:%s]: Originate summary-LSA %p",
1228 new->data->type, inet_ntoa (new->data->id), new);
1229 ospf_lsa_header_dump (new->data);
1230 }
1231
1232 return new;
1233}
1234
1235struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001236ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001237{
1238 struct ospf_lsa *new;
1239 struct summary_lsa *sl;
1240 struct prefix p;
1241
1242 /* Sanity check. */
1243 assert (lsa->data);
1244
1245 sl = (struct summary_lsa *)lsa->data;
1246 p.prefixlen = ip_masklen (sl->mask);
1247 new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1248 sl->header.id);
1249
1250 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1251
1252 /* Re-calculate checksum. */
1253 ospf_lsa_checksum (new->data);
1254
paul68980082003-03-25 05:07:42 +00001255 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001256
1257 /* Flood LSA through AS. */
1258 ospf_flood_through_area (new->area, NULL, new);
1259
1260 /* Debug logging. */
1261 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1262 {
1263 zlog_info ("LSA[Type%d:%s]: summary-LSA refresh",
1264 new->data->type, inet_ntoa (new->data->id));
1265 ospf_lsa_header_dump (new->data);
1266 }
1267
1268 return new;
1269}
1270
1271
1272/* summary-ASBR-LSA related functions. */
1273void
1274ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p,
1275 u_int32_t metric)
1276{
1277 struct in_addr mask;
1278
1279 masklen2ip (p->prefixlen, &mask);
1280
1281 /* Put Network Mask. */
1282 stream_put_ipv4 (s, mask.s_addr);
1283
1284 /* Set # TOS. */
1285 stream_putc (s, (u_char) 0);
1286
1287 /* Set metric. */
1288 stream_put_ospf_metric (s, metric);
1289}
1290
1291struct ospf_lsa *
1292ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p,
1293 u_int32_t metric, struct in_addr id)
1294{
1295 struct stream *s;
1296 struct ospf_lsa *new;
1297 struct lsa_header *lsah;
1298 int length;
1299
1300 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1301 zlog_info ("LSA[Type3]: Create summary-LSA instance");
1302
1303 /* Create new stream for LSA. */
1304 s = stream_new (OSPF_MAX_LSA_SIZE);
1305 lsah = (struct lsa_header *) STREAM_DATA (s);
1306
paul68980082003-03-25 05:07:42 +00001307 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA,
1308 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001309
1310 /* Set summary-LSA body fields. */
1311 ospf_summary_asbr_lsa_body_set (s, p, metric);
1312
1313 /* Set length. */
1314 length = stream_get_endp (s);
1315 lsah->length = htons (length);
1316
1317 /* Create OSPF LSA instance. */
1318 new = ospf_lsa_new ();
1319 new->area = area;
1320 SET_FLAG (new->flags, OSPF_LSA_SELF);
1321
1322 /* Copy LSA to store. */
1323 new->data = ospf_lsa_data_new (length);
1324 memcpy (new->data, lsah, length);
1325 stream_free (s);
1326
1327 return new;
1328}
1329
1330/* Originate summary-ASBR-LSA. */
1331struct ospf_lsa *
1332ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1333 struct ospf_area *area)
1334{
1335 struct ospf_lsa *new;
1336 struct in_addr id;
1337
paul68980082003-03-25 05:07:42 +00001338 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001339
1340 /* Create new summary-LSA instance. */
1341 new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id);
1342
1343 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001344 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001345
1346 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001347 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001348
1349 /* Flooding new LSA through area. */
1350 ospf_flood_through_area (area, NULL, new);
1351
1352 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1353 {
1354 zlog_info ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p",
1355 new->data->type, inet_ntoa (new->data->id), new);
1356 ospf_lsa_header_dump (new->data);
1357 }
1358
1359 return new;
1360}
1361
1362struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001363ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct ospf_lsa *new;
1366 struct summary_lsa *sl;
1367 struct prefix p;
1368
1369 /* Sanity check. */
1370 assert (lsa->data);
1371
1372 sl = (struct summary_lsa *)lsa->data;
1373 p.prefixlen = ip_masklen (sl->mask);
1374 new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1375 sl->header.id);
1376
1377 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1378
1379 /* Re-calculate checksum. */
1380 ospf_lsa_checksum (new->data);
1381
paul68980082003-03-25 05:07:42 +00001382 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001383
1384 /* Flood LSA through area. */
1385 ospf_flood_through_area (new->area, NULL, new);
1386
1387 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1388 {
1389 zlog_info ("LSA[Type%d:%s]: summary-ASBR-LSA refresh",
1390 new->data->type, inet_ntoa (new->data->id));
1391 ospf_lsa_header_dump (new->data);
1392 }
1393
1394 return new;
1395}
1396
1397/* AS-external-LSA related functions. */
1398
1399/* Get nexthop for AS-external-LSAs. Return nexthop if its interface
1400 is connected, else 0*/
1401struct in_addr
paul68980082003-03-25 05:07:42 +00001402ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop)
paul718e3742002-12-13 20:15:29 +00001403{
1404 struct in_addr fwd;
1405 struct prefix nh;
paul718e3742002-12-13 20:15:29 +00001406 listnode n1;
1407
1408 fwd.s_addr = 0;
1409
1410 if (!nexthop.s_addr)
1411 return fwd;
1412
1413 /* Check whether nexthop is covered by OSPF network. */
1414 nh.family = AF_INET;
1415 nh.u.prefix4 = nexthop;
1416 nh.prefixlen = IPV4_MAX_BITLEN;
1417
paul68980082003-03-25 05:07:42 +00001418 for (n1 = listhead (ospf->oiflist); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00001419 {
1420 struct ospf_interface *oi = getdata (n1);
1421
paul2e3b2e42002-12-13 21:03:13 +00001422 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001423 if (oi->address->family == AF_INET)
1424 if (prefix_match (oi->address, &nh))
1425 return nexthop;
1426 }
1427
1428 return fwd;
1429}
1430
1431#ifdef HAVE_NSSA
1432/* NSSA-external-LSA related functions. */
1433
1434/* Get 1st IP connection for Forward Addr */
1435
1436struct in_addr
1437ospf_get_ip_from_ifp (struct ospf_interface *oi)
1438{
1439 struct in_addr fwd;
1440
1441 fwd.s_addr = 0;
1442
paul2e3b2e42002-12-13 21:03:13 +00001443 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001444 return oi->address->u.prefix4;
1445
1446 return fwd;
1447}
1448
1449/* Get 1st IP connection for Forward Addr */
1450struct in_addr
paulf2c80652002-12-13 21:44:27 +00001451ospf_get_nssa_ip (struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001452{
1453 struct in_addr fwd;
paulf2c80652002-12-13 21:44:27 +00001454 struct in_addr best_default;
paul718e3742002-12-13 20:15:29 +00001455 listnode n1;
1456
1457 fwd.s_addr = 0;
paulf2c80652002-12-13 21:44:27 +00001458 best_default.s_addr = 0;
paul718e3742002-12-13 20:15:29 +00001459
paul68980082003-03-25 05:07:42 +00001460 for (n1 = listhead (area->ospf->oiflist); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00001461 {
1462 struct ospf_interface *oi = getdata (n1);
1463
paul2e3b2e42002-12-13 21:03:13 +00001464 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001465 if (oi->area->external_routing == OSPF_AREA_NSSA)
paul68980082003-03-25 05:07:42 +00001466 if (oi->address && oi->address->family == AF_INET)
1467 {
1468 if (best_default.s_addr == 0)
1469 best_default = oi->address->u.prefix4;
1470 if (oi->area == area)
1471 return oi->address->u.prefix4;
paulf2c80652002-12-13 21:44:27 +00001472 }
paul718e3742002-12-13 20:15:29 +00001473 }
paulf2c80652002-12-13 21:44:27 +00001474 if (best_default.s_addr != 0)
1475 return best_default;
paul718e3742002-12-13 20:15:29 +00001476
paul68980082003-03-25 05:07:42 +00001477 if (best_default.s_addr != 0)
1478 return best_default;
1479
paul718e3742002-12-13 20:15:29 +00001480 return fwd;
1481}
1482#endif /* HAVE_NSSA */
1483
1484#define DEFAULT_DEFAULT_METRIC 20
1485#define DEFAULT_DEFAULT_ORIGINATE_METRIC 10
1486#define DEFAULT_DEFAULT_ALWAYS_METRIC 1
1487
1488#define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2
1489
1490int
paul68980082003-03-25 05:07:42 +00001491metric_type (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001492{
paul68980082003-03-25 05:07:42 +00001493 return (ospf->dmetric[src].type < 0 ?
1494 DEFAULT_METRIC_TYPE : ospf->dmetric[src].type);
paul718e3742002-12-13 20:15:29 +00001495}
1496
1497int
paul68980082003-03-25 05:07:42 +00001498metric_value (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001499{
paul68980082003-03-25 05:07:42 +00001500 if (ospf->dmetric[src].value < 0)
paul718e3742002-12-13 20:15:29 +00001501 {
1502 if (src == DEFAULT_ROUTE)
1503 {
paul68980082003-03-25 05:07:42 +00001504 if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA)
paul718e3742002-12-13 20:15:29 +00001505 return DEFAULT_DEFAULT_ORIGINATE_METRIC;
1506 else
1507 return DEFAULT_DEFAULT_ALWAYS_METRIC;
1508 }
paul68980082003-03-25 05:07:42 +00001509 else if (ospf->default_metric < 0)
paul718e3742002-12-13 20:15:29 +00001510 return DEFAULT_DEFAULT_METRIC;
1511 else
paul68980082003-03-25 05:07:42 +00001512 return ospf->default_metric;
paul718e3742002-12-13 20:15:29 +00001513 }
1514
paul68980082003-03-25 05:07:42 +00001515 return ospf->dmetric[src].value;
paul718e3742002-12-13 20:15:29 +00001516}
1517
1518/* Set AS-external-LSA body. */
1519void
paul68980082003-03-25 05:07:42 +00001520ospf_external_lsa_body_set (struct stream *s, struct external_info *ei,
1521 struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001522{
1523 struct prefix_ipv4 *p = &ei->p;
1524 struct in_addr mask, fwd_addr;
1525 u_int32_t mvalue;
1526 int mtype;
1527 int type;
1528
1529 /* Put Network Mask. */
1530 masklen2ip (p->prefixlen, &mask);
1531 stream_put_ipv4 (s, mask.s_addr);
1532
1533 /* If prefix is default, specify DEFAULT_ROUTE. */
1534 type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
1535
1536 mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001537 ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type);
paul718e3742002-12-13 20:15:29 +00001538
1539 mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001540 ROUTEMAP_METRIC (ei) : metric_value (ospf, type);
paul718e3742002-12-13 20:15:29 +00001541
1542 /* Put type of external metric. */
1543 stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0));
1544
1545 /* Put 0 metric. TOS metric is not supported. */
1546 stream_put_ospf_metric (s, mvalue);
1547
1548 /* Get forwarding address to nexthop if on the Connection List, else 0. */
paul68980082003-03-25 05:07:42 +00001549 fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop);
paul718e3742002-12-13 20:15:29 +00001550
1551 /* Put forwarding address. */
1552 stream_put_ipv4 (s, fwd_addr.s_addr);
1553
1554 /* Put route tag -- This value should be introduced from configuration. */
1555 stream_putl (s, 0);
1556}
1557
1558/* Create new external-LSA. */
1559struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00001560ospf_external_lsa_new (struct ospf *ospf,
1561 struct external_info *ei, struct in_addr *old_id)
paul718e3742002-12-13 20:15:29 +00001562{
1563 struct stream *s;
1564 struct lsa_header *lsah;
1565 struct ospf_lsa *new;
1566 struct in_addr id;
1567 int length;
1568
1569 if (ei == NULL)
1570 {
1571 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1572 zlog_warn ("LSA[Type5]: External info is NULL, could not originated");
1573 return NULL;
1574 }
1575
1576 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1577 zlog_info ("LSA[Type5]: Originate AS-external-LSA instance");
1578
1579 /* If old Link State ID is specified, refresh LSA with same ID. */
1580 if (old_id)
1581 id = *old_id;
1582 /* Get Link State with unique ID. */
1583 else
1584 {
paul68980082003-03-25 05:07:42 +00001585 id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p);
paul718e3742002-12-13 20:15:29 +00001586 if (id.s_addr == 0xffffffff)
1587 {
1588 /* Maybe Link State ID not available. */
1589 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1590 zlog_info ("LSA[Type5]: Link ID not available, can't originate");
1591 return NULL;
1592 }
1593 }
1594
1595 /* Create new stream for LSA. */
1596 s = stream_new (OSPF_MAX_LSA_SIZE);
1597 lsah = (struct lsa_header *) STREAM_DATA (s);
1598
1599 /* Set LSA common header fields. */
paul68980082003-03-25 05:07:42 +00001600 lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA,
1601 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001602
1603 /* Set AS-external-LSA body fields. */
paul68980082003-03-25 05:07:42 +00001604 ospf_external_lsa_body_set (s, ei, ospf);
paul718e3742002-12-13 20:15:29 +00001605
1606 /* Set length. */
1607 length = stream_get_endp (s);
1608 lsah->length = htons (length);
1609
1610 /* Now, create OSPF LSA instance. */
1611 new = ospf_lsa_new ();
1612 new->area = NULL;
1613 SET_FLAG (new->flags, OSPF_LSA_SELF|OSPF_LSA_APPROVED);
1614
1615 /* Copy LSA data to store, discard stream. */
1616 new->data = ospf_lsa_data_new (length);
1617 memcpy (new->data, lsah, length);
1618 stream_free (s);
1619
1620 return new;
1621}
1622
1623#ifdef HAVE_NSSA
paul718e3742002-12-13 20:15:29 +00001624/* As Type-7 */
1625void
paul68980082003-03-25 05:07:42 +00001626ospf_install_flood_nssa (struct ospf *ospf,
1627 struct ospf_lsa *lsa, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00001628{
1629 struct ospf_lsa *new2;
paul68980082003-03-25 05:07:42 +00001630 struct as_external_lsa *extlsa;
paulf2c80652002-12-13 21:44:27 +00001631 listnode node;
paul718e3742002-12-13 20:15:29 +00001632
1633 /* NSSA Originate or Refresh (If anyNSSA)
1634
1635 LSA is self-originated. And just installed as Type-5.
1636 Additionally, install as Type-7 LSDB for every attached NSSA.
1637
1638 P-Bit controls which ABR performs translation to outside world; If
1639 we are an ABR....do not set the P-bit, because we send the Type-5,
1640 not as the ABR Translator, but as the ASBR owner within the AS!
1641
1642 If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The
1643 elected ABR Translator will see the P-bit, Translate, and re-flood.
1644
1645 Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
1646 Type-5's to non-NSSA Areas. (it will also attempt a re-install) */
1647
paul68980082003-03-25 05:07:42 +00001648 for (node = listhead (ospf->areas); node; nextnode (node))
1649 {
1650 struct ospf_area *area = getdata (node);
hasso0c14ad82003-07-03 08:36:02 +00001651
1652 /* Don't install Type-7 LSA's into nonNSSA area */
1653 if (area->external_routing != OSPF_AREA_NSSA)
1654 continue;
paul718e3742002-12-13 20:15:29 +00001655
paul68980082003-03-25 05:07:42 +00001656 /* make lsa duplicate, lock=1 */
1657 new2 = ospf_lsa_dup (lsa);
1658 new2->area = area;
1659 new2->data->type = OSPF_AS_NSSA_LSA;
paul718e3742002-12-13 20:15:29 +00001660
paul68980082003-03-25 05:07:42 +00001661 /* set P-bit if not ABR */
paul020709f2003-04-04 02:44:16 +00001662 if (! IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001663 {
1664 SET_FLAG(new2->data->options, OSPF_OPTION_NP);
1665
1666 /* set non-zero FWD ADDR
1667
1668 draft-ietf-ospf-nssa-update-09.txt
1669
1670 if the network between the NSSA AS boundary router and the
1671 adjacent AS is advertised into OSPF as an internal OSPF route,
1672 the forwarding address should be the next op address as is cu
1673 currently done with type-5 LSAs. If the intervening network is
1674 not adversited into OSPF as an internal OSPF route and the
1675 type-7 LSA's P-bit is set a forwarding address should be
1676 selected from one of the router's active OSPF inteface addresses
1677 which belong to the NSSA. If no such addresses exist, then
1678 no type-7 LSA's with the P-bit set should originate from this
1679 router. */
1680
1681 /* kevinm: not updating lsa anymore, just new2 */
1682 extlsa = (struct as_external_lsa *)(new2->data);
1683
1684 if (extlsa->e[0].fwd_addr.s_addr == 0)
1685 extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */
paul718e3742002-12-13 20:15:29 +00001686
pauld7480322003-05-16 17:31:51 +00001687 if (extlsa->e[0].fwd_addr.s_addr == 0)
1688 {
1689 if (IS_DEBUG_OSPF_NSSA)
1690 zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
1691 ospf_lsa_discard(new2);
1692 return;
1693 }
paulf2c80652002-12-13 21:44:27 +00001694 }
paul68980082003-03-25 05:07:42 +00001695 /* Re-calculate checksum. */
1696 ospf_lsa_checksum (new2->data);
paul718e3742002-12-13 20:15:29 +00001697
paul68980082003-03-25 05:07:42 +00001698 /* install also as Type-7 */
1699 ospf_lsa_install (ospf, NULL, new2); /* Remove Old, Lock New = 2 */
1700
1701 /* will send each copy, lock=2+n */
1702 ospf_flood_through_as (ospf, NULL, new2); /* all attached NSSA's, no AS/STUBs */
1703 }
paul718e3742002-12-13 20:15:29 +00001704}
1705#endif /* HAVE_NSSA */
1706
1707int
1708is_prefix_default (struct prefix_ipv4 *p)
1709{
1710 struct prefix_ipv4 q;
1711
1712 q.family = AF_INET;
1713 q.prefix.s_addr = 0;
1714 q.prefixlen = 0;
1715
1716 return prefix_same ((struct prefix *) p, (struct prefix *) &q);
1717}
1718
1719/* Originate an AS-external-LSA, install and flood. */
1720struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00001721ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00001722{
1723 struct ospf_lsa *new;
1724
1725 /* Added for NSSA project....
1726
1727 External LSAs are originated in ASBRs as usual, but for NSSA systems.
1728 there is the global Type-5 LSDB and a Type-7 LSDB installed for
1729 every area. The Type-7's are flooded to every IR and every ABR; We
1730 install the Type-5 LSDB so that the normal "refresh" code operates
1731 as usual, and flag them as not used during ASE calculations. The
1732 Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding
1733 Address of non-zero.
1734
1735 If an ABR is the elected NSSA translator, following SPF and during
1736 the ABR task it will translate all the scanned Type-7's, with P-bit
1737 ON and not-self generated, and translate to Type-5's throughout the
1738 non-NSSA/STUB AS.
1739
1740 A difference in operation depends whether this ASBR is an ABR
1741 or not. If not an ABR, the P-bit is ON, to indicate that any
1742 elected NSSA-ABR can perform its translation.
1743
1744 If an ABR, the P-bit is OFF; No ABR will perform translation and
1745 this ASBR will flood the Type-5 LSA as usual.
1746
1747 For the case where this ASBR is not an ABR, the ASE calculations
1748 are based on the Type-5 LSDB; The Type-7 LSDB exists just to
1749 demonstrate to the user that there are LSA's that belong to any
1750 attached NSSA.
1751
1752 Finally, it just so happens that when the ABR is translating every
1753 Type-7 into Type-5, it installs it into the Type-5 LSDB as an
1754 approved Type-5 (translated from Type-7); at the end of translation
1755 if any Translated Type-5's remain unapproved, then they must be
1756 flushed from the AS.
1757
1758 */
1759
1760 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00001761 if (!ospf_redistribute_check (ospf, ei, NULL))
paul718e3742002-12-13 20:15:29 +00001762 return NULL;
1763
1764 /* Create new AS-external-LSA instance. */
paul68980082003-03-25 05:07:42 +00001765 if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL)
paul718e3742002-12-13 20:15:29 +00001766 {
1767 if (IS_DEBUG_OSPF_EVENT)
1768 zlog_info ("LSA[Type5:%s]: Could not originate AS-external-LSA",
1769 inet_ntoa (ei->p.prefix));
1770 return NULL;
1771 }
1772
1773 /* Install newly created LSA into Type-5 LSDB, lock = 1. */
paul68980082003-03-25 05:07:42 +00001774 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001775
1776 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001777 ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001778
1779 /* Flooding new LSA. only to AS (non-NSSA/STUB) */
paul68980082003-03-25 05:07:42 +00001780 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001781
1782#ifdef HAVE_NSSA
1783 /* If there is any attached NSSA, do special handling */
paul68980082003-03-25 05:07:42 +00001784 if (ospf->anyNSSA)
1785 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
paul718e3742002-12-13 20:15:29 +00001786#endif /* HAVE_NSSA */
1787
1788 /* Debug logging. */
1789 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1790 {
1791 zlog_info ("LSA[Type%d:%s]: Originate AS-external-LSA %p",
1792 new->data->type, inet_ntoa (new->data->id), new);
1793 ospf_lsa_header_dump (new->data);
1794 }
1795
1796 return new;
1797}
1798
1799/* Originate AS-external-LSA from external info with initial flag. */
1800int
paul68980082003-03-25 05:07:42 +00001801ospf_external_lsa_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001802{
paul68980082003-03-25 05:07:42 +00001803 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001804 struct route_node *rn;
1805 struct external_info *ei;
1806 struct route_table *rt;
paul68980082003-03-25 05:07:42 +00001807 int type = THREAD_VAL (thread);
paul718e3742002-12-13 20:15:29 +00001808
paul68980082003-03-25 05:07:42 +00001809 ospf->t_external_lsa = NULL;
paul718e3742002-12-13 20:15:29 +00001810
1811 /* Originate As-external-LSA from all type of distribute source. */
1812 if ((rt = EXTERNAL_INFO (type)))
1813 for (rn = route_top (rt); rn; rn = route_next (rn))
1814 if ((ei = rn->info) != NULL)
1815 if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p))
paul68980082003-03-25 05:07:42 +00001816 if (!ospf_external_lsa_originate (ospf, ei))
paul718e3742002-12-13 20:15:29 +00001817 zlog_warn ("LSA: AS-external-LSA was not originated.");
1818
1819 return 0;
1820}
1821
1822struct external_info *
paul020709f2003-04-04 02:44:16 +00001823ospf_default_external_info (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001824{
1825 int type;
1826 struct route_node *rn;
1827 struct prefix_ipv4 p;
1828
1829 p.family = AF_INET;
1830 p.prefix.s_addr = 0;
1831 p.prefixlen = 0;
1832
1833 /* First, lookup redistributed default route. */
1834 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
1835 if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF)
1836 {
1837 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
1838 if (rn != NULL)
1839 {
1840 route_unlock_node (rn);
1841 assert (rn->info);
paul68980082003-03-25 05:07:42 +00001842 if (ospf_redistribute_check (ospf, rn->info, NULL))
paul718e3742002-12-13 20:15:29 +00001843 return rn->info;
1844 }
1845 }
1846
1847 return NULL;
1848}
1849
1850int
paul68980082003-03-25 05:07:42 +00001851ospf_default_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001852{
1853 int *origin;
1854 struct prefix_ipv4 p;
1855 struct in_addr nexthop;
1856 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +00001857 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001858
paul020709f2003-04-04 02:44:16 +00001859 ospf = ospf_lookup ();
1860
paul718e3742002-12-13 20:15:29 +00001861 /* Get originate flags. */
paul68980082003-03-25 05:07:42 +00001862 origin = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001863
1864 p.family = AF_INET;
1865 p.prefix.s_addr = 0;
1866 p.prefixlen = 0;
1867
1868 if (*origin == DEFAULT_ORIGINATE_ALWAYS)
1869 {
1870 /* If there is no default route via redistribute,
1871 then originate AS-external-LSA with nexthop 0 (self). */
1872 nexthop.s_addr = 0;
1873 ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop);
1874 }
1875
paul020709f2003-04-04 02:44:16 +00001876 if ((ei = ospf_default_external_info (ospf)))
paul68980082003-03-25 05:07:42 +00001877 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00001878
1879 return 0;
1880}
1881
paul645878f2003-04-13 21:42:11 +00001882#ifdef HAVE_NSSA
1883/* Flush any NSSA LSAs for given prefix */
1884void
1885ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p)
1886{
1887 struct listnode *node;
1888 struct ospf_lsa *lsa;
1889 struct ospf_area *area;
1890
pauld7480322003-05-16 17:31:51 +00001891 for (node = listhead (ospf->areas); node; nextnode (node))
paul645878f2003-04-13 21:42:11 +00001892 {
pauld7480322003-05-16 17:31:51 +00001893 if (((area = getdata (node)) != NULL)
1894 && (area->external_routing == OSPF_AREA_NSSA))
1895 {
1896 if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix,
1897 ospf->router_id)))
1898 {
1899 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1900 zlog_warn ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB",
1901 inet_ntoa (p->prefix), p->prefixlen);
1902 continue;
1903 }
1904 ospf_ls_retransmit_delete_nbr_area (area, lsa);
1905 if (!IS_LSA_MAXAGE (lsa))
1906 {
1907 ospf_refresher_unregister_lsa (ospf, lsa);
1908 ospf_lsa_flush_area (lsa, area);
1909 }
1910 }
paul645878f2003-04-13 21:42:11 +00001911 }
1912}
1913#endif /* HAVE_NSSA */
1914
paul718e3742002-12-13 20:15:29 +00001915/* Flush an AS-external-LSA from LSDB and routing domain. */
1916void
paul68980082003-03-25 05:07:42 +00001917ospf_external_lsa_flush (struct ospf *ospf,
1918 u_char type, struct prefix_ipv4 *p,
paul718e3742002-12-13 20:15:29 +00001919 unsigned int ifindex, struct in_addr nexthop)
1920{
1921 struct ospf_lsa *lsa;
1922
1923 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1924 zlog_info ("LSA: Flushing AS-external-LSA %s/%d",
1925 inet_ntoa (p->prefix), p->prefixlen);
1926
1927 /* First lookup LSA from LSDB. */
paul68980082003-03-25 05:07:42 +00001928 if (!(lsa = ospf_external_info_find_lsa (ospf, p)))
paul718e3742002-12-13 20:15:29 +00001929 {
1930 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1931 zlog_warn ("LSA: There is no such AS-external-LSA %s/%d in LSDB",
1932 inet_ntoa (p->prefix), p->prefixlen);
1933 return;
1934 }
pauld7480322003-05-16 17:31:51 +00001935#ifdef HAVE_NSSA
1936 /* If LSA is selforiginated and there is NSSA area, flush
1937 * Type-7 LSA's at first. */
1938
1939 if (IS_LSA_SELF(lsa) && (ospf->anyNSSA))
1940 ospf_nssa_lsa_flush (ospf, p);
1941#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00001942
1943 /* Sweep LSA from Link State Retransmit List. */
paul68980082003-03-25 05:07:42 +00001944 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001945
1946 /* There must be no self-originated LSA in rtrs_external. */
1947#if 0
1948 /* Remove External route from Zebra. */
1949 ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);
1950#endif
1951
1952 if (!IS_LSA_MAXAGE (lsa))
1953 {
1954 /* Unregister LSA from Refresh queue. */
paul68980082003-03-25 05:07:42 +00001955 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001956
1957 /* Flush AS-external-LSA through AS. */
paul68980082003-03-25 05:07:42 +00001958 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001959 }
1960
1961 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1962 zlog_info ("ospf_external_lsa_flush(): stop");
1963}
1964
1965void
paul68980082003-03-25 05:07:42 +00001966ospf_external_lsa_refresh_default (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001967{
1968 struct prefix_ipv4 p;
1969 struct external_info *ei;
1970 struct ospf_lsa *lsa;
1971
1972 p.family = AF_INET;
1973 p.prefixlen = 0;
1974 p.prefix.s_addr = 0;
1975
paul020709f2003-04-04 02:44:16 +00001976 ei = ospf_default_external_info (ospf);
paul68980082003-03-25 05:07:42 +00001977 lsa = ospf_external_info_find_lsa (ospf, &p);
paul718e3742002-12-13 20:15:29 +00001978
1979 if (ei)
1980 {
1981 if (lsa)
1982 {
1983 if (IS_DEBUG_OSPF_EVENT)
1984 zlog_info ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa);
paul68980082003-03-25 05:07:42 +00001985 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00001986 }
1987 else
1988 {
1989 if (IS_DEBUG_OSPF_EVENT)
1990 zlog_info ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
paul68980082003-03-25 05:07:42 +00001991 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00001992 }
1993 }
1994 else
1995 {
1996 if (lsa)
1997 {
1998 if (IS_DEBUG_OSPF_EVENT)
1999 zlog_info ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
paul68980082003-03-25 05:07:42 +00002000 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002001 }
2002 }
2003}
2004
2005void
paul68980082003-03-25 05:07:42 +00002006ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force)
paul718e3742002-12-13 20:15:29 +00002007{
2008 struct route_node *rn;
2009 struct external_info *ei;
2010
2011 if (type != DEFAULT_ROUTE)
2012 if (EXTERNAL_INFO(type))
2013 /* Refresh each redistributed AS-external-LSAs. */
2014 for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
2015 if ((ei = rn->info))
2016 if (!is_prefix_default (&ei->p))
2017 {
2018 struct ospf_lsa *lsa;
2019
paul68980082003-03-25 05:07:42 +00002020 if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
2021 ospf_external_lsa_refresh (ospf, lsa, ei, force);
paul718e3742002-12-13 20:15:29 +00002022 else
paul68980082003-03-25 05:07:42 +00002023 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00002024 }
2025}
2026
2027/* Refresh AS-external-LSA. */
2028void
paul68980082003-03-25 05:07:42 +00002029ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
paul718e3742002-12-13 20:15:29 +00002030 struct external_info *ei, int force)
2031{
2032 struct ospf_lsa *new;
2033 int changed;
2034
2035 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00002036 if (!ospf_redistribute_check (ospf, ei, &changed))
paul718e3742002-12-13 20:15:29 +00002037 {
paul68980082003-03-25 05:07:42 +00002038 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
2039 ei->ifindex, ei->nexthop);
paul718e3742002-12-13 20:15:29 +00002040 return;
2041 }
2042
2043 if (!changed && !force)
2044 return;
2045
2046 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00002047 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002048
2049 /* Unregister AS-external-LSA from refresh-list. */
paul68980082003-03-25 05:07:42 +00002050 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002051
paul68980082003-03-25 05:07:42 +00002052 new = ospf_external_lsa_new (ospf, ei, &lsa->data->id);
paul718e3742002-12-13 20:15:29 +00002053
2054 if (new == NULL)
2055 {
2056 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2057 zlog_warn ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
2058 inet_ntoa (lsa->data->id));
2059 return;
2060 }
2061
2062 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
2063
2064 /* Record timestamp. */
2065 gettimeofday (&new->tv_orig, NULL);
2066
2067 /* Re-calculate checksum. */
2068 ospf_lsa_checksum (new->data);
2069
paul68980082003-03-25 05:07:42 +00002070 ospf_lsa_install (ospf, NULL, new); /* As type-5. */
paul718e3742002-12-13 20:15:29 +00002071
2072 /* Flood LSA through AS. */
paul68980082003-03-25 05:07:42 +00002073 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00002074
2075#ifdef HAVE_NSSA
2076 /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
paul68980082003-03-25 05:07:42 +00002077 if (ospf->anyNSSA)
2078 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */
paul718e3742002-12-13 20:15:29 +00002079#endif /* HAVE_NSSA */
2080
2081 /* Register slef-originated LSA to refresh queue. */
paul68980082003-03-25 05:07:42 +00002082 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002083
2084 /* Debug logging. */
2085 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2086 {
2087 zlog_info ("LSA[Type%d:%s]: AS-external-LSA refresh",
2088 new->data->type, inet_ntoa (new->data->id));
2089 ospf_lsa_header_dump (new->data);
2090 }
2091
2092 return;
2093}
2094
2095
2096/* LSA installation functions. */
2097
2098/* Install router-LSA to an area. */
2099struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002100ospf_router_lsa_install (struct ospf *ospf,
2101 struct ospf_lsa *new, int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002102{
2103 struct ospf_area *area = new->area;
2104
2105 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2106 The entire routing table must be recalculated, starting with
2107 the shortest path calculations for each area (not just the
2108 area whose link-state database has changed).
2109 */
2110 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002111 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002112
2113 if (IS_LSA_SELF (new))
2114 {
2115 /* Set router-LSA refresh timer. */
2116 OSPF_TIMER_OFF (area->t_router_lsa_self);
2117 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
2118 ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
2119
2120 /* Set self-originated router-LSA. */
2121 ospf_lsa_unlock (area->router_lsa_self);
2122 area->router_lsa_self = ospf_lsa_lock (new);
2123
2124 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2125 zlog_info("LSA[Type%d]: ID %s is self-originated",
2126 new->data->type, inet_ntoa (new->data->id));
2127 }
2128
2129 return new;
2130}
2131
2132#define OSPF_INTERFACE_TIMER_ON(T,F,V) \
2133 if (!(T)) \
2134 (T) = thread_add_timer (master, (F), oi, (V))
2135
2136/* Install network-LSA to an area. */
2137struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002138ospf_network_lsa_install (struct ospf *ospf,
2139 struct ospf_interface *oi,
paul718e3742002-12-13 20:15:29 +00002140 struct ospf_lsa *new,
2141 int rt_recalc)
2142{
2143
2144 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2145 The entire routing table must be recalculated, starting with
2146 the shortest path calculations for each area (not just the
2147 area whose link-state database has changed).
2148 */
2149 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002150 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002151
2152 /* We supposed that when LSA is originated by us, we pass the int
2153 for which it was originated. If LSA was received by flooding,
2154 the RECEIVED flag is set, so we do not link the LSA to the int. */
2155 if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
2156 {
2157 /* Set LSRefresh timer. */
2158 OSPF_TIMER_OFF (oi->t_network_lsa_self);
2159
2160 OSPF_INTERFACE_TIMER_ON (oi->t_network_lsa_self,
2161 ospf_network_lsa_refresh_timer,
2162 OSPF_LS_REFRESH_TIME);
2163
2164 ospf_lsa_unlock (oi->network_lsa_self);
2165 oi->network_lsa_self = ospf_lsa_lock (new);
2166 }
2167
2168 return new;
2169}
2170
2171/* Install summary-LSA to an area. */
2172struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002173ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2174 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002175{
paul718e3742002-12-13 20:15:29 +00002176 if (rt_recalc && !IS_LSA_SELF (new))
2177 {
2178 /* RFC 2328 Section 13.2 Summary-LSAs
2179 The best route to the destination described by the summary-
2180 LSA must be recalculated (see Section 16.5). If this
2181 destination is an AS boundary router, it may also be
2182 necessary to re-examine all the AS-external-LSAs.
2183 */
2184
2185#if 0
2186 /* This doesn't exist yet... */
2187 ospf_summary_incremental_update(new); */
2188#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002189 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002190#endif /* #if 0 */
2191
2192 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2193 zlog_info ("ospf_summary_lsa_install(): SPF scheduled");
2194 }
2195
2196 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002197 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002198
2199 return new;
2200}
2201
2202/* Install ASBR-summary-LSA to an area. */
2203struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002204ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2205 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002206{
2207 if (rt_recalc && !IS_LSA_SELF (new))
2208 {
2209 /* RFC 2328 Section 13.2 Summary-LSAs
2210 The best route to the destination described by the summary-
2211 LSA must be recalculated (see Section 16.5). If this
2212 destination is an AS boundary router, it may also be
2213 necessary to re-examine all the AS-external-LSAs.
2214 */
2215#if 0
2216 /* These don't exist yet... */
2217 ospf_summary_incremental_update(new);
2218 /* Isn't this done by the above call?
2219 - RFC 2328 Section 16.5 implies it should be */
2220 /* ospf_ase_calculate_schedule(); */
2221#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002222 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002223#endif /* #if 0 */
2224 }
2225
2226 /* register LSA to refresh-list. */
2227 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002228 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002229
2230 return new;
2231}
2232
2233/* Install AS-external-LSA. */
2234struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002235ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2236 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002237{
paul68980082003-03-25 05:07:42 +00002238 ospf_ase_register_external_lsa (new, ospf);
paul718e3742002-12-13 20:15:29 +00002239 /* If LSA is not self-originated, calculate an external route. */
2240 if (rt_recalc)
2241 {
2242 /* RFC 2328 Section 13.2 AS-external-LSAs
2243 The best route to the destination described by the AS-
2244 external-LSA must be recalculated (see Section 16.6).
2245 */
2246
2247 if (!IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002248 ospf_ase_incremental_update (ospf, new);
paul718e3742002-12-13 20:15:29 +00002249 }
2250
pauld7480322003-05-16 17:31:51 +00002251#ifdef HAVE_NSSA
2252 /* There is no point to register selforiginate Type-7 LSA for
2253 * refreshing. We rely on refreshing Type-5 LSA's */
2254 if (IS_LSA_SELF (new) && (new->data->type == OSPF_AS_NSSA_LSA))
2255 return new;
2256#endif /* HAVE_NSSA */
2257
paul718e3742002-12-13 20:15:29 +00002258 /* Register self-originated LSA to refresh queue. */
2259 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002260 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002261
2262 return new;
2263}
2264
2265void
paul68980082003-03-25 05:07:42 +00002266ospf_discard_from_db (struct ospf *ospf,
2267 struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002268{
2269 struct ospf_lsa *old;
2270
2271 old = ospf_lsdb_lookup (lsdb, lsa);
2272
2273 if (!old)
2274 return;
2275
2276 if (old->refresh_list >= 0)
paul68980082003-03-25 05:07:42 +00002277 ospf_refresher_unregister_lsa (ospf, old);
paul718e3742002-12-13 20:15:29 +00002278
2279 switch (old->data->type)
2280 {
2281 case OSPF_AS_EXTERNAL_LSA:
2282#ifdef HAVE_OPAQUE_LSA
2283 case OSPF_OPAQUE_AS_LSA:
2284#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002285 ospf_ls_retransmit_delete_nbr_as (ospf, old);
2286 ospf_ase_unregister_external_lsa (old, ospf);
paul718e3742002-12-13 20:15:29 +00002287 break;
pauld7480322003-05-16 17:31:51 +00002288#ifdef HAVE_NSSA
2289 case OSPF_AS_NSSA_LSA:
2290 ospf_ls_retransmit_delete_nbr_area (old->area, old);
2291 ospf_ase_unregister_external_lsa (old, ospf);
2292 break;
2293#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002294 default:
paul68980082003-03-25 05:07:42 +00002295 ospf_ls_retransmit_delete_nbr_area (old->area, old);
paul718e3742002-12-13 20:15:29 +00002296 break;
2297 }
2298
paul68980082003-03-25 05:07:42 +00002299 ospf_lsa_maxage_delete (ospf, old);
paul718e3742002-12-13 20:15:29 +00002300 ospf_lsa_discard (old);
2301}
2302
paul718e3742002-12-13 20:15:29 +00002303struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002304ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
2305 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002306{
2307 struct ospf_lsa *new = NULL;
2308 struct ospf_lsa *old = NULL;
2309 struct ospf_lsdb *lsdb = NULL;
2310 int rt_recalc;
2311
2312 /* Set LSDB. */
2313 switch (lsa->data->type)
2314 {
paul68980082003-03-25 05:07:42 +00002315#ifdef HAVE_NSSA
paulf2c80652002-12-13 21:44:27 +00002316 /* kevinm */
2317 case OSPF_AS_NSSA_LSA:
2318 if (lsa->area)
2319 lsdb = lsa->area->lsdb;
2320 else
paul68980082003-03-25 05:07:42 +00002321 lsdb = ospf->lsdb;
paulf2c80652002-12-13 21:44:27 +00002322 break;
paul68980082003-03-25 05:07:42 +00002323#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002324 case OSPF_AS_EXTERNAL_LSA:
2325#ifdef HAVE_OPAQUE_LSA
2326 case OSPF_OPAQUE_AS_LSA:
2327#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002328 lsdb = ospf->lsdb;
paul718e3742002-12-13 20:15:29 +00002329 break;
2330 default:
2331 lsdb = lsa->area->lsdb;
2332 break;
2333 }
2334
paul718e3742002-12-13 20:15:29 +00002335 assert (lsdb);
2336
2337 /* RFC 2328 13.2. Installing LSAs in the database
2338
2339 Installing a new LSA in the database, either as the result of
2340 flooding or a newly self-originated LSA, may cause the OSPF
2341 routing table structure to be recalculated. The contents of the
2342 new LSA should be compared to the old instance, if present. If
2343 there is no difference, there is no need to recalculate the
2344 routing table. When comparing an LSA to its previous instance,
2345 the following are all considered to be differences in contents:
2346
2347 o The LSA's Options field has changed.
2348
2349 o One of the LSA instances has LS age set to MaxAge, and
2350 the other does not.
2351
2352 o The length field in the LSA header has changed.
2353
2354 o The body of the LSA (i.e., anything outside the 20-byte
2355 LSA header) has changed. Note that this excludes changes
2356 in LS Sequence Number and LS Checksum.
2357
2358 */
2359 /* Look up old LSA and determine if any SPF calculation or incremental
2360 update is needed */
2361 old = ospf_lsdb_lookup (lsdb, lsa);
2362
2363 /* Do comparision and record if recalc needed. */
2364 rt_recalc = 0;
2365 if ( old == NULL || ospf_lsa_different(old, lsa))
2366 rt_recalc = 1;
2367
2368 /* discard old LSA from LSDB */
2369 if (old != NULL)
paul68980082003-03-25 05:07:42 +00002370 ospf_discard_from_db (ospf, lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002371
2372 /* Insert LSA to LSDB. */
2373 ospf_lsdb_add (lsdb, lsa);
2374 lsa->lsdb = lsdb;
2375
2376 /* Calculate Checksum if self-originated?. */
2377 if (IS_LSA_SELF (lsa))
2378 ospf_lsa_checksum (lsa->data);
2379
2380 /* Do LSA specific installation process. */
2381 switch (lsa->data->type)
2382 {
2383 case OSPF_ROUTER_LSA:
paul68980082003-03-25 05:07:42 +00002384 new = ospf_router_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002385 break;
2386 case OSPF_NETWORK_LSA:
2387 assert (oi);
paul68980082003-03-25 05:07:42 +00002388 new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002389 break;
2390 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002391 new = ospf_summary_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002392 break;
2393 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002394 new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002395 break;
2396 case OSPF_AS_EXTERNAL_LSA:
paul68980082003-03-25 05:07:42 +00002397 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002398 break;
2399#ifdef HAVE_OPAQUE_LSA
2400 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00002401 if (IS_LSA_SELF (lsa))
paul68980082003-03-25 05:07:42 +00002402 lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */
paul09e4efd2003-01-18 00:12:02 +00002403 else
paul68980082003-03-25 05:07:42 +00002404 ; /* Incoming "oi" for this LSA has set at LSUpd reception. */
paul09e4efd2003-01-18 00:12:02 +00002405 /* Fallthrough */
paul718e3742002-12-13 20:15:29 +00002406 case OSPF_OPAQUE_AREA_LSA:
2407 case OSPF_OPAQUE_AS_LSA:
2408 new = ospf_opaque_lsa_install (lsa, rt_recalc);
2409 break;
2410#endif /* HAVE_OPAQUE_LSA */
2411 default: /* NSSA, or type-6,8,9....nothing special */
2412#ifdef HAVE_NSSA
paul68980082003-03-25 05:07:42 +00002413 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002414#endif /* HAVE_NSSA */
2415 break;
2416 }
2417
2418 if (new == NULL)
2419 return new; /* Installation failed, cannot proceed further -- endo. */
2420
2421 /* Debug logs. */
2422 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2423 {
2424 char area_str[INET_ADDRSTRLEN];
2425
2426 switch (lsa->data->type)
2427 {
2428 case OSPF_AS_EXTERNAL_LSA:
2429#ifdef HAVE_OPAQUE_LSA
2430 case OSPF_OPAQUE_AS_LSA:
2431#endif /* HAVE_OPAQUE_LSA */
paulf2c80652002-12-13 21:44:27 +00002432#ifdef HAVE_NSSA
2433 case OSPF_AS_NSSA_LSA:
paul68980082003-03-25 05:07:42 +00002434#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002435 zlog_info ("LSA[%s]: Install %s",
2436 dump_lsa_key (new),
2437 LOOKUP (ospf_lsa_type_msg, new->data->type));
2438 break;
2439 default:
2440 strcpy (area_str, inet_ntoa (new->area->area_id));
2441 zlog_info ("LSA[%s]: Install %s to Area %s",
2442 dump_lsa_key (new),
2443 LOOKUP (ospf_lsa_type_msg, new->data->type), area_str);
2444 break;
2445 }
2446 }
2447
2448 /* If received LSA' ls_age is MaxAge, set LSA on MaxAge LSA list. */
2449 if (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new))
2450 {
2451 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2452 zlog_info ("LSA[Type%d:%s]: Install LSA, MaxAge",
2453 new->data->type, inet_ntoa (new->data->id));
paul68980082003-03-25 05:07:42 +00002454 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002455 }
2456
2457 return new;
2458}
2459
2460
2461int
paul68980082003-03-25 05:07:42 +00002462ospf_check_nbr_status (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002463{
2464 listnode node;
2465
paul68980082003-03-25 05:07:42 +00002466 for (node = listhead (ospf->oiflist); node; node = nextnode (node))
paul718e3742002-12-13 20:15:29 +00002467 {
2468 struct ospf_interface *oi = getdata (node);
2469 struct route_node *rn;
2470 struct ospf_neighbor *nbr;
2471
2472 if (ospf_if_is_enable (oi))
2473 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2474 if ((nbr = rn->info) != NULL)
2475 if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading)
2476 {
2477 route_unlock_node (rn);
2478 return 0;
2479 }
2480 }
2481
2482 return 1;
2483}
2484
2485
2486#ifdef ORIGINAL_CODING
2487/* This function flood the maxaged LSA to DR. */
2488void
2489ospf_maxage_flood (struct ospf_lsa *lsa)
2490{
2491 switch (lsa->data->type)
2492 {
2493 case OSPF_ROUTER_LSA:
2494 case OSPF_NETWORK_LSA:
2495 case OSPF_SUMMARY_LSA:
2496 case OSPF_ASBR_SUMMARY_LSA:
2497#ifdef HAVE_NSSA
2498 case OSPF_AS_NSSA_LSA:
2499#endif /* HAVE_NSSA */
2500#ifdef HAVE_OPAQUE_LSA
2501 case OSPF_OPAQUE_LINK_LSA:
2502 case OSPF_OPAQUE_AREA_LSA:
2503#endif /* HAVE_OPAQUE_LSA */
2504 ospf_flood_through_area (lsa->area, NULL, lsa);
2505 break;
2506 case OSPF_AS_EXTERNAL_LSA:
2507#ifdef HAVE_OPAQUE_LSA
2508 case OSPF_OPAQUE_AS_LSA:
2509#endif /* HAVE_OPAQUE_LSA */
2510 ospf_flood_through_as (NULL, lsa);
2511 break;
2512 default:
2513 break;
2514 }
2515}
2516#endif /* ORIGINAL_CODING */
2517
2518int
2519ospf_maxage_lsa_remover (struct thread *thread)
2520{
paul68980082003-03-25 05:07:42 +00002521 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00002522 listnode node;
2523 listnode next;
2524 int reschedule = 0;
2525
paul68980082003-03-25 05:07:42 +00002526 ospf->t_maxage = NULL;
paul718e3742002-12-13 20:15:29 +00002527
2528 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2529 zlog_info ("LSA[MaxAge]: remover Start");
2530
paul68980082003-03-25 05:07:42 +00002531 reschedule = !ospf_check_nbr_status (ospf);
paul718e3742002-12-13 20:15:29 +00002532
2533 if (!reschedule)
paul68980082003-03-25 05:07:42 +00002534 for (node = listhead (ospf->maxage_lsa); node; node = next)
paul718e3742002-12-13 20:15:29 +00002535 {
2536 struct ospf_lsa *lsa = getdata (node);
2537 next = node->next;
2538
2539 if (lsa->retransmit_counter > 0)
2540 {
2541 reschedule = 1;
2542 continue;
2543 }
2544
2545 /* Remove LSA from the LSDB */
2546 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
2547 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2548 zlog_info ("LSA[Type%d:%s]: This LSA is self-originated: ",
2549 lsa->data->type, inet_ntoa (lsa->data->id));
2550
2551 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2552 zlog_info ("LSA[Type%d:%s]: MaxAge LSA removed from list",
2553 lsa->data->type, inet_ntoa (lsa->data->id));
2554
2555 /* Flood max age LSA. */
2556#ifdef ORIGINAL_CODING
2557 ospf_maxage_flood (lsa);
2558#else /* ORIGINAL_CODING */
paul68980082003-03-25 05:07:42 +00002559 ospf_flood_through (ospf, NULL, lsa);
paul718e3742002-12-13 20:15:29 +00002560#endif /* ORIGINAL_CODING */
2561
2562 /* Remove from lsdb. */
paul68980082003-03-25 05:07:42 +00002563 ospf_discard_from_db (ospf, lsa->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002564 ospf_lsdb_delete (lsa->lsdb, lsa);
2565 }
2566
2567 /* A MaxAge LSA must be removed immediately from the router's link
2568 state database as soon as both a) it is no longer contained on any
2569 neighbor Link state retransmission lists and b) none of the router's
2570 neighbors are in states Exchange or Loading. */
2571 if (reschedule)
paul68980082003-03-25 05:07:42 +00002572 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002573
2574 return 0;
2575}
2576
2577int
paul68980082003-03-25 05:07:42 +00002578ospf_lsa_maxage_exist (struct ospf *ospf, struct ospf_lsa *new)
paul718e3742002-12-13 20:15:29 +00002579{
2580 listnode node;
2581
paul68980082003-03-25 05:07:42 +00002582 for (node = listhead (ospf->maxage_lsa); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00002583 if (((struct ospf_lsa *) node->data) == new)
2584 return 1;
2585
2586 return 0;
2587}
2588
2589void
paul68980082003-03-25 05:07:42 +00002590ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002591{
2592 listnode n;
2593
paul68980082003-03-25 05:07:42 +00002594 if ((n = listnode_lookup (ospf->maxage_lsa, lsa)))
paul718e3742002-12-13 20:15:29 +00002595 {
paul68980082003-03-25 05:07:42 +00002596 list_delete_node (ospf->maxage_lsa, n);
paul718e3742002-12-13 20:15:29 +00002597 ospf_lsa_unlock (lsa);
2598 }
2599}
2600
2601void
paul68980082003-03-25 05:07:42 +00002602ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002603{
2604 /* When we saw a MaxAge LSA flooded to us, we put it on the list
2605 and schedule the MaxAge LSA remover. */
paul68980082003-03-25 05:07:42 +00002606 if (ospf_lsa_maxage_exist (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00002607 {
2608 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2609 zlog_info ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list",
2610 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
2611 return;
2612 }
2613
paul68980082003-03-25 05:07:42 +00002614 listnode_add (ospf->maxage_lsa, ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00002615
2616 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2617 zlog_info ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
2618
paul68980082003-03-25 05:07:42 +00002619 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002620}
2621
2622int
paul68980082003-03-25 05:07:42 +00002623ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002624{
2625#ifdef HAVE_NSSA
2626 /* Stay away from any Local Translated Type-7 LSAs */
2627 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
2628 return 0;
2629#endif /* HAVE_NSSA */
2630
2631 if (IS_LSA_MAXAGE (lsa))
2632 /* Self-originated LSAs should NOT time-out instead,
2633 they're flushed and submitted to the max_age list explicitly. */
paul68980082003-03-25 05:07:42 +00002634 if (!ospf_lsa_is_self_originated (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00002635 {
2636 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2637 zlog_info("LSA[%s]: is MaxAge", dump_lsa_key (lsa));
2638
2639 switch (lsa->data->type)
2640 {
paul718e3742002-12-13 20:15:29 +00002641#ifdef HAVE_OPAQUE_LSA
paul37163d62003-02-03 18:40:56 +00002642 case OSPF_OPAQUE_LINK_LSA:
2643 case OSPF_OPAQUE_AREA_LSA:
paul718e3742002-12-13 20:15:29 +00002644 case OSPF_OPAQUE_AS_LSA:
paul09e4efd2003-01-18 00:12:02 +00002645 /*
2646 * As a general rule, whenever network topology has changed
2647 * (due to an LSA removal in this case), routing recalculation
2648 * should be triggered. However, this is not true for opaque
2649 * LSAs. Even if an opaque LSA instance is going to be removed
2650 * from the routing domain, it does not mean a change in network
2651 * topology, and thus, routing recalculation is not needed here.
2652 */
2653 break;
paul718e3742002-12-13 20:15:29 +00002654#endif /* HAVE_OPAQUE_LSA */
paul09e4efd2003-01-18 00:12:02 +00002655 case OSPF_AS_EXTERNAL_LSA:
paul68980082003-03-25 05:07:42 +00002656#ifdef HAVE_NSSA
2657 case OSPF_AS_NSSA_LSA:
2658#endif /* HAVE_NSSA */
2659 ospf_ase_incremental_update (ospf, lsa);
2660 break;
paul718e3742002-12-13 20:15:29 +00002661 default:
paul68980082003-03-25 05:07:42 +00002662 ospf_spf_calculate_schedule (ospf);
2663 break;
paul718e3742002-12-13 20:15:29 +00002664 }
paul68980082003-03-25 05:07:42 +00002665 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002666 }
2667
2668 return 0;
2669}
2670
2671/* Periodical check of MaxAge LSA. */
2672int
paul68980082003-03-25 05:07:42 +00002673ospf_lsa_maxage_walker (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00002674{
paul68980082003-03-25 05:07:42 +00002675 struct ospf *ospf = THREAD_ARG (thread);
2676 struct route_node *rn;
2677 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +00002678 listnode node;
2679
paul68980082003-03-25 05:07:42 +00002680 ospf->t_maxage_walker = NULL;
paul718e3742002-12-13 20:15:29 +00002681
paul68980082003-03-25 05:07:42 +00002682 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00002683 {
2684 struct ospf_area *area = node->data;
2685
paul68980082003-03-25 05:07:42 +00002686 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
2687 ospf_lsa_maxage_walker_remover (ospf, lsa);
2688 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
2689 ospf_lsa_maxage_walker_remover (ospf, lsa);
2690 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
2691 ospf_lsa_maxage_walker_remover (ospf, lsa);
2692 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
2693 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002694#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002695 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2696 ospf_lsa_maxage_walker_remover (ospf, lsa);
2697 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2698 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002699#endif /* HAVE_OPAQUE_LSA */
paul4fb949e2003-05-10 20:06:51 +00002700#ifdef HAVE_NSSA
2701 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
2702 ospf_lsa_maxage_walker_remover (ospf, lsa);
2703#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002704 }
2705
paul4fb949e2003-05-10 20:06:51 +00002706 /* for AS-external-LSAs. */
paul68980082003-03-25 05:07:42 +00002707 if (ospf->lsdb)
2708 {
2709 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
2710 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002711#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002712 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
2713 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002714#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002715 }
paul718e3742002-12-13 20:15:29 +00002716
paul68980082003-03-25 05:07:42 +00002717 OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker,
2718 OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +00002719 return 0;
2720}
2721
paul68980082003-03-25 05:07:42 +00002722struct ospf_lsa *
2723ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type,
2724 struct prefix_ipv4 *p, struct in_addr router_id)
paul718e3742002-12-13 20:15:29 +00002725{
paul68980082003-03-25 05:07:42 +00002726 struct ospf_lsa *lsa;
2727 struct in_addr mask, id;
2728 struct lsa_header_mask
2729 {
2730 struct lsa_header header;
2731 struct in_addr mask;
2732 } *hmask;
paul718e3742002-12-13 20:15:29 +00002733
paul68980082003-03-25 05:07:42 +00002734 lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id);
2735 if (lsa == NULL)
2736 return NULL;
paul718e3742002-12-13 20:15:29 +00002737
paul68980082003-03-25 05:07:42 +00002738 masklen2ip (p->prefixlen, &mask);
paul718e3742002-12-13 20:15:29 +00002739
paul68980082003-03-25 05:07:42 +00002740 hmask = (struct lsa_header_mask *) lsa->data;
paul718e3742002-12-13 20:15:29 +00002741
paul68980082003-03-25 05:07:42 +00002742 if (mask.s_addr != hmask->mask.s_addr)
2743 {
2744 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
2745 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id);
2746 if (!lsa)
2747 return NULL;
2748 }
paul718e3742002-12-13 20:15:29 +00002749
paul68980082003-03-25 05:07:42 +00002750 return lsa;
paul718e3742002-12-13 20:15:29 +00002751}
2752
2753struct ospf_lsa *
2754ospf_lsa_lookup (struct ospf_area *area, u_int32_t type,
2755 struct in_addr id, struct in_addr adv_router)
2756{
paule05fba42003-04-13 20:20:53 +00002757 struct ospf *ospf = ospf_lookup();
2758 assert(ospf);
2759
paul718e3742002-12-13 20:15:29 +00002760 switch (type)
2761 {
2762 case OSPF_ROUTER_LSA:
2763 case OSPF_NETWORK_LSA:
2764 case OSPF_SUMMARY_LSA:
2765 case OSPF_ASBR_SUMMARY_LSA:
2766#ifdef HAVE_NSSA
2767 case OSPF_AS_NSSA_LSA:
2768#endif /* HAVE_NSSA */
2769#ifdef HAVE_OPAQUE_LSA
2770 case OSPF_OPAQUE_LINK_LSA:
2771 case OSPF_OPAQUE_AREA_LSA:
2772#endif /* HAVE_OPAQUE_LSA */
2773 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router);
2774 break;
2775 case OSPF_AS_EXTERNAL_LSA:
2776#ifdef HAVE_OPAQUE_LSA
2777 case OSPF_OPAQUE_AS_LSA:
2778#endif /* HAVE_OPAQUE_LSA */
paule05fba42003-04-13 20:20:53 +00002779 return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router);
paul718e3742002-12-13 20:15:29 +00002780 break;
2781 default:
2782 break;
2783 }
2784
2785 return NULL;
2786}
2787
2788struct ospf_lsa *
2789ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type,
2790 struct in_addr id)
2791{
2792 struct ospf_lsa *lsa;
2793 struct route_node *rn;
2794
2795 switch (type)
2796 {
2797 case OSPF_ROUTER_LSA:
2798 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
2799 break;
2800 case OSPF_NETWORK_LSA:
2801 for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn))
2802 if ((lsa = rn->info))
2803 if (IPV4_ADDR_SAME (&lsa->data->id, &id))
2804 {
2805 route_unlock_node (rn);
2806 return lsa;
2807 }
2808 break;
2809 case OSPF_SUMMARY_LSA:
2810 case OSPF_ASBR_SUMMARY_LSA:
2811 /* Currently not used. */
2812 assert (1);
2813 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
2814 break;
2815 case OSPF_AS_EXTERNAL_LSA:
2816#ifdef HAVE_OPAQUE_LSA
2817 case OSPF_OPAQUE_LINK_LSA:
2818 case OSPF_OPAQUE_AREA_LSA:
2819 case OSPF_OPAQUE_AS_LSA:
2820 /* Currently not used. */
2821 break;
2822#endif /* HAVE_OPAQUE_LSA */
2823 default:
2824 break;
2825 }
2826
2827 return NULL;
2828}
2829
2830struct ospf_lsa *
2831ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah)
2832{
2833 struct ospf_lsa *match;
2834
2835#ifdef HAVE_OPAQUE_LSA
2836 /*
2837 * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11)
2838 * is redefined to have two subfields; opaque-type and opaque-id.
2839 * However, it is harmless to treat the two sub fields together, as if
2840 * they two were forming a unique LSA-ID.
2841 */
2842#endif /* HAVE_OPAQUE_LSA */
2843
2844 match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router);
2845
2846 if (match == NULL)
2847 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
2848 zlog_info ("LSA[Type%d:%s]: Lookup by header, NO MATCH",
2849 lsah->type, inet_ntoa (lsah->id));
2850
2851 return match;
2852}
2853
2854/* return +n, l1 is more recent.
2855 return -n, l2 is more recent.
2856 return 0, l1 and l2 is identical. */
2857int
2858ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
2859{
2860 int r;
2861 int x, y;
2862
2863 if (l1 == NULL && l2 == NULL)
2864 return 0;
2865 if (l1 == NULL)
2866 return -1;
2867 if (l2 == NULL)
2868 return 1;
2869
2870 /* compare LS sequence number. */
2871 x = (int) ntohl (l1->data->ls_seqnum);
2872 y = (int) ntohl (l2->data->ls_seqnum);
2873 if (x > y)
2874 return 1;
2875 if (x < y)
2876 return -1;
2877
2878 /* compare LS checksum. */
2879 r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
2880 if (r)
2881 return r;
2882
2883 /* compare LS age. */
2884 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
2885 return 1;
2886 else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
2887 return -1;
2888
2889 /* compare LS age with MaxAgeDiff. */
2890 if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
2891 return -1;
2892 else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
2893 return 1;
2894
2895 /* LSAs are identical. */
2896 return 0;
2897}
2898
2899/* If two LSAs are different, return 1, otherwise return 0. */
2900int
2901ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
2902{
2903 char *p1, *p2;
2904 assert (l1);
2905 assert (l2);
2906 assert (l1->data);
2907 assert (l2->data);
2908
2909 if (l1->data->options != l2->data->options)
2910 return 1;
2911
2912 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
2913 return 1;
2914
2915 if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
2916 return 1;
2917
2918 if (l1->data->length != l2->data->length)
2919 return 1;
2920
2921 if (l1->data->length == 0)
2922 return 1;
2923
pauld1825832003-04-03 01:27:01 +00002924 assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002925
2926 p1 = (char *) l1->data;
2927 p2 = (char *) l2->data;
2928
2929 if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
2930 ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
2931 return 1;
2932
2933 return 0;
2934}
2935
2936#ifdef ORIGINAL_CODING
2937void
2938ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr,
2939 struct ospf_lsa *self,
2940 struct ospf_lsa *new)
2941{
2942 u_int32_t seqnum;
2943
2944 /* Adjust LS Sequence Number. */
2945 seqnum = ntohl (new->data->ls_seqnum) + 1;
2946 self->data->ls_seqnum = htonl (seqnum);
2947
2948 /* Recalculate LSA checksum. */
2949 ospf_lsa_checksum (self->data);
2950
2951 /* Reflooding LSA. */
2952 /* RFC2328 Section 13.3
2953 On non-broadcast networks, separate Link State Update
2954 packets must be sent, as unicasts, to each adjacent neighbor
2955 (i.e., those in state Exchange or greater). The destination
2956 IP addresses for these packets are the neighbors' IP
2957 addresses. */
2958 if (nbr->oi->type == OSPF_IFTYPE_NBMA)
2959 {
2960 struct route_node *rn;
2961 struct ospf_neighbor *onbr;
2962
2963 for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn))
2964 if ((onbr = rn->info) != NULL)
2965 if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange)
2966 ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT);
2967 }
2968 else
2969 ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT);
2970
2971 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2972 zlog_info ("LSA[Type%d:%s]: Flush self-originated LSA",
2973 self->data->type, inet_ntoa (self->data->id));
2974}
2975#else /* ORIGINAL_CODING */
2976static int
paul68980082003-03-25 05:07:42 +00002977ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002978{
2979 if (lsa == NULL || !IS_LSA_SELF (lsa))
2980 return 0;
2981
2982 if (IS_DEBUG_OSPF_EVENT)
2983 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
2984
2985 /* Force given lsa's age to MaxAge. */
2986 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2987
2988 switch (lsa->data->type)
2989 {
2990#ifdef HAVE_OPAQUE_LSA
2991 case OSPF_OPAQUE_LINK_LSA:
2992 case OSPF_OPAQUE_AREA_LSA:
2993 case OSPF_OPAQUE_AS_LSA:
2994 ospf_opaque_lsa_refresh (lsa);
2995 break;
2996#endif /* HAVE_OPAQUE_LSA */
2997 default:
paul68980082003-03-25 05:07:42 +00002998 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002999 break;
3000 }
3001
3002 return 0;
3003}
3004
3005void
paul68980082003-03-25 05:07:42 +00003006ospf_flush_self_originated_lsas_now (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00003007{
3008 listnode n1, n2;
3009 struct ospf_area *area;
3010 struct ospf_interface *oi;
3011 struct ospf_lsa *lsa;
paul68980082003-03-25 05:07:42 +00003012 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +00003013 int need_to_flush_ase = 0;
3014
paul68980082003-03-25 05:07:42 +00003015 for (n1 = listhead (ospf->areas); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00003016 {
3017 if ((area = getdata (n1)) == NULL)
3018 continue;
3019
3020 if ((lsa = area->router_lsa_self) != NULL)
3021 {
3022 if (IS_DEBUG_OSPF_EVENT)
3023 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
3024
3025 ospf_lsa_flush_area (lsa, area);
3026 ospf_lsa_unlock (area->router_lsa_self);
3027 area->router_lsa_self = NULL;
3028 OSPF_TIMER_OFF (area->t_router_lsa_self);
3029 }
3030
3031 for (n2 = listhead (area->oiflist); n2; nextnode (n2))
3032 {
3033 if ((oi = getdata (n2)) == NULL)
3034 continue;
3035
3036 if ((lsa = oi->network_lsa_self) != NULL
3037 && oi->state == ISM_DR
3038 && oi->full_nbrs > 0)
3039 {
3040 if (IS_DEBUG_OSPF_EVENT)
3041 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
3042
3043 ospf_lsa_flush_area (oi->network_lsa_self, area);
3044 ospf_lsa_unlock (oi->network_lsa_self);
3045 oi->network_lsa_self = NULL;
3046 OSPF_TIMER_OFF (oi->t_network_lsa_self);
3047 }
3048
3049 if (oi->type != OSPF_IFTYPE_VIRTUALLINK
3050 && area->external_routing == OSPF_AREA_DEFAULT)
3051 need_to_flush_ase = 1;
3052 }
3053
paul68980082003-03-25 05:07:42 +00003054 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
3055 ospf_lsa_flush_schedule (ospf, lsa);
3056 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
3057 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003058#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003059 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
3060 ospf_lsa_flush_schedule (ospf, lsa);
3061 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
3062 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003063#endif /* HAVE_OPAQUE_LSA */
3064 }
3065
3066 if (need_to_flush_ase)
3067 {
paul68980082003-03-25 05:07:42 +00003068 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
3069 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003070#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003071 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
3072 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003073#endif /* HAVE_OPAQUE_LSA */
3074 }
3075
3076 /*
3077 * Make sure that the MaxAge LSA remover is executed immediately,
3078 * without conflicting to other threads.
3079 */
paul68980082003-03-25 05:07:42 +00003080 if (ospf->t_maxage != NULL)
paul718e3742002-12-13 20:15:29 +00003081 {
paul68980082003-03-25 05:07:42 +00003082 OSPF_TIMER_OFF (ospf->t_maxage);
3083 thread_execute (master, ospf_maxage_lsa_remover, ospf, 0);
paul718e3742002-12-13 20:15:29 +00003084 }
3085
3086 return;
3087}
3088#endif /* ORIGINAL_CODING */
3089
3090/* If there is self-originated LSA, then return 1, otherwise return 0. */
3091/* An interface-independent version of ospf_lsa_is_self_originated */
3092int
paul68980082003-03-25 05:07:42 +00003093ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003094{
3095 listnode node;
3096
3097 /* This LSA is already checked. */
3098 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
3099 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3100
3101 /* Make sure LSA is self-checked. */
3102 SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);
3103
3104 /* AdvRouter and Router ID is the same. */
paul68980082003-03-25 05:07:42 +00003105 if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003106 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3107
3108 /* LSA is router-LSA. */
3109 else if (lsa->data->type == OSPF_ROUTER_LSA &&
paul68980082003-03-25 05:07:42 +00003110 IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003111 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3112
3113 /* LSA is network-LSA. Compare Link ID with all interfaces. */
3114 else if (lsa->data->type == OSPF_NETWORK_LSA)
paul68980082003-03-25 05:07:42 +00003115 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00003116 {
3117 struct ospf_interface *oi = getdata (node);
3118
3119 /* Ignore virtual link. */
3120 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
3121 if (oi->address->family == AF_INET)
3122 if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4))
3123 {
3124 /* to make it easier later */
3125 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3126 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3127 }
3128 }
3129
3130 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3131}
3132
3133/* Get unique Link State ID. */
3134struct in_addr
paul68980082003-03-25 05:07:42 +00003135ospf_lsa_unique_id (struct ospf *ospf,
3136 struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +00003137{
3138 struct ospf_lsa *lsa;
3139 struct in_addr mask, id;
3140
3141 id = p->prefix;
3142
3143 /* Check existence of LSA instance. */
paul68980082003-03-25 05:07:42 +00003144 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003145 if (lsa)
3146 {
3147 struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
3148 if (ip_masklen (al->mask) == p->prefixlen)
3149 {
3150 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
3151 zlog_warn ("ospf_lsa_unique_id(): "
3152 "Can't get Link State ID for %s/%d",
3153 inet_ntoa (p->prefix), p->prefixlen);
3154 /* id.s_addr = 0; */
3155 id.s_addr = 0xffffffff;
3156 return id;
3157 }
3158 /* Masklen differs, then apply wildcard mask to Link State ID. */
3159 else
3160 {
3161 masklen2ip (p->prefixlen, &mask);
3162
3163 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
paul68980082003-03-25 05:07:42 +00003164 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type,
3165 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003166 if (lsa)
3167 {
3168 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
3169 zlog_warn ("ospf_lsa_unique_id(): "
3170 "Can't get Link State ID for %s/%d",
3171 inet_ntoa (p->prefix), p->prefixlen);
3172 /* id.s_addr = 0; */
3173 id.s_addr = 0xffffffff;
3174 return id;
3175 }
3176 }
3177 }
3178
3179 return id;
3180}
3181
3182
3183#define LSA_ACTION_ORIGN_RTR 1
3184#define LSA_ACTION_ORIGN_NET 2
3185#define LSA_ACTION_FLOOD_AREA 3
3186#define LSA_ACTION_FLOOD_AS 4
3187#define LSA_ACTION_FLUSH_AREA 5
3188#define LSA_ACTION_FLUSH_AS 6
3189
3190struct lsa_action
3191{
3192 u_char action;
3193 struct ospf_area *area;
3194 struct ospf_interface *oi;
3195 struct ospf_lsa *lsa;
3196};
3197
3198int
3199ospf_lsa_action (struct thread *t)
3200{
3201 struct lsa_action *data;
paul020709f2003-04-04 02:44:16 +00003202 struct ospf *ospf;
3203
3204 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00003205
3206 data = THREAD_ARG (t);
3207
3208 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
3209 zlog_info ("LSA[Action]: Performing scheduled LSA action: %d",
3210 data->action);
3211
3212 switch (data->action)
3213 {
3214 case LSA_ACTION_ORIGN_RTR:
3215 ospf_router_lsa_refresh (data->area->router_lsa_self);
3216 break;
3217 case LSA_ACTION_ORIGN_NET:
3218 ospf_network_lsa_originate (data->oi);
3219 break;
3220 case LSA_ACTION_FLOOD_AREA:
3221 ospf_flood_through_area (data->area, NULL, data->lsa);
3222 break;
3223 case LSA_ACTION_FLOOD_AS:
paul68980082003-03-25 05:07:42 +00003224 ospf_flood_through_as (ospf, NULL, data->lsa);
paul718e3742002-12-13 20:15:29 +00003225 break;
3226 case LSA_ACTION_FLUSH_AREA:
3227 ospf_lsa_flush_area (data->lsa, data->area);
3228 break;
3229 case LSA_ACTION_FLUSH_AS:
paul68980082003-03-25 05:07:42 +00003230 ospf_lsa_flush_as (ospf, data->lsa);
paul718e3742002-12-13 20:15:29 +00003231 break;
3232 }
3233
3234 ospf_lsa_unlock (data->lsa);
3235 XFREE (MTYPE_OSPF_MESSAGE, data);
3236 return 0;
3237}
3238
3239void
3240ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa)
3241{
3242 struct lsa_action *data;
3243
3244 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3245 memset (data, 0, sizeof (struct lsa_action));
3246
3247 data->action = LSA_ACTION_FLOOD_AREA;
3248 data->area = area;
3249 data->lsa = ospf_lsa_lock (lsa);
3250
3251 thread_add_event (master, ospf_lsa_action, data, 0);
3252}
3253
3254void
3255ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
3256{
3257 struct lsa_action *data;
3258
3259 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3260 memset (data, 0, sizeof (struct lsa_action));
3261
3262 data->action = LSA_ACTION_FLUSH_AREA;
3263 data->area = area;
3264 data->lsa = ospf_lsa_lock (lsa);
3265
3266 thread_add_event (master, ospf_lsa_action, data, 0);
3267}
3268
3269
3270/* LSA Refreshment functions. */
3271void
paul68980082003-03-25 05:07:42 +00003272ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003273{
3274 struct external_info *ei;
3275 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3276
3277 switch (lsa->data->type)
3278 {
3279 /* Router and Network LSAs are processed differently. */
3280 case OSPF_ROUTER_LSA:
3281 case OSPF_NETWORK_LSA:
3282 break;
3283 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003284 ospf_summary_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003285 break;
3286 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003287 ospf_summary_asbr_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003288 break;
3289 case OSPF_AS_EXTERNAL_LSA:
3290 ei = ospf_external_info_check (lsa);
3291 if (ei)
paul68980082003-03-25 05:07:42 +00003292 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00003293 else
paul68980082003-03-25 05:07:42 +00003294 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003295 break;
3296#ifdef HAVE_OPAQUE_LSA
3297 case OSPF_OPAQUE_LINK_LSA:
3298 case OSPF_OPAQUE_AREA_LSA:
3299 case OSPF_OPAQUE_AS_LSA:
3300 ospf_opaque_lsa_refresh (lsa);
3301 break;
pauld7480322003-05-16 17:31:51 +00003302#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00003303 default:
3304 break;
paul718e3742002-12-13 20:15:29 +00003305 }
3306}
3307
3308void
paul68980082003-03-25 05:07:42 +00003309ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003310{
3311 u_int16_t index, current_index;
3312
3313 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3314
3315 if (lsa->refresh_list < 0)
3316 {
3317 int delay;
3318
3319 if (LS_AGE (lsa) == 0 &&
3320 ntohl (lsa->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)
3321 /* Randomize first update by OSPF_LS_REFRESH_SHIFT factor */
3322 delay = OSPF_LS_REFRESH_SHIFT + (random () % OSPF_LS_REFRESH_TIME);
3323 else
3324 /* Randomize another updates by +-OSPF_LS_REFRESH_JITTER factor */
3325 delay = OSPF_LS_REFRESH_TIME - LS_AGE (lsa) - OSPF_LS_REFRESH_JITTER
3326 + (random () % (2*OSPF_LS_REFRESH_JITTER));
3327
3328 if (delay < 0)
3329 delay = 0;
3330
paul68980082003-03-25 05:07:42 +00003331 current_index = ospf->lsa_refresh_queue.index +
3332 (time (NULL) - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
paul718e3742002-12-13 20:15:29 +00003333
3334 index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
3335 % (OSPF_LSA_REFRESHER_SLOTS);
3336
3337 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3338 zlog_info ("LSA[Refresh]: lsa with age %d added to index %d",
3339 LS_AGE (lsa), index);
paul68980082003-03-25 05:07:42 +00003340 if (!ospf->lsa_refresh_queue.qs[index])
3341 ospf->lsa_refresh_queue.qs[index] = list_new ();
3342 listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00003343 lsa->refresh_list = index;
paulf2c80652002-12-13 21:44:27 +00003344 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3345 zlog_info ("LSA[Refresh]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa, index);
paul718e3742002-12-13 20:15:29 +00003346 }
3347}
3348
3349void
paul68980082003-03-25 05:07:42 +00003350ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003351{
3352 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3353 if (lsa->refresh_list >= 0)
3354 {
paul68980082003-03-25 05:07:42 +00003355 list refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list];
paul718e3742002-12-13 20:15:29 +00003356 listnode_delete (refresh_list, lsa);
3357 if (!listcount (refresh_list))
3358 {
3359 list_free (refresh_list);
paul68980082003-03-25 05:07:42 +00003360 ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
paul718e3742002-12-13 20:15:29 +00003361 }
3362 ospf_lsa_unlock (lsa);
3363 lsa->refresh_list = -1;
3364 }
3365}
3366
3367int
3368ospf_lsa_refresh_walker (struct thread *t)
3369{
3370 list refresh_list;
3371 listnode node;
paul68980082003-03-25 05:07:42 +00003372 struct ospf *ospf = THREAD_ARG (t);
paul718e3742002-12-13 20:15:29 +00003373 int i;
3374 list lsa_to_refresh = list_new ();
3375
3376 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3377 zlog_info ("LSA[Refresh]:ospf_lsa_refresh_walker(): start");
3378
3379
paul68980082003-03-25 05:07:42 +00003380 i = ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003381
paul68980082003-03-25 05:07:42 +00003382 ospf->lsa_refresh_queue.index =
3383 (ospf->lsa_refresh_queue.index +
3384 (time (NULL) - ospf->lsa_refresher_started) / OSPF_LSA_REFRESHER_GRANULARITY)
paul718e3742002-12-13 20:15:29 +00003385 % OSPF_LSA_REFRESHER_SLOTS;
3386
3387 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3388 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
paul68980082003-03-25 05:07:42 +00003389 ospf->lsa_refresh_queue.index);
paul718e3742002-12-13 20:15:29 +00003390
paul68980082003-03-25 05:07:42 +00003391 for (;i != ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003392 i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
3393 {
3394 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3395 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d", i);
3396
paul68980082003-03-25 05:07:42 +00003397 refresh_list = ospf->lsa_refresh_queue.qs [i];
paul718e3742002-12-13 20:15:29 +00003398
paul68980082003-03-25 05:07:42 +00003399 ospf->lsa_refresh_queue.qs [i] = NULL;
3400
paul718e3742002-12-13 20:15:29 +00003401 if (refresh_list)
3402 {
3403 for (node = listhead (refresh_list); node;)
3404 {
3405 listnode next;
3406 struct ospf_lsa *lsa = getdata (node);
3407 next = node->next;
3408
3409 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
paulf2c80652002-12-13 21:44:27 +00003410 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa, i);
paul718e3742002-12-13 20:15:29 +00003411
3412 list_delete_node (refresh_list, node);
3413 ospf_lsa_unlock (lsa);
3414 lsa->refresh_list = -1;
3415 listnode_add (lsa_to_refresh, lsa);
3416 node = next;
3417 }
3418 list_free (refresh_list);
3419 }
3420 }
3421
paul68980082003-03-25 05:07:42 +00003422 ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
3423 ospf, ospf->lsa_refresh_interval);
3424 ospf->lsa_refresher_started = time (NULL);
paul718e3742002-12-13 20:15:29 +00003425
3426 for (node = listhead (lsa_to_refresh); node; nextnode (node))
paul68980082003-03-25 05:07:42 +00003427 ospf_lsa_refresh (ospf, getdata (node));
paul718e3742002-12-13 20:15:29 +00003428
3429 list_delete (lsa_to_refresh);
3430
3431 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3432 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
3433
3434 return 0;
3435}
3436