blob: c317ed87c45a28cfed677f3da2197290d555b763 [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
David Lamparter6b0655a2014-06-04 06:53:35 +020056
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
David Lamparter6b0655a2014-06-04 06:53:35 +020067
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 *);
Paul Jakma8a667cf2009-08-27 16:51:42 +010072static void ospf_network_run_interface (struct ospf *, struct interface *,
73 struct prefix *, struct ospf_area *);
74static void ospf_network_run_subnet (struct ospf *, struct connected *,
75 struct prefix *, struct ospf_area *);
Stephen Hemminger917e2992009-12-03 19:07:00 +030076static int ospf_network_match_iface (const struct connected *,
77 const struct prefix *);
paul88d6cf32005-10-29 12:50:09 +000078static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000079
paul718e3742002-12-13 20:15:29 +000080#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
David Lamparter6b0655a2014-06-04 06:53:35 +020081
paul718e3742002-12-13 20:15:29 +000082void
paul68980082003-03-25 05:07:42 +000083ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000084{
paul718e3742002-12-13 20:15:29 +000085 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000086 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010087 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000088 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000089
90 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000091 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000092
paul68980082003-03-25 05:07:42 +000093 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000094
Andrew J. Schorr16700082006-07-27 22:29:06 +000095 /* Select the router ID based on these priorities:
96 1. Statically assigned router ID is always the first choice.
97 2. If there is no statically assigned router ID, then try to stick
98 with the most recent value, since changing router ID's is very
99 disruptive.
100 3. Last choice: just go with whatever the zebra daemon recommends.
101 */
paul68980082003-03-25 05:07:42 +0000102 if (ospf->router_id_static.s_addr != 0)
103 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000104 else if (ospf->router_id.s_addr != 0)
105 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000106 else
hasso18a6dce2004-10-03 18:18:34 +0000107 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000108
paul68980082003-03-25 05:07:42 +0000109 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000110
111 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000112 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000113
114 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
115 {
paul1eb8ef22005-04-07 07:30:20 +0000116 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
Joakim Tjernlund94266fa2009-11-19 15:27:30 +0100117 {
118 /* Some nbrs are identified by router_id, these needs
119 * to be rebuilt. Possible optimization would be to do
120 * oi->nbr_self->router_id = router_id for
121 * !(virtual | ptop) links
122 */
Paul Jakmac920e512015-09-08 15:31:45 +0100123 ospf_nbr_self_reset (oi);
Joakim Tjernlund94266fa2009-11-19 15:27:30 +0100124 }
paul718e3742002-12-13 20:15:29 +0000125
126 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000127 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000128 {
129 int type;
130 /* Originate each redistributed external route. */
131 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000132 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000133 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000134 ospf, type);
paul718e3742002-12-13 20:15:29 +0000135 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000136 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000137 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000138
paul68980082003-03-25 05:07:42 +0000139 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000140 }
141
Paul Jakmac363d382010-01-24 22:42:13 +0000142 /* update router-lsa's for each area */
143 ospf_router_lsa_update (ospf);
paulb29800a2005-11-20 14:50:45 +0000144
145 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100146 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
147 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000148 }
149}
David Lamparter6b0655a2014-06-04 06:53:35 +0200150
paul718e3742002-12-13 20:15:29 +0000151/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000152static int
paul718e3742002-12-13 20:15:29 +0000153ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
154{
155 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
156 return 1;
157 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
158 return -1;
159 return 0;
160}
161
162/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000163static struct ospf *
164ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000165{
166 int i;
167
168 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
169
170 new->router_id.s_addr = htonl (0);
171 new->router_id_static.s_addr = htonl (0);
172
pauld57834f2005-07-12 20:04:22 +0000173 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000174 new->oiflist = list_new ();
175 new->vlinks = list_new ();
176 new->areas = list_new ();
177 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
178 new->networks = route_table_init ();
179 new->nbr_nbma = route_table_init ();
180
181 new->lsdb = ospf_lsdb_new ();
182
183 new->default_originate = DEFAULT_ORIGINATE_NONE;
184
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000185 new->passive_interface_default = OSPF_IF_ACTIVE;
186
paul718e3742002-12-13 20:15:29 +0000187 new->new_external_route = route_table_init ();
188 new->old_external_route = route_table_init ();
189 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000190
191 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000192 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800193 new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET;
194
paul718e3742002-12-13 20:15:29 +0000195 /* Distribute parameter init. */
196 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
197 {
198 new->dmetric[i].type = -1;
199 new->dmetric[i].value = -1;
200 }
201 new->default_metric = -1;
202 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
203
Michael Rossberg2ef762e2015-07-27 07:56:25 +0200204 /* LSA timers */
205 new->min_ls_interval = OSPF_MIN_LS_INTERVAL;
206 new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
207
paul718e3742002-12-13 20:15:29 +0000208 /* SPF timer value init. */
209 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
210 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000211 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
212 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000213
214 /* MaxAge init. */
Dinesh Dutt2449fcd2013-08-24 07:54:17 +0000215 new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800216 new->maxage_lsa = route_table_init();
paul718e3742002-12-13 20:15:29 +0000217 new->t_maxage_walker =
218 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000219 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000220
221 /* Distance table init. */
222 new->distance_table = route_table_init ();
223
224 new->lsa_refresh_queue.index = 0;
225 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
226 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
227 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000228 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000229
ajs5c333492005-02-23 15:43:01 +0000230 if ((new->fd = ospf_sock_init()) < 0)
231 {
232 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
233 "a socket");
234 exit(1);
235 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000236 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
237 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
Andrew Certain0798cee2012-12-04 13:43:42 -0800238 zlog_debug ("%s: starting with OSPF send buffer size %u",
Denis Ovsienkof102e752007-09-18 09:01:13 +0000239 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000240 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
241 {
242 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
243 OSPF_MAX_PACKET_SIZE+1);
244 exit(1);
245 }
246 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000247 new->oi_write_q = list_new ();
248
249 return new;
250}
251
252struct ospf *
paul020709f2003-04-04 02:44:16 +0000253ospf_lookup ()
254{
255 if (listcount (om->ospf) == 0)
256 return NULL;
257
paul1eb8ef22005-04-07 07:30:20 +0000258 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000259}
260
Paul Jakma8a667cf2009-08-27 16:51:42 +0100261static int
262ospf_is_ready (struct ospf *ospf)
263{
264 /* OSPF must be on and Router-ID must be configured. */
265 if (!ospf || ospf->router_id.s_addr == 0)
266 return 0;
267
268 return 1;
269}
270
paul4dadc292005-05-06 21:37:42 +0000271static void
paul020709f2003-04-04 02:44:16 +0000272ospf_add (struct ospf *ospf)
273{
274 listnode_add (om->ospf, ospf);
275}
276
paul4dadc292005-05-06 21:37:42 +0000277static void
paul020709f2003-04-04 02:44:16 +0000278ospf_delete (struct ospf *ospf)
279{
280 listnode_delete (om->ospf, ospf);
281}
282
283struct ospf *
paul718e3742002-12-13 20:15:29 +0000284ospf_get ()
285{
paul020709f2003-04-04 02:44:16 +0000286 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000287
paul020709f2003-04-04 02:44:16 +0000288 ospf = ospf_lookup ();
289 if (ospf == NULL)
290 {
291 ospf = ospf_new ();
292 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000293
paul020709f2003-04-04 02:44:16 +0000294 if (ospf->router_id_static.s_addr == 0)
295 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000296
297#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000298 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000299#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000300 }
paul68980082003-03-25 05:07:42 +0000301
302 return ospf;
paul718e3742002-12-13 20:15:29 +0000303}
David Lamparter6b0655a2014-06-04 06:53:35 +0200304
paulc9c93d52005-11-26 13:31:11 +0000305/* Handle the second half of deferred shutdown. This is called either
306 * from the deferred-shutdown timer thread, or directly through
307 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000308 *
309 * Function is to cleanup G-R state, if required then call ospf_finish_final
310 * to complete shutdown of this ospf instance. Possibly exit if the
311 * whole process is being shutdown and this was the last OSPF instance.
312 */
313static void
paulc9c93d52005-11-26 13:31:11 +0000314ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000315{
316 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000317 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000318
319 ospf_finish_final (ospf);
320
321 /* *ospf is now invalid */
322
323 /* ospfd being shut-down? If so, was this the last ospf instance? */
324 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
325 && (listcount (om->ospf) == 0))
326 exit (0);
327
328 return;
329}
330
331/* Timer thread for G-R */
332static int
paulc9c93d52005-11-26 13:31:11 +0000333ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000334{
335 struct ospf *ospf = THREAD_ARG(t);
336
paulc9c93d52005-11-26 13:31:11 +0000337 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000338
339 return 0;
340}
341
paulc9c93d52005-11-26 13:31:11 +0000342/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000343 * down directly into second-half of instance shutdown.
344 */
345static void
paulc9c93d52005-11-26 13:31:11 +0000346ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000347{
348 unsigned long timeout;
349 struct listnode *ln;
350 struct ospf_area *area;
351
paulc9c93d52005-11-26 13:31:11 +0000352 /* deferred shutdown already running? */
353 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000354 return;
355
356 /* Should we try push out max-metric LSAs? */
357 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
358 {
359 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
360 {
361 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
362
363 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000364 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000365 }
366 timeout = ospf->stub_router_shutdown_time;
367 }
368 else
paulc9c93d52005-11-26 13:31:11 +0000369 {
370 /* No timer needed */
371 ospf_deferred_shutdown_finish (ospf);
372 return;
373 }
paul88d6cf32005-10-29 12:50:09 +0000374
paulc9c93d52005-11-26 13:31:11 +0000375 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000376 timeout);
377 return;
378}
David Lamparter6b0655a2014-06-04 06:53:35 +0200379
paul88d6cf32005-10-29 12:50:09 +0000380/* Shut down the entire process */
381void
382ospf_terminate (void)
383{
384 struct ospf *ospf;
385 struct listnode *node, *nnode;
386
387 /* shutdown already in progress */
388 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
389 return;
390
391 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
392
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000393 /* exit immediately if OSPF not actually running */
394 if (listcount(om->ospf) == 0)
395 exit(0);
396
paul88d6cf32005-10-29 12:50:09 +0000397 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
398 ospf_finish (ospf);
399
400 /* Deliberately go back up, hopefully to thread scheduler, as
401 * One or more ospf_finish()'s may have deferred shutdown to a timer
402 * thread
403 */
404}
paul718e3742002-12-13 20:15:29 +0000405
406void
407ospf_finish (struct ospf *ospf)
408{
paulc9c93d52005-11-26 13:31:11 +0000409 /* let deferred shutdown decide */
410 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000411
paulc9c93d52005-11-26 13:31:11 +0000412 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000413 * deferred to expiry of G-S timer thread. Return back up, hopefully
414 * to thread scheduler.
415 */
paulc9c93d52005-11-26 13:31:11 +0000416 return;
paul88d6cf32005-10-29 12:50:09 +0000417}
418
419/* Final cleanup of ospf instance */
420static void
421ospf_finish_final (struct ospf *ospf)
422{
paul718e3742002-12-13 20:15:29 +0000423 struct route_node *rn;
424 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000425 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct ospf_interface *oi;
427 struct ospf_area *area;
428 struct ospf_vl_data *vl_data;
429 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000430 int i;
431
432#ifdef HAVE_OPAQUE_LSA
433 ospf_opaque_type11_lsa_term (ospf);
434#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000435
436 /* be nice if this worked, but it doesn't */
437 /*ospf_flush_self_originated_lsas_now (ospf);*/
438
439 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000440 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000441 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000442 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000443
paul1eb8ef22005-04-07 07:30:20 +0000444 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
445 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000446
paul1eb8ef22005-04-07 07:30:20 +0000447 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
448 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000449
450 list_delete (ospf->vlinks);
451
452 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000453 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
454 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000455
456 /* Clear static neighbors */
457 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
458 if ((nbr_nbma = rn->info))
459 {
460 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
461
462 if (nbr_nbma->nbr)
463 {
464 nbr_nbma->nbr->nbr_nbma = NULL;
465 nbr_nbma->nbr = NULL;
466 }
467
468 if (nbr_nbma->oi)
469 {
470 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
471 nbr_nbma->oi = NULL;
472 }
473
474 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
475 }
476
477 route_table_finish (ospf->nbr_nbma);
478
479 /* Clear networks and Areas. */
480 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
481 {
482 struct ospf_network *network;
483
484 if ((network = rn->info) != NULL)
485 {
paul68980082003-03-25 05:07:42 +0000486 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000487 rn->info = NULL;
488 route_unlock_node (rn);
489 }
490 }
491
paul1eb8ef22005-04-07 07:30:20 +0000492 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000493 {
paul718e3742002-12-13 20:15:29 +0000494 listnode_delete (ospf->areas, area);
495 ospf_area_free (area);
496 }
497
498 /* Cancel all timers. */
499 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000500 OSPF_TIMER_OFF (ospf->t_spf_calc);
501 OSPF_TIMER_OFF (ospf->t_ase_calc);
502 OSPF_TIMER_OFF (ospf->t_maxage);
503 OSPF_TIMER_OFF (ospf->t_maxage_walker);
504 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000505 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000506 OSPF_TIMER_OFF (ospf->t_distribute_update);
507 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
508 OSPF_TIMER_OFF (ospf->t_read);
509 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000510#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000511 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000512#endif
paul718e3742002-12-13 20:15:29 +0000513
514 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000515 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000516
517#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000518 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
519 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000520#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000521 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
522 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
523
paul718e3742002-12-13 20:15:29 +0000524 ospf_lsdb_delete_all (ospf->lsdb);
525 ospf_lsdb_free (ospf->lsdb);
526
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800527 for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn))
528 {
529 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000530
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800531 if ((lsa = rn->info) != NULL)
532 {
533 ospf_lsa_unlock (&lsa);
534 rn->info = NULL;
535 }
536 route_unlock_node (rn);
537 }
538 route_table_finish (ospf->maxage_lsa);
paul718e3742002-12-13 20:15:29 +0000539
540 if (ospf->old_table)
541 ospf_route_table_free (ospf->old_table);
542 if (ospf->new_table)
543 {
544 ospf_route_delete (ospf->new_table);
545 ospf_route_table_free (ospf->new_table);
546 }
547 if (ospf->old_rtrs)
548 ospf_rtrs_free (ospf->old_rtrs);
549 if (ospf->new_rtrs)
550 ospf_rtrs_free (ospf->new_rtrs);
551 if (ospf->new_external_route)
552 {
553 ospf_route_delete (ospf->new_external_route);
554 ospf_route_table_free (ospf->new_external_route);
555 }
556 if (ospf->old_external_route)
557 {
558 ospf_route_delete (ospf->old_external_route);
559 ospf_route_table_free (ospf->old_external_route);
560 }
561 if (ospf->external_lsas)
562 {
563 ospf_ase_external_lsas_finish (ospf->external_lsas);
564 }
565
566 list_delete (ospf->areas);
567
568 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
569 if (EXTERNAL_INFO (i) != NULL)
570 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
571 {
572 if (rn->info == NULL)
573 continue;
574
575 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
576 rn->info = NULL;
577 route_unlock_node (rn);
578 }
579
paul68980082003-03-25 05:07:42 +0000580 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000581 route_table_finish (ospf->distance_table);
582
paul020709f2003-04-04 02:44:16 +0000583 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000584
paul020709f2003-04-04 02:44:16 +0000585 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000586}
587
David Lamparter6b0655a2014-06-04 06:53:35 +0200588
paul718e3742002-12-13 20:15:29 +0000589/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000590static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000591ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000592{
593 struct ospf_area *new;
594
595 /* Allocate new config_network. */
596 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
597
paul68980082003-03-25 05:07:42 +0000598 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000599
600 new->area_id = area_id;
601
602 new->external_routing = OSPF_AREA_DEFAULT;
603 new->default_cost = 1;
604 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000605
paul718e3742002-12-13 20:15:29 +0000606 /* New LSDB init. */
607 new->lsdb = ospf_lsdb_new ();
608
609 /* Self-originated LSAs initialize. */
610 new->router_lsa_self = NULL;
611
612#ifdef HAVE_OPAQUE_LSA
613 ospf_opaque_type10_lsa_init (new);
614#endif /* HAVE_OPAQUE_LSA */
615
616 new->oiflist = list_new ();
617 new->ranges = route_table_init ();
618
619 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000620 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000621
622 return new;
623}
624
Stephen Hemminger917e2992009-12-03 19:07:00 +0300625static void
paul718e3742002-12-13 20:15:29 +0000626ospf_area_free (struct ospf_area *area)
627{
paul68980082003-03-25 05:07:42 +0000628 struct route_node *rn;
629 struct ospf_lsa *lsa;
630
paul718e3742002-12-13 20:15:29 +0000631 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000632 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
633 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
634 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
635 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
636 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
637 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
638 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
639 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000640
paul68980082003-03-25 05:07:42 +0000641 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
642 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000643#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000644 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
645 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
646 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
647 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000648#endif /* HAVE_OPAQUE_LSA */
649
650 ospf_lsdb_delete_all (area->lsdb);
651 ospf_lsdb_free (area->lsdb);
652
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000653 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000654
655 route_table_finish (area->ranges);
656 list_delete (area->oiflist);
657
658 if (EXPORT_NAME (area))
659 free (EXPORT_NAME (area));
660
661 if (IMPORT_NAME (area))
662 free (IMPORT_NAME (area));
663
664 /* Cancel timer. */
paul88d6cf32005-10-29 12:50:09 +0000665 OSPF_TIMER_OFF (area->t_stub_router);
666#ifdef HAVE_OPAQUE_LSA
667 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
668#endif /* HAVE_OPAQUE_LSA */
669
paul718e3742002-12-13 20:15:29 +0000670 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000671 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000672
673 XFREE (MTYPE_OSPF_AREA, area);
674}
675
676void
paul68980082003-03-25 05:07:42 +0000677ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
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 listcount (area->oiflist) == 0 &&
684 area->ranges->top == NULL &&
685 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
686 area->external_routing == OSPF_AREA_DEFAULT &&
687 area->no_summary == 0 &&
688 area->default_cost == 1 &&
689 EXPORT_NAME (area) == NULL &&
690 IMPORT_NAME (area) == NULL &&
691 area->auth_type == OSPF_AUTH_NULL)
692 {
paul68980082003-03-25 05:07:42 +0000693 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000694 ospf_area_free (area);
695 }
696}
697
698struct ospf_area *
paul68980082003-03-25 05:07:42 +0000699ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000700{
701 struct ospf_area *area;
702
paul68980082003-03-25 05:07:42 +0000703 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000704 if (!area)
705 {
paul68980082003-03-25 05:07:42 +0000706 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000707 area->format = format;
paul68980082003-03-25 05:07:42 +0000708 listnode_add_sort (ospf->areas, area);
709 ospf_check_abr_status (ospf);
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800710 if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET)
711 {
712 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
713 }
paul718e3742002-12-13 20:15:29 +0000714 }
715
716 return area;
717}
718
719struct ospf_area *
paul68980082003-03-25 05:07:42 +0000720ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000721{
722 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000723 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000724
paul1eb8ef22005-04-07 07:30:20 +0000725 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
726 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
727 return area;
paul718e3742002-12-13 20:15:29 +0000728
729 return NULL;
730}
731
732void
733ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
734{
735 listnode_add (area->oiflist, oi);
736}
737
738void
739ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
740{
741 listnode_delete (area->oiflist, oi);
742}
743
David Lamparter6b0655a2014-06-04 06:53:35 +0200744
paul718e3742002-12-13 20:15:29 +0000745/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000746static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000747ospf_network_new (struct in_addr area_id, int format)
748{
749 struct ospf_network *new;
750 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
751
752 new->area_id = area_id;
753 new->format = format;
754
755 return new;
756}
757
Paul Jakma8a667cf2009-08-27 16:51:42 +0100758static void
759add_ospf_interface (struct connected *co, struct ospf_area *area)
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200760{
761 struct ospf_interface *oi;
762
Paul Jakma8a667cf2009-08-27 16:51:42 +0100763 oi = ospf_if_new (area->ospf, co->ifp, co->address);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200764 oi->connected = co;
765
766 oi->area = area;
767
Paul Jakma8a667cf2009-08-27 16:51:42 +0100768 oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200769 oi->output_cost = ospf_if_get_output_cost (oi);
770
771 /* Add pseudo neighbor. */
772 ospf_nbr_add_self (oi);
773
774 /* Relate ospf interface to ospf instance. */
775 oi->ospf = area->ospf;
776
777 /* update network type as interface flag */
778 /* If network type is specified previously,
779 skip network type setting. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100780 oi->type = IF_DEF_PARAMS (co->ifp)->type;
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200781
782 ospf_area_add_if (oi->area, oi);
783
784 /* if router_id is not configured, dont bring up
785 * interfaces.
786 * ospf_router_id_update() will call ospf_if_update
787 * whenever r-id is configured instead.
788 */
789 if ((area->ospf->router_id.s_addr != 0)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100790 && if_is_operative (co->ifp))
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200791 ospf_if_up (oi);
792}
793
794static void
795update_redistributed (struct ospf *ospf, int add_to_ospf)
796{
797 struct route_node *rn;
798 struct external_info *ei;
799
800 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
801 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
802 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
803 rn; rn = route_next (rn))
804 if ((ei = rn->info) != NULL)
805 {
806 if (add_to_ospf)
807 {
808 if (ospf_external_info_find_lsa (ospf, &ei->p))
809 if (!ospf_distribute_check_connected (ospf, ei))
810 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
Paul Jakma8a667cf2009-08-27 16:51:42 +0100811 ei->ifindex /*, ei->nexthop */);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200812 }
813 else
814 {
815 if (!ospf_external_info_find_lsa (ospf, &ei->p))
816 if (ospf_distribute_check_connected (ospf, ei))
817 ospf_external_lsa_originate (ospf, ei);
818 }
819 }
820}
821
822static void
paul68980082003-03-25 05:07:42 +0000823ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000824{
paul68980082003-03-25 05:07:42 +0000825 ospf_area_check_free (ospf, network->area_id);
826 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000827 XFREE (MTYPE_OSPF_NETWORK, network);
828}
829
830int
831ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
832 struct in_addr area_id)
833{
834 struct ospf_network *network;
835 struct ospf_area *area;
836 struct route_node *rn;
paul147193a2003-04-19 00:31:59 +0000837 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000838
839 rn = route_node_get (ospf->networks, (struct prefix *)p);
840 if (rn->info)
841 {
842 /* There is already same network statement. */
843 route_unlock_node (rn);
844 return 0;
845 }
846
847 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000848 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000849
850 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100851 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000852
853 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100854 update_redistributed(ospf, 1);
855
paul68980082003-03-25 05:07:42 +0000856 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000857
858 return 1;
859}
860
861int
862ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
863 struct in_addr area_id)
864{
865 struct route_node *rn;
866 struct ospf_network *network;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100867 struct listnode *node, *nnode;
868 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000869
870 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
871 if (rn == NULL)
872 return 0;
873
874 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700875 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000876 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
877 return 0;
878
paul68980082003-03-25 05:07:42 +0000879 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000880 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700881 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000882
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100883 /* Find interfaces that not configured already. */
884 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
885 {
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100886 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
887 continue;
888
Paul Jakma8a667cf2009-08-27 16:51:42 +0100889 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100890 }
paul718e3742002-12-13 20:15:29 +0000891
892 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100893 update_redistributed(ospf, 0);
894
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200895 ospf_area_check_free (ospf, area_id);
Paul Jakma8a667cf2009-08-27 16:51:42 +0100896
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200897 return 1;
898}
899
Paul Jakma8a667cf2009-08-27 16:51:42 +0100900/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
901 * there might not be any 'router ospf' config.
902 *
903 * Otherwise, doesn't do anything different to ospf_if_update for now
904 */
905void
906ospf_interface_area_set (struct interface *ifp)
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200907{
Paul Jakma8a667cf2009-08-27 16:51:42 +0100908 struct ospf *ospf = ospf_get();
909
910 ospf_if_update (ospf, ifp);
911 /* if_update does a update_redistributed */
912
913 return;
914}
915
916void
917ospf_interface_area_unset (struct interface *ifp)
918{
919 struct route_node *rn_oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200920 struct ospf *ospf;
921
922 if ((ospf = ospf_lookup ()) == NULL)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100923 return; /* Ospf not ready yet */
924
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200925 /* Find interfaces that may need to be removed. */
926 for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
927 {
928 struct ospf_interface *oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200929
930 if ( (oi = rn_oi->info) == NULL)
931 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100932
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200933 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
934 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100935
936 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200937 }
938
939 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100940 update_redistributed (ospf, 0); /* interfaces possibly removed */
941
942 return;
943}
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200944
945
paul570f7592003-01-25 06:47:41 +0000946/* Check whether interface matches given network
947 * returns: 1, true. 0, false
948 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300949static int
950ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000951{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000952 /* new approach: more elegant and conceptually clean */
953 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000954}
955
Stephen Hemminger917e2992009-12-03 19:07:00 +0300956static void
Paul Jakma8a667cf2009-08-27 16:51:42 +0100957ospf_update_interface_area (struct connected *co, struct ospf_area *area)
958{
959 struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
960
961 /* nothing to be done case */
962 if (oi && oi->area == area)
963 return;
964
965 if (oi)
966 ospf_if_free (oi);
967
968 add_ospf_interface (co, area);
969}
970
971/* Run OSPF for the given subnet, taking into account the following
972 * possible sources of area configuration, in the given order of preference:
973 *
974 * - Whether there is interface+address specific area configuration
975 * - Whether there is a default area for the interface
976 * - Whether there is an area given as a parameter.
977 * - If no specific network prefix/area is supplied, whether there's
978 * a matching network configured.
979 */
980static void
981ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
982 struct prefix *p, struct ospf_area *given_area)
983{
984 struct ospf_interface *oi;
985 struct ospf_if_params *params;
986 struct ospf_area *area = NULL;
987 struct route_node *rn;
988 int configed = 0;
989
990 if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
991 return;
992
993 if (co->address->family != AF_INET)
994 return;
995
996 /* Try determine the appropriate area for this interface + address
997 * Start by checking interface config
998 */
999 if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
1000 params = IF_DEF_PARAMS (co->ifp);
1001
1002 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
1003 area = (ospf_area_get (ospf, params->if_area,
1004 OSPF_AREA_ID_FORMAT_ADDRESS));
1005
1006 /* If we've found an interface and/or addr specific area, then we're
1007 * done
1008 */
1009 if (area)
1010 {
1011 ospf_update_interface_area (co, area);
1012 return;
1013 }
1014
1015 /* Otherwise, only remaining possibility is a matching network statement */
1016 if (p)
1017 {
1018 assert (given_area != NULL);
1019
1020 /* Which either was supplied as a parameter.. (e.g. cause a new
1021 * network/area was just added)..
1022 */
1023 if (p->family == co->address->family
1024 && ospf_network_match_iface (co, p))
1025 ospf_update_interface_area (co, given_area);
1026
1027 return;
1028 }
1029
1030 /* Else we have to search the existing network/area config to see
1031 * if any match..
1032 */
1033 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1034 if (rn->info != NULL
1035 && ospf_network_match_iface (co, &rn->p))
1036 {
1037 struct ospf_network *network = (struct ospf_network *) rn->info;
1038 area = ospf_area_get (ospf, network->area_id, network->format);
1039 ospf_update_interface_area (co, area);
1040 configed = 1;
1041 }
1042
1043 /* If the subnet isn't in any area, deconfigure */
1044 if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
1045 ospf_if_free (oi);
1046}
1047
1048static void
1049ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
1050 struct prefix *p,
1051 struct ospf_area *given_area)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001052{
1053 struct listnode *cnode;
1054 struct connected *co;
1055
1056 if (memcmp (ifp->name, "VLINK", 5) == 0)
1057 return;
1058
Paul Jakma8a667cf2009-08-27 16:51:42 +01001059 /* Network prefix without area is nonsensical */
1060 if (p)
1061 assert (given_area != NULL);
1062
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001063 /* if interface prefix is match specified prefix,
1064 then create socket and join multicast group. */
1065 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001066 ospf_network_run_subnet (ospf, co, p, given_area);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001067}
1068
Stephen Hemminger917e2992009-12-03 19:07:00 +03001069static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001070ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001071{
1072 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00001073 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001074
1075 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001076 if (area->ospf->router_id.s_addr == 0)
1077 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +00001078
paul718e3742002-12-13 20:15:29 +00001079 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +00001080 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001081 ospf_network_run_interface (area->ospf, ifp, p, area);
paul718e3742002-12-13 20:15:29 +00001082}
1083
1084void
1085ospf_ls_upd_queue_empty (struct ospf_interface *oi)
1086{
1087 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00001088 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +00001089 struct list *lst;
paul718e3742002-12-13 20:15:29 +00001090 struct ospf_lsa *lsa;
1091
1092 /* empty ls update queue */
1093 for (rn = route_top (oi->ls_upd_queue); rn;
1094 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +00001095 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +00001096 {
paul1eb8ef22005-04-07 07:30:20 +00001097 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001098 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00001099 list_free (lst);
1100 rn->info = NULL;
1101 }
1102
1103 /* remove update event */
1104 if (oi->t_ls_upd_event)
1105 {
1106 thread_cancel (oi->t_ls_upd_event);
1107 oi->t_ls_upd_event = NULL;
1108 }
1109}
1110
1111void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001112ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +00001113{
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001114 if (!ospf)
1115 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001116
Paul Jakma8a667cf2009-08-27 16:51:42 +01001117 /* OSPF must be ready. */
1118 if (!ospf_is_ready (ospf))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001119 return;
Joakim Tjernlund738bce72009-08-07 13:48:15 +02001120
Paul Jakma8a667cf2009-08-27 16:51:42 +01001121 ospf_network_run_interface (ospf, ifp, NULL, NULL);
1122
1123 /* Update connected redistribute. */
1124 update_redistributed(ospf, 1);
paul718e3742002-12-13 20:15:29 +00001125}
1126
1127void
paul68980082003-03-25 05:07:42 +00001128ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001129{
paul1eb8ef22005-04-07 07:30:20 +00001130 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001131 struct ospf_vl_data *vl_data;
1132
paul1eb8ef22005-04-07 07:30:20 +00001133 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1134 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1135 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001136}
1137
David Lamparter6b0655a2014-06-04 06:53:35 +02001138
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001139static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001140{
1141 { OSPF_AREA_DEFAULT, "Default" },
1142 { OSPF_AREA_STUB, "Stub" },
1143 { OSPF_AREA_NSSA, "NSSA" },
1144};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001145static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001146
paul4dadc292005-05-06 21:37:42 +00001147static void
paul718e3742002-12-13 20:15:29 +00001148ospf_area_type_set (struct ospf_area *area, int type)
1149{
hasso52dc7ee2004-09-23 19:18:23 +00001150 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001151 struct ospf_interface *oi;
1152
1153 if (area->external_routing == type)
1154 {
1155 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001156 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001157 inet_ntoa (area->area_id));
1158 return;
1159 }
1160
1161 area->external_routing = type;
1162
1163 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001164 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001165 LOOKUP (ospf_area_type_msg, type));
1166
1167 switch (area->external_routing)
1168 {
1169 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001170 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1171 if (oi->nbr_self != NULL)
1172 {
1173 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1174 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1175 }
paul718e3742002-12-13 20:15:29 +00001176 break;
1177 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001178 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1179 if (oi->nbr_self != NULL)
1180 {
1181 if (IS_DEBUG_OSPF_EVENT)
1182 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1183 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1184 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1185 if (IS_DEBUG_OSPF_EVENT)
1186 zlog_debug ("options set on %s: %x",
1187 IF_NAME (oi), OPTIONS (oi));
1188 }
paul718e3742002-12-13 20:15:29 +00001189 break;
1190 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001191 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1192 if (oi->nbr_self != NULL)
1193 {
1194 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1195 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1196 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1197 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1198 }
paul718e3742002-12-13 20:15:29 +00001199 break;
1200 default:
1201 break;
1202 }
1203
Paul Jakmac363d382010-01-24 22:42:13 +00001204 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001205 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001206}
1207
1208int
paul68980082003-03-25 05:07:42 +00001209ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001210{
1211 if (area->shortcut_configured == mode)
1212 return 0;
1213
1214 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001215 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001216 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001217
paul68980082003-03-25 05:07:42 +00001218 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001219
1220 return 1;
1221}
1222
1223int
paul68980082003-03-25 05:07:42 +00001224ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001225{
1226 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001227 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001228 ospf_area_check_free (ospf, area->area_id);
1229 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001230
1231 return 1;
1232}
1233
paul4dadc292005-05-06 21:37:42 +00001234static int
paul718e3742002-12-13 20:15:29 +00001235ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1236{
1237 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001238 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001239 int count = 0;
1240
paul1eb8ef22005-04-07 07:30:20 +00001241 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1242 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1243 count++;
paul718e3742002-12-13 20:15:29 +00001244
1245 return count;
1246}
1247
1248int
1249ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1250{
1251 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001252 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001253
paul68980082003-03-25 05:07:42 +00001254 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001255 if (ospf_area_vlink_count (ospf, area))
1256 return 0;
1257
1258 if (area->external_routing != OSPF_AREA_STUB)
1259 ospf_area_type_set (area, OSPF_AREA_STUB);
1260
1261 return 1;
1262}
1263
1264int
1265ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1266{
1267 struct ospf_area *area;
1268
paul68980082003-03-25 05:07:42 +00001269 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001270 if (area == NULL)
1271 return 1;
1272
1273 if (area->external_routing == OSPF_AREA_STUB)
1274 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1275
paul68980082003-03-25 05:07:42 +00001276 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001277
1278 return 1;
1279}
1280
1281int
1282ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1283{
1284 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001285 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001286
paul68980082003-03-25 05:07:42 +00001287 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001288 area->no_summary = 1;
1289
1290 return 1;
1291}
1292
1293int
1294ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1295{
1296 struct ospf_area *area;
1297
paul68980082003-03-25 05:07:42 +00001298 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001299 if (area == NULL)
1300 return 0;
1301
1302 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001303 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001304
1305 return 1;
1306}
1307
1308int
1309ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1310{
1311 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001312 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001313
paul68980082003-03-25 05:07:42 +00001314 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001315 if (ospf_area_vlink_count (ospf, area))
1316 return 0;
1317
1318 if (area->external_routing != OSPF_AREA_NSSA)
1319 {
1320 ospf_area_type_set (area, OSPF_AREA_NSSA);
1321 ospf->anyNSSA++;
1322 }
1323
paul084c7842003-06-22 08:35:18 +00001324 /* set NSSA area defaults */
1325 area->no_summary = 0;
1326 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001327 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001328 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1329
paul718e3742002-12-13 20:15:29 +00001330 return 1;
1331}
1332
1333int
1334ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1335{
1336 struct ospf_area *area;
1337
paul68980082003-03-25 05:07:42 +00001338 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001339 if (area == NULL)
1340 return 0;
1341
1342 if (area->external_routing == OSPF_AREA_NSSA)
1343 {
1344 ospf->anyNSSA--;
1345 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1346 }
1347
paul68980082003-03-25 05:07:42 +00001348 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001349
1350 return 1;
1351}
1352
1353int
1354ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1355 int role)
1356{
1357 struct ospf_area *area;
1358
paul68980082003-03-25 05:07:42 +00001359 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001360 if (area == NULL)
1361 return 0;
1362
paul084c7842003-06-22 08:35:18 +00001363 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001364
1365 return 1;
1366}
1367
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001368#if 0
paul4dadc292005-05-06 21:37:42 +00001369/* XXX: unused? Leave for symmetry? */
1370static int
paul718e3742002-12-13 20:15:29 +00001371ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1372 struct in_addr area_id)
1373{
1374 struct ospf_area *area;
1375
paul68980082003-03-25 05:07:42 +00001376 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001377 if (area == NULL)
1378 return 0;
1379
paul084c7842003-06-22 08:35:18 +00001380 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001381
paul68980082003-03-25 05:07:42 +00001382 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001383
1384 return 1;
1385}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001386#endif
paul718e3742002-12-13 20:15:29 +00001387
1388int
paul68980082003-03-25 05:07:42 +00001389ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001390 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001391{
1392 struct access_list *list;
1393 list = access_list_lookup (AFI_IP, list_name);
1394
1395 EXPORT_LIST (area) = list;
1396
1397 if (EXPORT_NAME (area))
1398 free (EXPORT_NAME (area));
1399
1400 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001401 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001402
1403 return 1;
1404}
1405
1406int
paul68980082003-03-25 05:07:42 +00001407ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001408{
1409
1410 EXPORT_LIST (area) = 0;
1411
1412 if (EXPORT_NAME (area))
1413 free (EXPORT_NAME (area));
1414
1415 EXPORT_NAME (area) = NULL;
1416
paul68980082003-03-25 05:07:42 +00001417 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001418
paul68980082003-03-25 05:07:42 +00001419 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001420
1421 return 1;
1422}
1423
1424int
paul6c835672004-10-11 11:00:30 +00001425ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1426 const char *name)
paul718e3742002-12-13 20:15:29 +00001427{
1428 struct access_list *list;
1429 list = access_list_lookup (AFI_IP, name);
1430
1431 IMPORT_LIST (area) = list;
1432
1433 if (IMPORT_NAME (area))
1434 free (IMPORT_NAME (area));
1435
1436 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001437 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001438
1439 return 1;
1440}
1441
1442int
paul68980082003-03-25 05:07:42 +00001443ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001444{
1445 IMPORT_LIST (area) = 0;
1446
1447 if (IMPORT_NAME (area))
1448 free (IMPORT_NAME (area));
1449
1450 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001451 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001452
paul68980082003-03-25 05:07:42 +00001453 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001454
1455 return 1;
1456}
1457
1458int
paul718e3742002-12-13 20:15:29 +00001459ospf_timers_refresh_set (struct ospf *ospf, int interval)
1460{
1461 int time_left;
1462
1463 if (ospf->lsa_refresh_interval == interval)
1464 return 1;
1465
1466 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001467 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001468
1469 if (time_left > interval)
1470 {
1471 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1472 ospf->t_lsa_refresher =
1473 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1474 }
1475 ospf->lsa_refresh_interval = interval;
1476
1477 return 1;
1478}
1479
1480int
1481ospf_timers_refresh_unset (struct ospf *ospf)
1482{
1483 int time_left;
1484
1485 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001486 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001487
1488 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1489 {
1490 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1491 ospf->t_lsa_refresher =
1492 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1493 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1494 }
1495
1496 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1497
1498 return 1;
1499}
1500
David Lamparter6b0655a2014-06-04 06:53:35 +02001501
paul4dadc292005-05-06 21:37:42 +00001502static struct ospf_nbr_nbma *
1503ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001504{
1505 struct ospf_nbr_nbma *nbr_nbma;
1506
Stephen Hemminger393deb92008-08-18 14:13:29 -07001507 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001508 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001509
1510 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1511 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1512
1513 return nbr_nbma;
1514}
1515
paul4dadc292005-05-06 21:37:42 +00001516static void
paul718e3742002-12-13 20:15:29 +00001517ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1518{
1519 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1520}
1521
paul4dadc292005-05-06 21:37:42 +00001522static void
paul718e3742002-12-13 20:15:29 +00001523ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1524{
1525 struct route_node *rn;
1526 struct prefix_ipv4 p;
1527
1528 p.family = AF_INET;
1529 p.prefix = nbr_nbma->addr;
1530 p.prefixlen = IPV4_MAX_BITLEN;
1531
1532 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1533 if (rn)
1534 {
1535 ospf_nbr_nbma_free (rn->info);
1536 rn->info = NULL;
1537 route_unlock_node (rn);
1538 route_unlock_node (rn);
1539 }
1540}
1541
paul4dadc292005-05-06 21:37:42 +00001542static void
paul718e3742002-12-13 20:15:29 +00001543ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1544{
1545 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1546
1547 if (nbr_nbma->nbr)
1548 {
1549 nbr_nbma->nbr->nbr_nbma = NULL;
1550 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1551 }
1552
1553 if (nbr_nbma->oi)
1554 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1555}
1556
paul4dadc292005-05-06 21:37:42 +00001557static void
paul718e3742002-12-13 20:15:29 +00001558ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1559 struct ospf_interface *oi)
1560{
1561 struct ospf_neighbor *nbr;
1562 struct route_node *rn;
1563 struct prefix p;
1564
1565 if (oi->type != OSPF_IFTYPE_NBMA)
1566 return;
1567
1568 if (nbr_nbma->nbr != NULL)
1569 return;
1570
1571 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1572 return;
1573
1574 nbr_nbma->oi = oi;
1575 listnode_add (oi->nbr_nbma, nbr_nbma);
1576
1577 /* Get neighbor information from table. */
1578 p.family = AF_INET;
1579 p.prefixlen = IPV4_MAX_BITLEN;
1580 p.u.prefix4 = nbr_nbma->addr;
1581
1582 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1583 if (rn->info)
1584 {
1585 nbr = rn->info;
1586 nbr->nbr_nbma = nbr_nbma;
1587 nbr_nbma->nbr = nbr;
1588
1589 route_unlock_node (rn);
1590 }
1591 else
1592 {
1593 nbr = rn->info = ospf_nbr_new (oi);
1594 nbr->state = NSM_Down;
1595 nbr->src = nbr_nbma->addr;
1596 nbr->nbr_nbma = nbr_nbma;
1597 nbr->priority = nbr_nbma->priority;
1598 nbr->address = p;
1599
1600 nbr_nbma->nbr = nbr;
1601
1602 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1603 }
1604}
1605
1606void
paul68980082003-03-25 05:07:42 +00001607ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001608{
1609 struct ospf_nbr_nbma *nbr_nbma;
1610 struct route_node *rn;
1611 struct prefix_ipv4 p;
1612
1613 if (oi->type != OSPF_IFTYPE_NBMA)
1614 return;
1615
paul68980082003-03-25 05:07:42 +00001616 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001617 if ((nbr_nbma = rn->info))
1618 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1619 {
1620 p.family = AF_INET;
1621 p.prefix = nbr_nbma->addr;
1622 p.prefixlen = IPV4_MAX_BITLEN;
1623
1624 if (prefix_match (oi->address, (struct prefix *)&p))
1625 ospf_nbr_nbma_add (nbr_nbma, oi);
1626 }
1627}
1628
1629struct ospf_nbr_nbma *
1630ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1631{
1632 struct route_node *rn;
1633 struct prefix_ipv4 p;
1634
1635 p.family = AF_INET;
1636 p.prefix = nbr_addr;
1637 p.prefixlen = IPV4_MAX_BITLEN;
1638
1639 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1640 if (rn)
1641 {
1642 route_unlock_node (rn);
1643 return rn->info;
1644 }
1645 return NULL;
1646}
1647
1648struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001649ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001650{
1651#if 0
1652 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001653 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001654#endif
1655
paul68980082003-03-25 05:07:42 +00001656 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001657 return NULL;
1658
1659#if 0
paul1eb8ef22005-04-07 07:30:20 +00001660 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001661 {
paul718e3742002-12-13 20:15:29 +00001662 if (first)
1663 {
1664 *addr = nbr_nbma->addr;
1665 return nbr_nbma;
1666 }
1667 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1668 {
1669 *addr = nbr_nbma->addr;
1670 return nbr_nbma;
1671 }
1672 }
1673#endif
1674 return NULL;
1675}
1676
1677int
1678ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1679{
1680 struct ospf_nbr_nbma *nbr_nbma;
1681 struct ospf_interface *oi;
1682 struct prefix_ipv4 p;
1683 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001684 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001685
1686 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1687 if (nbr_nbma)
1688 return 0;
1689
1690 nbr_nbma = ospf_nbr_nbma_new ();
1691 nbr_nbma->addr = nbr_addr;
1692
1693 p.family = AF_INET;
1694 p.prefix = nbr_addr;
1695 p.prefixlen = IPV4_MAX_BITLEN;
1696
1697 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
Joakim Tjernlund4de398e2010-03-08 13:58:14 +01001698 if (rn->info)
1699 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001700 rn->info = nbr_nbma;
1701
paul1eb8ef22005-04-07 07:30:20 +00001702 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001703 {
paul718e3742002-12-13 20:15:29 +00001704 if (oi->type == OSPF_IFTYPE_NBMA)
1705 if (prefix_match (oi->address, (struct prefix *)&p))
1706 {
1707 ospf_nbr_nbma_add (nbr_nbma, oi);
1708 break;
1709 }
1710 }
1711
1712 return 1;
1713}
1714
1715int
1716ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1717{
1718 struct ospf_nbr_nbma *nbr_nbma;
1719
1720 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1721 if (nbr_nbma == NULL)
1722 return 0;
1723
1724 ospf_nbr_nbma_down (nbr_nbma);
1725 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1726
1727 return 1;
1728}
1729
1730int
1731ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1732 u_char priority)
1733{
1734 struct ospf_nbr_nbma *nbr_nbma;
1735
1736 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1737 if (nbr_nbma == NULL)
1738 return 0;
1739
1740 if (nbr_nbma->priority != priority)
1741 nbr_nbma->priority = priority;
1742
1743 return 1;
1744}
1745
1746int
1747ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1748{
1749 struct ospf_nbr_nbma *nbr_nbma;
1750
1751 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1752 if (nbr_nbma == NULL)
1753 return 0;
1754
1755 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1756 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1757
1758 return 1;
1759}
1760
1761int
1762ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001763 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001764{
1765 struct ospf_nbr_nbma *nbr_nbma;
1766
1767 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1768 if (nbr_nbma == NULL)
1769 return 0;
1770
1771 if (nbr_nbma->v_poll != interval)
1772 {
1773 nbr_nbma->v_poll = interval;
1774 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1775 {
1776 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1777 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1778 nbr_nbma->v_poll);
1779 }
1780 }
1781
1782 return 1;
1783}
1784
1785int
1786ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1787{
1788 struct ospf_nbr_nbma *nbr_nbma;
1789
1790 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1791 if (nbr_nbma == NULL)
1792 return 0;
1793
1794 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1795 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1796
1797 return 1;
1798}
1799
paul718e3742002-12-13 20:15:29 +00001800void
paul020709f2003-04-04 02:44:16 +00001801ospf_master_init ()
1802{
1803 memset (&ospf_master, 0, sizeof (struct ospf_master));
1804
1805 om = &ospf_master;
1806 om->ospf = list_new ();
1807 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001808 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001809}