]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospfd.c
Merge pull request #9348 from dlqs/consecutive
[mirror_frr.git] / ospfd / ospfd.c
CommitLineData
718e3744 1/* OSPF version 2 daemon program.
896014f4
DL
2 * Copyright (C) 1999, 2000 Toshiaki Takada
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 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"
d62a17ae 33#include "sockunion.h" /* for inet_aton () */
718e3744 34#include "zclient.h"
ded42248 35#include "routemap.h"
718e3744 36#include "plist.h"
f102e75f 37#include "sockopt.h"
567b877d 38#include "bfd.h"
8879bd22 39#include "libfrr.h"
8efe88ea 40#include "defaults.h"
313d7993 41#include "lib_errors.h"
132a782e 42#include "ldp_sync.h"
718e3744 43
44#include "ospfd/ospfd.h"
659f4e40 45#include "ospfd/ospf_bfd.h"
718e3744 46#include "ospfd/ospf_network.h"
47#include "ospfd/ospf_interface.h"
48#include "ospfd/ospf_ism.h"
49#include "ospfd/ospf_asbr.h"
50#include "ospfd/ospf_lsa.h"
51#include "ospfd/ospf_lsdb.h"
52#include "ospfd/ospf_neighbor.h"
53#include "ospfd/ospf_nsm.h"
54#include "ospfd/ospf_spf.h"
55#include "ospfd/ospf_packet.h"
56#include "ospfd/ospf_dump.h"
19c0412a 57#include "ospfd/ospf_route.h"
718e3744 58#include "ospfd/ospf_zebra.h"
59#include "ospfd/ospf_abr.h"
60#include "ospfd/ospf_flood.h"
718e3744 61#include "ospfd/ospf_ase.h"
132a782e 62#include "ospfd/ospf_ldp_sync.h"
cd52c44c 63#include "ospfd/ospf_gr.h"
718e3744 64
6b0655a2 65
96244aca 66DEFINE_QOBJ_TYPE(ospf);
edd7c245 67
020709f9 68/* OSPF process wide configuration. */
69static struct ospf_master ospf_master;
70
71/* OSPF process wide configuration pointer to export. */
72struct ospf_master *om;
718e3744 73
409f98ab
IR
74unsigned short ospf_instance;
75
718e3744 76extern struct zclient *zclient;
77
6b0655a2 78
d62a17ae 79static void ospf_remove_vls_through_area(struct ospf *, struct ospf_area *);
80static void ospf_network_free(struct ospf *, struct ospf_network *);
81static void ospf_area_free(struct ospf_area *);
82static void ospf_network_run(struct prefix *, struct ospf_area *);
83static void ospf_network_run_interface(struct ospf *, struct interface *,
84 struct prefix *, struct ospf_area *);
85static void ospf_network_run_subnet(struct ospf *, struct connected *,
86 struct prefix *, struct ospf_area *);
87static int ospf_network_match_iface(const struct connected *,
88 const struct prefix *);
89static void ospf_finish_final(struct ospf *);
718e3744 90
718e3744 91#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
6b0655a2 92
7fd0729f
G
93int p_spaces_compare_func(const struct p_space *a, const struct p_space *b)
94{
385a1e07
G
95 if (a->protected_resource->type == OSPF_TI_LFA_LINK_PROTECTION
96 && b->protected_resource->type == OSPF_TI_LFA_LINK_PROTECTION)
97 return (a->protected_resource->link->link_id.s_addr
98 - b->protected_resource->link->link_id.s_addr);
99
100 if (a->protected_resource->type == OSPF_TI_LFA_NODE_PROTECTION
101 && b->protected_resource->type == OSPF_TI_LFA_NODE_PROTECTION)
102 return (a->protected_resource->router_id.s_addr
103 - b->protected_resource->router_id.s_addr);
104
105 /* This should not happen */
106 return 0;
7fd0729f
G
107}
108
109int q_spaces_compare_func(const struct q_space *a, const struct q_space *b)
110{
111 return (a->root->id.s_addr - b->root->id.s_addr);
112}
113
114DECLARE_RBTREE_UNIQ(p_spaces, struct p_space, p_spaces_item,
960b9a53 115 p_spaces_compare_func);
7fd0729f 116
f91ce319 117void ospf_process_refresh_data(struct ospf *ospf, bool reset)
718e3744 118{
f4e14fdb 119 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
d62a17ae 120 struct in_addr router_id, router_id_old;
121 struct ospf_interface *oi;
122 struct interface *ifp;
f91ce319
MR
123 struct listnode *node, *nnode;
124 struct ospf_area *area;
125 bool rid_change = false;
2c19a6ec 126
d62a17ae 127 if (!ospf->oi_running) {
128 if (IS_DEBUG_OSPF_EVENT)
129 zlog_debug(
130 "Router ospf not configured -- Router-ID update postponed");
131 return;
25a346eb 132 }
718e3744 133
d62a17ae 134 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
135 zlog_debug("Router-ID[OLD:%pI4]: Update",
136 &ospf->router_id);
d62a17ae 137
138 router_id_old = ospf->router_id;
139
140 /* Select the router ID based on these priorities:
141 1. Statically assigned router ID is always the first choice.
142 2. If there is no statically assigned router ID, then try to stick
143 with the most recent value, since changing router ID's is very
144 disruptive.
145 3. Last choice: just go with whatever the zebra daemon recommends.
146 */
3a6290bd 147 if (ospf->router_id_static.s_addr != INADDR_ANY)
d62a17ae 148 router_id = ospf->router_id_static;
3a6290bd 149 else if (ospf->router_id.s_addr != INADDR_ANY)
d62a17ae 150 router_id = ospf->router_id;
151 else
6021c6c0 152 router_id = ospf->router_id_zebra;
d62a17ae 153
b5a8894d 154 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
155 zlog_debug("Router-ID[OLD:%pI4]: Update to %pI4",
156 &ospf->router_id, &router_id);
d62a17ae 157
f91ce319
MR
158 rid_change = !(IPV4_ADDR_SAME(&router_id_old, &router_id));
159 if (rid_change || (reset)) {
d62a17ae 160 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
161 /* Some nbrs are identified by router_id, these needs
162 * to be rebuilt. Possible optimization would be to do
163 * oi->nbr_self->router_id = router_id for
164 * !(virtual | ptop) links
165 */
166 ospf_nbr_self_reset(oi, router_id);
7e0274f8
DS
167
168 /*
169 * If the old router id was not set, but now it
170 * is and the interface is operative and the
171 * state is ISM_Down we should kick the state
172 * machine as that we processed the interfaces
173 * based upon the network statement( or intf config )
174 * but could not start it at that time.
175 */
176 if (if_is_operative(oi->ifp) && oi->state == ISM_Down
177 && router_id_old.s_addr == INADDR_ANY)
178 ospf_if_up(oi);
d62a17ae 179 }
180
f91ce319
MR
181 /* Flush (inline) all the self originated LSAs */
182 ospf_flush_self_originated_lsas_now(ospf);
d62a17ae 183
184 ospf->router_id = router_id;
185 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
186 zlog_debug("Router-ID[NEW:%pI4]: Update",
187 &ospf->router_id);
d62a17ae 188
189 /* Flush (inline) all external LSAs which now match the new
190 router-id,
0437e105 191 need to adjust the OSPF_LSA_SELF flag, so the flush doesn't
d62a17ae 192 hit
193 asserts in ospf_refresher_unregister_lsa(). This step is
194 needed
195 because the current quagga code does look-up for
196 self-originated LSAs
197 based on the self router-id alone but expects OSPF_LSA_SELF
198 to be
199 properly set */
200 if (ospf->lsdb) {
201 struct route_node *rn;
202 struct ospf_lsa *lsa;
203
044506e7 204 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
d62a17ae 205 /* AdvRouter and Router ID is the same. */
206 if (IPV4_ADDR_SAME(&lsa->data->adv_router,
f91ce319 207 &ospf->router_id) && rid_change) {
d62a17ae 208 SET_FLAG(lsa->flags,
209 OSPF_LSA_SELF_CHECKED);
210 SET_FLAG(lsa->flags, OSPF_LSA_SELF);
211 ospf_lsa_flush_schedule(ospf, lsa);
212 }
f91ce319
MR
213 /* The above flush will send immediately
214 * So discard the LSA to originate new
215 */
216 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
d62a17ae 217 }
f91ce319
MR
218
219 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
220 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
221
222 ospf_lsdb_delete_all(ospf->lsdb);
d62a17ae 223 }
224
f91ce319
MR
225 /* Delete the LSDB */
226 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
227 ospf_area_lsdb_discard_delete(area);
228
d62a17ae 229 /* update router-lsa's for each area */
230 ospf_router_lsa_update(ospf);
231
232 /* update ospf_interface's */
f91ce319
MR
233 FOR_ALL_INTERFACES (vrf, ifp) {
234 if (reset)
235 ospf_if_reset(ifp);
236 else
237 ospf_if_update(ospf, ifp);
238 }
fa3c7c7e
DL
239
240 ospf_external_lsa_rid_change(ospf);
718e3744 241 }
f91ce319
MR
242
243 ospf->inst_shutdown = 0;
244}
245
246void ospf_router_id_update(struct ospf *ospf)
247{
248 ospf_process_refresh_data(ospf, false);
249}
250
251void ospf_process_reset(struct ospf *ospf)
252{
253 ospf_process_refresh_data(ospf, true);
254}
255
256void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
257 const char *nbr_str)
258{
259 struct route_node *rn;
260 struct ospf_neighbor *nbr;
261 struct ospf_interface *oi;
262 struct listnode *node;
263
264 /* Clear only a particular nbr with nbr router id as nbr_id */
265 if (nbr_str != NULL) {
266 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
267 nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &nbr_id);
268 if (nbr)
269 OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
270 }
271 return;
272 }
273
274 /* send Neighbor event KillNbr to all associated neighbors. */
275 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
276 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
277 nbr = rn->info;
278 if (nbr && (nbr != oi->nbr_self))
279 OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
280 }
281 }
718e3744 282}
6b0655a2 283
718e3744 284/* For OSPF area sort by area id. */
d62a17ae 285static int ospf_area_id_cmp(struct ospf_area *a1, struct ospf_area *a2)
718e3744 286{
d62a17ae 287 if (ntohl(a1->area_id.s_addr) > ntohl(a2->area_id.s_addr))
288 return 1;
289 if (ntohl(a1->area_id.s_addr) < ntohl(a2->area_id.s_addr))
290 return -1;
291 return 0;
718e3744 292}
293
7fd0729f 294struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
718e3744 295{
d62a17ae 296 int i;
b5a8894d 297 struct vrf *vrf = NULL;
718e3744 298
d62a17ae 299 struct ospf *new = XCALLOC(MTYPE_OSPF_TOP, sizeof(struct ospf));
718e3744 300
d62a17ae 301 new->instance = instance;
302 new->router_id.s_addr = htonl(0);
303 new->router_id_static.s_addr = htonl(0);
14406e8e
DS
304 if (name) {
305 vrf = vrf_lookup_by_name(name);
306 if (vrf)
307 new->vrf_id = vrf->vrf_id;
308 else
309 new->vrf_id = VRF_UNKNOWN;
b5a8894d
CS
310 /* Freed in ospf_finish_final */
311 new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
b5a8894d 312 if (IS_DEBUG_OSPF_EVENT)
996c9314
LB
313 zlog_debug(
314 "%s: Create new ospf instance with vrf_name %s vrf_id %u",
15569c58 315 __func__, name, new->vrf_id);
b5a8894d
CS
316 } else {
317 new->vrf_id = VRF_DEFAULT;
318 vrf = vrf_lookup_by_id(VRF_DEFAULT);
b5a8894d 319 }
a2d7fdfe 320
321 if (vrf)
322 ospf_vrf_link(new, vrf);
323
b5a8894d
CS
324 ospf_zebra_vrf_register(new);
325
d62a17ae 326 new->abr_type = OSPF_ABR_DEFAULT;
327 new->oiflist = list_new();
328 new->vlinks = list_new();
329 new->areas = list_new();
330 new->areas->cmp = (int (*)(void *, void *))ospf_area_id_cmp;
331 new->networks = route_table_init();
332 new->nbr_nbma = route_table_init();
718e3744 333
d62a17ae 334 new->lsdb = ospf_lsdb_new();
718e3744 335
d62a17ae 336 new->default_originate = DEFAULT_ORIGINATE_NONE;
718e3744 337
d62a17ae 338 new->passive_interface_default = OSPF_IF_ACTIVE;
4ba4fc85 339
d62a17ae 340 new->new_external_route = route_table_init();
341 new->old_external_route = route_table_init();
342 new->external_lsas = route_table_init();
343
344 new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
345 new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
346 new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET;
347
348 /* Distribute parameter init. */
349 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
350 new->dtag[i] = 0;
351 }
352 new->default_metric = -1;
353 new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
354
355 /* LSA timers */
356 new->min_ls_interval = OSPF_MIN_LS_INTERVAL;
357 new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL;
358
359 /* SPF timer value init. */
360 new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
361 new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
362 new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
363 new->spf_hold_multiplier = 1;
364
365 /* MaxAge init. */
366 new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
367 new->maxage_lsa = route_table_init();
368 new->t_maxage_walker = NULL;
d62a17ae 369
3d5b9855 370 /* Max paths initialization */
371 new->max_multipath = MULTIPATH_NUM;
372
d62a17ae 373 /* Distance table init. */
374 new->distance_table = route_table_init();
375
376 new->lsa_refresh_queue.index = 0;
377 new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
378 new->t_lsa_refresher = NULL;
d62a17ae 379 new->lsa_refresher_started = monotime(NULL);
380
266469eb
DS
381 new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1);
382
d62a17ae 383 new->t_read = NULL;
d62a17ae 384 new->oi_write_q = list_new();
385 new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT;
386
a92706bb
JU
387 new->proactive_arp = OSPF_PROACTIVE_ARP_DEFAULT;
388
51f8588e 389 ospf_gr_helper_instance_init(new);
06bc3110 390
ad7222b7 391 ospf_asbr_external_aggregator_init(new);
392
d62a17ae 393 QOBJ_REG(new, ospf);
ae19c240 394
3c0eb8fa 395 new->fd = -1;
7fd0729f
G
396
397 return new;
398}
399
400/* Allocate new ospf structure. */
401static struct ospf *ospf_new(unsigned short instance, const char *name)
402{
403 struct ospf *new;
404
405 new = ospf_new_alloc(instance, name);
406
3c0eb8fa
PG
407 if ((ospf_sock_init(new)) < 0) {
408 if (new->vrf_id != VRF_UNKNOWN)
ade6974d 409 flog_err(
450971aa 410 EC_LIB_SOCKET,
ade6974d
QY
411 "%s: ospf_sock_init is unable to open a socket",
412 __func__);
3c0eb8fa
PG
413 return new;
414 }
7fd0729f
G
415
416 thread_add_timer(master, ospf_lsa_maxage_walker, new,
417 OSPF_LSA_MAXAGE_CHECK_INTERVAL, &new->t_maxage_walker);
418 thread_add_timer(master, ospf_lsa_refresh_walker, new,
419 new->lsa_refresh_interval, &new->t_lsa_refresher);
420
3c0eb8fa
PG
421 thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
422
10514170
RW
423 /*
424 * Read from non-volatile memory whether this instance is performing a
425 * graceful restart or not.
426 */
427 ospf_gr_nvm_read(new);
428
d62a17ae 429 return new;
718e3744 430}
431
d7c0a89a 432struct ospf *ospf_lookup_instance(unsigned short instance)
7c8ff89e 433{
d62a17ae 434 struct ospf *ospf;
435 struct listnode *node, *nnode;
7c8ff89e 436
d62a17ae 437 if (listcount(om->ospf) == 0)
438 return NULL;
7c8ff89e 439
d62a17ae 440 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
441 if ((ospf->instance == 0 && instance == 0)
442 || (ospf->instance && instance
443 && ospf->instance == instance))
444 return ospf;
7c8ff89e 445
d62a17ae 446 return NULL;
7c8ff89e
DS
447}
448
d62a17ae 449static int ospf_is_ready(struct ospf *ospf)
52c62ab8 450{
d62a17ae 451 /* OSPF must be on and Router-ID must be configured. */
975a328e 452 if (!ospf || ospf->router_id.s_addr == INADDR_ANY)
d62a17ae 453 return 0;
454
455 return 1;
52c62ab8
JAG
456}
457
d62a17ae 458static void ospf_add(struct ospf *ospf)
020709f9 459{
d62a17ae 460 listnode_add(om->ospf, ospf);
020709f9 461}
718e3744 462
d62a17ae 463static void ospf_delete(struct ospf *ospf)
020709f9 464{
d62a17ae 465 listnode_delete(om->ospf, ospf);
020709f9 466}
68980084 467
d7c0a89a 468struct ospf *ospf_lookup_by_inst_name(unsigned short instance, const char *name)
b5a8894d
CS
469{
470 struct ospf *ospf = NULL;
471 struct listnode *node, *nnode;
472
6895b354
PG
473 if (name == NULL || strmatch(name, VRF_DEFAULT_NAME))
474 return ospf_lookup_by_vrf_id(VRF_DEFAULT);
475
b5a8894d 476 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) {
996c9314
LB
477 if ((ospf->instance == instance)
478 && ((ospf->name == NULL && name == NULL)
479 || (ospf->name && name
480 && strcmp(ospf->name, name) == 0)))
b5a8894d
CS
481 return ospf;
482 }
483 return NULL;
484}
485
c3391da1 486static void ospf_init(struct ospf *ospf)
020709f9 487{
c3391da1
IR
488 ospf_opaque_type11_lsa_init(ospf);
489
490 if (ospf->vrf_id != VRF_UNKNOWN)
491 ospf->oi_running = 1;
492
c3391da1
IR
493 ospf_router_id_update(ospf);
494}
495
409f98ab 496struct ospf *ospf_lookup(unsigned short instance, const char *name)
c3391da1
IR
497{
498 struct ospf *ospf;
499
409f98ab
IR
500 if (ospf_instance) {
501 ospf = ospf_lookup_instance(instance);
502 } else {
b5a8894d 503 ospf = ospf_lookup_by_inst_name(instance, name);
d62a17ae 504 }
7c8ff89e 505
d62a17ae 506 return ospf;
7c8ff89e
DS
507}
508
409f98ab 509struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
7c8ff89e 510{
d62a17ae 511 struct ospf *ospf;
7c8ff89e 512
409f98ab
IR
513 ospf = ospf_lookup(instance, name);
514
c572fbfe 515 *created = (ospf == NULL);
d62a17ae 516 if (ospf == NULL) {
409f98ab 517 ospf = ospf_new(instance, name);
d62a17ae 518 ospf_add(ospf);
020709f9 519
c3391da1 520 ospf_init(ospf);
d62a17ae 521 }
68980084 522
d62a17ae 523 return ospf;
718e3744 524}
6b0655a2 525
b5a8894d
CS
526struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id)
527{
528 struct vrf *vrf = NULL;
529
530 vrf = vrf_lookup_by_id(vrf_id);
531 if (!vrf)
532 return NULL;
533 return (vrf->info) ? (struct ospf *)vrf->info : NULL;
b5a8894d
CS
534}
535
cbf32f74
IR
536uint32_t ospf_count_area_params(struct ospf *ospf)
537{
538 struct vrf *vrf;
539 struct interface *ifp;
540 uint32_t count = 0;
541
542 if (ospf->vrf_id != VRF_UNKNOWN) {
543 vrf = vrf_lookup_by_id(ospf->vrf_id);
544
545 FOR_ALL_INTERFACES (vrf, ifp) {
546 count += ospf_if_count_area_params(ifp);
547 }
548 }
549
550 return count;
551}
552
43b8d1d8
CS
553/* It should only be used when processing incoming info update from zebra.
554 * Other situations, it is not sufficient to lookup the ospf instance by
555 * vrf_name only without using the instance number.
556 */
557static struct ospf *ospf_lookup_by_name(const char *vrf_name)
b5a8894d
CS
558{
559 struct ospf *ospf = NULL;
560 struct listnode *node, *nnode;
561
562 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
43b8d1d8 563 if ((ospf->name == NULL && vrf_name == NULL)
996c9314
LB
564 || (ospf->name && vrf_name
565 && strcmp(ospf->name, vrf_name) == 0))
b5a8894d
CS
566 return ospf;
567 return NULL;
568}
569
c9c93d50 570/* Handle the second half of deferred shutdown. This is called either
571 * from the deferred-shutdown timer thread, or directly through
572 * ospf_deferred_shutdown_check.
88d6cf37 573 *
574 * Function is to cleanup G-R state, if required then call ospf_finish_final
575 * to complete shutdown of this ospf instance. Possibly exit if the
576 * whole process is being shutdown and this was the last OSPF instance.
577 */
d62a17ae 578static void ospf_deferred_shutdown_finish(struct ospf *ospf)
579{
580 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
581 OSPF_TIMER_OFF(ospf->t_deferred_shutdown);
582
583 ospf_finish_final(ospf);
584
585 /* *ospf is now invalid */
88d6cf37 586
d62a17ae 587 /* ospfd being shut-down? If so, was this the last ospf instance? */
588 if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)
589 && (listcount(om->ospf) == 0)) {
590 exit(0);
591 }
592
593 return;
88d6cf37 594}
595
596/* Timer thread for G-R */
d62a17ae 597static int ospf_deferred_shutdown_timer(struct thread *t)
88d6cf37 598{
d62a17ae 599 struct ospf *ospf = THREAD_ARG(t);
600
601 ospf_deferred_shutdown_finish(ospf);
602
603 return 0;
88d6cf37 604}
605
c9c93d50 606/* Check whether deferred-shutdown must be scheduled, otherwise call
88d6cf37 607 * down directly into second-half of instance shutdown.
608 */
d62a17ae 609static void ospf_deferred_shutdown_check(struct ospf *ospf)
610{
611 unsigned long timeout;
612 struct listnode *ln;
613 struct ospf_area *area;
614
615 /* deferred shutdown already running? */
616 if (ospf->t_deferred_shutdown)
617 return;
618
619 /* Should we try push out max-metric LSAs? */
620 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) {
621 for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) {
622 SET_FLAG(area->stub_router_state,
623 OSPF_AREA_ADMIN_STUB_ROUTED);
624
625 if (!CHECK_FLAG(area->stub_router_state,
626 OSPF_AREA_IS_STUB_ROUTED))
627 ospf_router_lsa_update_area(area);
628 }
629 timeout = ospf->stub_router_shutdown_time;
630 } else {
631 /* No timer needed */
632 ospf_deferred_shutdown_finish(ospf);
633 return;
634 }
635
636 OSPF_TIMER_ON(ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
637 timeout);
638 return;
88d6cf37 639}
6b0655a2 640
88d6cf37 641/* Shut down the entire process */
d62a17ae 642void ospf_terminate(void)
643{
644 struct ospf *ospf;
645 struct listnode *node, *nnode;
646
647 /* shutdown already in progress */
648 if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN))
649 return;
650
651 SET_FLAG(om->options, OSPF_MASTER_SHUTDOWN);
652
41b21bfa 653 /* Skip some steps if OSPF not actually running */
d62a17ae 654 if (listcount(om->ospf) == 0)
41b21bfa 655 goto done;
d62a17ae 656
d62a17ae 657 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
658 ospf_finish(ospf);
659
51f8588e
RW
660 /* Cleanup GR */
661 ospf_gr_helper_stop();
662
ded42248 663 /* Cleanup route maps */
ded42248
CS
664 route_map_finish();
665
666 /* reverse prefix_list_init */
667 prefix_list_add_hook(NULL);
668 prefix_list_delete_hook(NULL);
669 prefix_list_reset();
670
671 /* Cleanup vrf info */
672 ospf_vrf_terminate();
673
d62a17ae 674 /* Deliberately go back up, hopefully to thread scheduler, as
675 * One or more ospf_finish()'s may have deferred shutdown to a timer
676 * thread
677 */
678 zclient_stop(zclient);
679 zclient_free(zclient);
8879bd22 680
41b21bfa 681done:
8879bd22 682 frr_fini();
d62a17ae 683}
684
685void ospf_finish(struct ospf *ospf)
686{
687 /* let deferred shutdown decide */
688 ospf_deferred_shutdown_check(ospf);
689
690 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
691 * deferred to expiry of G-S timer thread. Return back up, hopefully
692 * to thread scheduler.
693 */
694 return;
88d6cf37 695}
696
697/* Final cleanup of ospf instance */
d62a17ae 698static void ospf_finish_final(struct ospf *ospf)
718e3744 699{
1113a2fb 700 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
d62a17ae 701 struct route_node *rn;
702 struct ospf_nbr_nbma *nbr_nbma;
703 struct ospf_lsa *lsa;
d62a17ae 704 struct ospf_interface *oi;
705 struct ospf_area *area;
706 struct ospf_vl_data *vl_data;
707 struct listnode *node, *nnode;
ca187fd3 708 struct ospf_redist *red;
d62a17ae 709 int i;
7c8ff89e 710
d62a17ae 711 QOBJ_UNREG(ospf);
7c8ff89e 712
d62a17ae 713 ospf_opaque_type11_lsa_term(ospf);
953cde65 714
bcf4475e
OD
715 ospf_opaque_finish();
716
10514170
RW
717 if (!ospf->gr_info.prepare_in_progress)
718 ospf_flush_self_originated_lsas_now(ospf);
953cde65 719
d62a17ae 720 /* Unregister redistribution */
721 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
722 struct list *red_list;
718e3744 723
d62a17ae 724 red_list = ospf->redist[i];
725 if (!red_list)
726 continue;
718e3744 727
1d753551 728 for (ALL_LIST_ELEMENTS(red_list, node, nnode, red)) {
d62a17ae 729 ospf_redistribute_unset(ospf, i, red->instance);
1d753551
DS
730 ospf_redist_del(ospf, i, red->instance);
731 }
d62a17ae 732 }
ca187fd3
IR
733 red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0);
734 if (red) {
735 ospf_routemap_unset(red);
736 ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
737 ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
738 }
718e3744 739
d62a17ae 740 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
741 ospf_remove_vls_through_area(ospf, area);
718e3744 742
d62a17ae 743 for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
744 ospf_vl_delete(ospf, vl_data);
718e3744 745
6a154c88 746 list_delete(&ospf->vlinks);
718e3744 747
132a782e 748 /* shutdown LDP-Sync */
749 if (ospf->vrf_id == VRF_DEFAULT)
750 ospf_ldp_sync_gbl_exit(ospf, true);
751
d62a17ae 752 /* Reset interface. */
753 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
754 ospf_if_free(oi);
6a154c88 755 list_delete(&ospf->oiflist);
c32eba04 756 ospf->oi_running = 0;
718e3744 757
b5a8894d
CS
758 /* De-Register VRF */
759 ospf_zebra_vrf_deregister(ospf);
760
d62a17ae 761 /* Clear static neighbors */
762 for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
763 if ((nbr_nbma = rn->info)) {
764 OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll);
718e3744 765
d62a17ae 766 if (nbr_nbma->nbr) {
767 nbr_nbma->nbr->nbr_nbma = NULL;
768 nbr_nbma->nbr = NULL;
769 }
770
771 if (nbr_nbma->oi) {
772 listnode_delete(nbr_nbma->oi->nbr_nbma,
773 nbr_nbma);
774 nbr_nbma->oi = NULL;
775 }
776
777 XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
778 }
779
780 route_table_finish(ospf->nbr_nbma);
781
782 /* Clear networks and Areas. */
783 for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) {
784 struct ospf_network *network;
785
786 if ((network = rn->info) != NULL) {
787 ospf_network_free(ospf, network);
788 rn->info = NULL;
789 route_unlock_node(rn);
790 }
91e6a0e5 791 }
7f586094 792 route_table_finish(ospf->networks);
718e3744 793
d62a17ae 794 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
795 listnode_delete(ospf->areas, area);
796 ospf_area_free(area);
797 }
718e3744 798
d62a17ae 799 /* Cancel all timers. */
c32eba04
CS
800 OSPF_TIMER_OFF(ospf->t_read);
801 OSPF_TIMER_OFF(ospf->t_write);
d62a17ae 802 OSPF_TIMER_OFF(ospf->t_spf_calc);
803 OSPF_TIMER_OFF(ospf->t_ase_calc);
804 OSPF_TIMER_OFF(ospf->t_maxage);
805 OSPF_TIMER_OFF(ospf->t_maxage_walker);
806 OSPF_TIMER_OFF(ospf->t_abr_task);
807 OSPF_TIMER_OFF(ospf->t_asbr_check);
1c1c342d 808 OSPF_TIMER_OFF(ospf->t_asbr_nssa_redist_update);
d62a17ae 809 OSPF_TIMER_OFF(ospf->t_distribute_update);
810 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
d62a17ae 811 OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
45a43856 812 OSPF_TIMER_OFF(ospf->t_sr_update);
1febb13d 813 OSPF_TIMER_OFF(ospf->t_default_routemap_timer);
ad7222b7 814 OSPF_TIMER_OFF(ospf->t_external_aggr);
10514170 815 OSPF_TIMER_OFF(ospf->gr_info.t_grace_period);
d62a17ae 816
996c9314 817 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
044506e7 818 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
996c9314 819 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
044506e7 820 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
d62a17ae 821
822 ospf_lsdb_delete_all(ospf->lsdb);
823 ospf_lsdb_free(ospf->lsdb);
824
825 for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) {
d62a17ae 826 if ((lsa = rn->info) != NULL) {
827 ospf_lsa_unlock(&lsa);
828 rn->info = NULL;
69843e81 829 route_unlock_node(rn);
d62a17ae 830 }
d62a17ae 831 }
832 route_table_finish(ospf->maxage_lsa);
833
834 if (ospf->old_table)
835 ospf_route_table_free(ospf->old_table);
836 if (ospf->new_table) {
10514170
RW
837 if (!ospf->gr_info.prepare_in_progress)
838 ospf_route_delete(ospf, ospf->new_table);
d62a17ae 839 ospf_route_table_free(ospf->new_table);
840 }
841 if (ospf->old_rtrs)
842 ospf_rtrs_free(ospf->old_rtrs);
843 if (ospf->new_rtrs)
844 ospf_rtrs_free(ospf->new_rtrs);
845 if (ospf->new_external_route) {
10514170
RW
846 if (!ospf->gr_info.prepare_in_progress)
847 ospf_route_delete(ospf, ospf->new_external_route);
d62a17ae 848 ospf_route_table_free(ospf->new_external_route);
849 }
850 if (ospf->old_external_route) {
10514170
RW
851 if (!ospf->gr_info.prepare_in_progress)
852 ospf_route_delete(ospf, ospf->old_external_route);
d62a17ae 853 ospf_route_table_free(ospf->old_external_route);
854 }
855 if (ospf->external_lsas) {
856 ospf_ase_external_lsas_finish(ospf->external_lsas);
857 }
718e3744 858
d62a17ae 859 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
860 struct list *ext_list;
d62a17ae 861 struct ospf_external *ext;
862
de1ac5fd 863 ext_list = ospf->external[i];
d62a17ae 864 if (!ext_list)
865 continue;
866
76fdc7f4 867 for (ALL_LIST_ELEMENTS(ext_list, node, nnode, ext)) {
d62a17ae 868 if (ext->external_info)
869 for (rn = route_top(ext->external_info); rn;
870 rn = route_next(rn)) {
871 if (rn->info == NULL)
872 continue;
873
874 XFREE(MTYPE_OSPF_EXTERNAL_INFO,
875 rn->info);
876 rn->info = NULL;
877 route_unlock_node(rn);
878 }
1d753551
DS
879
880 ospf_external_del(ospf, i, ext->instance);
d62a17ae 881 }
882 }
718e3744 883
d62a17ae 884 ospf_distance_reset(ospf);
885 route_table_finish(ospf->distance_table);
7c8ff89e 886
ad7222b7 887 /* Release extrenal Aggregator table */
888 for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) {
889 struct ospf_external_aggr_rt *aggr;
890
891 aggr = rn->info;
892
893 if (aggr) {
894 ospf_external_aggregator_free(aggr);
895 rn->info = NULL;
896 route_unlock_node(rn);
897 }
898 }
899
900 route_table_finish(ospf->rt_aggr_tbl);
901
902
c32eba04
CS
903 list_delete(&ospf->areas);
904 list_delete(&ospf->oi_write_q);
905
06bc3110 906 /* Reset GR helper data structers */
51f8588e 907 ospf_gr_helper_instance_stop(ospf);
06bc3110 908
c32eba04
CS
909 close(ospf->fd);
910 stream_free(ospf->ibuf);
911 ospf->fd = -1;
3d5b9855 912 ospf->max_multipath = MULTIPATH_NUM;
d62a17ae 913 ospf_delete(ospf);
7c8ff89e 914
1113a2fb 915 if (vrf)
916 ospf_vrf_unlink(ospf, vrf);
b5a8894d 917
1113a2fb 918 if (ospf->name)
919 XFREE(MTYPE_OSPF_TOP, ospf->name);
d62a17ae 920 XFREE(MTYPE_OSPF_TOP, ospf);
718e3744 921}
922
6b0655a2 923
718e3744 924/* allocate new OSPF Area object */
7fd0729f 925struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id)
718e3744 926{
d62a17ae 927 struct ospf_area *new;
718e3744 928
d62a17ae 929 /* Allocate new config_network. */
930 new = XCALLOC(MTYPE_OSPF_AREA, sizeof(struct ospf_area));
718e3744 931
d62a17ae 932 new->ospf = ospf;
718e3744 933
d62a17ae 934 new->area_id = area_id;
935 new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD;
718e3744 936
d62a17ae 937 new->external_routing = OSPF_AREA_DEFAULT;
938 new->default_cost = 1;
939 new->auth_type = OSPF_AUTH_NULL;
718e3744 940
d62a17ae 941 /* New LSDB init. */
942 new->lsdb = ospf_lsdb_new();
718e3744 943
d62a17ae 944 /* Self-originated LSAs initialize. */
945 new->router_lsa_self = NULL;
718e3744 946
d62a17ae 947 ospf_opaque_type10_lsa_init(new);
718e3744 948
d62a17ae 949 new->oiflist = list_new();
950 new->ranges = route_table_init();
718e3744 951
d62a17ae 952 if (area_id.s_addr == OSPF_AREA_BACKBONE)
953 ospf->backbone = new;
954
955 return new;
718e3744 956}
957
f91ce319 958void ospf_area_lsdb_discard_delete(struct ospf_area *area)
718e3744 959{
d62a17ae 960 struct route_node *rn;
961 struct ospf_lsa *lsa;
962
996c9314 963 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
044506e7 964 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 965 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
044506e7 966 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 967 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
044506e7 968 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 969 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
044506e7 970 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
68980084 971
996c9314 972 LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
044506e7 973 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 974 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7 975 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 976 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7 977 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
718e3744 978
d62a17ae 979 ospf_lsdb_delete_all(area->lsdb);
f91ce319
MR
980}
981
982static void ospf_area_free(struct ospf_area *area)
983{
984 ospf_opaque_type10_lsa_term(area);
985
986 /* Free LSDBs. */
987 ospf_area_lsdb_discard_delete(area);
988
d62a17ae 989 ospf_lsdb_free(area->lsdb);
718e3744 990
d62a17ae 991 ospf_lsa_unlock(&area->router_lsa_self);
718e3744 992
d62a17ae 993 route_table_finish(area->ranges);
6a154c88 994 list_delete(&area->oiflist);
718e3744 995
d62a17ae 996 if (EXPORT_NAME(area))
997 free(EXPORT_NAME(area));
718e3744 998
d62a17ae 999 if (IMPORT_NAME(area))
1000 free(IMPORT_NAME(area));
718e3744 1001
d62a17ae 1002 /* Cancel timer. */
1003 OSPF_TIMER_OFF(area->t_stub_router);
1004 OSPF_TIMER_OFF(area->t_opaque_lsa_self);
718e3744 1005
d62a17ae 1006 if (OSPF_IS_AREA_BACKBONE(area))
1007 area->ospf->backbone = NULL;
1008
1009 XFREE(MTYPE_OSPF_AREA, area);
718e3744 1010}
1011
d62a17ae 1012void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
718e3744 1013{
d62a17ae 1014 struct ospf_area *area;
718e3744 1015
d62a17ae 1016 area = ospf_area_lookup_by_area_id(ospf, area_id);
1017 if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
19ce7d5e 1018 && !ospf_vl_count(ospf, area)
d62a17ae 1019 && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
1020 && area->external_routing == OSPF_AREA_DEFAULT
1021 && area->no_summary == 0 && area->default_cost == 1
1022 && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL
1023 && area->auth_type == OSPF_AUTH_NULL) {
1024 listnode_delete(ospf->areas, area);
1025 ospf_area_free(area);
1026 }
718e3744 1027}
1028
d62a17ae 1029struct ospf_area *ospf_area_get(struct ospf *ospf, struct in_addr area_id)
718e3744 1030{
d62a17ae 1031 struct ospf_area *area;
1032
1033 area = ospf_area_lookup_by_area_id(ospf, area_id);
1034 if (!area) {
1035 area = ospf_area_new(ospf, area_id);
1036 listnode_add_sort(ospf->areas, area);
1037 ospf_check_abr_status(ospf);
1038 if (ospf->stub_router_admin_set
1039 == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET) {
1040 SET_FLAG(area->stub_router_state,
1041 OSPF_AREA_ADMIN_STUB_ROUTED);
1042 }
1043 }
718e3744 1044
d62a17ae 1045 return area;
718e3744 1046}
1047
d62a17ae 1048struct ospf_area *ospf_area_lookup_by_area_id(struct ospf *ospf,
1049 struct in_addr area_id)
718e3744 1050{
d62a17ae 1051 struct ospf_area *area;
1052 struct listnode *node;
718e3744 1053
d62a17ae 1054 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
1055 if (IPV4_ADDR_SAME(&area->area_id, &area_id))
1056 return area;
718e3744 1057
d62a17ae 1058 return NULL;
718e3744 1059}
1060
d62a17ae 1061void ospf_area_add_if(struct ospf_area *area, struct ospf_interface *oi)
718e3744 1062{
d62a17ae 1063 listnode_add(area->oiflist, oi);
718e3744 1064}
1065
d62a17ae 1066void ospf_area_del_if(struct ospf_area *area, struct ospf_interface *oi)
718e3744 1067{
d62a17ae 1068 listnode_delete(area->oiflist, oi);
718e3744 1069}
1070
52c62ab8 1071
7fd0729f
G
1072struct ospf_interface *add_ospf_interface(struct connected *co,
1073 struct ospf_area *area)
953cde65 1074{
d62a17ae 1075 struct ospf_interface *oi;
953cde65 1076
d62a17ae 1077 oi = ospf_if_new(area->ospf, co->ifp, co->address);
1078 oi->connected = co;
953cde65 1079
d62a17ae 1080 oi->area = area;
953cde65 1081
d62a17ae 1082 oi->params = ospf_lookup_if_params(co->ifp, oi->address->u.prefix4);
1083 oi->output_cost = ospf_if_get_output_cost(oi);
953cde65 1084
d62a17ae 1085 /* Relate ospf interface to ospf instance. */
1086 oi->ospf = area->ospf;
953cde65 1087
d62a17ae 1088 /* update network type as interface flag */
1089 /* If network type is specified previously,
1090 skip network type setting. */
1091 oi->type = IF_DEF_PARAMS(co->ifp)->type;
bc97889b 1092 oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
953cde65 1093
d62a17ae 1094 /* Add pseudo neighbor. */
1095 ospf_nbr_self_reset(oi, oi->ospf->router_id);
953cde65 1096
d62a17ae 1097 ospf_area_add_if(oi->area, oi);
52c62ab8 1098
132a782e 1099 /* if LDP-IGP Sync is configured globally inherit config */
1100 ospf_ldp_sync_if_init(oi);
1101
d62a17ae 1102 /*
1103 * if router_id is not configured, dont bring up
1104 * interfaces.
1105 * ospf_router_id_update() will call ospf_if_update
1106 * whenever r-id is configured instead.
1107 */
975a328e
DA
1108 if ((area->ospf->router_id.s_addr != INADDR_ANY)
1109 && if_is_operative(co->ifp))
d62a17ae 1110 ospf_if_up(oi);
7fd0729f
G
1111
1112 return oi;
953cde65
JT
1113}
1114
1115static void update_redistributed(struct ospf *ospf, int add_to_ospf)
1116{
d62a17ae 1117 struct route_node *rn;
1118 struct external_info *ei;
1119 struct ospf_external *ext;
1120
de1ac5fd
CS
1121 if (ospf_is_type_redistributed(ospf, ZEBRA_ROUTE_CONNECT, 0)) {
1122 ext = ospf_external_lookup(ospf, ZEBRA_ROUTE_CONNECT, 0);
1123 if ((ext) && EXTERNAL_INFO(ext)) {
d62a17ae 1124 for (rn = route_top(EXTERNAL_INFO(ext)); rn;
1125 rn = route_next(rn)) {
de1ac5fd
CS
1126 ei = rn->info;
1127 if (ei == NULL)
1128 continue;
1129
1130 if (add_to_ospf) {
996c9314
LB
1131 if (ospf_external_info_find_lsa(ospf,
1132 &ei->p))
de1ac5fd
CS
1133 if (!ospf_distribute_check_connected(
1134 ospf, ei))
1135 ospf_external_lsa_flush(
996c9314 1136 ospf, ei->type,
de1ac5fd
CS
1137 &ei->p,
1138 ei->ifindex /*, ei->nexthop */);
1139 } else {
1140 if (!ospf_external_info_find_lsa(
1141 ospf, &ei->p))
1142 if (ospf_distribute_check_connected(
1143 ospf, ei))
1144 ospf_external_lsa_originate(
996c9314 1145 ospf, ei);
d62a17ae 1146 }
1147 }
1148 }
de1ac5fd 1149 }
953cde65
JT
1150}
1151
718e3744 1152/* Config network statement related functions. */
d62a17ae 1153static struct ospf_network *ospf_network_new(struct in_addr area_id)
718e3744 1154{
d62a17ae 1155 struct ospf_network *new;
1156 new = XCALLOC(MTYPE_OSPF_NETWORK, sizeof(struct ospf_network));
718e3744 1157
d62a17ae 1158 new->area_id = area_id;
1159 new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD;
1160
1161 return new;
718e3744 1162}
1163
d62a17ae 1164static void ospf_network_free(struct ospf *ospf, struct ospf_network *network)
718e3744 1165{
d62a17ae 1166 ospf_area_check_free(ospf, network->area_id);
1167 ospf_schedule_abr_task(ospf);
1168 XFREE(MTYPE_OSPF_NETWORK, network);
718e3744 1169}
1170
d62a17ae 1171int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p,
1172 struct in_addr area_id, int df)
718e3744 1173{
d62a17ae 1174 struct ospf_network *network;
1175 struct ospf_area *area;
1176 struct route_node *rn;
718e3744 1177
d62a17ae 1178 rn = route_node_get(ospf->networks, (struct prefix *)p);
1179 if (rn->info) {
2b0a905a 1180 network = rn->info;
d62a17ae 1181 route_unlock_node(rn);
2b0a905a
DW
1182
1183 if (IPV4_ADDR_SAME(&area_id, &network->area_id)) {
1184 return 1;
1185 } else {
1186 /* There is already same network statement. */
1187 return 0;
1188 }
d62a17ae 1189 }
718e3744 1190
d62a17ae 1191 rn->info = network = ospf_network_new(area_id);
1192 network->area_id_fmt = df;
1193 area = ospf_area_get(ospf, area_id);
1194 ospf_area_display_format_set(ospf, area, df);
718e3744 1195
d62a17ae 1196 /* Run network config now. */
1197 ospf_network_run((struct prefix *)p, area);
718e3744 1198
d62a17ae 1199 /* Update connected redistribute. */
1200 update_redistributed(ospf, 1); /* interfaces possibly added */
718e3744 1201
d62a17ae 1202 ospf_area_check_free(ospf, area_id);
718e3744 1203
d62a17ae 1204 return 1;
718e3744 1205}
1206
d62a17ae 1207int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p,
1208 struct in_addr area_id)
718e3744 1209{
d62a17ae 1210 struct route_node *rn;
1211 struct ospf_network *network;
1212 struct listnode *node, *nnode;
1213 struct ospf_interface *oi;
718e3744 1214
d62a17ae 1215 rn = route_node_lookup(ospf->networks, (struct prefix *)p);
1216 if (rn == NULL)
1217 return 0;
718e3744 1218
d62a17ae 1219 network = rn->info;
1220 route_unlock_node(rn);
1221 if (!IPV4_ADDR_SAME(&area_id, &network->area_id))
1222 return 0;
718e3744 1223
d62a17ae 1224 ospf_network_free(ospf, rn->info);
1225 rn->info = NULL;
1226 route_unlock_node(rn); /* initial reference */
718e3744 1227
30c0daa4 1228 /* Find interfaces that are not configured already. */
d62a17ae 1229 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
30c0daa4 1230
996c9314
LB
1231 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
1232 continue;
30c0daa4 1233
996c9314 1234 ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
d62a17ae 1235 }
953cde65 1236
d62a17ae 1237 /* Update connected redistribute. */
1238 update_redistributed(ospf, 0); /* interfaces possibly removed */
1239 ospf_area_check_free(ospf, area_id);
1240
1241 return 1;
953cde65
JT
1242}
1243
52c62ab8
JAG
1244/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
1245 * there might not be any 'router ospf' config.
1246 *
1247 * Otherwise, doesn't do anything different to ospf_if_update for now
1248 */
b5a8894d 1249void ospf_interface_area_set(struct ospf *ospf, struct interface *ifp)
953cde65 1250{
b5a8894d
CS
1251 if (!ospf)
1252 return;
d62a17ae 1253
1254 ospf_if_update(ospf, ifp);
1255 /* if_update does a update_redistributed */
1256
1257 return;
953cde65
JT
1258}
1259
b5a8894d 1260void ospf_interface_area_unset(struct ospf *ospf, struct interface *ifp)
953cde65 1261{
d62a17ae 1262 struct route_node *rn_oi;
953cde65 1263
d62a17ae 1264 if (!ospf)
1265 return; /* Ospf not ready yet */
953cde65 1266
d62a17ae 1267 /* Find interfaces that may need to be removed. */
1268 for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi;
1269 rn_oi = route_next(rn_oi)) {
b5a8894d 1270 struct ospf_interface *oi = NULL;
d62a17ae 1271
1272 if ((oi = rn_oi->info) == NULL)
1273 continue;
1274
1275 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
1276 continue;
1277
1278 ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
1279 }
953cde65 1280
d62a17ae 1281 /* Update connected redistribute. */
1282 update_redistributed(ospf, 0); /* interfaces possibly removed */
718e3744 1283}
1284
570f7598 1285/* Check whether interface matches given network
1286 * returns: 1, true. 0, false
1287 */
d62a17ae 1288static int ospf_network_match_iface(const struct connected *co,
1289 const struct prefix *net)
570f7598 1290{
d62a17ae 1291 /* new approach: more elegant and conceptually clean */
1292 return prefix_match_network_statement(net, CONNECTED_PREFIX(co));
570f7598 1293}
1294
d62a17ae 1295static void ospf_update_interface_area(struct connected *co,
1296 struct ospf_area *area)
52c62ab8 1297{
d62a17ae 1298 struct ospf_interface *oi = ospf_if_table_lookup(co->ifp, co->address);
1299
1300 /* nothing to be done case */
1301 if (oi && oi->area == area) {
1302 return;
1303 }
1304
1305 if (oi)
1306 ospf_if_free(oi);
1307
1308 add_ospf_interface(co, area);
52c62ab8
JAG
1309}
1310
1311/* Run OSPF for the given subnet, taking into account the following
1312 * possible sources of area configuration, in the given order of preference:
1313 *
1314 * - Whether there is interface+address specific area configuration
1315 * - Whether there is a default area for the interface
1316 * - Whether there is an area given as a parameter.
1317 * - If no specific network prefix/area is supplied, whether there's
1318 * a matching network configured.
1319 */
d62a17ae 1320static void ospf_network_run_subnet(struct ospf *ospf, struct connected *co,
1321 struct prefix *p,
1322 struct ospf_area *given_area)
1323{
1324 struct ospf_interface *oi;
1325 struct ospf_if_params *params;
1326 struct ospf_area *area = NULL;
1327 struct route_node *rn;
1328 int configed = 0;
1329
1330 if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
1331 return;
1332
1333 if (co->address->family != AF_INET)
1334 return;
1335
1336 /* Try determine the appropriate area for this interface + address
1337 * Start by checking interface config
1338 */
1339 params = ospf_lookup_if_params(co->ifp, co->address->u.prefix4);
1340 if (params && OSPF_IF_PARAM_CONFIGURED(params, if_area))
1341 area = ospf_area_get(ospf, params->if_area);
1342 else {
1343 params = IF_DEF_PARAMS(co->ifp);
1344 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
1345 area = ospf_area_get(ospf, params->if_area);
1346 }
52c62ab8 1347
d62a17ae 1348 /* If we've found an interface and/or addr specific area, then we're
1349 * done
1350 */
1351 if (area) {
1352 ospf_update_interface_area(co, area);
1353 return;
1354 }
718e3744 1355
d62a17ae 1356 /* Otherwise, only remaining possibility is a matching network statement
1357 */
1358 if (p) {
1359 assert(given_area != NULL);
1360
1361 /* Which either was supplied as a parameter.. (e.g. cause a new
1362 * network/area was just added)..
1363 */
1364 if (p->family == co->address->family
1365 && ospf_network_match_iface(co, p))
1366 ospf_update_interface_area(co, given_area);
1367
1368 return;
1369 }
1370
1371 /* Else we have to search the existing network/area config to see
1372 * if any match..
1373 */
1374 for (rn = route_top(ospf->networks); rn; rn = route_next(rn))
1375 if (rn->info != NULL && ospf_network_match_iface(co, &rn->p)) {
1376 struct ospf_network *network =
1377 (struct ospf_network *)rn->info;
1378 area = ospf_area_get(ospf, network->area_id);
1379 ospf_update_interface_area(co, area);
1380 configed = 1;
1381 }
1382
1383 /* If the subnet isn't in any area, deconfigure */
1384 if (!configed && (oi = ospf_if_table_lookup(co->ifp, co->address)))
1385 ospf_if_free(oi);
718e3744 1386}
1387
d62a17ae 1388static void ospf_network_run_interface(struct ospf *ospf, struct interface *ifp,
1389 struct prefix *p,
1390 struct ospf_area *given_area)
718e3744 1391{
d62a17ae 1392 struct listnode *cnode;
1393 struct connected *co;
1394
1395 if (memcmp(ifp->name, "VLINK", 5) == 0)
1396 return;
718e3744 1397
d62a17ae 1398 /* Network prefix without area is nonsensical */
1399 if (p)
1400 assert(given_area != NULL);
1401
1402 /* if interface prefix is match specified prefix,
1403 then create socket and join multicast group. */
1404 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co))
1405 ospf_network_run_subnet(ospf, co, p, given_area);
718e3744 1406}
1407
d62a17ae 1408static void ospf_network_run(struct prefix *p, struct ospf_area *area)
718e3744 1409{
f4e14fdb 1410 struct vrf *vrf = vrf_lookup_by_id(area->ospf->vrf_id);
d62a17ae 1411 struct interface *ifp;
d62a17ae 1412
1413 /* Schedule Router ID Update. */
975a328e 1414 if (area->ospf->router_id.s_addr == INADDR_ANY)
d62a17ae 1415 ospf_router_id_update(area->ospf);
718e3744 1416
d62a17ae 1417 /* Get target interface. */
451fda4f 1418 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 1419 ospf_network_run_interface(area->ospf, ifp, p, area);
718e3744 1420}
1421
d62a17ae 1422void ospf_ls_upd_queue_empty(struct ospf_interface *oi)
1423{
1424 struct route_node *rn;
1425 struct listnode *node, *nnode;
1426 struct list *lst;
1427 struct ospf_lsa *lsa;
1428
1429 /* empty ls update queue */
1430 for (rn = route_top(oi->ls_upd_queue); rn; rn = route_next(rn))
1431 if ((lst = (struct list *)rn->info)) {
1432 for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa))
1433 ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */
6a154c88 1434 list_delete(&lst);
d62a17ae 1435 rn->info = NULL;
1436 }
1437
1438 /* remove update event */
b3d6bc6e 1439 thread_cancel(&oi->t_ls_upd_event);
d62a17ae 1440}
6b0655a2 1441
d62a17ae 1442void ospf_if_update(struct ospf *ospf, struct interface *ifp)
718e3744 1443{
43b8d1d8 1444
d62a17ae 1445 if (!ospf)
43b8d1d8 1446 return;
b5a8894d
CS
1447
1448 if (IS_DEBUG_OSPF_EVENT)
996c9314 1449 zlog_debug(
96b663a3 1450 "%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %pI4",
15569c58 1451 __func__, ifp->name, ifp->vrf_id,
996c9314 1452 ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id,
96b663a3 1453 &ospf->router_id);
d62a17ae 1454
1455 /* OSPF must be ready. */
1456 if (!ospf_is_ready(ospf))
1457 return;
1458
1459 ospf_network_run_interface(ospf, ifp, NULL, NULL);
1460
1461 /* Update connected redistribute. */
1462 update_redistributed(ospf, 1);
ef7bd2a3 1463
d62a17ae 1464}
718e3744 1465
d62a17ae 1466void ospf_remove_vls_through_area(struct ospf *ospf, struct ospf_area *area)
718e3744 1467{
d62a17ae 1468 struct listnode *node, *nnode;
1469 struct ospf_vl_data *vl_data;
718e3744 1470
d62a17ae 1471 for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
1472 if (IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
1473 ospf_vl_delete(ospf, vl_data);
1474}
718e3744 1475
718e3744 1476
d62a17ae 1477static const struct message ospf_area_type_msg[] = {
1478 {OSPF_AREA_DEFAULT, "Default"},
1479 {OSPF_AREA_STUB, "Stub"},
1480 {OSPF_AREA_NSSA, "NSSA"},
1481 {0}};
718e3744 1482
d62a17ae 1483static void ospf_area_type_set(struct ospf_area *area, int type)
1484{
1485 struct listnode *node;
1486 struct ospf_interface *oi;
1487
1488 if (area->external_routing == type) {
1489 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
1490 zlog_debug("Area[%pI4]: Types are the same, ignored.",
1491 &area->area_id);
d62a17ae 1492 return;
1493 }
718e3744 1494
d62a17ae 1495 area->external_routing = type;
1496
1497 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
1498 zlog_debug("Area[%pI4]: Configured as %s",
1499 &area->area_id,
d62a17ae 1500 lookup_msg(ospf_area_type_msg, type, NULL));
1501
1502 switch (area->external_routing) {
1503 case OSPF_AREA_DEFAULT:
1504 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1505 if (oi->nbr_self != NULL) {
1506 UNSET_FLAG(oi->nbr_self->options,
1507 OSPF_OPTION_NP);
1508 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
1509 }
1510 break;
1511 case OSPF_AREA_STUB:
1512 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1513 if (oi->nbr_self != NULL) {
1514 if (IS_DEBUG_OSPF_EVENT)
1515 zlog_debug(
1516 "setting options on %s accordingly",
1517 IF_NAME(oi));
1518 UNSET_FLAG(oi->nbr_self->options,
1519 OSPF_OPTION_NP);
1520 UNSET_FLAG(oi->nbr_self->options,
1521 OSPF_OPTION_E);
1522 if (IS_DEBUG_OSPF_EVENT)
1523 zlog_debug("options set on %s: %x",
1524 IF_NAME(oi), OPTIONS(oi));
1525 }
1526 break;
1527 case OSPF_AREA_NSSA:
1528 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1529 if (oi->nbr_self != NULL) {
1530 zlog_debug(
1531 "setting nssa options on %s accordingly",
1532 IF_NAME(oi));
1533 UNSET_FLAG(oi->nbr_self->options,
1534 OSPF_OPTION_E);
1535 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP);
1536 zlog_debug("options set on %s: %x", IF_NAME(oi),
1537 OPTIONS(oi));
1538 }
1539 break;
1540 default:
1541 break;
1542 }
1543
1544 ospf_router_lsa_update_area(area);
1545 ospf_schedule_abr_task(area->ospf);
718e3744 1546}
1547
d62a17ae 1548int ospf_area_shortcut_set(struct ospf *ospf, struct ospf_area *area, int mode)
718e3744 1549{
d62a17ae 1550 if (area->shortcut_configured == mode)
1551 return 0;
718e3744 1552
d62a17ae 1553 area->shortcut_configured = mode;
1554 ospf_router_lsa_update_area(area);
1555 ospf_schedule_abr_task(ospf);
718e3744 1556
d62a17ae 1557 ospf_area_check_free(ospf, area->area_id);
718e3744 1558
d62a17ae 1559 return 1;
718e3744 1560}
1561
d62a17ae 1562int ospf_area_shortcut_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1563{
d62a17ae 1564 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1565 ospf_router_lsa_update_area(area);
1566 ospf_area_check_free(ospf, area->area_id);
1567 ospf_schedule_abr_task(ospf);
718e3744 1568
d62a17ae 1569 return 1;
718e3744 1570}
1571
d62a17ae 1572static int ospf_area_vlink_count(struct ospf *ospf, struct ospf_area *area)
718e3744 1573{
d62a17ae 1574 struct ospf_vl_data *vl;
1575 struct listnode *node;
1576 int count = 0;
718e3744 1577
d62a17ae 1578 for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl))
1579 if (IPV4_ADDR_SAME(&vl->vl_area_id, &area->area_id))
1580 count++;
718e3744 1581
d62a17ae 1582 return count;
718e3744 1583}
1584
d62a17ae 1585int ospf_area_display_format_set(struct ospf *ospf, struct ospf_area *area,
1586 int df)
86573dcb 1587{
d62a17ae 1588 area->area_id_fmt = df;
86573dcb 1589
d62a17ae 1590 return 1;
86573dcb
QY
1591}
1592
d62a17ae 1593int ospf_area_stub_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1594{
d62a17ae 1595 struct ospf_area *area;
718e3744 1596
d62a17ae 1597 area = ospf_area_get(ospf, area_id);
1598 if (ospf_area_vlink_count(ospf, area))
1599 return 0;
718e3744 1600
d62a17ae 1601 if (area->external_routing != OSPF_AREA_STUB)
1602 ospf_area_type_set(area, OSPF_AREA_STUB);
718e3744 1603
d62a17ae 1604 return 1;
718e3744 1605}
1606
d62a17ae 1607int ospf_area_stub_unset(struct ospf *ospf, struct in_addr area_id)
718e3744 1608{
d62a17ae 1609 struct ospf_area *area;
718e3744 1610
d62a17ae 1611 area = ospf_area_lookup_by_area_id(ospf, area_id);
1612 if (area == NULL)
1613 return 1;
718e3744 1614
d62a17ae 1615 if (area->external_routing == OSPF_AREA_STUB)
1616 ospf_area_type_set(area, OSPF_AREA_DEFAULT);
718e3744 1617
d62a17ae 1618 ospf_area_check_free(ospf, area_id);
718e3744 1619
d62a17ae 1620 return 1;
718e3744 1621}
1622
d62a17ae 1623int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1624{
d62a17ae 1625 struct ospf_area *area;
718e3744 1626
d62a17ae 1627 area = ospf_area_get(ospf, area_id);
1628 area->no_summary = 1;
718e3744 1629
d62a17ae 1630 return 1;
718e3744 1631}
1632
d62a17ae 1633int ospf_area_no_summary_unset(struct ospf *ospf, struct in_addr area_id)
718e3744 1634{
d62a17ae 1635 struct ospf_area *area;
718e3744 1636
d62a17ae 1637 area = ospf_area_lookup_by_area_id(ospf, area_id);
1638 if (area == NULL)
1639 return 0;
718e3744 1640
d62a17ae 1641 area->no_summary = 0;
1642 ospf_area_check_free(ospf, area_id);
718e3744 1643
d62a17ae 1644 return 1;
718e3744 1645}
1646
7ef56a73 1647int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1648{
d62a17ae 1649 struct ospf_area *area;
718e3744 1650
d62a17ae 1651 area = ospf_area_get(ospf, area_id);
1652 if (ospf_area_vlink_count(ospf, area))
1653 return 0;
718e3744 1654
d62a17ae 1655 if (area->external_routing != OSPF_AREA_NSSA) {
1656 ospf_area_type_set(area, OSPF_AREA_NSSA);
1657 ospf->anyNSSA++;
7ef56a73 1658 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
d62a17ae 1659 }
718e3744 1660
7ef56a73 1661 ospf_area_no_summary_set(ospf, area_id);
084c7844 1662
d62a17ae 1663 return 1;
718e3744 1664}
1665
7ef56a73
CS
1666int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
1667{
1668 struct ospf_area *area;
1669
1670 area = ospf_area_get(ospf, area_id);
1671 if (ospf_area_vlink_count(ospf, area))
1672 return 0;
1673
1674 if (area->external_routing != OSPF_AREA_NSSA) {
1675 ospf_area_type_set(area, OSPF_AREA_NSSA);
1676 ospf->anyNSSA++;
1677
1678 /* set NSSA area defaults */
1679 area->no_summary = 0;
c317eddb 1680 area->suppress_fa = 0;
7ef56a73
CS
1681 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
1682 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
1683 area->NSSATranslatorStabilityInterval =
1684 OSPF_NSSA_TRANS_STABLE_DEFAULT;
1685 }
1686 return 1;
1687}
1688
1689int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
718e3744 1690{
d62a17ae 1691 struct ospf_area *area;
718e3744 1692
d62a17ae 1693 area = ospf_area_lookup_by_area_id(ospf, area_id);
1694 if (area == NULL)
1695 return 0;
718e3744 1696
7ef56a73
CS
1697 /* argc < 5 -> 'no area x nssa' */
1698 if (argc < 5 && area->external_routing == OSPF_AREA_NSSA) {
d62a17ae 1699 ospf->anyNSSA--;
7ef56a73
CS
1700 /* set NSSA area defaults */
1701 area->no_summary = 0;
c317eddb 1702 area->suppress_fa = 0;
7ef56a73
CS
1703 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
1704 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
1705 area->NSSATranslatorStabilityInterval =
1706 OSPF_NSSA_TRANS_STABLE_DEFAULT;
d62a17ae 1707 ospf_area_type_set(area, OSPF_AREA_DEFAULT);
7ef56a73 1708 } else {
a987fe6b 1709 ospf_area_nssa_translator_role_set(ospf, area_id,
1710 OSPF_NSSA_ROLE_CANDIDATE);
d62a17ae 1711 }
718e3744 1712
d62a17ae 1713 ospf_area_check_free(ospf, area_id);
718e3744 1714
d62a17ae 1715 return 1;
718e3744 1716}
1717
c317eddb 1718int ospf_area_nssa_suppress_fa_set(struct ospf *ospf, struct in_addr area_id)
1719{
1720 struct ospf_area *area;
1721
1722 area = ospf_area_lookup_by_area_id(ospf, area_id);
1723 if (area == NULL)
1724 return 0;
1725
1726 area->suppress_fa = 1;
1727
1728 return 1;
1729}
1730
1731int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf, struct in_addr area_id)
1732{
1733 struct ospf_area *area;
1734
1735 area = ospf_area_lookup_by_area_id(ospf, area_id);
1736 if (area == NULL)
1737 return 0;
1738
1739 area->suppress_fa = 0;
1740
1741 return 1;
1742}
1743
d62a17ae 1744int ospf_area_nssa_translator_role_set(struct ospf *ospf,
1745 struct in_addr area_id, int role)
718e3744 1746{
d62a17ae 1747 struct ospf_area *area;
718e3744 1748
d62a17ae 1749 area = ospf_area_lookup_by_area_id(ospf, area_id);
1750 if (area == NULL)
1751 return 0;
718e3744 1752
a987fe6b 1753 if (role != area->NSSATranslatorRole) {
1754 if ((area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)
1755 || (role == OSPF_NSSA_ROLE_ALWAYS)) {
1756 /* RFC 3101 3.1
1757 * if new role is OSPF_NSSA_ROLE_ALWAYS we need to set
1758 * Nt bit, if the role was OSPF_NSSA_ROLE_ALWAYS we need
1759 * to clear Nt bit
1760 */
1761 area->NSSATranslatorRole = role;
1762 ospf_router_lsa_update_area(area);
1763 } else
1764 area->NSSATranslatorRole = role;
1765 }
718e3744 1766
d62a17ae 1767 return 1;
718e3744 1768}
1769
d62a17ae 1770int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area,
1771 const char *list_name)
718e3744 1772{
d62a17ae 1773 struct access_list *list;
1774 list = access_list_lookup(AFI_IP, list_name);
718e3744 1775
d62a17ae 1776 EXPORT_LIST(area) = list;
718e3744 1777
d62a17ae 1778 if (EXPORT_NAME(area))
1779 free(EXPORT_NAME(area));
718e3744 1780
d62a17ae 1781 EXPORT_NAME(area) = strdup(list_name);
1782 ospf_schedule_abr_task(ospf);
718e3744 1783
d62a17ae 1784 return 1;
718e3744 1785}
1786
d62a17ae 1787int ospf_area_export_list_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1788{
1789
d62a17ae 1790 EXPORT_LIST(area) = 0;
718e3744 1791
d62a17ae 1792 if (EXPORT_NAME(area))
1793 free(EXPORT_NAME(area));
718e3744 1794
d62a17ae 1795 EXPORT_NAME(area) = NULL;
718e3744 1796
d62a17ae 1797 ospf_area_check_free(ospf, area->area_id);
718e3744 1798
d62a17ae 1799 ospf_schedule_abr_task(ospf);
1800
1801 return 1;
718e3744 1802}
1803
d62a17ae 1804int ospf_area_import_list_set(struct ospf *ospf, struct ospf_area *area,
1805 const char *name)
718e3744 1806{
d62a17ae 1807 struct access_list *list;
1808 list = access_list_lookup(AFI_IP, name);
718e3744 1809
d62a17ae 1810 IMPORT_LIST(area) = list;
718e3744 1811
d62a17ae 1812 if (IMPORT_NAME(area))
1813 free(IMPORT_NAME(area));
718e3744 1814
d62a17ae 1815 IMPORT_NAME(area) = strdup(name);
1816 ospf_schedule_abr_task(ospf);
718e3744 1817
d62a17ae 1818 return 1;
718e3744 1819}
1820
d62a17ae 1821int ospf_area_import_list_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1822{
d62a17ae 1823 IMPORT_LIST(area) = 0;
718e3744 1824
d62a17ae 1825 if (IMPORT_NAME(area))
1826 free(IMPORT_NAME(area));
718e3744 1827
d62a17ae 1828 IMPORT_NAME(area) = NULL;
1829 ospf_area_check_free(ospf, area->area_id);
718e3744 1830
d62a17ae 1831 ospf_schedule_abr_task(ospf);
718e3744 1832
d62a17ae 1833 return 1;
718e3744 1834}
1835
d62a17ae 1836int ospf_timers_refresh_set(struct ospf *ospf, int interval)
718e3744 1837{
d62a17ae 1838 int time_left;
718e3744 1839
d62a17ae 1840 if (ospf->lsa_refresh_interval == interval)
1841 return 1;
718e3744 1842
d62a17ae 1843 time_left = ospf->lsa_refresh_interval
1844 - (monotime(NULL) - ospf->lsa_refresher_started);
718e3744 1845
d62a17ae 1846 if (time_left > interval) {
1847 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
1848 thread_add_timer(master, ospf_lsa_refresh_walker, ospf,
1849 interval, &ospf->t_lsa_refresher);
1850 }
1851 ospf->lsa_refresh_interval = interval;
1852
1853 return 1;
718e3744 1854}
1855
d62a17ae 1856int ospf_timers_refresh_unset(struct ospf *ospf)
718e3744 1857{
d62a17ae 1858 int time_left;
718e3744 1859
d62a17ae 1860 time_left = ospf->lsa_refresh_interval
1861 - (monotime(NULL) - ospf->lsa_refresher_started);
718e3744 1862
d62a17ae 1863 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) {
1864 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
1865 ospf->t_lsa_refresher = NULL;
1866 thread_add_timer(master, ospf_lsa_refresh_walker, ospf,
1867 OSPF_LSA_REFRESH_INTERVAL_DEFAULT,
1868 &ospf->t_lsa_refresher);
1869 }
718e3744 1870
d62a17ae 1871 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
718e3744 1872
d62a17ae 1873 return 1;
718e3744 1874}
1875
6b0655a2 1876
d62a17ae 1877static struct ospf_nbr_nbma *ospf_nbr_nbma_new(void)
718e3744 1878{
d62a17ae 1879 struct ospf_nbr_nbma *nbr_nbma;
718e3744 1880
d62a17ae 1881 nbr_nbma = XCALLOC(MTYPE_OSPF_NEIGHBOR_STATIC,
1882 sizeof(struct ospf_nbr_nbma));
718e3744 1883
d62a17ae 1884 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1885 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
718e3744 1886
d62a17ae 1887 return nbr_nbma;
718e3744 1888}
1889
d62a17ae 1890static void ospf_nbr_nbma_free(struct ospf_nbr_nbma *nbr_nbma)
718e3744 1891{
d62a17ae 1892 XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
718e3744 1893}
1894
d62a17ae 1895static void ospf_nbr_nbma_delete(struct ospf *ospf,
1896 struct ospf_nbr_nbma *nbr_nbma)
718e3744 1897{
d62a17ae 1898 struct route_node *rn;
1899 struct prefix_ipv4 p;
718e3744 1900
d62a17ae 1901 p.family = AF_INET;
1902 p.prefix = nbr_nbma->addr;
1903 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 1904
d62a17ae 1905 rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p);
1906 if (rn) {
1907 ospf_nbr_nbma_free(rn->info);
1908 rn->info = NULL;
1909 route_unlock_node(rn);
1910 route_unlock_node(rn);
1911 }
718e3744 1912}
1913
d62a17ae 1914static void ospf_nbr_nbma_down(struct ospf_nbr_nbma *nbr_nbma)
718e3744 1915{
d62a17ae 1916 OSPF_TIMER_OFF(nbr_nbma->t_poll);
718e3744 1917
d62a17ae 1918 if (nbr_nbma->nbr) {
1919 nbr_nbma->nbr->nbr_nbma = NULL;
1920 OSPF_NSM_EVENT_EXECUTE(nbr_nbma->nbr, NSM_KillNbr);
1921 }
718e3744 1922
d62a17ae 1923 if (nbr_nbma->oi)
1924 listnode_delete(nbr_nbma->oi->nbr_nbma, nbr_nbma);
718e3744 1925}
1926
d62a17ae 1927static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma,
1928 struct ospf_interface *oi)
718e3744 1929{
d62a17ae 1930 struct ospf_neighbor *nbr;
1931 struct route_node *rn;
1932 struct prefix p;
718e3744 1933
d62a17ae 1934 if (oi->type != OSPF_IFTYPE_NBMA)
1935 return;
718e3744 1936
d62a17ae 1937 if (nbr_nbma->nbr != NULL)
1938 return;
718e3744 1939
d62a17ae 1940 if (IPV4_ADDR_SAME(&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1941 return;
718e3744 1942
d62a17ae 1943 nbr_nbma->oi = oi;
1944 listnode_add(oi->nbr_nbma, nbr_nbma);
718e3744 1945
d62a17ae 1946 /* Get neighbor information from table. */
1947 p.family = AF_INET;
1948 p.prefixlen = IPV4_MAX_BITLEN;
1949 p.u.prefix4 = nbr_nbma->addr;
718e3744 1950
c4efd0f4 1951 rn = route_node_get(oi->nbrs, &p);
d62a17ae 1952 if (rn->info) {
1953 nbr = rn->info;
1954 nbr->nbr_nbma = nbr_nbma;
1955 nbr_nbma->nbr = nbr;
718e3744 1956
d62a17ae 1957 route_unlock_node(rn);
1958 } else {
1959 nbr = rn->info = ospf_nbr_new(oi);
1960 nbr->state = NSM_Down;
1961 nbr->src = nbr_nbma->addr;
1962 nbr->nbr_nbma = nbr_nbma;
1963 nbr->priority = nbr_nbma->priority;
1964 nbr->address = p;
718e3744 1965
d62a17ae 1966 nbr_nbma->nbr = nbr;
1967
659f4e40
RZ
1968 /* Configure BFD if interface has it. */
1969 ospf_neighbor_bfd_apply(nbr);
1970
d62a17ae 1971 OSPF_NSM_EVENT_EXECUTE(nbr, NSM_Start);
1972 }
718e3744 1973}
1974
d62a17ae 1975void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi)
718e3744 1976{
d62a17ae 1977 struct ospf_nbr_nbma *nbr_nbma;
1978 struct route_node *rn;
1979 struct prefix_ipv4 p;
718e3744 1980
d62a17ae 1981 if (oi->type != OSPF_IFTYPE_NBMA)
1982 return;
718e3744 1983
d62a17ae 1984 for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
1985 if ((nbr_nbma = rn->info))
1986 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL) {
1987 p.family = AF_INET;
1988 p.prefix = nbr_nbma->addr;
1989 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 1990
d62a17ae 1991 if (prefix_match(oi->address,
1992 (struct prefix *)&p))
1993 ospf_nbr_nbma_add(nbr_nbma, oi);
1994 }
718e3744 1995}
1996
d62a17ae 1997struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *ospf,
1998 struct in_addr nbr_addr)
718e3744 1999{
d62a17ae 2000 struct route_node *rn;
2001 struct prefix_ipv4 p;
718e3744 2002
d62a17ae 2003 p.family = AF_INET;
2004 p.prefix = nbr_addr;
2005 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 2006
d62a17ae 2007 rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p);
2008 if (rn) {
2009 route_unlock_node(rn);
2010 return rn->info;
2011 }
2012 return NULL;
718e3744 2013}
2014
d62a17ae 2015int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2016{
d62a17ae 2017 struct ospf_nbr_nbma *nbr_nbma;
2018 struct ospf_interface *oi;
2019 struct prefix_ipv4 p;
2020 struct route_node *rn;
2021 struct listnode *node;
718e3744 2022
d62a17ae 2023 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2024 if (nbr_nbma)
2025 return 0;
718e3744 2026
d62a17ae 2027 nbr_nbma = ospf_nbr_nbma_new();
2028 nbr_nbma->addr = nbr_addr;
718e3744 2029
d62a17ae 2030 p.family = AF_INET;
2031 p.prefix = nbr_addr;
2032 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 2033
d62a17ae 2034 rn = route_node_get(ospf->nbr_nbma, (struct prefix *)&p);
2035 if (rn->info)
2036 route_unlock_node(rn);
2037 rn->info = nbr_nbma;
718e3744 2038
d62a17ae 2039 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
2040 if (oi->type == OSPF_IFTYPE_NBMA)
2041 if (prefix_match(oi->address, (struct prefix *)&p)) {
2042 ospf_nbr_nbma_add(nbr_nbma, oi);
2043 break;
2044 }
2045 }
718e3744 2046
d62a17ae 2047 return 1;
718e3744 2048}
2049
d62a17ae 2050int ospf_nbr_nbma_unset(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2051{
d62a17ae 2052 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2053
d62a17ae 2054 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2055 if (nbr_nbma == NULL)
2056 return 0;
718e3744 2057
d62a17ae 2058 ospf_nbr_nbma_down(nbr_nbma);
2059 ospf_nbr_nbma_delete(ospf, nbr_nbma);
718e3744 2060
d62a17ae 2061 return 1;
718e3744 2062}
2063
d62a17ae 2064int ospf_nbr_nbma_priority_set(struct ospf *ospf, struct in_addr nbr_addr,
d7c0a89a 2065 uint8_t priority)
718e3744 2066{
d62a17ae 2067 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2068
d62a17ae 2069 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2070 if (nbr_nbma == NULL)
2071 return 0;
718e3744 2072
d62a17ae 2073 if (nbr_nbma->priority != priority)
2074 nbr_nbma->priority = priority;
718e3744 2075
d62a17ae 2076 return 1;
718e3744 2077}
2078
d62a17ae 2079int ospf_nbr_nbma_priority_unset(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2080{
d62a17ae 2081 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2082
d62a17ae 2083 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2084 if (nbr_nbma == NULL)
2085 return 0;
718e3744 2086
d62a17ae 2087 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
2088 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
718e3744 2089
d62a17ae 2090 return 1;
718e3744 2091}
2092
d62a17ae 2093int ospf_nbr_nbma_poll_interval_set(struct ospf *ospf, struct in_addr nbr_addr,
2094 unsigned int interval)
718e3744 2095{
d62a17ae 2096 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2097
d62a17ae 2098 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2099 if (nbr_nbma == NULL)
2100 return 0;
718e3744 2101
d62a17ae 2102 if (nbr_nbma->v_poll != interval) {
2103 nbr_nbma->v_poll = interval;
2104 if (nbr_nbma->oi && ospf_if_is_up(nbr_nbma->oi)) {
2105 OSPF_TIMER_OFF(nbr_nbma->t_poll);
2106 OSPF_POLL_TIMER_ON(nbr_nbma->t_poll, ospf_poll_timer,
2107 nbr_nbma->v_poll);
2108 }
718e3744 2109 }
718e3744 2110
d62a17ae 2111 return 1;
718e3744 2112}
2113
d62a17ae 2114int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr)
718e3744 2115{
d62a17ae 2116 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2117
d62a17ae 2118 nbr_nbma = ospf_nbr_nbma_lookup(ospf, addr);
2119 if (nbr_nbma == NULL)
2120 return 0;
718e3744 2121
d62a17ae 2122 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
2123 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
718e3744 2124
d62a17ae 2125 return 1;
718e3744 2126}
2127
d62a17ae 2128void ospf_master_init(struct thread_master *master)
718e3744 2129{
d62a17ae 2130 memset(&ospf_master, 0, sizeof(struct ospf_master));
020709f9 2131
d62a17ae 2132 om = &ospf_master;
2133 om->ospf = list_new();
2134 om->master = master;
020709f9 2135}
b5a8894d
CS
2136
2137/* Link OSPF instance to VRF. */
2138void ospf_vrf_link(struct ospf *ospf, struct vrf *vrf)
2139{
2140 ospf->vrf_id = vrf->vrf_id;
2141 if (vrf->info != (void *)ospf)
2142 vrf->info = (void *)ospf;
2143}
2144
2145/* Unlink OSPF instance from VRF. */
2146void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf)
2147{
2148 if (vrf->info == (void *)ospf)
2149 vrf->info = NULL;
2150 ospf->vrf_id = VRF_UNKNOWN;
2151}
2152
2153/* This is hook function for vrf create called as part of vrf_init */
2154static int ospf_vrf_new(struct vrf *vrf)
2155{
2156 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2157 zlog_debug("%s: VRF Created: %s(%u)", __func__, vrf->name,
2158 vrf->vrf_id);
b5a8894d
CS
2159
2160 return 0;
2161}
2162
2163/* This is hook function for vrf delete call as part of vrf_init */
2164static int ospf_vrf_delete(struct vrf *vrf)
2165{
2166 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2167 zlog_debug("%s: VRF Deletion: %s(%u)", __func__, vrf->name,
2168 vrf->vrf_id);
b5a8894d
CS
2169
2170 return 0;
2171}
2172
de11c1bc 2173static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf, bool set)
3d9f7302
PZ
2174{
2175 int type;
2176 struct list *red_list;
2177
2178 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
2179 red_list = ospf->redist[type];
2180 if (!red_list)
2181 continue;
2182 if (IS_DEBUG_OSPF_EVENT)
2183 zlog_debug(
2184 "%s: setting redist vrf %d bitmap for type %d",
2185 __func__, ospf->vrf_id, type);
de11c1bc
IR
2186 if (set)
2187 vrf_bitmap_set(zclient->redist[AFI_IP][type],
2188 ospf->vrf_id);
2189 else
2190 vrf_bitmap_unset(zclient->redist[AFI_IP][type],
2191 ospf->vrf_id);
3d9f7302 2192 }
b46538c4
IR
2193
2194 red_list = ospf->redist[DEFAULT_ROUTE];
2195 if (red_list) {
2196 if (set)
2197 vrf_bitmap_set(zclient->default_information[AFI_IP],
2198 ospf->vrf_id);
2199 else
2200 vrf_bitmap_unset(zclient->default_information[AFI_IP],
2201 ospf->vrf_id);
2202 }
3d9f7302
PZ
2203}
2204
b5a8894d
CS
2205/* Enable OSPF VRF instance */
2206static int ospf_vrf_enable(struct vrf *vrf)
2207{
2208 struct ospf *ospf = NULL;
7d206035 2209 vrf_id_t old_vrf_id;
3c0eb8fa 2210 int ret = 0;
b5a8894d
CS
2211
2212 if (IS_DEBUG_OSPF_EVENT)
5e81f5dd
DS
2213 zlog_debug("%s: VRF %s id %u enabled", __func__, vrf->name,
2214 vrf->vrf_id);
b5a8894d
CS
2215
2216 ospf = ospf_lookup_by_name(vrf->name);
2217 if (ospf) {
6895b354
PG
2218 if (ospf->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
2219 XFREE(MTYPE_OSPF_TOP, ospf->name);
2220 ospf->name = NULL;
2221 }
b5a8894d
CS
2222 old_vrf_id = ospf->vrf_id;
2223 /* We have instance configured, link to VRF and make it "up". */
2224 ospf_vrf_link(ospf, vrf);
2225 if (IS_DEBUG_OSPF_EVENT)
996c9314
LB
2226 zlog_debug(
2227 "%s: ospf linked to vrf %s vrf_id %u (old id %u)",
5e81f5dd 2228 __func__, vrf->name, ospf->vrf_id, old_vrf_id);
b5a8894d
CS
2229
2230 if (old_vrf_id != ospf->vrf_id) {
de11c1bc 2231 ospf_set_redist_vrf_bitmaps(ospf, true);
3d9f7302 2232
de11c1bc
IR
2233 /* start zebra redist to us for new vrf */
2234 ospf_zebra_vrf_register(ospf);
313d7993 2235
de11c1bc 2236 ret = ospf_sock_init(ospf);
3c0eb8fa
PG
2237 if (ret < 0 || ospf->fd <= 0)
2238 return 0;
996c9314
LB
2239 thread_add_read(master, ospf_read, ospf, ospf->fd,
2240 &ospf->t_read);
b5a8894d
CS
2241 ospf->oi_running = 1;
2242 ospf_router_id_update(ospf);
2243 }
2244 }
2245
2246 return 0;
2247}
2248
2249/* Disable OSPF VRF instance */
2250static int ospf_vrf_disable(struct vrf *vrf)
2251{
2252 struct ospf *ospf = NULL;
2253 vrf_id_t old_vrf_id = VRF_UNKNOWN;
2254
2255 if (vrf->vrf_id == VRF_DEFAULT)
2256 return 0;
2257
2258 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2259 zlog_debug("%s: VRF %s id %d disabled.", __func__, vrf->name,
2260 vrf->vrf_id);
b5a8894d
CS
2261
2262 ospf = ospf_lookup_by_name(vrf->name);
2263 if (ospf) {
2264 old_vrf_id = ospf->vrf_id;
2265
de11c1bc
IR
2266 ospf_zebra_vrf_deregister(ospf);
2267
2268 ospf_set_redist_vrf_bitmaps(ospf, false);
2269
b5a8894d
CS
2270 /* We have instance configured, unlink
2271 * from VRF and make it "down".
2272 */
2273 ospf_vrf_unlink(ospf, vrf);
2274 ospf->oi_running = 0;
2275 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2276 zlog_debug("%s: ospf old_vrf_id %d unlinked", __func__,
2277 old_vrf_id);
b3d6bc6e 2278 thread_cancel(&ospf->t_read);
3c0eb8fa
PG
2279 close(ospf->fd);
2280 ospf->fd = -1;
b5a8894d
CS
2281 }
2282
2283 /* Note: This is a callback, the VRF will be deleted by the caller. */
2284 return 0;
2285}
2286
2287void ospf_vrf_init(void)
2288{
996c9314 2289 vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
b5c056fa 2290 ospf_vrf_delete, ospf_vrf_enable);
b5a8894d
CS
2291}
2292
2293void ospf_vrf_terminate(void)
2294{
2295 vrf_terminate();
2296}
2297
2298const char *ospf_vrf_id_to_name(vrf_id_t vrf_id)
2299{
2300 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
2301
2302 return vrf ? vrf->name : "NIL";
2303}
88b6b28e
DS
2304
2305const char *ospf_get_name(const struct ospf *ospf)
2306{
2307 if (ospf->name)
2308 return ospf->name;
2309 else
2310 return VRF_DEFAULT_NAME;
2311}