blob: d1de29d5eaf5bf7f81cf8609cac947b7b1cc37e4 [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 *);
Stephen Hemminger917e2992009-12-03 19:07:00 +030074static int ospf_network_match_iface (const struct connected *,
75 const struct prefix *);
paul88d6cf32005-10-29 12:50:09 +000076static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000077
paul718e3742002-12-13 20:15:29 +000078#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
paul88d6cf32005-10-29 12:50:09 +000079
paul718e3742002-12-13 20:15:29 +000080void
paul68980082003-03-25 05:07:42 +000081ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000082{
paul718e3742002-12-13 20:15:29 +000083 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000084 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010085 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000087
88 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000089 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000090
paul68980082003-03-25 05:07:42 +000091 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000092
Andrew J. Schorr16700082006-07-27 22:29:06 +000093 /* Select the router ID based on these priorities:
94 1. Statically assigned router ID is always the first choice.
95 2. If there is no statically assigned router ID, then try to stick
96 with the most recent value, since changing router ID's is very
97 disruptive.
98 3. Last choice: just go with whatever the zebra daemon recommends.
99 */
paul68980082003-03-25 05:07:42 +0000100 if (ospf->router_id_static.s_addr != 0)
101 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000102 else if (ospf->router_id.s_addr != 0)
103 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000104 else
hasso18a6dce2004-10-03 18:18:34 +0000105 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000106
paul68980082003-03-25 05:07:42 +0000107 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000108
109 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000110 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000111
112 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
113 {
paul1eb8ef22005-04-07 07:30:20 +0000114 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
115 /* Update self-neighbor's router_id. */
116 oi->nbr_self->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000117
118 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000119 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000120 {
121 int type;
122 /* Originate each redistributed external route. */
123 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000124 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000125 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000126 ospf, type);
paul718e3742002-12-13 20:15:29 +0000127 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000128 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000129 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000130
paul68980082003-03-25 05:07:42 +0000131 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000132 }
133
Paul Jakmac363d382010-01-24 22:42:13 +0000134 /* update router-lsa's for each area */
135 ospf_router_lsa_update (ospf);
paulb29800a2005-11-20 14:50:45 +0000136
137 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100138 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
139 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000140 }
141}
paul718e3742002-12-13 20:15:29 +0000142
143/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000144static int
paul718e3742002-12-13 20:15:29 +0000145ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
146{
147 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
148 return 1;
149 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
150 return -1;
151 return 0;
152}
153
154/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000155static struct ospf *
156ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000157{
158 int i;
159
160 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
161
162 new->router_id.s_addr = htonl (0);
163 new->router_id_static.s_addr = htonl (0);
164
pauld57834f2005-07-12 20:04:22 +0000165 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000166 new->oiflist = list_new ();
167 new->vlinks = list_new ();
168 new->areas = list_new ();
169 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
170 new->networks = route_table_init ();
171 new->nbr_nbma = route_table_init ();
172
173 new->lsdb = ospf_lsdb_new ();
174
175 new->default_originate = DEFAULT_ORIGINATE_NONE;
176
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000177 new->passive_interface_default = OSPF_IF_ACTIVE;
178
paul718e3742002-12-13 20:15:29 +0000179 new->new_external_route = route_table_init ();
180 new->old_external_route = route_table_init ();
181 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000182
183 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000184 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800185 new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET;
186
paul718e3742002-12-13 20:15:29 +0000187 /* Distribute parameter init. */
188 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
189 {
190 new->dmetric[i].type = -1;
191 new->dmetric[i].value = -1;
192 }
193 new->default_metric = -1;
194 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
195
196 /* SPF timer value init. */
197 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
198 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000199 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
200 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000201
202 /* MaxAge init. */
Paul Jakma02d942c2010-01-24 23:36:20 +0000203 new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800204 new->maxage_lsa = route_table_init();
paul718e3742002-12-13 20:15:29 +0000205 new->t_maxage_walker =
206 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000207 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000208
209 /* Distance table init. */
210 new->distance_table = route_table_init ();
211
212 new->lsa_refresh_queue.index = 0;
213 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
214 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
215 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000216 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000217
ajs5c333492005-02-23 15:43:01 +0000218 if ((new->fd = ospf_sock_init()) < 0)
219 {
220 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
221 "a socket");
222 exit(1);
223 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000224 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
225 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
226 zlog_debug ("%s: starting with OSPF send buffer size %d",
227 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000228 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
229 {
230 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
231 OSPF_MAX_PACKET_SIZE+1);
232 exit(1);
233 }
234 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000235 new->oi_write_q = list_new ();
236
237 return new;
238}
239
240struct ospf *
paul020709f2003-04-04 02:44:16 +0000241ospf_lookup ()
242{
243 if (listcount (om->ospf) == 0)
244 return NULL;
245
paul1eb8ef22005-04-07 07:30:20 +0000246 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000247}
248
paul4dadc292005-05-06 21:37:42 +0000249static void
paul020709f2003-04-04 02:44:16 +0000250ospf_add (struct ospf *ospf)
251{
252 listnode_add (om->ospf, ospf);
253}
254
paul4dadc292005-05-06 21:37:42 +0000255static void
paul020709f2003-04-04 02:44:16 +0000256ospf_delete (struct ospf *ospf)
257{
258 listnode_delete (om->ospf, ospf);
259}
260
261struct ospf *
paul718e3742002-12-13 20:15:29 +0000262ospf_get ()
263{
paul020709f2003-04-04 02:44:16 +0000264 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000265
paul020709f2003-04-04 02:44:16 +0000266 ospf = ospf_lookup ();
267 if (ospf == NULL)
268 {
269 ospf = ospf_new ();
270 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000271
paul020709f2003-04-04 02:44:16 +0000272 if (ospf->router_id_static.s_addr == 0)
273 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000274
275#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000276 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000277#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000278 }
paul68980082003-03-25 05:07:42 +0000279
280 return ospf;
paul718e3742002-12-13 20:15:29 +0000281}
paul88d6cf32005-10-29 12:50:09 +0000282
paulc9c93d52005-11-26 13:31:11 +0000283/* Handle the second half of deferred shutdown. This is called either
284 * from the deferred-shutdown timer thread, or directly through
285 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000286 *
287 * Function is to cleanup G-R state, if required then call ospf_finish_final
288 * to complete shutdown of this ospf instance. Possibly exit if the
289 * whole process is being shutdown and this was the last OSPF instance.
290 */
291static void
paulc9c93d52005-11-26 13:31:11 +0000292ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000293{
294 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000295 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000296
297 ospf_finish_final (ospf);
298
299 /* *ospf is now invalid */
300
301 /* ospfd being shut-down? If so, was this the last ospf instance? */
302 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
303 && (listcount (om->ospf) == 0))
304 exit (0);
305
306 return;
307}
308
309/* Timer thread for G-R */
310static int
paulc9c93d52005-11-26 13:31:11 +0000311ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000312{
313 struct ospf *ospf = THREAD_ARG(t);
314
paulc9c93d52005-11-26 13:31:11 +0000315 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000316
317 return 0;
318}
319
paulc9c93d52005-11-26 13:31:11 +0000320/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000321 * down directly into second-half of instance shutdown.
322 */
323static void
paulc9c93d52005-11-26 13:31:11 +0000324ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000325{
326 unsigned long timeout;
327 struct listnode *ln;
328 struct ospf_area *area;
329
paulc9c93d52005-11-26 13:31:11 +0000330 /* deferred shutdown already running? */
331 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000332 return;
333
334 /* Should we try push out max-metric LSAs? */
335 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
336 {
337 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
338 {
339 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
340
341 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000342 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000343 }
344 timeout = ospf->stub_router_shutdown_time;
345 }
346 else
paulc9c93d52005-11-26 13:31:11 +0000347 {
348 /* No timer needed */
349 ospf_deferred_shutdown_finish (ospf);
350 return;
351 }
paul88d6cf32005-10-29 12:50:09 +0000352
paulc9c93d52005-11-26 13:31:11 +0000353 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000354 timeout);
355 return;
356}
357
358/* Shut down the entire process */
359void
360ospf_terminate (void)
361{
362 struct ospf *ospf;
363 struct listnode *node, *nnode;
364
365 /* shutdown already in progress */
366 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
367 return;
368
369 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
370
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000371 /* exit immediately if OSPF not actually running */
372 if (listcount(om->ospf) == 0)
373 exit(0);
374
paul88d6cf32005-10-29 12:50:09 +0000375 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
376 ospf_finish (ospf);
377
378 /* Deliberately go back up, hopefully to thread scheduler, as
379 * One or more ospf_finish()'s may have deferred shutdown to a timer
380 * thread
381 */
382}
paul718e3742002-12-13 20:15:29 +0000383
384void
385ospf_finish (struct ospf *ospf)
386{
paulc9c93d52005-11-26 13:31:11 +0000387 /* let deferred shutdown decide */
388 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000389
paulc9c93d52005-11-26 13:31:11 +0000390 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000391 * deferred to expiry of G-S timer thread. Return back up, hopefully
392 * to thread scheduler.
393 */
paulc9c93d52005-11-26 13:31:11 +0000394 return;
paul88d6cf32005-10-29 12:50:09 +0000395}
396
397/* Final cleanup of ospf instance */
398static void
399ospf_finish_final (struct ospf *ospf)
400{
paul718e3742002-12-13 20:15:29 +0000401 struct route_node *rn;
402 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000403 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000404 struct ospf_interface *oi;
405 struct ospf_area *area;
406 struct ospf_vl_data *vl_data;
407 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000408 int i;
409
410#ifdef HAVE_OPAQUE_LSA
411 ospf_opaque_type11_lsa_term (ospf);
412#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000413
414 /* be nice if this worked, but it doesn't */
415 /*ospf_flush_self_originated_lsas_now (ospf);*/
416
417 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000418 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000419 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000420 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000421
paul1eb8ef22005-04-07 07:30:20 +0000422 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
423 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000424
paul1eb8ef22005-04-07 07:30:20 +0000425 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
426 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000427
428 list_delete (ospf->vlinks);
429
430 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000431 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
432 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000433
434 /* Clear static neighbors */
435 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
436 if ((nbr_nbma = rn->info))
437 {
438 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
439
440 if (nbr_nbma->nbr)
441 {
442 nbr_nbma->nbr->nbr_nbma = NULL;
443 nbr_nbma->nbr = NULL;
444 }
445
446 if (nbr_nbma->oi)
447 {
448 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
449 nbr_nbma->oi = NULL;
450 }
451
452 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
453 }
454
455 route_table_finish (ospf->nbr_nbma);
456
457 /* Clear networks and Areas. */
458 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
459 {
460 struct ospf_network *network;
461
462 if ((network = rn->info) != NULL)
463 {
paul68980082003-03-25 05:07:42 +0000464 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000465 rn->info = NULL;
466 route_unlock_node (rn);
467 }
468 }
469
paul1eb8ef22005-04-07 07:30:20 +0000470 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000471 {
paul718e3742002-12-13 20:15:29 +0000472 listnode_delete (ospf->areas, area);
473 ospf_area_free (area);
474 }
475
476 /* Cancel all timers. */
477 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000478 OSPF_TIMER_OFF (ospf->t_spf_calc);
479 OSPF_TIMER_OFF (ospf->t_ase_calc);
480 OSPF_TIMER_OFF (ospf->t_maxage);
481 OSPF_TIMER_OFF (ospf->t_maxage_walker);
482 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000483 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000484 OSPF_TIMER_OFF (ospf->t_distribute_update);
485 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
486 OSPF_TIMER_OFF (ospf->t_read);
487 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000488#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000489 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000490#endif
paul718e3742002-12-13 20:15:29 +0000491
492 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000493 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000494
495#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000496 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
497 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000498#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000499 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
500 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
501
paul718e3742002-12-13 20:15:29 +0000502 ospf_lsdb_delete_all (ospf->lsdb);
503 ospf_lsdb_free (ospf->lsdb);
504
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800505 for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn))
506 {
507 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000508
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800509 if ((lsa = rn->info) != NULL)
510 {
511 ospf_lsa_unlock (&lsa);
512 rn->info = NULL;
513 }
514 route_unlock_node (rn);
515 }
516 route_table_finish (ospf->maxage_lsa);
paul718e3742002-12-13 20:15:29 +0000517
518 if (ospf->old_table)
519 ospf_route_table_free (ospf->old_table);
520 if (ospf->new_table)
521 {
522 ospf_route_delete (ospf->new_table);
523 ospf_route_table_free (ospf->new_table);
524 }
525 if (ospf->old_rtrs)
526 ospf_rtrs_free (ospf->old_rtrs);
527 if (ospf->new_rtrs)
528 ospf_rtrs_free (ospf->new_rtrs);
529 if (ospf->new_external_route)
530 {
531 ospf_route_delete (ospf->new_external_route);
532 ospf_route_table_free (ospf->new_external_route);
533 }
534 if (ospf->old_external_route)
535 {
536 ospf_route_delete (ospf->old_external_route);
537 ospf_route_table_free (ospf->old_external_route);
538 }
539 if (ospf->external_lsas)
540 {
541 ospf_ase_external_lsas_finish (ospf->external_lsas);
542 }
543
544 list_delete (ospf->areas);
545
546 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
547 if (EXTERNAL_INFO (i) != NULL)
548 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
549 {
550 if (rn->info == NULL)
551 continue;
552
553 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
554 rn->info = NULL;
555 route_unlock_node (rn);
556 }
557
paul68980082003-03-25 05:07:42 +0000558 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000559 route_table_finish (ospf->distance_table);
560
paul020709f2003-04-04 02:44:16 +0000561 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000562
paul020709f2003-04-04 02:44:16 +0000563 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000564}
565
566
567/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000568static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000569ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000570{
571 struct ospf_area *new;
572
573 /* Allocate new config_network. */
574 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
575
paul68980082003-03-25 05:07:42 +0000576 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000577
578 new->area_id = area_id;
579
580 new->external_routing = OSPF_AREA_DEFAULT;
581 new->default_cost = 1;
582 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000583
paul718e3742002-12-13 20:15:29 +0000584 /* New LSDB init. */
585 new->lsdb = ospf_lsdb_new ();
586
587 /* Self-originated LSAs initialize. */
588 new->router_lsa_self = NULL;
589
590#ifdef HAVE_OPAQUE_LSA
591 ospf_opaque_type10_lsa_init (new);
592#endif /* HAVE_OPAQUE_LSA */
593
594 new->oiflist = list_new ();
595 new->ranges = route_table_init ();
596
597 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000598 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000599
600 return new;
601}
602
Stephen Hemminger917e2992009-12-03 19:07:00 +0300603static void
paul718e3742002-12-13 20:15:29 +0000604ospf_area_free (struct ospf_area *area)
605{
paul68980082003-03-25 05:07:42 +0000606 struct route_node *rn;
607 struct ospf_lsa *lsa;
608
paul718e3742002-12-13 20:15:29 +0000609 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000610 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
611 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
612 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
613 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
614 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
615 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
616 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
617 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000618
paul68980082003-03-25 05:07:42 +0000619 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
620 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000621#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000622 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
623 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
624 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
625 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000626#endif /* HAVE_OPAQUE_LSA */
627
628 ospf_lsdb_delete_all (area->lsdb);
629 ospf_lsdb_free (area->lsdb);
630
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000631 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000632
633 route_table_finish (area->ranges);
634 list_delete (area->oiflist);
635
636 if (EXPORT_NAME (area))
637 free (EXPORT_NAME (area));
638
639 if (IMPORT_NAME (area))
640 free (IMPORT_NAME (area));
641
642 /* Cancel timer. */
paul88d6cf32005-10-29 12:50:09 +0000643 OSPF_TIMER_OFF (area->t_stub_router);
644#ifdef HAVE_OPAQUE_LSA
645 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
646#endif /* HAVE_OPAQUE_LSA */
647
paul718e3742002-12-13 20:15:29 +0000648 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000649 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000650
651 XFREE (MTYPE_OSPF_AREA, area);
652}
653
654void
paul68980082003-03-25 05:07:42 +0000655ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000656{
657 struct ospf_area *area;
658
paul68980082003-03-25 05:07:42 +0000659 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000660 if (area &&
661 listcount (area->oiflist) == 0 &&
662 area->ranges->top == NULL &&
663 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
664 area->external_routing == OSPF_AREA_DEFAULT &&
665 area->no_summary == 0 &&
666 area->default_cost == 1 &&
667 EXPORT_NAME (area) == NULL &&
668 IMPORT_NAME (area) == NULL &&
669 area->auth_type == OSPF_AUTH_NULL)
670 {
paul68980082003-03-25 05:07:42 +0000671 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000672 ospf_area_free (area);
673 }
674}
675
676struct ospf_area *
paul68980082003-03-25 05:07:42 +0000677ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000678{
679 struct ospf_area *area;
680
paul68980082003-03-25 05:07:42 +0000681 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000682 if (!area)
683 {
paul68980082003-03-25 05:07:42 +0000684 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000685 area->format = format;
paul68980082003-03-25 05:07:42 +0000686 listnode_add_sort (ospf->areas, area);
687 ospf_check_abr_status (ospf);
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800688 if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET)
689 {
690 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
691 }
paul718e3742002-12-13 20:15:29 +0000692 }
693
694 return area;
695}
696
697struct ospf_area *
paul68980082003-03-25 05:07:42 +0000698ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000699{
700 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000701 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000702
paul1eb8ef22005-04-07 07:30:20 +0000703 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
704 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
705 return area;
paul718e3742002-12-13 20:15:29 +0000706
707 return NULL;
708}
709
710void
711ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
712{
713 listnode_add (area->oiflist, oi);
714}
715
716void
717ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
718{
719 listnode_delete (area->oiflist, oi);
720}
721
722
723/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000724static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000725ospf_network_new (struct in_addr area_id, int format)
726{
727 struct ospf_network *new;
728 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
729
730 new->area_id = area_id;
731 new->format = format;
732
733 return new;
734}
735
Stephen Hemminger917e2992009-12-03 19:07:00 +0300736static void
paul68980082003-03-25 05:07:42 +0000737ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000738{
paul68980082003-03-25 05:07:42 +0000739 ospf_area_check_free (ospf, network->area_id);
740 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000741 XFREE (MTYPE_OSPF_NETWORK, network);
742}
743
744int
745ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
746 struct in_addr area_id)
747{
748 struct ospf_network *network;
749 struct ospf_area *area;
750 struct route_node *rn;
751 struct external_info *ei;
paul147193a2003-04-19 00:31:59 +0000752 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000753
754 rn = route_node_get (ospf->networks, (struct prefix *)p);
755 if (rn->info)
756 {
757 /* There is already same network statement. */
758 route_unlock_node (rn);
759 return 0;
760 }
761
762 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000763 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000764
765 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100766 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000767
768 /* Update connected redistribute. */
769 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
770 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
771 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
772 rn; rn = route_next (rn))
773 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000774 if (ospf_external_info_find_lsa (ospf, &ei->p))
775 if (!ospf_distribute_check_connected (ospf, ei))
776 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
ajs5339cfd2005-09-19 13:28:05 +0000777 ei->ifindex /*, ei->nexthop */);
paul718e3742002-12-13 20:15:29 +0000778
paul68980082003-03-25 05:07:42 +0000779 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000780
781 return 1;
782}
783
784int
785ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
786 struct in_addr area_id)
787{
788 struct route_node *rn;
789 struct ospf_network *network;
790 struct external_info *ei;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100791 struct listnode *node, *nnode;
792 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000793
794 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
795 if (rn == NULL)
796 return 0;
797
798 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700799 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000800 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
801 return 0;
802
paul68980082003-03-25 05:07:42 +0000803 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000804 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700805 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000806
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100807 /* Find interfaces that not configured already. */
808 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
809 {
810 int found = 0;
811 struct connected *co = oi->connected;
812
813 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
814 continue;
815
816 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
817 {
818 if (rn->info == NULL)
819 continue;
820
821 if (ospf_network_match_iface(co,&rn->p))
822 {
823 found = 1;
824 route_unlock_node (rn);
825 break;
826 }
827 }
828
829 if (found == 0)
830 ospf_if_free (oi);
831 }
paul718e3742002-12-13 20:15:29 +0000832
833 /* Update connected redistribute. */
834 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
835 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
836 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
837 rn; rn = route_next (rn))
838 if ((ei = rn->info) != NULL)
paul68980082003-03-25 05:07:42 +0000839 if (!ospf_external_info_find_lsa (ospf, &ei->p))
840 if (ospf_distribute_check_connected (ospf, ei))
841 ospf_external_lsa_originate (ospf, ei);
paul718e3742002-12-13 20:15:29 +0000842
843 return 1;
844}
845
paul570f7592003-01-25 06:47:41 +0000846/* Check whether interface matches given network
847 * returns: 1, true. 0, false
848 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300849static int
850ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000851{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000852 /* new approach: more elegant and conceptually clean */
853 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000854}
855
Stephen Hemminger917e2992009-12-03 19:07:00 +0300856static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100857ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
858 struct interface *ifp)
859{
860 struct listnode *cnode;
861 struct connected *co;
862
863 if (memcmp (ifp->name, "VLINK", 5) == 0)
864 return;
865
866 /* if interface prefix is match specified prefix,
867 then create socket and join multicast group. */
868 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
869 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200870
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100871 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
872 continue;
873
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100874 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +0200875 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100876 && ospf_network_match_iface(co,p))
877 {
878 struct ospf_interface *oi;
879
880 oi = ospf_if_new (area->ospf, ifp, co->address);
881 oi->connected = co;
882
883 oi->area = area;
884
885 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
886 oi->output_cost = ospf_if_get_output_cost (oi);
887
888 /* Add pseudo neighbor. */
889 ospf_nbr_add_self (oi);
890
891 /* Relate ospf interface to ospf instance. */
892 oi->ospf = area->ospf;
893
894 /* update network type as interface flag */
895 /* If network type is specified previously,
896 skip network type setting. */
897 oi->type = IF_DEF_PARAMS (ifp)->type;
898
899 ospf_area_add_if (oi->area, oi);
900
901 /* if router_id is not configured, dont bring up
902 * interfaces.
903 * ospf_router_id_update() will call ospf_if_update
904 * whenever r-id is configured instead.
905 */
906 if ((area->ospf->router_id.s_addr != 0)
907 && if_is_operative (ifp))
908 ospf_if_up (oi);
909 }
910 }
911}
912
Stephen Hemminger917e2992009-12-03 19:07:00 +0300913static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100914ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000915{
916 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000917 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000918
919 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100920 if (area->ospf->router_id.s_addr == 0)
921 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +0000922
paul718e3742002-12-13 20:15:29 +0000923 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +0000924 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100925 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +0000926}
927
928void
929ospf_ls_upd_queue_empty (struct ospf_interface *oi)
930{
931 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +0000932 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000933 struct list *lst;
paul718e3742002-12-13 20:15:29 +0000934 struct ospf_lsa *lsa;
935
936 /* empty ls update queue */
937 for (rn = route_top (oi->ls_upd_queue); rn;
938 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +0000939 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +0000940 {
paul1eb8ef22005-04-07 07:30:20 +0000941 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000942 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +0000943 list_free (lst);
944 rn->info = NULL;
945 }
946
947 /* remove update event */
948 if (oi->t_ls_upd_event)
949 {
950 thread_cancel (oi->t_ls_upd_event);
951 oi->t_ls_upd_event = NULL;
952 }
953}
954
955void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100956ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000957{
958 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000959 struct ospf_network *network;
960 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100961
962 if (!ospf)
963 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +0000964
Joakim Tjernlund6e687d72008-09-24 17:15:48 +0100965 /* OSPF must be on and Router-ID must be configured. */
966 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100967 return;
968
969 /* Run each netowrk for this interface. */
970 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
971 if (rn->info != NULL)
972 {
973 network = (struct ospf_network *) rn->info;
974 area = ospf_area_get (ospf, network->area_id, network->format);
975 ospf_network_run_interface (&rn->p, area, ifp);
976 }
paul718e3742002-12-13 20:15:29 +0000977}
978
979void
paul68980082003-03-25 05:07:42 +0000980ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +0000981{
paul1eb8ef22005-04-07 07:30:20 +0000982 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000983 struct ospf_vl_data *vl_data;
984
paul1eb8ef22005-04-07 07:30:20 +0000985 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
986 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
987 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000988}
989
990
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700991static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +0000992{
993 { OSPF_AREA_DEFAULT, "Default" },
994 { OSPF_AREA_STUB, "Stub" },
995 { OSPF_AREA_NSSA, "NSSA" },
996};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -0700997static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +0000998
paul4dadc292005-05-06 21:37:42 +0000999static void
paul718e3742002-12-13 20:15:29 +00001000ospf_area_type_set (struct ospf_area *area, int type)
1001{
hasso52dc7ee2004-09-23 19:18:23 +00001002 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001003 struct ospf_interface *oi;
1004
1005 if (area->external_routing == type)
1006 {
1007 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001008 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001009 inet_ntoa (area->area_id));
1010 return;
1011 }
1012
1013 area->external_routing = type;
1014
1015 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001016 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001017 LOOKUP (ospf_area_type_msg, type));
1018
1019 switch (area->external_routing)
1020 {
1021 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001022 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1023 if (oi->nbr_self != NULL)
1024 {
1025 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1026 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1027 }
paul718e3742002-12-13 20:15:29 +00001028 break;
1029 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001030 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1031 if (oi->nbr_self != NULL)
1032 {
1033 if (IS_DEBUG_OSPF_EVENT)
1034 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1035 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1036 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1037 if (IS_DEBUG_OSPF_EVENT)
1038 zlog_debug ("options set on %s: %x",
1039 IF_NAME (oi), OPTIONS (oi));
1040 }
paul718e3742002-12-13 20:15:29 +00001041 break;
1042 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001043 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1044 if (oi->nbr_self != NULL)
1045 {
1046 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1047 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1048 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1049 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1050 }
paul718e3742002-12-13 20:15:29 +00001051 break;
1052 default:
1053 break;
1054 }
1055
Paul Jakmac363d382010-01-24 22:42:13 +00001056 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001057 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001058}
1059
1060int
paul68980082003-03-25 05:07:42 +00001061ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001062{
1063 if (area->shortcut_configured == mode)
1064 return 0;
1065
1066 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001067 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001068 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001069
paul68980082003-03-25 05:07:42 +00001070 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001071
1072 return 1;
1073}
1074
1075int
paul68980082003-03-25 05:07:42 +00001076ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001077{
1078 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001079 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001080 ospf_area_check_free (ospf, area->area_id);
1081 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001082
1083 return 1;
1084}
1085
paul4dadc292005-05-06 21:37:42 +00001086static int
paul718e3742002-12-13 20:15:29 +00001087ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1088{
1089 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001090 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001091 int count = 0;
1092
paul1eb8ef22005-04-07 07:30:20 +00001093 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1094 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1095 count++;
paul718e3742002-12-13 20:15:29 +00001096
1097 return count;
1098}
1099
1100int
1101ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1102{
1103 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001104 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001105
paul68980082003-03-25 05:07:42 +00001106 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001107 if (ospf_area_vlink_count (ospf, area))
1108 return 0;
1109
1110 if (area->external_routing != OSPF_AREA_STUB)
1111 ospf_area_type_set (area, OSPF_AREA_STUB);
1112
1113 return 1;
1114}
1115
1116int
1117ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1118{
1119 struct ospf_area *area;
1120
paul68980082003-03-25 05:07:42 +00001121 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001122 if (area == NULL)
1123 return 1;
1124
1125 if (area->external_routing == OSPF_AREA_STUB)
1126 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1127
paul68980082003-03-25 05:07:42 +00001128 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001129
1130 return 1;
1131}
1132
1133int
1134ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1135{
1136 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001137 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001138
paul68980082003-03-25 05:07:42 +00001139 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001140 area->no_summary = 1;
1141
1142 return 1;
1143}
1144
1145int
1146ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1147{
1148 struct ospf_area *area;
1149
paul68980082003-03-25 05:07:42 +00001150 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001151 if (area == NULL)
1152 return 0;
1153
1154 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001155 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001156
1157 return 1;
1158}
1159
1160int
1161ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1162{
1163 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001164 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001165
paul68980082003-03-25 05:07:42 +00001166 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001167 if (ospf_area_vlink_count (ospf, area))
1168 return 0;
1169
1170 if (area->external_routing != OSPF_AREA_NSSA)
1171 {
1172 ospf_area_type_set (area, OSPF_AREA_NSSA);
1173 ospf->anyNSSA++;
1174 }
1175
paul084c7842003-06-22 08:35:18 +00001176 /* set NSSA area defaults */
1177 area->no_summary = 0;
1178 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001179 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001180 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1181
paul718e3742002-12-13 20:15:29 +00001182 return 1;
1183}
1184
1185int
1186ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1187{
1188 struct ospf_area *area;
1189
paul68980082003-03-25 05:07:42 +00001190 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001191 if (area == NULL)
1192 return 0;
1193
1194 if (area->external_routing == OSPF_AREA_NSSA)
1195 {
1196 ospf->anyNSSA--;
1197 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1198 }
1199
paul68980082003-03-25 05:07:42 +00001200 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001201
1202 return 1;
1203}
1204
1205int
1206ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1207 int role)
1208{
1209 struct ospf_area *area;
1210
paul68980082003-03-25 05:07:42 +00001211 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001212 if (area == NULL)
1213 return 0;
1214
paul084c7842003-06-22 08:35:18 +00001215 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001216
1217 return 1;
1218}
1219
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001220#if 0
paul4dadc292005-05-06 21:37:42 +00001221/* XXX: unused? Leave for symmetry? */
1222static int
paul718e3742002-12-13 20:15:29 +00001223ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1224 struct in_addr area_id)
1225{
1226 struct ospf_area *area;
1227
paul68980082003-03-25 05:07:42 +00001228 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001229 if (area == NULL)
1230 return 0;
1231
paul084c7842003-06-22 08:35:18 +00001232 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001233
paul68980082003-03-25 05:07:42 +00001234 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001235
1236 return 1;
1237}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001238#endif
paul718e3742002-12-13 20:15:29 +00001239
1240int
paul68980082003-03-25 05:07:42 +00001241ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001242 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001243{
1244 struct access_list *list;
1245 list = access_list_lookup (AFI_IP, list_name);
1246
1247 EXPORT_LIST (area) = list;
1248
1249 if (EXPORT_NAME (area))
1250 free (EXPORT_NAME (area));
1251
1252 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001253 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001254
1255 return 1;
1256}
1257
1258int
paul68980082003-03-25 05:07:42 +00001259ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001260{
1261
1262 EXPORT_LIST (area) = 0;
1263
1264 if (EXPORT_NAME (area))
1265 free (EXPORT_NAME (area));
1266
1267 EXPORT_NAME (area) = NULL;
1268
paul68980082003-03-25 05:07:42 +00001269 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001270
paul68980082003-03-25 05:07:42 +00001271 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001272
1273 return 1;
1274}
1275
1276int
paul6c835672004-10-11 11:00:30 +00001277ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1278 const char *name)
paul718e3742002-12-13 20:15:29 +00001279{
1280 struct access_list *list;
1281 list = access_list_lookup (AFI_IP, name);
1282
1283 IMPORT_LIST (area) = list;
1284
1285 if (IMPORT_NAME (area))
1286 free (IMPORT_NAME (area));
1287
1288 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001289 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001290
1291 return 1;
1292}
1293
1294int
paul68980082003-03-25 05:07:42 +00001295ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001296{
1297 IMPORT_LIST (area) = 0;
1298
1299 if (IMPORT_NAME (area))
1300 free (IMPORT_NAME (area));
1301
1302 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001303 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001304
paul68980082003-03-25 05:07:42 +00001305 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001306
1307 return 1;
1308}
1309
1310int
paul718e3742002-12-13 20:15:29 +00001311ospf_timers_refresh_set (struct ospf *ospf, int interval)
1312{
1313 int time_left;
1314
1315 if (ospf->lsa_refresh_interval == interval)
1316 return 1;
1317
1318 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001319 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001320
1321 if (time_left > interval)
1322 {
1323 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1324 ospf->t_lsa_refresher =
1325 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1326 }
1327 ospf->lsa_refresh_interval = interval;
1328
1329 return 1;
1330}
1331
1332int
1333ospf_timers_refresh_unset (struct ospf *ospf)
1334{
1335 int time_left;
1336
1337 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001338 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001339
1340 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1341 {
1342 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1343 ospf->t_lsa_refresher =
1344 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1345 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1346 }
1347
1348 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1349
1350 return 1;
1351}
1352
1353
paul4dadc292005-05-06 21:37:42 +00001354static struct ospf_nbr_nbma *
1355ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001356{
1357 struct ospf_nbr_nbma *nbr_nbma;
1358
Stephen Hemminger393deb92008-08-18 14:13:29 -07001359 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001360 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001361
1362 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1363 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1364
1365 return nbr_nbma;
1366}
1367
paul4dadc292005-05-06 21:37:42 +00001368static void
paul718e3742002-12-13 20:15:29 +00001369ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1370{
1371 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1372}
1373
paul4dadc292005-05-06 21:37:42 +00001374static void
paul718e3742002-12-13 20:15:29 +00001375ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1376{
1377 struct route_node *rn;
1378 struct prefix_ipv4 p;
1379
1380 p.family = AF_INET;
1381 p.prefix = nbr_nbma->addr;
1382 p.prefixlen = IPV4_MAX_BITLEN;
1383
1384 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1385 if (rn)
1386 {
1387 ospf_nbr_nbma_free (rn->info);
1388 rn->info = NULL;
1389 route_unlock_node (rn);
1390 route_unlock_node (rn);
1391 }
1392}
1393
paul4dadc292005-05-06 21:37:42 +00001394static void
paul718e3742002-12-13 20:15:29 +00001395ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1396{
1397 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1398
1399 if (nbr_nbma->nbr)
1400 {
1401 nbr_nbma->nbr->nbr_nbma = NULL;
1402 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1403 }
1404
1405 if (nbr_nbma->oi)
1406 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1407}
1408
paul4dadc292005-05-06 21:37:42 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1411 struct ospf_interface *oi)
1412{
1413 struct ospf_neighbor *nbr;
1414 struct route_node *rn;
1415 struct prefix p;
1416
1417 if (oi->type != OSPF_IFTYPE_NBMA)
1418 return;
1419
1420 if (nbr_nbma->nbr != NULL)
1421 return;
1422
1423 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1424 return;
1425
1426 nbr_nbma->oi = oi;
1427 listnode_add (oi->nbr_nbma, nbr_nbma);
1428
1429 /* Get neighbor information from table. */
1430 p.family = AF_INET;
1431 p.prefixlen = IPV4_MAX_BITLEN;
1432 p.u.prefix4 = nbr_nbma->addr;
1433
1434 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1435 if (rn->info)
1436 {
1437 nbr = rn->info;
1438 nbr->nbr_nbma = nbr_nbma;
1439 nbr_nbma->nbr = nbr;
1440
1441 route_unlock_node (rn);
1442 }
1443 else
1444 {
1445 nbr = rn->info = ospf_nbr_new (oi);
1446 nbr->state = NSM_Down;
1447 nbr->src = nbr_nbma->addr;
1448 nbr->nbr_nbma = nbr_nbma;
1449 nbr->priority = nbr_nbma->priority;
1450 nbr->address = p;
1451
1452 nbr_nbma->nbr = nbr;
1453
1454 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1455 }
1456}
1457
1458void
paul68980082003-03-25 05:07:42 +00001459ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001460{
1461 struct ospf_nbr_nbma *nbr_nbma;
1462 struct route_node *rn;
1463 struct prefix_ipv4 p;
1464
1465 if (oi->type != OSPF_IFTYPE_NBMA)
1466 return;
1467
paul68980082003-03-25 05:07:42 +00001468 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001469 if ((nbr_nbma = rn->info))
1470 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1471 {
1472 p.family = AF_INET;
1473 p.prefix = nbr_nbma->addr;
1474 p.prefixlen = IPV4_MAX_BITLEN;
1475
1476 if (prefix_match (oi->address, (struct prefix *)&p))
1477 ospf_nbr_nbma_add (nbr_nbma, oi);
1478 }
1479}
1480
1481struct ospf_nbr_nbma *
1482ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1483{
1484 struct route_node *rn;
1485 struct prefix_ipv4 p;
1486
1487 p.family = AF_INET;
1488 p.prefix = nbr_addr;
1489 p.prefixlen = IPV4_MAX_BITLEN;
1490
1491 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1492 if (rn)
1493 {
1494 route_unlock_node (rn);
1495 return rn->info;
1496 }
1497 return NULL;
1498}
1499
1500struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001501ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001502{
1503#if 0
1504 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001505 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001506#endif
1507
paul68980082003-03-25 05:07:42 +00001508 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001509 return NULL;
1510
1511#if 0
paul1eb8ef22005-04-07 07:30:20 +00001512 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001513 {
paul718e3742002-12-13 20:15:29 +00001514 if (first)
1515 {
1516 *addr = nbr_nbma->addr;
1517 return nbr_nbma;
1518 }
1519 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1520 {
1521 *addr = nbr_nbma->addr;
1522 return nbr_nbma;
1523 }
1524 }
1525#endif
1526 return NULL;
1527}
1528
1529int
1530ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1531{
1532 struct ospf_nbr_nbma *nbr_nbma;
1533 struct ospf_interface *oi;
1534 struct prefix_ipv4 p;
1535 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001536 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001537
1538 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1539 if (nbr_nbma)
1540 return 0;
1541
1542 nbr_nbma = ospf_nbr_nbma_new ();
1543 nbr_nbma->addr = nbr_addr;
1544
1545 p.family = AF_INET;
1546 p.prefix = nbr_addr;
1547 p.prefixlen = IPV4_MAX_BITLEN;
1548
1549 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
1550 rn->info = nbr_nbma;
1551
paul1eb8ef22005-04-07 07:30:20 +00001552 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001553 {
paul718e3742002-12-13 20:15:29 +00001554 if (oi->type == OSPF_IFTYPE_NBMA)
1555 if (prefix_match (oi->address, (struct prefix *)&p))
1556 {
1557 ospf_nbr_nbma_add (nbr_nbma, oi);
1558 break;
1559 }
1560 }
1561
1562 return 1;
1563}
1564
1565int
1566ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1567{
1568 struct ospf_nbr_nbma *nbr_nbma;
1569
1570 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1571 if (nbr_nbma == NULL)
1572 return 0;
1573
1574 ospf_nbr_nbma_down (nbr_nbma);
1575 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1576
1577 return 1;
1578}
1579
1580int
1581ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1582 u_char priority)
1583{
1584 struct ospf_nbr_nbma *nbr_nbma;
1585
1586 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1587 if (nbr_nbma == NULL)
1588 return 0;
1589
1590 if (nbr_nbma->priority != priority)
1591 nbr_nbma->priority = priority;
1592
1593 return 1;
1594}
1595
1596int
1597ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1598{
1599 struct ospf_nbr_nbma *nbr_nbma;
1600
1601 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1602 if (nbr_nbma == NULL)
1603 return 0;
1604
1605 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1606 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1607
1608 return 1;
1609}
1610
1611int
1612ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001613 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001614{
1615 struct ospf_nbr_nbma *nbr_nbma;
1616
1617 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1618 if (nbr_nbma == NULL)
1619 return 0;
1620
1621 if (nbr_nbma->v_poll != interval)
1622 {
1623 nbr_nbma->v_poll = interval;
1624 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1625 {
1626 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1627 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1628 nbr_nbma->v_poll);
1629 }
1630 }
1631
1632 return 1;
1633}
1634
1635int
1636ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1637{
1638 struct ospf_nbr_nbma *nbr_nbma;
1639
1640 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1641 if (nbr_nbma == NULL)
1642 return 0;
1643
1644 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1645 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1646
1647 return 1;
1648}
1649
paul718e3742002-12-13 20:15:29 +00001650void
paul020709f2003-04-04 02:44:16 +00001651ospf_master_init ()
1652{
1653 memset (&ospf_master, 0, sizeof (struct ospf_master));
1654
1655 om = &ospf_master;
1656 om->ospf = list_new ();
1657 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001658 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001659}