blob: a01af602ebd026f9ab782d20679223d3d53b7d34 [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
Olivier Dugeon29a14012016-04-19 18:42:40 +0200258 return listgetdata ((struct listnode *)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
paul020709f2003-04-04 02:44:16 +0000297 ospf_opaque_type11_lsa_init (ospf);
paul020709f2003-04-04 02:44:16 +0000298 }
paul68980082003-03-25 05:07:42 +0000299
300 return ospf;
paul718e3742002-12-13 20:15:29 +0000301}
David Lamparter6b0655a2014-06-04 06:53:35 +0200302
paulc9c93d52005-11-26 13:31:11 +0000303/* Handle the second half of deferred shutdown. This is called either
304 * from the deferred-shutdown timer thread, or directly through
305 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000306 *
307 * Function is to cleanup G-R state, if required then call ospf_finish_final
308 * to complete shutdown of this ospf instance. Possibly exit if the
309 * whole process is being shutdown and this was the last OSPF instance.
310 */
311static void
paulc9c93d52005-11-26 13:31:11 +0000312ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000313{
314 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000315 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000316
317 ospf_finish_final (ospf);
318
319 /* *ospf is now invalid */
320
321 /* ospfd being shut-down? If so, was this the last ospf instance? */
322 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
323 && (listcount (om->ospf) == 0))
324 exit (0);
325
326 return;
327}
328
329/* Timer thread for G-R */
330static int
paulc9c93d52005-11-26 13:31:11 +0000331ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000332{
333 struct ospf *ospf = THREAD_ARG(t);
334
paulc9c93d52005-11-26 13:31:11 +0000335 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000336
337 return 0;
338}
339
paulc9c93d52005-11-26 13:31:11 +0000340/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000341 * down directly into second-half of instance shutdown.
342 */
343static void
paulc9c93d52005-11-26 13:31:11 +0000344ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000345{
346 unsigned long timeout;
347 struct listnode *ln;
348 struct ospf_area *area;
349
paulc9c93d52005-11-26 13:31:11 +0000350 /* deferred shutdown already running? */
351 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000352 return;
353
354 /* Should we try push out max-metric LSAs? */
355 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
356 {
357 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
358 {
359 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
360
361 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000362 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000363 }
364 timeout = ospf->stub_router_shutdown_time;
365 }
366 else
paulc9c93d52005-11-26 13:31:11 +0000367 {
368 /* No timer needed */
369 ospf_deferred_shutdown_finish (ospf);
370 return;
371 }
paul88d6cf32005-10-29 12:50:09 +0000372
paulc9c93d52005-11-26 13:31:11 +0000373 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000374 timeout);
375 return;
376}
David Lamparter6b0655a2014-06-04 06:53:35 +0200377
paul88d6cf32005-10-29 12:50:09 +0000378/* Shut down the entire process */
379void
380ospf_terminate (void)
381{
382 struct ospf *ospf;
383 struct listnode *node, *nnode;
384
385 /* shutdown already in progress */
386 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
387 return;
388
389 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
390
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000391 /* exit immediately if OSPF not actually running */
392 if (listcount(om->ospf) == 0)
393 exit(0);
394
paul88d6cf32005-10-29 12:50:09 +0000395 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
396 ospf_finish (ospf);
397
398 /* Deliberately go back up, hopefully to thread scheduler, as
399 * One or more ospf_finish()'s may have deferred shutdown to a timer
400 * thread
401 */
402}
paul718e3742002-12-13 20:15:29 +0000403
404void
405ospf_finish (struct ospf *ospf)
406{
paulc9c93d52005-11-26 13:31:11 +0000407 /* let deferred shutdown decide */
408 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000409
paulc9c93d52005-11-26 13:31:11 +0000410 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000411 * deferred to expiry of G-S timer thread. Return back up, hopefully
412 * to thread scheduler.
413 */
paulc9c93d52005-11-26 13:31:11 +0000414 return;
paul88d6cf32005-10-29 12:50:09 +0000415}
416
417/* Final cleanup of ospf instance */
418static void
419ospf_finish_final (struct ospf *ospf)
420{
paul718e3742002-12-13 20:15:29 +0000421 struct route_node *rn;
422 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000423 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000424 struct ospf_interface *oi;
425 struct ospf_area *area;
426 struct ospf_vl_data *vl_data;
427 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000428 int i;
429
paul718e3742002-12-13 20:15:29 +0000430 ospf_opaque_type11_lsa_term (ospf);
paul88d6cf32005-10-29 12:50:09 +0000431
432 /* be nice if this worked, but it doesn't */
433 /*ospf_flush_self_originated_lsas_now (ospf);*/
434
435 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000436 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000437 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000438 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000439
paul1eb8ef22005-04-07 07:30:20 +0000440 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
441 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000442
paul1eb8ef22005-04-07 07:30:20 +0000443 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
444 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000445
446 list_delete (ospf->vlinks);
447
448 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000449 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
450 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000451
452 /* Clear static neighbors */
453 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
454 if ((nbr_nbma = rn->info))
455 {
456 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
457
458 if (nbr_nbma->nbr)
459 {
460 nbr_nbma->nbr->nbr_nbma = NULL;
461 nbr_nbma->nbr = NULL;
462 }
463
464 if (nbr_nbma->oi)
465 {
466 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
467 nbr_nbma->oi = NULL;
468 }
469
470 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
471 }
472
473 route_table_finish (ospf->nbr_nbma);
474
475 /* Clear networks and Areas. */
476 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
477 {
478 struct ospf_network *network;
479
480 if ((network = rn->info) != NULL)
481 {
paul68980082003-03-25 05:07:42 +0000482 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000483 rn->info = NULL;
484 route_unlock_node (rn);
485 }
486 }
487
paul1eb8ef22005-04-07 07:30:20 +0000488 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000489 {
paul718e3742002-12-13 20:15:29 +0000490 listnode_delete (ospf->areas, area);
491 ospf_area_free (area);
492 }
493
494 /* Cancel all timers. */
495 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000496 OSPF_TIMER_OFF (ospf->t_spf_calc);
497 OSPF_TIMER_OFF (ospf->t_ase_calc);
498 OSPF_TIMER_OFF (ospf->t_maxage);
499 OSPF_TIMER_OFF (ospf->t_maxage_walker);
500 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000501 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000502 OSPF_TIMER_OFF (ospf->t_distribute_update);
503 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
504 OSPF_TIMER_OFF (ospf->t_read);
505 OSPF_TIMER_OFF (ospf->t_write);
paul88d6cf32005-10-29 12:50:09 +0000506 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul718e3742002-12-13 20:15:29 +0000507
508 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000509 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000510
paul68980082003-03-25 05:07:42 +0000511 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
512 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul68980082003-03-25 05:07:42 +0000513 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
514 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
515
paul718e3742002-12-13 20:15:29 +0000516 ospf_lsdb_delete_all (ospf->lsdb);
517 ospf_lsdb_free (ospf->lsdb);
518
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800519 for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn))
520 {
521 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000522
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800523 if ((lsa = rn->info) != NULL)
524 {
525 ospf_lsa_unlock (&lsa);
526 rn->info = NULL;
527 }
528 route_unlock_node (rn);
529 }
530 route_table_finish (ospf->maxage_lsa);
paul718e3742002-12-13 20:15:29 +0000531
532 if (ospf->old_table)
533 ospf_route_table_free (ospf->old_table);
534 if (ospf->new_table)
535 {
536 ospf_route_delete (ospf->new_table);
537 ospf_route_table_free (ospf->new_table);
538 }
539 if (ospf->old_rtrs)
540 ospf_rtrs_free (ospf->old_rtrs);
541 if (ospf->new_rtrs)
542 ospf_rtrs_free (ospf->new_rtrs);
543 if (ospf->new_external_route)
544 {
545 ospf_route_delete (ospf->new_external_route);
546 ospf_route_table_free (ospf->new_external_route);
547 }
548 if (ospf->old_external_route)
549 {
550 ospf_route_delete (ospf->old_external_route);
551 ospf_route_table_free (ospf->old_external_route);
552 }
553 if (ospf->external_lsas)
554 {
555 ospf_ase_external_lsas_finish (ospf->external_lsas);
556 }
557
558 list_delete (ospf->areas);
559
560 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
561 if (EXTERNAL_INFO (i) != NULL)
562 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
563 {
564 if (rn->info == NULL)
565 continue;
566
567 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
568 rn->info = NULL;
569 route_unlock_node (rn);
570 }
571
paul68980082003-03-25 05:07:42 +0000572 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000573 route_table_finish (ospf->distance_table);
574
paul020709f2003-04-04 02:44:16 +0000575 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000576
paul020709f2003-04-04 02:44:16 +0000577 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000578}
579
David Lamparter6b0655a2014-06-04 06:53:35 +0200580
paul718e3742002-12-13 20:15:29 +0000581/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000582static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000583ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000584{
585 struct ospf_area *new;
586
587 /* Allocate new config_network. */
588 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
589
paul68980082003-03-25 05:07:42 +0000590 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000591
592 new->area_id = area_id;
593
594 new->external_routing = OSPF_AREA_DEFAULT;
595 new->default_cost = 1;
596 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000597
paul718e3742002-12-13 20:15:29 +0000598 /* New LSDB init. */
599 new->lsdb = ospf_lsdb_new ();
600
601 /* Self-originated LSAs initialize. */
602 new->router_lsa_self = NULL;
603
paul718e3742002-12-13 20:15:29 +0000604 ospf_opaque_type10_lsa_init (new);
paul718e3742002-12-13 20:15:29 +0000605
606 new->oiflist = list_new ();
607 new->ranges = route_table_init ();
608
609 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000610 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000611
612 return new;
613}
614
Stephen Hemminger917e2992009-12-03 19:07:00 +0300615static void
paul718e3742002-12-13 20:15:29 +0000616ospf_area_free (struct ospf_area *area)
617{
paul68980082003-03-25 05:07:42 +0000618 struct route_node *rn;
619 struct ospf_lsa *lsa;
620
paul718e3742002-12-13 20:15:29 +0000621 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000622 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
623 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
624 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
625 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
626 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
627 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
628 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
629 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000630
paul68980082003-03-25 05:07:42 +0000631 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
632 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul68980082003-03-25 05:07:42 +0000633 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
634 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
635 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
636 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000637
638 ospf_lsdb_delete_all (area->lsdb);
639 ospf_lsdb_free (area->lsdb);
640
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000641 ospf_lsa_unlock (&area->router_lsa_self);
paul718e3742002-12-13 20:15:29 +0000642
643 route_table_finish (area->ranges);
644 list_delete (area->oiflist);
645
646 if (EXPORT_NAME (area))
647 free (EXPORT_NAME (area));
648
649 if (IMPORT_NAME (area))
650 free (IMPORT_NAME (area));
651
652 /* Cancel timer. */
paul88d6cf32005-10-29 12:50:09 +0000653 OSPF_TIMER_OFF (area->t_stub_router);
paul88d6cf32005-10-29 12:50:09 +0000654 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
paul88d6cf32005-10-29 12:50:09 +0000655
paul718e3742002-12-13 20:15:29 +0000656 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000657 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000658
659 XFREE (MTYPE_OSPF_AREA, area);
660}
661
662void
paul68980082003-03-25 05:07:42 +0000663ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000664{
665 struct ospf_area *area;
666
paul68980082003-03-25 05:07:42 +0000667 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000668 if (area &&
669 listcount (area->oiflist) == 0 &&
670 area->ranges->top == NULL &&
671 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
672 area->external_routing == OSPF_AREA_DEFAULT &&
673 area->no_summary == 0 &&
674 area->default_cost == 1 &&
675 EXPORT_NAME (area) == NULL &&
676 IMPORT_NAME (area) == NULL &&
677 area->auth_type == OSPF_AUTH_NULL)
678 {
paul68980082003-03-25 05:07:42 +0000679 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000680 ospf_area_free (area);
681 }
682}
683
684struct ospf_area *
paul68980082003-03-25 05:07:42 +0000685ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000686{
687 struct ospf_area *area;
688
paul68980082003-03-25 05:07:42 +0000689 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000690 if (!area)
691 {
paul68980082003-03-25 05:07:42 +0000692 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000693 area->format = format;
paul68980082003-03-25 05:07:42 +0000694 listnode_add_sort (ospf->areas, area);
695 ospf_check_abr_status (ospf);
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800696 if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET)
697 {
698 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
699 }
paul718e3742002-12-13 20:15:29 +0000700 }
701
702 return area;
703}
704
705struct ospf_area *
paul68980082003-03-25 05:07:42 +0000706ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000707{
708 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000709 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000710
paul1eb8ef22005-04-07 07:30:20 +0000711 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
712 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
713 return area;
paul718e3742002-12-13 20:15:29 +0000714
715 return NULL;
716}
717
718void
719ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
720{
721 listnode_add (area->oiflist, oi);
722}
723
724void
725ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
726{
727 listnode_delete (area->oiflist, oi);
728}
729
David Lamparter6b0655a2014-06-04 06:53:35 +0200730
paul718e3742002-12-13 20:15:29 +0000731/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000732static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000733ospf_network_new (struct in_addr area_id, int format)
734{
735 struct ospf_network *new;
736 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
737
738 new->area_id = area_id;
739 new->format = format;
740
741 return new;
742}
743
Paul Jakma8a667cf2009-08-27 16:51:42 +0100744static void
745add_ospf_interface (struct connected *co, struct ospf_area *area)
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200746{
747 struct ospf_interface *oi;
748
Paul Jakma8a667cf2009-08-27 16:51:42 +0100749 oi = ospf_if_new (area->ospf, co->ifp, co->address);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200750 oi->connected = co;
751
752 oi->area = area;
753
Paul Jakma8a667cf2009-08-27 16:51:42 +0100754 oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200755 oi->output_cost = ospf_if_get_output_cost (oi);
756
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200757 /* Relate ospf interface to ospf instance. */
758 oi->ospf = area->ospf;
759
760 /* update network type as interface flag */
761 /* If network type is specified previously,
762 skip network type setting. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100763 oi->type = IF_DEF_PARAMS (co->ifp)->type;
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200764
Jafar Al-Gharaibehbb01bdd2016-04-21 16:22:33 -0500765 /* Add pseudo neighbor. */
766 ospf_nbr_self_reset (oi);
767
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200768 ospf_area_add_if (oi->area, oi);
769
770 /* if router_id is not configured, dont bring up
771 * interfaces.
772 * ospf_router_id_update() will call ospf_if_update
773 * whenever r-id is configured instead.
774 */
775 if ((area->ospf->router_id.s_addr != 0)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100776 && if_is_operative (co->ifp))
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200777 ospf_if_up (oi);
778}
779
780static void
781update_redistributed (struct ospf *ospf, int add_to_ospf)
782{
783 struct route_node *rn;
784 struct external_info *ei;
785
786 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
787 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
788 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
789 rn; rn = route_next (rn))
790 if ((ei = rn->info) != NULL)
791 {
792 if (add_to_ospf)
793 {
794 if (ospf_external_info_find_lsa (ospf, &ei->p))
795 if (!ospf_distribute_check_connected (ospf, ei))
796 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
Paul Jakma8a667cf2009-08-27 16:51:42 +0100797 ei->ifindex /*, ei->nexthop */);
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200798 }
799 else
800 {
801 if (!ospf_external_info_find_lsa (ospf, &ei->p))
802 if (ospf_distribute_check_connected (ospf, ei))
803 ospf_external_lsa_originate (ospf, ei);
804 }
805 }
806}
807
808static void
paul68980082003-03-25 05:07:42 +0000809ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000810{
paul68980082003-03-25 05:07:42 +0000811 ospf_area_check_free (ospf, network->area_id);
812 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000813 XFREE (MTYPE_OSPF_NETWORK, network);
814}
815
816int
817ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
818 struct in_addr area_id)
819{
820 struct ospf_network *network;
821 struct ospf_area *area;
822 struct route_node *rn;
paul147193a2003-04-19 00:31:59 +0000823 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000824
825 rn = route_node_get (ospf->networks, (struct prefix *)p);
826 if (rn->info)
827 {
828 /* There is already same network statement. */
829 route_unlock_node (rn);
830 return 0;
831 }
832
833 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000834 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000835
836 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100837 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000838
839 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100840 update_redistributed(ospf, 1);
841
paul68980082003-03-25 05:07:42 +0000842 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000843
844 return 1;
845}
846
847int
848ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
849 struct in_addr area_id)
850{
851 struct route_node *rn;
852 struct ospf_network *network;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100853 struct listnode *node, *nnode;
854 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000855
856 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
857 if (rn == NULL)
858 return 0;
859
860 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700861 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000862 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
863 return 0;
864
paul68980082003-03-25 05:07:42 +0000865 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000866 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700867 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000868
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100869 /* Find interfaces that not configured already. */
870 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
871 {
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100872 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
873 continue;
874
Paul Jakma8a667cf2009-08-27 16:51:42 +0100875 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100876 }
paul718e3742002-12-13 20:15:29 +0000877
878 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100879 update_redistributed(ospf, 0);
880
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200881 ospf_area_check_free (ospf, area_id);
Paul Jakma8a667cf2009-08-27 16:51:42 +0100882
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200883 return 1;
884}
885
Paul Jakma8a667cf2009-08-27 16:51:42 +0100886/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
887 * there might not be any 'router ospf' config.
888 *
889 * Otherwise, doesn't do anything different to ospf_if_update for now
890 */
891void
892ospf_interface_area_set (struct interface *ifp)
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200893{
Paul Jakma8a667cf2009-08-27 16:51:42 +0100894 struct ospf *ospf = ospf_get();
895
896 ospf_if_update (ospf, ifp);
897 /* if_update does a update_redistributed */
898
899 return;
900}
901
902void
903ospf_interface_area_unset (struct interface *ifp)
904{
905 struct route_node *rn_oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200906 struct ospf *ospf;
907
908 if ((ospf = ospf_lookup ()) == NULL)
Paul Jakma8a667cf2009-08-27 16:51:42 +0100909 return; /* Ospf not ready yet */
910
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200911 /* Find interfaces that may need to be removed. */
912 for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
913 {
914 struct ospf_interface *oi;
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200915
916 if ( (oi = rn_oi->info) == NULL)
917 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100918
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200919 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
920 continue;
Paul Jakma8a667cf2009-08-27 16:51:42 +0100921
922 ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200923 }
924
925 /* Update connected redistribute. */
Paul Jakma8a667cf2009-08-27 16:51:42 +0100926 update_redistributed (ospf, 0); /* interfaces possibly removed */
927
928 return;
929}
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200930
931
paul570f7592003-01-25 06:47:41 +0000932/* Check whether interface matches given network
933 * returns: 1, true. 0, false
934 */
Stephen Hemminger917e2992009-12-03 19:07:00 +0300935static int
936ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +0000937{
Andrew J. Schorre4529632006-12-12 19:18:21 +0000938 /* new approach: more elegant and conceptually clean */
939 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +0000940}
941
Stephen Hemminger917e2992009-12-03 19:07:00 +0300942static void
Paul Jakma8a667cf2009-08-27 16:51:42 +0100943ospf_update_interface_area (struct connected *co, struct ospf_area *area)
944{
945 struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
946
947 /* nothing to be done case */
948 if (oi && oi->area == area)
949 return;
950
951 if (oi)
952 ospf_if_free (oi);
953
954 add_ospf_interface (co, area);
955}
956
957/* Run OSPF for the given subnet, taking into account the following
958 * possible sources of area configuration, in the given order of preference:
959 *
960 * - Whether there is interface+address specific area configuration
961 * - Whether there is a default area for the interface
962 * - Whether there is an area given as a parameter.
963 * - If no specific network prefix/area is supplied, whether there's
964 * a matching network configured.
965 */
966static void
967ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
968 struct prefix *p, struct ospf_area *given_area)
969{
970 struct ospf_interface *oi;
971 struct ospf_if_params *params;
972 struct ospf_area *area = NULL;
973 struct route_node *rn;
974 int configed = 0;
975
976 if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
977 return;
978
979 if (co->address->family != AF_INET)
980 return;
981
982 /* Try determine the appropriate area for this interface + address
983 * Start by checking interface config
984 */
985 if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
986 params = IF_DEF_PARAMS (co->ifp);
987
988 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
989 area = (ospf_area_get (ospf, params->if_area,
990 OSPF_AREA_ID_FORMAT_ADDRESS));
991
992 /* If we've found an interface and/or addr specific area, then we're
993 * done
994 */
995 if (area)
996 {
997 ospf_update_interface_area (co, area);
998 return;
999 }
1000
1001 /* Otherwise, only remaining possibility is a matching network statement */
1002 if (p)
1003 {
1004 assert (given_area != NULL);
1005
1006 /* Which either was supplied as a parameter.. (e.g. cause a new
1007 * network/area was just added)..
1008 */
1009 if (p->family == co->address->family
1010 && ospf_network_match_iface (co, p))
1011 ospf_update_interface_area (co, given_area);
1012
1013 return;
1014 }
1015
1016 /* Else we have to search the existing network/area config to see
1017 * if any match..
1018 */
1019 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1020 if (rn->info != NULL
1021 && ospf_network_match_iface (co, &rn->p))
1022 {
1023 struct ospf_network *network = (struct ospf_network *) rn->info;
1024 area = ospf_area_get (ospf, network->area_id, network->format);
1025 ospf_update_interface_area (co, area);
1026 configed = 1;
1027 }
1028
1029 /* If the subnet isn't in any area, deconfigure */
1030 if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
1031 ospf_if_free (oi);
1032}
1033
1034static void
1035ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
1036 struct prefix *p,
1037 struct ospf_area *given_area)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001038{
1039 struct listnode *cnode;
1040 struct connected *co;
1041
1042 if (memcmp (ifp->name, "VLINK", 5) == 0)
1043 return;
1044
Paul Jakma8a667cf2009-08-27 16:51:42 +01001045 /* Network prefix without area is nonsensical */
1046 if (p)
1047 assert (given_area != NULL);
1048
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001049 /* if interface prefix is match specified prefix,
1050 then create socket and join multicast group. */
1051 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001052 ospf_network_run_subnet (ospf, co, p, given_area);
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001053}
1054
Stephen Hemminger917e2992009-12-03 19:07:00 +03001055static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001056ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001057{
1058 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00001059 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001060
1061 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001062 if (area->ospf->router_id.s_addr == 0)
1063 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +00001064
paul718e3742002-12-13 20:15:29 +00001065 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +00001066 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Paul Jakma8a667cf2009-08-27 16:51:42 +01001067 ospf_network_run_interface (area->ospf, ifp, p, area);
paul718e3742002-12-13 20:15:29 +00001068}
1069
1070void
1071ospf_ls_upd_queue_empty (struct ospf_interface *oi)
1072{
1073 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00001074 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +00001075 struct list *lst;
paul718e3742002-12-13 20:15:29 +00001076 struct ospf_lsa *lsa;
1077
1078 /* empty ls update queue */
1079 for (rn = route_top (oi->ls_upd_queue); rn;
1080 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +00001081 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +00001082 {
paul1eb8ef22005-04-07 07:30:20 +00001083 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001084 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00001085 list_free (lst);
1086 rn->info = NULL;
1087 }
1088
1089 /* remove update event */
1090 if (oi->t_ls_upd_event)
1091 {
1092 thread_cancel (oi->t_ls_upd_event);
1093 oi->t_ls_upd_event = NULL;
1094 }
1095}
1096
1097void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001098ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +00001099{
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001100 if (!ospf)
1101 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001102
Paul Jakma8a667cf2009-08-27 16:51:42 +01001103 /* OSPF must be ready. */
1104 if (!ospf_is_ready (ospf))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001105 return;
Joakim Tjernlund738bce72009-08-07 13:48:15 +02001106
Paul Jakma8a667cf2009-08-27 16:51:42 +01001107 ospf_network_run_interface (ospf, ifp, NULL, NULL);
1108
1109 /* Update connected redistribute. */
1110 update_redistributed(ospf, 1);
paul718e3742002-12-13 20:15:29 +00001111}
1112
1113void
paul68980082003-03-25 05:07:42 +00001114ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001115{
paul1eb8ef22005-04-07 07:30:20 +00001116 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001117 struct ospf_vl_data *vl_data;
1118
paul1eb8ef22005-04-07 07:30:20 +00001119 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1120 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1121 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001122}
1123
David Lamparter6b0655a2014-06-04 06:53:35 +02001124
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001125static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001126{
1127 { OSPF_AREA_DEFAULT, "Default" },
1128 { OSPF_AREA_STUB, "Stub" },
1129 { OSPF_AREA_NSSA, "NSSA" },
1130};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001131static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001132
paul4dadc292005-05-06 21:37:42 +00001133static void
paul718e3742002-12-13 20:15:29 +00001134ospf_area_type_set (struct ospf_area *area, int type)
1135{
hasso52dc7ee2004-09-23 19:18:23 +00001136 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001137 struct ospf_interface *oi;
1138
1139 if (area->external_routing == type)
1140 {
1141 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001142 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001143 inet_ntoa (area->area_id));
1144 return;
1145 }
1146
1147 area->external_routing = type;
1148
1149 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001150 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001151 LOOKUP (ospf_area_type_msg, type));
1152
1153 switch (area->external_routing)
1154 {
1155 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001156 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1157 if (oi->nbr_self != NULL)
1158 {
1159 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1160 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1161 }
paul718e3742002-12-13 20:15:29 +00001162 break;
1163 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001164 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1165 if (oi->nbr_self != NULL)
1166 {
1167 if (IS_DEBUG_OSPF_EVENT)
1168 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1169 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1170 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1171 if (IS_DEBUG_OSPF_EVENT)
1172 zlog_debug ("options set on %s: %x",
1173 IF_NAME (oi), OPTIONS (oi));
1174 }
paul718e3742002-12-13 20:15:29 +00001175 break;
1176 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001177 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1178 if (oi->nbr_self != NULL)
1179 {
1180 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1181 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1182 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1183 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1184 }
paul718e3742002-12-13 20:15:29 +00001185 break;
1186 default:
1187 break;
1188 }
1189
Paul Jakmac363d382010-01-24 22:42:13 +00001190 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001191 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001192}
1193
1194int
paul68980082003-03-25 05:07:42 +00001195ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001196{
1197 if (area->shortcut_configured == mode)
1198 return 0;
1199
1200 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001201 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001202 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001203
paul68980082003-03-25 05:07:42 +00001204 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001205
1206 return 1;
1207}
1208
1209int
paul68980082003-03-25 05:07:42 +00001210ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001211{
1212 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001213 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001214 ospf_area_check_free (ospf, area->area_id);
1215 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001216
1217 return 1;
1218}
1219
paul4dadc292005-05-06 21:37:42 +00001220static int
paul718e3742002-12-13 20:15:29 +00001221ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1222{
1223 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001224 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001225 int count = 0;
1226
paul1eb8ef22005-04-07 07:30:20 +00001227 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1228 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1229 count++;
paul718e3742002-12-13 20:15:29 +00001230
1231 return count;
1232}
1233
1234int
1235ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1236{
1237 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001238 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001239
paul68980082003-03-25 05:07:42 +00001240 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001241 if (ospf_area_vlink_count (ospf, area))
1242 return 0;
1243
1244 if (area->external_routing != OSPF_AREA_STUB)
1245 ospf_area_type_set (area, OSPF_AREA_STUB);
1246
1247 return 1;
1248}
1249
1250int
1251ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1252{
1253 struct ospf_area *area;
1254
paul68980082003-03-25 05:07:42 +00001255 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001256 if (area == NULL)
1257 return 1;
1258
1259 if (area->external_routing == OSPF_AREA_STUB)
1260 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1261
paul68980082003-03-25 05:07:42 +00001262 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001263
1264 return 1;
1265}
1266
1267int
1268ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1269{
1270 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001271 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001272
paul68980082003-03-25 05:07:42 +00001273 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001274 area->no_summary = 1;
1275
1276 return 1;
1277}
1278
1279int
1280ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1281{
1282 struct ospf_area *area;
1283
paul68980082003-03-25 05:07:42 +00001284 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001285 if (area == NULL)
1286 return 0;
1287
1288 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001289 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001290
1291 return 1;
1292}
1293
1294int
1295ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1296{
1297 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001298 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001299
paul68980082003-03-25 05:07:42 +00001300 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001301 if (ospf_area_vlink_count (ospf, area))
1302 return 0;
1303
1304 if (area->external_routing != OSPF_AREA_NSSA)
1305 {
1306 ospf_area_type_set (area, OSPF_AREA_NSSA);
1307 ospf->anyNSSA++;
1308 }
1309
paul084c7842003-06-22 08:35:18 +00001310 /* set NSSA area defaults */
1311 area->no_summary = 0;
1312 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001313 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001314 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1315
paul718e3742002-12-13 20:15:29 +00001316 return 1;
1317}
1318
1319int
1320ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1321{
1322 struct ospf_area *area;
1323
paul68980082003-03-25 05:07:42 +00001324 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001325 if (area == NULL)
1326 return 0;
1327
1328 if (area->external_routing == OSPF_AREA_NSSA)
1329 {
1330 ospf->anyNSSA--;
1331 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1332 }
1333
paul68980082003-03-25 05:07:42 +00001334 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001335
1336 return 1;
1337}
1338
1339int
1340ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1341 int role)
1342{
1343 struct ospf_area *area;
1344
paul68980082003-03-25 05:07:42 +00001345 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001346 if (area == NULL)
1347 return 0;
1348
paul084c7842003-06-22 08:35:18 +00001349 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001350
1351 return 1;
1352}
1353
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001354#if 0
paul4dadc292005-05-06 21:37:42 +00001355/* XXX: unused? Leave for symmetry? */
1356static int
paul718e3742002-12-13 20:15:29 +00001357ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1358 struct in_addr area_id)
1359{
1360 struct ospf_area *area;
1361
paul68980082003-03-25 05:07:42 +00001362 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001363 if (area == NULL)
1364 return 0;
1365
paul084c7842003-06-22 08:35:18 +00001366 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001367
paul68980082003-03-25 05:07:42 +00001368 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001369
1370 return 1;
1371}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001372#endif
paul718e3742002-12-13 20:15:29 +00001373
1374int
paul68980082003-03-25 05:07:42 +00001375ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001376 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001377{
1378 struct access_list *list;
1379 list = access_list_lookup (AFI_IP, list_name);
1380
1381 EXPORT_LIST (area) = list;
1382
1383 if (EXPORT_NAME (area))
1384 free (EXPORT_NAME (area));
1385
1386 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001387 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001388
1389 return 1;
1390}
1391
1392int
paul68980082003-03-25 05:07:42 +00001393ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001394{
1395
1396 EXPORT_LIST (area) = 0;
1397
1398 if (EXPORT_NAME (area))
1399 free (EXPORT_NAME (area));
1400
1401 EXPORT_NAME (area) = NULL;
1402
paul68980082003-03-25 05:07:42 +00001403 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001404
paul68980082003-03-25 05:07:42 +00001405 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001406
1407 return 1;
1408}
1409
1410int
paul6c835672004-10-11 11:00:30 +00001411ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1412 const char *name)
paul718e3742002-12-13 20:15:29 +00001413{
1414 struct access_list *list;
1415 list = access_list_lookup (AFI_IP, name);
1416
1417 IMPORT_LIST (area) = list;
1418
1419 if (IMPORT_NAME (area))
1420 free (IMPORT_NAME (area));
1421
1422 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001423 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001424
1425 return 1;
1426}
1427
1428int
paul68980082003-03-25 05:07:42 +00001429ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001430{
1431 IMPORT_LIST (area) = 0;
1432
1433 if (IMPORT_NAME (area))
1434 free (IMPORT_NAME (area));
1435
1436 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001437 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001438
paul68980082003-03-25 05:07:42 +00001439 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001440
1441 return 1;
1442}
1443
1444int
paul718e3742002-12-13 20:15:29 +00001445ospf_timers_refresh_set (struct ospf *ospf, int interval)
1446{
1447 int time_left;
1448
1449 if (ospf->lsa_refresh_interval == interval)
1450 return 1;
1451
1452 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001453 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001454
1455 if (time_left > interval)
1456 {
1457 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1458 ospf->t_lsa_refresher =
1459 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1460 }
1461 ospf->lsa_refresh_interval = interval;
1462
1463 return 1;
1464}
1465
1466int
1467ospf_timers_refresh_unset (struct ospf *ospf)
1468{
1469 int time_left;
1470
1471 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001472 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001473
1474 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1475 {
1476 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1477 ospf->t_lsa_refresher =
1478 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1479 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1480 }
1481
1482 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1483
1484 return 1;
1485}
1486
David Lamparter6b0655a2014-06-04 06:53:35 +02001487
paul4dadc292005-05-06 21:37:42 +00001488static struct ospf_nbr_nbma *
1489ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001490{
1491 struct ospf_nbr_nbma *nbr_nbma;
1492
Stephen Hemminger393deb92008-08-18 14:13:29 -07001493 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001494 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001495
1496 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1497 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1498
1499 return nbr_nbma;
1500}
1501
paul4dadc292005-05-06 21:37:42 +00001502static void
paul718e3742002-12-13 20:15:29 +00001503ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1504{
1505 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1506}
1507
paul4dadc292005-05-06 21:37:42 +00001508static void
paul718e3742002-12-13 20:15:29 +00001509ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1510{
1511 struct route_node *rn;
1512 struct prefix_ipv4 p;
1513
1514 p.family = AF_INET;
1515 p.prefix = nbr_nbma->addr;
1516 p.prefixlen = IPV4_MAX_BITLEN;
1517
1518 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1519 if (rn)
1520 {
1521 ospf_nbr_nbma_free (rn->info);
1522 rn->info = NULL;
1523 route_unlock_node (rn);
1524 route_unlock_node (rn);
1525 }
1526}
1527
paul4dadc292005-05-06 21:37:42 +00001528static void
paul718e3742002-12-13 20:15:29 +00001529ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1530{
1531 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1532
1533 if (nbr_nbma->nbr)
1534 {
1535 nbr_nbma->nbr->nbr_nbma = NULL;
1536 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1537 }
1538
1539 if (nbr_nbma->oi)
1540 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1541}
1542
paul4dadc292005-05-06 21:37:42 +00001543static void
paul718e3742002-12-13 20:15:29 +00001544ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1545 struct ospf_interface *oi)
1546{
1547 struct ospf_neighbor *nbr;
1548 struct route_node *rn;
1549 struct prefix p;
1550
1551 if (oi->type != OSPF_IFTYPE_NBMA)
1552 return;
1553
1554 if (nbr_nbma->nbr != NULL)
1555 return;
1556
1557 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1558 return;
1559
1560 nbr_nbma->oi = oi;
1561 listnode_add (oi->nbr_nbma, nbr_nbma);
1562
1563 /* Get neighbor information from table. */
1564 p.family = AF_INET;
1565 p.prefixlen = IPV4_MAX_BITLEN;
1566 p.u.prefix4 = nbr_nbma->addr;
1567
1568 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1569 if (rn->info)
1570 {
1571 nbr = rn->info;
1572 nbr->nbr_nbma = nbr_nbma;
1573 nbr_nbma->nbr = nbr;
1574
1575 route_unlock_node (rn);
1576 }
1577 else
1578 {
1579 nbr = rn->info = ospf_nbr_new (oi);
1580 nbr->state = NSM_Down;
1581 nbr->src = nbr_nbma->addr;
1582 nbr->nbr_nbma = nbr_nbma;
1583 nbr->priority = nbr_nbma->priority;
1584 nbr->address = p;
1585
1586 nbr_nbma->nbr = nbr;
1587
1588 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1589 }
1590}
1591
1592void
paul68980082003-03-25 05:07:42 +00001593ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001594{
1595 struct ospf_nbr_nbma *nbr_nbma;
1596 struct route_node *rn;
1597 struct prefix_ipv4 p;
1598
1599 if (oi->type != OSPF_IFTYPE_NBMA)
1600 return;
1601
paul68980082003-03-25 05:07:42 +00001602 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001603 if ((nbr_nbma = rn->info))
1604 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1605 {
1606 p.family = AF_INET;
1607 p.prefix = nbr_nbma->addr;
1608 p.prefixlen = IPV4_MAX_BITLEN;
1609
1610 if (prefix_match (oi->address, (struct prefix *)&p))
1611 ospf_nbr_nbma_add (nbr_nbma, oi);
1612 }
1613}
1614
1615struct ospf_nbr_nbma *
1616ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1617{
1618 struct route_node *rn;
1619 struct prefix_ipv4 p;
1620
1621 p.family = AF_INET;
1622 p.prefix = nbr_addr;
1623 p.prefixlen = IPV4_MAX_BITLEN;
1624
1625 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1626 if (rn)
1627 {
1628 route_unlock_node (rn);
1629 return rn->info;
1630 }
1631 return NULL;
1632}
1633
1634struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001635ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001636{
1637#if 0
1638 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001639 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001640#endif
1641
paul68980082003-03-25 05:07:42 +00001642 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001643 return NULL;
1644
1645#if 0
paul1eb8ef22005-04-07 07:30:20 +00001646 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001647 {
paul718e3742002-12-13 20:15:29 +00001648 if (first)
1649 {
1650 *addr = nbr_nbma->addr;
1651 return nbr_nbma;
1652 }
1653 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1654 {
1655 *addr = nbr_nbma->addr;
1656 return nbr_nbma;
1657 }
1658 }
1659#endif
1660 return NULL;
1661}
1662
1663int
1664ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1665{
1666 struct ospf_nbr_nbma *nbr_nbma;
1667 struct ospf_interface *oi;
1668 struct prefix_ipv4 p;
1669 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001670 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001671
1672 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1673 if (nbr_nbma)
1674 return 0;
1675
1676 nbr_nbma = ospf_nbr_nbma_new ();
1677 nbr_nbma->addr = nbr_addr;
1678
1679 p.family = AF_INET;
1680 p.prefix = nbr_addr;
1681 p.prefixlen = IPV4_MAX_BITLEN;
1682
1683 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
Joakim Tjernlund4de398e2010-03-08 13:58:14 +01001684 if (rn->info)
1685 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001686 rn->info = nbr_nbma;
1687
paul1eb8ef22005-04-07 07:30:20 +00001688 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001689 {
paul718e3742002-12-13 20:15:29 +00001690 if (oi->type == OSPF_IFTYPE_NBMA)
1691 if (prefix_match (oi->address, (struct prefix *)&p))
1692 {
1693 ospf_nbr_nbma_add (nbr_nbma, oi);
1694 break;
1695 }
1696 }
1697
1698 return 1;
1699}
1700
1701int
1702ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1703{
1704 struct ospf_nbr_nbma *nbr_nbma;
1705
1706 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1707 if (nbr_nbma == NULL)
1708 return 0;
1709
1710 ospf_nbr_nbma_down (nbr_nbma);
1711 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1712
1713 return 1;
1714}
1715
1716int
1717ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1718 u_char priority)
1719{
1720 struct ospf_nbr_nbma *nbr_nbma;
1721
1722 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1723 if (nbr_nbma == NULL)
1724 return 0;
1725
1726 if (nbr_nbma->priority != priority)
1727 nbr_nbma->priority = priority;
1728
1729 return 1;
1730}
1731
1732int
1733ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1734{
1735 struct ospf_nbr_nbma *nbr_nbma;
1736
1737 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1738 if (nbr_nbma == NULL)
1739 return 0;
1740
1741 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1742 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1743
1744 return 1;
1745}
1746
1747int
1748ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001749 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001750{
1751 struct ospf_nbr_nbma *nbr_nbma;
1752
1753 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1754 if (nbr_nbma == NULL)
1755 return 0;
1756
1757 if (nbr_nbma->v_poll != interval)
1758 {
1759 nbr_nbma->v_poll = interval;
1760 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1761 {
1762 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1763 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1764 nbr_nbma->v_poll);
1765 }
1766 }
1767
1768 return 1;
1769}
1770
1771int
1772ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1773{
1774 struct ospf_nbr_nbma *nbr_nbma;
1775
1776 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1777 if (nbr_nbma == NULL)
1778 return 0;
1779
1780 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1781 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1782
1783 return 1;
1784}
1785
paul718e3742002-12-13 20:15:29 +00001786void
paul020709f2003-04-04 02:44:16 +00001787ospf_master_init ()
1788{
1789 memset (&ospf_master, 0, sizeof (struct ospf_master));
1790
1791 om = &ospf_master;
1792 om->ospf = list_new ();
1793 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001794 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001795}