blob: 31b9a4f19846a6e73464e920625164ad909ccf57 [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))
ajse588f212004-12-08 18:12:06 +0000152 zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds",
paul718e3742002-12-13 20:15:29 +0000153 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;
hassoc9e52be2004-09-26 16:09:34 +0000189 sp = (u_char *) &lsa->options;
paul718e3742002-12-13 20:15:29 +0000190
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))
ajse588f212004-12-08 18:12:06 +0000263 zlog_debug ("LSA: duplicated %p (new: %p)", lsa, new);
paulf2c80652002-12-13 21:44:27 +0000264
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))
ajse588f212004-12-08 18:12:06 +0000275 zlog_debug ("LSA: freed %p", lsa);
paul718e3742002-12-13 20:15:29 +0000276
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))
ajse588f212004-12-08 18:12:06 +0000354 zlog_debug ("LSA[Type%d:%s]: data freed %p",
paul718e3742002-12-13 20:15:29 +0000355 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[] = {
hasso52dc7ee2004-09-23 19:18:23 +0000367 "Type255,id(255.255.255.255),ar(255.255.255.255)"
paul718e3742002-12-13 20:15:29 +0000368 };
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
paul9985f832005-02-09 15:51:56 +0000410 stream_forward_endp (s, OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +0000411}
412
paul68980082003-03-25 05:07:42 +0000413
paul718e3742002-12-13 20:15:29 +0000414/* router-LSA related functions. */
415/* Get router-LSA flags. */
paul4dadc292005-05-06 21:37:42 +0000416static u_char
paul718e3742002-12-13 20:15:29 +0000417router_lsa_flags (struct ospf_area *area)
418{
419 u_char flags;
420
paul68980082003-03-25 05:07:42 +0000421 flags = area->ospf->flags;
paul718e3742002-12-13 20:15:29 +0000422
423 /* Set virtual link flag. */
424 if (ospf_full_virtual_nbrs (area))
425 SET_FLAG (flags, ROUTER_LSA_VIRTUAL);
426 else
427 /* Just sanity check */
428 UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL);
429
430 /* Set Shortcut ABR behabiour flag. */
431 UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT);
paul68980082003-03-25 05:07:42 +0000432 if (area->ospf->abr_type == OSPF_ABR_SHORTCUT)
paul718e3742002-12-13 20:15:29 +0000433 if (!OSPF_IS_AREA_BACKBONE (area))
434 if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
paul68980082003-03-25 05:07:42 +0000435 area->ospf->backbone == NULL) ||
paul718e3742002-12-13 20:15:29 +0000436 area->shortcut_configured == OSPF_SHORTCUT_ENABLE)
437 SET_FLAG (flags, ROUTER_LSA_SHORTCUT);
438
439 /* ASBR can't exit in stub area. */
440 if (area->external_routing == OSPF_AREA_STUB)
paul942b6c12003-06-22 08:22:18 +0000441 UNSET_FLAG (flags, ROUTER_LSA_EXTERNAL);
442 /* If ASBR set External flag */
443 else if (IS_OSPF_ASBR (area->ospf))
444 SET_FLAG (flags, ROUTER_LSA_EXTERNAL);
445
446 /* Set ABR dependent flags */
447 if (IS_OSPF_ABR (area->ospf))
448 {
449 SET_FLAG (flags, ROUTER_LSA_BORDER);
paul942b6c12003-06-22 08:22:18 +0000450 /* If Area is NSSA and we are both ABR and unconditional translator,
pauld4a53d52003-07-12 21:30:57 +0000451 * set Nt bit to inform other routers.
paul942b6c12003-06-22 08:22:18 +0000452 */
pauld4a53d52003-07-12 21:30:57 +0000453 if ( (area->external_routing == OSPF_AREA_NSSA)
454 && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS))
455 SET_FLAG (flags, ROUTER_LSA_NT);
paul942b6c12003-06-22 08:22:18 +0000456 }
paul718e3742002-12-13 20:15:29 +0000457 return flags;
458}
459
460/* Lookup neighbor other than myself.
461 And check neighbor count,
462 Point-to-Point link must have only 1 neighbor. */
463struct ospf_neighbor *
paul68980082003-03-25 05:07:42 +0000464ospf_nbr_lookup_ptop (struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +0000465{
paul718e3742002-12-13 20:15:29 +0000466 struct ospf_neighbor *nbr = NULL;
paul68980082003-03-25 05:07:42 +0000467 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000468
469 /* Search neighbor, there must be one of two nbrs. */
paul68980082003-03-25 05:07:42 +0000470 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
471 if ((nbr = rn->info))
472 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +0000473 if (nbr->state == NSM_Full)
paul68980082003-03-25 05:07:42 +0000474 {
475 route_unlock_node (rn);
476 break;
477 }
paul718e3742002-12-13 20:15:29 +0000478
479 /* PtoP link must have only 1 neighbor. */
paul68980082003-03-25 05:07:42 +0000480 if (ospf_nbr_count (oi, 0) > 1)
paul718e3742002-12-13 20:15:29 +0000481 zlog_warn ("Point-to-Point link has more than 1 neighobrs.");
482
483 return nbr;
484}
485
paul88d6cf32005-10-29 12:50:09 +0000486/* Determine cost of link, taking RFC3137 stub-router support into
487 * consideration
488 */
489static u_int16_t
490ospf_link_cost (struct ospf_interface *oi)
491{
492 /* RFC3137 stub router support */
493 if (!CHECK_FLAG (oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
494 return oi->output_cost;
495 else
496 return OSPF_OUTPUT_COST_INFINITE;
497}
498
paul718e3742002-12-13 20:15:29 +0000499/* Set a link information. */
paul4dadc292005-05-06 21:37:42 +0000500static void
paul718e3742002-12-13 20:15:29 +0000501link_info_set (struct stream *s, struct in_addr id,
502 struct in_addr data, u_char type, u_char tos, u_int16_t cost)
503{
504 /* TOS based routing is not supported. */
505 stream_put_ipv4 (s, id.s_addr); /* Link ID. */
506 stream_put_ipv4 (s, data.s_addr); /* Link Data. */
507 stream_putc (s, type); /* Link Type. */
508 stream_putc (s, tos); /* TOS = 0. */
509 stream_putw (s, cost); /* Link Cost. */
510}
511
512/* Describe Point-to-Point link. */
paul4dadc292005-05-06 21:37:42 +0000513static int
paul718e3742002-12-13 20:15:29 +0000514lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
515{
516 int links = 0;
517 struct ospf_neighbor *nbr;
518 struct in_addr id, mask;
paul88d6cf32005-10-29 12:50:09 +0000519 u_int16_t cost = ospf_link_cost (oi);
paul718e3742002-12-13 20:15:29 +0000520
521 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000522 zlog_debug ("LSA[Type1]: Set link Point-to-Point");
paul718e3742002-12-13 20:15:29 +0000523
paul68980082003-03-25 05:07:42 +0000524 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000525 if (nbr->state == NSM_Full)
526 {
527 /* For unnumbered point-to-point networks, the Link Data field
528 should specify the interface's MIB-II ifIndex value. */
529 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
paul88d6cf32005-10-29 12:50:09 +0000530 LSA_LINK_TYPE_POINTOPOINT, 0, cost);
paul718e3742002-12-13 20:15:29 +0000531 links++;
532 }
533
hasso3fb9cd62004-10-19 19:44:43 +0000534 if (CONNECTED_DEST_HOST(oi->connected))
paul718e3742002-12-13 20:15:29 +0000535 {
536 /* Option 1:
537 link_type = LSA_LINK_TYPE_STUB;
538 link_id = nbr->address.u.prefix4;
539 link_data.s_addr = 0xffffffff;
540 link_cost = o->output_cost; */
541
542 id.s_addr = oi->connected->destination->u.prefix4.s_addr;
543 mask.s_addr = 0xffffffff;
544 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
545 }
546 else
547 {
548 /* Option 2: We need to include link to a stub
549 network regardless of the state of the neighbor */
550 masklen2ip (oi->address->prefixlen, &mask);
551 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
552 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
553 }
554 links++;
555
556 return links;
557}
558
559/* Describe Broadcast Link. */
paul4dadc292005-05-06 21:37:42 +0000560static int
paul718e3742002-12-13 20:15:29 +0000561lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
562{
563 struct ospf_neighbor *dr;
564 struct in_addr id, mask;
paul88d6cf32005-10-29 12:50:09 +0000565 u_int16_t cost = ospf_link_cost (oi);
566
paul718e3742002-12-13 20:15:29 +0000567 /* Describe Type 3 Link. */
568 if (oi->state == ISM_Waiting)
569 {
570 masklen2ip (oi->address->prefixlen, &mask);
571 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
572 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
573 return 1;
574 }
575
576 dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
577 /* Describe Type 2 link. */
578 if (dr && (dr->state == NSM_Full ||
579 IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
paul68980082003-03-25 05:07:42 +0000580 ospf_nbr_count (oi, NSM_Full) > 0)
paul718e3742002-12-13 20:15:29 +0000581 {
582 link_info_set (s, DR (oi), oi->address->u.prefix4,
paul88d6cf32005-10-29 12:50:09 +0000583 LSA_LINK_TYPE_TRANSIT, 0, cost);
paul718e3742002-12-13 20:15:29 +0000584 }
585 /* Describe type 3 link. */
586 else
587 {
588 masklen2ip (oi->address->prefixlen, &mask);
589 id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
590 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
591 }
592 return 1;
593}
594
paul4dadc292005-05-06 21:37:42 +0000595static int
paul718e3742002-12-13 20:15:29 +0000596lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
597{
598 struct in_addr id, mask;
paul88d6cf32005-10-29 12:50:09 +0000599
paul718e3742002-12-13 20:15:29 +0000600 /* Describe Type 3 Link. */
601 if (oi->state != ISM_Loopback)
602 return 0;
603
604 mask.s_addr = 0xffffffff;
605 id.s_addr = oi->address->u.prefix4.s_addr;
606 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
607 return 1;
608}
609
610/* Describe Virtual Link. */
paul4dadc292005-05-06 21:37:42 +0000611static int
paul718e3742002-12-13 20:15:29 +0000612lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
613{
614 struct ospf_neighbor *nbr;
paul88d6cf32005-10-29 12:50:09 +0000615 u_int16_t cost = ospf_link_cost (oi);
paul718e3742002-12-13 20:15:29 +0000616
paul718e3742002-12-13 20:15:29 +0000617 if (oi->state == ISM_PointToPoint)
paul68980082003-03-25 05:07:42 +0000618 if ((nbr = ospf_nbr_lookup_ptop (oi)))
paul718e3742002-12-13 20:15:29 +0000619 if (nbr->state == NSM_Full)
620 {
621 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
paul88d6cf32005-10-29 12:50:09 +0000622 LSA_LINK_TYPE_VIRTUALLINK, 0, cost);
paul718e3742002-12-13 20:15:29 +0000623 return 1;
624 }
625
626 return 0;
627}
628
629#define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O)
630
paul7afa08d2002-12-13 20:59:45 +0000631/* this function add for support point-to-multipoint ,see rfc2328
63212.4.1.4.*/
633/* from "edward rrr" <edward_rrr@hotmail.com>
634 http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
paul4dadc292005-05-06 21:37:42 +0000635static int
paul68980082003-03-25 05:07:42 +0000636lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
paul7afa08d2002-12-13 20:59:45 +0000637{
638 int links = 0;
639 struct route_node *rn;
640 struct ospf_neighbor *nbr = NULL;
641 struct in_addr id, mask;
paul88d6cf32005-10-29 12:50:09 +0000642 u_int16_t cost = ospf_link_cost (oi);
paul7afa08d2002-12-13 20:59:45 +0000643
644 mask.s_addr = 0xffffffff;
645 id.s_addr = oi->address->u.prefix4.s_addr;
646 link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
647 links++;
648
paul1cc8f762003-04-05 19:34:32 +0000649 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000650 zlog_debug ("PointToMultipoint: running ptomultip_set");
paul7afa08d2002-12-13 20:59:45 +0000651
652 /* Search neighbor, */
653 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
654 if ((nbr = rn->info) != NULL)
655 /* Ignore myself. */
paul68980082003-03-25 05:07:42 +0000656 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul7afa08d2002-12-13 20:59:45 +0000657 if (nbr->state == NSM_Full)
658
659 {
paul7afa08d2002-12-13 20:59:45 +0000660 link_info_set (s, nbr->router_id, oi->address->u.prefix4,
paul88d6cf32005-10-29 12:50:09 +0000661 LSA_LINK_TYPE_POINTOPOINT, 0, cost);
paul7afa08d2002-12-13 20:59:45 +0000662 links++;
paul1cc8f762003-04-05 19:34:32 +0000663 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000664 zlog_debug ("PointToMultipoint: set link to %s",
paul1cc8f762003-04-05 19:34:32 +0000665 inet_ntoa(oi->address->u.prefix4));
paul7afa08d2002-12-13 20:59:45 +0000666 }
667
668 return links;
paul7afa08d2002-12-13 20:59:45 +0000669}
670
paul718e3742002-12-13 20:15:29 +0000671/* Set router-LSA link information. */
paul4dadc292005-05-06 21:37:42 +0000672static int
paul718e3742002-12-13 20:15:29 +0000673router_lsa_link_set (struct stream *s, struct ospf_area *area)
674{
hasso52dc7ee2004-09-23 19:18:23 +0000675 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000676 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000677 int links = 0;
678
paul1eb8ef22005-04-07 07:30:20 +0000679 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +0000680 {
paul718e3742002-12-13 20:15:29 +0000681 struct interface *ifp = oi->ifp;
682
683 /* Check interface is up, OSPF is enable. */
paul2e3b2e42002-12-13 21:03:13 +0000684 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000685 {
686 if (oi->state != ISM_Down)
687 {
688 /* Describe each link. */
689 switch (oi->type)
690 {
691 case OSPF_IFTYPE_POINTOPOINT:
692 links += lsa_link_ptop_set (s, oi);
693 break;
694 case OSPF_IFTYPE_BROADCAST:
695 links += lsa_link_broadcast_set (s, oi);
696 break;
697 case OSPF_IFTYPE_NBMA:
698 links += lsa_link_nbma_set (s, oi);
699 break;
700 case OSPF_IFTYPE_POINTOMULTIPOINT:
paul68980082003-03-25 05:07:42 +0000701 links += lsa_link_ptomp_set (s, oi);
paul718e3742002-12-13 20:15:29 +0000702 break;
703 case OSPF_IFTYPE_VIRTUALLINK:
704 links += lsa_link_virtuallink_set (s, oi);
705 break;
706 case OSPF_IFTYPE_LOOPBACK:
707 links += lsa_link_loopback_set (s, oi);
708 }
709 }
710 }
711 }
712
713 return links;
714}
715
716/* Set router-LSA body. */
paul4dadc292005-05-06 21:37:42 +0000717static void
paul718e3742002-12-13 20:15:29 +0000718ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
719{
720 unsigned long putp;
721 u_int16_t cnt;
722
723 /* Set flags. */
724 stream_putc (s, router_lsa_flags (area));
725
726 /* Set Zero fields. */
727 stream_putc (s, 0);
728
729 /* Keep pointer to # links. */
paul9985f832005-02-09 15:51:56 +0000730 putp = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000731
732 /* Forward word */
733 stream_putw(s, 0);
734
735 /* Set all link information. */
736 cnt = router_lsa_link_set (s, area);
737
738 /* Set # of links here. */
739 stream_putw_at (s, putp, cnt);
740}
paul88d6cf32005-10-29 12:50:09 +0000741
742static int
743ospf_stub_router_timer (struct thread *t)
744{
745 struct ospf_area *area = THREAD_ARG (t);
746
747 area->t_stub_router = NULL;
748
749 SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
750
751 /* clear stub route state and generate router-lsa refresh, don't
752 * clobber an administratively set stub-router state though.
753 */
754 if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
755 return 0;
756
757 UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
758
759 ospf_router_lsa_timer_add (area);
760
761 return 0;
762}
paul718e3742002-12-13 20:15:29 +0000763
paul88d6cf32005-10-29 12:50:09 +0000764inline static void
765ospf_stub_router_check (struct ospf_area *area)
766{
767 /* area must either be administratively configured to be stub
768 * or startup-time stub-router must be configured and we must in a pre-stub
769 * state.
770 */
771 if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
772 {
773 SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
774 return;
775 }
776
777 /* not admin-stubbed, check whether startup stubbing is configured and
778 * whether it's not been done yet
779 */
780 if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED))
781 return;
782
783 if (area->ospf->stub_router_startup_time == OSPF_STUB_ROUTER_UNCONFIGURED)
784 {
785 /* stub-router is hence done forever for this area, even if someone
786 * tries configure it (take effect next restart).
787 */
788 SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
789 return;
790 }
791
792 /* startup stub-router configured and not yet done */
793 SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
794
795 OSPF_AREA_TIMER_ON (area->t_stub_router, ospf_stub_router_timer,
796 area->ospf->stub_router_startup_time);
797}
798
paul718e3742002-12-13 20:15:29 +0000799/* Create new router-LSA. */
paul4dadc292005-05-06 21:37:42 +0000800static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000801ospf_router_lsa_new (struct ospf_area *area)
802{
paul68980082003-03-25 05:07:42 +0000803 struct ospf *ospf = area->ospf;
paul718e3742002-12-13 20:15:29 +0000804 struct stream *s;
805 struct lsa_header *lsah;
806 struct ospf_lsa *new;
807 int length;
808
809 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000810 zlog_debug ("LSA[Type1]: Create router-LSA instance");
paul718e3742002-12-13 20:15:29 +0000811
paul88d6cf32005-10-29 12:50:09 +0000812 /* check whether stub-router is desired, and if this is the first
813 * router LSA.
814 */
815 ospf_stub_router_check (area);
816
paul718e3742002-12-13 20:15:29 +0000817 /* Create a stream for LSA. */
818 s = stream_new (OSPF_MAX_LSA_SIZE);
819 lsah = (struct lsa_header *) STREAM_DATA (s);
820
paul718e3742002-12-13 20:15:29 +0000821 /* Set LSA common header fields. */
pauld4a53d52003-07-12 21:30:57 +0000822 lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area),
pauld4a53d52003-07-12 21:30:57 +0000823 OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000824
825 /* Set router-LSA body fields. */
826 ospf_router_lsa_body_set (s, area);
827
828 /* Set length. */
829 length = stream_get_endp (s);
830 lsah->length = htons (length);
831
832 /* Now, create OSPF LSA instance. */
833 new = ospf_lsa_new ();
834 new->area = area;
835 SET_FLAG (new->flags, OSPF_LSA_SELF);
836
837 /* Copy LSA data to store, discard stream. */
838 new->data = ospf_lsa_data_new (length);
839 memcpy (new->data, lsah, length);
840 stream_free (s);
841
842 return new;
843}
844
845/* Originate Router-LSA. */
paul88d6cf32005-10-29 12:50:09 +0000846static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000847ospf_router_lsa_originate (struct ospf_area *area)
848{
849 struct ospf_lsa *new;
paul88d6cf32005-10-29 12:50:09 +0000850
paul718e3742002-12-13 20:15:29 +0000851 /* Create new router-LSA instance. */
852 new = ospf_router_lsa_new (area);
853
854 /* Sanity check. */
855 if (new->data->adv_router.s_addr == 0)
856 {
857 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +0000858 zlog_debug ("LSA[Type1]: AdvRouter is 0, discard");
paul718e3742002-12-13 20:15:29 +0000859 ospf_lsa_discard (new);
860 return NULL;
861 }
862
863 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +0000864 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000865
866 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +0000867 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +0000868
869 /* Flooding new LSA through area. */
870 ospf_flood_through_area (area, NULL, new);
871
872 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
873 {
ajse588f212004-12-08 18:12:06 +0000874 zlog_debug ("LSA[Type%d:%s]: Originate router-LSA %p",
paul718e3742002-12-13 20:15:29 +0000875 new->data->type, inet_ntoa (new->data->id), new);
876 ospf_lsa_header_dump (new->data);
877 }
878
879 return new;
880}
881
882/* Refresh router-LSA. */
paul4dadc292005-05-06 21:37:42 +0000883static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +0000884ospf_router_lsa_refresh (struct ospf_lsa *lsa)
885{
886 struct ospf_area *area = lsa->area;
887 struct ospf_lsa *new;
888
889 /* Sanity check. */
890 assert (lsa->data);
891
892 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +0000893 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +0000894
895 /* Create new router-LSA instance. */
896 new = ospf_router_lsa_new (area);
897 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
898
paul68980082003-03-25 05:07:42 +0000899 ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +0000900
901 /* Flood LSA through area. */
902 ospf_flood_through_area (area, NULL, new);
903
904 /* Debug logging. */
905 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
906 {
ajse588f212004-12-08 18:12:06 +0000907 zlog_debug ("LSA[Type%d:%s]: router-LSA refresh",
paul718e3742002-12-13 20:15:29 +0000908 new->data->type, inet_ntoa (new->data->id));
909 ospf_lsa_header_dump (new->data);
910 }
911
912 return NULL;
913}
914
paul4dadc292005-05-06 21:37:42 +0000915static int
paul718e3742002-12-13 20:15:29 +0000916ospf_router_lsa_timer (struct thread *t)
917{
918 struct ospf_area *area;
919
920 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +0000921 zlog_debug ("Timer[router-LSA]: (router-LSA Refresh expire)");
paul718e3742002-12-13 20:15:29 +0000922
923 area = THREAD_ARG (t);
924 area->t_router_lsa_self = NULL;
925
926 /* Now refresh router-LSA. */
927 if (area->router_lsa_self)
928 ospf_router_lsa_refresh (area->router_lsa_self);
929 /* Newly originate router-LSA. */
930 else
931 ospf_router_lsa_originate (area);
932
933 return 0;
934}
935
936void
937ospf_router_lsa_timer_add (struct ospf_area *area)
938{
939 /* Keep area's self-originated router-LSA. */
940 struct ospf_lsa *lsa = area->router_lsa_self;
941
942 /* Cancel previously scheduled router-LSA timer. */
943 if (area->t_router_lsa_self)
944 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000945 zlog_debug ("LSA[Type1]: Cancel previous router-LSA timer");
paul718e3742002-12-13 20:15:29 +0000946
947 OSPF_TIMER_OFF (area->t_router_lsa_self);
948
949 /* If router-LSA is originated previously, check the interval time. */
950 if (lsa)
951 {
952 int delay;
953 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
954 {
955 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
956 ospf_router_lsa_timer, delay);
957 return;
958 }
959 }
960
961 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000962 zlog_debug ("LSA[Type1]: Scheduling router-LSA origination right away");
paul718e3742002-12-13 20:15:29 +0000963
964 /* Immediately refresh router-LSA. */
965 OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);
966}
967
968int
paul68980082003-03-25 05:07:42 +0000969ospf_router_lsa_update_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000970{
paul68980082003-03-25 05:07:42 +0000971 struct ospf *ospf = THREAD_ARG (thread);
paul1eb8ef22005-04-07 07:30:20 +0000972 struct listnode *node, *nnode;
973 struct ospf_area *area;
paul718e3742002-12-13 20:15:29 +0000974
975 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000976 zlog_debug ("Timer[router-LSA Update]: (timer expire)");
paul718e3742002-12-13 20:15:29 +0000977
paul68980082003-03-25 05:07:42 +0000978 ospf->t_router_lsa_update = NULL;
paul718e3742002-12-13 20:15:29 +0000979
paul1eb8ef22005-04-07 07:30:20 +0000980 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000981 {
paul718e3742002-12-13 20:15:29 +0000982 struct ospf_lsa *lsa = area->router_lsa_self;
983 struct router_lsa *rl;
hassoeb1ce602004-10-08 08:17:22 +0000984 const char *area_str;
paul718e3742002-12-13 20:15:29 +0000985
986 /* Keep Area ID string. */
987 area_str = AREA_NAME (area);
988
989 /* If LSA not exist in this Area, originate new. */
990 if (lsa == NULL)
991 {
992 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +0000993 zlog_debug("LSA[Type1]: Create router-LSA for Area %s", area_str);
paul718e3742002-12-13 20:15:29 +0000994
995 ospf_router_lsa_originate (area);
996 }
997 /* If router-ID is changed, Link ID must change.
998 First flush old LSA, then originate new. */
paul68980082003-03-25 05:07:42 +0000999 else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00001000 {
1001 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001002 zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
paul718e3742002-12-13 20:15:29 +00001003 lsa->data->type, inet_ntoa (lsa->data->id), area_str);
1004 ospf_lsa_flush_area (lsa, area);
1005 ospf_lsa_unlock (area->router_lsa_self);
1006 area->router_lsa_self = NULL;
1007
1008 /* Refresh router-LSA, (not install) and flood through area. */
1009 ospf_router_lsa_timer_add (area);
1010 }
1011 else
1012 {
1013 rl = (struct router_lsa *) lsa->data;
1014 /* Refresh router-LSA, (not install) and flood through area. */
paul68980082003-03-25 05:07:42 +00001015 if (rl->flags != ospf->flags)
paul718e3742002-12-13 20:15:29 +00001016 ospf_router_lsa_timer_add (area);
1017 }
1018 }
1019
1020 return 0;
1021}
1022
1023
1024/* network-LSA related functions. */
1025/* Originate Network-LSA. */
paul4dadc292005-05-06 21:37:42 +00001026static void
paul718e3742002-12-13 20:15:29 +00001027ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi)
1028{
1029 struct in_addr mask;
1030 struct route_node *rn;
1031 struct ospf_neighbor *nbr;
1032
1033 masklen2ip (oi->address->prefixlen, &mask);
1034 stream_put_ipv4 (s, mask.s_addr);
1035
1036 /* The network-LSA lists those routers that are fully adjacent to
1037 the Designated Router; each fully adjacent router is identified by
1038 its OSPF Router ID. The Designated Router includes itself in this
1039 list. RFC2328, Section 12.4.2 */
1040
1041 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
1042 if ((nbr = rn->info) != NULL)
1043 if (nbr->state == NSM_Full || nbr == oi->nbr_self)
1044 stream_put_ipv4 (s, nbr->router_id.s_addr);
1045}
1046
paul4dadc292005-05-06 21:37:42 +00001047static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001048ospf_network_lsa_new (struct ospf_interface *oi)
1049{
1050 struct stream *s;
1051 struct ospf_lsa *new;
1052 struct lsa_header *lsah;
1053 int length;
1054
1055 /* If there are no neighbours on this network (the net is stub),
1056 the router does not originate network-LSA (see RFC 12.4.2) */
1057 if (oi->full_nbrs == 0)
1058 return NULL;
1059
1060 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001061 zlog_debug ("LSA[Type2]: Create network-LSA instance");
paul718e3742002-12-13 20:15:29 +00001062
1063 /* Create new stream for LSA. */
1064 s = stream_new (OSPF_MAX_LSA_SIZE);
1065 lsah = (struct lsa_header *) STREAM_DATA (s);
1066
1067 lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)),
paul68980082003-03-25 05:07:42 +00001068 OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001069
1070 /* Set network-LSA body fields. */
1071 ospf_network_lsa_body_set (s, oi);
1072
1073 /* Set length. */
1074 length = stream_get_endp (s);
1075 lsah->length = htons (length);
1076
1077 /* Create OSPF LSA instance. */
1078 new = ospf_lsa_new ();
1079 new->area = oi->area;
1080 SET_FLAG (new->flags, OSPF_LSA_SELF);
1081
1082 /* Copy LSA to store. */
1083 new->data = ospf_lsa_data_new (length);
1084 memcpy (new->data, lsah, length);
1085 stream_free (s);
1086
1087 return new;
1088}
1089
1090/* Originate network-LSA. */
paul4dadc292005-05-06 21:37:42 +00001091static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001092ospf_network_lsa_originate (struct ospf_interface *oi)
1093{
1094 struct ospf_lsa *new;
1095
1096 /* Create new network-LSA instance. */
1097 new = ospf_network_lsa_new (oi);
1098 if (new == NULL)
1099 return NULL;
1100
1101 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001102 new = ospf_lsa_install (oi->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001103
1104 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001105 oi->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001106
1107 /* Flooding new LSA through area. */
1108 ospf_flood_through_area (oi->area, NULL, new);
1109
1110 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1111 {
ajse588f212004-12-08 18:12:06 +00001112 zlog_debug ("LSA[Type%d:%s]: Originate network-LSA %p",
paul718e3742002-12-13 20:15:29 +00001113 new->data->type, inet_ntoa (new->data->id), new);
1114 ospf_lsa_header_dump (new->data);
1115 }
1116
1117 return new;
1118}
1119
1120int
1121ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
1122{
1123 struct ospf_area *area = lsa->area;
1124 struct ospf_lsa *new;
1125
1126 assert (lsa->data);
1127
1128 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00001129 ospf_ls_retransmit_delete_nbr_area (area, lsa);
paul718e3742002-12-13 20:15:29 +00001130
1131 /* Create new network-LSA instance. */
1132 new = ospf_network_lsa_new (oi);
1133 if (new == NULL)
1134 return -1;
1135 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1136
paul68980082003-03-25 05:07:42 +00001137 ospf_lsa_install (area->ospf, oi, new);
paul718e3742002-12-13 20:15:29 +00001138
1139 /* Flood LSA through aera. */
1140 ospf_flood_through_area (area, NULL, new);
1141
1142 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1143 {
ajse588f212004-12-08 18:12:06 +00001144 zlog_debug ("LSA[Type%d:%s]: network-LSA refresh",
paul718e3742002-12-13 20:15:29 +00001145 new->data->type, inet_ntoa (new->data->id));
1146 ospf_lsa_header_dump (new->data);
1147 }
1148
1149 return 0;
1150}
1151
paul4dadc292005-05-06 21:37:42 +00001152static int
paul718e3742002-12-13 20:15:29 +00001153ospf_network_lsa_refresh_timer (struct thread *t)
1154{
1155 struct ospf_interface *oi;
1156
1157 oi = THREAD_ARG (t);
1158 oi->t_network_lsa_self = NULL;
1159
1160 if (oi->network_lsa_self)
1161 /* Now refresh network-LSA. */
1162 ospf_network_lsa_refresh (oi->network_lsa_self, oi);
1163 else
1164 /* Newly create network-LSA. */
1165 ospf_network_lsa_originate (oi);
1166
1167 return 0;
1168}
1169
1170void
1171ospf_network_lsa_timer_add (struct ospf_interface *oi)
1172{
1173 /* Keep interface's self-originated network-LSA. */
1174 struct ospf_lsa *lsa = oi->network_lsa_self;
1175
1176 /* Cancel previously schedules network-LSA timer. */
1177 if (oi->t_network_lsa_self)
1178 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001179 zlog_debug ("LSA[Type2]: Cancel previous network-LSA timer");
paul718e3742002-12-13 20:15:29 +00001180 OSPF_TIMER_OFF (oi->t_network_lsa_self);
1181
1182 /* If network-LSA is originated previously, check the interval time. */
1183 if (lsa)
1184 {
1185 int delay;
1186 if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
1187 {
1188 oi->t_network_lsa_self =
1189 thread_add_timer (master, ospf_network_lsa_refresh_timer,
1190 oi, delay);
1191 return;
1192 }
1193 }
1194
1195 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001196 zlog_debug ("Scheduling network-LSA origination right away");
paul718e3742002-12-13 20:15:29 +00001197
1198 /* Immediately refresh network-LSA. */
1199 oi->t_network_lsa_self =
1200 thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);
1201}
1202
1203
paul4dadc292005-05-06 21:37:42 +00001204static void
paul718e3742002-12-13 20:15:29 +00001205stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
1206{
1207 u_int32_t metric;
1208 char *mp;
1209
1210 /* Put 0 metric. TOS metric is not supported. */
1211 metric = htonl (metric_value);
1212 mp = (char *) &metric;
1213 mp++;
1214 stream_put (s, mp, 3);
1215}
1216
1217/* summary-LSA related functions. */
paul4dadc292005-05-06 21:37:42 +00001218static void
paul718e3742002-12-13 20:15:29 +00001219ospf_summary_lsa_body_set (struct stream *s, struct prefix *p,
1220 u_int32_t metric)
1221{
1222 struct in_addr mask;
1223
1224 masklen2ip (p->prefixlen, &mask);
1225
1226 /* Put Network Mask. */
1227 stream_put_ipv4 (s, mask.s_addr);
1228
1229 /* Set # TOS. */
1230 stream_putc (s, (u_char) 0);
1231
1232 /* Set metric. */
1233 stream_put_ospf_metric (s, metric);
1234}
1235
paul4dadc292005-05-06 21:37:42 +00001236static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001237ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p,
1238 u_int32_t metric, struct in_addr id)
1239{
1240 struct stream *s;
1241 struct ospf_lsa *new;
1242 struct lsa_header *lsah;
1243 int length;
1244
1245 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001246 zlog_debug ("LSA[Type3]: Create summary-LSA instance");
paul718e3742002-12-13 20:15:29 +00001247
1248 /* Create new stream for LSA. */
1249 s = stream_new (OSPF_MAX_LSA_SIZE);
1250 lsah = (struct lsa_header *) STREAM_DATA (s);
1251
paul68980082003-03-25 05:07:42 +00001252 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA,
1253 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001254
1255 /* Set summary-LSA body fields. */
1256 ospf_summary_lsa_body_set (s, p, metric);
1257
1258 /* Set length. */
1259 length = stream_get_endp (s);
1260 lsah->length = htons (length);
1261
1262 /* Create OSPF LSA instance. */
1263 new = ospf_lsa_new ();
1264 new->area = area;
1265 SET_FLAG (new->flags, OSPF_LSA_SELF);
1266
1267 /* Copy LSA to store. */
1268 new->data = ospf_lsa_data_new (length);
1269 memcpy (new->data, lsah, length);
1270 stream_free (s);
1271
1272 return new;
1273}
1274
1275/* Originate Summary-LSA. */
1276struct ospf_lsa *
1277ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1278 struct ospf_area *area)
1279{
1280 struct ospf_lsa *new;
1281 struct in_addr id;
1282
paul68980082003-03-25 05:07:42 +00001283 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001284
1285 /* Create new summary-LSA instance. */
1286 new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id);
1287
1288 /* Instlal LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001289 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001290
1291 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001292 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001293
1294 /* Flooding new LSA through area. */
1295 ospf_flood_through_area (area, NULL, new);
1296
1297 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1298 {
ajse588f212004-12-08 18:12:06 +00001299 zlog_debug ("LSA[Type%d:%s]: Originate summary-LSA %p",
paul718e3742002-12-13 20:15:29 +00001300 new->data->type, inet_ntoa (new->data->id), new);
1301 ospf_lsa_header_dump (new->data);
1302 }
1303
1304 return new;
1305}
1306
1307struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001308ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001309{
1310 struct ospf_lsa *new;
1311 struct summary_lsa *sl;
1312 struct prefix p;
1313
1314 /* Sanity check. */
1315 assert (lsa->data);
1316
1317 sl = (struct summary_lsa *)lsa->data;
1318 p.prefixlen = ip_masklen (sl->mask);
1319 new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1320 sl->header.id);
1321
1322 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1323
1324 /* Re-calculate checksum. */
1325 ospf_lsa_checksum (new->data);
1326
paul68980082003-03-25 05:07:42 +00001327 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001328
1329 /* Flood LSA through AS. */
1330 ospf_flood_through_area (new->area, NULL, new);
1331
1332 /* Debug logging. */
1333 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1334 {
ajse588f212004-12-08 18:12:06 +00001335 zlog_debug ("LSA[Type%d:%s]: summary-LSA refresh",
paul718e3742002-12-13 20:15:29 +00001336 new->data->type, inet_ntoa (new->data->id));
1337 ospf_lsa_header_dump (new->data);
1338 }
1339
1340 return new;
1341}
1342
1343
1344/* summary-ASBR-LSA related functions. */
paul4dadc292005-05-06 21:37:42 +00001345static void
paul718e3742002-12-13 20:15:29 +00001346ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p,
1347 u_int32_t metric)
1348{
1349 struct in_addr mask;
1350
1351 masklen2ip (p->prefixlen, &mask);
1352
1353 /* Put Network Mask. */
1354 stream_put_ipv4 (s, mask.s_addr);
1355
1356 /* Set # TOS. */
1357 stream_putc (s, (u_char) 0);
1358
1359 /* Set metric. */
1360 stream_put_ospf_metric (s, metric);
1361}
1362
paul4dadc292005-05-06 21:37:42 +00001363static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001364ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p,
1365 u_int32_t metric, struct in_addr id)
1366{
1367 struct stream *s;
1368 struct ospf_lsa *new;
1369 struct lsa_header *lsah;
1370 int length;
1371
1372 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001373 zlog_debug ("LSA[Type3]: Create summary-LSA instance");
paul718e3742002-12-13 20:15:29 +00001374
1375 /* Create new stream for LSA. */
1376 s = stream_new (OSPF_MAX_LSA_SIZE);
1377 lsah = (struct lsa_header *) STREAM_DATA (s);
1378
paul68980082003-03-25 05:07:42 +00001379 lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA,
1380 id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001381
1382 /* Set summary-LSA body fields. */
1383 ospf_summary_asbr_lsa_body_set (s, p, metric);
1384
1385 /* Set length. */
1386 length = stream_get_endp (s);
1387 lsah->length = htons (length);
1388
1389 /* Create OSPF LSA instance. */
1390 new = ospf_lsa_new ();
1391 new->area = area;
1392 SET_FLAG (new->flags, OSPF_LSA_SELF);
1393
1394 /* Copy LSA to store. */
1395 new->data = ospf_lsa_data_new (length);
1396 memcpy (new->data, lsah, length);
1397 stream_free (s);
1398
1399 return new;
1400}
1401
1402/* Originate summary-ASBR-LSA. */
1403struct ospf_lsa *
1404ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
1405 struct ospf_area *area)
1406{
1407 struct ospf_lsa *new;
1408 struct in_addr id;
1409
paul68980082003-03-25 05:07:42 +00001410 id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p);
paul718e3742002-12-13 20:15:29 +00001411
1412 /* Create new summary-LSA instance. */
1413 new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id);
1414
1415 /* Install LSA to LSDB. */
paul68980082003-03-25 05:07:42 +00001416 new = ospf_lsa_install (area->ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001417
1418 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00001419 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001420
1421 /* Flooding new LSA through area. */
1422 ospf_flood_through_area (area, NULL, new);
1423
1424 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1425 {
ajse588f212004-12-08 18:12:06 +00001426 zlog_debug ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p",
paul718e3742002-12-13 20:15:29 +00001427 new->data->type, inet_ntoa (new->data->id), new);
1428 ospf_lsa_header_dump (new->data);
1429 }
1430
1431 return new;
1432}
1433
1434struct ospf_lsa*
paul68980082003-03-25 05:07:42 +00001435ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001436{
1437 struct ospf_lsa *new;
1438 struct summary_lsa *sl;
1439 struct prefix p;
1440
1441 /* Sanity check. */
1442 assert (lsa->data);
1443
1444 sl = (struct summary_lsa *)lsa->data;
1445 p.prefixlen = ip_masklen (sl->mask);
1446 new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
1447 sl->header.id);
1448
1449 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1450
1451 /* Re-calculate checksum. */
1452 ospf_lsa_checksum (new->data);
1453
paul68980082003-03-25 05:07:42 +00001454 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00001455
1456 /* Flood LSA through area. */
1457 ospf_flood_through_area (new->area, NULL, new);
1458
1459 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1460 {
ajse588f212004-12-08 18:12:06 +00001461 zlog_debug ("LSA[Type%d:%s]: summary-ASBR-LSA refresh",
paul718e3742002-12-13 20:15:29 +00001462 new->data->type, inet_ntoa (new->data->id));
1463 ospf_lsa_header_dump (new->data);
1464 }
1465
1466 return new;
1467}
1468
1469/* AS-external-LSA related functions. */
1470
1471/* Get nexthop for AS-external-LSAs. Return nexthop if its interface
1472 is connected, else 0*/
paul4dadc292005-05-06 21:37:42 +00001473static struct in_addr
paul68980082003-03-25 05:07:42 +00001474ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop)
paul718e3742002-12-13 20:15:29 +00001475{
1476 struct in_addr fwd;
1477 struct prefix nh;
paul1eb8ef22005-04-07 07:30:20 +00001478 struct listnode *node;
1479 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001480
1481 fwd.s_addr = 0;
1482
1483 if (!nexthop.s_addr)
1484 return fwd;
1485
1486 /* Check whether nexthop is covered by OSPF network. */
1487 nh.family = AF_INET;
1488 nh.u.prefix4 = nexthop;
1489 nh.prefixlen = IPV4_MAX_BITLEN;
1490
paul1eb8ef22005-04-07 07:30:20 +00001491 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
1492 if (if_is_operative (oi->ifp))
1493 if (oi->address->family == AF_INET)
1494 if (prefix_match (oi->address, &nh))
1495 return nexthop;
paul718e3742002-12-13 20:15:29 +00001496
1497 return fwd;
1498}
1499
paul718e3742002-12-13 20:15:29 +00001500/* NSSA-external-LSA related functions. */
1501
1502/* Get 1st IP connection for Forward Addr */
paul4dadc292005-05-06 21:37:42 +00001503
paul718e3742002-12-13 20:15:29 +00001504struct in_addr
1505ospf_get_ip_from_ifp (struct ospf_interface *oi)
1506{
1507 struct in_addr fwd;
1508
1509 fwd.s_addr = 0;
1510
paul2e3b2e42002-12-13 21:03:13 +00001511 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001512 return oi->address->u.prefix4;
1513
1514 return fwd;
1515}
1516
1517/* Get 1st IP connection for Forward Addr */
1518struct in_addr
paulf2c80652002-12-13 21:44:27 +00001519ospf_get_nssa_ip (struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001520{
1521 struct in_addr fwd;
paulf2c80652002-12-13 21:44:27 +00001522 struct in_addr best_default;
paul1eb8ef22005-04-07 07:30:20 +00001523 struct listnode *node;
1524 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00001525
1526 fwd.s_addr = 0;
paulf2c80652002-12-13 21:44:27 +00001527 best_default.s_addr = 0;
paul718e3742002-12-13 20:15:29 +00001528
paul1eb8ef22005-04-07 07:30:20 +00001529 for (ALL_LIST_ELEMENTS_RO (area->ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001530 {
paul2e3b2e42002-12-13 21:03:13 +00001531 if (if_is_operative (oi->ifp))
paul718e3742002-12-13 20:15:29 +00001532 if (oi->area->external_routing == OSPF_AREA_NSSA)
paul68980082003-03-25 05:07:42 +00001533 if (oi->address && oi->address->family == AF_INET)
1534 {
1535 if (best_default.s_addr == 0)
1536 best_default = oi->address->u.prefix4;
1537 if (oi->area == area)
1538 return oi->address->u.prefix4;
paulf2c80652002-12-13 21:44:27 +00001539 }
paul718e3742002-12-13 20:15:29 +00001540 }
paulf2c80652002-12-13 21:44:27 +00001541 if (best_default.s_addr != 0)
1542 return best_default;
paul718e3742002-12-13 20:15:29 +00001543
paul68980082003-03-25 05:07:42 +00001544 if (best_default.s_addr != 0)
1545 return best_default;
1546
paul718e3742002-12-13 20:15:29 +00001547 return fwd;
1548}
hassobeebba72004-06-20 21:00:27 +00001549
paul718e3742002-12-13 20:15:29 +00001550#define DEFAULT_DEFAULT_METRIC 20
1551#define DEFAULT_DEFAULT_ORIGINATE_METRIC 10
1552#define DEFAULT_DEFAULT_ALWAYS_METRIC 1
1553
1554#define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2
1555
1556int
paul68980082003-03-25 05:07:42 +00001557metric_type (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001558{
paul68980082003-03-25 05:07:42 +00001559 return (ospf->dmetric[src].type < 0 ?
1560 DEFAULT_METRIC_TYPE : ospf->dmetric[src].type);
paul718e3742002-12-13 20:15:29 +00001561}
1562
1563int
paul68980082003-03-25 05:07:42 +00001564metric_value (struct ospf *ospf, u_char src)
paul718e3742002-12-13 20:15:29 +00001565{
paul68980082003-03-25 05:07:42 +00001566 if (ospf->dmetric[src].value < 0)
paul718e3742002-12-13 20:15:29 +00001567 {
1568 if (src == DEFAULT_ROUTE)
1569 {
paul68980082003-03-25 05:07:42 +00001570 if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA)
paul718e3742002-12-13 20:15:29 +00001571 return DEFAULT_DEFAULT_ORIGINATE_METRIC;
1572 else
1573 return DEFAULT_DEFAULT_ALWAYS_METRIC;
1574 }
paul68980082003-03-25 05:07:42 +00001575 else if (ospf->default_metric < 0)
paul718e3742002-12-13 20:15:29 +00001576 return DEFAULT_DEFAULT_METRIC;
1577 else
paul68980082003-03-25 05:07:42 +00001578 return ospf->default_metric;
paul718e3742002-12-13 20:15:29 +00001579 }
1580
paul68980082003-03-25 05:07:42 +00001581 return ospf->dmetric[src].value;
paul718e3742002-12-13 20:15:29 +00001582}
1583
1584/* Set AS-external-LSA body. */
paul4dadc292005-05-06 21:37:42 +00001585static void
paul68980082003-03-25 05:07:42 +00001586ospf_external_lsa_body_set (struct stream *s, struct external_info *ei,
1587 struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00001588{
1589 struct prefix_ipv4 *p = &ei->p;
1590 struct in_addr mask, fwd_addr;
1591 u_int32_t mvalue;
1592 int mtype;
1593 int type;
1594
1595 /* Put Network Mask. */
1596 masklen2ip (p->prefixlen, &mask);
1597 stream_put_ipv4 (s, mask.s_addr);
1598
1599 /* If prefix is default, specify DEFAULT_ROUTE. */
1600 type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
1601
1602 mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001603 ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type);
paul718e3742002-12-13 20:15:29 +00001604
1605 mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
paul68980082003-03-25 05:07:42 +00001606 ROUTEMAP_METRIC (ei) : metric_value (ospf, type);
paul718e3742002-12-13 20:15:29 +00001607
1608 /* Put type of external metric. */
1609 stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0));
1610
1611 /* Put 0 metric. TOS metric is not supported. */
1612 stream_put_ospf_metric (s, mvalue);
1613
1614 /* Get forwarding address to nexthop if on the Connection List, else 0. */
paul68980082003-03-25 05:07:42 +00001615 fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop);
paul718e3742002-12-13 20:15:29 +00001616
1617 /* Put forwarding address. */
1618 stream_put_ipv4 (s, fwd_addr.s_addr);
1619
1620 /* Put route tag -- This value should be introduced from configuration. */
1621 stream_putl (s, 0);
1622}
1623
1624/* Create new external-LSA. */
paul4dadc292005-05-06 21:37:42 +00001625static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00001626ospf_external_lsa_new (struct ospf *ospf,
1627 struct external_info *ei, struct in_addr *old_id)
paul718e3742002-12-13 20:15:29 +00001628{
1629 struct stream *s;
1630 struct lsa_header *lsah;
1631 struct ospf_lsa *new;
1632 struct in_addr id;
1633 int length;
1634
1635 if (ei == NULL)
1636 {
1637 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001638 zlog_debug ("LSA[Type5]: External info is NULL, could not originated");
paul718e3742002-12-13 20:15:29 +00001639 return NULL;
1640 }
1641
1642 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001643 zlog_debug ("LSA[Type5]: Originate AS-external-LSA instance");
paul718e3742002-12-13 20:15:29 +00001644
1645 /* If old Link State ID is specified, refresh LSA with same ID. */
1646 if (old_id)
1647 id = *old_id;
1648 /* Get Link State with unique ID. */
1649 else
1650 {
paul68980082003-03-25 05:07:42 +00001651 id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p);
paul718e3742002-12-13 20:15:29 +00001652 if (id.s_addr == 0xffffffff)
1653 {
1654 /* Maybe Link State ID not available. */
1655 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00001656 zlog_debug ("LSA[Type5]: Link ID not available, can't originate");
paul718e3742002-12-13 20:15:29 +00001657 return NULL;
1658 }
1659 }
1660
1661 /* Create new stream for LSA. */
1662 s = stream_new (OSPF_MAX_LSA_SIZE);
1663 lsah = (struct lsa_header *) STREAM_DATA (s);
1664
1665 /* Set LSA common header fields. */
paul68980082003-03-25 05:07:42 +00001666 lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA,
1667 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00001668
1669 /* Set AS-external-LSA body fields. */
paul68980082003-03-25 05:07:42 +00001670 ospf_external_lsa_body_set (s, ei, ospf);
paul718e3742002-12-13 20:15:29 +00001671
1672 /* Set length. */
1673 length = stream_get_endp (s);
1674 lsah->length = htons (length);
1675
1676 /* Now, create OSPF LSA instance. */
1677 new = ospf_lsa_new ();
1678 new->area = NULL;
1679 SET_FLAG (new->flags, OSPF_LSA_SELF|OSPF_LSA_APPROVED);
1680
1681 /* Copy LSA data to store, discard stream. */
1682 new->data = ospf_lsa_data_new (length);
1683 memcpy (new->data, lsah, length);
1684 stream_free (s);
1685
1686 return new;
1687}
1688
paul718e3742002-12-13 20:15:29 +00001689/* As Type-7 */
paul4dadc292005-05-06 21:37:42 +00001690static void
paul68980082003-03-25 05:07:42 +00001691ospf_install_flood_nssa (struct ospf *ospf,
1692 struct ospf_lsa *lsa, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00001693{
pauld4a53d52003-07-12 21:30:57 +00001694 struct ospf_lsa *new;
paul68980082003-03-25 05:07:42 +00001695 struct as_external_lsa *extlsa;
paul1eb8ef22005-04-07 07:30:20 +00001696 struct ospf_area *area;
1697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
pauld4a53d52003-07-12 21:30:57 +00001699 /* LSA may be a Type-5 originated via translation of a Type-7 LSA
1700 * which originated from an NSSA area. In which case it should not be
1701 * flooded back to NSSA areas.
1702 */
1703 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
1704 return;
1705
paul718e3742002-12-13 20:15:29 +00001706 /* NSSA Originate or Refresh (If anyNSSA)
1707
1708 LSA is self-originated. And just installed as Type-5.
1709 Additionally, install as Type-7 LSDB for every attached NSSA.
1710
1711 P-Bit controls which ABR performs translation to outside world; If
1712 we are an ABR....do not set the P-bit, because we send the Type-5,
1713 not as the ABR Translator, but as the ASBR owner within the AS!
1714
1715 If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The
1716 elected ABR Translator will see the P-bit, Translate, and re-flood.
1717
1718 Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
1719 Type-5's to non-NSSA Areas. (it will also attempt a re-install) */
1720
paul1eb8ef22005-04-07 07:30:20 +00001721 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul68980082003-03-25 05:07:42 +00001722 {
hasso0c14ad82003-07-03 08:36:02 +00001723 /* Don't install Type-7 LSA's into nonNSSA area */
1724 if (area->external_routing != OSPF_AREA_NSSA)
1725 continue;
paul718e3742002-12-13 20:15:29 +00001726
paul68980082003-03-25 05:07:42 +00001727 /* make lsa duplicate, lock=1 */
pauld4a53d52003-07-12 21:30:57 +00001728 new = ospf_lsa_dup (lsa);
1729 new->area = area;
1730 new->data->type = OSPF_AS_NSSA_LSA;
paul718e3742002-12-13 20:15:29 +00001731
paul68980082003-03-25 05:07:42 +00001732 /* set P-bit if not ABR */
paul020709f2003-04-04 02:44:16 +00001733 if (! IS_OSPF_ABR (ospf))
paul68980082003-03-25 05:07:42 +00001734 {
pauld4a53d52003-07-12 21:30:57 +00001735 SET_FLAG(new->data->options, OSPF_OPTION_NP);
paul68980082003-03-25 05:07:42 +00001736
1737 /* set non-zero FWD ADDR
1738
1739 draft-ietf-ospf-nssa-update-09.txt
1740
1741 if the network between the NSSA AS boundary router and the
1742 adjacent AS is advertised into OSPF as an internal OSPF route,
1743 the forwarding address should be the next op address as is cu
1744 currently done with type-5 LSAs. If the intervening network is
1745 not adversited into OSPF as an internal OSPF route and the
1746 type-7 LSA's P-bit is set a forwarding address should be
1747 selected from one of the router's active OSPF inteface addresses
1748 which belong to the NSSA. If no such addresses exist, then
1749 no type-7 LSA's with the P-bit set should originate from this
1750 router. */
1751
pauld4a53d52003-07-12 21:30:57 +00001752 /* kevinm: not updating lsa anymore, just new */
1753 extlsa = (struct as_external_lsa *)(new->data);
paul68980082003-03-25 05:07:42 +00001754
1755 if (extlsa->e[0].fwd_addr.s_addr == 0)
1756 extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */
paul718e3742002-12-13 20:15:29 +00001757
pauld7480322003-05-16 17:31:51 +00001758 if (extlsa->e[0].fwd_addr.s_addr == 0)
1759 {
1760 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001761 zlog_debug ("LSA[Type-7]: Could not build FWD-ADDR");
pauld4a53d52003-07-12 21:30:57 +00001762 ospf_lsa_discard(new);
pauld7480322003-05-16 17:31:51 +00001763 return;
1764 }
paulf2c80652002-12-13 21:44:27 +00001765 }
paul68980082003-03-25 05:07:42 +00001766 /* Re-calculate checksum. */
pauld4a53d52003-07-12 21:30:57 +00001767 ospf_lsa_checksum (new->data);
paul718e3742002-12-13 20:15:29 +00001768
paul68980082003-03-25 05:07:42 +00001769 /* install also as Type-7 */
pauld4a53d52003-07-12 21:30:57 +00001770 ospf_lsa_install (ospf, NULL, new); /* Remove Old, Lock New = 2 */
paul68980082003-03-25 05:07:42 +00001771
1772 /* will send each copy, lock=2+n */
pauld4a53d52003-07-12 21:30:57 +00001773 ospf_flood_through_as (ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */
paul68980082003-03-25 05:07:42 +00001774 }
paul718e3742002-12-13 20:15:29 +00001775}
pauld4a53d52003-07-12 21:30:57 +00001776
paul4dadc292005-05-06 21:37:42 +00001777static struct ospf_lsa *
pauld4a53d52003-07-12 21:30:57 +00001778ospf_lsa_translated_nssa_new (struct ospf *ospf,
1779 struct ospf_lsa *type7)
1780{
1781
1782 struct ospf_lsa *new;
1783 struct as_external_lsa *ext, *extnew;
1784 struct external_info ei;
1785
1786 ext = (struct as_external_lsa *)(type7->data);
1787
1788 /* need external_info struct, fill in bare minimum */
1789 ei.p.family = AF_INET;
1790 ei.p.prefix = type7->data->id;
1791 ei.p.prefixlen = ip_masklen (ext->mask);
1792 ei.type = ZEBRA_ROUTE_OSPF;
1793 ei.nexthop = ext->header.adv_router;
1794 ei.route_map_set.metric = -1;
1795 ei.route_map_set.metric_type = -1;
1796 ei.tag = 0;
1797
1798 if ( (new = ospf_external_lsa_new (ospf, &ei, &type7->data->id)) == NULL)
1799 {
1800 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001801 zlog_debug ("ospf_nssa_translate_originate(): Could not originate "
pauld4a53d52003-07-12 21:30:57 +00001802 "Translated Type-5 for %s",
1803 inet_ntoa (ei.p.prefix));
1804 return NULL;
1805 }
1806
1807 extnew = (struct as_external_lsa *)(new->data);
1808
1809 /* copy over Type-7 data to new */
1810 extnew->e[0].tos = ext->e[0].tos;
1811 extnew->e[0].route_tag = ext->e[0].route_tag;
1812 extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
1813 new->data->ls_seqnum = type7->data->ls_seqnum;
1814
1815 /* add translated flag, checksum and lock new lsa */
1816 SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */
1817 ospf_lsa_checksum (new->data);
1818 new = ospf_lsa_lock (new);
1819
1820 return new;
1821}
1822
1823/* compare type-5 to type-7
1824 * -1: err, 0: same, 1: different
1825 */
paul4dadc292005-05-06 21:37:42 +00001826static int
pauld4a53d52003-07-12 21:30:57 +00001827ospf_lsa_translated_nssa_compare (struct ospf_lsa *t7, struct ospf_lsa *t5)
1828{
1829
1830 struct as_external_lsa *e5 = (struct as_external_lsa *)t5,
1831 *e7 = (struct as_external_lsa *)t7;
1832
1833
1834 /* sanity checks */
1835 if (! ((t5->data->type == OSPF_AS_EXTERNAL_LSA)
1836 && (t7->data->type == OSPF_AS_NSSA_LSA)))
1837 return -1;
1838
1839 if (t5->data->id.s_addr != t7->data->id.s_addr)
1840 return -1;
1841
1842 if (t5->data->ls_seqnum != t7->data->ls_seqnum)
1843 return LSA_REFRESH_FORCE;
1844
1845 if (e5->mask.s_addr != e7->mask.s_addr)
1846 return LSA_REFRESH_FORCE;
1847
1848 if (e5->e[0].fwd_addr.s_addr != e7->e[0].fwd_addr.s_addr)
1849 return LSA_REFRESH_FORCE;
1850
1851 if (e5->e[0].route_tag != e7->e[0].route_tag)
1852 return LSA_REFRESH_FORCE;
1853
1854 if (GET_METRIC (e5->e[0].metric) != GET_METRIC (e7->e[0].metric))
1855 return LSA_REFRESH_FORCE;
1856
1857 return LSA_REFRESH_IF_CHANGED;
1858}
1859
1860/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
1861struct ospf_lsa *
1862ospf_translated_nssa_originate (struct ospf *ospf, struct ospf_lsa *type7)
1863{
1864 struct ospf_lsa *new;
1865 struct as_external_lsa *extnew;
1866
1867 /* we cant use ospf_external_lsa_originate() as we need to set
1868 * the OSPF_LSA_LOCAL_XLT flag, must originate by hand
1869 */
1870
1871 if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
1872 {
1873 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001874 zlog_debug ("ospf_translated_nssa_originate(): Could not translate "
pauld4a53d52003-07-12 21:30:57 +00001875 "Type-7, Id %s, to Type-5",
1876 inet_ntoa (type7->data->id));
1877 return NULL;
1878 }
1879
1880 extnew = (struct as_external_lsa *)new;
1881
1882 if (IS_DEBUG_OSPF_NSSA)
1883 {
ajse588f212004-12-08 18:12:06 +00001884 zlog_debug ("ospf_translated_nssa_originate(): "
pauld4a53d52003-07-12 21:30:57 +00001885 "translated Type 7, installed:");
1886 ospf_lsa_header_dump (new->data);
ajse588f212004-12-08 18:12:06 +00001887 zlog_debug (" Network mask: %d",ip_masklen (extnew->mask));
1888 zlog_debug (" Forward addr: %s", inet_ntoa (extnew->e[0].fwd_addr));
pauld4a53d52003-07-12 21:30:57 +00001889 }
1890
1891 if ( (new = ospf_lsa_install (ospf, NULL, new)) == NULL)
1892 {
1893 if (IS_DEBUG_OSPF_NSSA);
ajse588f212004-12-08 18:12:06 +00001894 zlog_debug ("ospf_lsa_translated_nssa_originate(): "
pauld4a53d52003-07-12 21:30:57 +00001895 "Could not install LSA "
1896 "id %s", inet_ntoa (type7->data->id));
1897 return NULL;
1898 }
1899
1900 ospf->lsa_originate_count++;
1901 ospf_flood_through_as (ospf, NULL, new);
1902
1903 return new;
1904}
1905
1906/* Refresh Translated from NSSA AS-external-LSA. */
1907struct ospf_lsa *
1908ospf_translated_nssa_refresh (struct ospf *ospf, struct ospf_lsa *type7,
1909 struct ospf_lsa *type5)
1910{
1911 struct ospf_lsa *new = NULL;
1912
1913 /* Sanity checks. */
1914 assert (type7 || type5);
1915 if (type7)
1916 assert (type7->data);
1917 if (type5)
1918 assert (type5->data);
1919 assert (ospf->anyNSSA);
1920
1921 /* get required data according to what has been given */
1922 if (type7 && type5 == NULL)
1923 {
1924 /* find the translated Type-5 for this Type-7 */
1925 struct as_external_lsa *ext = (struct as_external_lsa *)(type7->data);
1926 struct prefix_ipv4 p =
1927 {
1928 .prefix = type7->data->id,
1929 .prefixlen = ip_masklen (ext->mask),
1930 .family = AF_INET,
1931 };
1932
1933 type5 = ospf_external_info_find_lsa (ospf, &p);
1934 }
1935 else if (type5 && type7 == NULL)
1936 {
1937 /* find the type-7 from which supplied type-5 was translated,
1938 * ie find first type-7 with same LSA Id.
1939 */
paul1eb8ef22005-04-07 07:30:20 +00001940 struct listnode *ln, *lnn;
pauld4a53d52003-07-12 21:30:57 +00001941 struct route_node *rn;
1942 struct ospf_lsa *lsa;
1943 struct ospf_area *area;
1944
paul1eb8ef22005-04-07 07:30:20 +00001945 for (ALL_LIST_ELEMENTS (ospf->areas, ln, lnn, area))
pauld4a53d52003-07-12 21:30:57 +00001946 {
1947 if (area->external_routing != OSPF_AREA_NSSA
1948 && !type7)
1949 continue;
1950
1951 LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
1952 {
1953 if (lsa->data->id.s_addr == type5->data->id.s_addr)
1954 {
1955 type7 = lsa;
1956 break;
1957 }
1958 }
1959 }
1960 }
1961
1962 /* do we have type7? */
1963 if (!type7)
1964 {
1965 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001966 zlog_debug ("ospf_translated_nssa_refresh(): no Type-7 found for "
pauld4a53d52003-07-12 21:30:57 +00001967 "Type-5 LSA Id %s",
1968 inet_ntoa (type7->data->id));
1969 return NULL;
1970 }
1971
1972 /* do we have valid translated type5? */
1973 if (type5 == NULL || !CHECK_FLAG (type5->flags, OSPF_LSA_LOCAL_XLT) )
1974 {
1975 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001976 zlog_debug ("ospf_translated_nssa_refresh(): No translated Type-5 "
pauld4a53d52003-07-12 21:30:57 +00001977 "found for Type-7 with Id %s",
1978 inet_ntoa (type7->data->id));
1979 return NULL;
1980 }
1981
1982 /* Delete LSA from neighbor retransmit-list. */
1983 ospf_ls_retransmit_delete_nbr_as (ospf, type5);
1984
1985 /* create new translated LSA */
1986 if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
1987 {
1988 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001989 zlog_debug ("ospf_translated_nssa_refresh(): Could not translate "
pauld4a53d52003-07-12 21:30:57 +00001990 "Type-7 for %s to Type-5",
1991 inet_ntoa (type7->data->id));
1992 return NULL;
1993 }
1994
1995 if ( !(new = ospf_lsa_install (ospf, NULL, new)) )
1996 {
1997 if (IS_DEBUG_OSPF_NSSA)
ajse588f212004-12-08 18:12:06 +00001998 zlog_debug ("ospf_translated_nssa_refresh(): Could not install "
pauld4a53d52003-07-12 21:30:57 +00001999 "translated LSA, Id %s",
2000 inet_ntoa (new->data->id));
2001 return NULL;
2002 }
2003
2004 /* Flood LSA through area. */
2005 ospf_flood_through_as (ospf, NULL, new);
2006
2007 return new;
2008}
paul718e3742002-12-13 20:15:29 +00002009
2010int
2011is_prefix_default (struct prefix_ipv4 *p)
2012{
2013 struct prefix_ipv4 q;
2014
2015 q.family = AF_INET;
2016 q.prefix.s_addr = 0;
2017 q.prefixlen = 0;
2018
2019 return prefix_same ((struct prefix *) p, (struct prefix *) &q);
2020}
2021
2022/* Originate an AS-external-LSA, install and flood. */
2023struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002024ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei)
paul718e3742002-12-13 20:15:29 +00002025{
2026 struct ospf_lsa *new;
2027
2028 /* Added for NSSA project....
2029
2030 External LSAs are originated in ASBRs as usual, but for NSSA systems.
2031 there is the global Type-5 LSDB and a Type-7 LSDB installed for
2032 every area. The Type-7's are flooded to every IR and every ABR; We
2033 install the Type-5 LSDB so that the normal "refresh" code operates
2034 as usual, and flag them as not used during ASE calculations. The
2035 Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding
2036 Address of non-zero.
2037
2038 If an ABR is the elected NSSA translator, following SPF and during
2039 the ABR task it will translate all the scanned Type-7's, with P-bit
2040 ON and not-self generated, and translate to Type-5's throughout the
2041 non-NSSA/STUB AS.
2042
2043 A difference in operation depends whether this ASBR is an ABR
2044 or not. If not an ABR, the P-bit is ON, to indicate that any
2045 elected NSSA-ABR can perform its translation.
2046
2047 If an ABR, the P-bit is OFF; No ABR will perform translation and
2048 this ASBR will flood the Type-5 LSA as usual.
2049
2050 For the case where this ASBR is not an ABR, the ASE calculations
2051 are based on the Type-5 LSDB; The Type-7 LSDB exists just to
2052 demonstrate to the user that there are LSA's that belong to any
2053 attached NSSA.
2054
2055 Finally, it just so happens that when the ABR is translating every
2056 Type-7 into Type-5, it installs it into the Type-5 LSDB as an
2057 approved Type-5 (translated from Type-7); at the end of translation
2058 if any Translated Type-5's remain unapproved, then they must be
2059 flushed from the AS.
2060
2061 */
2062
2063 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00002064 if (!ospf_redistribute_check (ospf, ei, NULL))
paul718e3742002-12-13 20:15:29 +00002065 return NULL;
2066
2067 /* Create new AS-external-LSA instance. */
paul68980082003-03-25 05:07:42 +00002068 if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL)
paul718e3742002-12-13 20:15:29 +00002069 {
2070 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00002071 zlog_debug ("LSA[Type5:%s]: Could not originate AS-external-LSA",
paul718e3742002-12-13 20:15:29 +00002072 inet_ntoa (ei->p.prefix));
2073 return NULL;
2074 }
2075
2076 /* Install newly created LSA into Type-5 LSDB, lock = 1. */
paul68980082003-03-25 05:07:42 +00002077 ospf_lsa_install (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00002078
2079 /* Update LSA origination count. */
paul68980082003-03-25 05:07:42 +00002080 ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00002081
2082 /* Flooding new LSA. only to AS (non-NSSA/STUB) */
paul68980082003-03-25 05:07:42 +00002083 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00002084
paul718e3742002-12-13 20:15:29 +00002085 /* If there is any attached NSSA, do special handling */
pauld4a53d52003-07-12 21:30:57 +00002086 if (ospf->anyNSSA &&
2087 /* stay away from translated LSAs! */
2088 !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
paul68980082003-03-25 05:07:42 +00002089 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
paul718e3742002-12-13 20:15:29 +00002090
2091 /* Debug logging. */
2092 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2093 {
ajse588f212004-12-08 18:12:06 +00002094 zlog_debug ("LSA[Type%d:%s]: Originate AS-external-LSA %p",
paul718e3742002-12-13 20:15:29 +00002095 new->data->type, inet_ntoa (new->data->id), new);
2096 ospf_lsa_header_dump (new->data);
2097 }
2098
2099 return new;
2100}
2101
2102/* Originate AS-external-LSA from external info with initial flag. */
2103int
paul68980082003-03-25 05:07:42 +00002104ospf_external_lsa_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00002105{
paul68980082003-03-25 05:07:42 +00002106 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00002107 struct route_node *rn;
2108 struct external_info *ei;
2109 struct route_table *rt;
paul68980082003-03-25 05:07:42 +00002110 int type = THREAD_VAL (thread);
paul718e3742002-12-13 20:15:29 +00002111
paul68980082003-03-25 05:07:42 +00002112 ospf->t_external_lsa = NULL;
paul718e3742002-12-13 20:15:29 +00002113
2114 /* Originate As-external-LSA from all type of distribute source. */
2115 if ((rt = EXTERNAL_INFO (type)))
2116 for (rn = route_top (rt); rn; rn = route_next (rn))
2117 if ((ei = rn->info) != NULL)
2118 if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p))
paul68980082003-03-25 05:07:42 +00002119 if (!ospf_external_lsa_originate (ospf, ei))
paul718e3742002-12-13 20:15:29 +00002120 zlog_warn ("LSA: AS-external-LSA was not originated.");
2121
2122 return 0;
2123}
2124
paul4dadc292005-05-06 21:37:42 +00002125static struct external_info *
paul020709f2003-04-04 02:44:16 +00002126ospf_default_external_info (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002127{
2128 int type;
2129 struct route_node *rn;
2130 struct prefix_ipv4 p;
2131
2132 p.family = AF_INET;
2133 p.prefix.s_addr = 0;
2134 p.prefixlen = 0;
2135
2136 /* First, lookup redistributed default route. */
2137 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
2138 if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF)
2139 {
2140 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
2141 if (rn != NULL)
2142 {
2143 route_unlock_node (rn);
2144 assert (rn->info);
paul68980082003-03-25 05:07:42 +00002145 if (ospf_redistribute_check (ospf, rn->info, NULL))
paul718e3742002-12-13 20:15:29 +00002146 return rn->info;
2147 }
2148 }
2149
2150 return NULL;
2151}
2152
2153int
paul68980082003-03-25 05:07:42 +00002154ospf_default_originate_timer (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00002155{
2156 int *origin;
2157 struct prefix_ipv4 p;
2158 struct in_addr nexthop;
2159 struct external_info *ei;
paul020709f2003-04-04 02:44:16 +00002160 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002161
paul020709f2003-04-04 02:44:16 +00002162 ospf = ospf_lookup ();
2163
paul718e3742002-12-13 20:15:29 +00002164 /* Get originate flags. */
paul68980082003-03-25 05:07:42 +00002165 origin = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +00002166
2167 p.family = AF_INET;
2168 p.prefix.s_addr = 0;
2169 p.prefixlen = 0;
2170
2171 if (*origin == DEFAULT_ORIGINATE_ALWAYS)
2172 {
2173 /* If there is no default route via redistribute,
2174 then originate AS-external-LSA with nexthop 0 (self). */
2175 nexthop.s_addr = 0;
2176 ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop);
2177 }
2178
paul020709f2003-04-04 02:44:16 +00002179 if ((ei = ospf_default_external_info (ospf)))
paul68980082003-03-25 05:07:42 +00002180 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00002181
2182 return 0;
2183}
2184
paul645878f2003-04-13 21:42:11 +00002185/* Flush any NSSA LSAs for given prefix */
2186void
2187ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p)
2188{
paul1eb8ef22005-04-07 07:30:20 +00002189 struct listnode *node, *nnode;
paul645878f2003-04-13 21:42:11 +00002190 struct ospf_lsa *lsa;
2191 struct ospf_area *area;
2192
paul1eb8ef22005-04-07 07:30:20 +00002193 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul645878f2003-04-13 21:42:11 +00002194 {
paul1eb8ef22005-04-07 07:30:20 +00002195 if (area->external_routing == OSPF_AREA_NSSA)
pauld7480322003-05-16 17:31:51 +00002196 {
2197 if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix,
2198 ospf->router_id)))
2199 {
2200 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002201 zlog_debug ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB",
pauld7480322003-05-16 17:31:51 +00002202 inet_ntoa (p->prefix), p->prefixlen);
2203 continue;
2204 }
2205 ospf_ls_retransmit_delete_nbr_area (area, lsa);
2206 if (!IS_LSA_MAXAGE (lsa))
2207 {
2208 ospf_refresher_unregister_lsa (ospf, lsa);
2209 ospf_lsa_flush_area (lsa, area);
2210 }
2211 }
paul645878f2003-04-13 21:42:11 +00002212 }
2213}
paul645878f2003-04-13 21:42:11 +00002214
paul718e3742002-12-13 20:15:29 +00002215/* Flush an AS-external-LSA from LSDB and routing domain. */
2216void
paul68980082003-03-25 05:07:42 +00002217ospf_external_lsa_flush (struct ospf *ospf,
2218 u_char type, struct prefix_ipv4 *p,
ajs5339cfd2005-09-19 13:28:05 +00002219 unsigned int ifindex /*, struct in_addr nexthop */)
paul718e3742002-12-13 20:15:29 +00002220{
2221 struct ospf_lsa *lsa;
2222
2223 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002224 zlog_debug ("LSA: Flushing AS-external-LSA %s/%d",
paul718e3742002-12-13 20:15:29 +00002225 inet_ntoa (p->prefix), p->prefixlen);
2226
2227 /* First lookup LSA from LSDB. */
paul68980082003-03-25 05:07:42 +00002228 if (!(lsa = ospf_external_info_find_lsa (ospf, p)))
paul718e3742002-12-13 20:15:29 +00002229 {
2230 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002231 zlog_debug ("LSA: There is no such AS-external-LSA %s/%d in LSDB",
paul718e3742002-12-13 20:15:29 +00002232 inet_ntoa (p->prefix), p->prefixlen);
2233 return;
2234 }
hassobeebba72004-06-20 21:00:27 +00002235
pauld4a53d52003-07-12 21:30:57 +00002236 /* If LSA is selforiginated, not a translated LSA, and there is
2237 * NSSA area, flush Type-7 LSA's at first.
2238 */
2239 if (IS_LSA_SELF(lsa) && (ospf->anyNSSA)
2240 && !(CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)))
pauld7480322003-05-16 17:31:51 +00002241 ospf_nssa_lsa_flush (ospf, p);
paul718e3742002-12-13 20:15:29 +00002242
2243 /* Sweep LSA from Link State Retransmit List. */
paul68980082003-03-25 05:07:42 +00002244 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002245
2246 /* There must be no self-originated LSA in rtrs_external. */
2247#if 0
2248 /* Remove External route from Zebra. */
2249 ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);
2250#endif
2251
2252 if (!IS_LSA_MAXAGE (lsa))
2253 {
2254 /* Unregister LSA from Refresh queue. */
paul68980082003-03-25 05:07:42 +00002255 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002256
2257 /* Flush AS-external-LSA through AS. */
paul68980082003-03-25 05:07:42 +00002258 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002259 }
2260
2261 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002262 zlog_debug ("ospf_external_lsa_flush(): stop");
paul718e3742002-12-13 20:15:29 +00002263}
2264
2265void
paul68980082003-03-25 05:07:42 +00002266ospf_external_lsa_refresh_default (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002267{
2268 struct prefix_ipv4 p;
2269 struct external_info *ei;
2270 struct ospf_lsa *lsa;
2271
2272 p.family = AF_INET;
2273 p.prefixlen = 0;
2274 p.prefix.s_addr = 0;
2275
paul020709f2003-04-04 02:44:16 +00002276 ei = ospf_default_external_info (ospf);
paul68980082003-03-25 05:07:42 +00002277 lsa = ospf_external_info_find_lsa (ospf, &p);
paul718e3742002-12-13 20:15:29 +00002278
2279 if (ei)
2280 {
2281 if (lsa)
2282 {
2283 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00002284 zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa);
paul68980082003-03-25 05:07:42 +00002285 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00002286 }
2287 else
2288 {
2289 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00002290 zlog_debug ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
paul68980082003-03-25 05:07:42 +00002291 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00002292 }
2293 }
2294 else
2295 {
2296 if (lsa)
2297 {
2298 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00002299 zlog_debug ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
paul68980082003-03-25 05:07:42 +00002300 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002301 }
2302 }
2303}
2304
2305void
paul68980082003-03-25 05:07:42 +00002306ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force)
paul718e3742002-12-13 20:15:29 +00002307{
2308 struct route_node *rn;
2309 struct external_info *ei;
2310
2311 if (type != DEFAULT_ROUTE)
2312 if (EXTERNAL_INFO(type))
2313 /* Refresh each redistributed AS-external-LSAs. */
2314 for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
2315 if ((ei = rn->info))
2316 if (!is_prefix_default (&ei->p))
2317 {
2318 struct ospf_lsa *lsa;
2319
paul68980082003-03-25 05:07:42 +00002320 if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
2321 ospf_external_lsa_refresh (ospf, lsa, ei, force);
paul718e3742002-12-13 20:15:29 +00002322 else
paul68980082003-03-25 05:07:42 +00002323 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +00002324 }
2325}
2326
2327/* Refresh AS-external-LSA. */
2328void
paul68980082003-03-25 05:07:42 +00002329ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
paul718e3742002-12-13 20:15:29 +00002330 struct external_info *ei, int force)
2331{
2332 struct ospf_lsa *new;
2333 int changed;
2334
2335 /* Check the AS-external-LSA should be originated. */
paul68980082003-03-25 05:07:42 +00002336 if (!ospf_redistribute_check (ospf, ei, &changed))
paul718e3742002-12-13 20:15:29 +00002337 {
pauld4a53d52003-07-12 21:30:57 +00002338 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00002339 zlog_debug ("LSA[Type%d:%s]: Could not be refreshed, "
pauld4a53d52003-07-12 21:30:57 +00002340 "redist check fail",
2341 lsa->data->type, inet_ntoa (lsa->data->id));
paul68980082003-03-25 05:07:42 +00002342 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +00002343 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +00002344 return;
2345 }
2346
2347 if (!changed && !force)
pauld4a53d52003-07-12 21:30:57 +00002348 {
2349 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00002350 zlog_debug ("LSA[Type%d:%s]: Not refreshed, not changed/forced",
pauld4a53d52003-07-12 21:30:57 +00002351 lsa->data->type, inet_ntoa (lsa->data->id));
2352 return;
2353 }
paul718e3742002-12-13 20:15:29 +00002354
2355 /* Delete LSA from neighbor retransmit-list. */
paul68980082003-03-25 05:07:42 +00002356 ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002357
2358 /* Unregister AS-external-LSA from refresh-list. */
paul68980082003-03-25 05:07:42 +00002359 ospf_refresher_unregister_lsa (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002360
paul68980082003-03-25 05:07:42 +00002361 new = ospf_external_lsa_new (ospf, ei, &lsa->data->id);
paul718e3742002-12-13 20:15:29 +00002362
2363 if (new == NULL)
2364 {
2365 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00002366 zlog_debug ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
paul718e3742002-12-13 20:15:29 +00002367 inet_ntoa (lsa->data->id));
2368 return;
2369 }
2370
2371 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
2372
2373 /* Record timestamp. */
2374 gettimeofday (&new->tv_orig, NULL);
2375
2376 /* Re-calculate checksum. */
2377 ospf_lsa_checksum (new->data);
2378
paul68980082003-03-25 05:07:42 +00002379 ospf_lsa_install (ospf, NULL, new); /* As type-5. */
paul718e3742002-12-13 20:15:29 +00002380
2381 /* Flood LSA through AS. */
paul68980082003-03-25 05:07:42 +00002382 ospf_flood_through_as (ospf, NULL, new);
paul718e3742002-12-13 20:15:29 +00002383
paul718e3742002-12-13 20:15:29 +00002384 /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
pauld4a53d52003-07-12 21:30:57 +00002385 if (ospf->anyNSSA && !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
paul68980082003-03-25 05:07:42 +00002386 ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */
paul718e3742002-12-13 20:15:29 +00002387
pauld4a53d52003-07-12 21:30:57 +00002388 /* Register self-originated LSA to refresh queue.
2389 * Translated LSAs should not be registered, but refreshed upon
2390 * refresh of the Type-7
2391 */
2392 if ( !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT) )
2393 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002394
2395 /* Debug logging. */
2396 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2397 {
ajse588f212004-12-08 18:12:06 +00002398 zlog_debug ("LSA[Type%d:%s]: AS-external-LSA refresh",
pauld4a53d52003-07-12 21:30:57 +00002399 new->data->type, inet_ntoa (new->data->id));
paul718e3742002-12-13 20:15:29 +00002400 ospf_lsa_header_dump (new->data);
2401 }
2402
2403 return;
2404}
2405
2406
2407/* LSA installation functions. */
2408
2409/* Install router-LSA to an area. */
paul4dadc292005-05-06 21:37:42 +00002410static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002411ospf_router_lsa_install (struct ospf *ospf,
2412 struct ospf_lsa *new, int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002413{
2414 struct ospf_area *area = new->area;
2415
2416 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2417 The entire routing table must be recalculated, starting with
2418 the shortest path calculations for each area (not just the
2419 area whose link-state database has changed).
2420 */
2421 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002422 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002423
2424 if (IS_LSA_SELF (new))
2425 {
2426 /* Set router-LSA refresh timer. */
2427 OSPF_TIMER_OFF (area->t_router_lsa_self);
2428 OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
pauld4a53d52003-07-12 21:30:57 +00002429 ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
paul718e3742002-12-13 20:15:29 +00002430
2431 /* Set self-originated router-LSA. */
2432 ospf_lsa_unlock (area->router_lsa_self);
2433 area->router_lsa_self = ospf_lsa_lock (new);
2434
2435 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajse588f212004-12-08 18:12:06 +00002436 zlog_debug("LSA[Type%d]: ID %s seq 0x%x is self-originated",
paul0c2be262004-05-31 14:16:54 +00002437 new->data->type, inet_ntoa (new->data->id),
2438 ntohl(new->data->ls_seqnum));
paul718e3742002-12-13 20:15:29 +00002439 }
2440
2441 return new;
2442}
2443
2444#define OSPF_INTERFACE_TIMER_ON(T,F,V) \
2445 if (!(T)) \
2446 (T) = thread_add_timer (master, (F), oi, (V))
2447
2448/* Install network-LSA to an area. */
paul4dadc292005-05-06 21:37:42 +00002449static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002450ospf_network_lsa_install (struct ospf *ospf,
2451 struct ospf_interface *oi,
paul718e3742002-12-13 20:15:29 +00002452 struct ospf_lsa *new,
2453 int rt_recalc)
2454{
2455
2456 /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
2457 The entire routing table must be recalculated, starting with
2458 the shortest path calculations for each area (not just the
2459 area whose link-state database has changed).
2460 */
2461 if (rt_recalc)
paul68980082003-03-25 05:07:42 +00002462 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002463
2464 /* We supposed that when LSA is originated by us, we pass the int
2465 for which it was originated. If LSA was received by flooding,
2466 the RECEIVED flag is set, so we do not link the LSA to the int. */
2467 if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
2468 {
2469 /* Set LSRefresh timer. */
2470 OSPF_TIMER_OFF (oi->t_network_lsa_self);
2471
2472 OSPF_INTERFACE_TIMER_ON (oi->t_network_lsa_self,
2473 ospf_network_lsa_refresh_timer,
2474 OSPF_LS_REFRESH_TIME);
2475
2476 ospf_lsa_unlock (oi->network_lsa_self);
2477 oi->network_lsa_self = ospf_lsa_lock (new);
2478 }
2479
2480 return new;
2481}
2482
2483/* Install summary-LSA to an area. */
paul4dadc292005-05-06 21:37:42 +00002484static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002485ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2486 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002487{
paul718e3742002-12-13 20:15:29 +00002488 if (rt_recalc && !IS_LSA_SELF (new))
2489 {
2490 /* RFC 2328 Section 13.2 Summary-LSAs
2491 The best route to the destination described by the summary-
2492 LSA must be recalculated (see Section 16.5). If this
2493 destination is an AS boundary router, it may also be
2494 necessary to re-examine all the AS-external-LSAs.
2495 */
2496
2497#if 0
2498 /* This doesn't exist yet... */
2499 ospf_summary_incremental_update(new); */
2500#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002501 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002502#endif /* #if 0 */
2503
2504 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajse588f212004-12-08 18:12:06 +00002505 zlog_debug ("ospf_summary_lsa_install(): SPF scheduled");
paul718e3742002-12-13 20:15:29 +00002506 }
2507
2508 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002509 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002510
2511 return new;
2512}
2513
2514/* Install ASBR-summary-LSA to an area. */
paul4dadc292005-05-06 21:37:42 +00002515static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002516ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2517 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002518{
2519 if (rt_recalc && !IS_LSA_SELF (new))
2520 {
2521 /* RFC 2328 Section 13.2 Summary-LSAs
2522 The best route to the destination described by the summary-
2523 LSA must be recalculated (see Section 16.5). If this
2524 destination is an AS boundary router, it may also be
2525 necessary to re-examine all the AS-external-LSAs.
2526 */
2527#if 0
2528 /* These don't exist yet... */
2529 ospf_summary_incremental_update(new);
2530 /* Isn't this done by the above call?
2531 - RFC 2328 Section 16.5 implies it should be */
2532 /* ospf_ase_calculate_schedule(); */
2533#else /* #if 0 */
paul68980082003-03-25 05:07:42 +00002534 ospf_spf_calculate_schedule (ospf);
paul718e3742002-12-13 20:15:29 +00002535#endif /* #if 0 */
2536 }
2537
2538 /* register LSA to refresh-list. */
2539 if (IS_LSA_SELF (new))
paul68980082003-03-25 05:07:42 +00002540 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002541
2542 return new;
2543}
2544
2545/* Install AS-external-LSA. */
paul4dadc292005-05-06 21:37:42 +00002546static struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002547ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
2548 int rt_recalc)
paul718e3742002-12-13 20:15:29 +00002549{
paul68980082003-03-25 05:07:42 +00002550 ospf_ase_register_external_lsa (new, ospf);
paul718e3742002-12-13 20:15:29 +00002551 /* If LSA is not self-originated, calculate an external route. */
2552 if (rt_recalc)
2553 {
2554 /* RFC 2328 Section 13.2 AS-external-LSAs
2555 The best route to the destination described by the AS-
2556 external-LSA must be recalculated (see Section 16.6).
2557 */
2558
2559 if (!IS_LSA_SELF (new))
pauld4a53d52003-07-12 21:30:57 +00002560 ospf_ase_incremental_update (ospf, new);
paul718e3742002-12-13 20:15:29 +00002561 }
2562
pauld4a53d52003-07-12 21:30:57 +00002563 if (new->data->type == OSPF_AS_NSSA_LSA)
2564 {
2565 /* There is no point to register selforiginate Type-7 LSA for
2566 * refreshing. We rely on refreshing Type-5 LSA's
2567 */
2568 if (IS_LSA_SELF (new))
2569 return new;
2570 else
2571 {
2572 /* Try refresh type-5 translated LSA for this LSA, if one exists.
2573 * New translations will be taken care of by the abr_task.
2574 */
2575 ospf_translated_nssa_refresh (ospf, new, NULL);
2576 }
2577 }
pauld7480322003-05-16 17:31:51 +00002578
pauld4a53d52003-07-12 21:30:57 +00002579 /* Register self-originated LSA to refresh queue.
paul8fc0f642003-07-13 01:36:06 +00002580 * Leave Translated LSAs alone if NSSA is enabled
pauld4a53d52003-07-12 21:30:57 +00002581 */
hassobeebba72004-06-20 21:00:27 +00002582 if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT ) )
paul68980082003-03-25 05:07:42 +00002583 ospf_refresher_register_lsa (ospf, new);
paul718e3742002-12-13 20:15:29 +00002584
2585 return new;
2586}
2587
2588void
paul68980082003-03-25 05:07:42 +00002589ospf_discard_from_db (struct ospf *ospf,
2590 struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002591{
2592 struct ospf_lsa *old;
2593
2594 old = ospf_lsdb_lookup (lsdb, lsa);
2595
2596 if (!old)
2597 return;
2598
2599 if (old->refresh_list >= 0)
paul68980082003-03-25 05:07:42 +00002600 ospf_refresher_unregister_lsa (ospf, old);
paul718e3742002-12-13 20:15:29 +00002601
2602 switch (old->data->type)
2603 {
2604 case OSPF_AS_EXTERNAL_LSA:
paul69310a62005-05-11 18:09:59 +00002605 ospf_ase_unregister_external_lsa (old, ospf);
2606 ospf_ls_retransmit_delete_nbr_as (ospf, old);
2607 break;
paul718e3742002-12-13 20:15:29 +00002608#ifdef HAVE_OPAQUE_LSA
2609 case OSPF_OPAQUE_AS_LSA:
paul68980082003-03-25 05:07:42 +00002610 ospf_ls_retransmit_delete_nbr_as (ospf, old);
paul718e3742002-12-13 20:15:29 +00002611 break;
paul69310a62005-05-11 18:09:59 +00002612#endif /* HAVE_OPAQUE_LSA */
pauld7480322003-05-16 17:31:51 +00002613 case OSPF_AS_NSSA_LSA:
2614 ospf_ls_retransmit_delete_nbr_area (old->area, old);
2615 ospf_ase_unregister_external_lsa (old, ospf);
hassobeebba72004-06-20 21:00:27 +00002616 break;
paul718e3742002-12-13 20:15:29 +00002617 default:
paul68980082003-03-25 05:07:42 +00002618 ospf_ls_retransmit_delete_nbr_area (old->area, old);
paul718e3742002-12-13 20:15:29 +00002619 break;
2620 }
2621
paul68980082003-03-25 05:07:42 +00002622 ospf_lsa_maxage_delete (ospf, old);
paul718e3742002-12-13 20:15:29 +00002623 ospf_lsa_discard (old);
2624}
2625
paul718e3742002-12-13 20:15:29 +00002626struct ospf_lsa *
paul68980082003-03-25 05:07:42 +00002627ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
2628 struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002629{
2630 struct ospf_lsa *new = NULL;
2631 struct ospf_lsa *old = NULL;
2632 struct ospf_lsdb *lsdb = NULL;
2633 int rt_recalc;
2634
2635 /* Set LSDB. */
2636 switch (lsa->data->type)
2637 {
paulf2c80652002-12-13 21:44:27 +00002638 /* kevinm */
2639 case OSPF_AS_NSSA_LSA:
2640 if (lsa->area)
2641 lsdb = lsa->area->lsdb;
2642 else
paul68980082003-03-25 05:07:42 +00002643 lsdb = ospf->lsdb;
paulf2c80652002-12-13 21:44:27 +00002644 break;
paul718e3742002-12-13 20:15:29 +00002645 case OSPF_AS_EXTERNAL_LSA:
2646#ifdef HAVE_OPAQUE_LSA
2647 case OSPF_OPAQUE_AS_LSA:
2648#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00002649 lsdb = ospf->lsdb;
paul718e3742002-12-13 20:15:29 +00002650 break;
2651 default:
2652 lsdb = lsa->area->lsdb;
2653 break;
2654 }
2655
paul718e3742002-12-13 20:15:29 +00002656 assert (lsdb);
2657
2658 /* RFC 2328 13.2. Installing LSAs in the database
2659
2660 Installing a new LSA in the database, either as the result of
2661 flooding or a newly self-originated LSA, may cause the OSPF
2662 routing table structure to be recalculated. The contents of the
2663 new LSA should be compared to the old instance, if present. If
2664 there is no difference, there is no need to recalculate the
2665 routing table. When comparing an LSA to its previous instance,
2666 the following are all considered to be differences in contents:
2667
2668 o The LSA's Options field has changed.
2669
2670 o One of the LSA instances has LS age set to MaxAge, and
2671 the other does not.
2672
2673 o The length field in the LSA header has changed.
2674
2675 o The body of the LSA (i.e., anything outside the 20-byte
2676 LSA header) has changed. Note that this excludes changes
2677 in LS Sequence Number and LS Checksum.
2678
2679 */
2680 /* Look up old LSA and determine if any SPF calculation or incremental
2681 update is needed */
2682 old = ospf_lsdb_lookup (lsdb, lsa);
2683
2684 /* Do comparision and record if recalc needed. */
2685 rt_recalc = 0;
2686 if ( old == NULL || ospf_lsa_different(old, lsa))
2687 rt_recalc = 1;
2688
paul7ddf1d62003-10-13 09:06:46 +00002689 /*
2690 Sequence number check (Section 14.1 of rfc 2328)
2691 "Premature aging is used when it is time for a self-originated
2692 LSA's sequence number field to wrap. At this point, the current
2693 LSA instance (having LS sequence number MaxSequenceNumber) must
2694 be prematurely aged and flushed from the routing domain before a
2695 new instance with sequence number equal to InitialSequenceNumber
2696 can be originated. "
2697 */
2698
paul553ff112004-06-06 09:41:00 +00002699 if (ntohl(lsa->data->ls_seqnum) - 1 == htonl(OSPF_MAX_SEQUENCE_NUMBER))
paul7ddf1d62003-10-13 09:06:46 +00002700 {
2701 if (ospf_lsa_is_self_originated(ospf, lsa))
2702 {
paul0c2be262004-05-31 14:16:54 +00002703 lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER);
2704
2705 if (!IS_LSA_MAXAGE(lsa))
paul7ddf1d62003-10-13 09:06:46 +00002706 lsa->flags |= OSPF_LSA_PREMATURE_AGE;
2707 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
2708
2709 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
2710 {
ajse588f212004-12-08 18:12:06 +00002711 zlog_debug ("ospf_lsa_install() Premature Aging "
paul7ddf1d62003-10-13 09:06:46 +00002712 "lsa 0x%lx", (u_long)lsa);
2713 ospf_lsa_header_dump (lsa->data);
2714 }
2715 }
2716 else
2717 {
2718 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2719 {
ajse588f212004-12-08 18:12:06 +00002720 zlog_debug ("ospf_lsa_install() got an lsa with seq 0x80000000 "
paul7ddf1d62003-10-13 09:06:46 +00002721 "that was not self originated. Ignoring\n");
2722 ospf_lsa_header_dump (lsa->data);
2723 }
2724 return old;
2725 }
2726 }
2727
paul718e3742002-12-13 20:15:29 +00002728 /* discard old LSA from LSDB */
2729 if (old != NULL)
paul68980082003-03-25 05:07:42 +00002730 ospf_discard_from_db (ospf, lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002731
paul718e3742002-12-13 20:15:29 +00002732 /* Calculate Checksum if self-originated?. */
2733 if (IS_LSA_SELF (lsa))
2734 ospf_lsa_checksum (lsa->data);
2735
hassofe71a972004-12-22 16:16:02 +00002736 /* Insert LSA to LSDB. */
2737 ospf_lsdb_add (lsdb, lsa);
2738 lsa->lsdb = lsdb;
2739
paul718e3742002-12-13 20:15:29 +00002740 /* Do LSA specific installation process. */
2741 switch (lsa->data->type)
2742 {
2743 case OSPF_ROUTER_LSA:
paul68980082003-03-25 05:07:42 +00002744 new = ospf_router_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002745 break;
2746 case OSPF_NETWORK_LSA:
2747 assert (oi);
paul68980082003-03-25 05:07:42 +00002748 new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002749 break;
2750 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002751 new = ospf_summary_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002752 break;
2753 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00002754 new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002755 break;
2756 case OSPF_AS_EXTERNAL_LSA:
paul68980082003-03-25 05:07:42 +00002757 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
paul718e3742002-12-13 20:15:29 +00002758 break;
2759#ifdef HAVE_OPAQUE_LSA
2760 case OSPF_OPAQUE_LINK_LSA:
paul09e4efd2003-01-18 00:12:02 +00002761 if (IS_LSA_SELF (lsa))
paul68980082003-03-25 05:07:42 +00002762 lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */
paul09e4efd2003-01-18 00:12:02 +00002763 else
paul68980082003-03-25 05:07:42 +00002764 ; /* Incoming "oi" for this LSA has set at LSUpd reception. */
paul09e4efd2003-01-18 00:12:02 +00002765 /* Fallthrough */
paul718e3742002-12-13 20:15:29 +00002766 case OSPF_OPAQUE_AREA_LSA:
2767 case OSPF_OPAQUE_AS_LSA:
2768 new = ospf_opaque_lsa_install (lsa, rt_recalc);
2769 break;
2770#endif /* HAVE_OPAQUE_LSA */
pauld4a53d52003-07-12 21:30:57 +00002771 case OSPF_AS_NSSA_LSA:
paul68980082003-03-25 05:07:42 +00002772 new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
pauld4a53d52003-07-12 21:30:57 +00002773 default: /* type-6,8,9....nothing special */
paul718e3742002-12-13 20:15:29 +00002774 break;
2775 }
2776
2777 if (new == NULL)
2778 return new; /* Installation failed, cannot proceed further -- endo. */
2779
2780 /* Debug logs. */
2781 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
2782 {
2783 char area_str[INET_ADDRSTRLEN];
2784
2785 switch (lsa->data->type)
2786 {
2787 case OSPF_AS_EXTERNAL_LSA:
2788#ifdef HAVE_OPAQUE_LSA
2789 case OSPF_OPAQUE_AS_LSA:
2790#endif /* HAVE_OPAQUE_LSA */
hassobeebba72004-06-20 21:00:27 +00002791 case OSPF_AS_NSSA_LSA:
ajse588f212004-12-08 18:12:06 +00002792 zlog_debug ("LSA[%s]: Install %s",
paul718e3742002-12-13 20:15:29 +00002793 dump_lsa_key (new),
2794 LOOKUP (ospf_lsa_type_msg, new->data->type));
2795 break;
2796 default:
2797 strcpy (area_str, inet_ntoa (new->area->area_id));
ajse588f212004-12-08 18:12:06 +00002798 zlog_debug ("LSA[%s]: Install %s to Area %s",
paul718e3742002-12-13 20:15:29 +00002799 dump_lsa_key (new),
2800 LOOKUP (ospf_lsa_type_msg, new->data->type), area_str);
2801 break;
2802 }
2803 }
2804
paul7ddf1d62003-10-13 09:06:46 +00002805 /*
2806 If received LSA' ls_age is MaxAge, or lsa is being prematurely aged
2807 (it's getting flushed out of the area), set LSA on MaxAge LSA list.
2808 */
2809 if ((lsa->flags & OSPF_LSA_PREMATURE_AGE) ||
2810 (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new)))
paul718e3742002-12-13 20:15:29 +00002811 {
paul7ddf1d62003-10-13 09:06:46 +00002812 if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
ajse588f212004-12-08 18:12:06 +00002813 zlog_debug ("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge",
paul0c2be262004-05-31 14:16:54 +00002814 new->data->type,
2815 inet_ntoa (new->data->id),
2816 lsa);
paul68980082003-03-25 05:07:42 +00002817 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00002818 }
2819
2820 return new;
2821}
2822
2823
paul4dadc292005-05-06 21:37:42 +00002824static int
paul68980082003-03-25 05:07:42 +00002825ospf_check_nbr_status (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00002826{
paul1eb8ef22005-04-07 07:30:20 +00002827 struct listnode *node, *nnode;
2828 struct ospf_interface *oi;
2829
2830 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +00002831 {
paul718e3742002-12-13 20:15:29 +00002832 struct route_node *rn;
2833 struct ospf_neighbor *nbr;
2834
2835 if (ospf_if_is_enable (oi))
2836 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
2837 if ((nbr = rn->info) != NULL)
2838 if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading)
2839 {
2840 route_unlock_node (rn);
2841 return 0;
2842 }
2843 }
2844
2845 return 1;
2846}
2847
2848
2849#ifdef ORIGINAL_CODING
2850/* This function flood the maxaged LSA to DR. */
2851void
2852ospf_maxage_flood (struct ospf_lsa *lsa)
2853{
2854 switch (lsa->data->type)
2855 {
2856 case OSPF_ROUTER_LSA:
2857 case OSPF_NETWORK_LSA:
2858 case OSPF_SUMMARY_LSA:
2859 case OSPF_ASBR_SUMMARY_LSA:
paul718e3742002-12-13 20:15:29 +00002860 case OSPF_AS_NSSA_LSA:
paul718e3742002-12-13 20:15:29 +00002861#ifdef HAVE_OPAQUE_LSA
2862 case OSPF_OPAQUE_LINK_LSA:
2863 case OSPF_OPAQUE_AREA_LSA:
2864#endif /* HAVE_OPAQUE_LSA */
2865 ospf_flood_through_area (lsa->area, NULL, lsa);
2866 break;
2867 case OSPF_AS_EXTERNAL_LSA:
2868#ifdef HAVE_OPAQUE_LSA
2869 case OSPF_OPAQUE_AS_LSA:
2870#endif /* HAVE_OPAQUE_LSA */
2871 ospf_flood_through_as (NULL, lsa);
2872 break;
2873 default:
2874 break;
2875 }
2876}
2877#endif /* ORIGINAL_CODING */
2878
paul4dadc292005-05-06 21:37:42 +00002879static int
paul718e3742002-12-13 20:15:29 +00002880ospf_maxage_lsa_remover (struct thread *thread)
2881{
paul68980082003-03-25 05:07:42 +00002882 struct ospf *ospf = THREAD_ARG (thread);
paul1eb8ef22005-04-07 07:30:20 +00002883 struct ospf_lsa *lsa;
2884 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002885 int reschedule = 0;
2886
paul68980082003-03-25 05:07:42 +00002887 ospf->t_maxage = NULL;
paul718e3742002-12-13 20:15:29 +00002888
2889 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002890 zlog_debug ("LSA[MaxAge]: remover Start");
paul718e3742002-12-13 20:15:29 +00002891
paul68980082003-03-25 05:07:42 +00002892 reschedule = !ospf_check_nbr_status (ospf);
paul718e3742002-12-13 20:15:29 +00002893
2894 if (!reschedule)
paul1eb8ef22005-04-07 07:30:20 +00002895 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
paul718e3742002-12-13 20:15:29 +00002896 {
paul718e3742002-12-13 20:15:29 +00002897 if (lsa->retransmit_counter > 0)
2898 {
2899 reschedule = 1;
2900 continue;
2901 }
2902
2903 /* Remove LSA from the LSDB */
2904 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
2905 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002906 zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-oririnated: ",
paul7ddf1d62003-10-13 09:06:46 +00002907 lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa);
paul718e3742002-12-13 20:15:29 +00002908
2909 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002910 zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list",
paul718e3742002-12-13 20:15:29 +00002911 lsa->data->type, inet_ntoa (lsa->data->id));
2912
2913 /* Flood max age LSA. */
2914#ifdef ORIGINAL_CODING
2915 ospf_maxage_flood (lsa);
2916#else /* ORIGINAL_CODING */
paul68980082003-03-25 05:07:42 +00002917 ospf_flood_through (ospf, NULL, lsa);
paul718e3742002-12-13 20:15:29 +00002918#endif /* ORIGINAL_CODING */
2919
paul7ddf1d62003-10-13 09:06:46 +00002920 if (lsa->flags & OSPF_LSA_PREMATURE_AGE)
2921 {
2922 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002923 zlog_debug ("originating new router lsa for lsa 0x%lx \n",
paul7ddf1d62003-10-13 09:06:46 +00002924 (u_long)lsa);
2925 ospf_router_lsa_originate(lsa->area);
2926 }
2927
paul718e3742002-12-13 20:15:29 +00002928 /* Remove from lsdb. */
paul68980082003-03-25 05:07:42 +00002929 ospf_discard_from_db (ospf, lsa->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +00002930 ospf_lsdb_delete (lsa->lsdb, lsa);
2931 }
2932
2933 /* A MaxAge LSA must be removed immediately from the router's link
2934 state database as soon as both a) it is no longer contained on any
2935 neighbor Link state retransmission lists and b) none of the router's
2936 neighbors are in states Exchange or Loading. */
2937 if (reschedule)
paul68980082003-03-25 05:07:42 +00002938 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002939
2940 return 0;
2941}
2942
paul4dadc292005-05-06 21:37:42 +00002943static int
paul68980082003-03-25 05:07:42 +00002944ospf_lsa_maxage_exist (struct ospf *ospf, struct ospf_lsa *new)
paul718e3742002-12-13 20:15:29 +00002945{
hasso52dc7ee2004-09-23 19:18:23 +00002946 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +00002947 struct ospf_lsa *lsa;
2948
2949 for (ALL_LIST_ELEMENTS_RO (ospf->maxage_lsa, node, lsa))
2950 if (lsa == new)
paul718e3742002-12-13 20:15:29 +00002951 return 1;
2952
2953 return 0;
2954}
2955
2956void
paul68980082003-03-25 05:07:42 +00002957ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002958{
hasso52dc7ee2004-09-23 19:18:23 +00002959 struct listnode *n;
paul718e3742002-12-13 20:15:29 +00002960
paul68980082003-03-25 05:07:42 +00002961 if ((n = listnode_lookup (ospf->maxage_lsa, lsa)))
paul718e3742002-12-13 20:15:29 +00002962 {
paul68980082003-03-25 05:07:42 +00002963 list_delete_node (ospf->maxage_lsa, n);
paul718e3742002-12-13 20:15:29 +00002964 ospf_lsa_unlock (lsa);
2965 }
2966}
2967
2968void
paul68980082003-03-25 05:07:42 +00002969ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002970{
2971 /* When we saw a MaxAge LSA flooded to us, we put it on the list
2972 and schedule the MaxAge LSA remover. */
paul68980082003-03-25 05:07:42 +00002973 if (ospf_lsa_maxage_exist (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00002974 {
2975 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002976 zlog_debug ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list",
paul718e3742002-12-13 20:15:29 +00002977 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
2978 return;
2979 }
2980
paul68980082003-03-25 05:07:42 +00002981 listnode_add (ospf->maxage_lsa, ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00002982
2983 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00002984 zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00002985
paul68980082003-03-25 05:07:42 +00002986 OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
paul718e3742002-12-13 20:15:29 +00002987}
2988
paul4dadc292005-05-06 21:37:42 +00002989static int
paul68980082003-03-25 05:07:42 +00002990ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00002991{
paul718e3742002-12-13 20:15:29 +00002992 /* Stay away from any Local Translated Type-7 LSAs */
2993 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
2994 return 0;
paul718e3742002-12-13 20:15:29 +00002995
2996 if (IS_LSA_MAXAGE (lsa))
2997 /* Self-originated LSAs should NOT time-out instead,
2998 they're flushed and submitted to the max_age list explicitly. */
paul68980082003-03-25 05:07:42 +00002999 if (!ospf_lsa_is_self_originated (ospf, lsa))
paul718e3742002-12-13 20:15:29 +00003000 {
3001 if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
ajse588f212004-12-08 18:12:06 +00003002 zlog_debug("LSA[%s]: is MaxAge", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00003003
3004 switch (lsa->data->type)
3005 {
paul718e3742002-12-13 20:15:29 +00003006#ifdef HAVE_OPAQUE_LSA
paul37163d62003-02-03 18:40:56 +00003007 case OSPF_OPAQUE_LINK_LSA:
3008 case OSPF_OPAQUE_AREA_LSA:
paul718e3742002-12-13 20:15:29 +00003009 case OSPF_OPAQUE_AS_LSA:
paul09e4efd2003-01-18 00:12:02 +00003010 /*
3011 * As a general rule, whenever network topology has changed
3012 * (due to an LSA removal in this case), routing recalculation
3013 * should be triggered. However, this is not true for opaque
3014 * LSAs. Even if an opaque LSA instance is going to be removed
3015 * from the routing domain, it does not mean a change in network
3016 * topology, and thus, routing recalculation is not needed here.
3017 */
3018 break;
paul718e3742002-12-13 20:15:29 +00003019#endif /* HAVE_OPAQUE_LSA */
paul09e4efd2003-01-18 00:12:02 +00003020 case OSPF_AS_EXTERNAL_LSA:
hassobeebba72004-06-20 21:00:27 +00003021 case OSPF_AS_NSSA_LSA:
paul68980082003-03-25 05:07:42 +00003022 ospf_ase_incremental_update (ospf, lsa);
3023 break;
paul718e3742002-12-13 20:15:29 +00003024 default:
paul68980082003-03-25 05:07:42 +00003025 ospf_spf_calculate_schedule (ospf);
3026 break;
paul718e3742002-12-13 20:15:29 +00003027 }
paul68980082003-03-25 05:07:42 +00003028 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003029 }
3030
3031 return 0;
3032}
3033
3034/* Periodical check of MaxAge LSA. */
3035int
paul68980082003-03-25 05:07:42 +00003036ospf_lsa_maxage_walker (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00003037{
paul68980082003-03-25 05:07:42 +00003038 struct ospf *ospf = THREAD_ARG (thread);
3039 struct route_node *rn;
3040 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +00003041 struct ospf_area *area;
3042 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003043
paul68980082003-03-25 05:07:42 +00003044 ospf->t_maxage_walker = NULL;
paul718e3742002-12-13 20:15:29 +00003045
paul1eb8ef22005-04-07 07:30:20 +00003046 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +00003047 {
paul68980082003-03-25 05:07:42 +00003048 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
3049 ospf_lsa_maxage_walker_remover (ospf, lsa);
3050 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
3051 ospf_lsa_maxage_walker_remover (ospf, lsa);
3052 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
3053 ospf_lsa_maxage_walker_remover (ospf, lsa);
3054 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
3055 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003056#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003057 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
3058 ospf_lsa_maxage_walker_remover (ospf, lsa);
3059 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
3060 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003061#endif /* HAVE_OPAQUE_LSA */
paul4fb949e2003-05-10 20:06:51 +00003062 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
3063 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003064 }
3065
paul4fb949e2003-05-10 20:06:51 +00003066 /* for AS-external-LSAs. */
paul68980082003-03-25 05:07:42 +00003067 if (ospf->lsdb)
3068 {
3069 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
3070 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003071#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003072 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
3073 ospf_lsa_maxage_walker_remover (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003074#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +00003075 }
paul718e3742002-12-13 20:15:29 +00003076
paul68980082003-03-25 05:07:42 +00003077 OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker,
3078 OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +00003079 return 0;
3080}
3081
paul68980082003-03-25 05:07:42 +00003082struct ospf_lsa *
3083ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type,
3084 struct prefix_ipv4 *p, struct in_addr router_id)
paul718e3742002-12-13 20:15:29 +00003085{
paul68980082003-03-25 05:07:42 +00003086 struct ospf_lsa *lsa;
3087 struct in_addr mask, id;
3088 struct lsa_header_mask
3089 {
3090 struct lsa_header header;
3091 struct in_addr mask;
3092 } *hmask;
paul718e3742002-12-13 20:15:29 +00003093
paul68980082003-03-25 05:07:42 +00003094 lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id);
3095 if (lsa == NULL)
3096 return NULL;
paul718e3742002-12-13 20:15:29 +00003097
paul68980082003-03-25 05:07:42 +00003098 masklen2ip (p->prefixlen, &mask);
paul718e3742002-12-13 20:15:29 +00003099
paul68980082003-03-25 05:07:42 +00003100 hmask = (struct lsa_header_mask *) lsa->data;
paul718e3742002-12-13 20:15:29 +00003101
paul68980082003-03-25 05:07:42 +00003102 if (mask.s_addr != hmask->mask.s_addr)
3103 {
3104 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
3105 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id);
3106 if (!lsa)
3107 return NULL;
3108 }
paul718e3742002-12-13 20:15:29 +00003109
paul68980082003-03-25 05:07:42 +00003110 return lsa;
paul718e3742002-12-13 20:15:29 +00003111}
3112
3113struct ospf_lsa *
3114ospf_lsa_lookup (struct ospf_area *area, u_int32_t type,
3115 struct in_addr id, struct in_addr adv_router)
3116{
paule05fba42003-04-13 20:20:53 +00003117 struct ospf *ospf = ospf_lookup();
3118 assert(ospf);
3119
paul718e3742002-12-13 20:15:29 +00003120 switch (type)
3121 {
3122 case OSPF_ROUTER_LSA:
3123 case OSPF_NETWORK_LSA:
3124 case OSPF_SUMMARY_LSA:
3125 case OSPF_ASBR_SUMMARY_LSA:
paul718e3742002-12-13 20:15:29 +00003126 case OSPF_AS_NSSA_LSA:
paul718e3742002-12-13 20:15:29 +00003127#ifdef HAVE_OPAQUE_LSA
3128 case OSPF_OPAQUE_LINK_LSA:
3129 case OSPF_OPAQUE_AREA_LSA:
3130#endif /* HAVE_OPAQUE_LSA */
3131 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router);
3132 break;
3133 case OSPF_AS_EXTERNAL_LSA:
3134#ifdef HAVE_OPAQUE_LSA
3135 case OSPF_OPAQUE_AS_LSA:
3136#endif /* HAVE_OPAQUE_LSA */
paule05fba42003-04-13 20:20:53 +00003137 return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router);
paul718e3742002-12-13 20:15:29 +00003138 break;
3139 default:
3140 break;
3141 }
3142
3143 return NULL;
3144}
3145
3146struct ospf_lsa *
3147ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type,
3148 struct in_addr id)
3149{
3150 struct ospf_lsa *lsa;
3151 struct route_node *rn;
3152
3153 switch (type)
3154 {
3155 case OSPF_ROUTER_LSA:
3156 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
3157 break;
3158 case OSPF_NETWORK_LSA:
3159 for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn))
3160 if ((lsa = rn->info))
3161 if (IPV4_ADDR_SAME (&lsa->data->id, &id))
3162 {
3163 route_unlock_node (rn);
3164 return lsa;
3165 }
3166 break;
3167 case OSPF_SUMMARY_LSA:
3168 case OSPF_ASBR_SUMMARY_LSA:
3169 /* Currently not used. */
3170 assert (1);
3171 return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
3172 break;
3173 case OSPF_AS_EXTERNAL_LSA:
pauld4a53d52003-07-12 21:30:57 +00003174 case OSPF_AS_NSSA_LSA:
paul718e3742002-12-13 20:15:29 +00003175#ifdef HAVE_OPAQUE_LSA
3176 case OSPF_OPAQUE_LINK_LSA:
3177 case OSPF_OPAQUE_AREA_LSA:
3178 case OSPF_OPAQUE_AS_LSA:
3179 /* Currently not used. */
3180 break;
3181#endif /* HAVE_OPAQUE_LSA */
3182 default:
3183 break;
3184 }
3185
3186 return NULL;
3187}
3188
3189struct ospf_lsa *
3190ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah)
3191{
3192 struct ospf_lsa *match;
3193
3194#ifdef HAVE_OPAQUE_LSA
3195 /*
3196 * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11)
3197 * is redefined to have two subfields; opaque-type and opaque-id.
3198 * However, it is harmless to treat the two sub fields together, as if
3199 * they two were forming a unique LSA-ID.
3200 */
3201#endif /* HAVE_OPAQUE_LSA */
3202
3203 match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router);
3204
3205 if (match == NULL)
3206 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
ajse588f212004-12-08 18:12:06 +00003207 zlog_debug ("LSA[Type%d:%s]: Lookup by header, NO MATCH",
paul718e3742002-12-13 20:15:29 +00003208 lsah->type, inet_ntoa (lsah->id));
3209
3210 return match;
3211}
3212
3213/* return +n, l1 is more recent.
3214 return -n, l2 is more recent.
3215 return 0, l1 and l2 is identical. */
3216int
3217ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
3218{
3219 int r;
3220 int x, y;
3221
3222 if (l1 == NULL && l2 == NULL)
3223 return 0;
3224 if (l1 == NULL)
3225 return -1;
3226 if (l2 == NULL)
3227 return 1;
3228
3229 /* compare LS sequence number. */
3230 x = (int) ntohl (l1->data->ls_seqnum);
3231 y = (int) ntohl (l2->data->ls_seqnum);
3232 if (x > y)
3233 return 1;
3234 if (x < y)
3235 return -1;
3236
3237 /* compare LS checksum. */
3238 r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
3239 if (r)
3240 return r;
3241
3242 /* compare LS age. */
3243 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
3244 return 1;
3245 else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
3246 return -1;
3247
3248 /* compare LS age with MaxAgeDiff. */
3249 if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
3250 return -1;
3251 else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
3252 return 1;
3253
3254 /* LSAs are identical. */
3255 return 0;
3256}
3257
3258/* If two LSAs are different, return 1, otherwise return 0. */
3259int
3260ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
3261{
3262 char *p1, *p2;
3263 assert (l1);
3264 assert (l2);
3265 assert (l1->data);
3266 assert (l2->data);
3267
3268 if (l1->data->options != l2->data->options)
3269 return 1;
3270
3271 if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
3272 return 1;
3273
3274 if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
3275 return 1;
3276
3277 if (l1->data->length != l2->data->length)
3278 return 1;
3279
3280 if (l1->data->length == 0)
3281 return 1;
3282
pauld1825832003-04-03 01:27:01 +00003283 assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00003284
3285 p1 = (char *) l1->data;
3286 p2 = (char *) l2->data;
3287
3288 if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
3289 ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
3290 return 1;
3291
3292 return 0;
3293}
3294
3295#ifdef ORIGINAL_CODING
3296void
3297ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr,
3298 struct ospf_lsa *self,
3299 struct ospf_lsa *new)
3300{
3301 u_int32_t seqnum;
3302
3303 /* Adjust LS Sequence Number. */
3304 seqnum = ntohl (new->data->ls_seqnum) + 1;
3305 self->data->ls_seqnum = htonl (seqnum);
3306
3307 /* Recalculate LSA checksum. */
3308 ospf_lsa_checksum (self->data);
3309
3310 /* Reflooding LSA. */
3311 /* RFC2328 Section 13.3
3312 On non-broadcast networks, separate Link State Update
3313 packets must be sent, as unicasts, to each adjacent neighbor
3314 (i.e., those in state Exchange or greater). The destination
3315 IP addresses for these packets are the neighbors' IP
3316 addresses. */
3317 if (nbr->oi->type == OSPF_IFTYPE_NBMA)
3318 {
3319 struct route_node *rn;
3320 struct ospf_neighbor *onbr;
3321
3322 for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn))
3323 if ((onbr = rn->info) != NULL)
3324 if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange)
3325 ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT);
3326 }
3327 else
3328 ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT);
3329
3330 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00003331 zlog_debug ("LSA[Type%d:%s]: Flush self-originated LSA",
paul718e3742002-12-13 20:15:29 +00003332 self->data->type, inet_ntoa (self->data->id));
3333}
3334#else /* ORIGINAL_CODING */
3335static int
paul68980082003-03-25 05:07:42 +00003336ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003337{
3338 if (lsa == NULL || !IS_LSA_SELF (lsa))
3339 return 0;
3340
3341 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00003342 zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00003343
3344 /* Force given lsa's age to MaxAge. */
3345 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
3346
3347 switch (lsa->data->type)
3348 {
3349#ifdef HAVE_OPAQUE_LSA
3350 case OSPF_OPAQUE_LINK_LSA:
3351 case OSPF_OPAQUE_AREA_LSA:
3352 case OSPF_OPAQUE_AS_LSA:
3353 ospf_opaque_lsa_refresh (lsa);
3354 break;
3355#endif /* HAVE_OPAQUE_LSA */
3356 default:
paul68980082003-03-25 05:07:42 +00003357 ospf_lsa_maxage (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003358 break;
3359 }
3360
3361 return 0;
3362}
3363
3364void
paul68980082003-03-25 05:07:42 +00003365ospf_flush_self_originated_lsas_now (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +00003366{
paul1eb8ef22005-04-07 07:30:20 +00003367 struct listnode *node, *nnode;
3368 struct listnode *node2, *nnode2;
paul718e3742002-12-13 20:15:29 +00003369 struct ospf_area *area;
3370 struct ospf_interface *oi;
3371 struct ospf_lsa *lsa;
paul68980082003-03-25 05:07:42 +00003372 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +00003373 int need_to_flush_ase = 0;
3374
paul1eb8ef22005-04-07 07:30:20 +00003375 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +00003376 {
paul718e3742002-12-13 20:15:29 +00003377 if ((lsa = area->router_lsa_self) != NULL)
3378 {
3379 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00003380 zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00003381
3382 ospf_lsa_flush_area (lsa, area);
3383 ospf_lsa_unlock (area->router_lsa_self);
3384 area->router_lsa_self = NULL;
3385 OSPF_TIMER_OFF (area->t_router_lsa_self);
3386 }
3387
paul1eb8ef22005-04-07 07:30:20 +00003388 for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
paul718e3742002-12-13 20:15:29 +00003389 {
paul718e3742002-12-13 20:15:29 +00003390 if ((lsa = oi->network_lsa_self) != NULL
paul1eb8ef22005-04-07 07:30:20 +00003391 && oi->state == ISM_DR
3392 && oi->full_nbrs > 0)
paul718e3742002-12-13 20:15:29 +00003393 {
3394 if (IS_DEBUG_OSPF_EVENT)
ajse588f212004-12-08 18:12:06 +00003395 zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
paul718e3742002-12-13 20:15:29 +00003396
3397 ospf_lsa_flush_area (oi->network_lsa_self, area);
3398 ospf_lsa_unlock (oi->network_lsa_self);
3399 oi->network_lsa_self = NULL;
3400 OSPF_TIMER_OFF (oi->t_network_lsa_self);
3401 }
3402
3403 if (oi->type != OSPF_IFTYPE_VIRTUALLINK
3404 && area->external_routing == OSPF_AREA_DEFAULT)
3405 need_to_flush_ase = 1;
3406 }
3407
paul68980082003-03-25 05:07:42 +00003408 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
3409 ospf_lsa_flush_schedule (ospf, lsa);
3410 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
3411 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003412#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003413 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
3414 ospf_lsa_flush_schedule (ospf, lsa);
3415 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
3416 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003417#endif /* HAVE_OPAQUE_LSA */
3418 }
3419
3420 if (need_to_flush_ase)
3421 {
paul68980082003-03-25 05:07:42 +00003422 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
3423 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003424#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00003425 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
3426 ospf_lsa_flush_schedule (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003427#endif /* HAVE_OPAQUE_LSA */
3428 }
3429
3430 /*
3431 * Make sure that the MaxAge LSA remover is executed immediately,
3432 * without conflicting to other threads.
3433 */
paul68980082003-03-25 05:07:42 +00003434 if (ospf->t_maxage != NULL)
paul718e3742002-12-13 20:15:29 +00003435 {
paul68980082003-03-25 05:07:42 +00003436 OSPF_TIMER_OFF (ospf->t_maxage);
3437 thread_execute (master, ospf_maxage_lsa_remover, ospf, 0);
paul718e3742002-12-13 20:15:29 +00003438 }
3439
3440 return;
3441}
3442#endif /* ORIGINAL_CODING */
3443
3444/* If there is self-originated LSA, then return 1, otherwise return 0. */
3445/* An interface-independent version of ospf_lsa_is_self_originated */
3446int
paul68980082003-03-25 05:07:42 +00003447ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003448{
hasso52dc7ee2004-09-23 19:18:23 +00003449 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +00003450 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +00003451
3452 /* This LSA is already checked. */
3453 if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
3454 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3455
3456 /* Make sure LSA is self-checked. */
3457 SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);
3458
3459 /* AdvRouter and Router ID is the same. */
paul68980082003-03-25 05:07:42 +00003460 if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003461 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3462
3463 /* LSA is router-LSA. */
3464 else if (lsa->data->type == OSPF_ROUTER_LSA &&
paul68980082003-03-25 05:07:42 +00003465 IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
paul718e3742002-12-13 20:15:29 +00003466 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3467
3468 /* LSA is network-LSA. Compare Link ID with all interfaces. */
3469 else if (lsa->data->type == OSPF_NETWORK_LSA)
paul1eb8ef22005-04-07 07:30:20 +00003470 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00003471 {
paul718e3742002-12-13 20:15:29 +00003472 /* Ignore virtual link. */
3473 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
3474 if (oi->address->family == AF_INET)
3475 if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4))
3476 {
3477 /* to make it easier later */
3478 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
3479 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3480 }
3481 }
3482
3483 return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
3484}
3485
3486/* Get unique Link State ID. */
3487struct in_addr
paul68980082003-03-25 05:07:42 +00003488ospf_lsa_unique_id (struct ospf *ospf,
3489 struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +00003490{
3491 struct ospf_lsa *lsa;
3492 struct in_addr mask, id;
3493
3494 id = p->prefix;
3495
3496 /* Check existence of LSA instance. */
paul68980082003-03-25 05:07:42 +00003497 lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003498 if (lsa)
3499 {
3500 struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
3501 if (ip_masklen (al->mask) == p->prefixlen)
3502 {
3503 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00003504 zlog_debug ("ospf_lsa_unique_id(): "
paul718e3742002-12-13 20:15:29 +00003505 "Can't get Link State ID for %s/%d",
3506 inet_ntoa (p->prefix), p->prefixlen);
3507 /* id.s_addr = 0; */
3508 id.s_addr = 0xffffffff;
3509 return id;
3510 }
3511 /* Masklen differs, then apply wildcard mask to Link State ID. */
3512 else
3513 {
3514 masklen2ip (p->prefixlen, &mask);
3515
3516 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
paul68980082003-03-25 05:07:42 +00003517 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type,
3518 id, ospf->router_id);
paul718e3742002-12-13 20:15:29 +00003519 if (lsa)
3520 {
3521 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
ajse588f212004-12-08 18:12:06 +00003522 zlog_debug ("ospf_lsa_unique_id(): "
paul718e3742002-12-13 20:15:29 +00003523 "Can't get Link State ID for %s/%d",
3524 inet_ntoa (p->prefix), p->prefixlen);
3525 /* id.s_addr = 0; */
3526 id.s_addr = 0xffffffff;
3527 return id;
3528 }
3529 }
3530 }
3531
3532 return id;
3533}
3534
3535
3536#define LSA_ACTION_ORIGN_RTR 1
3537#define LSA_ACTION_ORIGN_NET 2
3538#define LSA_ACTION_FLOOD_AREA 3
3539#define LSA_ACTION_FLOOD_AS 4
3540#define LSA_ACTION_FLUSH_AREA 5
3541#define LSA_ACTION_FLUSH_AS 6
3542
3543struct lsa_action
3544{
3545 u_char action;
3546 struct ospf_area *area;
3547 struct ospf_interface *oi;
3548 struct ospf_lsa *lsa;
3549};
3550
paul4dadc292005-05-06 21:37:42 +00003551static int
paul718e3742002-12-13 20:15:29 +00003552ospf_lsa_action (struct thread *t)
3553{
3554 struct lsa_action *data;
paul020709f2003-04-04 02:44:16 +00003555 struct ospf *ospf;
3556
3557 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00003558
3559 data = THREAD_ARG (t);
3560
3561 if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
ajse588f212004-12-08 18:12:06 +00003562 zlog_debug ("LSA[Action]: Performing scheduled LSA action: %d",
paul718e3742002-12-13 20:15:29 +00003563 data->action);
3564
3565 switch (data->action)
3566 {
3567 case LSA_ACTION_ORIGN_RTR:
3568 ospf_router_lsa_refresh (data->area->router_lsa_self);
3569 break;
3570 case LSA_ACTION_ORIGN_NET:
3571 ospf_network_lsa_originate (data->oi);
3572 break;
3573 case LSA_ACTION_FLOOD_AREA:
3574 ospf_flood_through_area (data->area, NULL, data->lsa);
3575 break;
3576 case LSA_ACTION_FLOOD_AS:
paul68980082003-03-25 05:07:42 +00003577 ospf_flood_through_as (ospf, NULL, data->lsa);
paul718e3742002-12-13 20:15:29 +00003578 break;
3579 case LSA_ACTION_FLUSH_AREA:
3580 ospf_lsa_flush_area (data->lsa, data->area);
3581 break;
3582 case LSA_ACTION_FLUSH_AS:
paul68980082003-03-25 05:07:42 +00003583 ospf_lsa_flush_as (ospf, data->lsa);
paul718e3742002-12-13 20:15:29 +00003584 break;
3585 }
3586
3587 ospf_lsa_unlock (data->lsa);
3588 XFREE (MTYPE_OSPF_MESSAGE, data);
3589 return 0;
3590}
3591
3592void
3593ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa)
3594{
3595 struct lsa_action *data;
3596
3597 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3598 memset (data, 0, sizeof (struct lsa_action));
3599
3600 data->action = LSA_ACTION_FLOOD_AREA;
3601 data->area = area;
3602 data->lsa = ospf_lsa_lock (lsa);
3603
3604 thread_add_event (master, ospf_lsa_action, data, 0);
3605}
3606
3607void
3608ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
3609{
3610 struct lsa_action *data;
3611
3612 data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
3613 memset (data, 0, sizeof (struct lsa_action));
3614
3615 data->action = LSA_ACTION_FLUSH_AREA;
3616 data->area = area;
3617 data->lsa = ospf_lsa_lock (lsa);
3618
3619 thread_add_event (master, ospf_lsa_action, data, 0);
3620}
3621
3622
3623/* LSA Refreshment functions. */
paul4dadc292005-05-06 21:37:42 +00003624static void
paul68980082003-03-25 05:07:42 +00003625ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003626{
3627 struct external_info *ei;
3628 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3629
3630 switch (lsa->data->type)
3631 {
3632 /* Router and Network LSAs are processed differently. */
3633 case OSPF_ROUTER_LSA:
3634 case OSPF_NETWORK_LSA:
3635 break;
3636 case OSPF_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003637 ospf_summary_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003638 break;
3639 case OSPF_ASBR_SUMMARY_LSA:
paul68980082003-03-25 05:07:42 +00003640 ospf_summary_asbr_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003641 break;
3642 case OSPF_AS_EXTERNAL_LSA:
pauld4a53d52003-07-12 21:30:57 +00003643 /* Translated from NSSA Type-5s are refreshed when
3644 * from refresh of Type-7 - do not refresh these directly.
3645 */
3646 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
3647 break;
paul718e3742002-12-13 20:15:29 +00003648 ei = ospf_external_info_check (lsa);
3649 if (ei)
pauld4a53d52003-07-12 21:30:57 +00003650 ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
paul718e3742002-12-13 20:15:29 +00003651 else
pauld4a53d52003-07-12 21:30:57 +00003652 ospf_lsa_flush_as (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003653 break;
3654#ifdef HAVE_OPAQUE_LSA
3655 case OSPF_OPAQUE_LINK_LSA:
3656 case OSPF_OPAQUE_AREA_LSA:
3657 case OSPF_OPAQUE_AS_LSA:
3658 ospf_opaque_lsa_refresh (lsa);
3659 break;
pauld7480322003-05-16 17:31:51 +00003660#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00003661 default:
3662 break;
paul718e3742002-12-13 20:15:29 +00003663 }
3664}
3665
3666void
paul68980082003-03-25 05:07:42 +00003667ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003668{
3669 u_int16_t index, current_index;
3670
3671 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3672
3673 if (lsa->refresh_list < 0)
3674 {
3675 int delay;
3676
3677 if (LS_AGE (lsa) == 0 &&
3678 ntohl (lsa->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)
3679 /* Randomize first update by OSPF_LS_REFRESH_SHIFT factor */
3680 delay = OSPF_LS_REFRESH_SHIFT + (random () % OSPF_LS_REFRESH_TIME);
3681 else
3682 /* Randomize another updates by +-OSPF_LS_REFRESH_JITTER factor */
3683 delay = OSPF_LS_REFRESH_TIME - LS_AGE (lsa) - OSPF_LS_REFRESH_JITTER
3684 + (random () % (2*OSPF_LS_REFRESH_JITTER));
3685
3686 if (delay < 0)
3687 delay = 0;
3688
paul68980082003-03-25 05:07:42 +00003689 current_index = ospf->lsa_refresh_queue.index +
3690 (time (NULL) - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
paul718e3742002-12-13 20:15:29 +00003691
3692 index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
3693 % (OSPF_LSA_REFRESHER_SLOTS);
3694
3695 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003696 zlog_debug ("LSA[Refresh]: lsa %s with age %d added to index %d",
pauld4a53d52003-07-12 21:30:57 +00003697 inet_ntoa (lsa->data->id), LS_AGE (lsa), index);
paul68980082003-03-25 05:07:42 +00003698 if (!ospf->lsa_refresh_queue.qs[index])
3699 ospf->lsa_refresh_queue.qs[index] = list_new ();
3700 listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
paul718e3742002-12-13 20:15:29 +00003701 lsa->refresh_list = index;
paulf2c80652002-12-13 21:44:27 +00003702 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003703 zlog_debug ("LSA[Refresh:%s]: ospf_refresher_register_lsa(): "
pauld4a53d52003-07-12 21:30:57 +00003704 "setting refresh_list on lsa %p (slod %d)",
3705 inet_ntoa (lsa->data->id), lsa, index);
paul718e3742002-12-13 20:15:29 +00003706 }
3707}
3708
3709void
paul68980082003-03-25 05:07:42 +00003710ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00003711{
3712 assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
3713 if (lsa->refresh_list >= 0)
3714 {
hasso52dc7ee2004-09-23 19:18:23 +00003715 struct list *refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list];
paul718e3742002-12-13 20:15:29 +00003716 listnode_delete (refresh_list, lsa);
3717 if (!listcount (refresh_list))
3718 {
3719 list_free (refresh_list);
paul68980082003-03-25 05:07:42 +00003720 ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
paul718e3742002-12-13 20:15:29 +00003721 }
3722 ospf_lsa_unlock (lsa);
3723 lsa->refresh_list = -1;
3724 }
3725}
3726
3727int
3728ospf_lsa_refresh_walker (struct thread *t)
3729{
hasso52dc7ee2004-09-23 19:18:23 +00003730 struct list *refresh_list;
paul1eb8ef22005-04-07 07:30:20 +00003731 struct listnode *node, *nnode;
paul68980082003-03-25 05:07:42 +00003732 struct ospf *ospf = THREAD_ARG (t);
paul1eb8ef22005-04-07 07:30:20 +00003733 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +00003734 int i;
hasso52dc7ee2004-09-23 19:18:23 +00003735 struct list *lsa_to_refresh = list_new ();
paul718e3742002-12-13 20:15:29 +00003736
3737 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003738 zlog_debug ("LSA[Refresh]:ospf_lsa_refresh_walker(): start");
paul718e3742002-12-13 20:15:29 +00003739
3740
paul68980082003-03-25 05:07:42 +00003741 i = ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003742
ajs9dbc7972005-03-13 19:27:22 +00003743 /* Note: if clock has jumped backwards, then time change could be negative,
3744 so we are careful to cast the expression to unsigned before taking
3745 modulus. */
paul68980082003-03-25 05:07:42 +00003746 ospf->lsa_refresh_queue.index =
ajs9dbc7972005-03-13 19:27:22 +00003747 ((unsigned long)(ospf->lsa_refresh_queue.index +
3748 (time (NULL) - ospf->lsa_refresher_started) /
3749 OSPF_LSA_REFRESHER_GRANULARITY)) % OSPF_LSA_REFRESHER_SLOTS;
paul718e3742002-12-13 20:15:29 +00003750
3751 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003752 zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
paul68980082003-03-25 05:07:42 +00003753 ospf->lsa_refresh_queue.index);
paul718e3742002-12-13 20:15:29 +00003754
paul68980082003-03-25 05:07:42 +00003755 for (;i != ospf->lsa_refresh_queue.index;
paul718e3742002-12-13 20:15:29 +00003756 i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
3757 {
3758 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003759 zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): "
pauld4a53d52003-07-12 21:30:57 +00003760 "refresh index %d", i);
paul718e3742002-12-13 20:15:29 +00003761
paul68980082003-03-25 05:07:42 +00003762 refresh_list = ospf->lsa_refresh_queue.qs [i];
paul718e3742002-12-13 20:15:29 +00003763
paul68980082003-03-25 05:07:42 +00003764 ospf->lsa_refresh_queue.qs [i] = NULL;
3765
paul718e3742002-12-13 20:15:29 +00003766 if (refresh_list)
3767 {
paul1eb8ef22005-04-07 07:30:20 +00003768 for (ALL_LIST_ELEMENTS (refresh_list, node, nnode, lsa))
paul718e3742002-12-13 20:15:29 +00003769 {
paul718e3742002-12-13 20:15:29 +00003770 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003771 zlog_debug ("LSA[Refresh:%s]: ospf_lsa_refresh_walker(): "
pauld4a53d52003-07-12 21:30:57 +00003772 "refresh lsa %p (slot %d)",
3773 inet_ntoa (lsa->data->id), lsa, i);
paul718e3742002-12-13 20:15:29 +00003774
3775 list_delete_node (refresh_list, node);
3776 ospf_lsa_unlock (lsa);
3777 lsa->refresh_list = -1;
3778 listnode_add (lsa_to_refresh, lsa);
paul718e3742002-12-13 20:15:29 +00003779 }
3780 list_free (refresh_list);
3781 }
3782 }
3783
paul68980082003-03-25 05:07:42 +00003784 ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
3785 ospf, ospf->lsa_refresh_interval);
3786 ospf->lsa_refresher_started = time (NULL);
paul718e3742002-12-13 20:15:29 +00003787
paul1eb8ef22005-04-07 07:30:20 +00003788 for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa))
3789 ospf_lsa_refresh (ospf, lsa);
paul718e3742002-12-13 20:15:29 +00003790
3791 list_delete (lsa_to_refresh);
3792
3793 if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
ajse588f212004-12-08 18:12:06 +00003794 zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
paul718e3742002-12-13 20:15:29 +00003795
3796 return 0;
3797}
3798