blob: 98d6d77a546e63d8dc63571a370d3e5e7efdbc36 [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;
Piotr Chytła2b2e38c2015-12-01 10:10:41 -0500200 new->dtag[i] = 0;
paul718e3742002-12-13 20:15:29 +0000201 }
202 new->default_metric = -1;
203 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
204
Michael Rossberg2ef762e2015-07-27 07:56:25 +0200205 /* LSA timers */
206 new->min_ls_interval = OSPF_MIN_LS_INTERVAL;
207 new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
208
paul718e3742002-12-13 20:15:29 +0000209 /* SPF timer value init. */
210 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
211 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000212 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
213 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000214
215 /* MaxAge init. */
Dinesh Dutt2449fcd2013-08-24 07:54:17 +0000216 new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800217 new->maxage_lsa = route_table_init();
paul718e3742002-12-13 20:15:29 +0000218 new->t_maxage_walker =
219 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000220 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000221
222 /* Distance table init. */
223 new->distance_table = route_table_init ();
224
225 new->lsa_refresh_queue.index = 0;
226 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
227 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
228 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000229 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000230
ajs5c333492005-02-23 15:43:01 +0000231 if ((new->fd = ospf_sock_init()) < 0)
232 {
233 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
234 "a socket");
235 exit(1);
236 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000237 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
238 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
Andrew Certain0798cee2012-12-04 13:43:42 -0800239 zlog_debug ("%s: starting with OSPF send buffer size %u",
Denis Ovsienkof102e752007-09-18 09:01:13 +0000240 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000241 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
242 {
243 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
244 OSPF_MAX_PACKET_SIZE+1);
245 exit(1);
246 }
247 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000248 new->oi_write_q = list_new ();
249
250 return new;
251}
252
253struct ospf *
paul020709f2003-04-04 02:44:16 +0000254ospf_lookup ()
255{
256 if (listcount (om->ospf) == 0)
257 return NULL;
258
Olivier Dugeon29a14012016-04-19 18:42:40 +0200259 return listgetdata ((struct listnode *)listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000260}
261
Paul Jakma8a667cf2009-08-27 16:51:42 +0100262static int
263ospf_is_ready (struct ospf *ospf)
264{
265 /* OSPF must be on and Router-ID must be configured. */
266 if (!ospf || ospf->router_id.s_addr == 0)
267 return 0;
268
269 return 1;
270}
271
paul4dadc292005-05-06 21:37:42 +0000272static void
paul020709f2003-04-04 02:44:16 +0000273ospf_add (struct ospf *ospf)
274{
275 listnode_add (om->ospf, ospf);
276}
277
paul4dadc292005-05-06 21:37:42 +0000278static void
paul020709f2003-04-04 02:44:16 +0000279ospf_delete (struct ospf *ospf)
280{
281 listnode_delete (om->ospf, ospf);
282}
283
284struct ospf *
paul718e3742002-12-13 20:15:29 +0000285ospf_get ()
286{
paul020709f2003-04-04 02:44:16 +0000287 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000288
paul020709f2003-04-04 02:44:16 +0000289 ospf = ospf_lookup ();
290 if (ospf == NULL)
291 {
292 ospf = ospf_new ();
293 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000294
paul020709f2003-04-04 02:44:16 +0000295 if (ospf->router_id_static.s_addr == 0)
296 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000297
paul020709f2003-04-04 02:44:16 +0000298 ospf_opaque_type11_lsa_init (ospf);
paul020709f2003-04-04 02:44:16 +0000299 }
paul68980082003-03-25 05:07:42 +0000300
301 return ospf;
paul718e3742002-12-13 20:15:29 +0000302}
David Lamparter6b0655a2014-06-04 06:53:35 +0200303
paulc9c93d52005-11-26 13:31:11 +0000304/* Handle the second half of deferred shutdown. This is called either
305 * from the deferred-shutdown timer thread, or directly through
306 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000307 *
308 * Function is to cleanup G-R state, if required then call ospf_finish_final
309 * to complete shutdown of this ospf instance. Possibly exit if the
310 * whole process is being shutdown and this was the last OSPF instance.
311 */
312static void
paulc9c93d52005-11-26 13:31:11 +0000313ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000314{
315 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000316 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000317
318 ospf_finish_final (ospf);
319
320 /* *ospf is now invalid */
321
322 /* ospfd being shut-down? If so, was this the last ospf instance? */
323 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
324 && (listcount (om->ospf) == 0))
325 exit (0);
326
327 return;
328}
329
330/* Timer thread for G-R */
331static int
paulc9c93d52005-11-26 13:31:11 +0000332ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000333{
334 struct ospf *ospf = THREAD_ARG(t);
335
paulc9c93d52005-11-26 13:31:11 +0000336 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000337
338 return 0;
339}
340
paulc9c93d52005-11-26 13:31:11 +0000341/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000342 * down directly into second-half of instance shutdown.
343 */
344static void
paulc9c93d52005-11-26 13:31:11 +0000345ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000346{
347 unsigned long timeout;
348 struct listnode *ln;
349 struct ospf_area *area;
350
paulc9c93d52005-11-26 13:31:11 +0000351 /* deferred shutdown already running? */
352 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000353 return;
354
355 /* Should we try push out max-metric LSAs? */
356 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
357 {
358 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
359 {
360 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
361
362 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000363 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000364 }
365 timeout = ospf->stub_router_shutdown_time;
366 }
367 else
paulc9c93d52005-11-26 13:31:11 +0000368 {
369 /* No timer needed */
370 ospf_deferred_shutdown_finish (ospf);
371 return;
372 }
paul88d6cf32005-10-29 12:50:09 +0000373
paulc9c93d52005-11-26 13:31:11 +0000374 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000375 timeout);
376 return;
377}
David Lamparter6b0655a2014-06-04 06:53:35 +0200378
paul88d6cf32005-10-29 12:50:09 +0000379/* Shut down the entire process */
380void
381ospf_terminate (void)
382{
383 struct ospf *ospf;
384 struct listnode *node, *nnode;
385
386 /* shutdown already in progress */
387 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
388 return;
389
390 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
391
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000392 /* exit immediately if OSPF not actually running */
393 if (listcount(om->ospf) == 0)
394 exit(0);
395
paul88d6cf32005-10-29 12:50:09 +0000396 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
397 ospf_finish (ospf);
398
399 /* Deliberately go back up, hopefully to thread scheduler, as
400 * One or more ospf_finish()'s may have deferred shutdown to a timer
401 * thread
402 */
403}
paul718e3742002-12-13 20:15:29 +0000404
405void
406ospf_finish (struct ospf *ospf)
407{
paulc9c93d52005-11-26 13:31:11 +0000408 /* let deferred shutdown decide */
409 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000410
paulc9c93d52005-11-26 13:31:11 +0000411 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000412 * deferred to expiry of G-S timer thread. Return back up, hopefully
413 * to thread scheduler.
414 */
paulc9c93d52005-11-26 13:31:11 +0000415 return;
paul88d6cf32005-10-29 12:50:09 +0000416}
417
418/* Final cleanup of ospf instance */
419static void
420ospf_finish_final (struct ospf *ospf)
421{
paul718e3742002-12-13 20:15:29 +0000422 struct route_node *rn;
423 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000424 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000425 struct ospf_interface *oi;
426 struct ospf_area *area;
427 struct ospf_vl_data *vl_data;
428 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000429 int i;
430
paul718e3742002-12-13 20:15:29 +0000431 ospf_opaque_type11_lsa_term (ospf);
paul88d6cf32005-10-29 12:50:09 +0000432
433 /* be nice if this worked, but it doesn't */
434 /*ospf_flush_self_originated_lsas_now (ospf);*/
435
436 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000437 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000438 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000439 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000440
paul1eb8ef22005-04-07 07:30:20 +0000441 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
442 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000443
paul1eb8ef22005-04-07 07:30:20 +0000444 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
445 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000446
447 list_delete (ospf->vlinks);
448
449 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000450 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
451 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000452
453 /* Clear static neighbors */
454 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
455 if ((nbr_nbma = rn->info))
456 {
457 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
458
459 if (nbr_nbma->nbr)
460 {
461 nbr_nbma->nbr->nbr_nbma = NULL;
462 nbr_nbma->nbr = NULL;
463 }
464
465 if (nbr_nbma->oi)
466 {
467 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
468 nbr_nbma->oi = NULL;
469 }
470
471 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
472 }
473
474 route_table_finish (ospf->nbr_nbma);
475
476 /* Clear networks and Areas. */
477 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
478 {
479 struct ospf_network *network;
480
481 if ((network = rn->info) != NULL)
482 {
paul68980082003-03-25 05:07:42 +0000483 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000484 rn->info = NULL;
485 route_unlock_node (rn);
486 }
487 }
488
paul1eb8ef22005-04-07 07:30:20 +0000489 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000490 {
paul718e3742002-12-13 20:15:29 +0000491 listnode_delete (ospf->areas, area);
492 ospf_area_free (area);
493 }
494
495 /* Cancel all timers. */
496 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000497 OSPF_TIMER_OFF (ospf->t_spf_calc);
498 OSPF_TIMER_OFF (ospf->t_ase_calc);
499 OSPF_TIMER_OFF (ospf->t_maxage);
500 OSPF_TIMER_OFF (ospf->t_maxage_walker);
501 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000502 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000503 OSPF_TIMER_OFF (ospf->t_distribute_update);
504 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
505 OSPF_TIMER_OFF (ospf->t_read);
506 OSPF_TIMER_OFF (ospf->t_write);
paul88d6cf32005-10-29 12:50:09 +0000507 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul718e3742002-12-13 20:15:29 +0000508
509 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000510 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000511
paul68980082003-03-25 05:07:42 +0000512 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
513 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul68980082003-03-25 05:07:42 +0000514 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
515 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
516
paul718e3742002-12-13 20:15:29 +0000517 ospf_lsdb_delete_all (ospf->lsdb);
518 ospf_lsdb_free (ospf->lsdb);
519
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800520 for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn))
521 {
522 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000523
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800524 if ((lsa = rn->info) != NULL)
525 {
526 ospf_lsa_unlock (&lsa);
527 rn->info = NULL;
528 }
529 route_unlock_node (rn);
530 }
531 route_table_finish (ospf->maxage_lsa);
paul718e3742002-12-13 20:15:29 +0000532
533 if (ospf->old_table)
534 ospf_route_table_free (ospf->old_table);
535 if (ospf->new_table)
536 {
537 ospf_route_delete (ospf->new_table);
538 ospf_route_table_free (ospf->new_table);
539 }
540 if (ospf->old_rtrs)
541 ospf_rtrs_free (ospf->old_rtrs);
542 if (ospf->new_rtrs)
543 ospf_rtrs_free (ospf->new_rtrs);
544 if (ospf->new_external_route)
545 {
546 ospf_route_delete (ospf->new_external_route);
547 ospf_route_table_free (ospf->new_external_route);
548 }
549 if (ospf->old_external_route)
550 {
551 ospf_route_delete (ospf->old_external_route);
552 ospf_route_table_free (ospf->old_external_route);
553 }
554 if (ospf->external_lsas)
555 {
556 ospf_ase_external_lsas_finish (ospf->external_lsas);
557 }
558
559 list_delete (ospf->areas);
560
561 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
562 if (EXTERNAL_INFO (i) != NULL)
563 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
564 {
565 if (rn->info == NULL)
566 continue;
567
568 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
569 rn->info = NULL;
570 route_unlock_node (rn);
571 }
572
paul68980082003-03-25 05:07:42 +0000573 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000574 route_table_finish (ospf->distance_table);
575
paul020709f2003-04-04 02:44:16 +0000576 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000577
paul020709f2003-04-04 02:44:16 +0000578 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000579}
580
David Lamparter6b0655a2014-06-04 06:53:35 +0200581
paul718e3742002-12-13 20:15:29 +0000582/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000583static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000584ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000585{
586 struct ospf_area *new;
587
588 /* Allocate new config_network. */
589 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
590
paul68980082003-03-25 05:07:42 +0000591 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000592
593 new->area_id = area_id;
594
595 new->external_routing = OSPF_AREA_DEFAULT;
596 new->default_cost = 1;
597 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000598
paul718e3742002-12-13 20:15:29 +0000599 /* New LSDB init. */
600 new->lsdb = ospf_lsdb_new ();
601
602 /* Self-originated LSAs initialize. */
603 new->router_lsa_self = NULL;
604
paul718e3742002-12-13 20:15:29 +0000605 ospf_opaque_type10_lsa_init (new);
paul718e3742002-12-13 20:15:29 +0000606
607 new->oiflist = list_new ();
608 new->ranges = route_table_init ();
609
610 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000611 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000612
613 return new;
614}
615
Stephen Hemminger917e2992009-12-03 19:07:00 +0300616static void
paul718e3742002-12-13 20:15:29 +0000617ospf_area_free (struct ospf_area *area)
618{
paul68980082003-03-25 05:07:42 +0000619 struct route_node *rn;
620 struct ospf_lsa *lsa;
621
paul718e3742002-12-13 20:15:29 +0000622 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000623 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
624 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
625 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
626 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
627 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
628 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
629 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
630 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000631
paul68980082003-03-25 05:07:42 +0000632 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
633 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul68980082003-03-25 05:07:42 +0000634 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
635 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
636 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
637 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000638
639 ospf_lsdb_delete_all (area->lsdb);
640 ospf_lsdb_free (area->lsdb);
641
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000642 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000643
644 route_table_finish (area->ranges);
645 list_delete (area->oiflist);
646
647 if (EXPORT_NAME (area))
648 free (EXPORT_NAME (area));
649
650 if (IMPORT_NAME (area))
651 free (IMPORT_NAME (area));
652
653 /* Cancel timer. */
paul88d6cf32005-10-29 12:50:09 +0000654 OSPF_TIMER_OFF (area->t_stub_router);
paul88d6cf32005-10-29 12:50:09 +0000655 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000656
paul718e3742002-12-13 20:15:29 +0000657 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000658 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000659
660 XFREE (MTYPE_OSPF_AREA, area);
661}
662
663void
paul68980082003-03-25 05:07:42 +0000664ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000665{
666 struct ospf_area *area;
667
paul68980082003-03-25 05:07:42 +0000668 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000669 if (area &&
670 listcount (area->oiflist) == 0 &&
671 area->ranges->top == NULL &&
672 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
673 area->external_routing == OSPF_AREA_DEFAULT &&
674 area->no_summary == 0 &&
675 area->default_cost == 1 &&
676 EXPORT_NAME (area) == NULL &&
677 IMPORT_NAME (area) == NULL &&
678 area->auth_type == OSPF_AUTH_NULL)
679 {
paul68980082003-03-25 05:07:42 +0000680 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000681 ospf_area_free (area);
682 }
683}
684
685struct ospf_area *
paul68980082003-03-25 05:07:42 +0000686ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000687{
688 struct ospf_area *area;
689
paul68980082003-03-25 05:07:42 +0000690 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000691 if (!area)
692 {
paul68980082003-03-25 05:07:42 +0000693 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000694 area->format = format;
paul68980082003-03-25 05:07:42 +0000695 listnode_add_sort (ospf->areas, area);
696 ospf_check_abr_status (ospf);
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800697 if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET)
698 {
699 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
700 }
paul718e3742002-12-13 20:15:29 +0000701 }
702
703 return area;
704}
705
706struct ospf_area *
paul68980082003-03-25 05:07:42 +0000707ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000708{
709 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000710 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000711
paul1eb8ef22005-04-07 07:30:20 +0000712 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
713 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
714 return area;
paul718e3742002-12-13 20:15:29 +0000715
716 return NULL;
717}
718
719void
720ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
721{
722 listnode_add (area->oiflist, oi);
723}
724
725void
726ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
727{
728 listnode_delete (area->oiflist, oi);
729}
730
David Lamparter6b0655a2014-06-04 06:53:35 +0200731
paul718e3742002-12-13 20:15:29 +0000732/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000733static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000734ospf_network_new (struct in_addr area_id, int format)
735{
736 struct ospf_network *new;
737 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
738
739 new->area_id = area_id;
740 new->format = format;
741
742 return new;
743}
744
Paul Jakma8a667cf2009-08-27 16:51:42 +0100745static void
746add_ospf_interface (struct connected *co, struct ospf_area *area)
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200747{
748 struct ospf_interface *oi;
749
Paul Jakma8a667cf2009-08-27 16:51:42 +0100750 oi = ospf_if_new (area->ospf, co->ifp, co->address);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200751 oi->connected = co;
752
753 oi->area = area;
754
Paul Jakma8a667cf2009-08-27 16:51:42 +0100755 oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200756 oi->output_cost = ospf_if_get_output_cost (oi);
757
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200758 /* Relate ospf interface to ospf instance. */
759 oi->ospf = area->ospf;
760
761 /* update network type as interface flag */
762 /* If network type is specified previously,
763 skip network type setting. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100764 oi->type = IF_DEF_PARAMS (co->ifp)->type;
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200765
Jafar Al-Gharaibehbb01bdd2016-04-21 16:22:33 -0500766 /* Add pseudo neighbor. */
767 ospf_nbr_self_reset (oi);
768
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200769 ospf_area_add_if (oi->area, oi);
770
771 /* if router_id is not configured, dont bring up
772 * interfaces.
773 * ospf_router_id_update() will call ospf_if_update
774 * whenever r-id is configured instead.
775 */
776 if ((area->ospf->router_id.s_addr != 0)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100777 && if_is_operative (co->ifp))
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200778 ospf_if_up (oi);
779}
780
781static void
782update_redistributed (struct ospf *ospf, int add_to_ospf)
783{
784 struct route_node *rn;
785 struct external_info *ei;
786
787 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
788 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
789 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
790 rn; rn = route_next (rn))
791 if ((ei = rn->info) != NULL)
792 {
793 if (add_to_ospf)
794 {
795 if (ospf_external_info_find_lsa (ospf, &ei->p))
796 if (!ospf_distribute_check_connected (ospf, ei))
797 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
Paul Jakma8a667cf2009-08-27 16:51:42 +0100798 ei->ifindex /*, ei->nexthop */);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200799 }
800 else
801 {
802 if (!ospf_external_info_find_lsa (ospf, &ei->p))
803 if (ospf_distribute_check_connected (ospf, ei))
804 ospf_external_lsa_originate (ospf, ei);
805 }
806 }
807}
808
809static void
paul68980082003-03-25 05:07:42 +0000810ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000811{
paul68980082003-03-25 05:07:42 +0000812 ospf_area_check_free (ospf, network->area_id);
813 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000814 XFREE (MTYPE_OSPF_NETWORK, network);
815}
816
817int
818ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
819 struct in_addr area_id)
820{
821 struct ospf_network *network;
822 struct ospf_area *area;
823 struct route_node *rn;
paul147193a2003-04-19 00:31:59 +0000824 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000825
826 rn = route_node_get (ospf->networks, (struct prefix *)p);
827 if (rn->info)
828 {
829 /* There is already same network statement. */
830 route_unlock_node (rn);
831 return 0;
832 }
833
834 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000835 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000836
837 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100838 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000839
840 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100841 update_redistributed(ospf, 1);
842
paul68980082003-03-25 05:07:42 +0000843 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000844
845 return 1;
846}
847
848int
849ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
850 struct in_addr area_id)
851{
852 struct route_node *rn;
853 struct ospf_network *network;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100854 struct listnode *node, *nnode;
855 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000856
857 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
858 if (rn == NULL)
859 return 0;
860
861 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700862 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000863 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
864 return 0;
865
paul68980082003-03-25 05:07:42 +0000866 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000867 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700868 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000869
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100870 /* Find interfaces that not configured already. */
871 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
872 {
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100873 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
874 continue;
875
Paul Jakma8a667cf2009-08-27 16:51:42 +0100876 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100877 }
paul718e3742002-12-13 20:15:29 +0000878
879 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100880 update_redistributed(ospf, 0);
881
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200882 ospf_area_check_free (ospf, area_id);
Paul Jakma8a667cf2009-08-27 16:51:42 +0100883
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200884 return 1;
885}
886
Paul Jakma8a667cf2009-08-27 16:51:42 +0100887/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
888 * there might not be any 'router ospf' config.
889 *
890 * Otherwise, doesn't do anything different to ospf_if_update for now
891 */
892void
893ospf_interface_area_set (struct interface *ifp)
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200894{
Paul Jakma8a667cf2009-08-27 16:51:42 +0100895 struct ospf *ospf = ospf_get();
896
897 ospf_if_update (ospf, ifp);
898 /* if_update does a update_redistributed */
899
900 return;
901}
902
903void
904ospf_interface_area_unset (struct interface *ifp)
905{
906 struct route_node *rn_oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200907 struct ospf *ospf;
908
909 if ((ospf = ospf_lookup ()) == NULL)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100910 return; /* Ospf not ready yet */
911
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200912 /* Find interfaces that may need to be removed. */
913 for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
914 {
915 struct ospf_interface *oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200916
917 if ( (oi = rn_oi->info) == NULL)
918 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100919
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200920 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
921 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100922
923 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200924 }
925
926 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100927 update_redistributed (ospf, 0); /* interfaces possibly removed */
928
929 return;
930}
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200931
932
paul570f7592003-01-25 06:47:41 +0000933/* Check whether interface matches given network
934 * returns: 1, true. 0, false
935 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300936static int
937ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000938{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000939 /* new approach: more elegant and conceptually clean */
940 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000941}
942
Stephen Hemminger917e2992009-12-03 19:07:00 +0300943static void
Paul Jakma8a667cf2009-08-27 16:51:42 +0100944ospf_update_interface_area (struct connected *co, struct ospf_area *area)
945{
946 struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
947
948 /* nothing to be done case */
949 if (oi && oi->area == area)
950 return;
951
952 if (oi)
953 ospf_if_free (oi);
954
955 add_ospf_interface (co, area);
956}
957
958/* Run OSPF for the given subnet, taking into account the following
959 * possible sources of area configuration, in the given order of preference:
960 *
961 * - Whether there is interface+address specific area configuration
962 * - Whether there is a default area for the interface
963 * - Whether there is an area given as a parameter.
964 * - If no specific network prefix/area is supplied, whether there's
965 * a matching network configured.
966 */
967static void
968ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
969 struct prefix *p, struct ospf_area *given_area)
970{
971 struct ospf_interface *oi;
972 struct ospf_if_params *params;
973 struct ospf_area *area = NULL;
974 struct route_node *rn;
975 int configed = 0;
976
977 if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
978 return;
979
980 if (co->address->family != AF_INET)
981 return;
982
983 /* Try determine the appropriate area for this interface + address
984 * Start by checking interface config
985 */
986 if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
987 params = IF_DEF_PARAMS (co->ifp);
988
989 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
990 area = (ospf_area_get (ospf, params->if_area,
991 OSPF_AREA_ID_FORMAT_ADDRESS));
992
993 /* If we've found an interface and/or addr specific area, then we're
994 * done
995 */
996 if (area)
997 {
998 ospf_update_interface_area (co, area);
999 return;
1000 }
1001
1002 /* Otherwise, only remaining possibility is a matching network statement */
1003 if (p)
1004 {
1005 assert (given_area != NULL);
1006
1007 /* Which either was supplied as a parameter.. (e.g. cause a new
1008 * network/area was just added)..
1009 */
1010 if (p->family == co->address->family
1011 && ospf_network_match_iface (co, p))
1012 ospf_update_interface_area (co, given_area);
1013
1014 return;
1015 }
1016
1017 /* Else we have to search the existing network/area config to see
1018 * if any match..
1019 */
1020 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1021 if (rn->info != NULL
1022 && ospf_network_match_iface (co, &rn->p))
1023 {
1024 struct ospf_network *network = (struct ospf_network *) rn->info;
1025 area = ospf_area_get (ospf, network->area_id, network->format);
1026 ospf_update_interface_area (co, area);
1027 configed = 1;
1028 }
1029
1030 /* If the subnet isn't in any area, deconfigure */
1031 if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
1032 ospf_if_free (oi);
1033}
1034
1035static void
1036ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
1037 struct prefix *p,
1038 struct ospf_area *given_area)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001039{
1040 struct listnode *cnode;
1041 struct connected *co;
1042
1043 if (memcmp (ifp->name, "VLINK", 5) == 0)
1044 return;
1045
Paul Jakma8a667cf2009-08-27 16:51:42 +01001046 /* Network prefix without area is nonsensical */
1047 if (p)
1048 assert (given_area != NULL);
1049
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001050 /* if interface prefix is match specified prefix,
1051 then create socket and join multicast group. */
1052 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001053 ospf_network_run_subnet (ospf, co, p, given_area);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001054}
1055
Stephen Hemminger917e2992009-12-03 19:07:00 +03001056static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001057ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001058{
1059 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00001060 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001061
1062 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001063 if (area->ospf->router_id.s_addr == 0)
1064 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +00001065
paul718e3742002-12-13 20:15:29 +00001066 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +00001067 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001068 ospf_network_run_interface (area->ospf, ifp, p, area);
paul718e3742002-12-13 20:15:29 +00001069}
1070
1071void
1072ospf_ls_upd_queue_empty (struct ospf_interface *oi)
1073{
1074 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00001075 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +00001076 struct list *lst;
paul718e3742002-12-13 20:15:29 +00001077 struct ospf_lsa *lsa;
1078
1079 /* empty ls update queue */
1080 for (rn = route_top (oi->ls_upd_queue); rn;
1081 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +00001082 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +00001083 {
paul1eb8ef22005-04-07 07:30:20 +00001084 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001085 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00001086 list_free (lst);
1087 rn->info = NULL;
1088 }
1089
1090 /* remove update event */
1091 if (oi->t_ls_upd_event)
1092 {
1093 thread_cancel (oi->t_ls_upd_event);
1094 oi->t_ls_upd_event = NULL;
1095 }
1096}
1097
1098void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001099ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +00001100{
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001101 if (!ospf)
1102 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001103
Paul Jakma8a667cf2009-08-27 16:51:42 +01001104 /* OSPF must be ready. */
1105 if (!ospf_is_ready (ospf))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001106 return;
Joakim Tjernlund738bce72009-08-07 13:48:15 +02001107
Paul Jakma8a667cf2009-08-27 16:51:42 +01001108 ospf_network_run_interface (ospf, ifp, NULL, NULL);
1109
1110 /* Update connected redistribute. */
1111 update_redistributed(ospf, 1);
paul718e3742002-12-13 20:15:29 +00001112}
1113
1114void
paul68980082003-03-25 05:07:42 +00001115ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001116{
paul1eb8ef22005-04-07 07:30:20 +00001117 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001118 struct ospf_vl_data *vl_data;
1119
paul1eb8ef22005-04-07 07:30:20 +00001120 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1121 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1122 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001123}
1124
David Lamparter6b0655a2014-06-04 06:53:35 +02001125
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001126static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001127{
1128 { OSPF_AREA_DEFAULT, "Default" },
1129 { OSPF_AREA_STUB, "Stub" },
1130 { OSPF_AREA_NSSA, "NSSA" },
1131};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001132static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001133
paul4dadc292005-05-06 21:37:42 +00001134static void
paul718e3742002-12-13 20:15:29 +00001135ospf_area_type_set (struct ospf_area *area, int type)
1136{
hasso52dc7ee2004-09-23 19:18:23 +00001137 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001138 struct ospf_interface *oi;
1139
1140 if (area->external_routing == type)
1141 {
1142 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001143 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001144 inet_ntoa (area->area_id));
1145 return;
1146 }
1147
1148 area->external_routing = type;
1149
1150 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001151 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001152 LOOKUP (ospf_area_type_msg, type));
1153
1154 switch (area->external_routing)
1155 {
1156 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001157 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1158 if (oi->nbr_self != NULL)
1159 {
1160 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1161 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1162 }
paul718e3742002-12-13 20:15:29 +00001163 break;
1164 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001165 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1166 if (oi->nbr_self != NULL)
1167 {
1168 if (IS_DEBUG_OSPF_EVENT)
1169 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1170 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1171 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1172 if (IS_DEBUG_OSPF_EVENT)
1173 zlog_debug ("options set on %s: %x",
1174 IF_NAME (oi), OPTIONS (oi));
1175 }
paul718e3742002-12-13 20:15:29 +00001176 break;
1177 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001178 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1179 if (oi->nbr_self != NULL)
1180 {
1181 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1182 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1183 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1184 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1185 }
paul718e3742002-12-13 20:15:29 +00001186 break;
1187 default:
1188 break;
1189 }
1190
Paul Jakmac363d382010-01-24 22:42:13 +00001191 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001192 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001193}
1194
1195int
paul68980082003-03-25 05:07:42 +00001196ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001197{
1198 if (area->shortcut_configured == mode)
1199 return 0;
1200
1201 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001202 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001203 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001204
paul68980082003-03-25 05:07:42 +00001205 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001206
1207 return 1;
1208}
1209
1210int
paul68980082003-03-25 05:07:42 +00001211ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001212{
1213 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001214 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001215 ospf_area_check_free (ospf, area->area_id);
1216 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001217
1218 return 1;
1219}
1220
paul4dadc292005-05-06 21:37:42 +00001221static int
paul718e3742002-12-13 20:15:29 +00001222ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1223{
1224 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001225 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001226 int count = 0;
1227
paul1eb8ef22005-04-07 07:30:20 +00001228 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1229 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1230 count++;
paul718e3742002-12-13 20:15:29 +00001231
1232 return count;
1233}
1234
1235int
1236ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1237{
1238 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001239 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001240
paul68980082003-03-25 05:07:42 +00001241 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001242 if (ospf_area_vlink_count (ospf, area))
1243 return 0;
1244
1245 if (area->external_routing != OSPF_AREA_STUB)
1246 ospf_area_type_set (area, OSPF_AREA_STUB);
1247
1248 return 1;
1249}
1250
1251int
1252ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1253{
1254 struct ospf_area *area;
1255
paul68980082003-03-25 05:07:42 +00001256 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001257 if (area == NULL)
1258 return 1;
1259
1260 if (area->external_routing == OSPF_AREA_STUB)
1261 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1262
paul68980082003-03-25 05:07:42 +00001263 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001264
1265 return 1;
1266}
1267
1268int
1269ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1270{
1271 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001272 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001273
paul68980082003-03-25 05:07:42 +00001274 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001275 area->no_summary = 1;
1276
1277 return 1;
1278}
1279
1280int
1281ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1282{
1283 struct ospf_area *area;
1284
paul68980082003-03-25 05:07:42 +00001285 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001286 if (area == NULL)
1287 return 0;
1288
1289 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001290 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001291
1292 return 1;
1293}
1294
1295int
1296ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1297{
1298 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001299 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001300
paul68980082003-03-25 05:07:42 +00001301 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001302 if (ospf_area_vlink_count (ospf, area))
1303 return 0;
1304
1305 if (area->external_routing != OSPF_AREA_NSSA)
1306 {
1307 ospf_area_type_set (area, OSPF_AREA_NSSA);
1308 ospf->anyNSSA++;
1309 }
1310
paul084c7842003-06-22 08:35:18 +00001311 /* set NSSA area defaults */
1312 area->no_summary = 0;
1313 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001314 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001315 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1316
paul718e3742002-12-13 20:15:29 +00001317 return 1;
1318}
1319
1320int
1321ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1322{
1323 struct ospf_area *area;
1324
paul68980082003-03-25 05:07:42 +00001325 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001326 if (area == NULL)
1327 return 0;
1328
1329 if (area->external_routing == OSPF_AREA_NSSA)
1330 {
1331 ospf->anyNSSA--;
1332 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1333 }
1334
paul68980082003-03-25 05:07:42 +00001335 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001336
1337 return 1;
1338}
1339
1340int
1341ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1342 int role)
1343{
1344 struct ospf_area *area;
1345
paul68980082003-03-25 05:07:42 +00001346 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001347 if (area == NULL)
1348 return 0;
1349
paul084c7842003-06-22 08:35:18 +00001350 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001351
1352 return 1;
1353}
1354
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001355#if 0
paul4dadc292005-05-06 21:37:42 +00001356/* XXX: unused? Leave for symmetry? */
1357static int
paul718e3742002-12-13 20:15:29 +00001358ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1359 struct in_addr area_id)
1360{
1361 struct ospf_area *area;
1362
paul68980082003-03-25 05:07:42 +00001363 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001364 if (area == NULL)
1365 return 0;
1366
paul084c7842003-06-22 08:35:18 +00001367 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001368
paul68980082003-03-25 05:07:42 +00001369 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001370
1371 return 1;
1372}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001373#endif
paul718e3742002-12-13 20:15:29 +00001374
1375int
paul68980082003-03-25 05:07:42 +00001376ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001377 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct access_list *list;
1380 list = access_list_lookup (AFI_IP, list_name);
1381
1382 EXPORT_LIST (area) = list;
1383
1384 if (EXPORT_NAME (area))
1385 free (EXPORT_NAME (area));
1386
1387 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001388 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001389
1390 return 1;
1391}
1392
1393int
paul68980082003-03-25 05:07:42 +00001394ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001395{
1396
1397 EXPORT_LIST (area) = 0;
1398
1399 if (EXPORT_NAME (area))
1400 free (EXPORT_NAME (area));
1401
1402 EXPORT_NAME (area) = NULL;
1403
paul68980082003-03-25 05:07:42 +00001404 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001405
paul68980082003-03-25 05:07:42 +00001406 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001407
1408 return 1;
1409}
1410
1411int
paul6c835672004-10-11 11:00:30 +00001412ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1413 const char *name)
paul718e3742002-12-13 20:15:29 +00001414{
1415 struct access_list *list;
1416 list = access_list_lookup (AFI_IP, name);
1417
1418 IMPORT_LIST (area) = list;
1419
1420 if (IMPORT_NAME (area))
1421 free (IMPORT_NAME (area));
1422
1423 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001424 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001425
1426 return 1;
1427}
1428
1429int
paul68980082003-03-25 05:07:42 +00001430ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001431{
1432 IMPORT_LIST (area) = 0;
1433
1434 if (IMPORT_NAME (area))
1435 free (IMPORT_NAME (area));
1436
1437 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001438 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001439
paul68980082003-03-25 05:07:42 +00001440 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001441
1442 return 1;
1443}
1444
1445int
paul718e3742002-12-13 20:15:29 +00001446ospf_timers_refresh_set (struct ospf *ospf, int interval)
1447{
1448 int time_left;
1449
1450 if (ospf->lsa_refresh_interval == interval)
1451 return 1;
1452
1453 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001454 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001455
1456 if (time_left > interval)
1457 {
1458 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1459 ospf->t_lsa_refresher =
1460 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1461 }
1462 ospf->lsa_refresh_interval = interval;
1463
1464 return 1;
1465}
1466
1467int
1468ospf_timers_refresh_unset (struct ospf *ospf)
1469{
1470 int time_left;
1471
1472 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001473 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001474
1475 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1476 {
1477 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1478 ospf->t_lsa_refresher =
1479 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1480 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1481 }
1482
1483 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1484
1485 return 1;
1486}
1487
David Lamparter6b0655a2014-06-04 06:53:35 +02001488
paul4dadc292005-05-06 21:37:42 +00001489static struct ospf_nbr_nbma *
1490ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001491{
1492 struct ospf_nbr_nbma *nbr_nbma;
1493
Stephen Hemminger393deb92008-08-18 14:13:29 -07001494 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001495 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001496
1497 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1498 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1499
1500 return nbr_nbma;
1501}
1502
paul4dadc292005-05-06 21:37:42 +00001503static void
paul718e3742002-12-13 20:15:29 +00001504ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1505{
1506 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1507}
1508
paul4dadc292005-05-06 21:37:42 +00001509static void
paul718e3742002-12-13 20:15:29 +00001510ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1511{
1512 struct route_node *rn;
1513 struct prefix_ipv4 p;
1514
1515 p.family = AF_INET;
1516 p.prefix = nbr_nbma->addr;
1517 p.prefixlen = IPV4_MAX_BITLEN;
1518
1519 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1520 if (rn)
1521 {
1522 ospf_nbr_nbma_free (rn->info);
1523 rn->info = NULL;
1524 route_unlock_node (rn);
1525 route_unlock_node (rn);
1526 }
1527}
1528
paul4dadc292005-05-06 21:37:42 +00001529static void
paul718e3742002-12-13 20:15:29 +00001530ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1531{
1532 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1533
1534 if (nbr_nbma->nbr)
1535 {
1536 nbr_nbma->nbr->nbr_nbma = NULL;
1537 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1538 }
1539
1540 if (nbr_nbma->oi)
1541 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1542}
1543
paul4dadc292005-05-06 21:37:42 +00001544static void
paul718e3742002-12-13 20:15:29 +00001545ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1546 struct ospf_interface *oi)
1547{
1548 struct ospf_neighbor *nbr;
1549 struct route_node *rn;
1550 struct prefix p;
1551
1552 if (oi->type != OSPF_IFTYPE_NBMA)
1553 return;
1554
1555 if (nbr_nbma->nbr != NULL)
1556 return;
1557
1558 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1559 return;
1560
1561 nbr_nbma->oi = oi;
1562 listnode_add (oi->nbr_nbma, nbr_nbma);
1563
1564 /* Get neighbor information from table. */
1565 p.family = AF_INET;
1566 p.prefixlen = IPV4_MAX_BITLEN;
1567 p.u.prefix4 = nbr_nbma->addr;
1568
1569 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1570 if (rn->info)
1571 {
1572 nbr = rn->info;
1573 nbr->nbr_nbma = nbr_nbma;
1574 nbr_nbma->nbr = nbr;
1575
1576 route_unlock_node (rn);
1577 }
1578 else
1579 {
1580 nbr = rn->info = ospf_nbr_new (oi);
1581 nbr->state = NSM_Down;
1582 nbr->src = nbr_nbma->addr;
1583 nbr->nbr_nbma = nbr_nbma;
1584 nbr->priority = nbr_nbma->priority;
1585 nbr->address = p;
1586
1587 nbr_nbma->nbr = nbr;
1588
1589 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1590 }
1591}
1592
1593void
paul68980082003-03-25 05:07:42 +00001594ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001595{
1596 struct ospf_nbr_nbma *nbr_nbma;
1597 struct route_node *rn;
1598 struct prefix_ipv4 p;
1599
1600 if (oi->type != OSPF_IFTYPE_NBMA)
1601 return;
1602
paul68980082003-03-25 05:07:42 +00001603 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001604 if ((nbr_nbma = rn->info))
1605 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1606 {
1607 p.family = AF_INET;
1608 p.prefix = nbr_nbma->addr;
1609 p.prefixlen = IPV4_MAX_BITLEN;
1610
1611 if (prefix_match (oi->address, (struct prefix *)&p))
1612 ospf_nbr_nbma_add (nbr_nbma, oi);
1613 }
1614}
1615
1616struct ospf_nbr_nbma *
1617ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1618{
1619 struct route_node *rn;
1620 struct prefix_ipv4 p;
1621
1622 p.family = AF_INET;
1623 p.prefix = nbr_addr;
1624 p.prefixlen = IPV4_MAX_BITLEN;
1625
1626 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1627 if (rn)
1628 {
1629 route_unlock_node (rn);
1630 return rn->info;
1631 }
1632 return NULL;
1633}
1634
1635struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001636ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001637{
1638#if 0
1639 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001640 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001641#endif
1642
paul68980082003-03-25 05:07:42 +00001643 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001644 return NULL;
1645
1646#if 0
paul1eb8ef22005-04-07 07:30:20 +00001647 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001648 {
paul718e3742002-12-13 20:15:29 +00001649 if (first)
1650 {
1651 *addr = nbr_nbma->addr;
1652 return nbr_nbma;
1653 }
1654 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1655 {
1656 *addr = nbr_nbma->addr;
1657 return nbr_nbma;
1658 }
1659 }
1660#endif
1661 return NULL;
1662}
1663
1664int
1665ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1666{
1667 struct ospf_nbr_nbma *nbr_nbma;
1668 struct ospf_interface *oi;
1669 struct prefix_ipv4 p;
1670 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001671 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001672
1673 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1674 if (nbr_nbma)
1675 return 0;
1676
1677 nbr_nbma = ospf_nbr_nbma_new ();
1678 nbr_nbma->addr = nbr_addr;
1679
1680 p.family = AF_INET;
1681 p.prefix = nbr_addr;
1682 p.prefixlen = IPV4_MAX_BITLEN;
1683
1684 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
Joakim Tjernlund4de398e2010-03-08 13:58:14 +01001685 if (rn->info)
1686 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001687 rn->info = nbr_nbma;
1688
paul1eb8ef22005-04-07 07:30:20 +00001689 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001690 {
paul718e3742002-12-13 20:15:29 +00001691 if (oi->type == OSPF_IFTYPE_NBMA)
1692 if (prefix_match (oi->address, (struct prefix *)&p))
1693 {
1694 ospf_nbr_nbma_add (nbr_nbma, oi);
1695 break;
1696 }
1697 }
1698
1699 return 1;
1700}
1701
1702int
1703ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1704{
1705 struct ospf_nbr_nbma *nbr_nbma;
1706
1707 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1708 if (nbr_nbma == NULL)
1709 return 0;
1710
1711 ospf_nbr_nbma_down (nbr_nbma);
1712 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1713
1714 return 1;
1715}
1716
1717int
1718ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1719 u_char priority)
1720{
1721 struct ospf_nbr_nbma *nbr_nbma;
1722
1723 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1724 if (nbr_nbma == NULL)
1725 return 0;
1726
1727 if (nbr_nbma->priority != priority)
1728 nbr_nbma->priority = priority;
1729
1730 return 1;
1731}
1732
1733int
1734ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1735{
1736 struct ospf_nbr_nbma *nbr_nbma;
1737
1738 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1739 if (nbr_nbma == NULL)
1740 return 0;
1741
1742 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1743 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1744
1745 return 1;
1746}
1747
1748int
1749ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001750 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001751{
1752 struct ospf_nbr_nbma *nbr_nbma;
1753
1754 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1755 if (nbr_nbma == NULL)
1756 return 0;
1757
1758 if (nbr_nbma->v_poll != interval)
1759 {
1760 nbr_nbma->v_poll = interval;
1761 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1762 {
1763 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1764 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1765 nbr_nbma->v_poll);
1766 }
1767 }
1768
1769 return 1;
1770}
1771
1772int
1773ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1774{
1775 struct ospf_nbr_nbma *nbr_nbma;
1776
1777 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1778 if (nbr_nbma == NULL)
1779 return 0;
1780
1781 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1782 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1783
1784 return 1;
1785}
1786
paul718e3742002-12-13 20:15:29 +00001787void
paul020709f2003-04-04 02:44:16 +00001788ospf_master_init ()
1789{
1790 memset (&ospf_master, 0, sizeof (struct ospf_master));
1791
1792 om = &ospf_master;
1793 om->ospf = list_new ();
1794 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001795 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001796}