blob: 34cbc446ab8e3aa03c71184d8554c21e2d05001a [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)
441 UNSET_FLAG (flags, OSPF_FLAG_ASBR);
442
443 return flags;
444}
445
446/* Lookup neighbor other than myself.
447 And check neighbor count,
448 Point-to-Point link must have only 1 neighbor. */
449struct ospf_neighbor *
paul68980082003-03-25 05:07:42 +0000450ospf_nbr_lookup_ptop (struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +0000451{
paul718e3742002-12-13 20:15:29 +0000452 struct ospf_neighbor *nbr = NULL;
paul68980082003-03-25 05:07:42 +0000453 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000454
455 /* Search neighbor, there must be one of two nbrs. */
paul68980082003-03-25 05:07:42 +0000456 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
457 if ((nbr = rn->info))
458 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +0000459 if (nbr->state == NSM_Full)
paul68980082003-03-25 05:07:42 +0000460 {
461 route_unlock_node (rn);
462 break;
463 }
paul718e3742002-12-13 20:15:29 +0000464
465 /* PtoP link must have only 1 neighbor. */
paul68980082003-03-25 05:07:42 +0000466 if (ospf_nbr_count (oi, 0) > 1)
paul718e3742002-12-13 20:15:29 +0000467 zlog_warn ("Point-to-Point link has more than 1 neighobrs.");
468
469 return nbr;
470}
471
472/* Set a link information. */
473void
474link_info_set (struct stream *s, struct in_addr id,
475 struct in_addr data, u_char type, u_char tos, u_int16_t cost)
476{
477 /* TOS based routing is not supported. */
478 stream_put_ipv4 (s, id.s_addr); /* Link ID. */
479 stream_put_ipv4 (s, data.s_addr); /* Link Data. */
480 stream_putc (s, type); /* Link Type. */
481 stream_putc (s, tos); /* TOS = 0. */
482 stream_putw (s, cost); /* Link Cost. */
483}
484
485/* Describe Point-to-Point link. */
486int
487lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
488{
489 int links = 0;
490 struct ospf_neighbor *nbr;
491 struct in_addr id, mask;
492
493 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
494 zlog_info ("LSA[Type1]: Set link Point-to-Point");
495
paul68980082003-03-25 05:07:42 +0000496 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000497 if (nbr->state == NSM_Full)
498 {
499 /* For unnumbered point-to-point networks, the Link Data field
500 should specify the interface's MIB-II ifIndex value. */
501 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
502 LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
503 links++;
504 }
505
506 if (oi->connected->destination != NULL)
507 {
508 /* Option 1:
509 link_type = LSA_LINK_TYPE_STUB;
510 link_id = nbr->address.u.prefix4;
511 link_data.s_addr = 0xffffffff;
512 link_cost = o->output_cost; */
513
514 id.s_addr = oi->connected->destination->u.prefix4.s_addr;
515 mask.s_addr = 0xffffffff;
516 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
517 }
518 else
519 {
520 /* Option 2: We need to include link to a stub
521 network regardless of the state of the neighbor */
522 masklen2ip (oi->address->prefixlen, &mask);
523 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
524 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
525 }
526 links++;
527
528 return links;
529}
530
531/* Describe Broadcast Link. */
532int
533lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
534{
535 struct ospf_neighbor *dr;
536 struct in_addr id, mask;
537
538 /* Describe Type 3 Link. */
539 if (oi->state == ISM_Waiting)
540 {
541 masklen2ip (oi->address->prefixlen, &mask);
542 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
543 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
544 return 1;
545 }
546
547 dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
548 /* Describe Type 2 link. */
549 if (dr && (dr->state == NSM_Full ||
550 IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
paul68980082003-03-25 05:07:42 +0000551 ospf_nbr_count (oi, NSM_Full) > 0)
paul718e3742002-12-13 20:15:29 +0000552 {
553 link_info_set (s, DR (oi), oi->address->u.prefix4,
554 LSA_LINK_TYPE_TRANSIT, 0, oi->output_cost);
555 }
556 /* Describe type 3 link. */
557 else
558 {
559 masklen2ip (oi->address->prefixlen, &mask);
560 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
561 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
562 }
563 return 1;
564}
565
566int
567lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
568{
569 struct in_addr id, mask;
570
571 /* Describe Type 3 Link. */
572 if (oi->state != ISM_Loopback)
573 return 0;
574
575 mask.s_addr = 0xffffffff;
576 id.s_addr = oi->address->u.prefix4.s_addr;
577 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
578 return 1;
579}
580
581/* Describe Virtual Link. */
582int
583lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
584{
585 struct ospf_neighbor *nbr;
586
paul718e3742002-12-13 20:15:29 +0000587 if (oi->state == ISM_PointToPoint)
paul68980082003-03-25 05:07:42 +0000588 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000589 if (nbr->state == NSM_Full)
590 {
591 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
592 LSA_LINK_TYPE_VIRTUALLINK, 0, oi->output_cost);
593 return 1;
594 }
595
596 return 0;
597}
598
599#define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O)
600
paul7afa08d2002-12-13 20:59:45 +0000601/* this function add for support point-to-multipoint ,see rfc2328
60212.4.1.4.*/
603/* from "edward rrr" <edward_rrr@hotmail.com>
604 http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
paul68980082003-03-25 05:07:42 +0000605int
606lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
paul7afa08d2002-12-13 20:59:45 +0000607{
608 int links = 0;
609 struct route_node *rn;
610 struct ospf_neighbor *nbr = NULL;
611 struct in_addr id, mask;
612
613 mask.s_addr = 0xffffffff;
614 id.s_addr = oi->address->u.prefix4.s_addr;
615 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
616 links++;
617
paul1cc8f762003-04-05 19:34:32 +0000618 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
619 zlog_info ("PointToMultipoint: running ptomultip_set");
paul7afa08d2002-12-13 20:59:45 +0000620
621 /* Search neighbor, */
622 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
623 if ((nbr = rn->info) != NULL)
624 /* Ignore myself. */
paul68980082003-03-25 05:07:42 +0000625 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul7afa08d2002-12-13 20:59:45 +0000626 if (nbr->state == NSM_Full)
627
628 {
paul7afa08d2002-12-13 20:59:45 +0000629 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
630 LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
631 links++;
paul1cc8f762003-04-05 19:34:32 +0000632 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
633 zlog_info ("PointToMultipoint: set link to %s",
634 inet_ntoa(oi->address->u.prefix4));
paul7afa08d2002-12-13 20:59:45 +0000635 }
636
637 return links;
paul7afa08d2002-12-13 20:59:45 +0000638}
639
paul718e3742002-12-13 20:15:29 +0000640/* Set router-LSA link information. */
641int
642router_lsa_link_set (struct stream *s, struct ospf_area *area)
643{
644 listnode node;
645 int links = 0;
646
647 for (node = listhead (area->oiflist); node; node = nextnode (node))
648 {
649 struct ospf_interface *oi = node->data;
650 struct interface *ifp = oi->ifp;
651
652 /* Check interface is up, OSPF is enable. */
paul2e3b2e42002-12-13 21:03:13 +0000653 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000654 {
655 if (oi->state != ISM_Down)
656 {
657 /* Describe each link. */
658 switch (oi->type)
659 {
660 case OSPF_IFTYPE_POINTOPOINT:
661 links += lsa_link_ptop_set (s, oi);
662 break;
663 case OSPF_IFTYPE_BROADCAST:
664 links += lsa_link_broadcast_set (s, oi);
665 break;
666 case OSPF_IFTYPE_NBMA:
667 links += lsa_link_nbma_set (s, oi);
668 break;
669 case OSPF_IFTYPE_POINTOMULTIPOINT:
paul68980082003-03-25 05:07:42 +0000670 links += lsa_link_ptomp_set (s, oi);
paul718e3742002-12-13 20:15:29 +0000671 break;
672 case OSPF_IFTYPE_VIRTUALLINK:
673 links += lsa_link_virtuallink_set (s, oi);
674 break;
675 case OSPF_IFTYPE_LOOPBACK:
676 links += lsa_link_loopback_set (s, oi);
677 }
678 }
679 }
680 }
681
682 return links;
683}
684
685/* Set router-LSA body. */
686void
687ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
688{
689 unsigned long putp;
690 u_int16_t cnt;
691
692 /* Set flags. */
693 stream_putc (s, router_lsa_flags (area));
694
695 /* Set Zero fields. */
696 stream_putc (s, 0);
697
698 /* Keep pointer to # links. */
699 putp = s->putp;
700
701 /* Forward word */
702 stream_putw(s, 0);
703
704 /* Set all link information. */
705 cnt = router_lsa_link_set (s, area);
706
707 /* Set # of links here. */
708 stream_putw_at (s, putp, cnt);
709}
710
711/* Create new router-LSA. */
712struct ospf_lsa *
713ospf_router_lsa_new (struct ospf_area *area)
714{
paul68980082003-03-25 05:07:42 +0000715 struct ospf *ospf = area->ospf;
paul718e3742002-12-13 20:15:29 +0000716 struct stream *s;
717 struct lsa_header *lsah;
718 struct ospf_lsa *new;
719 int length;
720
721 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
722 zlog_info ("LSA[Type1]: Create router-LSA instance");
723
724 /* Create a stream for LSA. */
725 s = stream_new (OSPF_MAX_LSA_SIZE);
726 lsah = (struct lsa_header *) STREAM_DATA (s);
727
728#ifdef HAVE_NSSA
729 /* Set LSA common header fields. */
730 lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_NSSA_GET (area),
paul68980082003-03-25 05:07:42 +0000731 OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000732#else /* ! HAVE_NSSA */
733 /* Set LSA common header fields. */
734 lsa_header_set (s, LSA_OPTIONS_GET (area),
paul68980082003-03-25 05:07:42 +0000735 OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000736#endif /* HAVE_NSSA */
737
738 /* Set router-LSA body fields. */
739 ospf_router_lsa_body_set (s, area);
740
741 /* Set length. */
742 length = stream_get_endp (s);
743 lsah->length = htons (length);
744
745 /* Now, create OSPF LSA instance. */
746 new = ospf_lsa_new ();
747 new->area = area;
748 SET_FLAG (new->flags, OSPF_LSA_SELF);
749
750 /* Copy LSA data to store, discard stream. */
751 new->data = ospf_lsa_data_new (length);
752 memcpy (new->data, lsah, length);
753 stream_free (s);
754
755 return new;
756}
757
758/* Originate Router-LSA. */
759struct ospf_lsa *
760ospf_router_lsa_originate (struct ospf_area *area)
761{
762 struct ospf_lsa *new;
763
764 /* Create new router-LSA instance. */
765 new = ospf_router_lsa_new (area);
766
767 /* Sanity check. */
768 if (new->data->adv_router.s_addr == 0)
769 {
770 if (IS_DEBUG_OSPF_EVENT)
771 zlog_info ("LSA[Type1]: AdvRouter is 0, discard");
772 ospf_lsa_discard (new);
773 return NULL;
774 }
775
776 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +0000777 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000778
779 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +0000780 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +0000781
782 /* Flooding new LSA through area. */
783 ospf_flood_through_area (area, NULL, new);
784
785 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
786 {
787 zlog_info ("LSA[Type%d:%s]: Originate router-LSA %p",
788 new->data->type, inet_ntoa (new->data->id), new);
789 ospf_lsa_header_dump (new->data);
790 }
791
792 return new;
793}
794
795/* Refresh router-LSA. */
796struct ospf_lsa *
797ospf_router_lsa_refresh (struct ospf_lsa *lsa)
798{
799 struct ospf_area *area = lsa->area;
800 struct ospf_lsa *new;
801
802 /* Sanity check. */
803 assert (lsa->data);
804
805 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +0000806 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +0000807
808 /* Create new router-LSA instance. */
809 new = ospf_router_lsa_new (area);
810 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
811
paul68980082003-03-25 05:07:42 +0000812 ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000813
814 /* Flood LSA through area. */
815 ospf_flood_through_area (area, NULL, new);
816
817 /* Debug logging. */
818 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
819 {
820 zlog_info ("LSA[Type%d:%s]: router-LSA refresh",
821 new->data->type, inet_ntoa (new->data->id));
822 ospf_lsa_header_dump (new->data);
823 }
824
825 return NULL;
826}
827
828int
829ospf_router_lsa_timer (struct thread *t)
830{
831 struct ospf_area *area;
832
833 if (IS_DEBUG_OSPF_EVENT)
834 zlog_info ("Timer[router-LSA]: (router-LSA Refresh expire)");
835
836 area = THREAD_ARG (t);
837 area->t_router_lsa_self = NULL;
838
839 /* Now refresh router-LSA. */
840 if (area->router_lsa_self)
841 ospf_router_lsa_refresh (area->router_lsa_self);
842 /* Newly originate router-LSA. */
843 else
844 ospf_router_lsa_originate (area);
845
846 return 0;
847}
848
849void
850ospf_router_lsa_timer_add (struct ospf_area *area)
851{
852 /* Keep area's self-originated router-LSA. */
853 struct ospf_lsa *lsa = area->router_lsa_self;
854
855 /* Cancel previously scheduled router-LSA timer. */
856 if (area->t_router_lsa_self)
857 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
858 zlog_info ("LSA[Type1]: Cancel previous router-LSA timer");
859
860 OSPF_TIMER_OFF (area->t_router_lsa_self);
861
862 /* If router-LSA is originated previously, check the interval time. */
863 if (lsa)
864 {
865 int delay;
866 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
867 {
868 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
869 ospf_router_lsa_timer, delay);
870 return;
871 }
872 }
873
874 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
875 zlog_info ("LSA[Type1]: Scheduling router-LSA origination right away");
876
877 /* Immediately refresh router-LSA. */
878 OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);
879}
880
881int
paul68980082003-03-25 05:07:42 +0000882ospf_router_lsa_update_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000883{
paul68980082003-03-25 05:07:42 +0000884 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000885 listnode node;
886
887 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
888 zlog_info ("Timer[router-LSA Update]: (timer expire)");
889
paul68980082003-03-25 05:07:42 +0000890 ospf->t_router_lsa_update = NULL;
paul718e3742002-12-13 20:15:29 +0000891
paul68980082003-03-25 05:07:42 +0000892 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +0000893 {
894 struct ospf_area *area = getdata (node);
895 struct ospf_lsa *lsa = area->router_lsa_self;
896 struct router_lsa *rl;
897 char *area_str;
898
899 /* Keep Area ID string. */
900 area_str = AREA_NAME (area);
901
902 /* If LSA not exist in this Area, originate new. */
903 if (lsa == NULL)
904 {
905 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
906 zlog_info("LSA[Type1]: Create router-LSA for Area %s", area_str);
907
908 ospf_router_lsa_originate (area);
909 }
910 /* If router-ID is changed, Link ID must change.
911 First flush old LSA, then originate new. */
paul68980082003-03-25 05:07:42 +0000912 else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +0000913 {
914 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
915 zlog_info("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
916 lsa->data->type, inet_ntoa (lsa->data->id), area_str);
917 ospf_lsa_flush_area (lsa, area);
918 ospf_lsa_unlock (area->router_lsa_self);
919 area->router_lsa_self = NULL;
920
921 /* Refresh router-LSA, (not install) and flood through area. */
922 ospf_router_lsa_timer_add (area);
923 }
924 else
925 {
926 rl = (struct router_lsa *) lsa->data;
927 /* Refresh router-LSA, (not install) and flood through area. */
paul68980082003-03-25 05:07:42 +0000928 if (rl->flags != ospf->flags)
paul718e3742002-12-13 20:15:29 +0000929 ospf_router_lsa_timer_add (area);
930 }
931 }
932
933 return 0;
934}
935
936
937/* network-LSA related functions. */
938/* Originate Network-LSA. */
939void
940ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi)
941{
942 struct in_addr mask;
943 struct route_node *rn;
944 struct ospf_neighbor *nbr;
945
946 masklen2ip (oi->address->prefixlen, &mask);
947 stream_put_ipv4 (s, mask.s_addr);
948
949 /* The network-LSA lists those routers that are fully adjacent to
950 the Designated Router; each fully adjacent router is identified by
951 its OSPF Router ID. The Designated Router includes itself in this
952 list. RFC2328, Section 12.4.2 */
953
954 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
955 if ((nbr = rn->info) != NULL)
956 if (nbr->state == NSM_Full || nbr == oi->nbr_self)
957 stream_put_ipv4 (s, nbr->router_id.s_addr);
958}
959
960struct ospf_lsa *
961ospf_network_lsa_new (struct ospf_interface *oi)
962{
963 struct stream *s;
964 struct ospf_lsa *new;
965 struct lsa_header *lsah;
966 int length;
967
968 /* If there are no neighbours on this network (the net is stub),
969 the router does not originate network-LSA (see RFC 12.4.2) */
970 if (oi->full_nbrs == 0)
971 return NULL;
972
973 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
974 zlog_info ("LSA[Type2]: Create network-LSA instance");
975
976 /* Create new stream for LSA. */
977 s = stream_new (OSPF_MAX_LSA_SIZE);
978 lsah = (struct lsa_header *) STREAM_DATA (s);
979
980 lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)),
paul68980082003-03-25 05:07:42 +0000981 OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000982
983 /* Set network-LSA body fields. */
984 ospf_network_lsa_body_set (s, oi);
985
986 /* Set length. */
987 length = stream_get_endp (s);
988 lsah->length = htons (length);
989
990 /* Create OSPF LSA instance. */
991 new = ospf_lsa_new ();
992 new->area = oi->area;
993 SET_FLAG (new->flags, OSPF_LSA_SELF);
994
995 /* Copy LSA to store. */
996 new->data = ospf_lsa_data_new (length);
997 memcpy (new->data, lsah, length);
998 stream_free (s);
999
1000 return new;
1001}
1002
1003/* Originate network-LSA. */
1004struct ospf_lsa *
1005ospf_network_lsa_originate (struct ospf_interface *oi)
1006{
1007 struct ospf_lsa *new;
1008
1009 /* Create new network-LSA instance. */
1010 new = ospf_network_lsa_new (oi);
1011 if (new == NULL)
1012 return NULL;
1013
1014 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001015 new = ospf_lsa_install (oi->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001016
1017 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001018 oi->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001019
1020 /* Flooding new LSA through area. */
1021 ospf_flood_through_area (oi->area, NULL, new);
1022
1023 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1024 {
1025 zlog_info ("LSA[Type%d:%s]: Originate network-LSA %p",
1026 new->data->type, inet_ntoa (new->data->id), new);
1027 ospf_lsa_header_dump (new->data);
1028 }
1029
1030 return new;
1031}
1032
1033int
1034ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
1035{
1036 struct ospf_area *area = lsa->area;
1037 struct ospf_lsa *new;
1038
1039 assert (lsa->data);
1040
1041 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00001042 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +00001043
1044 /* Create new network-LSA instance. */
1045 new = ospf_network_lsa_new (oi);
1046 if (new == NULL)
1047 return -1;
1048 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1049
paul68980082003-03-25 05:07:42 +00001050 ospf_lsa_install (area->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001051
1052 /* Flood LSA through aera. */
1053 ospf_flood_through_area (area, NULL, new);
1054
1055 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1056 {
1057 zlog_info ("LSA[Type%d:%s]: network-LSA refresh",
1058 new->data->type, inet_ntoa (new->data->id));
1059 ospf_lsa_header_dump (new->data);
1060 }
1061
1062 return 0;
1063}
1064
1065int
1066ospf_network_lsa_refresh_timer (struct thread *t)
1067{
1068 struct ospf_interface *oi;
1069
1070 oi = THREAD_ARG (t);
1071 oi->t_network_lsa_self = NULL;
1072
1073 if (oi->network_lsa_self)
1074 /* Now refresh network-LSA. */
1075 ospf_network_lsa_refresh (oi->network_lsa_self, oi);
1076 else
1077 /* Newly create network-LSA. */
1078 ospf_network_lsa_originate (oi);
1079
1080 return 0;
1081}
1082
1083void
1084ospf_network_lsa_timer_add (struct ospf_interface *oi)
1085{
1086 /* Keep interface's self-originated network-LSA. */
1087 struct ospf_lsa *lsa = oi->network_lsa_self;
1088
1089 /* Cancel previously schedules network-LSA timer. */
1090 if (oi->t_network_lsa_self)
1091 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1092 zlog_info ("LSA[Type2]: Cancel previous network-LSA timer");
1093 OSPF_TIMER_OFF (oi->t_network_lsa_self);
1094
1095 /* If network-LSA is originated previously, check the interval time. */
1096 if (lsa)
1097 {
1098 int delay;
1099 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
1100 {
1101 oi->t_network_lsa_self =
1102 thread_add_timer (master, ospf_network_lsa_refresh_timer,
1103 oi, delay);
1104 return;
1105 }
1106 }
1107
1108 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1109 zlog_info ("Scheduling network-LSA origination right away");
1110
1111 /* Immediately refresh network-LSA. */
1112 oi->t_network_lsa_self =
1113 thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);
1114}
1115
1116
1117void
1118stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
1119{
1120 u_int32_t metric;
1121 char *mp;
1122
1123 /* Put 0 metric. TOS metric is not supported. */
1124 metric = htonl (metric_value);
1125 mp = (char *) &metric;
1126 mp++;
1127 stream_put (s, mp, 3);
1128}
1129
1130/* summary-LSA related functions. */
1131void
1132ospf_summary_lsa_body_set (struct stream *s, struct prefix *p,
1133 u_int32_t metric)
1134{
1135 struct in_addr mask;
1136
1137 masklen2ip (p->prefixlen, &mask);
1138
1139 /* Put Network Mask. */
1140 stream_put_ipv4 (s, mask.s_addr);
1141
1142 /* Set # TOS. */
1143 stream_putc (s, (u_char) 0);
1144
1145 /* Set metric. */
1146 stream_put_ospf_metric (s, metric);
1147}
1148
1149struct ospf_lsa *
1150ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p,
1151 u_int32_t metric, struct in_addr id)
1152{
1153 struct stream *s;
1154 struct ospf_lsa *new;
1155 struct lsa_header *lsah;
1156 int length;
1157
1158 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1159 zlog_info ("LSA[Type3]: Create summary-LSA instance");
1160
1161 /* Create new stream for LSA. */
1162 s = stream_new (OSPF_MAX_LSA_SIZE);
1163 lsah = (struct lsa_header *) STREAM_DATA (s);
1164
paul68980082003-03-25 05:07:42 +00001165 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA,
1166 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001167
1168 /* Set summary-LSA body fields. */
1169 ospf_summary_lsa_body_set (s, p, metric);
1170
1171 /* Set length. */
1172 length = stream_get_endp (s);
1173 lsah->length = htons (length);
1174
1175 /* Create OSPF LSA instance. */
1176 new = ospf_lsa_new ();
1177 new->area = area;
1178 SET_FLAG (new->flags, OSPF_LSA_SELF);
1179
1180 /* Copy LSA to store. */
1181 new->data = ospf_lsa_data_new (length);
1182 memcpy (new->data, lsah, length);
1183 stream_free (s);
1184
1185 return new;
1186}
1187
1188/* Originate Summary-LSA. */
1189struct ospf_lsa *
1190ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1191 struct ospf_area *area)
1192{
1193 struct ospf_lsa *new;
1194 struct in_addr id;
1195
paul68980082003-03-25 05:07:42 +00001196 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001197
1198 /* Create new summary-LSA instance. */
1199 new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id);
1200
1201 /* Instlal LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001202 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001203
1204 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001205 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001206
1207 /* Flooding new LSA through area. */
1208 ospf_flood_through_area (area, NULL, new);
1209
1210 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1211 {
1212 zlog_info ("LSA[Type%d:%s]: Originate summary-LSA %p",
1213 new->data->type, inet_ntoa (new->data->id), new);
1214 ospf_lsa_header_dump (new->data);
1215 }
1216
1217 return new;
1218}
1219
1220struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001221ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001222{
1223 struct ospf_lsa *new;
1224 struct summary_lsa *sl;
1225 struct prefix p;
1226
1227 /* Sanity check. */
1228 assert (lsa->data);
1229
1230 sl = (struct summary_lsa *)lsa->data;
1231 p.prefixlen = ip_masklen (sl->mask);
1232 new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1233 sl->header.id);
1234
1235 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1236
1237 /* Re-calculate checksum. */
1238 ospf_lsa_checksum (new->data);
1239
paul68980082003-03-25 05:07:42 +00001240 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001241
1242 /* Flood LSA through AS. */
1243 ospf_flood_through_area (new->area, NULL, new);
1244
1245 /* Debug logging. */
1246 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1247 {
1248 zlog_info ("LSA[Type%d:%s]: summary-LSA refresh",
1249 new->data->type, inet_ntoa (new->data->id));
1250 ospf_lsa_header_dump (new->data);
1251 }
1252
1253 return new;
1254}
1255
1256
1257/* summary-ASBR-LSA related functions. */
1258void
1259ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p,
1260 u_int32_t metric)
1261{
1262 struct in_addr mask;
1263
1264 masklen2ip (p->prefixlen, &mask);
1265
1266 /* Put Network Mask. */
1267 stream_put_ipv4 (s, mask.s_addr);
1268
1269 /* Set # TOS. */
1270 stream_putc (s, (u_char) 0);
1271
1272 /* Set metric. */
1273 stream_put_ospf_metric (s, metric);
1274}
1275
1276struct ospf_lsa *
1277ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p,
1278 u_int32_t metric, struct in_addr id)
1279{
1280 struct stream *s;
1281 struct ospf_lsa *new;
1282 struct lsa_header *lsah;
1283 int length;
1284
1285 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1286 zlog_info ("LSA[Type3]: Create summary-LSA instance");
1287
1288 /* Create new stream for LSA. */
1289 s = stream_new (OSPF_MAX_LSA_SIZE);
1290 lsah = (struct lsa_header *) STREAM_DATA (s);
1291
paul68980082003-03-25 05:07:42 +00001292 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA,
1293 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001294
1295 /* Set summary-LSA body fields. */
1296 ospf_summary_asbr_lsa_body_set (s, p, metric);
1297
1298 /* Set length. */
1299 length = stream_get_endp (s);
1300 lsah->length = htons (length);
1301
1302 /* Create OSPF LSA instance. */
1303 new = ospf_lsa_new ();
1304 new->area = area;
1305 SET_FLAG (new->flags, OSPF_LSA_SELF);
1306
1307 /* Copy LSA to store. */
1308 new->data = ospf_lsa_data_new (length);
1309 memcpy (new->data, lsah, length);
1310 stream_free (s);
1311
1312 return new;
1313}
1314
1315/* Originate summary-ASBR-LSA. */
1316struct ospf_lsa *
1317ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1318 struct ospf_area *area)
1319{
1320 struct ospf_lsa *new;
1321 struct in_addr id;
1322
paul68980082003-03-25 05:07:42 +00001323 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001324
1325 /* Create new summary-LSA instance. */
1326 new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id);
1327
1328 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001329 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001330
1331 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001332 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001333
1334 /* Flooding new LSA through area. */
1335 ospf_flood_through_area (area, NULL, new);
1336
1337 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1338 {
1339 zlog_info ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p",
1340 new->data->type, inet_ntoa (new->data->id), new);
1341 ospf_lsa_header_dump (new->data);
1342 }
1343
1344 return new;
1345}
1346
1347struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001348ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001349{
1350 struct ospf_lsa *new;
1351 struct summary_lsa *sl;
1352 struct prefix p;
1353
1354 /* Sanity check. */
1355 assert (lsa->data);
1356
1357 sl = (struct summary_lsa *)lsa->data;
1358 p.prefixlen = ip_masklen (sl->mask);
1359 new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1360 sl->header.id);
1361
1362 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1363
1364 /* Re-calculate checksum. */
1365 ospf_lsa_checksum (new->data);
1366
paul68980082003-03-25 05:07:42 +00001367 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001368
1369 /* Flood LSA through area. */
1370 ospf_flood_through_area (new->area, NULL, new);
1371
1372 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1373 {
1374 zlog_info ("LSA[Type%d:%s]: summary-ASBR-LSA refresh",
1375 new->data->type, inet_ntoa (new->data->id));
1376 ospf_lsa_header_dump (new->data);
1377 }
1378
1379 return new;
1380}
1381
1382/* AS-external-LSA related functions. */
1383
1384/* Get nexthop for AS-external-LSAs. Return nexthop if its interface
1385 is connected, else 0*/
1386struct in_addr
paul68980082003-03-25 05:07:42 +00001387ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop)
paul718e3742002-12-13 20:15:29 +00001388{
1389 struct in_addr fwd;
1390 struct prefix nh;
paul718e3742002-12-13 20:15:29 +00001391 listnode n1;
1392
1393 fwd.s_addr = 0;
1394
1395 if (!nexthop.s_addr)
1396 return fwd;
1397
1398 /* Check whether nexthop is covered by OSPF network. */
1399 nh.family = AF_INET;
1400 nh.u.prefix4 = nexthop;
1401 nh.prefixlen = IPV4_MAX_BITLEN;
1402
paul68980082003-03-25 05:07:42 +00001403 for (n1 = listhead (ospf->oiflist); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00001404 {
1405 struct ospf_interface *oi = getdata (n1);
1406
paul2e3b2e42002-12-13 21:03:13 +00001407 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001408 if (oi->address->family == AF_INET)
1409 if (prefix_match (oi->address, &nh))
1410 return nexthop;
1411 }
1412
1413 return fwd;
1414}
1415
1416#ifdef HAVE_NSSA
1417/* NSSA-external-LSA related functions. */
1418
1419/* Get 1st IP connection for Forward Addr */
1420
1421struct in_addr
1422ospf_get_ip_from_ifp (struct ospf_interface *oi)
1423{
1424 struct in_addr fwd;
1425
1426 fwd.s_addr = 0;
1427
paul2e3b2e42002-12-13 21:03:13 +00001428 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001429 return oi->address->u.prefix4;
1430
1431 return fwd;
1432}
1433
1434/* Get 1st IP connection for Forward Addr */
1435struct in_addr
paulf2c80652002-12-13 21:44:27 +00001436ospf_get_nssa_ip (struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001437{
1438 struct in_addr fwd;
paulf2c80652002-12-13 21:44:27 +00001439 struct in_addr best_default;
paul718e3742002-12-13 20:15:29 +00001440 listnode n1;
1441
1442 fwd.s_addr = 0;
paulf2c80652002-12-13 21:44:27 +00001443 best_default.s_addr = 0;
paul718e3742002-12-13 20:15:29 +00001444
paul68980082003-03-25 05:07:42 +00001445 for (n1 = listhead (area->ospf->oiflist); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00001446 {
1447 struct ospf_interface *oi = getdata (n1);
1448
paul2e3b2e42002-12-13 21:03:13 +00001449 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001450 if (oi->area->external_routing == OSPF_AREA_NSSA)
paul68980082003-03-25 05:07:42 +00001451 if (oi->address && oi->address->family == AF_INET)
1452 {
1453 if (best_default.s_addr == 0)
1454 best_default = oi->address->u.prefix4;
1455 if (oi->area == area)
1456 return oi->address->u.prefix4;
paulf2c80652002-12-13 21:44:27 +00001457 }
paul718e3742002-12-13 20:15:29 +00001458 }
paulf2c80652002-12-13 21:44:27 +00001459 if (best_default.s_addr != 0)
1460 return best_default;
paul718e3742002-12-13 20:15:29 +00001461
paul68980082003-03-25 05:07:42 +00001462 if (best_default.s_addr != 0)
1463 return best_default;
1464
paul718e3742002-12-13 20:15:29 +00001465 return fwd;
1466}
1467#endif /* HAVE_NSSA */
1468
1469#define DEFAULT_DEFAULT_METRIC 20
1470#define DEFAULT_DEFAULT_ORIGINATE_METRIC 10
1471#define DEFAULT_DEFAULT_ALWAYS_METRIC 1
1472
1473#define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2
1474
1475int
paul68980082003-03-25 05:07:42 +00001476metric_type (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001477{
paul68980082003-03-25 05:07:42 +00001478 return (ospf->dmetric[src].type < 0 ?
1479 DEFAULT_METRIC_TYPE : ospf->dmetric[src].type);
paul718e3742002-12-13 20:15:29 +00001480}
1481
1482int
paul68980082003-03-25 05:07:42 +00001483metric_value (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001484{
paul68980082003-03-25 05:07:42 +00001485 if (ospf->dmetric[src].value < 0)
paul718e3742002-12-13 20:15:29 +00001486 {
1487 if (src == DEFAULT_ROUTE)
1488 {
paul68980082003-03-25 05:07:42 +00001489 if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA)
paul718e3742002-12-13 20:15:29 +00001490 return DEFAULT_DEFAULT_ORIGINATE_METRIC;
1491 else
1492 return DEFAULT_DEFAULT_ALWAYS_METRIC;
1493 }
paul68980082003-03-25 05:07:42 +00001494 else if (ospf->default_metric < 0)
paul718e3742002-12-13 20:15:29 +00001495 return DEFAULT_DEFAULT_METRIC;
1496 else
paul68980082003-03-25 05:07:42 +00001497 return ospf->default_metric;
paul718e3742002-12-13 20:15:29 +00001498 }
1499
paul68980082003-03-25 05:07:42 +00001500 return ospf->dmetric[src].value;
paul718e3742002-12-13 20:15:29 +00001501}
1502
1503/* Set AS-external-LSA body. */
1504void
paul68980082003-03-25 05:07:42 +00001505ospf_external_lsa_body_set (struct stream *s, struct external_info *ei,
1506 struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001507{
1508 struct prefix_ipv4 *p = &ei->p;
1509 struct in_addr mask, fwd_addr;
1510 u_int32_t mvalue;
1511 int mtype;
1512 int type;
1513
1514 /* Put Network Mask. */
1515 masklen2ip (p->prefixlen, &mask);
1516 stream_put_ipv4 (s, mask.s_addr);
1517
1518 /* If prefix is default, specify DEFAULT_ROUTE. */
1519 type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
1520
1521 mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001522 ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type);
paul718e3742002-12-13 20:15:29 +00001523
1524 mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001525 ROUTEMAP_METRIC (ei) : metric_value (ospf, type);
paul718e3742002-12-13 20:15:29 +00001526
1527 /* Put type of external metric. */
1528 stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0));
1529
1530 /* Put 0 metric. TOS metric is not supported. */
1531 stream_put_ospf_metric (s, mvalue);
1532
1533 /* Get forwarding address to nexthop if on the Connection List, else 0. */
paul68980082003-03-25 05:07:42 +00001534 fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop);
paul718e3742002-12-13 20:15:29 +00001535
1536 /* Put forwarding address. */
1537 stream_put_ipv4 (s, fwd_addr.s_addr);
1538
1539 /* Put route tag -- This value should be introduced from configuration. */
1540 stream_putl (s, 0);
1541}
1542
1543/* Create new external-LSA. */
1544struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00001545ospf_external_lsa_new (struct ospf *ospf,
1546 struct external_info *ei, struct in_addr *old_id)
paul718e3742002-12-13 20:15:29 +00001547{
1548 struct stream *s;
1549 struct lsa_header *lsah;
1550 struct ospf_lsa *new;
1551 struct in_addr id;
1552 int length;
1553
1554 if (ei == NULL)
1555 {
1556 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1557 zlog_warn ("LSA[Type5]: External info is NULL, could not originated");
1558 return NULL;
1559 }
1560
1561 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1562 zlog_info ("LSA[Type5]: Originate AS-external-LSA instance");
1563
1564 /* If old Link State ID is specified, refresh LSA with same ID. */
1565 if (old_id)
1566 id = *old_id;
1567 /* Get Link State with unique ID. */
1568 else
1569 {
paul68980082003-03-25 05:07:42 +00001570 id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p);
paul718e3742002-12-13 20:15:29 +00001571 if (id.s_addr == 0xffffffff)
1572 {
1573 /* Maybe Link State ID not available. */
1574 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1575 zlog_info ("LSA[Type5]: Link ID not available, can't originate");
1576 return NULL;
1577 }
1578 }
1579
1580 /* Create new stream for LSA. */
1581 s = stream_new (OSPF_MAX_LSA_SIZE);
1582 lsah = (struct lsa_header *) STREAM_DATA (s);
1583
1584 /* Set LSA common header fields. */
paul68980082003-03-25 05:07:42 +00001585 lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA,
1586 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001587
1588 /* Set AS-external-LSA body fields. */
paul68980082003-03-25 05:07:42 +00001589 ospf_external_lsa_body_set (s, ei, ospf);
paul718e3742002-12-13 20:15:29 +00001590
1591 /* Set length. */
1592 length = stream_get_endp (s);
1593 lsah->length = htons (length);
1594
1595 /* Now, create OSPF LSA instance. */
1596 new = ospf_lsa_new ();
1597 new->area = NULL;
1598 SET_FLAG (new->flags, OSPF_LSA_SELF|OSPF_LSA_APPROVED);
1599
1600 /* Copy LSA data to store, discard stream. */
1601 new->data = ospf_lsa_data_new (length);
1602 memcpy (new->data, lsah, length);
1603 stream_free (s);
1604
1605 return new;
1606}
1607
1608#ifdef HAVE_NSSA
paul718e3742002-12-13 20:15:29 +00001609/* As Type-7 */
1610void
paul68980082003-03-25 05:07:42 +00001611ospf_install_flood_nssa (struct ospf *ospf,
1612 struct ospf_lsa *lsa, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00001613{
1614 struct ospf_lsa *new2;
paul68980082003-03-25 05:07:42 +00001615 struct as_external_lsa *extlsa;
paulf2c80652002-12-13 21:44:27 +00001616 listnode node;
paul718e3742002-12-13 20:15:29 +00001617
1618 /* NSSA Originate or Refresh (If anyNSSA)
1619
1620 LSA is self-originated. And just installed as Type-5.
1621 Additionally, install as Type-7 LSDB for every attached NSSA.
1622
1623 P-Bit controls which ABR performs translation to outside world; If
1624 we are an ABR....do not set the P-bit, because we send the Type-5,
1625 not as the ABR Translator, but as the ASBR owner within the AS!
1626
1627 If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The
1628 elected ABR Translator will see the P-bit, Translate, and re-flood.
1629
1630 Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
1631 Type-5's to non-NSSA Areas. (it will also attempt a re-install) */
1632
paul68980082003-03-25 05:07:42 +00001633 for (node = listhead (ospf->areas); node; nextnode (node))
1634 {
1635 struct ospf_area *area = getdata (node);
paul718e3742002-12-13 20:15:29 +00001636
paul68980082003-03-25 05:07:42 +00001637 /* make lsa duplicate, lock=1 */
1638 new2 = ospf_lsa_dup (lsa);
1639 new2->area = area;
1640 new2->data->type = OSPF_AS_NSSA_LSA;
paul718e3742002-12-13 20:15:29 +00001641
paul68980082003-03-25 05:07:42 +00001642 /* set P-bit if not ABR */
paul020709f2003-04-04 02:44:16 +00001643 if (! IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001644 {
1645 SET_FLAG(new2->data->options, OSPF_OPTION_NP);
1646
1647 /* set non-zero FWD ADDR
1648
1649 draft-ietf-ospf-nssa-update-09.txt
1650
1651 if the network between the NSSA AS boundary router and the
1652 adjacent AS is advertised into OSPF as an internal OSPF route,
1653 the forwarding address should be the next op address as is cu
1654 currently done with type-5 LSAs. If the intervening network is
1655 not adversited into OSPF as an internal OSPF route and the
1656 type-7 LSA's P-bit is set a forwarding address should be
1657 selected from one of the router's active OSPF inteface addresses
1658 which belong to the NSSA. If no such addresses exist, then
1659 no type-7 LSA's with the P-bit set should originate from this
1660 router. */
1661
1662 /* kevinm: not updating lsa anymore, just new2 */
1663 extlsa = (struct as_external_lsa *)(new2->data);
1664
1665 if (extlsa->e[0].fwd_addr.s_addr == 0)
1666 extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */
paul718e3742002-12-13 20:15:29 +00001667
pauld7480322003-05-16 17:31:51 +00001668 if (extlsa->e[0].fwd_addr.s_addr == 0)
1669 {
1670 if (IS_DEBUG_OSPF_NSSA)
1671 zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
1672 ospf_lsa_discard(new2);
1673 return;
1674 }
paulf2c80652002-12-13 21:44:27 +00001675 }
paul68980082003-03-25 05:07:42 +00001676 /* Re-calculate checksum. */
1677 ospf_lsa_checksum (new2->data);
paul718e3742002-12-13 20:15:29 +00001678
paul68980082003-03-25 05:07:42 +00001679 /* install also as Type-7 */
1680 ospf_lsa_install (ospf, NULL, new2); /* Remove Old, Lock New = 2 */
1681
1682 /* will send each copy, lock=2+n */
1683 ospf_flood_through_as (ospf, NULL, new2); /* all attached NSSA's, no AS/STUBs */
1684 }
paul718e3742002-12-13 20:15:29 +00001685}
1686#endif /* HAVE_NSSA */
1687
1688int
1689is_prefix_default (struct prefix_ipv4 *p)
1690{
1691 struct prefix_ipv4 q;
1692
1693 q.family = AF_INET;
1694 q.prefix.s_addr = 0;
1695 q.prefixlen = 0;
1696
1697 return prefix_same ((struct prefix *) p, (struct prefix *) &q);
1698}
1699
1700/* Originate an AS-external-LSA, install and flood. */
1701struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00001702ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00001703{
1704 struct ospf_lsa *new;
1705
1706 /* Added for NSSA project....
1707
1708 External LSAs are originated in ASBRs as usual, but for NSSA systems.
1709 there is the global Type-5 LSDB and a Type-7 LSDB installed for
1710 every area. The Type-7's are flooded to every IR and every ABR; We
1711 install the Type-5 LSDB so that the normal "refresh" code operates
1712 as usual, and flag them as not used during ASE calculations. The
1713 Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding
1714 Address of non-zero.
1715
1716 If an ABR is the elected NSSA translator, following SPF and during
1717 the ABR task it will translate all the scanned Type-7's, with P-bit
1718 ON and not-self generated, and translate to Type-5's throughout the
1719 non-NSSA/STUB AS.
1720
1721 A difference in operation depends whether this ASBR is an ABR
1722 or not. If not an ABR, the P-bit is ON, to indicate that any
1723 elected NSSA-ABR can perform its translation.
1724
1725 If an ABR, the P-bit is OFF; No ABR will perform translation and
1726 this ASBR will flood the Type-5 LSA as usual.
1727
1728 For the case where this ASBR is not an ABR, the ASE calculations
1729 are based on the Type-5 LSDB; The Type-7 LSDB exists just to
1730 demonstrate to the user that there are LSA's that belong to any
1731 attached NSSA.
1732
1733 Finally, it just so happens that when the ABR is translating every
1734 Type-7 into Type-5, it installs it into the Type-5 LSDB as an
1735 approved Type-5 (translated from Type-7); at the end of translation
1736 if any Translated Type-5's remain unapproved, then they must be
1737 flushed from the AS.
1738
1739 */
1740
1741 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00001742 if (!ospf_redistribute_check (ospf, ei, NULL))
paul718e3742002-12-13 20:15:29 +00001743 return NULL;
1744
1745 /* Create new AS-external-LSA instance. */
paul68980082003-03-25 05:07:42 +00001746 if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL)
paul718e3742002-12-13 20:15:29 +00001747 {
1748 if (IS_DEBUG_OSPF_EVENT)
1749 zlog_info ("LSA[Type5:%s]: Could not originate AS-external-LSA",
1750 inet_ntoa (ei->p.prefix));
1751 return NULL;
1752 }
1753
1754 /* Install newly created LSA into Type-5 LSDB, lock = 1. */
paul68980082003-03-25 05:07:42 +00001755 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001756
1757 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001758 ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001759
1760 /* Flooding new LSA. only to AS (non-NSSA/STUB) */
paul68980082003-03-25 05:07:42 +00001761 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001762
1763#ifdef HAVE_NSSA
1764 /* If there is any attached NSSA, do special handling */
paul68980082003-03-25 05:07:42 +00001765 if (ospf->anyNSSA)
1766 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
paul718e3742002-12-13 20:15:29 +00001767#endif /* HAVE_NSSA */
1768
1769 /* Debug logging. */
1770 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1771 {
1772 zlog_info ("LSA[Type%d:%s]: Originate AS-external-LSA %p",
1773 new->data->type, inet_ntoa (new->data->id), new);
1774 ospf_lsa_header_dump (new->data);
1775 }
1776
1777 return new;
1778}
1779
1780/* Originate AS-external-LSA from external info with initial flag. */
1781int
paul68980082003-03-25 05:07:42 +00001782ospf_external_lsa_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001783{
paul68980082003-03-25 05:07:42 +00001784 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001785 struct route_node *rn;
1786 struct external_info *ei;
1787 struct route_table *rt;
paul68980082003-03-25 05:07:42 +00001788 int type = THREAD_VAL (thread);
paul718e3742002-12-13 20:15:29 +00001789
paul68980082003-03-25 05:07:42 +00001790 ospf->t_external_lsa = NULL;
paul718e3742002-12-13 20:15:29 +00001791
1792 /* Originate As-external-LSA from all type of distribute source. */
1793 if ((rt = EXTERNAL_INFO (type)))
1794 for (rn = route_top (rt); rn; rn = route_next (rn))
1795 if ((ei = rn->info) != NULL)
1796 if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p))
paul68980082003-03-25 05:07:42 +00001797 if (!ospf_external_lsa_originate (ospf, ei))
paul718e3742002-12-13 20:15:29 +00001798 zlog_warn ("LSA: AS-external-LSA was not originated.");
1799
1800 return 0;
1801}
1802
1803struct external_info *
paul020709f2003-04-04 02:44:16 +00001804ospf_default_external_info (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001805{
1806 int type;
1807 struct route_node *rn;
1808 struct prefix_ipv4 p;
1809
1810 p.family = AF_INET;
1811 p.prefix.s_addr = 0;
1812 p.prefixlen = 0;
1813
1814 /* First, lookup redistributed default route. */
1815 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
1816 if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF)
1817 {
1818 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
1819 if (rn != NULL)
1820 {
1821 route_unlock_node (rn);
1822 assert (rn->info);
paul68980082003-03-25 05:07:42 +00001823 if (ospf_redistribute_check (ospf, rn->info, NULL))
paul718e3742002-12-13 20:15:29 +00001824 return rn->info;
1825 }
1826 }
1827
1828 return NULL;
1829}
1830
1831int
paul68980082003-03-25 05:07:42 +00001832ospf_default_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001833{
1834 int *origin;
1835 struct prefix_ipv4 p;
1836 struct in_addr nexthop;
1837 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +00001838 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00001839
paul020709f2003-04-04 02:44:16 +00001840 ospf = ospf_lookup ();
1841
paul718e3742002-12-13 20:15:29 +00001842 /* Get originate flags. */
paul68980082003-03-25 05:07:42 +00001843 origin = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00001844
1845 p.family = AF_INET;
1846 p.prefix.s_addr = 0;
1847 p.prefixlen = 0;
1848
1849 if (*origin == DEFAULT_ORIGINATE_ALWAYS)
1850 {
1851 /* If there is no default route via redistribute,
1852 then originate AS-external-LSA with nexthop 0 (self). */
1853 nexthop.s_addr = 0;
1854 ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop);
1855 }
1856
paul020709f2003-04-04 02:44:16 +00001857 if ((ei = ospf_default_external_info (ospf)))
paul68980082003-03-25 05:07:42 +00001858 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00001859
1860 return 0;
1861}
1862
paul645878f2003-04-13 21:42:11 +00001863#ifdef HAVE_NSSA
1864/* Flush any NSSA LSAs for given prefix */
1865void
1866ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p)
1867{
1868 struct listnode *node;
1869 struct ospf_lsa *lsa;
1870 struct ospf_area *area;
1871
pauld7480322003-05-16 17:31:51 +00001872 for (node = listhead (ospf->areas); node; nextnode (node))
paul645878f2003-04-13 21:42:11 +00001873 {
pauld7480322003-05-16 17:31:51 +00001874 if (((area = getdata (node)) != NULL)
1875 && (area->external_routing == OSPF_AREA_NSSA))
1876 {
1877 if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix,
1878 ospf->router_id)))
1879 {
1880 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1881 zlog_warn ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB",
1882 inet_ntoa (p->prefix), p->prefixlen);
1883 continue;
1884 }
1885 ospf_ls_retransmit_delete_nbr_area (area, lsa);
1886 if (!IS_LSA_MAXAGE (lsa))
1887 {
1888 ospf_refresher_unregister_lsa (ospf, lsa);
1889 ospf_lsa_flush_area (lsa, area);
1890 }
1891 }
paul645878f2003-04-13 21:42:11 +00001892 }
1893}
1894#endif /* HAVE_NSSA */
1895
paul718e3742002-12-13 20:15:29 +00001896/* Flush an AS-external-LSA from LSDB and routing domain. */
1897void
paul68980082003-03-25 05:07:42 +00001898ospf_external_lsa_flush (struct ospf *ospf,
1899 u_char type, struct prefix_ipv4 *p,
paul718e3742002-12-13 20:15:29 +00001900 unsigned int ifindex, struct in_addr nexthop)
1901{
1902 struct ospf_lsa *lsa;
1903
1904 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1905 zlog_info ("LSA: Flushing AS-external-LSA %s/%d",
1906 inet_ntoa (p->prefix), p->prefixlen);
1907
1908 /* First lookup LSA from LSDB. */
paul68980082003-03-25 05:07:42 +00001909 if (!(lsa = ospf_external_info_find_lsa (ospf, p)))
paul718e3742002-12-13 20:15:29 +00001910 {
1911 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1912 zlog_warn ("LSA: There is no such AS-external-LSA %s/%d in LSDB",
1913 inet_ntoa (p->prefix), p->prefixlen);
1914 return;
1915 }
pauld7480322003-05-16 17:31:51 +00001916#ifdef HAVE_NSSA
1917 /* If LSA is selforiginated and there is NSSA area, flush
1918 * Type-7 LSA's at first. */
1919
1920 if (IS_LSA_SELF(lsa) && (ospf->anyNSSA))
1921 ospf_nssa_lsa_flush (ospf, p);
1922#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00001923
1924 /* Sweep LSA from Link State Retransmit List. */
paul68980082003-03-25 05:07:42 +00001925 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001926
1927 /* There must be no self-originated LSA in rtrs_external. */
1928#if 0
1929 /* Remove External route from Zebra. */
1930 ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);
1931#endif
1932
1933 if (!IS_LSA_MAXAGE (lsa))
1934 {
1935 /* Unregister LSA from Refresh queue. */
paul68980082003-03-25 05:07:42 +00001936 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001937
1938 /* Flush AS-external-LSA through AS. */
paul68980082003-03-25 05:07:42 +00001939 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001940 }
1941
1942 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
1943 zlog_info ("ospf_external_lsa_flush(): stop");
1944}
1945
1946void
paul68980082003-03-25 05:07:42 +00001947ospf_external_lsa_refresh_default (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001948{
1949 struct prefix_ipv4 p;
1950 struct external_info *ei;
1951 struct ospf_lsa *lsa;
1952
1953 p.family = AF_INET;
1954 p.prefixlen = 0;
1955 p.prefix.s_addr = 0;
1956
paul020709f2003-04-04 02:44:16 +00001957 ei = ospf_default_external_info (ospf);
paul68980082003-03-25 05:07:42 +00001958 lsa = ospf_external_info_find_lsa (ospf, &p);
paul718e3742002-12-13 20:15:29 +00001959
1960 if (ei)
1961 {
1962 if (lsa)
1963 {
1964 if (IS_DEBUG_OSPF_EVENT)
1965 zlog_info ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa);
paul68980082003-03-25 05:07:42 +00001966 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00001967 }
1968 else
1969 {
1970 if (IS_DEBUG_OSPF_EVENT)
1971 zlog_info ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
paul68980082003-03-25 05:07:42 +00001972 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00001973 }
1974 }
1975 else
1976 {
1977 if (lsa)
1978 {
1979 if (IS_DEBUG_OSPF_EVENT)
1980 zlog_info ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
paul68980082003-03-25 05:07:42 +00001981 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00001982 }
1983 }
1984}
1985
1986void
paul68980082003-03-25 05:07:42 +00001987ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force)
paul718e3742002-12-13 20:15:29 +00001988{
1989 struct route_node *rn;
1990 struct external_info *ei;
1991
1992 if (type != DEFAULT_ROUTE)
1993 if (EXTERNAL_INFO(type))
1994 /* Refresh each redistributed AS-external-LSAs. */
1995 for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
1996 if ((ei = rn->info))
1997 if (!is_prefix_default (&ei->p))
1998 {
1999 struct ospf_lsa *lsa;
2000
paul68980082003-03-25 05:07:42 +00002001 if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
2002 ospf_external_lsa_refresh (ospf, lsa, ei, force);
paul718e3742002-12-13 20:15:29 +00002003 else
paul68980082003-03-25 05:07:42 +00002004 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00002005 }
2006}
2007
2008/* Refresh AS-external-LSA. */
2009void
paul68980082003-03-25 05:07:42 +00002010ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
paul718e3742002-12-13 20:15:29 +00002011 struct external_info *ei, int force)
2012{
2013 struct ospf_lsa *new;
2014 int changed;
2015
2016 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00002017 if (!ospf_redistribute_check (ospf, ei, &changed))
paul718e3742002-12-13 20:15:29 +00002018 {
paul68980082003-03-25 05:07:42 +00002019 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
2020 ei->ifindex, ei->nexthop);
paul718e3742002-12-13 20:15:29 +00002021 return;
2022 }
2023
2024 if (!changed && !force)
2025 return;
2026
2027 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00002028 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002029
2030 /* Unregister AS-external-LSA from refresh-list. */
paul68980082003-03-25 05:07:42 +00002031 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002032
paul68980082003-03-25 05:07:42 +00002033 new = ospf_external_lsa_new (ospf, ei, &lsa->data->id);
paul718e3742002-12-13 20:15:29 +00002034
2035 if (new == NULL)
2036 {
2037 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2038 zlog_warn ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
2039 inet_ntoa (lsa->data->id));
2040 return;
2041 }
2042
2043 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
2044
2045 /* Record timestamp. */
2046 gettimeofday (&new->tv_orig, NULL);
2047
2048 /* Re-calculate checksum. */
2049 ospf_lsa_checksum (new->data);
2050
paul68980082003-03-25 05:07:42 +00002051 ospf_lsa_install (ospf, NULL, new); /* As type-5. */
paul718e3742002-12-13 20:15:29 +00002052
2053 /* Flood LSA through AS. */
paul68980082003-03-25 05:07:42 +00002054 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00002055
2056#ifdef HAVE_NSSA
2057 /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
paul68980082003-03-25 05:07:42 +00002058 if (ospf->anyNSSA)
2059 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */
paul718e3742002-12-13 20:15:29 +00002060#endif /* HAVE_NSSA */
2061
2062 /* Register slef-originated LSA to refresh queue. */
paul68980082003-03-25 05:07:42 +00002063 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002064
2065 /* Debug logging. */
2066 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2067 {
2068 zlog_info ("LSA[Type%d:%s]: AS-external-LSA refresh",
2069 new->data->type, inet_ntoa (new->data->id));
2070 ospf_lsa_header_dump (new->data);
2071 }
2072
2073 return;
2074}
2075
2076
2077/* LSA installation functions. */
2078
2079/* Install router-LSA to an area. */
2080struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002081ospf_router_lsa_install (struct ospf *ospf,
2082 struct ospf_lsa *new, int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002083{
2084 struct ospf_area *area = new->area;
2085
2086 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2087 The entire routing table must be recalculated, starting with
2088 the shortest path calculations for each area (not just the
2089 area whose link-state database has changed).
2090 */
2091 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002092 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002093
2094 if (IS_LSA_SELF (new))
2095 {
2096 /* Set router-LSA refresh timer. */
2097 OSPF_TIMER_OFF (area->t_router_lsa_self);
2098 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
2099 ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
2100
2101 /* Set self-originated router-LSA. */
2102 ospf_lsa_unlock (area->router_lsa_self);
2103 area->router_lsa_self = ospf_lsa_lock (new);
2104
2105 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2106 zlog_info("LSA[Type%d]: ID %s is self-originated",
2107 new->data->type, inet_ntoa (new->data->id));
2108 }
2109
2110 return new;
2111}
2112
2113#define OSPF_INTERFACE_TIMER_ON(T,F,V) \
2114 if (!(T)) \
2115 (T) = thread_add_timer (master, (F), oi, (V))
2116
2117/* Install network-LSA to an area. */
2118struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002119ospf_network_lsa_install (struct ospf *ospf,
2120 struct ospf_interface *oi,
paul718e3742002-12-13 20:15:29 +00002121 struct ospf_lsa *new,
2122 int rt_recalc)
2123{
2124
2125 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2126 The entire routing table must be recalculated, starting with
2127 the shortest path calculations for each area (not just the
2128 area whose link-state database has changed).
2129 */
2130 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002131 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002132
2133 /* We supposed that when LSA is originated by us, we pass the int
2134 for which it was originated. If LSA was received by flooding,
2135 the RECEIVED flag is set, so we do not link the LSA to the int. */
2136 if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
2137 {
2138 /* Set LSRefresh timer. */
2139 OSPF_TIMER_OFF (oi->t_network_lsa_self);
2140
2141 OSPF_INTERFACE_TIMER_ON (oi->t_network_lsa_self,
2142 ospf_network_lsa_refresh_timer,
2143 OSPF_LS_REFRESH_TIME);
2144
2145 ospf_lsa_unlock (oi->network_lsa_self);
2146 oi->network_lsa_self = ospf_lsa_lock (new);
2147 }
2148
2149 return new;
2150}
2151
2152/* Install summary-LSA to an area. */
2153struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002154ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2155 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002156{
paul718e3742002-12-13 20:15:29 +00002157 if (rt_recalc && !IS_LSA_SELF (new))
2158 {
2159 /* RFC 2328 Section 13.2 Summary-LSAs
2160 The best route to the destination described by the summary-
2161 LSA must be recalculated (see Section 16.5). If this
2162 destination is an AS boundary router, it may also be
2163 necessary to re-examine all the AS-external-LSAs.
2164 */
2165
2166#if 0
2167 /* This doesn't exist yet... */
2168 ospf_summary_incremental_update(new); */
2169#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002170 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002171#endif /* #if 0 */
2172
2173 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2174 zlog_info ("ospf_summary_lsa_install(): SPF scheduled");
2175 }
2176
2177 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002178 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002179
2180 return new;
2181}
2182
2183/* Install ASBR-summary-LSA to an area. */
2184struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002185ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2186 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002187{
2188 if (rt_recalc && !IS_LSA_SELF (new))
2189 {
2190 /* RFC 2328 Section 13.2 Summary-LSAs
2191 The best route to the destination described by the summary-
2192 LSA must be recalculated (see Section 16.5). If this
2193 destination is an AS boundary router, it may also be
2194 necessary to re-examine all the AS-external-LSAs.
2195 */
2196#if 0
2197 /* These don't exist yet... */
2198 ospf_summary_incremental_update(new);
2199 /* Isn't this done by the above call?
2200 - RFC 2328 Section 16.5 implies it should be */
2201 /* ospf_ase_calculate_schedule(); */
2202#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002203 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002204#endif /* #if 0 */
2205 }
2206
2207 /* register LSA to refresh-list. */
2208 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002209 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002210
2211 return new;
2212}
2213
2214/* Install AS-external-LSA. */
2215struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002216ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2217 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002218{
paul68980082003-03-25 05:07:42 +00002219 ospf_ase_register_external_lsa (new, ospf);
paul718e3742002-12-13 20:15:29 +00002220 /* If LSA is not self-originated, calculate an external route. */
2221 if (rt_recalc)
2222 {
2223 /* RFC 2328 Section 13.2 AS-external-LSAs
2224 The best route to the destination described by the AS-
2225 external-LSA must be recalculated (see Section 16.6).
2226 */
2227
2228 if (!IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002229 ospf_ase_incremental_update (ospf, new);
paul718e3742002-12-13 20:15:29 +00002230 }
2231
pauld7480322003-05-16 17:31:51 +00002232#ifdef HAVE_NSSA
2233 /* There is no point to register selforiginate Type-7 LSA for
2234 * refreshing. We rely on refreshing Type-5 LSA's */
2235 if (IS_LSA_SELF (new) && (new->data->type == OSPF_AS_NSSA_LSA))
2236 return new;
2237#endif /* HAVE_NSSA */
2238
paul718e3742002-12-13 20:15:29 +00002239 /* Register self-originated LSA to refresh queue. */
2240 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002241 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002242
2243 return new;
2244}
2245
2246void
paul68980082003-03-25 05:07:42 +00002247ospf_discard_from_db (struct ospf *ospf,
2248 struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002249{
2250 struct ospf_lsa *old;
2251
2252 old = ospf_lsdb_lookup (lsdb, lsa);
2253
2254 if (!old)
2255 return;
2256
2257 if (old->refresh_list >= 0)
paul68980082003-03-25 05:07:42 +00002258 ospf_refresher_unregister_lsa (ospf, old);
paul718e3742002-12-13 20:15:29 +00002259
2260 switch (old->data->type)
2261 {
2262 case OSPF_AS_EXTERNAL_LSA:
2263#ifdef HAVE_OPAQUE_LSA
2264 case OSPF_OPAQUE_AS_LSA:
2265#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002266 ospf_ls_retransmit_delete_nbr_as (ospf, old);
2267 ospf_ase_unregister_external_lsa (old, ospf);
paul718e3742002-12-13 20:15:29 +00002268 break;
pauld7480322003-05-16 17:31:51 +00002269#ifdef HAVE_NSSA
2270 case OSPF_AS_NSSA_LSA:
2271 ospf_ls_retransmit_delete_nbr_area (old->area, old);
2272 ospf_ase_unregister_external_lsa (old, ospf);
2273 break;
2274#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002275 default:
paul68980082003-03-25 05:07:42 +00002276 ospf_ls_retransmit_delete_nbr_area (old->area, old);
paul718e3742002-12-13 20:15:29 +00002277 break;
2278 }
2279
paul68980082003-03-25 05:07:42 +00002280 ospf_lsa_maxage_delete (ospf, old);
paul718e3742002-12-13 20:15:29 +00002281 ospf_lsa_discard (old);
2282}
2283
paul718e3742002-12-13 20:15:29 +00002284struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002285ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
2286 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002287{
2288 struct ospf_lsa *new = NULL;
2289 struct ospf_lsa *old = NULL;
2290 struct ospf_lsdb *lsdb = NULL;
2291 int rt_recalc;
2292
2293 /* Set LSDB. */
2294 switch (lsa->data->type)
2295 {
paul68980082003-03-25 05:07:42 +00002296#ifdef HAVE_NSSA
paulf2c80652002-12-13 21:44:27 +00002297 /* kevinm */
2298 case OSPF_AS_NSSA_LSA:
2299 if (lsa->area)
2300 lsdb = lsa->area->lsdb;
2301 else
paul68980082003-03-25 05:07:42 +00002302 lsdb = ospf->lsdb;
paulf2c80652002-12-13 21:44:27 +00002303 break;
paul68980082003-03-25 05:07:42 +00002304#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002305 case OSPF_AS_EXTERNAL_LSA:
2306#ifdef HAVE_OPAQUE_LSA
2307 case OSPF_OPAQUE_AS_LSA:
2308#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002309 lsdb = ospf->lsdb;
paul718e3742002-12-13 20:15:29 +00002310 break;
2311 default:
2312 lsdb = lsa->area->lsdb;
2313 break;
2314 }
2315
paul718e3742002-12-13 20:15:29 +00002316 assert (lsdb);
2317
2318 /* RFC 2328 13.2. Installing LSAs in the database
2319
2320 Installing a new LSA in the database, either as the result of
2321 flooding or a newly self-originated LSA, may cause the OSPF
2322 routing table structure to be recalculated. The contents of the
2323 new LSA should be compared to the old instance, if present. If
2324 there is no difference, there is no need to recalculate the
2325 routing table. When comparing an LSA to its previous instance,
2326 the following are all considered to be differences in contents:
2327
2328 o The LSA's Options field has changed.
2329
2330 o One of the LSA instances has LS age set to MaxAge, and
2331 the other does not.
2332
2333 o The length field in the LSA header has changed.
2334
2335 o The body of the LSA (i.e., anything outside the 20-byte
2336 LSA header) has changed. Note that this excludes changes
2337 in LS Sequence Number and LS Checksum.
2338
2339 */
2340 /* Look up old LSA and determine if any SPF calculation or incremental
2341 update is needed */
2342 old = ospf_lsdb_lookup (lsdb, lsa);
2343
2344 /* Do comparision and record if recalc needed. */
2345 rt_recalc = 0;
2346 if ( old == NULL || ospf_lsa_different(old, lsa))
2347 rt_recalc = 1;
2348
2349 /* discard old LSA from LSDB */
2350 if (old != NULL)
paul68980082003-03-25 05:07:42 +00002351 ospf_discard_from_db (ospf, lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002352
2353 /* Insert LSA to LSDB. */
2354 ospf_lsdb_add (lsdb, lsa);
2355 lsa->lsdb = lsdb;
2356
2357 /* Calculate Checksum if self-originated?. */
2358 if (IS_LSA_SELF (lsa))
2359 ospf_lsa_checksum (lsa->data);
2360
2361 /* Do LSA specific installation process. */
2362 switch (lsa->data->type)
2363 {
2364 case OSPF_ROUTER_LSA:
paul68980082003-03-25 05:07:42 +00002365 new = ospf_router_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002366 break;
2367 case OSPF_NETWORK_LSA:
2368 assert (oi);
paul68980082003-03-25 05:07:42 +00002369 new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002370 break;
2371 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002372 new = ospf_summary_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002373 break;
2374 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002375 new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002376 break;
2377 case OSPF_AS_EXTERNAL_LSA:
paul68980082003-03-25 05:07:42 +00002378 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002379 break;
2380#ifdef HAVE_OPAQUE_LSA
2381 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00002382 if (IS_LSA_SELF (lsa))
paul68980082003-03-25 05:07:42 +00002383 lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */
paul09e4efd2003-01-18 00:12:02 +00002384 else
paul68980082003-03-25 05:07:42 +00002385 ; /* Incoming "oi" for this LSA has set at LSUpd reception. */
paul09e4efd2003-01-18 00:12:02 +00002386 /* Fallthrough */
paul718e3742002-12-13 20:15:29 +00002387 case OSPF_OPAQUE_AREA_LSA:
2388 case OSPF_OPAQUE_AS_LSA:
2389 new = ospf_opaque_lsa_install (lsa, rt_recalc);
2390 break;
2391#endif /* HAVE_OPAQUE_LSA */
2392 default: /* NSSA, or type-6,8,9....nothing special */
2393#ifdef HAVE_NSSA
paul68980082003-03-25 05:07:42 +00002394 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002395#endif /* HAVE_NSSA */
2396 break;
2397 }
2398
2399 if (new == NULL)
2400 return new; /* Installation failed, cannot proceed further -- endo. */
2401
2402 /* Debug logs. */
2403 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2404 {
2405 char area_str[INET_ADDRSTRLEN];
2406
2407 switch (lsa->data->type)
2408 {
2409 case OSPF_AS_EXTERNAL_LSA:
2410#ifdef HAVE_OPAQUE_LSA
2411 case OSPF_OPAQUE_AS_LSA:
2412#endif /* HAVE_OPAQUE_LSA */
paulf2c80652002-12-13 21:44:27 +00002413#ifdef HAVE_NSSA
2414 case OSPF_AS_NSSA_LSA:
paul68980082003-03-25 05:07:42 +00002415#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002416 zlog_info ("LSA[%s]: Install %s",
2417 dump_lsa_key (new),
2418 LOOKUP (ospf_lsa_type_msg, new->data->type));
2419 break;
2420 default:
2421 strcpy (area_str, inet_ntoa (new->area->area_id));
2422 zlog_info ("LSA[%s]: Install %s to Area %s",
2423 dump_lsa_key (new),
2424 LOOKUP (ospf_lsa_type_msg, new->data->type), area_str);
2425 break;
2426 }
2427 }
2428
2429 /* If received LSA' ls_age is MaxAge, set LSA on MaxAge LSA list. */
2430 if (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new))
2431 {
2432 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2433 zlog_info ("LSA[Type%d:%s]: Install LSA, MaxAge",
2434 new->data->type, inet_ntoa (new->data->id));
paul68980082003-03-25 05:07:42 +00002435 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002436 }
2437
2438 return new;
2439}
2440
2441
2442int
paul68980082003-03-25 05:07:42 +00002443ospf_check_nbr_status (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002444{
2445 listnode node;
2446
paul68980082003-03-25 05:07:42 +00002447 for (node = listhead (ospf->oiflist); node; node = nextnode (node))
paul718e3742002-12-13 20:15:29 +00002448 {
2449 struct ospf_interface *oi = getdata (node);
2450 struct route_node *rn;
2451 struct ospf_neighbor *nbr;
2452
2453 if (ospf_if_is_enable (oi))
2454 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2455 if ((nbr = rn->info) != NULL)
2456 if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading)
2457 {
2458 route_unlock_node (rn);
2459 return 0;
2460 }
2461 }
2462
2463 return 1;
2464}
2465
2466
2467#ifdef ORIGINAL_CODING
2468/* This function flood the maxaged LSA to DR. */
2469void
2470ospf_maxage_flood (struct ospf_lsa *lsa)
2471{
2472 switch (lsa->data->type)
2473 {
2474 case OSPF_ROUTER_LSA:
2475 case OSPF_NETWORK_LSA:
2476 case OSPF_SUMMARY_LSA:
2477 case OSPF_ASBR_SUMMARY_LSA:
2478#ifdef HAVE_NSSA
2479 case OSPF_AS_NSSA_LSA:
2480#endif /* HAVE_NSSA */
2481#ifdef HAVE_OPAQUE_LSA
2482 case OSPF_OPAQUE_LINK_LSA:
2483 case OSPF_OPAQUE_AREA_LSA:
2484#endif /* HAVE_OPAQUE_LSA */
2485 ospf_flood_through_area (lsa->area, NULL, lsa);
2486 break;
2487 case OSPF_AS_EXTERNAL_LSA:
2488#ifdef HAVE_OPAQUE_LSA
2489 case OSPF_OPAQUE_AS_LSA:
2490#endif /* HAVE_OPAQUE_LSA */
2491 ospf_flood_through_as (NULL, lsa);
2492 break;
2493 default:
2494 break;
2495 }
2496}
2497#endif /* ORIGINAL_CODING */
2498
2499int
2500ospf_maxage_lsa_remover (struct thread *thread)
2501{
paul68980082003-03-25 05:07:42 +00002502 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00002503 listnode node;
2504 listnode next;
2505 int reschedule = 0;
2506
paul68980082003-03-25 05:07:42 +00002507 ospf->t_maxage = NULL;
paul718e3742002-12-13 20:15:29 +00002508
2509 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2510 zlog_info ("LSA[MaxAge]: remover Start");
2511
paul68980082003-03-25 05:07:42 +00002512 reschedule = !ospf_check_nbr_status (ospf);
paul718e3742002-12-13 20:15:29 +00002513
2514 if (!reschedule)
paul68980082003-03-25 05:07:42 +00002515 for (node = listhead (ospf->maxage_lsa); node; node = next)
paul718e3742002-12-13 20:15:29 +00002516 {
2517 struct ospf_lsa *lsa = getdata (node);
2518 next = node->next;
2519
2520 if (lsa->retransmit_counter > 0)
2521 {
2522 reschedule = 1;
2523 continue;
2524 }
2525
2526 /* Remove LSA from the LSDB */
2527 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
2528 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2529 zlog_info ("LSA[Type%d:%s]: This LSA is self-originated: ",
2530 lsa->data->type, inet_ntoa (lsa->data->id));
2531
2532 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2533 zlog_info ("LSA[Type%d:%s]: MaxAge LSA removed from list",
2534 lsa->data->type, inet_ntoa (lsa->data->id));
2535
2536 /* Flood max age LSA. */
2537#ifdef ORIGINAL_CODING
2538 ospf_maxage_flood (lsa);
2539#else /* ORIGINAL_CODING */
paul68980082003-03-25 05:07:42 +00002540 ospf_flood_through (ospf, NULL, lsa);
paul718e3742002-12-13 20:15:29 +00002541#endif /* ORIGINAL_CODING */
2542
2543 /* Remove from lsdb. */
paul68980082003-03-25 05:07:42 +00002544 ospf_discard_from_db (ospf, lsa->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002545 ospf_lsdb_delete (lsa->lsdb, lsa);
2546 }
2547
2548 /* A MaxAge LSA must be removed immediately from the router's link
2549 state database as soon as both a) it is no longer contained on any
2550 neighbor Link state retransmission lists and b) none of the router's
2551 neighbors are in states Exchange or Loading. */
2552 if (reschedule)
paul68980082003-03-25 05:07:42 +00002553 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002554
2555 return 0;
2556}
2557
2558int
paul68980082003-03-25 05:07:42 +00002559ospf_lsa_maxage_exist (struct ospf *ospf, struct ospf_lsa *new)
paul718e3742002-12-13 20:15:29 +00002560{
2561 listnode node;
2562
paul68980082003-03-25 05:07:42 +00002563 for (node = listhead (ospf->maxage_lsa); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00002564 if (((struct ospf_lsa *) node->data) == new)
2565 return 1;
2566
2567 return 0;
2568}
2569
2570void
paul68980082003-03-25 05:07:42 +00002571ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002572{
2573 listnode n;
2574
paul68980082003-03-25 05:07:42 +00002575 if ((n = listnode_lookup (ospf->maxage_lsa, lsa)))
paul718e3742002-12-13 20:15:29 +00002576 {
paul68980082003-03-25 05:07:42 +00002577 list_delete_node (ospf->maxage_lsa, n);
paul718e3742002-12-13 20:15:29 +00002578 ospf_lsa_unlock (lsa);
2579 }
2580}
2581
2582void
paul68980082003-03-25 05:07:42 +00002583ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002584{
2585 /* When we saw a MaxAge LSA flooded to us, we put it on the list
2586 and schedule the MaxAge LSA remover. */
paul68980082003-03-25 05:07:42 +00002587 if (ospf_lsa_maxage_exist (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00002588 {
2589 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2590 zlog_info ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list",
2591 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
2592 return;
2593 }
2594
paul68980082003-03-25 05:07:42 +00002595 listnode_add (ospf->maxage_lsa, ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00002596
2597 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2598 zlog_info ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
2599
paul68980082003-03-25 05:07:42 +00002600 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002601}
2602
2603int
paul68980082003-03-25 05:07:42 +00002604ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002605{
2606#ifdef HAVE_NSSA
2607 /* Stay away from any Local Translated Type-7 LSAs */
2608 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
2609 return 0;
2610#endif /* HAVE_NSSA */
2611
2612 if (IS_LSA_MAXAGE (lsa))
2613 /* Self-originated LSAs should NOT time-out instead,
2614 they're flushed and submitted to the max_age list explicitly. */
paul68980082003-03-25 05:07:42 +00002615 if (!ospf_lsa_is_self_originated (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00002616 {
2617 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
2618 zlog_info("LSA[%s]: is MaxAge", dump_lsa_key (lsa));
2619
2620 switch (lsa->data->type)
2621 {
paul718e3742002-12-13 20:15:29 +00002622#ifdef HAVE_OPAQUE_LSA
paul37163d62003-02-03 18:40:56 +00002623 case OSPF_OPAQUE_LINK_LSA:
2624 case OSPF_OPAQUE_AREA_LSA:
paul718e3742002-12-13 20:15:29 +00002625 case OSPF_OPAQUE_AS_LSA:
paul09e4efd2003-01-18 00:12:02 +00002626 /*
2627 * As a general rule, whenever network topology has changed
2628 * (due to an LSA removal in this case), routing recalculation
2629 * should be triggered. However, this is not true for opaque
2630 * LSAs. Even if an opaque LSA instance is going to be removed
2631 * from the routing domain, it does not mean a change in network
2632 * topology, and thus, routing recalculation is not needed here.
2633 */
2634 break;
paul718e3742002-12-13 20:15:29 +00002635#endif /* HAVE_OPAQUE_LSA */
paul09e4efd2003-01-18 00:12:02 +00002636 case OSPF_AS_EXTERNAL_LSA:
paul68980082003-03-25 05:07:42 +00002637#ifdef HAVE_NSSA
2638 case OSPF_AS_NSSA_LSA:
2639#endif /* HAVE_NSSA */
2640 ospf_ase_incremental_update (ospf, lsa);
2641 break;
paul718e3742002-12-13 20:15:29 +00002642 default:
paul68980082003-03-25 05:07:42 +00002643 ospf_spf_calculate_schedule (ospf);
2644 break;
paul718e3742002-12-13 20:15:29 +00002645 }
paul68980082003-03-25 05:07:42 +00002646 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002647 }
2648
2649 return 0;
2650}
2651
2652/* Periodical check of MaxAge LSA. */
2653int
paul68980082003-03-25 05:07:42 +00002654ospf_lsa_maxage_walker (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00002655{
paul68980082003-03-25 05:07:42 +00002656 struct ospf *ospf = THREAD_ARG (thread);
2657 struct route_node *rn;
2658 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +00002659 listnode node;
2660
paul68980082003-03-25 05:07:42 +00002661 ospf->t_maxage_walker = NULL;
paul718e3742002-12-13 20:15:29 +00002662
paul68980082003-03-25 05:07:42 +00002663 for (node = listhead (ospf->areas); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00002664 {
2665 struct ospf_area *area = node->data;
2666
paul68980082003-03-25 05:07:42 +00002667 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
2668 ospf_lsa_maxage_walker_remover (ospf, lsa);
2669 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
2670 ospf_lsa_maxage_walker_remover (ospf, lsa);
2671 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
2672 ospf_lsa_maxage_walker_remover (ospf, lsa);
2673 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
2674 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002675#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002676 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
2677 ospf_lsa_maxage_walker_remover (ospf, lsa);
2678 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
2679 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002680#endif /* HAVE_OPAQUE_LSA */
paul4fb949e2003-05-10 20:06:51 +00002681#ifdef HAVE_NSSA
2682 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
2683 ospf_lsa_maxage_walker_remover (ospf, lsa);
2684#endif /* HAVE_NSSA */
paul718e3742002-12-13 20:15:29 +00002685 }
2686
paul4fb949e2003-05-10 20:06:51 +00002687 /* for AS-external-LSAs. */
paul68980082003-03-25 05:07:42 +00002688 if (ospf->lsdb)
2689 {
2690 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
2691 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002692#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002693 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
2694 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002695#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002696 }
paul718e3742002-12-13 20:15:29 +00002697
paul68980082003-03-25 05:07:42 +00002698 OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker,
2699 OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +00002700 return 0;
2701}
2702
paul68980082003-03-25 05:07:42 +00002703struct ospf_lsa *
2704ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type,
2705 struct prefix_ipv4 *p, struct in_addr router_id)
paul718e3742002-12-13 20:15:29 +00002706{
paul68980082003-03-25 05:07:42 +00002707 struct ospf_lsa *lsa;
2708 struct in_addr mask, id;
2709 struct lsa_header_mask
2710 {
2711 struct lsa_header header;
2712 struct in_addr mask;
2713 } *hmask;
paul718e3742002-12-13 20:15:29 +00002714
paul68980082003-03-25 05:07:42 +00002715 lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id);
2716 if (lsa == NULL)
2717 return NULL;
paul718e3742002-12-13 20:15:29 +00002718
paul68980082003-03-25 05:07:42 +00002719 masklen2ip (p->prefixlen, &mask);
paul718e3742002-12-13 20:15:29 +00002720
paul68980082003-03-25 05:07:42 +00002721 hmask = (struct lsa_header_mask *) lsa->data;
paul718e3742002-12-13 20:15:29 +00002722
paul68980082003-03-25 05:07:42 +00002723 if (mask.s_addr != hmask->mask.s_addr)
2724 {
2725 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
2726 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id);
2727 if (!lsa)
2728 return NULL;
2729 }
paul718e3742002-12-13 20:15:29 +00002730
paul68980082003-03-25 05:07:42 +00002731 return lsa;
paul718e3742002-12-13 20:15:29 +00002732}
2733
2734struct ospf_lsa *
2735ospf_lsa_lookup (struct ospf_area *area, u_int32_t type,
2736 struct in_addr id, struct in_addr adv_router)
2737{
paule05fba42003-04-13 20:20:53 +00002738 struct ospf *ospf = ospf_lookup();
2739 assert(ospf);
2740
paul718e3742002-12-13 20:15:29 +00002741 switch (type)
2742 {
2743 case OSPF_ROUTER_LSA:
2744 case OSPF_NETWORK_LSA:
2745 case OSPF_SUMMARY_LSA:
2746 case OSPF_ASBR_SUMMARY_LSA:
2747#ifdef HAVE_NSSA
2748 case OSPF_AS_NSSA_LSA:
2749#endif /* HAVE_NSSA */
2750#ifdef HAVE_OPAQUE_LSA
2751 case OSPF_OPAQUE_LINK_LSA:
2752 case OSPF_OPAQUE_AREA_LSA:
2753#endif /* HAVE_OPAQUE_LSA */
2754 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router);
2755 break;
2756 case OSPF_AS_EXTERNAL_LSA:
2757#ifdef HAVE_OPAQUE_LSA
2758 case OSPF_OPAQUE_AS_LSA:
2759#endif /* HAVE_OPAQUE_LSA */
paule05fba42003-04-13 20:20:53 +00002760 return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router);
paul718e3742002-12-13 20:15:29 +00002761 break;
2762 default:
2763 break;
2764 }
2765
2766 return NULL;
2767}
2768
2769struct ospf_lsa *
2770ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type,
2771 struct in_addr id)
2772{
2773 struct ospf_lsa *lsa;
2774 struct route_node *rn;
2775
2776 switch (type)
2777 {
2778 case OSPF_ROUTER_LSA:
2779 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
2780 break;
2781 case OSPF_NETWORK_LSA:
2782 for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn))
2783 if ((lsa = rn->info))
2784 if (IPV4_ADDR_SAME (&lsa->data->id, &id))
2785 {
2786 route_unlock_node (rn);
2787 return lsa;
2788 }
2789 break;
2790 case OSPF_SUMMARY_LSA:
2791 case OSPF_ASBR_SUMMARY_LSA:
2792 /* Currently not used. */
2793 assert (1);
2794 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
2795 break;
2796 case OSPF_AS_EXTERNAL_LSA:
2797#ifdef HAVE_OPAQUE_LSA
2798 case OSPF_OPAQUE_LINK_LSA:
2799 case OSPF_OPAQUE_AREA_LSA:
2800 case OSPF_OPAQUE_AS_LSA:
2801 /* Currently not used. */
2802 break;
2803#endif /* HAVE_OPAQUE_LSA */
2804 default:
2805 break;
2806 }
2807
2808 return NULL;
2809}
2810
2811struct ospf_lsa *
2812ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah)
2813{
2814 struct ospf_lsa *match;
2815
2816#ifdef HAVE_OPAQUE_LSA
2817 /*
2818 * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11)
2819 * is redefined to have two subfields; opaque-type and opaque-id.
2820 * However, it is harmless to treat the two sub fields together, as if
2821 * they two were forming a unique LSA-ID.
2822 */
2823#endif /* HAVE_OPAQUE_LSA */
2824
2825 match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router);
2826
2827 if (match == NULL)
2828 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
2829 zlog_info ("LSA[Type%d:%s]: Lookup by header, NO MATCH",
2830 lsah->type, inet_ntoa (lsah->id));
2831
2832 return match;
2833}
2834
2835/* return +n, l1 is more recent.
2836 return -n, l2 is more recent.
2837 return 0, l1 and l2 is identical. */
2838int
2839ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
2840{
2841 int r;
2842 int x, y;
2843
2844 if (l1 == NULL && l2 == NULL)
2845 return 0;
2846 if (l1 == NULL)
2847 return -1;
2848 if (l2 == NULL)
2849 return 1;
2850
2851 /* compare LS sequence number. */
2852 x = (int) ntohl (l1->data->ls_seqnum);
2853 y = (int) ntohl (l2->data->ls_seqnum);
2854 if (x > y)
2855 return 1;
2856 if (x < y)
2857 return -1;
2858
2859 /* compare LS checksum. */
2860 r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
2861 if (r)
2862 return r;
2863
2864 /* compare LS age. */
2865 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
2866 return 1;
2867 else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
2868 return -1;
2869
2870 /* compare LS age with MaxAgeDiff. */
2871 if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
2872 return -1;
2873 else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
2874 return 1;
2875
2876 /* LSAs are identical. */
2877 return 0;
2878}
2879
2880/* If two LSAs are different, return 1, otherwise return 0. */
2881int
2882ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
2883{
2884 char *p1, *p2;
2885 assert (l1);
2886 assert (l2);
2887 assert (l1->data);
2888 assert (l2->data);
2889
2890 if (l1->data->options != l2->data->options)
2891 return 1;
2892
2893 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
2894 return 1;
2895
2896 if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
2897 return 1;
2898
2899 if (l1->data->length != l2->data->length)
2900 return 1;
2901
2902 if (l1->data->length == 0)
2903 return 1;
2904
pauld1825832003-04-03 01:27:01 +00002905 assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002906
2907 p1 = (char *) l1->data;
2908 p2 = (char *) l2->data;
2909
2910 if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
2911 ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
2912 return 1;
2913
2914 return 0;
2915}
2916
2917#ifdef ORIGINAL_CODING
2918void
2919ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr,
2920 struct ospf_lsa *self,
2921 struct ospf_lsa *new)
2922{
2923 u_int32_t seqnum;
2924
2925 /* Adjust LS Sequence Number. */
2926 seqnum = ntohl (new->data->ls_seqnum) + 1;
2927 self->data->ls_seqnum = htonl (seqnum);
2928
2929 /* Recalculate LSA checksum. */
2930 ospf_lsa_checksum (self->data);
2931
2932 /* Reflooding LSA. */
2933 /* RFC2328 Section 13.3
2934 On non-broadcast networks, separate Link State Update
2935 packets must be sent, as unicasts, to each adjacent neighbor
2936 (i.e., those in state Exchange or greater). The destination
2937 IP addresses for these packets are the neighbors' IP
2938 addresses. */
2939 if (nbr->oi->type == OSPF_IFTYPE_NBMA)
2940 {
2941 struct route_node *rn;
2942 struct ospf_neighbor *onbr;
2943
2944 for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn))
2945 if ((onbr = rn->info) != NULL)
2946 if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange)
2947 ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT);
2948 }
2949 else
2950 ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT);
2951
2952 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2953 zlog_info ("LSA[Type%d:%s]: Flush self-originated LSA",
2954 self->data->type, inet_ntoa (self->data->id));
2955}
2956#else /* ORIGINAL_CODING */
2957static int
paul68980082003-03-25 05:07:42 +00002958ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002959{
2960 if (lsa == NULL || !IS_LSA_SELF (lsa))
2961 return 0;
2962
2963 if (IS_DEBUG_OSPF_EVENT)
2964 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
2965
2966 /* Force given lsa's age to MaxAge. */
2967 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2968
2969 switch (lsa->data->type)
2970 {
2971#ifdef HAVE_OPAQUE_LSA
2972 case OSPF_OPAQUE_LINK_LSA:
2973 case OSPF_OPAQUE_AREA_LSA:
2974 case OSPF_OPAQUE_AS_LSA:
2975 ospf_opaque_lsa_refresh (lsa);
2976 break;
2977#endif /* HAVE_OPAQUE_LSA */
2978 default:
paul68980082003-03-25 05:07:42 +00002979 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002980 break;
2981 }
2982
2983 return 0;
2984}
2985
2986void
paul68980082003-03-25 05:07:42 +00002987ospf_flush_self_originated_lsas_now (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002988{
2989 listnode n1, n2;
2990 struct ospf_area *area;
2991 struct ospf_interface *oi;
2992 struct ospf_lsa *lsa;
paul68980082003-03-25 05:07:42 +00002993 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +00002994 int need_to_flush_ase = 0;
2995
paul68980082003-03-25 05:07:42 +00002996 for (n1 = listhead (ospf->areas); n1; nextnode (n1))
paul718e3742002-12-13 20:15:29 +00002997 {
2998 if ((area = getdata (n1)) == NULL)
2999 continue;
3000
3001 if ((lsa = area->router_lsa_self) != NULL)
3002 {
3003 if (IS_DEBUG_OSPF_EVENT)
3004 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
3005
3006 ospf_lsa_flush_area (lsa, area);
3007 ospf_lsa_unlock (area->router_lsa_self);
3008 area->router_lsa_self = NULL;
3009 OSPF_TIMER_OFF (area->t_router_lsa_self);
3010 }
3011
3012 for (n2 = listhead (area->oiflist); n2; nextnode (n2))
3013 {
3014 if ((oi = getdata (n2)) == NULL)
3015 continue;
3016
3017 if ((lsa = oi->network_lsa_self) != NULL
3018 && oi->state == ISM_DR
3019 && oi->full_nbrs > 0)
3020 {
3021 if (IS_DEBUG_OSPF_EVENT)
3022 zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
3023
3024 ospf_lsa_flush_area (oi->network_lsa_self, area);
3025 ospf_lsa_unlock (oi->network_lsa_self);
3026 oi->network_lsa_self = NULL;
3027 OSPF_TIMER_OFF (oi->t_network_lsa_self);
3028 }
3029
3030 if (oi->type != OSPF_IFTYPE_VIRTUALLINK
3031 && area->external_routing == OSPF_AREA_DEFAULT)
3032 need_to_flush_ase = 1;
3033 }
3034
paul68980082003-03-25 05:07:42 +00003035 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
3036 ospf_lsa_flush_schedule (ospf, lsa);
3037 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
3038 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003039#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003040 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
3041 ospf_lsa_flush_schedule (ospf, lsa);
3042 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
3043 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003044#endif /* HAVE_OPAQUE_LSA */
3045 }
3046
3047 if (need_to_flush_ase)
3048 {
paul68980082003-03-25 05:07:42 +00003049 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
3050 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003051#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003052 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
3053 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003054#endif /* HAVE_OPAQUE_LSA */
3055 }
3056
3057 /*
3058 * Make sure that the MaxAge LSA remover is executed immediately,
3059 * without conflicting to other threads.
3060 */
paul68980082003-03-25 05:07:42 +00003061 if (ospf->t_maxage != NULL)
paul718e3742002-12-13 20:15:29 +00003062 {
paul68980082003-03-25 05:07:42 +00003063 OSPF_TIMER_OFF (ospf->t_maxage);
3064 thread_execute (master, ospf_maxage_lsa_remover, ospf, 0);
paul718e3742002-12-13 20:15:29 +00003065 }
3066
3067 return;
3068}
3069#endif /* ORIGINAL_CODING */
3070
3071/* If there is self-originated LSA, then return 1, otherwise return 0. */
3072/* An interface-independent version of ospf_lsa_is_self_originated */
3073int
paul68980082003-03-25 05:07:42 +00003074ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003075{
3076 listnode node;
3077
3078 /* This LSA is already checked. */
3079 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
3080 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3081
3082 /* Make sure LSA is self-checked. */
3083 SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);
3084
3085 /* AdvRouter and Router ID is the same. */
paul68980082003-03-25 05:07:42 +00003086 if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003087 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3088
3089 /* LSA is router-LSA. */
3090 else if (lsa->data->type == OSPF_ROUTER_LSA &&
paul68980082003-03-25 05:07:42 +00003091 IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003092 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3093
3094 /* LSA is network-LSA. Compare Link ID with all interfaces. */
3095 else if (lsa->data->type == OSPF_NETWORK_LSA)
paul68980082003-03-25 05:07:42 +00003096 for (node = listhead (ospf->oiflist); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00003097 {
3098 struct ospf_interface *oi = getdata (node);
3099
3100 /* Ignore virtual link. */
3101 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
3102 if (oi->address->family == AF_INET)
3103 if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4))
3104 {
3105 /* to make it easier later */
3106 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3107 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3108 }
3109 }
3110
3111 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3112}
3113
3114/* Get unique Link State ID. */
3115struct in_addr
paul68980082003-03-25 05:07:42 +00003116ospf_lsa_unique_id (struct ospf *ospf,
3117 struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +00003118{
3119 struct ospf_lsa *lsa;
3120 struct in_addr mask, id;
3121
3122 id = p->prefix;
3123
3124 /* Check existence of LSA instance. */
paul68980082003-03-25 05:07:42 +00003125 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003126 if (lsa)
3127 {
3128 struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
3129 if (ip_masklen (al->mask) == p->prefixlen)
3130 {
3131 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
3132 zlog_warn ("ospf_lsa_unique_id(): "
3133 "Can't get Link State ID for %s/%d",
3134 inet_ntoa (p->prefix), p->prefixlen);
3135 /* id.s_addr = 0; */
3136 id.s_addr = 0xffffffff;
3137 return id;
3138 }
3139 /* Masklen differs, then apply wildcard mask to Link State ID. */
3140 else
3141 {
3142 masklen2ip (p->prefixlen, &mask);
3143
3144 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
paul68980082003-03-25 05:07:42 +00003145 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type,
3146 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003147 if (lsa)
3148 {
3149 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
3150 zlog_warn ("ospf_lsa_unique_id(): "
3151 "Can't get Link State ID for %s/%d",
3152 inet_ntoa (p->prefix), p->prefixlen);
3153 /* id.s_addr = 0; */
3154 id.s_addr = 0xffffffff;
3155 return id;
3156 }
3157 }
3158 }
3159
3160 return id;
3161}
3162
3163
3164#define LSA_ACTION_ORIGN_RTR 1
3165#define LSA_ACTION_ORIGN_NET 2
3166#define LSA_ACTION_FLOOD_AREA 3
3167#define LSA_ACTION_FLOOD_AS 4
3168#define LSA_ACTION_FLUSH_AREA 5
3169#define LSA_ACTION_FLUSH_AS 6
3170
3171struct lsa_action
3172{
3173 u_char action;
3174 struct ospf_area *area;
3175 struct ospf_interface *oi;
3176 struct ospf_lsa *lsa;
3177};
3178
3179int
3180ospf_lsa_action (struct thread *t)
3181{
3182 struct lsa_action *data;
paul020709f2003-04-04 02:44:16 +00003183 struct ospf *ospf;
3184
3185 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00003186
3187 data = THREAD_ARG (t);
3188
3189 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
3190 zlog_info ("LSA[Action]: Performing scheduled LSA action: %d",
3191 data->action);
3192
3193 switch (data->action)
3194 {
3195 case LSA_ACTION_ORIGN_RTR:
3196 ospf_router_lsa_refresh (data->area->router_lsa_self);
3197 break;
3198 case LSA_ACTION_ORIGN_NET:
3199 ospf_network_lsa_originate (data->oi);
3200 break;
3201 case LSA_ACTION_FLOOD_AREA:
3202 ospf_flood_through_area (data->area, NULL, data->lsa);
3203 break;
3204 case LSA_ACTION_FLOOD_AS:
paul68980082003-03-25 05:07:42 +00003205 ospf_flood_through_as (ospf, NULL, data->lsa);
paul718e3742002-12-13 20:15:29 +00003206 break;
3207 case LSA_ACTION_FLUSH_AREA:
3208 ospf_lsa_flush_area (data->lsa, data->area);
3209 break;
3210 case LSA_ACTION_FLUSH_AS:
paul68980082003-03-25 05:07:42 +00003211 ospf_lsa_flush_as (ospf, data->lsa);
paul718e3742002-12-13 20:15:29 +00003212 break;
3213 }
3214
3215 ospf_lsa_unlock (data->lsa);
3216 XFREE (MTYPE_OSPF_MESSAGE, data);
3217 return 0;
3218}
3219
3220void
3221ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa)
3222{
3223 struct lsa_action *data;
3224
3225 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3226 memset (data, 0, sizeof (struct lsa_action));
3227
3228 data->action = LSA_ACTION_FLOOD_AREA;
3229 data->area = area;
3230 data->lsa = ospf_lsa_lock (lsa);
3231
3232 thread_add_event (master, ospf_lsa_action, data, 0);
3233}
3234
3235void
3236ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
3237{
3238 struct lsa_action *data;
3239
3240 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3241 memset (data, 0, sizeof (struct lsa_action));
3242
3243 data->action = LSA_ACTION_FLUSH_AREA;
3244 data->area = area;
3245 data->lsa = ospf_lsa_lock (lsa);
3246
3247 thread_add_event (master, ospf_lsa_action, data, 0);
3248}
3249
3250
3251/* LSA Refreshment functions. */
3252void
paul68980082003-03-25 05:07:42 +00003253ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003254{
3255 struct external_info *ei;
3256 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3257
3258 switch (lsa->data->type)
3259 {
3260 /* Router and Network LSAs are processed differently. */
3261 case OSPF_ROUTER_LSA:
3262 case OSPF_NETWORK_LSA:
3263 break;
3264 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003265 ospf_summary_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003266 break;
3267 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003268 ospf_summary_asbr_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003269 break;
3270 case OSPF_AS_EXTERNAL_LSA:
3271 ei = ospf_external_info_check (lsa);
3272 if (ei)
paul68980082003-03-25 05:07:42 +00003273 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00003274 else
paul68980082003-03-25 05:07:42 +00003275 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003276 break;
3277#ifdef HAVE_OPAQUE_LSA
3278 case OSPF_OPAQUE_LINK_LSA:
3279 case OSPF_OPAQUE_AREA_LSA:
3280 case OSPF_OPAQUE_AS_LSA:
3281 ospf_opaque_lsa_refresh (lsa);
3282 break;
pauld7480322003-05-16 17:31:51 +00003283#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00003284 default:
3285 break;
paul718e3742002-12-13 20:15:29 +00003286 }
3287}
3288
3289void
paul68980082003-03-25 05:07:42 +00003290ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003291{
3292 u_int16_t index, current_index;
3293
3294 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3295
3296 if (lsa->refresh_list < 0)
3297 {
3298 int delay;
3299
3300 if (LS_AGE (lsa) == 0 &&
3301 ntohl (lsa->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)
3302 /* Randomize first update by OSPF_LS_REFRESH_SHIFT factor */
3303 delay = OSPF_LS_REFRESH_SHIFT + (random () % OSPF_LS_REFRESH_TIME);
3304 else
3305 /* Randomize another updates by +-OSPF_LS_REFRESH_JITTER factor */
3306 delay = OSPF_LS_REFRESH_TIME - LS_AGE (lsa) - OSPF_LS_REFRESH_JITTER
3307 + (random () % (2*OSPF_LS_REFRESH_JITTER));
3308
3309 if (delay < 0)
3310 delay = 0;
3311
paul68980082003-03-25 05:07:42 +00003312 current_index = ospf->lsa_refresh_queue.index +
3313 (time (NULL) - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
paul718e3742002-12-13 20:15:29 +00003314
3315 index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
3316 % (OSPF_LSA_REFRESHER_SLOTS);
3317
3318 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3319 zlog_info ("LSA[Refresh]: lsa with age %d added to index %d",
3320 LS_AGE (lsa), index);
paul68980082003-03-25 05:07:42 +00003321 if (!ospf->lsa_refresh_queue.qs[index])
3322 ospf->lsa_refresh_queue.qs[index] = list_new ();
3323 listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00003324 lsa->refresh_list = index;
paulf2c80652002-12-13 21:44:27 +00003325 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3326 zlog_info ("LSA[Refresh]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa, index);
paul718e3742002-12-13 20:15:29 +00003327 }
3328}
3329
3330void
paul68980082003-03-25 05:07:42 +00003331ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003332{
3333 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3334 if (lsa->refresh_list >= 0)
3335 {
paul68980082003-03-25 05:07:42 +00003336 list refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list];
paul718e3742002-12-13 20:15:29 +00003337 listnode_delete (refresh_list, lsa);
3338 if (!listcount (refresh_list))
3339 {
3340 list_free (refresh_list);
paul68980082003-03-25 05:07:42 +00003341 ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
paul718e3742002-12-13 20:15:29 +00003342 }
3343 ospf_lsa_unlock (lsa);
3344 lsa->refresh_list = -1;
3345 }
3346}
3347
3348int
3349ospf_lsa_refresh_walker (struct thread *t)
3350{
3351 list refresh_list;
3352 listnode node;
paul68980082003-03-25 05:07:42 +00003353 struct ospf *ospf = THREAD_ARG (t);
paul718e3742002-12-13 20:15:29 +00003354 int i;
3355 list lsa_to_refresh = list_new ();
3356
3357 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3358 zlog_info ("LSA[Refresh]:ospf_lsa_refresh_walker(): start");
3359
3360
paul68980082003-03-25 05:07:42 +00003361 i = ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003362
paul68980082003-03-25 05:07:42 +00003363 ospf->lsa_refresh_queue.index =
3364 (ospf->lsa_refresh_queue.index +
3365 (time (NULL) - ospf->lsa_refresher_started) / OSPF_LSA_REFRESHER_GRANULARITY)
paul718e3742002-12-13 20:15:29 +00003366 % OSPF_LSA_REFRESHER_SLOTS;
3367
3368 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3369 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
paul68980082003-03-25 05:07:42 +00003370 ospf->lsa_refresh_queue.index);
paul718e3742002-12-13 20:15:29 +00003371
paul68980082003-03-25 05:07:42 +00003372 for (;i != ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003373 i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
3374 {
3375 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3376 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d", i);
3377
paul68980082003-03-25 05:07:42 +00003378 refresh_list = ospf->lsa_refresh_queue.qs [i];
paul718e3742002-12-13 20:15:29 +00003379
paul68980082003-03-25 05:07:42 +00003380 ospf->lsa_refresh_queue.qs [i] = NULL;
3381
paul718e3742002-12-13 20:15:29 +00003382 if (refresh_list)
3383 {
3384 for (node = listhead (refresh_list); node;)
3385 {
3386 listnode next;
3387 struct ospf_lsa *lsa = getdata (node);
3388 next = node->next;
3389
3390 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
paulf2c80652002-12-13 21:44:27 +00003391 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa, i);
paul718e3742002-12-13 20:15:29 +00003392
3393 list_delete_node (refresh_list, node);
3394 ospf_lsa_unlock (lsa);
3395 lsa->refresh_list = -1;
3396 listnode_add (lsa_to_refresh, lsa);
3397 node = next;
3398 }
3399 list_free (refresh_list);
3400 }
3401 }
3402
paul68980082003-03-25 05:07:42 +00003403 ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
3404 ospf, ospf->lsa_refresh_interval);
3405 ospf->lsa_refresher_started = time (NULL);
paul718e3742002-12-13 20:15:29 +00003406
3407 for (node = listhead (lsa_to_refresh); node; nextnode (node))
paul68980082003-03-25 05:07:42 +00003408 ospf_lsa_refresh (ospf, getdata (node));
paul718e3742002-12-13 20:15:29 +00003409
3410 list_delete (lsa_to_refresh);
3411
3412 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
3413 zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
3414
3415 return 0;
3416}
3417