blob: f6669d7f5590c3b3c75f0113d335b5976e8ee61c [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 *);
72static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
73 struct interface *);
Stephen Hemminger917e2992009-12-03 19:07:00 +030074static int ospf_network_match_iface (const struct connected *,
75 const struct prefix *);
paul88d6cf32005-10-29 12:50:09 +000076static void ospf_finish_final (struct ospf *);
paul718e3742002-12-13 20:15:29 +000077
paul718e3742002-12-13 20:15:29 +000078#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
David Lamparter6b0655a2014-06-04 06:53:35 +020079
paul718e3742002-12-13 20:15:29 +000080void
paul68980082003-03-25 05:07:42 +000081ospf_router_id_update (struct ospf *ospf)
paul718e3742002-12-13 20:15:29 +000082{
paul718e3742002-12-13 20:15:29 +000083 struct in_addr router_id, router_id_old;
paul1eb8ef22005-04-07 07:30:20 +000084 struct ospf_interface *oi;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +010085 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +000086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000087
88 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +000089 zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +000090
paul68980082003-03-25 05:07:42 +000091 router_id_old = ospf->router_id;
paul718e3742002-12-13 20:15:29 +000092
Andrew J. Schorr16700082006-07-27 22:29:06 +000093 /* Select the router ID based on these priorities:
94 1. Statically assigned router ID is always the first choice.
95 2. If there is no statically assigned router ID, then try to stick
96 with the most recent value, since changing router ID's is very
97 disruptive.
98 3. Last choice: just go with whatever the zebra daemon recommends.
99 */
paul68980082003-03-25 05:07:42 +0000100 if (ospf->router_id_static.s_addr != 0)
101 router_id = ospf->router_id_static;
Andrew J. Schorr16700082006-07-27 22:29:06 +0000102 else if (ospf->router_id.s_addr != 0)
103 router_id = ospf->router_id;
paul718e3742002-12-13 20:15:29 +0000104 else
hasso18a6dce2004-10-03 18:18:34 +0000105 router_id = router_id_zebra;
paul718e3742002-12-13 20:15:29 +0000106
paul68980082003-03-25 05:07:42 +0000107 ospf->router_id = router_id;
paul718e3742002-12-13 20:15:29 +0000108
109 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +0000110 zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
paul718e3742002-12-13 20:15:29 +0000111
112 if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
113 {
paul1eb8ef22005-04-07 07:30:20 +0000114 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
Joakim Tjernlund94266fa2009-11-19 15:27:30 +0100115 {
116 /* Some nbrs are identified by router_id, these needs
117 * to be rebuilt. Possible optimization would be to do
118 * oi->nbr_self->router_id = router_id for
119 * !(virtual | ptop) links
120 */
Paul Jakmac920e512015-09-08 15:31:45 +0100121 ospf_nbr_self_reset (oi);
Joakim Tjernlund94266fa2009-11-19 15:27:30 +0100122 }
paul718e3742002-12-13 20:15:29 +0000123
124 /* If AS-external-LSA is queued, then flush those LSAs. */
paul68980082003-03-25 05:07:42 +0000125 if (router_id_old.s_addr == 0 && ospf->external_origin)
paul718e3742002-12-13 20:15:29 +0000126 {
127 int type;
128 /* Originate each redistributed external route. */
129 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
paul68980082003-03-25 05:07:42 +0000130 if (ospf->external_origin & (1 << type))
paul718e3742002-12-13 20:15:29 +0000131 thread_add_event (master, ospf_external_lsa_originate_timer,
paul68980082003-03-25 05:07:42 +0000132 ospf, type);
paul718e3742002-12-13 20:15:29 +0000133 /* Originate Deafult. */
paul68980082003-03-25 05:07:42 +0000134 if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
Paul Jakma4021b602006-05-12 22:55:41 +0000135 thread_add_event (master, ospf_default_originate_timer, ospf, 0);
paul718e3742002-12-13 20:15:29 +0000136
paul68980082003-03-25 05:07:42 +0000137 ospf->external_origin = 0;
paul718e3742002-12-13 20:15:29 +0000138 }
139
Paul Jakmac363d382010-01-24 22:42:13 +0000140 /* update router-lsa's for each area */
141 ospf_router_lsa_update (ospf);
paulb29800a2005-11-20 14:50:45 +0000142
143 /* update ospf_interface's */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100144 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
145 ospf_if_update (ospf, ifp);
paul718e3742002-12-13 20:15:29 +0000146 }
147}
David Lamparter6b0655a2014-06-04 06:53:35 +0200148
paul718e3742002-12-13 20:15:29 +0000149/* For OSPF area sort by area id. */
paul4dadc292005-05-06 21:37:42 +0000150static int
paul718e3742002-12-13 20:15:29 +0000151ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
152{
153 if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
154 return 1;
155 if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
156 return -1;
157 return 0;
158}
159
160/* Allocate new ospf structure. */
paul4dadc292005-05-06 21:37:42 +0000161static struct ospf *
162ospf_new (void)
paul718e3742002-12-13 20:15:29 +0000163{
164 int i;
165
166 struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
167
168 new->router_id.s_addr = htonl (0);
169 new->router_id_static.s_addr = htonl (0);
170
pauld57834f2005-07-12 20:04:22 +0000171 new->abr_type = OSPF_ABR_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000172 new->oiflist = list_new ();
173 new->vlinks = list_new ();
174 new->areas = list_new ();
175 new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
176 new->networks = route_table_init ();
177 new->nbr_nbma = route_table_init ();
178
179 new->lsdb = ospf_lsdb_new ();
180
181 new->default_originate = DEFAULT_ORIGINATE_NONE;
182
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000183 new->passive_interface_default = OSPF_IF_ACTIVE;
184
paul718e3742002-12-13 20:15:29 +0000185 new->new_external_route = route_table_init ();
186 new->old_external_route = route_table_init ();
187 new->external_lsas = route_table_init ();
paul88d6cf32005-10-29 12:50:09 +0000188
189 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paul31a59762005-11-14 11:11:11 +0000190 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800191 new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET;
192
paul718e3742002-12-13 20:15:29 +0000193 /* Distribute parameter init. */
194 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
195 {
196 new->dmetric[i].type = -1;
197 new->dmetric[i].value = -1;
198 }
199 new->default_metric = -1;
200 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
201
Michael Rossberg2ef762e2015-07-27 07:56:25 +0200202 /* LSA timers */
203 new->min_ls_interval = OSPF_MIN_LS_INTERVAL;
204 new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
205
paul718e3742002-12-13 20:15:29 +0000206 /* SPF timer value init. */
207 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
208 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
pauld24f6e22005-10-21 09:23:12 +0000209 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
210 new->spf_hold_multiplier = 1;
paul718e3742002-12-13 20:15:29 +0000211
212 /* MaxAge init. */
Dinesh Dutt2449fcd2013-08-24 07:54:17 +0000213 new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800214 new->maxage_lsa = route_table_init();
paul718e3742002-12-13 20:15:29 +0000215 new->t_maxage_walker =
216 thread_add_timer (master, ospf_lsa_maxage_walker,
paul68980082003-03-25 05:07:42 +0000217 new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
paul718e3742002-12-13 20:15:29 +0000218
219 /* Distance table init. */
220 new->distance_table = route_table_init ();
221
222 new->lsa_refresh_queue.index = 0;
223 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
224 new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
225 new, new->lsa_refresh_interval);
Paul Jakma2518efd2006-08-27 06:49:29 +0000226 new->lsa_refresher_started = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +0000227
ajs5c333492005-02-23 15:43:01 +0000228 if ((new->fd = ospf_sock_init()) < 0)
229 {
230 zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
231 "a socket");
232 exit(1);
233 }
Denis Ovsienkof102e752007-09-18 09:01:13 +0000234 new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
235 if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
Andrew Certain0798cee2012-12-04 13:43:42 -0800236 zlog_debug ("%s: starting with OSPF send buffer size %u",
Denis Ovsienkof102e752007-09-18 09:01:13 +0000237 __func__, new->maxsndbuflen);
ajs5c333492005-02-23 15:43:01 +0000238 if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
239 {
240 zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
241 OSPF_MAX_PACKET_SIZE+1);
242 exit(1);
243 }
244 new->t_read = thread_add_read (master, ospf_read, new, new->fd);
paul718e3742002-12-13 20:15:29 +0000245 new->oi_write_q = list_new ();
246
247 return new;
248}
249
250struct ospf *
paul020709f2003-04-04 02:44:16 +0000251ospf_lookup ()
252{
253 if (listcount (om->ospf) == 0)
254 return NULL;
255
paul1eb8ef22005-04-07 07:30:20 +0000256 return listgetdata (listhead (om->ospf));
paul020709f2003-04-04 02:44:16 +0000257}
258
paul4dadc292005-05-06 21:37:42 +0000259static void
paul020709f2003-04-04 02:44:16 +0000260ospf_add (struct ospf *ospf)
261{
262 listnode_add (om->ospf, ospf);
263}
264
paul4dadc292005-05-06 21:37:42 +0000265static void
paul020709f2003-04-04 02:44:16 +0000266ospf_delete (struct ospf *ospf)
267{
268 listnode_delete (om->ospf, ospf);
269}
270
271struct ospf *
paul718e3742002-12-13 20:15:29 +0000272ospf_get ()
273{
paul020709f2003-04-04 02:44:16 +0000274 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +0000275
paul020709f2003-04-04 02:44:16 +0000276 ospf = ospf_lookup ();
277 if (ospf == NULL)
278 {
279 ospf = ospf_new ();
280 ospf_add (ospf);
paul718e3742002-12-13 20:15:29 +0000281
paul020709f2003-04-04 02:44:16 +0000282 if (ospf->router_id_static.s_addr == 0)
283 ospf_router_id_update (ospf);
paul718e3742002-12-13 20:15:29 +0000284
285#ifdef HAVE_OPAQUE_LSA
paul020709f2003-04-04 02:44:16 +0000286 ospf_opaque_type11_lsa_init (ospf);
paul718e3742002-12-13 20:15:29 +0000287#endif /* HAVE_OPAQUE_LSA */
paul020709f2003-04-04 02:44:16 +0000288 }
paul68980082003-03-25 05:07:42 +0000289
290 return ospf;
paul718e3742002-12-13 20:15:29 +0000291}
David Lamparter6b0655a2014-06-04 06:53:35 +0200292
paulc9c93d52005-11-26 13:31:11 +0000293/* Handle the second half of deferred shutdown. This is called either
294 * from the deferred-shutdown timer thread, or directly through
295 * ospf_deferred_shutdown_check.
paul88d6cf32005-10-29 12:50:09 +0000296 *
297 * Function is to cleanup G-R state, if required then call ospf_finish_final
298 * to complete shutdown of this ospf instance. Possibly exit if the
299 * whole process is being shutdown and this was the last OSPF instance.
300 */
301static void
paulc9c93d52005-11-26 13:31:11 +0000302ospf_deferred_shutdown_finish (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000303{
304 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
paulc9c93d52005-11-26 13:31:11 +0000305 OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
paul88d6cf32005-10-29 12:50:09 +0000306
307 ospf_finish_final (ospf);
308
309 /* *ospf is now invalid */
310
311 /* ospfd being shut-down? If so, was this the last ospf instance? */
312 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
313 && (listcount (om->ospf) == 0))
314 exit (0);
315
316 return;
317}
318
319/* Timer thread for G-R */
320static int
paulc9c93d52005-11-26 13:31:11 +0000321ospf_deferred_shutdown_timer (struct thread *t)
paul88d6cf32005-10-29 12:50:09 +0000322{
323 struct ospf *ospf = THREAD_ARG(t);
324
paulc9c93d52005-11-26 13:31:11 +0000325 ospf_deferred_shutdown_finish (ospf);
paul88d6cf32005-10-29 12:50:09 +0000326
327 return 0;
328}
329
paulc9c93d52005-11-26 13:31:11 +0000330/* Check whether deferred-shutdown must be scheduled, otherwise call
paul88d6cf32005-10-29 12:50:09 +0000331 * down directly into second-half of instance shutdown.
332 */
333static void
paulc9c93d52005-11-26 13:31:11 +0000334ospf_deferred_shutdown_check (struct ospf *ospf)
paul88d6cf32005-10-29 12:50:09 +0000335{
336 unsigned long timeout;
337 struct listnode *ln;
338 struct ospf_area *area;
339
paulc9c93d52005-11-26 13:31:11 +0000340 /* deferred shutdown already running? */
341 if (ospf->t_deferred_shutdown)
paul88d6cf32005-10-29 12:50:09 +0000342 return;
343
344 /* Should we try push out max-metric LSAs? */
345 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
346 {
347 for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
348 {
349 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
350
351 if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
Paul Jakmac363d382010-01-24 22:42:13 +0000352 ospf_router_lsa_update_area (area);
paul88d6cf32005-10-29 12:50:09 +0000353 }
354 timeout = ospf->stub_router_shutdown_time;
355 }
356 else
paulc9c93d52005-11-26 13:31:11 +0000357 {
358 /* No timer needed */
359 ospf_deferred_shutdown_finish (ospf);
360 return;
361 }
paul88d6cf32005-10-29 12:50:09 +0000362
paulc9c93d52005-11-26 13:31:11 +0000363 OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
paul88d6cf32005-10-29 12:50:09 +0000364 timeout);
365 return;
366}
David Lamparter6b0655a2014-06-04 06:53:35 +0200367
paul88d6cf32005-10-29 12:50:09 +0000368/* Shut down the entire process */
369void
370ospf_terminate (void)
371{
372 struct ospf *ospf;
373 struct listnode *node, *nnode;
374
375 /* shutdown already in progress */
376 if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
377 return;
378
379 SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
380
Andrew J. Schorr4056a542007-02-27 13:55:46 +0000381 /* exit immediately if OSPF not actually running */
382 if (listcount(om->ospf) == 0)
383 exit(0);
384
paul88d6cf32005-10-29 12:50:09 +0000385 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
386 ospf_finish (ospf);
387
388 /* Deliberately go back up, hopefully to thread scheduler, as
389 * One or more ospf_finish()'s may have deferred shutdown to a timer
390 * thread
391 */
392}
paul718e3742002-12-13 20:15:29 +0000393
394void
395ospf_finish (struct ospf *ospf)
396{
paulc9c93d52005-11-26 13:31:11 +0000397 /* let deferred shutdown decide */
398 ospf_deferred_shutdown_check (ospf);
paul88d6cf32005-10-29 12:50:09 +0000399
paulc9c93d52005-11-26 13:31:11 +0000400 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
paul88d6cf32005-10-29 12:50:09 +0000401 * deferred to expiry of G-S timer thread. Return back up, hopefully
402 * to thread scheduler.
403 */
paulc9c93d52005-11-26 13:31:11 +0000404 return;
paul88d6cf32005-10-29 12:50:09 +0000405}
406
407/* Final cleanup of ospf instance */
408static void
409ospf_finish_final (struct ospf *ospf)
410{
paul718e3742002-12-13 20:15:29 +0000411 struct route_node *rn;
412 struct ospf_nbr_nbma *nbr_nbma;
paul68980082003-03-25 05:07:42 +0000413 struct ospf_lsa *lsa;
paul1eb8ef22005-04-07 07:30:20 +0000414 struct ospf_interface *oi;
415 struct ospf_area *area;
416 struct ospf_vl_data *vl_data;
417 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000418 int i;
419
420#ifdef HAVE_OPAQUE_LSA
421 ospf_opaque_type11_lsa_term (ospf);
422#endif /* HAVE_OPAQUE_LSA */
paul88d6cf32005-10-29 12:50:09 +0000423
424 /* be nice if this worked, but it doesn't */
425 /*ospf_flush_self_originated_lsas_now (ospf);*/
426
427 /* Unregister redistribution */
paul718e3742002-12-13 20:15:29 +0000428 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
paul020709f2003-04-04 02:44:16 +0000429 ospf_redistribute_unset (ospf, i);
Paul Jakma29b5a042006-08-27 08:01:20 +0000430 ospf_redistribute_default_unset (ospf);
paul718e3742002-12-13 20:15:29 +0000431
paul1eb8ef22005-04-07 07:30:20 +0000432 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
433 ospf_remove_vls_through_area (ospf, area);
paul718e3742002-12-13 20:15:29 +0000434
paul1eb8ef22005-04-07 07:30:20 +0000435 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
436 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +0000437
438 list_delete (ospf->vlinks);
439
440 /* Reset interface. */
paul1eb8ef22005-04-07 07:30:20 +0000441 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
442 ospf_if_free (oi);
paul718e3742002-12-13 20:15:29 +0000443
444 /* Clear static neighbors */
445 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
446 if ((nbr_nbma = rn->info))
447 {
448 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
449
450 if (nbr_nbma->nbr)
451 {
452 nbr_nbma->nbr->nbr_nbma = NULL;
453 nbr_nbma->nbr = NULL;
454 }
455
456 if (nbr_nbma->oi)
457 {
458 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
459 nbr_nbma->oi = NULL;
460 }
461
462 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
463 }
464
465 route_table_finish (ospf->nbr_nbma);
466
467 /* Clear networks and Areas. */
468 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
469 {
470 struct ospf_network *network;
471
472 if ((network = rn->info) != NULL)
473 {
paul68980082003-03-25 05:07:42 +0000474 ospf_network_free (ospf, network);
paul718e3742002-12-13 20:15:29 +0000475 rn->info = NULL;
476 route_unlock_node (rn);
477 }
478 }
479
paul1eb8ef22005-04-07 07:30:20 +0000480 for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
paul718e3742002-12-13 20:15:29 +0000481 {
paul718e3742002-12-13 20:15:29 +0000482 listnode_delete (ospf->areas, area);
483 ospf_area_free (area);
484 }
485
486 /* Cancel all timers. */
487 OSPF_TIMER_OFF (ospf->t_external_lsa);
paul718e3742002-12-13 20:15:29 +0000488 OSPF_TIMER_OFF (ospf->t_spf_calc);
489 OSPF_TIMER_OFF (ospf->t_ase_calc);
490 OSPF_TIMER_OFF (ospf->t_maxage);
491 OSPF_TIMER_OFF (ospf->t_maxage_walker);
492 OSPF_TIMER_OFF (ospf->t_abr_task);
paul88d6cf32005-10-29 12:50:09 +0000493 OSPF_TIMER_OFF (ospf->t_asbr_check);
paul718e3742002-12-13 20:15:29 +0000494 OSPF_TIMER_OFF (ospf->t_distribute_update);
495 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
496 OSPF_TIMER_OFF (ospf->t_read);
497 OSPF_TIMER_OFF (ospf->t_write);
paul31a59762005-11-14 11:11:11 +0000498#ifdef HAVE_OPAQUE_LSA
paul88d6cf32005-10-29 12:50:09 +0000499 OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
paul31a59762005-11-14 11:11:11 +0000500#endif
paul718e3742002-12-13 20:15:29 +0000501
502 close (ospf->fd);
ajs5c333492005-02-23 15:43:01 +0000503 stream_free(ospf->ibuf);
paul718e3742002-12-13 20:15:29 +0000504
505#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000506 LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
507 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000508#endif /* HAVE_OPAQUE_LSA */
paul68980082003-03-25 05:07:42 +0000509 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
510 ospf_discard_from_db (ospf, ospf->lsdb, lsa);
511
paul718e3742002-12-13 20:15:29 +0000512 ospf_lsdb_delete_all (ospf->lsdb);
513 ospf_lsdb_free (ospf->lsdb);
514
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800515 for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn))
516 {
517 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000518
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800519 if ((lsa = rn->info) != NULL)
520 {
521 ospf_lsa_unlock (&lsa);
522 rn->info = NULL;
523 }
524 route_unlock_node (rn);
525 }
526 route_table_finish (ospf->maxage_lsa);
paul718e3742002-12-13 20:15:29 +0000527
528 if (ospf->old_table)
529 ospf_route_table_free (ospf->old_table);
530 if (ospf->new_table)
531 {
532 ospf_route_delete (ospf->new_table);
533 ospf_route_table_free (ospf->new_table);
534 }
535 if (ospf->old_rtrs)
536 ospf_rtrs_free (ospf->old_rtrs);
537 if (ospf->new_rtrs)
538 ospf_rtrs_free (ospf->new_rtrs);
539 if (ospf->new_external_route)
540 {
541 ospf_route_delete (ospf->new_external_route);
542 ospf_route_table_free (ospf->new_external_route);
543 }
544 if (ospf->old_external_route)
545 {
546 ospf_route_delete (ospf->old_external_route);
547 ospf_route_table_free (ospf->old_external_route);
548 }
549 if (ospf->external_lsas)
550 {
551 ospf_ase_external_lsas_finish (ospf->external_lsas);
552 }
553
554 list_delete (ospf->areas);
555
556 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
557 if (EXTERNAL_INFO (i) != NULL)
558 for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
559 {
560 if (rn->info == NULL)
561 continue;
562
563 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
564 rn->info = NULL;
565 route_unlock_node (rn);
566 }
567
paul68980082003-03-25 05:07:42 +0000568 ospf_distance_reset (ospf);
paul718e3742002-12-13 20:15:29 +0000569 route_table_finish (ospf->distance_table);
570
paul020709f2003-04-04 02:44:16 +0000571 ospf_delete (ospf);
paul718e3742002-12-13 20:15:29 +0000572
paul020709f2003-04-04 02:44:16 +0000573 XFREE (MTYPE_OSPF_TOP, ospf);
paul718e3742002-12-13 20:15:29 +0000574}
575
David Lamparter6b0655a2014-06-04 06:53:35 +0200576
paul718e3742002-12-13 20:15:29 +0000577/* allocate new OSPF Area object */
paul4dadc292005-05-06 21:37:42 +0000578static struct ospf_area *
paul68980082003-03-25 05:07:42 +0000579ospf_area_new (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000580{
581 struct ospf_area *new;
582
583 /* Allocate new config_network. */
584 new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
585
paul68980082003-03-25 05:07:42 +0000586 new->ospf = ospf;
paul718e3742002-12-13 20:15:29 +0000587
588 new->area_id = area_id;
589
590 new->external_routing = OSPF_AREA_DEFAULT;
591 new->default_cost = 1;
592 new->auth_type = OSPF_AUTH_NULL;
paul88d6cf32005-10-29 12:50:09 +0000593
paul718e3742002-12-13 20:15:29 +0000594 /* New LSDB init. */
595 new->lsdb = ospf_lsdb_new ();
596
597 /* Self-originated LSAs initialize. */
598 new->router_lsa_self = NULL;
599
600#ifdef HAVE_OPAQUE_LSA
601 ospf_opaque_type10_lsa_init (new);
602#endif /* HAVE_OPAQUE_LSA */
603
604 new->oiflist = list_new ();
605 new->ranges = route_table_init ();
606
607 if (area_id.s_addr == OSPF_AREA_BACKBONE)
paul68980082003-03-25 05:07:42 +0000608 ospf->backbone = new;
paul718e3742002-12-13 20:15:29 +0000609
610 return new;
611}
612
Stephen Hemminger917e2992009-12-03 19:07:00 +0300613static void
paul718e3742002-12-13 20:15:29 +0000614ospf_area_free (struct ospf_area *area)
615{
paul68980082003-03-25 05:07:42 +0000616 struct route_node *rn;
617 struct ospf_lsa *lsa;
618
paul718e3742002-12-13 20:15:29 +0000619 /* Free LSDBs. */
paul68980082003-03-25 05:07:42 +0000620 LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
621 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
622 LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
623 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
624 LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
625 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
626 LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
627 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000628
paul68980082003-03-25 05:07:42 +0000629 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
630 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000631#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000632 LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
633 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
634 LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
635 ospf_discard_from_db (area->ospf, area->lsdb, lsa);
paul718e3742002-12-13 20:15:29 +0000636#endif /* HAVE_OPAQUE_LSA */
637
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);
654#ifdef HAVE_OPAQUE_LSA
655 OSPF_TIMER_OFF (area->t_opaque_lsa_self);
656#endif /* HAVE_OPAQUE_LSA */
657
paul718e3742002-12-13 20:15:29 +0000658 if (OSPF_IS_AREA_BACKBONE (area))
paul68980082003-03-25 05:07:42 +0000659 area->ospf->backbone = NULL;
paul718e3742002-12-13 20:15:29 +0000660
661 XFREE (MTYPE_OSPF_AREA, area);
662}
663
664void
paul68980082003-03-25 05:07:42 +0000665ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000666{
667 struct ospf_area *area;
668
paul68980082003-03-25 05:07:42 +0000669 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000670 if (area &&
671 listcount (area->oiflist) == 0 &&
672 area->ranges->top == NULL &&
673 area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
674 area->external_routing == OSPF_AREA_DEFAULT &&
675 area->no_summary == 0 &&
676 area->default_cost == 1 &&
677 EXPORT_NAME (area) == NULL &&
678 IMPORT_NAME (area) == NULL &&
679 area->auth_type == OSPF_AUTH_NULL)
680 {
paul68980082003-03-25 05:07:42 +0000681 listnode_delete (ospf->areas, area);
paul718e3742002-12-13 20:15:29 +0000682 ospf_area_free (area);
683 }
684}
685
686struct ospf_area *
paul68980082003-03-25 05:07:42 +0000687ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
paul718e3742002-12-13 20:15:29 +0000688{
689 struct ospf_area *area;
690
paul68980082003-03-25 05:07:42 +0000691 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000692 if (!area)
693 {
paul68980082003-03-25 05:07:42 +0000694 area = ospf_area_new (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000695 area->format = format;
paul68980082003-03-25 05:07:42 +0000696 listnode_add_sort (ospf->areas, area);
697 ospf_check_abr_status (ospf);
Ayan Banerjee4ba4fc82012-12-03 11:17:24 -0800698 if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET)
699 {
700 SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
701 }
paul718e3742002-12-13 20:15:29 +0000702 }
703
704 return area;
705}
706
707struct ospf_area *
paul68980082003-03-25 05:07:42 +0000708ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
paul718e3742002-12-13 20:15:29 +0000709{
710 struct ospf_area *area;
hasso52dc7ee2004-09-23 19:18:23 +0000711 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000712
paul1eb8ef22005-04-07 07:30:20 +0000713 for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
714 if (IPV4_ADDR_SAME (&area->area_id, &area_id))
715 return area;
paul718e3742002-12-13 20:15:29 +0000716
717 return NULL;
718}
719
720void
721ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
722{
723 listnode_add (area->oiflist, oi);
724}
725
726void
727ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
728{
729 listnode_delete (area->oiflist, oi);
730}
731
David Lamparter6b0655a2014-06-04 06:53:35 +0200732
paul718e3742002-12-13 20:15:29 +0000733/* Config network statement related functions. */
paul4dadc292005-05-06 21:37:42 +0000734static struct ospf_network *
paul718e3742002-12-13 20:15:29 +0000735ospf_network_new (struct in_addr area_id, int format)
736{
737 struct ospf_network *new;
738 new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
739
740 new->area_id = area_id;
741 new->format = format;
742
743 return new;
744}
745
Stephen Hemminger917e2992009-12-03 19:07:00 +0300746static void
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200747add_ospf_interface (struct interface *ifp, struct ospf_area *area,
748 struct connected *co)
749{
750 struct ospf_interface *oi;
751
752 oi = ospf_if_new (area->ospf, ifp, co->address);
753 oi->connected = co;
754
755 oi->area = area;
756
757 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
758 oi->output_cost = ospf_if_get_output_cost (oi);
759
760 /* Add pseudo neighbor. */
761 ospf_nbr_add_self (oi);
762
763 /* Relate ospf interface to ospf instance. */
764 oi->ospf = area->ospf;
765
766 /* update network type as interface flag */
767 /* If network type is specified previously,
768 skip network type setting. */
769 oi->type = IF_DEF_PARAMS (ifp)->type;
770
771 ospf_area_add_if (oi->area, oi);
772
773 /* if router_id is not configured, dont bring up
774 * interfaces.
775 * ospf_router_id_update() will call ospf_if_update
776 * whenever r-id is configured instead.
777 */
778 if ((area->ospf->router_id.s_addr != 0)
779 && if_is_operative (ifp))
780 ospf_if_up (oi);
781}
782
783static void
784update_redistributed (struct ospf *ospf, int add_to_ospf)
785{
786 struct route_node *rn;
787 struct external_info *ei;
788
789 if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
790 if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
791 for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
792 rn; rn = route_next (rn))
793 if ((ei = rn->info) != NULL)
794 {
795 if (add_to_ospf)
796 {
797 if (ospf_external_info_find_lsa (ospf, &ei->p))
798 if (!ospf_distribute_check_connected (ospf, ei))
799 ospf_external_lsa_flush (ospf, ei->type, &ei->p,
800 ei->ifindex /*, ei->nexthop */);
801 }
802 else
803 {
804 if (!ospf_external_info_find_lsa (ospf, &ei->p))
805 if (ospf_distribute_check_connected (ospf, ei))
806 ospf_external_lsa_originate (ospf, ei);
807 }
808 }
809}
810
811static void
paul68980082003-03-25 05:07:42 +0000812ospf_network_free (struct ospf *ospf, struct ospf_network *network)
paul718e3742002-12-13 20:15:29 +0000813{
paul68980082003-03-25 05:07:42 +0000814 ospf_area_check_free (ospf, network->area_id);
815 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +0000816 XFREE (MTYPE_OSPF_NETWORK, network);
817}
818
819int
820ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
821 struct in_addr area_id)
822{
823 struct ospf_network *network;
824 struct ospf_area *area;
825 struct route_node *rn;
paul147193a2003-04-19 00:31:59 +0000826 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +0000827
828 rn = route_node_get (ospf->networks, (struct prefix *)p);
829 if (rn->info)
830 {
831 /* There is already same network statement. */
832 route_unlock_node (rn);
833 return 0;
834 }
835
836 rn->info = network = ospf_network_new (area_id, ret);
paul68980082003-03-25 05:07:42 +0000837 area = ospf_area_get (ospf, area_id, ret);
paul718e3742002-12-13 20:15:29 +0000838
839 /* Run network config now. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100840 ospf_network_run ((struct prefix *)p, area);
paul718e3742002-12-13 20:15:29 +0000841
842 /* Update connected redistribute. */
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200843 update_redistributed(ospf, 1); /* interfaces possibly added */
paul68980082003-03-25 05:07:42 +0000844 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +0000845
846 return 1;
847}
848
849int
850ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
851 struct in_addr area_id)
852{
853 struct route_node *rn;
854 struct ospf_network *network;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100855 struct listnode *node, *nnode;
856 struct ospf_interface *oi;
paul718e3742002-12-13 20:15:29 +0000857
858 rn = route_node_lookup (ospf->networks, (struct prefix *)p);
859 if (rn == NULL)
860 return 0;
861
862 network = rn->info;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700863 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000864 if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
865 return 0;
866
paul68980082003-03-25 05:07:42 +0000867 ospf_network_free (ospf, rn->info);
paul718e3742002-12-13 20:15:29 +0000868 rn->info = NULL;
Stephen Hemminger965f54f2009-06-03 16:44:21 -0700869 route_unlock_node (rn); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000870
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100871 /* Find interfaces that not configured already. */
872 for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
873 {
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200874 struct ospf_if_params *params;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100875 int found = 0;
876 struct connected *co = oi->connected;
877
878 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
879 continue;
880
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200881 params = IF_DEF_PARAMS (oi->ifp);
882 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
883 continue;
884
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100885 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
886 {
887 if (rn->info == NULL)
888 continue;
889
890 if (ospf_network_match_iface(co,&rn->p))
891 {
892 found = 1;
893 route_unlock_node (rn);
894 break;
895 }
896 }
897
898 if (found == 0)
Joakim Tjernlund6b274d92010-03-09 06:42:30 +0000899 {
900 ospf_if_free (oi);
901 ospf_area_check_free (ospf, area_id);
902 }
Joakim Tjernlunda49eb302008-09-02 19:06:31 +0100903 }
paul718e3742002-12-13 20:15:29 +0000904
905 /* Update connected redistribute. */
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +0200906 update_redistributed(ospf, 0); /* interfaces possibly removed */
paul718e3742002-12-13 20:15:29 +0000907 return 1;
908}
909
Joakim Tjernlund738bce72009-08-07 13:48:15 +0200910int
911ospf_interface_set (struct interface *ifp)
912{
913 struct ospf_area *area;
914 struct listnode *cnode;
915 struct connected *co;
916 struct ospf *ospf;
917 struct ospf_if_params *params;
918 struct in_addr area_id;
919 int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
920
921 if ((ospf = ospf_lookup ()) == NULL)
922 return 1; /* Ospf not ready yet */
923
924 params = IF_DEF_PARAMS (ifp);
925 area_id = params->if_area;
926
927 area = ospf_area_get (ospf, area_id, ret);
928
929 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
930 {
931 struct ospf_interface *oi;
932
933 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
934 continue;
935
936 oi = ospf_if_table_lookup(ifp, co->address);
937 if (oi)
938 { /* Just adjust area for existing interface */
939 ospf_area_del_if (oi->area, oi);
940 oi->area = area;
941 ospf_area_add_if (oi->area, oi);
942 }
943 else
944 {
945 add_ospf_interface(ifp, area, co);
946 }
947 }
948
949 /* Update connected redistribute. */
950 update_redistributed(ospf, 1); /* interface possibly added */
951 ospf_area_check_free (ospf, area_id);
952
953 return 1;
954}
955
956int
957ospf_interface_unset (struct interface *ifp)
958{
959 struct route_node *rn_oi, *rn;
960 struct ospf *ospf;
961
962 if ((ospf = ospf_lookup ()) == NULL)
963 return 1; /* Ospf not ready yet */
964
965 /* Find interfaces that may need to be removed. */
966 for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
967 {
968 struct ospf_interface *oi;
969 struct connected *co;
970 int found = 0;
971
972 if ( (oi = rn_oi->info) == NULL)
973 continue;
974 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
975 continue;
976 co = oi->connected;
977
978 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
979 {
980 if (rn->info == NULL)
981 continue;
982
983 if (ospf_network_match_iface(co,&rn->p))
984 {
985 found = 1;
986 route_unlock_node (rn);
987 break;
988 }
989 }
990
991 if (found == 0)
992 ospf_if_free (oi);
993 }
994
995 /* Update connected redistribute. */
996 update_redistributed(ospf, 0); /* interfaces possibly removed */
997 return 1;
998 }
999
1000
paul570f7592003-01-25 06:47:41 +00001001/* Check whether interface matches given network
1002 * returns: 1, true. 0, false
1003 */
Stephen Hemminger917e2992009-12-03 19:07:00 +03001004static int
1005ospf_network_match_iface(const struct connected *co, const struct prefix *net)
paul570f7592003-01-25 06:47:41 +00001006{
Andrew J. Schorre4529632006-12-12 19:18:21 +00001007 /* new approach: more elegant and conceptually clean */
1008 return prefix_match(net, CONNECTED_PREFIX(co));
paul570f7592003-01-25 06:47:41 +00001009}
1010
Stephen Hemminger917e2992009-12-03 19:07:00 +03001011static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001012ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
1013 struct interface *ifp)
1014{
1015 struct listnode *cnode;
1016 struct connected *co;
1017
1018 if (memcmp (ifp->name, "VLINK", 5) == 0)
1019 return;
1020
1021 /* if interface prefix is match specified prefix,
1022 then create socket and join multicast group. */
1023 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
1024 {
Joakim Tjernlundf0f63842009-07-27 12:42:29 +02001025
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001026 if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
1027 continue;
1028
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001029 if (p->family == co->address->family
Joakim Tjernlundf0f63842009-07-27 12:42:29 +02001030 && ! ospf_if_table_lookup(ifp, co->address)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001031 && ospf_network_match_iface(co,p))
Joakim Tjernlund7bd7f552009-08-07 13:48:15 +02001032 {
1033 add_ospf_interface(ifp, area, co);
1034 }
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001035 }
1036}
1037
Stephen Hemminger917e2992009-12-03 19:07:00 +03001038static void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001039ospf_network_run (struct prefix *p, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001040{
1041 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00001042 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001043
1044 /* Schedule Router ID Update. */
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001045 if (area->ospf->router_id.s_addr == 0)
1046 ospf_router_id_update (area->ospf);
paulb29800a2005-11-20 14:50:45 +00001047
paul718e3742002-12-13 20:15:29 +00001048 /* Get target interface. */
paul1eb8ef22005-04-07 07:30:20 +00001049 for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001050 ospf_network_run_interface (p, area, ifp);
paul718e3742002-12-13 20:15:29 +00001051}
1052
1053void
1054ospf_ls_upd_queue_empty (struct ospf_interface *oi)
1055{
1056 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00001057 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +00001058 struct list *lst;
paul718e3742002-12-13 20:15:29 +00001059 struct ospf_lsa *lsa;
1060
1061 /* empty ls update queue */
1062 for (rn = route_top (oi->ls_upd_queue); rn;
1063 rn = route_next (rn))
hasso52dc7ee2004-09-23 19:18:23 +00001064 if ((lst = (struct list *) rn->info))
paul718e3742002-12-13 20:15:29 +00001065 {
paul1eb8ef22005-04-07 07:30:20 +00001066 for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001067 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00001068 list_free (lst);
1069 rn->info = NULL;
1070 }
1071
1072 /* remove update event */
1073 if (oi->t_ls_upd_event)
1074 {
1075 thread_cancel (oi->t_ls_upd_event);
1076 oi->t_ls_upd_event = NULL;
1077 }
1078}
1079
1080void
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001081ospf_if_update (struct ospf *ospf, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +00001082{
1083 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +00001084 struct ospf_network *network;
1085 struct ospf_area *area;
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001086
1087 if (!ospf)
1088 ospf = ospf_lookup ();
paul718e3742002-12-13 20:15:29 +00001089
Joakim Tjernlund6e687d72008-09-24 17:15:48 +01001090 /* OSPF must be on and Router-ID must be configured. */
1091 if (!ospf || ospf->router_id.s_addr == 0)
Joakim Tjernlunda49eb302008-09-02 19:06:31 +01001092 return;
Joakim Tjernlund738bce72009-08-07 13:48:15 +02001093
1094 if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area))
1095 ospf_interface_set (ifp);
1096 else
1097 {
1098 /* Run each netowrk for this interface. */
1099 for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
1100 if (rn->info != NULL)
1101 {
1102 network = (struct ospf_network *) rn->info;
1103 area = ospf_area_get (ospf, network->area_id, network->format);
1104 ospf_network_run_interface (&rn->p, area, ifp);
1105 }
1106 }
paul718e3742002-12-13 20:15:29 +00001107}
1108
1109void
paul68980082003-03-25 05:07:42 +00001110ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001111{
paul1eb8ef22005-04-07 07:30:20 +00001112 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001113 struct ospf_vl_data *vl_data;
1114
paul1eb8ef22005-04-07 07:30:20 +00001115 for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1116 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1117 ospf_vl_delete (ospf, vl_data);
paul718e3742002-12-13 20:15:29 +00001118}
1119
David Lamparter6b0655a2014-06-04 06:53:35 +02001120
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001121static const struct message ospf_area_type_msg[] =
paul718e3742002-12-13 20:15:29 +00001122{
1123 { OSPF_AREA_DEFAULT, "Default" },
1124 { OSPF_AREA_STUB, "Stub" },
1125 { OSPF_AREA_NSSA, "NSSA" },
1126};
Stephen Hemminger7ba82f72009-05-15 10:47:45 -07001127static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
paul718e3742002-12-13 20:15:29 +00001128
paul4dadc292005-05-06 21:37:42 +00001129static void
paul718e3742002-12-13 20:15:29 +00001130ospf_area_type_set (struct ospf_area *area, int type)
1131{
hasso52dc7ee2004-09-23 19:18:23 +00001132 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001133 struct ospf_interface *oi;
1134
1135 if (area->external_routing == type)
1136 {
1137 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001138 zlog_debug ("Area[%s]: Types are the same, ignored.",
paul718e3742002-12-13 20:15:29 +00001139 inet_ntoa (area->area_id));
1140 return;
1141 }
1142
1143 area->external_routing = type;
1144
1145 if (IS_DEBUG_OSPF_EVENT)
ajs9b0e25c2004-12-08 19:06:51 +00001146 zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
paul718e3742002-12-13 20:15:29 +00001147 LOOKUP (ospf_area_type_msg, type));
1148
1149 switch (area->external_routing)
1150 {
1151 case OSPF_AREA_DEFAULT:
paul1eb8ef22005-04-07 07:30:20 +00001152 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1153 if (oi->nbr_self != NULL)
1154 {
1155 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1156 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1157 }
paul718e3742002-12-13 20:15:29 +00001158 break;
1159 case OSPF_AREA_STUB:
paul1eb8ef22005-04-07 07:30:20 +00001160 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1161 if (oi->nbr_self != NULL)
1162 {
1163 if (IS_DEBUG_OSPF_EVENT)
1164 zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
1165 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1166 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1167 if (IS_DEBUG_OSPF_EVENT)
1168 zlog_debug ("options set on %s: %x",
1169 IF_NAME (oi), OPTIONS (oi));
1170 }
paul718e3742002-12-13 20:15:29 +00001171 break;
1172 case OSPF_AREA_NSSA:
paul1eb8ef22005-04-07 07:30:20 +00001173 for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
1174 if (oi->nbr_self != NULL)
1175 {
1176 zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
1177 UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
1178 SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
1179 zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
1180 }
paul718e3742002-12-13 20:15:29 +00001181 break;
1182 default:
1183 break;
1184 }
1185
Paul Jakmac363d382010-01-24 22:42:13 +00001186 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001187 ospf_schedule_abr_task (area->ospf);
paul718e3742002-12-13 20:15:29 +00001188}
1189
1190int
paul68980082003-03-25 05:07:42 +00001191ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
paul718e3742002-12-13 20:15:29 +00001192{
1193 if (area->shortcut_configured == mode)
1194 return 0;
1195
1196 area->shortcut_configured = mode;
Paul Jakmac363d382010-01-24 22:42:13 +00001197 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001198 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001199
paul68980082003-03-25 05:07:42 +00001200 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001201
1202 return 1;
1203}
1204
1205int
paul68980082003-03-25 05:07:42 +00001206ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
paul718e3742002-12-13 20:15:29 +00001207{
1208 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
Paul Jakmac363d382010-01-24 22:42:13 +00001209 ospf_router_lsa_update_area (area);
paul68980082003-03-25 05:07:42 +00001210 ospf_area_check_free (ospf, area->area_id);
1211 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001212
1213 return 1;
1214}
1215
paul4dadc292005-05-06 21:37:42 +00001216static int
paul718e3742002-12-13 20:15:29 +00001217ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
1218{
1219 struct ospf_vl_data *vl;
hasso52dc7ee2004-09-23 19:18:23 +00001220 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001221 int count = 0;
1222
paul1eb8ef22005-04-07 07:30:20 +00001223 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
1224 if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
1225 count++;
paul718e3742002-12-13 20:15:29 +00001226
1227 return count;
1228}
1229
1230int
1231ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
1232{
1233 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001234 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001235
paul68980082003-03-25 05:07:42 +00001236 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001237 if (ospf_area_vlink_count (ospf, area))
1238 return 0;
1239
1240 if (area->external_routing != OSPF_AREA_STUB)
1241 ospf_area_type_set (area, OSPF_AREA_STUB);
1242
1243 return 1;
1244}
1245
1246int
1247ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
1248{
1249 struct ospf_area *area;
1250
paul68980082003-03-25 05:07:42 +00001251 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001252 if (area == NULL)
1253 return 1;
1254
1255 if (area->external_routing == OSPF_AREA_STUB)
1256 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1257
paul68980082003-03-25 05:07:42 +00001258 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001259
1260 return 1;
1261}
1262
1263int
1264ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
1265{
1266 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001267 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001268
paul68980082003-03-25 05:07:42 +00001269 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001270 area->no_summary = 1;
1271
1272 return 1;
1273}
1274
1275int
1276ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
1277{
1278 struct ospf_area *area;
1279
paul68980082003-03-25 05:07:42 +00001280 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001281 if (area == NULL)
1282 return 0;
1283
1284 area->no_summary = 0;
paul68980082003-03-25 05:07:42 +00001285 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001286
1287 return 1;
1288}
1289
1290int
1291ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
1292{
1293 struct ospf_area *area;
paul147193a2003-04-19 00:31:59 +00001294 int format = OSPF_AREA_ID_FORMAT_ADDRESS;
paul718e3742002-12-13 20:15:29 +00001295
paul68980082003-03-25 05:07:42 +00001296 area = ospf_area_get (ospf, area_id, format);
paul718e3742002-12-13 20:15:29 +00001297 if (ospf_area_vlink_count (ospf, area))
1298 return 0;
1299
1300 if (area->external_routing != OSPF_AREA_NSSA)
1301 {
1302 ospf_area_type_set (area, OSPF_AREA_NSSA);
1303 ospf->anyNSSA++;
1304 }
1305
paul084c7842003-06-22 08:35:18 +00001306 /* set NSSA area defaults */
1307 area->no_summary = 0;
1308 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
pauld4a53d52003-07-12 21:30:57 +00001309 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
paul084c7842003-06-22 08:35:18 +00001310 area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
1311
paul718e3742002-12-13 20:15:29 +00001312 return 1;
1313}
1314
1315int
1316ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
1317{
1318 struct ospf_area *area;
1319
paul68980082003-03-25 05:07:42 +00001320 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001321 if (area == NULL)
1322 return 0;
1323
1324 if (area->external_routing == OSPF_AREA_NSSA)
1325 {
1326 ospf->anyNSSA--;
1327 ospf_area_type_set (area, OSPF_AREA_DEFAULT);
1328 }
1329
paul68980082003-03-25 05:07:42 +00001330 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001331
1332 return 1;
1333}
1334
1335int
1336ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
1337 int role)
1338{
1339 struct ospf_area *area;
1340
paul68980082003-03-25 05:07:42 +00001341 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001342 if (area == NULL)
1343 return 0;
1344
paul084c7842003-06-22 08:35:18 +00001345 area->NSSATranslatorRole = role;
paul718e3742002-12-13 20:15:29 +00001346
1347 return 1;
1348}
1349
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001350#if 0
paul4dadc292005-05-06 21:37:42 +00001351/* XXX: unused? Leave for symmetry? */
1352static int
paul718e3742002-12-13 20:15:29 +00001353ospf_area_nssa_translator_role_unset (struct ospf *ospf,
1354 struct in_addr area_id)
1355{
1356 struct ospf_area *area;
1357
paul68980082003-03-25 05:07:42 +00001358 area = ospf_area_lookup_by_area_id (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001359 if (area == NULL)
1360 return 0;
1361
paul084c7842003-06-22 08:35:18 +00001362 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
paul718e3742002-12-13 20:15:29 +00001363
paul68980082003-03-25 05:07:42 +00001364 ospf_area_check_free (ospf, area_id);
paul718e3742002-12-13 20:15:29 +00001365
1366 return 1;
1367}
Stephen Hemminger075e12f2011-12-06 23:54:17 +04001368#endif
paul718e3742002-12-13 20:15:29 +00001369
1370int
paul68980082003-03-25 05:07:42 +00001371ospf_area_export_list_set (struct ospf *ospf,
paul6c835672004-10-11 11:00:30 +00001372 struct ospf_area *area, const char *list_name)
paul718e3742002-12-13 20:15:29 +00001373{
1374 struct access_list *list;
1375 list = access_list_lookup (AFI_IP, list_name);
1376
1377 EXPORT_LIST (area) = list;
1378
1379 if (EXPORT_NAME (area))
1380 free (EXPORT_NAME (area));
1381
1382 EXPORT_NAME (area) = strdup (list_name);
paul68980082003-03-25 05:07:42 +00001383 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001384
1385 return 1;
1386}
1387
1388int
paul68980082003-03-25 05:07:42 +00001389ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001390{
1391
1392 EXPORT_LIST (area) = 0;
1393
1394 if (EXPORT_NAME (area))
1395 free (EXPORT_NAME (area));
1396
1397 EXPORT_NAME (area) = NULL;
1398
paul68980082003-03-25 05:07:42 +00001399 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001400
paul68980082003-03-25 05:07:42 +00001401 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001402
1403 return 1;
1404}
1405
1406int
paul6c835672004-10-11 11:00:30 +00001407ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
1408 const char *name)
paul718e3742002-12-13 20:15:29 +00001409{
1410 struct access_list *list;
1411 list = access_list_lookup (AFI_IP, name);
1412
1413 IMPORT_LIST (area) = list;
1414
1415 if (IMPORT_NAME (area))
1416 free (IMPORT_NAME (area));
1417
1418 IMPORT_NAME (area) = strdup (name);
paul68980082003-03-25 05:07:42 +00001419 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001420
1421 return 1;
1422}
1423
1424int
paul68980082003-03-25 05:07:42 +00001425ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
paul718e3742002-12-13 20:15:29 +00001426{
1427 IMPORT_LIST (area) = 0;
1428
1429 if (IMPORT_NAME (area))
1430 free (IMPORT_NAME (area));
1431
1432 IMPORT_NAME (area) = NULL;
paul68980082003-03-25 05:07:42 +00001433 ospf_area_check_free (ospf, area->area_id);
paul718e3742002-12-13 20:15:29 +00001434
paul68980082003-03-25 05:07:42 +00001435 ospf_schedule_abr_task (ospf);
paul718e3742002-12-13 20:15:29 +00001436
1437 return 1;
1438}
1439
1440int
paul718e3742002-12-13 20:15:29 +00001441ospf_timers_refresh_set (struct ospf *ospf, int interval)
1442{
1443 int time_left;
1444
1445 if (ospf->lsa_refresh_interval == interval)
1446 return 1;
1447
1448 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001449 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001450
1451 if (time_left > interval)
1452 {
1453 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1454 ospf->t_lsa_refresher =
1455 thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
1456 }
1457 ospf->lsa_refresh_interval = interval;
1458
1459 return 1;
1460}
1461
1462int
1463ospf_timers_refresh_unset (struct ospf *ospf)
1464{
1465 int time_left;
1466
1467 time_left = ospf->lsa_refresh_interval -
Paul Jakma2518efd2006-08-27 06:49:29 +00001468 (quagga_time (NULL) - ospf->lsa_refresher_started);
paul718e3742002-12-13 20:15:29 +00001469
1470 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
1471 {
1472 OSPF_TIMER_OFF (ospf->t_lsa_refresher);
1473 ospf->t_lsa_refresher =
1474 thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
1475 OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
1476 }
1477
1478 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
1479
1480 return 1;
1481}
1482
David Lamparter6b0655a2014-06-04 06:53:35 +02001483
paul4dadc292005-05-06 21:37:42 +00001484static struct ospf_nbr_nbma *
1485ospf_nbr_nbma_new (void)
paul718e3742002-12-13 20:15:29 +00001486{
1487 struct ospf_nbr_nbma *nbr_nbma;
1488
Stephen Hemminger393deb92008-08-18 14:13:29 -07001489 nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
paul718e3742002-12-13 20:15:29 +00001490 sizeof (struct ospf_nbr_nbma));
paul718e3742002-12-13 20:15:29 +00001491
1492 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1493 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1494
1495 return nbr_nbma;
1496}
1497
paul4dadc292005-05-06 21:37:42 +00001498static void
paul718e3742002-12-13 20:15:29 +00001499ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
1500{
1501 XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
1502}
1503
paul4dadc292005-05-06 21:37:42 +00001504static void
paul718e3742002-12-13 20:15:29 +00001505ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
1506{
1507 struct route_node *rn;
1508 struct prefix_ipv4 p;
1509
1510 p.family = AF_INET;
1511 p.prefix = nbr_nbma->addr;
1512 p.prefixlen = IPV4_MAX_BITLEN;
1513
1514 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1515 if (rn)
1516 {
1517 ospf_nbr_nbma_free (rn->info);
1518 rn->info = NULL;
1519 route_unlock_node (rn);
1520 route_unlock_node (rn);
1521 }
1522}
1523
paul4dadc292005-05-06 21:37:42 +00001524static void
paul718e3742002-12-13 20:15:29 +00001525ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
1526{
1527 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1528
1529 if (nbr_nbma->nbr)
1530 {
1531 nbr_nbma->nbr->nbr_nbma = NULL;
1532 OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
1533 }
1534
1535 if (nbr_nbma->oi)
1536 listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
1537}
1538
paul4dadc292005-05-06 21:37:42 +00001539static void
paul718e3742002-12-13 20:15:29 +00001540ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
1541 struct ospf_interface *oi)
1542{
1543 struct ospf_neighbor *nbr;
1544 struct route_node *rn;
1545 struct prefix p;
1546
1547 if (oi->type != OSPF_IFTYPE_NBMA)
1548 return;
1549
1550 if (nbr_nbma->nbr != NULL)
1551 return;
1552
1553 if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1554 return;
1555
1556 nbr_nbma->oi = oi;
1557 listnode_add (oi->nbr_nbma, nbr_nbma);
1558
1559 /* Get neighbor information from table. */
1560 p.family = AF_INET;
1561 p.prefixlen = IPV4_MAX_BITLEN;
1562 p.u.prefix4 = nbr_nbma->addr;
1563
1564 rn = route_node_get (oi->nbrs, (struct prefix *)&p);
1565 if (rn->info)
1566 {
1567 nbr = rn->info;
1568 nbr->nbr_nbma = nbr_nbma;
1569 nbr_nbma->nbr = nbr;
1570
1571 route_unlock_node (rn);
1572 }
1573 else
1574 {
1575 nbr = rn->info = ospf_nbr_new (oi);
1576 nbr->state = NSM_Down;
1577 nbr->src = nbr_nbma->addr;
1578 nbr->nbr_nbma = nbr_nbma;
1579 nbr->priority = nbr_nbma->priority;
1580 nbr->address = p;
1581
1582 nbr_nbma->nbr = nbr;
1583
1584 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
1585 }
1586}
1587
1588void
paul68980082003-03-25 05:07:42 +00001589ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
paul718e3742002-12-13 20:15:29 +00001590{
1591 struct ospf_nbr_nbma *nbr_nbma;
1592 struct route_node *rn;
1593 struct prefix_ipv4 p;
1594
1595 if (oi->type != OSPF_IFTYPE_NBMA)
1596 return;
1597
paul68980082003-03-25 05:07:42 +00001598 for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
paul718e3742002-12-13 20:15:29 +00001599 if ((nbr_nbma = rn->info))
1600 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
1601 {
1602 p.family = AF_INET;
1603 p.prefix = nbr_nbma->addr;
1604 p.prefixlen = IPV4_MAX_BITLEN;
1605
1606 if (prefix_match (oi->address, (struct prefix *)&p))
1607 ospf_nbr_nbma_add (nbr_nbma, oi);
1608 }
1609}
1610
1611struct ospf_nbr_nbma *
1612ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
1613{
1614 struct route_node *rn;
1615 struct prefix_ipv4 p;
1616
1617 p.family = AF_INET;
1618 p.prefix = nbr_addr;
1619 p.prefixlen = IPV4_MAX_BITLEN;
1620
1621 rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
1622 if (rn)
1623 {
1624 route_unlock_node (rn);
1625 return rn->info;
1626 }
1627 return NULL;
1628}
1629
1630struct ospf_nbr_nbma *
paul68980082003-03-25 05:07:42 +00001631ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
paul718e3742002-12-13 20:15:29 +00001632{
1633#if 0
1634 struct ospf_nbr_nbma *nbr_nbma;
hasso52dc7ee2004-09-23 19:18:23 +00001635 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001636#endif
1637
paul68980082003-03-25 05:07:42 +00001638 if (ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001639 return NULL;
1640
1641#if 0
paul1eb8ef22005-04-07 07:30:20 +00001642 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
paul718e3742002-12-13 20:15:29 +00001643 {
paul718e3742002-12-13 20:15:29 +00001644 if (first)
1645 {
1646 *addr = nbr_nbma->addr;
1647 return nbr_nbma;
1648 }
1649 else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
1650 {
1651 *addr = nbr_nbma->addr;
1652 return nbr_nbma;
1653 }
1654 }
1655#endif
1656 return NULL;
1657}
1658
1659int
1660ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
1661{
1662 struct ospf_nbr_nbma *nbr_nbma;
1663 struct ospf_interface *oi;
1664 struct prefix_ipv4 p;
1665 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00001666 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001667
1668 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1669 if (nbr_nbma)
1670 return 0;
1671
1672 nbr_nbma = ospf_nbr_nbma_new ();
1673 nbr_nbma->addr = nbr_addr;
1674
1675 p.family = AF_INET;
1676 p.prefix = nbr_addr;
1677 p.prefixlen = IPV4_MAX_BITLEN;
1678
1679 rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
Joakim Tjernlund4de398e2010-03-08 13:58:14 +01001680 if (rn->info)
1681 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001682 rn->info = nbr_nbma;
1683
paul1eb8ef22005-04-07 07:30:20 +00001684 for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
paul718e3742002-12-13 20:15:29 +00001685 {
paul718e3742002-12-13 20:15:29 +00001686 if (oi->type == OSPF_IFTYPE_NBMA)
1687 if (prefix_match (oi->address, (struct prefix *)&p))
1688 {
1689 ospf_nbr_nbma_add (nbr_nbma, oi);
1690 break;
1691 }
1692 }
1693
1694 return 1;
1695}
1696
1697int
1698ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
1699{
1700 struct ospf_nbr_nbma *nbr_nbma;
1701
1702 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1703 if (nbr_nbma == NULL)
1704 return 0;
1705
1706 ospf_nbr_nbma_down (nbr_nbma);
1707 ospf_nbr_nbma_delete (ospf, nbr_nbma);
1708
1709 return 1;
1710}
1711
1712int
1713ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
1714 u_char priority)
1715{
1716 struct ospf_nbr_nbma *nbr_nbma;
1717
1718 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1719 if (nbr_nbma == NULL)
1720 return 0;
1721
1722 if (nbr_nbma->priority != priority)
1723 nbr_nbma->priority = priority;
1724
1725 return 1;
1726}
1727
1728int
1729ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
1730{
1731 struct ospf_nbr_nbma *nbr_nbma;
1732
1733 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1734 if (nbr_nbma == NULL)
1735 return 0;
1736
1737 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
1738 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1739
1740 return 1;
1741}
1742
1743int
1744ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
paul6c835672004-10-11 11:00:30 +00001745 unsigned int interval)
paul718e3742002-12-13 20:15:29 +00001746{
1747 struct ospf_nbr_nbma *nbr_nbma;
1748
1749 nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
1750 if (nbr_nbma == NULL)
1751 return 0;
1752
1753 if (nbr_nbma->v_poll != interval)
1754 {
1755 nbr_nbma->v_poll = interval;
1756 if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
1757 {
1758 OSPF_TIMER_OFF (nbr_nbma->t_poll);
1759 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
1760 nbr_nbma->v_poll);
1761 }
1762 }
1763
1764 return 1;
1765}
1766
1767int
1768ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
1769{
1770 struct ospf_nbr_nbma *nbr_nbma;
1771
1772 nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
1773 if (nbr_nbma == NULL)
1774 return 0;
1775
1776 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
1777 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
1778
1779 return 1;
1780}
1781
paul718e3742002-12-13 20:15:29 +00001782void
paul020709f2003-04-04 02:44:16 +00001783ospf_master_init ()
1784{
1785 memset (&ospf_master, 0, sizeof (struct ospf_master));
1786
1787 om = &ospf_master;
1788 om->ospf = list_new ();
1789 om->master = thread_master_create ();
Paul Jakma2518efd2006-08-27 06:49:29 +00001790 om->start_time = quagga_time (NULL);
paul020709f2003-04-04 02:44:16 +00001791}