blob: 08e410056507713ab079e3adca4fb25a7719565a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* OSPF version 2 daemon program.
2 Copyright (C) 1999, 2000 Toshiaki Takada
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "vty.h"
25#include "command.h"
26#include "linklist.h"
27#include "prefix.h"
28#include "table.h"
29#include "if.h"
30#include "memory.h"
31#include "stream.h"
32#include "log.h"
33#include "sockunion.h" /* for inet_aton () */
34#include "zclient.h"
35#include "plist.h"
Denis Ovsienkof102e752007-09-18 09:01:13 +000036#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_network.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_spf.h"
48#include "ospfd/ospf_packet.h"
49#include "ospfd/ospf_dump.h"
50#include "ospfd/ospf_zebra.h"
51#include "ospfd/ospf_abr.h"
52#include "ospfd/ospf_flood.h"
53#include "ospfd/ospf_route.h"
54#include "ospfd/ospf_ase.h"
55
paul020709f2003-04-04 02:44:16 +000056
pauledd7c242003-06-04 13:59:38 +000057
paul020709f2003-04-04 02:44:16 +000058/* OSPF process wide configuration. */
59static struct ospf_master ospf_master;
60
61/* OSPF process wide configuration pointer to export. */
62struct ospf_master *om;
paul718e3742002-12-13 20:15:29 +000063
64extern struct zclient *zclient;
hasso18a6dce2004-10-03 18:18:34 +000065extern struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000066
67
paul88d6cf32005-10-29 12:50:09 +000068static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
69static void ospf_network_free (struct ospf *, struct ospf_network *);
70static void ospf_area_free (struct ospf_area *);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010071static void ospf_network_run (struct prefix *, struct ospf_area *);
72static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
73 struct interface *);
paul88d6cf32005-10-29 12:50:09 +000074static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000075
paul718e3742002-12-13 20:15:29 +000076#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000077
paul718e3742002-12-13 20:15:29 +000078void
paul68980082003-03-25 05:07:42 +000079ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000080{
paul718e3742002-12-13 20:15:29 +000081 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000082 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010083 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000084 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000085
86 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000087 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000088
paul68980082003-03-25 05:07:42 +000089 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000090
Andrew J. Schorr16700082006-07-27 22:29:06 +000091 /* Select the router ID based on these priorities:
92 1. Statically assigned router ID is always the first choice.
93 2. If there is no statically assigned router ID, then try to stick
94 with the most recent value, since changing router ID's is very
95 disruptive.
96 3. Last choice: just go with whatever the zebra daemon recommends.
97 */
paul68980082003-03-25 05:07:42 +000098 if (ospf->router_id_static.s_addr != 0)
99 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000100 else if (ospf->router_id.s_addr != 0)
101 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000102 else
hasso18a6dce2004-10-03 18:18:34 +0000103 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000104
paul68980082003-03-25 05:07:42 +0000105 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000106
107 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000108 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000109
110 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
111 {
paul1eb8ef22005-04-07 07:30:20 +0000112 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
113 /* Update self-neighbor's router_id. */
114 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000115
116 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000117 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000118 {
119 int type;
120 /* Originate each redistributed external route. */
121 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000122 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000123 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000124 ospf, type);
paul718e3742002-12-13 20:15:29 +0000125 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000126 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000127 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000128
paul68980082003-03-25 05:07:42 +0000129 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000130 }
131
paul68980082003-03-25 05:07:42 +0000132 OSPF_TIMER_ON (ospf->t_router_lsa_update,
paul718e3742002-12-13 20:15:29 +0000133 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
paulb29800a2005-11-20 14:50:45 +0000134
135 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100136 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
137 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000138 }
139}
paul718e3742002-12-13 20:15:29 +0000140
141/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000142static int
paul718e3742002-12-13 20:15:29 +0000143ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
144{
145 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
146 return 1;
147 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
148 return -1;
149 return 0;
150}
151
152/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000153static struct ospf *
154ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000155{
156 int i;
157
158 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
159
160 new->router_id.s_addr = htonl (0);
161 new->router_id_static.s_addr = htonl (0);
162
pauld57834f2005-07-12 20:04:22 +0000163 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000164 new->oiflist = list_new ();
165 new->vlinks = list_new ();
166 new->areas = list_new ();
167 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
168 new->networks = route_table_init ();
169 new->nbr_nbma = route_table_init ();
170
171 new->lsdb = ospf_lsdb_new ();
172
173 new->default_originate = DEFAULT_ORIGINATE_NONE;
174
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000175 new->passive_interface_default = OSPF_IF_ACTIVE;
176
paul718e3742002-12-13 20:15:29 +0000177 new->new_external_route = route_table_init ();
178 new->old_external_route = route_table_init ();
179 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000180
181 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000182 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul88d6cf32005-10-29 12:50:09 +0000183
paul718e3742002-12-13 20:15:29 +0000184 /* Distribute parameter init. */
185 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
186 {
187 new->dmetric[i].type = -1;
188 new->dmetric[i].value = -1;
189 }
190 new->default_metric = -1;
191 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
192
193 /* SPF timer value init. */
194 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
195 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000196 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
197 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000198
199 /* MaxAge init. */
200 new->maxage_lsa = list_new ();
201 new->t_maxage_walker =
202 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000203 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000204
205 /* Distance table init. */
206 new->distance_table = route_table_init ();
207
208 new->lsa_refresh_queue.index = 0;
209 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
210 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
211 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000212 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000213
ajs5c333492005-02-23 15:43:01 +0000214 if ((new->fd = ospf_sock_init()) < 0)
215 {
216 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
217 "a socket");
218 exit(1);
219 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000220 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
221 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
222 zlog_debug ("%s: starting with OSPF send buffer size %d",
223 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000224 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
225 {
226 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
227 OSPF_MAX_PACKET_SIZE+1);
228 exit(1);
229 }
230 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000231 new->oi_write_q = list_new ();
232
233 return new;
234}
235
236struct ospf *
paul020709f2003-04-04 02:44:16 +0000237ospf_lookup ()
238{
239 if (listcount (om->ospf) == 0)
240 return NULL;
241
paul1eb8ef22005-04-07 07:30:20 +0000242 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000243}
244
paul4dadc292005-05-06 21:37:42 +0000245static void
paul020709f2003-04-04 02:44:16 +0000246ospf_add (struct ospf *ospf)
247{
248 listnode_add (om->ospf, ospf);
249}
250
paul4dadc292005-05-06 21:37:42 +0000251static void
paul020709f2003-04-04 02:44:16 +0000252ospf_delete (struct ospf *ospf)
253{
254 listnode_delete (om->ospf, ospf);
255}
256
257struct ospf *
paul718e3742002-12-13 20:15:29 +0000258ospf_get ()
259{
paul020709f2003-04-04 02:44:16 +0000260 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000261
paul020709f2003-04-04 02:44:16 +0000262 ospf = ospf_lookup ();
263 if (ospf == NULL)
264 {
265 ospf = ospf_new ();
266 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000267
paul020709f2003-04-04 02:44:16 +0000268 if (ospf->router_id_static.s_addr == 0)
269 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000270
271#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000272 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000273#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000274 }
paul68980082003-03-25 05:07:42 +0000275
276 return ospf;
paul718e3742002-12-13 20:15:29 +0000277}
paul88d6cf32005-10-29 12:50:09 +0000278
paulc9c93d52005-11-26 13:31:11 +0000279/* Handle the second half of deferred shutdown. This is called either
280 * from the deferred-shutdown timer thread, or directly through
281 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000282 *
283 * Function is to cleanup G-R state, if required then call ospf_finish_final
284 * to complete shutdown of this ospf instance. Possibly exit if the
285 * whole process is being shutdown and this was the last OSPF instance.
286 */
287static void
paulc9c93d52005-11-26 13:31:11 +0000288ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000289{
290 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000291 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000292
293 ospf_finish_final (ospf);
294
295 /* *ospf is now invalid */
296
297 /* ospfd being shut-down? If so, was this the last ospf instance? */
298 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
299 && (listcount (om->ospf) == 0))
300 exit (0);
301
302 return;
303}
304
305/* Timer thread for G-R */
306static int
paulc9c93d52005-11-26 13:31:11 +0000307ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000308{
309 struct ospf *ospf = THREAD_ARG(t);
310
paulc9c93d52005-11-26 13:31:11 +0000311 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000312
313 return 0;
314}
315
paulc9c93d52005-11-26 13:31:11 +0000316/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000317 * down directly into second-half of instance shutdown.
318 */
319static void
paulc9c93d52005-11-26 13:31:11 +0000320ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000321{
322 unsigned long timeout;
323 struct listnode *ln;
324 struct ospf_area *area;
325
paulc9c93d52005-11-26 13:31:11 +0000326 /* deferred shutdown already running? */
327 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000328 return;
329
330 /* Should we try push out max-metric LSAs? */
331 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
332 {
333 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
334 {
335 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
336
337 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
338 ospf_router_lsa_timer_add (area);
339 }
340 timeout = ospf->stub_router_shutdown_time;
341 }
342 else
paulc9c93d52005-11-26 13:31:11 +0000343 {
344 /* No timer needed */
345 ospf_deferred_shutdown_finish (ospf);
346 return;
347 }
paul88d6cf32005-10-29 12:50:09 +0000348
paulc9c93d52005-11-26 13:31:11 +0000349 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000350 timeout);
351 return;
352}
353
354/* Shut down the entire process */
355void
356ospf_terminate (void)
357{
358 struct ospf *ospf;
359 struct listnode *node, *nnode;
360
361 /* shutdown already in progress */
362 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
363 return;
364
365 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
366
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000367 /* exit immediately if OSPF not actually running */
368 if (listcount(om->ospf) == 0)
369 exit(0);
370
paul88d6cf32005-10-29 12:50:09 +0000371 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
372 ospf_finish (ospf);
373
374 /* Deliberately go back up, hopefully to thread scheduler, as
375 * One or more ospf_finish()'s may have deferred shutdown to a timer
376 * thread
377 */
378}
paul718e3742002-12-13 20:15:29 +0000379
380void
381ospf_finish (struct ospf *ospf)
382{
paulc9c93d52005-11-26 13:31:11 +0000383 /* let deferred shutdown decide */
384 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000385
paulc9c93d52005-11-26 13:31:11 +0000386 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000387 * deferred to expiry of G-S timer thread. Return back up, hopefully
388 * to thread scheduler.
389 */
paulc9c93d52005-11-26 13:31:11 +0000390 return;
paul88d6cf32005-10-29 12:50:09 +0000391}
392
393/* Final cleanup of ospf instance */
394static void
395ospf_finish_final (struct ospf *ospf)
396{
paul718e3742002-12-13 20:15:29 +0000397 struct route_node *rn;
398 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000399 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000400 struct ospf_interface *oi;
401 struct ospf_area *area;
402 struct ospf_vl_data *vl_data;
403 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000404 int i;
405
406#ifdef HAVE_OPAQUE_LSA
407 ospf_opaque_type11_lsa_term (ospf);
408#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000409
410 /* be nice if this worked, but it doesn't */
411 /*ospf_flush_self_originated_lsas_now (ospf);*/
412
413 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000414 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000415 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000416 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000417
paul1eb8ef22005-04-07 07:30:20 +0000418 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
419 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000420
paul1eb8ef22005-04-07 07:30:20 +0000421 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
422 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000423
424 list_delete (ospf->vlinks);
425
426 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
428 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000429
430 /* Clear static neighbors */
431 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
432 if ((nbr_nbma = rn->info))
433 {
434 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
435
436 if (nbr_nbma->nbr)
437 {
438 nbr_nbma->nbr->nbr_nbma = NULL;
439 nbr_nbma->nbr = NULL;
440 }
441
442 if (nbr_nbma->oi)
443 {
444 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
445 nbr_nbma->oi = NULL;
446 }
447
448 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
449 }
450
451 route_table_finish (ospf->nbr_nbma);
452
453 /* Clear networks and Areas. */
454 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
455 {
456 struct ospf_network *network;
457
458 if ((network = rn->info) != NULL)
459 {
paul68980082003-03-25 05:07:42 +0000460 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000461 rn->info = NULL;
462 route_unlock_node (rn);
463 }
464 }
465
paul1eb8ef22005-04-07 07:30:20 +0000466 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000467 {
paul718e3742002-12-13 20:15:29 +0000468 listnode_delete (ospf->areas, area);
469 ospf_area_free (area);
470 }
471
472 /* Cancel all timers. */
473 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000474 OSPF_TIMER_OFF (ospf->t_router_lsa_update);
475 OSPF_TIMER_OFF (ospf->t_spf_calc);
476 OSPF_TIMER_OFF (ospf->t_ase_calc);
477 OSPF_TIMER_OFF (ospf->t_maxage);
478 OSPF_TIMER_OFF (ospf->t_maxage_walker);
479 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000480 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000481 OSPF_TIMER_OFF (ospf->t_distribute_update);
482 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
483 OSPF_TIMER_OFF (ospf->t_read);
484 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000485#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000486 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000487#endif
paul718e3742002-12-13 20:15:29 +0000488
489 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000490 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000491
492#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000493 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
494 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000495#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000496 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
497 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
498
paul718e3742002-12-13 20:15:29 +0000499 ospf_lsdb_delete_all (ospf->lsdb);
500 ospf_lsdb_free (ospf->lsdb);
501
paul1eb8ef22005-04-07 07:30:20 +0000502 for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000503 ospf_lsa_unlock (&lsa); /* maxage_lsa */
paul718e3742002-12-13 20:15:29 +0000504
505 list_delete (ospf->maxage_lsa);
506
507 if (ospf->old_table)
508 ospf_route_table_free (ospf->old_table);
509 if (ospf->new_table)
510 {
511 ospf_route_delete (ospf->new_table);
512 ospf_route_table_free (ospf->new_table);
513 }
514 if (ospf->old_rtrs)
515 ospf_rtrs_free (ospf->old_rtrs);
516 if (ospf->new_rtrs)
517 ospf_rtrs_free (ospf->new_rtrs);
518 if (ospf->new_external_route)
519 {
520 ospf_route_delete (ospf->new_external_route);
521 ospf_route_table_free (ospf->new_external_route);
522 }
523 if (ospf->old_external_route)
524 {
525 ospf_route_delete (ospf->old_external_route);
526 ospf_route_table_free (ospf->old_external_route);
527 }
528 if (ospf->external_lsas)
529 {
530 ospf_ase_external_lsas_finish (ospf->external_lsas);
531 }
532
533 list_delete (ospf->areas);
534
535 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
536 if (EXTERNAL_INFO (i) != NULL)
537 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
538 {
539 if (rn->info == NULL)
540 continue;
541
542 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
543 rn->info = NULL;
544 route_unlock_node (rn);
545 }
546
paul68980082003-03-25 05:07:42 +0000547 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000548 route_table_finish (ospf->distance_table);
549
paul020709f2003-04-04 02:44:16 +0000550 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000551
paul020709f2003-04-04 02:44:16 +0000552 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000553}
554
555
556/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000557static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000558ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000559{
560 struct ospf_area *new;
561
562 /* Allocate new config_network. */
563 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
564
paul68980082003-03-25 05:07:42 +0000565 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000566
567 new->area_id = area_id;
568
569 new->external_routing = OSPF_AREA_DEFAULT;
570 new->default_cost = 1;
571 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000572
paul718e3742002-12-13 20:15:29 +0000573 /* New LSDB init. */
574 new->lsdb = ospf_lsdb_new ();
575
576 /* Self-originated LSAs initialize. */
577 new->router_lsa_self = NULL;
578
579#ifdef HAVE_OPAQUE_LSA
580 ospf_opaque_type10_lsa_init (new);
581#endif /* HAVE_OPAQUE_LSA */
582
583 new->oiflist = list_new ();
584 new->ranges = route_table_init ();
585
586 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000587 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000588
589 return new;
590}
591
592void
593ospf_area_free (struct ospf_area *area)
594{
paul68980082003-03-25 05:07:42 +0000595 struct route_node *rn;
596 struct ospf_lsa *lsa;
597
paul718e3742002-12-13 20:15:29 +0000598 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000599 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
600 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
601 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
602 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
603 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
604 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
605 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
606 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000607
paul68980082003-03-25 05:07:42 +0000608 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
609 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000610#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000611 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
612 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
613 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
614 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000615#endif /* HAVE_OPAQUE_LSA */
616
617 ospf_lsdb_delete_all (area->lsdb);
618 ospf_lsdb_free (area->lsdb);
619
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000620 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000621
622 route_table_finish (area->ranges);
623 list_delete (area->oiflist);
624
625 if (EXPORT_NAME (area))
626 free (EXPORT_NAME (area));
627
628 if (IMPORT_NAME (area))
629 free (IMPORT_NAME (area));
630
631 /* Cancel timer. */
632 OSPF_TIMER_OFF (area->t_router_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000633 OSPF_TIMER_OFF (area->t_stub_router);
634#ifdef HAVE_OPAQUE_LSA
635 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
636#endif /* HAVE_OPAQUE_LSA */
637
paul718e3742002-12-13 20:15:29 +0000638 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000639 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000640
641 XFREE (MTYPE_OSPF_AREA, area);
642}
643
644void
paul68980082003-03-25 05:07:42 +0000645ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000646{
647 struct ospf_area *area;
648
paul68980082003-03-25 05:07:42 +0000649 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000650 if (area &&
651 listcount (area->oiflist) == 0 &&
652 area->ranges->top == NULL &&
653 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
654 area->external_routing == OSPF_AREA_DEFAULT &&
655 area->no_summary == 0 &&
656 area->default_cost == 1 &&
657 EXPORT_NAME (area) == NULL &&
658 IMPORT_NAME (area) == NULL &&
659 area->auth_type == OSPF_AUTH_NULL)
660 {
paul68980082003-03-25 05:07:42 +0000661 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000662 ospf_area_free (area);
663 }
664}
665
666struct ospf_area *
paul68980082003-03-25 05:07:42 +0000667ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000668{
669 struct ospf_area *area;
670
paul68980082003-03-25 05:07:42 +0000671 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000672 if (!area)
673 {
paul68980082003-03-25 05:07:42 +0000674 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000675 area->format = format;
paul68980082003-03-25 05:07:42 +0000676 listnode_add_sort (ospf->areas, area);
677 ospf_check_abr_status (ospf);
paul718e3742002-12-13 20:15:29 +0000678 }
679
680 return area;
681}
682
683struct ospf_area *
paul68980082003-03-25 05:07:42 +0000684ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000685{
686 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000687 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000688
paul1eb8ef22005-04-07 07:30:20 +0000689 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
690 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
691 return area;
paul718e3742002-12-13 20:15:29 +0000692
693 return NULL;
694}
695
696void
697ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
698{
699 listnode_add (area->oiflist, oi);
700}
701
702void
703ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
704{
705 listnode_delete (area->oiflist, oi);
706}
707
708
709/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000710static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000711ospf_network_new (struct in_addr area_id, int format)
712{
713 struct ospf_network *new;
714 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
715
716 new->area_id = area_id;
717 new->format = format;
718
719 return new;
720}
721
722void
paul68980082003-03-25 05:07:42 +0000723ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000724{
paul68980082003-03-25 05:07:42 +0000725 ospf_area_check_free (ospf, network->area_id);
726 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000727 XFREE (MTYPE_OSPF_NETWORK, network);
728}
729
730int
731ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
732 struct in_addr area_id)
733{
734 struct ospf_network *network;
735 struct ospf_area *area;
736 struct route_node *rn;
737 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000738 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000739
740 rn = route_node_get (ospf->networks, (struct prefix *)p);
741 if (rn->info)
742 {
743 /* There is already same network statement. */
744 route_unlock_node (rn);
745 return 0;
746 }
747
748 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000749 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000750
751 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100752 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000753
754 /* Update connected redistribute. */
755 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
756 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
757 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
758 rn; rn = route_next (rn))
759 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000760 if (ospf_external_info_find_lsa (ospf, &ei->p))
761 if (!ospf_distribute_check_connected (ospf, ei))
762 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000763 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000764
paul68980082003-03-25 05:07:42 +0000765 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000766
767 return 1;
768}
769
770int
771ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
772 struct in_addr area_id)
773{
774 struct route_node *rn;
775 struct ospf_network *network;
776 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100777 struct listnode *node, *nnode;
778 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000779
780 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
781 if (rn == NULL)
782 return 0;
783
784 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700785 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000786 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
787 return 0;
788
paul68980082003-03-25 05:07:42 +0000789 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000790 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700791 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000792
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100793 /* Find interfaces that not configured already. */
794 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
795 {
796 int found = 0;
797 struct connected *co = oi->connected;
798
799 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
800 continue;
801
802 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
803 {
804 if (rn->info == NULL)
805 continue;
806
807 if (ospf_network_match_iface(co,&rn->p))
808 {
809 found = 1;
810 route_unlock_node (rn);
811 break;
812 }
813 }
814
815 if (found == 0)
816 ospf_if_free (oi);
817 }
paul718e3742002-12-13 20:15:29 +0000818
819 /* Update connected redistribute. */
820 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
821 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
822 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
823 rn; rn = route_next (rn))
824 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000825 if (!ospf_external_info_find_lsa (ospf, &ei->p))
826 if (ospf_distribute_check_connected (ospf, ei))
827 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000828
829 return 1;
830}
831
paul570f7592003-01-25 06:47:41 +0000832/* Check whether interface matches given network
833 * returns: 1, true. 0, false
834 */
835int
836ospf_network_match_iface(struct connected *co, struct prefix *net)
837{
Andrew J. Schorrf0ec8322007-04-30 16:52:05 +0000838/* #define COMPATIBILITY_MODE */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000839 /* The old code used to have a special case for PtP interfaces:
840
841 if (if_is_pointopoint (co->ifp) && co->destination &&
842 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
843 return 1;
844
845 The new approach is much more general. If a peer address is supplied,
846 then we are routing to that prefix, so that's the address to compare
847 against (not the local address, which may not be unique).
848 */
849#ifndef COMPATIBILITY_MODE
850 /* new approach: more elegant and conceptually clean */
851 return prefix_match(net, CONNECTED_PREFIX(co));
852#else /* COMPATIBILITY_MODE */
853 /* match old (strange?) behavior */
854
paul570f7592003-01-25 06:47:41 +0000855 /* Behaviour to match both Cisco where:
856 * iface address lies within network specified -> ospf
857 * and zebra 0.9[2ish-3]:
858 * PtP special case: network specified == iface peer addr -> ospf
859 */
gdt8f40e892003-12-05 14:01:43 +0000860
paulf3ae74c2004-11-04 20:35:31 +0000861 /* For PtP, match if peer address matches network address exactly.
862 * This can be addr/32 or addr/p for p < 32, but the addr must match
863 * exactly; this is not a test for falling within the prefix. This
gdt8f40e892003-12-05 14:01:43 +0000864 * test is solely for compatibility with zebra.
gdt8f40e892003-12-05 14:01:43 +0000865 */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000866 if (CONNECTED_PEER(co) &&
paulf3ae74c2004-11-04 20:35:31 +0000867 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
868 return 1;
869
870#if 0
871 /* Decline to accept PtP if dst address does not match the
872 * prefix. (ifdefed out because this is a workaround, not the
873 * desired behavior.) */
874 if (if_is_pointopoint (co->ifp) &&
875 ! prefix_match (net, co->destination))
876 return 0;
877#endif
878
879 /* If the address is within the prefix, accept. Note that this
880 * applies to PtP as well as other types.
881 */
882 if (prefix_match (net, co->address))
883 return 1;
884
885 return 0; /* no match */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000886
887#endif /* COMPATIBILITY_MODE */
paul570f7592003-01-25 06:47:41 +0000888}
889
paul718e3742002-12-13 20:15:29 +0000890void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100891ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
892 struct interface *ifp)
893{
894 struct listnode *cnode;
895 struct connected *co;
896
897 if (memcmp (ifp->name, "VLINK", 5) == 0)
898 return;
899
900 /* if interface prefix is match specified prefix,
901 then create socket and join multicast group. */
902 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
903 {
904 struct prefix *addr;
905
906 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
907 continue;
908
909 addr = CONNECTED_ID(co);
910
911 if (p->family == co->address->family
912 && ! ospf_if_is_configured (area->ospf, &(addr->u.prefix4))
913 && ospf_network_match_iface(co,p))
914 {
915 struct ospf_interface *oi;
916
917 oi = ospf_if_new (area->ospf, ifp, co->address);
918 oi->connected = co;
919
920 oi->area = area;
921
922 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
923 oi->output_cost = ospf_if_get_output_cost (oi);
924
925 /* Add pseudo neighbor. */
926 ospf_nbr_add_self (oi);
927
928 /* Relate ospf interface to ospf instance. */
929 oi->ospf = area->ospf;
930
931 /* update network type as interface flag */
932 /* If network type is specified previously,
933 skip network type setting. */
934 oi->type = IF_DEF_PARAMS (ifp)->type;
935
936 ospf_area_add_if (oi->area, oi);
937
938 /* if router_id is not configured, dont bring up
939 * interfaces.
940 * ospf_router_id_update() will call ospf_if_update
941 * whenever r-id is configured instead.
942 */
943 if ((area->ospf->router_id.s_addr != 0)
944 && if_is_operative (ifp))
945 ospf_if_up (oi);
946 }
947 }
948}
949
950void
951ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000952{
953 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000954 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000955
956 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100957 if (area->ospf->router_id.s_addr == 0)
958 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000959
paul718e3742002-12-13 20:15:29 +0000960 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000961 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100962 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000963}
964
965void
966ospf_ls_upd_queue_empty (struct ospf_interface *oi)
967{
968 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000969 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000970 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000971 struct ospf_lsa *lsa;
972
973 /* empty ls update queue */
974 for (rn = route_top (oi->ls_upd_queue); rn;
975 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000976 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000977 {
paul1eb8ef22005-04-07 07:30:20 +0000978 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000979 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000980 list_free (lst);
981 rn->info = NULL;
982 }
983
984 /* remove update event */
985 if (oi->t_ls_upd_event)
986 {
987 thread_cancel (oi->t_ls_upd_event);
988 oi->t_ls_upd_event = NULL;
989 }
990}
991
992void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100993ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000994{
995 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000996 struct ospf_network *network;
997 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100998
999 if (!ospf)
1000 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001001
Joakim Tjernlund6e687d72008-09-24 17:15:48 +01001002 /* OSPF must be on and Router-ID must be configured. */
1003 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001004 return;
1005
1006 /* Run each netowrk for this interface. */
1007 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1008 if (rn->info != NULL)
1009 {
1010 network = (struct ospf_network *) rn->info;
1011 area = ospf_area_get (ospf, network->area_id, network->format);
1012 ospf_network_run_interface (&rn->p, area, ifp);
1013 }
paul718e3742002-12-13 20:15:29 +00001014}
1015
1016void
paul68980082003-03-25 05:07:42 +00001017ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001018{
paul1eb8ef22005-04-07 07:30:20 +00001019 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001020 struct ospf_vl_data *vl_data;
1021
paul1eb8ef22005-04-07 07:30:20 +00001022 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1023 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1024 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001025}
1026
1027
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001028static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001029{
1030 { OSPF_AREA_DEFAULT, "Default" },
1031 { OSPF_AREA_STUB, "Stub" },
1032 { OSPF_AREA_NSSA, "NSSA" },
1033};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001034static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001035
paul4dadc292005-05-06 21:37:42 +00001036static void
paul718e3742002-12-13 20:15:29 +00001037ospf_area_type_set (struct ospf_area *area, int type)
1038{
hasso52dc7ee2004-09-23 19:18:23 +00001039 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001040 struct ospf_interface *oi;
1041
1042 if (area->external_routing == type)
1043 {
1044 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001045 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001046 inet_ntoa (area->area_id));
1047 return;
1048 }
1049
1050 area->external_routing = type;
1051
1052 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001053 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001054 LOOKUP (ospf_area_type_msg, type));
1055
1056 switch (area->external_routing)
1057 {
1058 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001059 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1060 if (oi->nbr_self != NULL)
1061 {
1062 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1063 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1064 }
paul718e3742002-12-13 20:15:29 +00001065 break;
1066 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001067 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1068 if (oi->nbr_self != NULL)
1069 {
1070 if (IS_DEBUG_OSPF_EVENT)
1071 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1072 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1073 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1074 if (IS_DEBUG_OSPF_EVENT)
1075 zlog_debug ("options set on %s: %x",
1076 IF_NAME (oi), OPTIONS (oi));
1077 }
paul718e3742002-12-13 20:15:29 +00001078 break;
1079 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001080 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1081 if (oi->nbr_self != NULL)
1082 {
1083 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1084 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1085 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1086 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1087 }
paul718e3742002-12-13 20:15:29 +00001088 break;
1089 default:
1090 break;
1091 }
1092
1093 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001094 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001095}
1096
1097int
paul68980082003-03-25 05:07:42 +00001098ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001099{
1100 if (area->shortcut_configured == mode)
1101 return 0;
1102
1103 area->shortcut_configured = mode;
1104 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001105 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001106
paul68980082003-03-25 05:07:42 +00001107 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001108
1109 return 1;
1110}
1111
1112int
paul68980082003-03-25 05:07:42 +00001113ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001114{
1115 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1116 ospf_router_lsa_timer_add (area);
paul68980082003-03-25 05:07:42 +00001117 ospf_area_check_free (ospf, area->area_id);
1118 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001119
1120 return 1;
1121}
1122
paul4dadc292005-05-06 21:37:42 +00001123static int
paul718e3742002-12-13 20:15:29 +00001124ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1125{
1126 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001127 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001128 int count = 0;
1129
paul1eb8ef22005-04-07 07:30:20 +00001130 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1131 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1132 count++;
paul718e3742002-12-13 20:15:29 +00001133
1134 return count;
1135}
1136
1137int
1138ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1139{
1140 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001141 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001142
paul68980082003-03-25 05:07:42 +00001143 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001144 if (ospf_area_vlink_count (ospf, area))
1145 return 0;
1146
1147 if (area->external_routing != OSPF_AREA_STUB)
1148 ospf_area_type_set (area, OSPF_AREA_STUB);
1149
1150 return 1;
1151}
1152
1153int
1154ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1155{
1156 struct ospf_area *area;
1157
paul68980082003-03-25 05:07:42 +00001158 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001159 if (area == NULL)
1160 return 1;
1161
1162 if (area->external_routing == OSPF_AREA_STUB)
1163 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1164
paul68980082003-03-25 05:07:42 +00001165 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001166
1167 return 1;
1168}
1169
1170int
1171ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1172{
1173 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001174 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001175
paul68980082003-03-25 05:07:42 +00001176 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001177 area->no_summary = 1;
1178
1179 return 1;
1180}
1181
1182int
1183ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1184{
1185 struct ospf_area *area;
1186
paul68980082003-03-25 05:07:42 +00001187 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001188 if (area == NULL)
1189 return 0;
1190
1191 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001192 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001193
1194 return 1;
1195}
1196
1197int
1198ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1199{
1200 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001201 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001202
paul68980082003-03-25 05:07:42 +00001203 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001204 if (ospf_area_vlink_count (ospf, area))
1205 return 0;
1206
1207 if (area->external_routing != OSPF_AREA_NSSA)
1208 {
1209 ospf_area_type_set (area, OSPF_AREA_NSSA);
1210 ospf->anyNSSA++;
1211 }
1212
paul084c7842003-06-22 08:35:18 +00001213 /* set NSSA area defaults */
1214 area->no_summary = 0;
1215 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001216 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001217 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1218
paul718e3742002-12-13 20:15:29 +00001219 return 1;
1220}
1221
1222int
1223ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1224{
1225 struct ospf_area *area;
1226
paul68980082003-03-25 05:07:42 +00001227 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001228 if (area == NULL)
1229 return 0;
1230
1231 if (area->external_routing == OSPF_AREA_NSSA)
1232 {
1233 ospf->anyNSSA--;
1234 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1235 }
1236
paul68980082003-03-25 05:07:42 +00001237 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001238
1239 return 1;
1240}
1241
1242int
1243ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1244 int role)
1245{
1246 struct ospf_area *area;
1247
paul68980082003-03-25 05:07:42 +00001248 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001249 if (area == NULL)
1250 return 0;
1251
paul084c7842003-06-22 08:35:18 +00001252 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001253
1254 return 1;
1255}
1256
paul4dadc292005-05-06 21:37:42 +00001257/* XXX: unused? Leave for symmetry? */
1258static int
paul718e3742002-12-13 20:15:29 +00001259ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1260 struct in_addr area_id)
1261{
1262 struct ospf_area *area;
1263
paul68980082003-03-25 05:07:42 +00001264 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001265 if (area == NULL)
1266 return 0;
1267
paul084c7842003-06-22 08:35:18 +00001268 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001269
paul68980082003-03-25 05:07:42 +00001270 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001271
1272 return 1;
1273}
1274
1275int
paul68980082003-03-25 05:07:42 +00001276ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001277 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001278{
1279 struct access_list *list;
1280 list = access_list_lookup (AFI_IP, list_name);
1281
1282 EXPORT_LIST (area) = list;
1283
1284 if (EXPORT_NAME (area))
1285 free (EXPORT_NAME (area));
1286
1287 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001288 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001289
1290 return 1;
1291}
1292
1293int
paul68980082003-03-25 05:07:42 +00001294ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001295{
1296
1297 EXPORT_LIST (area) = 0;
1298
1299 if (EXPORT_NAME (area))
1300 free (EXPORT_NAME (area));
1301
1302 EXPORT_NAME (area) = NULL;
1303
paul68980082003-03-25 05:07:42 +00001304 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001305
paul68980082003-03-25 05:07:42 +00001306 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001307
1308 return 1;
1309}
1310
1311int
paul6c835672004-10-11 11:00:30 +00001312ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1313 const char *name)
paul718e3742002-12-13 20:15:29 +00001314{
1315 struct access_list *list;
1316 list = access_list_lookup (AFI_IP, name);
1317
1318 IMPORT_LIST (area) = list;
1319
1320 if (IMPORT_NAME (area))
1321 free (IMPORT_NAME (area));
1322
1323 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001324 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001325
1326 return 1;
1327}
1328
1329int
paul68980082003-03-25 05:07:42 +00001330ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001331{
1332 IMPORT_LIST (area) = 0;
1333
1334 if (IMPORT_NAME (area))
1335 free (IMPORT_NAME (area));
1336
1337 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001338 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001339
paul68980082003-03-25 05:07:42 +00001340 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001341
1342 return 1;
1343}
1344
1345int
paul718e3742002-12-13 20:15:29 +00001346ospf_timers_refresh_set (struct ospf *ospf, int interval)
1347{
1348 int time_left;
1349
1350 if (ospf->lsa_refresh_interval == interval)
1351 return 1;
1352
1353 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001354 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001355
1356 if (time_left > interval)
1357 {
1358 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1359 ospf->t_lsa_refresher =
1360 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1361 }
1362 ospf->lsa_refresh_interval = interval;
1363
1364 return 1;
1365}
1366
1367int
1368ospf_timers_refresh_unset (struct ospf *ospf)
1369{
1370 int time_left;
1371
1372 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001373 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001374
1375 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1376 {
1377 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1378 ospf->t_lsa_refresher =
1379 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1380 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1381 }
1382
1383 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1384
1385 return 1;
1386}
1387
1388
paul4dadc292005-05-06 21:37:42 +00001389static struct ospf_nbr_nbma *
1390ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001391{
1392 struct ospf_nbr_nbma *nbr_nbma;
1393
Stephen Hemminger393deb92008-08-18 14:13:29 -07001394 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001395 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001396
1397 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1398 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1399
1400 return nbr_nbma;
1401}
1402
paul4dadc292005-05-06 21:37:42 +00001403static void
paul718e3742002-12-13 20:15:29 +00001404ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1405{
1406 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1407}
1408
paul4dadc292005-05-06 21:37:42 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1411{
1412 struct route_node *rn;
1413 struct prefix_ipv4 p;
1414
1415 p.family = AF_INET;
1416 p.prefix = nbr_nbma->addr;
1417 p.prefixlen = IPV4_MAX_BITLEN;
1418
1419 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1420 if (rn)
1421 {
1422 ospf_nbr_nbma_free (rn->info);
1423 rn->info = NULL;
1424 route_unlock_node (rn);
1425 route_unlock_node (rn);
1426 }
1427}
1428
paul4dadc292005-05-06 21:37:42 +00001429static void
paul718e3742002-12-13 20:15:29 +00001430ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1431{
1432 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1433
1434 if (nbr_nbma->nbr)
1435 {
1436 nbr_nbma->nbr->nbr_nbma = NULL;
1437 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1438 }
1439
1440 if (nbr_nbma->oi)
1441 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1442}
1443
paul4dadc292005-05-06 21:37:42 +00001444static void
paul718e3742002-12-13 20:15:29 +00001445ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1446 struct ospf_interface *oi)
1447{
1448 struct ospf_neighbor *nbr;
1449 struct route_node *rn;
1450 struct prefix p;
1451
1452 if (oi->type != OSPF_IFTYPE_NBMA)
1453 return;
1454
1455 if (nbr_nbma->nbr != NULL)
1456 return;
1457
1458 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1459 return;
1460
1461 nbr_nbma->oi = oi;
1462 listnode_add (oi->nbr_nbma, nbr_nbma);
1463
1464 /* Get neighbor information from table. */
1465 p.family = AF_INET;
1466 p.prefixlen = IPV4_MAX_BITLEN;
1467 p.u.prefix4 = nbr_nbma->addr;
1468
1469 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1470 if (rn->info)
1471 {
1472 nbr = rn->info;
1473 nbr->nbr_nbma = nbr_nbma;
1474 nbr_nbma->nbr = nbr;
1475
1476 route_unlock_node (rn);
1477 }
1478 else
1479 {
1480 nbr = rn->info = ospf_nbr_new (oi);
1481 nbr->state = NSM_Down;
1482 nbr->src = nbr_nbma->addr;
1483 nbr->nbr_nbma = nbr_nbma;
1484 nbr->priority = nbr_nbma->priority;
1485 nbr->address = p;
1486
1487 nbr_nbma->nbr = nbr;
1488
1489 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1490 }
1491}
1492
1493void
paul68980082003-03-25 05:07:42 +00001494ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001495{
1496 struct ospf_nbr_nbma *nbr_nbma;
1497 struct route_node *rn;
1498 struct prefix_ipv4 p;
1499
1500 if (oi->type != OSPF_IFTYPE_NBMA)
1501 return;
1502
paul68980082003-03-25 05:07:42 +00001503 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001504 if ((nbr_nbma = rn->info))
1505 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1506 {
1507 p.family = AF_INET;
1508 p.prefix = nbr_nbma->addr;
1509 p.prefixlen = IPV4_MAX_BITLEN;
1510
1511 if (prefix_match (oi->address, (struct prefix *)&p))
1512 ospf_nbr_nbma_add (nbr_nbma, oi);
1513 }
1514}
1515
1516struct ospf_nbr_nbma *
1517ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1518{
1519 struct route_node *rn;
1520 struct prefix_ipv4 p;
1521
1522 p.family = AF_INET;
1523 p.prefix = nbr_addr;
1524 p.prefixlen = IPV4_MAX_BITLEN;
1525
1526 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1527 if (rn)
1528 {
1529 route_unlock_node (rn);
1530 return rn->info;
1531 }
1532 return NULL;
1533}
1534
1535struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001536ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001537{
1538#if 0
1539 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001540 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001541#endif
1542
paul68980082003-03-25 05:07:42 +00001543 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001544 return NULL;
1545
1546#if 0
paul1eb8ef22005-04-07 07:30:20 +00001547 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001548 {
paul718e3742002-12-13 20:15:29 +00001549 if (first)
1550 {
1551 *addr = nbr_nbma->addr;
1552 return nbr_nbma;
1553 }
1554 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1555 {
1556 *addr = nbr_nbma->addr;
1557 return nbr_nbma;
1558 }
1559 }
1560#endif
1561 return NULL;
1562}
1563
1564int
1565ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1566{
1567 struct ospf_nbr_nbma *nbr_nbma;
1568 struct ospf_interface *oi;
1569 struct prefix_ipv4 p;
1570 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001571 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001572
1573 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1574 if (nbr_nbma)
1575 return 0;
1576
1577 nbr_nbma = ospf_nbr_nbma_new ();
1578 nbr_nbma->addr = nbr_addr;
1579
1580 p.family = AF_INET;
1581 p.prefix = nbr_addr;
1582 p.prefixlen = IPV4_MAX_BITLEN;
1583
1584 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1585 rn->info = nbr_nbma;
1586
paul1eb8ef22005-04-07 07:30:20 +00001587 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001588 {
paul718e3742002-12-13 20:15:29 +00001589 if (oi->type == OSPF_IFTYPE_NBMA)
1590 if (prefix_match (oi->address, (struct prefix *)&p))
1591 {
1592 ospf_nbr_nbma_add (nbr_nbma, oi);
1593 break;
1594 }
1595 }
1596
1597 return 1;
1598}
1599
1600int
1601ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1602{
1603 struct ospf_nbr_nbma *nbr_nbma;
1604
1605 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1606 if (nbr_nbma == NULL)
1607 return 0;
1608
1609 ospf_nbr_nbma_down (nbr_nbma);
1610 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1611
1612 return 1;
1613}
1614
1615int
1616ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1617 u_char priority)
1618{
1619 struct ospf_nbr_nbma *nbr_nbma;
1620
1621 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1622 if (nbr_nbma == NULL)
1623 return 0;
1624
1625 if (nbr_nbma->priority != priority)
1626 nbr_nbma->priority = priority;
1627
1628 return 1;
1629}
1630
1631int
1632ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1633{
1634 struct ospf_nbr_nbma *nbr_nbma;
1635
1636 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1637 if (nbr_nbma == NULL)
1638 return 0;
1639
1640 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1641 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1642
1643 return 1;
1644}
1645
1646int
1647ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001648 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001649{
1650 struct ospf_nbr_nbma *nbr_nbma;
1651
1652 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1653 if (nbr_nbma == NULL)
1654 return 0;
1655
1656 if (nbr_nbma->v_poll != interval)
1657 {
1658 nbr_nbma->v_poll = interval;
1659 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1660 {
1661 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1662 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1663 nbr_nbma->v_poll);
1664 }
1665 }
1666
1667 return 1;
1668}
1669
1670int
1671ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1672{
1673 struct ospf_nbr_nbma *nbr_nbma;
1674
1675 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1676 if (nbr_nbma == NULL)
1677 return 0;
1678
1679 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1680 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1681
1682 return 1;
1683}
1684
paul718e3742002-12-13 20:15:29 +00001685void
paul020709f2003-04-04 02:44:16 +00001686ospf_master_init ()
1687{
1688 memset (&ospf_master, 0, sizeof (struct ospf_master));
1689
1690 om = &ospf_master;
1691 om->ospf = list_new ();
1692 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001693 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001694}