]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospfd.c
ospfd: rename the graceful restart header
[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
d62a17ae 423 return new;
718e3744 424}
425
d7c0a89a 426struct ospf *ospf_lookup_instance(unsigned short instance)
7c8ff89e 427{
d62a17ae 428 struct ospf *ospf;
429 struct listnode *node, *nnode;
7c8ff89e 430
d62a17ae 431 if (listcount(om->ospf) == 0)
432 return NULL;
7c8ff89e 433
d62a17ae 434 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
435 if ((ospf->instance == 0 && instance == 0)
436 || (ospf->instance && instance
437 && ospf->instance == instance))
438 return ospf;
7c8ff89e 439
d62a17ae 440 return NULL;
7c8ff89e
DS
441}
442
d62a17ae 443static int ospf_is_ready(struct ospf *ospf)
52c62ab8 444{
d62a17ae 445 /* OSPF must be on and Router-ID must be configured. */
975a328e 446 if (!ospf || ospf->router_id.s_addr == INADDR_ANY)
d62a17ae 447 return 0;
448
449 return 1;
52c62ab8
JAG
450}
451
d62a17ae 452static void ospf_add(struct ospf *ospf)
020709f9 453{
d62a17ae 454 listnode_add(om->ospf, ospf);
020709f9 455}
718e3744 456
d62a17ae 457static void ospf_delete(struct ospf *ospf)
020709f9 458{
d62a17ae 459 listnode_delete(om->ospf, ospf);
020709f9 460}
68980084 461
d7c0a89a 462struct ospf *ospf_lookup_by_inst_name(unsigned short instance, const char *name)
b5a8894d
CS
463{
464 struct ospf *ospf = NULL;
465 struct listnode *node, *nnode;
466
6895b354
PG
467 if (name == NULL || strmatch(name, VRF_DEFAULT_NAME))
468 return ospf_lookup_by_vrf_id(VRF_DEFAULT);
469
b5a8894d 470 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) {
996c9314
LB
471 if ((ospf->instance == instance)
472 && ((ospf->name == NULL && name == NULL)
473 || (ospf->name && name
474 && strcmp(ospf->name, name) == 0)))
b5a8894d
CS
475 return ospf;
476 }
477 return NULL;
478}
479
c3391da1 480static void ospf_init(struct ospf *ospf)
020709f9 481{
c3391da1
IR
482 ospf_opaque_type11_lsa_init(ospf);
483
484 if (ospf->vrf_id != VRF_UNKNOWN)
485 ospf->oi_running = 1;
486
c3391da1
IR
487 ospf_router_id_update(ospf);
488}
489
409f98ab 490struct ospf *ospf_lookup(unsigned short instance, const char *name)
c3391da1
IR
491{
492 struct ospf *ospf;
493
409f98ab
IR
494 if (ospf_instance) {
495 ospf = ospf_lookup_instance(instance);
496 } else {
b5a8894d 497 ospf = ospf_lookup_by_inst_name(instance, name);
d62a17ae 498 }
7c8ff89e 499
d62a17ae 500 return ospf;
7c8ff89e
DS
501}
502
409f98ab 503struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
7c8ff89e 504{
d62a17ae 505 struct ospf *ospf;
7c8ff89e 506
409f98ab
IR
507 ospf = ospf_lookup(instance, name);
508
c572fbfe 509 *created = (ospf == NULL);
d62a17ae 510 if (ospf == NULL) {
409f98ab 511 ospf = ospf_new(instance, name);
d62a17ae 512 ospf_add(ospf);
020709f9 513
c3391da1 514 ospf_init(ospf);
d62a17ae 515 }
68980084 516
d62a17ae 517 return ospf;
718e3744 518}
6b0655a2 519
b5a8894d
CS
520struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id)
521{
522 struct vrf *vrf = NULL;
523
524 vrf = vrf_lookup_by_id(vrf_id);
525 if (!vrf)
526 return NULL;
527 return (vrf->info) ? (struct ospf *)vrf->info : NULL;
b5a8894d
CS
528}
529
cbf32f74
IR
530uint32_t ospf_count_area_params(struct ospf *ospf)
531{
532 struct vrf *vrf;
533 struct interface *ifp;
534 uint32_t count = 0;
535
536 if (ospf->vrf_id != VRF_UNKNOWN) {
537 vrf = vrf_lookup_by_id(ospf->vrf_id);
538
539 FOR_ALL_INTERFACES (vrf, ifp) {
540 count += ospf_if_count_area_params(ifp);
541 }
542 }
543
544 return count;
545}
546
43b8d1d8
CS
547/* It should only be used when processing incoming info update from zebra.
548 * Other situations, it is not sufficient to lookup the ospf instance by
549 * vrf_name only without using the instance number.
550 */
551static struct ospf *ospf_lookup_by_name(const char *vrf_name)
b5a8894d
CS
552{
553 struct ospf *ospf = NULL;
554 struct listnode *node, *nnode;
555
556 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
43b8d1d8 557 if ((ospf->name == NULL && vrf_name == NULL)
996c9314
LB
558 || (ospf->name && vrf_name
559 && strcmp(ospf->name, vrf_name) == 0))
b5a8894d
CS
560 return ospf;
561 return NULL;
562}
563
c9c93d50 564/* Handle the second half of deferred shutdown. This is called either
565 * from the deferred-shutdown timer thread, or directly through
566 * ospf_deferred_shutdown_check.
88d6cf37 567 *
568 * Function is to cleanup G-R state, if required then call ospf_finish_final
569 * to complete shutdown of this ospf instance. Possibly exit if the
570 * whole process is being shutdown and this was the last OSPF instance.
571 */
d62a17ae 572static void ospf_deferred_shutdown_finish(struct ospf *ospf)
573{
574 ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
575 OSPF_TIMER_OFF(ospf->t_deferred_shutdown);
576
577 ospf_finish_final(ospf);
578
579 /* *ospf is now invalid */
88d6cf37 580
d62a17ae 581 /* ospfd being shut-down? If so, was this the last ospf instance? */
582 if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)
583 && (listcount(om->ospf) == 0)) {
584 exit(0);
585 }
586
587 return;
88d6cf37 588}
589
590/* Timer thread for G-R */
d62a17ae 591static int ospf_deferred_shutdown_timer(struct thread *t)
88d6cf37 592{
d62a17ae 593 struct ospf *ospf = THREAD_ARG(t);
594
595 ospf_deferred_shutdown_finish(ospf);
596
597 return 0;
88d6cf37 598}
599
c9c93d50 600/* Check whether deferred-shutdown must be scheduled, otherwise call
88d6cf37 601 * down directly into second-half of instance shutdown.
602 */
d62a17ae 603static void ospf_deferred_shutdown_check(struct ospf *ospf)
604{
605 unsigned long timeout;
606 struct listnode *ln;
607 struct ospf_area *area;
608
609 /* deferred shutdown already running? */
610 if (ospf->t_deferred_shutdown)
611 return;
612
613 /* Should we try push out max-metric LSAs? */
614 if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) {
615 for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) {
616 SET_FLAG(area->stub_router_state,
617 OSPF_AREA_ADMIN_STUB_ROUTED);
618
619 if (!CHECK_FLAG(area->stub_router_state,
620 OSPF_AREA_IS_STUB_ROUTED))
621 ospf_router_lsa_update_area(area);
622 }
623 timeout = ospf->stub_router_shutdown_time;
624 } else {
625 /* No timer needed */
626 ospf_deferred_shutdown_finish(ospf);
627 return;
628 }
629
630 OSPF_TIMER_ON(ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
631 timeout);
632 return;
88d6cf37 633}
6b0655a2 634
88d6cf37 635/* Shut down the entire process */
d62a17ae 636void ospf_terminate(void)
637{
638 struct ospf *ospf;
639 struct listnode *node, *nnode;
640
641 /* shutdown already in progress */
642 if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN))
643 return;
644
645 SET_FLAG(om->options, OSPF_MASTER_SHUTDOWN);
646
41b21bfa 647 /* Skip some steps if OSPF not actually running */
d62a17ae 648 if (listcount(om->ospf) == 0)
41b21bfa 649 goto done;
d62a17ae 650
d62a17ae 651 for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
652 ospf_finish(ospf);
653
51f8588e
RW
654 /* Cleanup GR */
655 ospf_gr_helper_stop();
656
ded42248 657 /* Cleanup route maps */
ded42248
CS
658 route_map_finish();
659
660 /* reverse prefix_list_init */
661 prefix_list_add_hook(NULL);
662 prefix_list_delete_hook(NULL);
663 prefix_list_reset();
664
665 /* Cleanup vrf info */
666 ospf_vrf_terminate();
667
d62a17ae 668 /* Deliberately go back up, hopefully to thread scheduler, as
669 * One or more ospf_finish()'s may have deferred shutdown to a timer
670 * thread
671 */
672 zclient_stop(zclient);
673 zclient_free(zclient);
8879bd22 674
41b21bfa 675done:
8879bd22 676 frr_fini();
d62a17ae 677}
678
679void ospf_finish(struct ospf *ospf)
680{
681 /* let deferred shutdown decide */
682 ospf_deferred_shutdown_check(ospf);
683
684 /* if ospf_deferred_shutdown returns, then ospf_finish_final is
685 * deferred to expiry of G-S timer thread. Return back up, hopefully
686 * to thread scheduler.
687 */
688 return;
88d6cf37 689}
690
691/* Final cleanup of ospf instance */
d62a17ae 692static void ospf_finish_final(struct ospf *ospf)
718e3744 693{
1113a2fb 694 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
d62a17ae 695 struct route_node *rn;
696 struct ospf_nbr_nbma *nbr_nbma;
697 struct ospf_lsa *lsa;
d62a17ae 698 struct ospf_interface *oi;
699 struct ospf_area *area;
700 struct ospf_vl_data *vl_data;
701 struct listnode *node, *nnode;
ca187fd3 702 struct ospf_redist *red;
d62a17ae 703 int i;
7c8ff89e 704
d62a17ae 705 QOBJ_UNREG(ospf);
7c8ff89e 706
d62a17ae 707 ospf_opaque_type11_lsa_term(ospf);
953cde65 708
bcf4475e
OD
709 ospf_opaque_finish();
710
046460a1 711 ospf_flush_self_originated_lsas_now(ospf);
953cde65 712
d62a17ae 713 /* Unregister redistribution */
714 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
715 struct list *red_list;
718e3744 716
d62a17ae 717 red_list = ospf->redist[i];
718 if (!red_list)
719 continue;
718e3744 720
1d753551 721 for (ALL_LIST_ELEMENTS(red_list, node, nnode, red)) {
d62a17ae 722 ospf_redistribute_unset(ospf, i, red->instance);
1d753551
DS
723 ospf_redist_del(ospf, i, red->instance);
724 }
d62a17ae 725 }
ca187fd3
IR
726 red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0);
727 if (red) {
728 ospf_routemap_unset(red);
729 ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
730 ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
731 }
718e3744 732
d62a17ae 733 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
734 ospf_remove_vls_through_area(ospf, area);
718e3744 735
d62a17ae 736 for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
737 ospf_vl_delete(ospf, vl_data);
718e3744 738
6a154c88 739 list_delete(&ospf->vlinks);
718e3744 740
132a782e 741 /* shutdown LDP-Sync */
742 if (ospf->vrf_id == VRF_DEFAULT)
743 ospf_ldp_sync_gbl_exit(ospf, true);
744
d62a17ae 745 /* Reset interface. */
746 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
747 ospf_if_free(oi);
6a154c88 748 list_delete(&ospf->oiflist);
c32eba04 749 ospf->oi_running = 0;
718e3744 750
b5a8894d
CS
751 /* De-Register VRF */
752 ospf_zebra_vrf_deregister(ospf);
753
d62a17ae 754 /* Clear static neighbors */
755 for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
756 if ((nbr_nbma = rn->info)) {
757 OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll);
718e3744 758
d62a17ae 759 if (nbr_nbma->nbr) {
760 nbr_nbma->nbr->nbr_nbma = NULL;
761 nbr_nbma->nbr = NULL;
762 }
763
764 if (nbr_nbma->oi) {
765 listnode_delete(nbr_nbma->oi->nbr_nbma,
766 nbr_nbma);
767 nbr_nbma->oi = NULL;
768 }
769
770 XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
771 }
772
773 route_table_finish(ospf->nbr_nbma);
774
775 /* Clear networks and Areas. */
776 for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) {
777 struct ospf_network *network;
778
779 if ((network = rn->info) != NULL) {
780 ospf_network_free(ospf, network);
781 rn->info = NULL;
782 route_unlock_node(rn);
783 }
91e6a0e5 784 }
7f586094 785 route_table_finish(ospf->networks);
718e3744 786
d62a17ae 787 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
788 listnode_delete(ospf->areas, area);
789 ospf_area_free(area);
790 }
718e3744 791
d62a17ae 792 /* Cancel all timers. */
c32eba04
CS
793 OSPF_TIMER_OFF(ospf->t_read);
794 OSPF_TIMER_OFF(ospf->t_write);
d62a17ae 795 OSPF_TIMER_OFF(ospf->t_spf_calc);
796 OSPF_TIMER_OFF(ospf->t_ase_calc);
797 OSPF_TIMER_OFF(ospf->t_maxage);
798 OSPF_TIMER_OFF(ospf->t_maxage_walker);
799 OSPF_TIMER_OFF(ospf->t_abr_task);
800 OSPF_TIMER_OFF(ospf->t_asbr_check);
1c1c342d 801 OSPF_TIMER_OFF(ospf->t_asbr_nssa_redist_update);
d62a17ae 802 OSPF_TIMER_OFF(ospf->t_distribute_update);
803 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
d62a17ae 804 OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
45a43856 805 OSPF_TIMER_OFF(ospf->t_sr_update);
1febb13d 806 OSPF_TIMER_OFF(ospf->t_default_routemap_timer);
ad7222b7 807 OSPF_TIMER_OFF(ospf->t_external_aggr);
d62a17ae 808
996c9314 809 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
044506e7 810 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
996c9314 811 LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
044506e7 812 ospf_discard_from_db(ospf, ospf->lsdb, lsa);
d62a17ae 813
814 ospf_lsdb_delete_all(ospf->lsdb);
815 ospf_lsdb_free(ospf->lsdb);
816
817 for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) {
d62a17ae 818 if ((lsa = rn->info) != NULL) {
819 ospf_lsa_unlock(&lsa);
820 rn->info = NULL;
69843e81 821 route_unlock_node(rn);
d62a17ae 822 }
d62a17ae 823 }
824 route_table_finish(ospf->maxage_lsa);
825
826 if (ospf->old_table)
827 ospf_route_table_free(ospf->old_table);
828 if (ospf->new_table) {
b5a8894d 829 ospf_route_delete(ospf, ospf->new_table);
d62a17ae 830 ospf_route_table_free(ospf->new_table);
831 }
832 if (ospf->old_rtrs)
833 ospf_rtrs_free(ospf->old_rtrs);
834 if (ospf->new_rtrs)
835 ospf_rtrs_free(ospf->new_rtrs);
836 if (ospf->new_external_route) {
b5a8894d 837 ospf_route_delete(ospf, ospf->new_external_route);
d62a17ae 838 ospf_route_table_free(ospf->new_external_route);
839 }
840 if (ospf->old_external_route) {
b5a8894d 841 ospf_route_delete(ospf, ospf->old_external_route);
d62a17ae 842 ospf_route_table_free(ospf->old_external_route);
843 }
844 if (ospf->external_lsas) {
845 ospf_ase_external_lsas_finish(ospf->external_lsas);
846 }
718e3744 847
d62a17ae 848 for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
849 struct list *ext_list;
d62a17ae 850 struct ospf_external *ext;
851
de1ac5fd 852 ext_list = ospf->external[i];
d62a17ae 853 if (!ext_list)
854 continue;
855
76fdc7f4 856 for (ALL_LIST_ELEMENTS(ext_list, node, nnode, ext)) {
d62a17ae 857 if (ext->external_info)
858 for (rn = route_top(ext->external_info); rn;
859 rn = route_next(rn)) {
860 if (rn->info == NULL)
861 continue;
862
863 XFREE(MTYPE_OSPF_EXTERNAL_INFO,
864 rn->info);
865 rn->info = NULL;
866 route_unlock_node(rn);
867 }
1d753551
DS
868
869 ospf_external_del(ospf, i, ext->instance);
d62a17ae 870 }
871 }
718e3744 872
d62a17ae 873 ospf_distance_reset(ospf);
874 route_table_finish(ospf->distance_table);
7c8ff89e 875
ad7222b7 876 /* Release extrenal Aggregator table */
877 for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) {
878 struct ospf_external_aggr_rt *aggr;
879
880 aggr = rn->info;
881
882 if (aggr) {
883 ospf_external_aggregator_free(aggr);
884 rn->info = NULL;
885 route_unlock_node(rn);
886 }
887 }
888
889 route_table_finish(ospf->rt_aggr_tbl);
890
891
c32eba04
CS
892 list_delete(&ospf->areas);
893 list_delete(&ospf->oi_write_q);
894
06bc3110 895 /* Reset GR helper data structers */
51f8588e 896 ospf_gr_helper_instance_stop(ospf);
06bc3110 897
c32eba04
CS
898 close(ospf->fd);
899 stream_free(ospf->ibuf);
900 ospf->fd = -1;
3d5b9855 901 ospf->max_multipath = MULTIPATH_NUM;
d62a17ae 902 ospf_delete(ospf);
7c8ff89e 903
1113a2fb 904 if (vrf)
905 ospf_vrf_unlink(ospf, vrf);
b5a8894d 906
1113a2fb 907 if (ospf->name)
908 XFREE(MTYPE_OSPF_TOP, ospf->name);
d62a17ae 909 XFREE(MTYPE_OSPF_TOP, ospf);
718e3744 910}
911
6b0655a2 912
718e3744 913/* allocate new OSPF Area object */
7fd0729f 914struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id)
718e3744 915{
d62a17ae 916 struct ospf_area *new;
718e3744 917
d62a17ae 918 /* Allocate new config_network. */
919 new = XCALLOC(MTYPE_OSPF_AREA, sizeof(struct ospf_area));
718e3744 920
d62a17ae 921 new->ospf = ospf;
718e3744 922
d62a17ae 923 new->area_id = area_id;
924 new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD;
718e3744 925
d62a17ae 926 new->external_routing = OSPF_AREA_DEFAULT;
927 new->default_cost = 1;
928 new->auth_type = OSPF_AUTH_NULL;
718e3744 929
d62a17ae 930 /* New LSDB init. */
931 new->lsdb = ospf_lsdb_new();
718e3744 932
d62a17ae 933 /* Self-originated LSAs initialize. */
934 new->router_lsa_self = NULL;
718e3744 935
d62a17ae 936 ospf_opaque_type10_lsa_init(new);
718e3744 937
d62a17ae 938 new->oiflist = list_new();
939 new->ranges = route_table_init();
718e3744 940
d62a17ae 941 if (area_id.s_addr == OSPF_AREA_BACKBONE)
942 ospf->backbone = new;
943
944 return new;
718e3744 945}
946
f91ce319 947void ospf_area_lsdb_discard_delete(struct ospf_area *area)
718e3744 948{
d62a17ae 949 struct route_node *rn;
950 struct ospf_lsa *lsa;
951
996c9314 952 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
044506e7 953 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 954 LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
044506e7 955 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 956 LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
044506e7 957 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 958 LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
044506e7 959 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
68980084 960
996c9314 961 LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
044506e7 962 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 963 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
044506e7 964 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
996c9314 965 LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
044506e7 966 ospf_discard_from_db(area->ospf, area->lsdb, lsa);
718e3744 967
d62a17ae 968 ospf_lsdb_delete_all(area->lsdb);
f91ce319
MR
969}
970
971static void ospf_area_free(struct ospf_area *area)
972{
973 ospf_opaque_type10_lsa_term(area);
974
975 /* Free LSDBs. */
976 ospf_area_lsdb_discard_delete(area);
977
d62a17ae 978 ospf_lsdb_free(area->lsdb);
718e3744 979
d62a17ae 980 ospf_lsa_unlock(&area->router_lsa_self);
718e3744 981
d62a17ae 982 route_table_finish(area->ranges);
6a154c88 983 list_delete(&area->oiflist);
718e3744 984
d62a17ae 985 if (EXPORT_NAME(area))
986 free(EXPORT_NAME(area));
718e3744 987
d62a17ae 988 if (IMPORT_NAME(area))
989 free(IMPORT_NAME(area));
718e3744 990
d62a17ae 991 /* Cancel timer. */
992 OSPF_TIMER_OFF(area->t_stub_router);
993 OSPF_TIMER_OFF(area->t_opaque_lsa_self);
718e3744 994
d62a17ae 995 if (OSPF_IS_AREA_BACKBONE(area))
996 area->ospf->backbone = NULL;
997
998 XFREE(MTYPE_OSPF_AREA, area);
718e3744 999}
1000
d62a17ae 1001void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
718e3744 1002{
d62a17ae 1003 struct ospf_area *area;
718e3744 1004
d62a17ae 1005 area = ospf_area_lookup_by_area_id(ospf, area_id);
1006 if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
19ce7d5e 1007 && !ospf_vl_count(ospf, area)
d62a17ae 1008 && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
1009 && area->external_routing == OSPF_AREA_DEFAULT
1010 && area->no_summary == 0 && area->default_cost == 1
1011 && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL
1012 && area->auth_type == OSPF_AUTH_NULL) {
1013 listnode_delete(ospf->areas, area);
1014 ospf_area_free(area);
1015 }
718e3744 1016}
1017
d62a17ae 1018struct ospf_area *ospf_area_get(struct ospf *ospf, struct in_addr area_id)
718e3744 1019{
d62a17ae 1020 struct ospf_area *area;
1021
1022 area = ospf_area_lookup_by_area_id(ospf, area_id);
1023 if (!area) {
1024 area = ospf_area_new(ospf, area_id);
1025 listnode_add_sort(ospf->areas, area);
1026 ospf_check_abr_status(ospf);
1027 if (ospf->stub_router_admin_set
1028 == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET) {
1029 SET_FLAG(area->stub_router_state,
1030 OSPF_AREA_ADMIN_STUB_ROUTED);
1031 }
1032 }
718e3744 1033
d62a17ae 1034 return area;
718e3744 1035}
1036
d62a17ae 1037struct ospf_area *ospf_area_lookup_by_area_id(struct ospf *ospf,
1038 struct in_addr area_id)
718e3744 1039{
d62a17ae 1040 struct ospf_area *area;
1041 struct listnode *node;
718e3744 1042
d62a17ae 1043 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
1044 if (IPV4_ADDR_SAME(&area->area_id, &area_id))
1045 return area;
718e3744 1046
d62a17ae 1047 return NULL;
718e3744 1048}
1049
d62a17ae 1050void ospf_area_add_if(struct ospf_area *area, struct ospf_interface *oi)
718e3744 1051{
d62a17ae 1052 listnode_add(area->oiflist, oi);
718e3744 1053}
1054
d62a17ae 1055void ospf_area_del_if(struct ospf_area *area, struct ospf_interface *oi)
718e3744 1056{
d62a17ae 1057 listnode_delete(area->oiflist, oi);
718e3744 1058}
1059
52c62ab8 1060
7fd0729f
G
1061struct ospf_interface *add_ospf_interface(struct connected *co,
1062 struct ospf_area *area)
953cde65 1063{
d62a17ae 1064 struct ospf_interface *oi;
953cde65 1065
d62a17ae 1066 oi = ospf_if_new(area->ospf, co->ifp, co->address);
1067 oi->connected = co;
953cde65 1068
d62a17ae 1069 oi->area = area;
953cde65 1070
d62a17ae 1071 oi->params = ospf_lookup_if_params(co->ifp, oi->address->u.prefix4);
1072 oi->output_cost = ospf_if_get_output_cost(oi);
953cde65 1073
d62a17ae 1074 /* Relate ospf interface to ospf instance. */
1075 oi->ospf = area->ospf;
953cde65 1076
d62a17ae 1077 /* update network type as interface flag */
1078 /* If network type is specified previously,
1079 skip network type setting. */
1080 oi->type = IF_DEF_PARAMS(co->ifp)->type;
bc97889b 1081 oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
953cde65 1082
d62a17ae 1083 /* Add pseudo neighbor. */
1084 ospf_nbr_self_reset(oi, oi->ospf->router_id);
953cde65 1085
d62a17ae 1086 ospf_area_add_if(oi->area, oi);
52c62ab8 1087
132a782e 1088 /* if LDP-IGP Sync is configured globally inherit config */
1089 ospf_ldp_sync_if_init(oi);
1090
d62a17ae 1091 /*
1092 * if router_id is not configured, dont bring up
1093 * interfaces.
1094 * ospf_router_id_update() will call ospf_if_update
1095 * whenever r-id is configured instead.
1096 */
975a328e
DA
1097 if ((area->ospf->router_id.s_addr != INADDR_ANY)
1098 && if_is_operative(co->ifp))
d62a17ae 1099 ospf_if_up(oi);
7fd0729f
G
1100
1101 return oi;
953cde65
JT
1102}
1103
1104static void update_redistributed(struct ospf *ospf, int add_to_ospf)
1105{
d62a17ae 1106 struct route_node *rn;
1107 struct external_info *ei;
1108 struct ospf_external *ext;
1109
de1ac5fd
CS
1110 if (ospf_is_type_redistributed(ospf, ZEBRA_ROUTE_CONNECT, 0)) {
1111 ext = ospf_external_lookup(ospf, ZEBRA_ROUTE_CONNECT, 0);
1112 if ((ext) && EXTERNAL_INFO(ext)) {
d62a17ae 1113 for (rn = route_top(EXTERNAL_INFO(ext)); rn;
1114 rn = route_next(rn)) {
de1ac5fd
CS
1115 ei = rn->info;
1116 if (ei == NULL)
1117 continue;
1118
1119 if (add_to_ospf) {
996c9314
LB
1120 if (ospf_external_info_find_lsa(ospf,
1121 &ei->p))
de1ac5fd
CS
1122 if (!ospf_distribute_check_connected(
1123 ospf, ei))
1124 ospf_external_lsa_flush(
996c9314 1125 ospf, ei->type,
de1ac5fd
CS
1126 &ei->p,
1127 ei->ifindex /*, ei->nexthop */);
1128 } else {
1129 if (!ospf_external_info_find_lsa(
1130 ospf, &ei->p))
1131 if (ospf_distribute_check_connected(
1132 ospf, ei))
1133 ospf_external_lsa_originate(
996c9314 1134 ospf, ei);
d62a17ae 1135 }
1136 }
1137 }
de1ac5fd 1138 }
953cde65
JT
1139}
1140
718e3744 1141/* Config network statement related functions. */
d62a17ae 1142static struct ospf_network *ospf_network_new(struct in_addr area_id)
718e3744 1143{
d62a17ae 1144 struct ospf_network *new;
1145 new = XCALLOC(MTYPE_OSPF_NETWORK, sizeof(struct ospf_network));
718e3744 1146
d62a17ae 1147 new->area_id = area_id;
1148 new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD;
1149
1150 return new;
718e3744 1151}
1152
d62a17ae 1153static void ospf_network_free(struct ospf *ospf, struct ospf_network *network)
718e3744 1154{
d62a17ae 1155 ospf_area_check_free(ospf, network->area_id);
1156 ospf_schedule_abr_task(ospf);
1157 XFREE(MTYPE_OSPF_NETWORK, network);
718e3744 1158}
1159
d62a17ae 1160int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p,
1161 struct in_addr area_id, int df)
718e3744 1162{
d62a17ae 1163 struct ospf_network *network;
1164 struct ospf_area *area;
1165 struct route_node *rn;
718e3744 1166
d62a17ae 1167 rn = route_node_get(ospf->networks, (struct prefix *)p);
1168 if (rn->info) {
2b0a905a 1169 network = rn->info;
d62a17ae 1170 route_unlock_node(rn);
2b0a905a
DW
1171
1172 if (IPV4_ADDR_SAME(&area_id, &network->area_id)) {
1173 return 1;
1174 } else {
1175 /* There is already same network statement. */
1176 return 0;
1177 }
d62a17ae 1178 }
718e3744 1179
d62a17ae 1180 rn->info = network = ospf_network_new(area_id);
1181 network->area_id_fmt = df;
1182 area = ospf_area_get(ospf, area_id);
1183 ospf_area_display_format_set(ospf, area, df);
718e3744 1184
d62a17ae 1185 /* Run network config now. */
1186 ospf_network_run((struct prefix *)p, area);
718e3744 1187
d62a17ae 1188 /* Update connected redistribute. */
1189 update_redistributed(ospf, 1); /* interfaces possibly added */
718e3744 1190
d62a17ae 1191 ospf_area_check_free(ospf, area_id);
718e3744 1192
d62a17ae 1193 return 1;
718e3744 1194}
1195
d62a17ae 1196int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p,
1197 struct in_addr area_id)
718e3744 1198{
d62a17ae 1199 struct route_node *rn;
1200 struct ospf_network *network;
1201 struct listnode *node, *nnode;
1202 struct ospf_interface *oi;
718e3744 1203
d62a17ae 1204 rn = route_node_lookup(ospf->networks, (struct prefix *)p);
1205 if (rn == NULL)
1206 return 0;
718e3744 1207
d62a17ae 1208 network = rn->info;
1209 route_unlock_node(rn);
1210 if (!IPV4_ADDR_SAME(&area_id, &network->area_id))
1211 return 0;
718e3744 1212
d62a17ae 1213 ospf_network_free(ospf, rn->info);
1214 rn->info = NULL;
1215 route_unlock_node(rn); /* initial reference */
718e3744 1216
30c0daa4 1217 /* Find interfaces that are not configured already. */
d62a17ae 1218 for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
30c0daa4 1219
996c9314
LB
1220 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
1221 continue;
30c0daa4 1222
996c9314 1223 ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
d62a17ae 1224 }
953cde65 1225
d62a17ae 1226 /* Update connected redistribute. */
1227 update_redistributed(ospf, 0); /* interfaces possibly removed */
1228 ospf_area_check_free(ospf, area_id);
1229
1230 return 1;
953cde65
JT
1231}
1232
52c62ab8
JAG
1233/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
1234 * there might not be any 'router ospf' config.
1235 *
1236 * Otherwise, doesn't do anything different to ospf_if_update for now
1237 */
b5a8894d 1238void ospf_interface_area_set(struct ospf *ospf, struct interface *ifp)
953cde65 1239{
b5a8894d
CS
1240 if (!ospf)
1241 return;
d62a17ae 1242
1243 ospf_if_update(ospf, ifp);
1244 /* if_update does a update_redistributed */
1245
1246 return;
953cde65
JT
1247}
1248
b5a8894d 1249void ospf_interface_area_unset(struct ospf *ospf, struct interface *ifp)
953cde65 1250{
d62a17ae 1251 struct route_node *rn_oi;
953cde65 1252
d62a17ae 1253 if (!ospf)
1254 return; /* Ospf not ready yet */
953cde65 1255
d62a17ae 1256 /* Find interfaces that may need to be removed. */
1257 for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi;
1258 rn_oi = route_next(rn_oi)) {
b5a8894d 1259 struct ospf_interface *oi = NULL;
d62a17ae 1260
1261 if ((oi = rn_oi->info) == NULL)
1262 continue;
1263
1264 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
1265 continue;
1266
1267 ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
1268 }
953cde65 1269
d62a17ae 1270 /* Update connected redistribute. */
1271 update_redistributed(ospf, 0); /* interfaces possibly removed */
718e3744 1272}
1273
570f7598 1274/* Check whether interface matches given network
1275 * returns: 1, true. 0, false
1276 */
d62a17ae 1277static int ospf_network_match_iface(const struct connected *co,
1278 const struct prefix *net)
570f7598 1279{
d62a17ae 1280 /* new approach: more elegant and conceptually clean */
1281 return prefix_match_network_statement(net, CONNECTED_PREFIX(co));
570f7598 1282}
1283
d62a17ae 1284static void ospf_update_interface_area(struct connected *co,
1285 struct ospf_area *area)
52c62ab8 1286{
d62a17ae 1287 struct ospf_interface *oi = ospf_if_table_lookup(co->ifp, co->address);
1288
1289 /* nothing to be done case */
1290 if (oi && oi->area == area) {
1291 return;
1292 }
1293
1294 if (oi)
1295 ospf_if_free(oi);
1296
1297 add_ospf_interface(co, area);
52c62ab8
JAG
1298}
1299
1300/* Run OSPF for the given subnet, taking into account the following
1301 * possible sources of area configuration, in the given order of preference:
1302 *
1303 * - Whether there is interface+address specific area configuration
1304 * - Whether there is a default area for the interface
1305 * - Whether there is an area given as a parameter.
1306 * - If no specific network prefix/area is supplied, whether there's
1307 * a matching network configured.
1308 */
d62a17ae 1309static void ospf_network_run_subnet(struct ospf *ospf, struct connected *co,
1310 struct prefix *p,
1311 struct ospf_area *given_area)
1312{
1313 struct ospf_interface *oi;
1314 struct ospf_if_params *params;
1315 struct ospf_area *area = NULL;
1316 struct route_node *rn;
1317 int configed = 0;
1318
1319 if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
1320 return;
1321
1322 if (co->address->family != AF_INET)
1323 return;
1324
1325 /* Try determine the appropriate area for this interface + address
1326 * Start by checking interface config
1327 */
1328 params = ospf_lookup_if_params(co->ifp, co->address->u.prefix4);
1329 if (params && OSPF_IF_PARAM_CONFIGURED(params, if_area))
1330 area = ospf_area_get(ospf, params->if_area);
1331 else {
1332 params = IF_DEF_PARAMS(co->ifp);
1333 if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
1334 area = ospf_area_get(ospf, params->if_area);
1335 }
52c62ab8 1336
d62a17ae 1337 /* If we've found an interface and/or addr specific area, then we're
1338 * done
1339 */
1340 if (area) {
1341 ospf_update_interface_area(co, area);
1342 return;
1343 }
718e3744 1344
d62a17ae 1345 /* Otherwise, only remaining possibility is a matching network statement
1346 */
1347 if (p) {
1348 assert(given_area != NULL);
1349
1350 /* Which either was supplied as a parameter.. (e.g. cause a new
1351 * network/area was just added)..
1352 */
1353 if (p->family == co->address->family
1354 && ospf_network_match_iface(co, p))
1355 ospf_update_interface_area(co, given_area);
1356
1357 return;
1358 }
1359
1360 /* Else we have to search the existing network/area config to see
1361 * if any match..
1362 */
1363 for (rn = route_top(ospf->networks); rn; rn = route_next(rn))
1364 if (rn->info != NULL && ospf_network_match_iface(co, &rn->p)) {
1365 struct ospf_network *network =
1366 (struct ospf_network *)rn->info;
1367 area = ospf_area_get(ospf, network->area_id);
1368 ospf_update_interface_area(co, area);
1369 configed = 1;
1370 }
1371
1372 /* If the subnet isn't in any area, deconfigure */
1373 if (!configed && (oi = ospf_if_table_lookup(co->ifp, co->address)))
1374 ospf_if_free(oi);
718e3744 1375}
1376
d62a17ae 1377static void ospf_network_run_interface(struct ospf *ospf, struct interface *ifp,
1378 struct prefix *p,
1379 struct ospf_area *given_area)
718e3744 1380{
d62a17ae 1381 struct listnode *cnode;
1382 struct connected *co;
1383
1384 if (memcmp(ifp->name, "VLINK", 5) == 0)
1385 return;
718e3744 1386
d62a17ae 1387 /* Network prefix without area is nonsensical */
1388 if (p)
1389 assert(given_area != NULL);
1390
1391 /* if interface prefix is match specified prefix,
1392 then create socket and join multicast group. */
1393 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co))
1394 ospf_network_run_subnet(ospf, co, p, given_area);
718e3744 1395}
1396
d62a17ae 1397static void ospf_network_run(struct prefix *p, struct ospf_area *area)
718e3744 1398{
f4e14fdb 1399 struct vrf *vrf = vrf_lookup_by_id(area->ospf->vrf_id);
d62a17ae 1400 struct interface *ifp;
d62a17ae 1401
1402 /* Schedule Router ID Update. */
975a328e 1403 if (area->ospf->router_id.s_addr == INADDR_ANY)
d62a17ae 1404 ospf_router_id_update(area->ospf);
718e3744 1405
d62a17ae 1406 /* Get target interface. */
451fda4f 1407 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 1408 ospf_network_run_interface(area->ospf, ifp, p, area);
718e3744 1409}
1410
d62a17ae 1411void ospf_ls_upd_queue_empty(struct ospf_interface *oi)
1412{
1413 struct route_node *rn;
1414 struct listnode *node, *nnode;
1415 struct list *lst;
1416 struct ospf_lsa *lsa;
1417
1418 /* empty ls update queue */
1419 for (rn = route_top(oi->ls_upd_queue); rn; rn = route_next(rn))
1420 if ((lst = (struct list *)rn->info)) {
1421 for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa))
1422 ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */
6a154c88 1423 list_delete(&lst);
d62a17ae 1424 rn->info = NULL;
1425 }
1426
1427 /* remove update event */
b3d6bc6e 1428 thread_cancel(&oi->t_ls_upd_event);
d62a17ae 1429}
6b0655a2 1430
d62a17ae 1431void ospf_if_update(struct ospf *ospf, struct interface *ifp)
718e3744 1432{
43b8d1d8 1433
d62a17ae 1434 if (!ospf)
43b8d1d8 1435 return;
b5a8894d
CS
1436
1437 if (IS_DEBUG_OSPF_EVENT)
996c9314 1438 zlog_debug(
96b663a3 1439 "%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %pI4",
15569c58 1440 __func__, ifp->name, ifp->vrf_id,
996c9314 1441 ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id,
96b663a3 1442 &ospf->router_id);
d62a17ae 1443
1444 /* OSPF must be ready. */
1445 if (!ospf_is_ready(ospf))
1446 return;
1447
1448 ospf_network_run_interface(ospf, ifp, NULL, NULL);
1449
1450 /* Update connected redistribute. */
1451 update_redistributed(ospf, 1);
ef7bd2a3 1452
d62a17ae 1453}
718e3744 1454
d62a17ae 1455void ospf_remove_vls_through_area(struct ospf *ospf, struct ospf_area *area)
718e3744 1456{
d62a17ae 1457 struct listnode *node, *nnode;
1458 struct ospf_vl_data *vl_data;
718e3744 1459
d62a17ae 1460 for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
1461 if (IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
1462 ospf_vl_delete(ospf, vl_data);
1463}
718e3744 1464
718e3744 1465
d62a17ae 1466static const struct message ospf_area_type_msg[] = {
1467 {OSPF_AREA_DEFAULT, "Default"},
1468 {OSPF_AREA_STUB, "Stub"},
1469 {OSPF_AREA_NSSA, "NSSA"},
1470 {0}};
718e3744 1471
d62a17ae 1472static void ospf_area_type_set(struct ospf_area *area, int type)
1473{
1474 struct listnode *node;
1475 struct ospf_interface *oi;
1476
1477 if (area->external_routing == type) {
1478 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
1479 zlog_debug("Area[%pI4]: Types are the same, ignored.",
1480 &area->area_id);
d62a17ae 1481 return;
1482 }
718e3744 1483
d62a17ae 1484 area->external_routing = type;
1485
1486 if (IS_DEBUG_OSPF_EVENT)
96b663a3
MS
1487 zlog_debug("Area[%pI4]: Configured as %s",
1488 &area->area_id,
d62a17ae 1489 lookup_msg(ospf_area_type_msg, type, NULL));
1490
1491 switch (area->external_routing) {
1492 case OSPF_AREA_DEFAULT:
1493 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1494 if (oi->nbr_self != NULL) {
1495 UNSET_FLAG(oi->nbr_self->options,
1496 OSPF_OPTION_NP);
1497 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E);
1498 }
1499 break;
1500 case OSPF_AREA_STUB:
1501 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1502 if (oi->nbr_self != NULL) {
1503 if (IS_DEBUG_OSPF_EVENT)
1504 zlog_debug(
1505 "setting options on %s accordingly",
1506 IF_NAME(oi));
1507 UNSET_FLAG(oi->nbr_self->options,
1508 OSPF_OPTION_NP);
1509 UNSET_FLAG(oi->nbr_self->options,
1510 OSPF_OPTION_E);
1511 if (IS_DEBUG_OSPF_EVENT)
1512 zlog_debug("options set on %s: %x",
1513 IF_NAME(oi), OPTIONS(oi));
1514 }
1515 break;
1516 case OSPF_AREA_NSSA:
1517 for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi))
1518 if (oi->nbr_self != NULL) {
1519 zlog_debug(
1520 "setting nssa options on %s accordingly",
1521 IF_NAME(oi));
1522 UNSET_FLAG(oi->nbr_self->options,
1523 OSPF_OPTION_E);
1524 SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP);
1525 zlog_debug("options set on %s: %x", IF_NAME(oi),
1526 OPTIONS(oi));
1527 }
1528 break;
1529 default:
1530 break;
1531 }
1532
1533 ospf_router_lsa_update_area(area);
1534 ospf_schedule_abr_task(area->ospf);
718e3744 1535}
1536
d62a17ae 1537int ospf_area_shortcut_set(struct ospf *ospf, struct ospf_area *area, int mode)
718e3744 1538{
d62a17ae 1539 if (area->shortcut_configured == mode)
1540 return 0;
718e3744 1541
d62a17ae 1542 area->shortcut_configured = mode;
1543 ospf_router_lsa_update_area(area);
1544 ospf_schedule_abr_task(ospf);
718e3744 1545
d62a17ae 1546 ospf_area_check_free(ospf, area->area_id);
718e3744 1547
d62a17ae 1548 return 1;
718e3744 1549}
1550
d62a17ae 1551int ospf_area_shortcut_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1552{
d62a17ae 1553 area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
1554 ospf_router_lsa_update_area(area);
1555 ospf_area_check_free(ospf, area->area_id);
1556 ospf_schedule_abr_task(ospf);
718e3744 1557
d62a17ae 1558 return 1;
718e3744 1559}
1560
d62a17ae 1561static int ospf_area_vlink_count(struct ospf *ospf, struct ospf_area *area)
718e3744 1562{
d62a17ae 1563 struct ospf_vl_data *vl;
1564 struct listnode *node;
1565 int count = 0;
718e3744 1566
d62a17ae 1567 for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl))
1568 if (IPV4_ADDR_SAME(&vl->vl_area_id, &area->area_id))
1569 count++;
718e3744 1570
d62a17ae 1571 return count;
718e3744 1572}
1573
d62a17ae 1574int ospf_area_display_format_set(struct ospf *ospf, struct ospf_area *area,
1575 int df)
86573dcb 1576{
d62a17ae 1577 area->area_id_fmt = df;
86573dcb 1578
d62a17ae 1579 return 1;
86573dcb
QY
1580}
1581
d62a17ae 1582int ospf_area_stub_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1583{
d62a17ae 1584 struct ospf_area *area;
718e3744 1585
d62a17ae 1586 area = ospf_area_get(ospf, area_id);
1587 if (ospf_area_vlink_count(ospf, area))
1588 return 0;
718e3744 1589
d62a17ae 1590 if (area->external_routing != OSPF_AREA_STUB)
1591 ospf_area_type_set(area, OSPF_AREA_STUB);
718e3744 1592
d62a17ae 1593 return 1;
718e3744 1594}
1595
d62a17ae 1596int ospf_area_stub_unset(struct ospf *ospf, struct in_addr area_id)
718e3744 1597{
d62a17ae 1598 struct ospf_area *area;
718e3744 1599
d62a17ae 1600 area = ospf_area_lookup_by_area_id(ospf, area_id);
1601 if (area == NULL)
1602 return 1;
718e3744 1603
d62a17ae 1604 if (area->external_routing == OSPF_AREA_STUB)
1605 ospf_area_type_set(area, OSPF_AREA_DEFAULT);
718e3744 1606
d62a17ae 1607 ospf_area_check_free(ospf, area_id);
718e3744 1608
d62a17ae 1609 return 1;
718e3744 1610}
1611
d62a17ae 1612int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1613{
d62a17ae 1614 struct ospf_area *area;
718e3744 1615
d62a17ae 1616 area = ospf_area_get(ospf, area_id);
1617 area->no_summary = 1;
718e3744 1618
d62a17ae 1619 return 1;
718e3744 1620}
1621
d62a17ae 1622int ospf_area_no_summary_unset(struct ospf *ospf, struct in_addr area_id)
718e3744 1623{
d62a17ae 1624 struct ospf_area *area;
718e3744 1625
d62a17ae 1626 area = ospf_area_lookup_by_area_id(ospf, area_id);
1627 if (area == NULL)
1628 return 0;
718e3744 1629
d62a17ae 1630 area->no_summary = 0;
1631 ospf_area_check_free(ospf, area_id);
718e3744 1632
d62a17ae 1633 return 1;
718e3744 1634}
1635
7ef56a73 1636int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id)
718e3744 1637{
d62a17ae 1638 struct ospf_area *area;
718e3744 1639
d62a17ae 1640 area = ospf_area_get(ospf, area_id);
1641 if (ospf_area_vlink_count(ospf, area))
1642 return 0;
718e3744 1643
d62a17ae 1644 if (area->external_routing != OSPF_AREA_NSSA) {
1645 ospf_area_type_set(area, OSPF_AREA_NSSA);
1646 ospf->anyNSSA++;
7ef56a73 1647 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
d62a17ae 1648 }
718e3744 1649
7ef56a73 1650 ospf_area_no_summary_set(ospf, area_id);
084c7844 1651
d62a17ae 1652 return 1;
718e3744 1653}
1654
7ef56a73
CS
1655int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
1656{
1657 struct ospf_area *area;
1658
1659 area = ospf_area_get(ospf, area_id);
1660 if (ospf_area_vlink_count(ospf, area))
1661 return 0;
1662
1663 if (area->external_routing != OSPF_AREA_NSSA) {
1664 ospf_area_type_set(area, OSPF_AREA_NSSA);
1665 ospf->anyNSSA++;
1666
1667 /* set NSSA area defaults */
1668 area->no_summary = 0;
c317eddb 1669 area->suppress_fa = 0;
7ef56a73
CS
1670 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
1671 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
1672 area->NSSATranslatorStabilityInterval =
1673 OSPF_NSSA_TRANS_STABLE_DEFAULT;
1674 }
1675 return 1;
1676}
1677
1678int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
718e3744 1679{
d62a17ae 1680 struct ospf_area *area;
718e3744 1681
d62a17ae 1682 area = ospf_area_lookup_by_area_id(ospf, area_id);
1683 if (area == NULL)
1684 return 0;
718e3744 1685
7ef56a73
CS
1686 /* argc < 5 -> 'no area x nssa' */
1687 if (argc < 5 && area->external_routing == OSPF_AREA_NSSA) {
d62a17ae 1688 ospf->anyNSSA--;
7ef56a73
CS
1689 /* set NSSA area defaults */
1690 area->no_summary = 0;
c317eddb 1691 area->suppress_fa = 0;
7ef56a73
CS
1692 area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
1693 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
1694 area->NSSATranslatorStabilityInterval =
1695 OSPF_NSSA_TRANS_STABLE_DEFAULT;
d62a17ae 1696 ospf_area_type_set(area, OSPF_AREA_DEFAULT);
7ef56a73 1697 } else {
a987fe6b 1698 ospf_area_nssa_translator_role_set(ospf, area_id,
1699 OSPF_NSSA_ROLE_CANDIDATE);
d62a17ae 1700 }
718e3744 1701
d62a17ae 1702 ospf_area_check_free(ospf, area_id);
718e3744 1703
d62a17ae 1704 return 1;
718e3744 1705}
1706
c317eddb 1707int ospf_area_nssa_suppress_fa_set(struct ospf *ospf, struct in_addr area_id)
1708{
1709 struct ospf_area *area;
1710
1711 area = ospf_area_lookup_by_area_id(ospf, area_id);
1712 if (area == NULL)
1713 return 0;
1714
1715 area->suppress_fa = 1;
1716
1717 return 1;
1718}
1719
1720int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf, struct in_addr area_id)
1721{
1722 struct ospf_area *area;
1723
1724 area = ospf_area_lookup_by_area_id(ospf, area_id);
1725 if (area == NULL)
1726 return 0;
1727
1728 area->suppress_fa = 0;
1729
1730 return 1;
1731}
1732
d62a17ae 1733int ospf_area_nssa_translator_role_set(struct ospf *ospf,
1734 struct in_addr area_id, int role)
718e3744 1735{
d62a17ae 1736 struct ospf_area *area;
718e3744 1737
d62a17ae 1738 area = ospf_area_lookup_by_area_id(ospf, area_id);
1739 if (area == NULL)
1740 return 0;
718e3744 1741
a987fe6b 1742 if (role != area->NSSATranslatorRole) {
1743 if ((area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)
1744 || (role == OSPF_NSSA_ROLE_ALWAYS)) {
1745 /* RFC 3101 3.1
1746 * if new role is OSPF_NSSA_ROLE_ALWAYS we need to set
1747 * Nt bit, if the role was OSPF_NSSA_ROLE_ALWAYS we need
1748 * to clear Nt bit
1749 */
1750 area->NSSATranslatorRole = role;
1751 ospf_router_lsa_update_area(area);
1752 } else
1753 area->NSSATranslatorRole = role;
1754 }
718e3744 1755
d62a17ae 1756 return 1;
718e3744 1757}
1758
d62a17ae 1759int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area,
1760 const char *list_name)
718e3744 1761{
d62a17ae 1762 struct access_list *list;
1763 list = access_list_lookup(AFI_IP, list_name);
718e3744 1764
d62a17ae 1765 EXPORT_LIST(area) = list;
718e3744 1766
d62a17ae 1767 if (EXPORT_NAME(area))
1768 free(EXPORT_NAME(area));
718e3744 1769
d62a17ae 1770 EXPORT_NAME(area) = strdup(list_name);
1771 ospf_schedule_abr_task(ospf);
718e3744 1772
d62a17ae 1773 return 1;
718e3744 1774}
1775
d62a17ae 1776int ospf_area_export_list_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1777{
1778
d62a17ae 1779 EXPORT_LIST(area) = 0;
718e3744 1780
d62a17ae 1781 if (EXPORT_NAME(area))
1782 free(EXPORT_NAME(area));
718e3744 1783
d62a17ae 1784 EXPORT_NAME(area) = NULL;
718e3744 1785
d62a17ae 1786 ospf_area_check_free(ospf, area->area_id);
718e3744 1787
d62a17ae 1788 ospf_schedule_abr_task(ospf);
1789
1790 return 1;
718e3744 1791}
1792
d62a17ae 1793int ospf_area_import_list_set(struct ospf *ospf, struct ospf_area *area,
1794 const char *name)
718e3744 1795{
d62a17ae 1796 struct access_list *list;
1797 list = access_list_lookup(AFI_IP, name);
718e3744 1798
d62a17ae 1799 IMPORT_LIST(area) = list;
718e3744 1800
d62a17ae 1801 if (IMPORT_NAME(area))
1802 free(IMPORT_NAME(area));
718e3744 1803
d62a17ae 1804 IMPORT_NAME(area) = strdup(name);
1805 ospf_schedule_abr_task(ospf);
718e3744 1806
d62a17ae 1807 return 1;
718e3744 1808}
1809
d62a17ae 1810int ospf_area_import_list_unset(struct ospf *ospf, struct ospf_area *area)
718e3744 1811{
d62a17ae 1812 IMPORT_LIST(area) = 0;
718e3744 1813
d62a17ae 1814 if (IMPORT_NAME(area))
1815 free(IMPORT_NAME(area));
718e3744 1816
d62a17ae 1817 IMPORT_NAME(area) = NULL;
1818 ospf_area_check_free(ospf, area->area_id);
718e3744 1819
d62a17ae 1820 ospf_schedule_abr_task(ospf);
718e3744 1821
d62a17ae 1822 return 1;
718e3744 1823}
1824
d62a17ae 1825int ospf_timers_refresh_set(struct ospf *ospf, int interval)
718e3744 1826{
d62a17ae 1827 int time_left;
718e3744 1828
d62a17ae 1829 if (ospf->lsa_refresh_interval == interval)
1830 return 1;
718e3744 1831
d62a17ae 1832 time_left = ospf->lsa_refresh_interval
1833 - (monotime(NULL) - ospf->lsa_refresher_started);
718e3744 1834
d62a17ae 1835 if (time_left > interval) {
1836 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
1837 thread_add_timer(master, ospf_lsa_refresh_walker, ospf,
1838 interval, &ospf->t_lsa_refresher);
1839 }
1840 ospf->lsa_refresh_interval = interval;
1841
1842 return 1;
718e3744 1843}
1844
d62a17ae 1845int ospf_timers_refresh_unset(struct ospf *ospf)
718e3744 1846{
d62a17ae 1847 int time_left;
718e3744 1848
d62a17ae 1849 time_left = ospf->lsa_refresh_interval
1850 - (monotime(NULL) - ospf->lsa_refresher_started);
718e3744 1851
d62a17ae 1852 if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) {
1853 OSPF_TIMER_OFF(ospf->t_lsa_refresher);
1854 ospf->t_lsa_refresher = NULL;
1855 thread_add_timer(master, ospf_lsa_refresh_walker, ospf,
1856 OSPF_LSA_REFRESH_INTERVAL_DEFAULT,
1857 &ospf->t_lsa_refresher);
1858 }
718e3744 1859
d62a17ae 1860 ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
718e3744 1861
d62a17ae 1862 return 1;
718e3744 1863}
1864
6b0655a2 1865
d62a17ae 1866static struct ospf_nbr_nbma *ospf_nbr_nbma_new(void)
718e3744 1867{
d62a17ae 1868 struct ospf_nbr_nbma *nbr_nbma;
718e3744 1869
d62a17ae 1870 nbr_nbma = XCALLOC(MTYPE_OSPF_NEIGHBOR_STATIC,
1871 sizeof(struct ospf_nbr_nbma));
718e3744 1872
d62a17ae 1873 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
1874 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
718e3744 1875
d62a17ae 1876 return nbr_nbma;
718e3744 1877}
1878
d62a17ae 1879static void ospf_nbr_nbma_free(struct ospf_nbr_nbma *nbr_nbma)
718e3744 1880{
d62a17ae 1881 XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
718e3744 1882}
1883
d62a17ae 1884static void ospf_nbr_nbma_delete(struct ospf *ospf,
1885 struct ospf_nbr_nbma *nbr_nbma)
718e3744 1886{
d62a17ae 1887 struct route_node *rn;
1888 struct prefix_ipv4 p;
718e3744 1889
d62a17ae 1890 p.family = AF_INET;
1891 p.prefix = nbr_nbma->addr;
1892 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 1893
d62a17ae 1894 rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p);
1895 if (rn) {
1896 ospf_nbr_nbma_free(rn->info);
1897 rn->info = NULL;
1898 route_unlock_node(rn);
1899 route_unlock_node(rn);
1900 }
718e3744 1901}
1902
d62a17ae 1903static void ospf_nbr_nbma_down(struct ospf_nbr_nbma *nbr_nbma)
718e3744 1904{
d62a17ae 1905 OSPF_TIMER_OFF(nbr_nbma->t_poll);
718e3744 1906
d62a17ae 1907 if (nbr_nbma->nbr) {
1908 nbr_nbma->nbr->nbr_nbma = NULL;
1909 OSPF_NSM_EVENT_EXECUTE(nbr_nbma->nbr, NSM_KillNbr);
1910 }
718e3744 1911
d62a17ae 1912 if (nbr_nbma->oi)
1913 listnode_delete(nbr_nbma->oi->nbr_nbma, nbr_nbma);
718e3744 1914}
1915
d62a17ae 1916static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma,
1917 struct ospf_interface *oi)
718e3744 1918{
d62a17ae 1919 struct ospf_neighbor *nbr;
1920 struct route_node *rn;
1921 struct prefix p;
718e3744 1922
d62a17ae 1923 if (oi->type != OSPF_IFTYPE_NBMA)
1924 return;
718e3744 1925
d62a17ae 1926 if (nbr_nbma->nbr != NULL)
1927 return;
718e3744 1928
d62a17ae 1929 if (IPV4_ADDR_SAME(&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
1930 return;
718e3744 1931
d62a17ae 1932 nbr_nbma->oi = oi;
1933 listnode_add(oi->nbr_nbma, nbr_nbma);
718e3744 1934
d62a17ae 1935 /* Get neighbor information from table. */
1936 p.family = AF_INET;
1937 p.prefixlen = IPV4_MAX_BITLEN;
1938 p.u.prefix4 = nbr_nbma->addr;
718e3744 1939
c4efd0f4 1940 rn = route_node_get(oi->nbrs, &p);
d62a17ae 1941 if (rn->info) {
1942 nbr = rn->info;
1943 nbr->nbr_nbma = nbr_nbma;
1944 nbr_nbma->nbr = nbr;
718e3744 1945
d62a17ae 1946 route_unlock_node(rn);
1947 } else {
1948 nbr = rn->info = ospf_nbr_new(oi);
1949 nbr->state = NSM_Down;
1950 nbr->src = nbr_nbma->addr;
1951 nbr->nbr_nbma = nbr_nbma;
1952 nbr->priority = nbr_nbma->priority;
1953 nbr->address = p;
718e3744 1954
d62a17ae 1955 nbr_nbma->nbr = nbr;
1956
659f4e40
RZ
1957 /* Configure BFD if interface has it. */
1958 ospf_neighbor_bfd_apply(nbr);
1959
d62a17ae 1960 OSPF_NSM_EVENT_EXECUTE(nbr, NSM_Start);
1961 }
718e3744 1962}
1963
d62a17ae 1964void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi)
718e3744 1965{
d62a17ae 1966 struct ospf_nbr_nbma *nbr_nbma;
1967 struct route_node *rn;
1968 struct prefix_ipv4 p;
718e3744 1969
d62a17ae 1970 if (oi->type != OSPF_IFTYPE_NBMA)
1971 return;
718e3744 1972
d62a17ae 1973 for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
1974 if ((nbr_nbma = rn->info))
1975 if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL) {
1976 p.family = AF_INET;
1977 p.prefix = nbr_nbma->addr;
1978 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 1979
d62a17ae 1980 if (prefix_match(oi->address,
1981 (struct prefix *)&p))
1982 ospf_nbr_nbma_add(nbr_nbma, oi);
1983 }
718e3744 1984}
1985
d62a17ae 1986struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *ospf,
1987 struct in_addr nbr_addr)
718e3744 1988{
d62a17ae 1989 struct route_node *rn;
1990 struct prefix_ipv4 p;
718e3744 1991
d62a17ae 1992 p.family = AF_INET;
1993 p.prefix = nbr_addr;
1994 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 1995
d62a17ae 1996 rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p);
1997 if (rn) {
1998 route_unlock_node(rn);
1999 return rn->info;
2000 }
2001 return NULL;
718e3744 2002}
2003
d62a17ae 2004int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2005{
d62a17ae 2006 struct ospf_nbr_nbma *nbr_nbma;
2007 struct ospf_interface *oi;
2008 struct prefix_ipv4 p;
2009 struct route_node *rn;
2010 struct listnode *node;
718e3744 2011
d62a17ae 2012 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2013 if (nbr_nbma)
2014 return 0;
718e3744 2015
d62a17ae 2016 nbr_nbma = ospf_nbr_nbma_new();
2017 nbr_nbma->addr = nbr_addr;
718e3744 2018
d62a17ae 2019 p.family = AF_INET;
2020 p.prefix = nbr_addr;
2021 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 2022
d62a17ae 2023 rn = route_node_get(ospf->nbr_nbma, (struct prefix *)&p);
2024 if (rn->info)
2025 route_unlock_node(rn);
2026 rn->info = nbr_nbma;
718e3744 2027
d62a17ae 2028 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
2029 if (oi->type == OSPF_IFTYPE_NBMA)
2030 if (prefix_match(oi->address, (struct prefix *)&p)) {
2031 ospf_nbr_nbma_add(nbr_nbma, oi);
2032 break;
2033 }
2034 }
718e3744 2035
d62a17ae 2036 return 1;
718e3744 2037}
2038
d62a17ae 2039int ospf_nbr_nbma_unset(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2040{
d62a17ae 2041 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2042
d62a17ae 2043 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2044 if (nbr_nbma == NULL)
2045 return 0;
718e3744 2046
d62a17ae 2047 ospf_nbr_nbma_down(nbr_nbma);
2048 ospf_nbr_nbma_delete(ospf, nbr_nbma);
718e3744 2049
d62a17ae 2050 return 1;
718e3744 2051}
2052
d62a17ae 2053int ospf_nbr_nbma_priority_set(struct ospf *ospf, struct in_addr nbr_addr,
d7c0a89a 2054 uint8_t priority)
718e3744 2055{
d62a17ae 2056 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2057
d62a17ae 2058 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2059 if (nbr_nbma == NULL)
2060 return 0;
718e3744 2061
d62a17ae 2062 if (nbr_nbma->priority != priority)
2063 nbr_nbma->priority = priority;
718e3744 2064
d62a17ae 2065 return 1;
718e3744 2066}
2067
d62a17ae 2068int ospf_nbr_nbma_priority_unset(struct ospf *ospf, struct in_addr nbr_addr)
718e3744 2069{
d62a17ae 2070 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2071
d62a17ae 2072 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2073 if (nbr_nbma == NULL)
2074 return 0;
718e3744 2075
d62a17ae 2076 if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
2077 nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
718e3744 2078
d62a17ae 2079 return 1;
718e3744 2080}
2081
d62a17ae 2082int ospf_nbr_nbma_poll_interval_set(struct ospf *ospf, struct in_addr nbr_addr,
2083 unsigned int interval)
718e3744 2084{
d62a17ae 2085 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2086
d62a17ae 2087 nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr);
2088 if (nbr_nbma == NULL)
2089 return 0;
718e3744 2090
d62a17ae 2091 if (nbr_nbma->v_poll != interval) {
2092 nbr_nbma->v_poll = interval;
2093 if (nbr_nbma->oi && ospf_if_is_up(nbr_nbma->oi)) {
2094 OSPF_TIMER_OFF(nbr_nbma->t_poll);
2095 OSPF_POLL_TIMER_ON(nbr_nbma->t_poll, ospf_poll_timer,
2096 nbr_nbma->v_poll);
2097 }
718e3744 2098 }
718e3744 2099
d62a17ae 2100 return 1;
718e3744 2101}
2102
d62a17ae 2103int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr)
718e3744 2104{
d62a17ae 2105 struct ospf_nbr_nbma *nbr_nbma;
718e3744 2106
d62a17ae 2107 nbr_nbma = ospf_nbr_nbma_lookup(ospf, addr);
2108 if (nbr_nbma == NULL)
2109 return 0;
718e3744 2110
d62a17ae 2111 if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
2112 nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
718e3744 2113
d62a17ae 2114 return 1;
718e3744 2115}
2116
d62a17ae 2117void ospf_master_init(struct thread_master *master)
718e3744 2118{
d62a17ae 2119 memset(&ospf_master, 0, sizeof(struct ospf_master));
020709f9 2120
d62a17ae 2121 om = &ospf_master;
2122 om->ospf = list_new();
2123 om->master = master;
020709f9 2124}
b5a8894d
CS
2125
2126/* Link OSPF instance to VRF. */
2127void ospf_vrf_link(struct ospf *ospf, struct vrf *vrf)
2128{
2129 ospf->vrf_id = vrf->vrf_id;
2130 if (vrf->info != (void *)ospf)
2131 vrf->info = (void *)ospf;
2132}
2133
2134/* Unlink OSPF instance from VRF. */
2135void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf)
2136{
2137 if (vrf->info == (void *)ospf)
2138 vrf->info = NULL;
2139 ospf->vrf_id = VRF_UNKNOWN;
2140}
2141
2142/* This is hook function for vrf create called as part of vrf_init */
2143static int ospf_vrf_new(struct vrf *vrf)
2144{
2145 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2146 zlog_debug("%s: VRF Created: %s(%u)", __func__, vrf->name,
2147 vrf->vrf_id);
b5a8894d
CS
2148
2149 return 0;
2150}
2151
2152/* This is hook function for vrf delete call as part of vrf_init */
2153static int ospf_vrf_delete(struct vrf *vrf)
2154{
2155 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2156 zlog_debug("%s: VRF Deletion: %s(%u)", __func__, vrf->name,
2157 vrf->vrf_id);
b5a8894d
CS
2158
2159 return 0;
2160}
2161
de11c1bc 2162static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf, bool set)
3d9f7302
PZ
2163{
2164 int type;
2165 struct list *red_list;
2166
2167 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
2168 red_list = ospf->redist[type];
2169 if (!red_list)
2170 continue;
2171 if (IS_DEBUG_OSPF_EVENT)
2172 zlog_debug(
2173 "%s: setting redist vrf %d bitmap for type %d",
2174 __func__, ospf->vrf_id, type);
de11c1bc
IR
2175 if (set)
2176 vrf_bitmap_set(zclient->redist[AFI_IP][type],
2177 ospf->vrf_id);
2178 else
2179 vrf_bitmap_unset(zclient->redist[AFI_IP][type],
2180 ospf->vrf_id);
3d9f7302 2181 }
b46538c4
IR
2182
2183 red_list = ospf->redist[DEFAULT_ROUTE];
2184 if (red_list) {
2185 if (set)
2186 vrf_bitmap_set(zclient->default_information[AFI_IP],
2187 ospf->vrf_id);
2188 else
2189 vrf_bitmap_unset(zclient->default_information[AFI_IP],
2190 ospf->vrf_id);
2191 }
3d9f7302
PZ
2192}
2193
b5a8894d
CS
2194/* Enable OSPF VRF instance */
2195static int ospf_vrf_enable(struct vrf *vrf)
2196{
2197 struct ospf *ospf = NULL;
7d206035 2198 vrf_id_t old_vrf_id;
3c0eb8fa 2199 int ret = 0;
b5a8894d
CS
2200
2201 if (IS_DEBUG_OSPF_EVENT)
5e81f5dd
DS
2202 zlog_debug("%s: VRF %s id %u enabled", __func__, vrf->name,
2203 vrf->vrf_id);
b5a8894d
CS
2204
2205 ospf = ospf_lookup_by_name(vrf->name);
2206 if (ospf) {
6895b354
PG
2207 if (ospf->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
2208 XFREE(MTYPE_OSPF_TOP, ospf->name);
2209 ospf->name = NULL;
2210 }
b5a8894d
CS
2211 old_vrf_id = ospf->vrf_id;
2212 /* We have instance configured, link to VRF and make it "up". */
2213 ospf_vrf_link(ospf, vrf);
2214 if (IS_DEBUG_OSPF_EVENT)
996c9314
LB
2215 zlog_debug(
2216 "%s: ospf linked to vrf %s vrf_id %u (old id %u)",
5e81f5dd 2217 __func__, vrf->name, ospf->vrf_id, old_vrf_id);
b5a8894d
CS
2218
2219 if (old_vrf_id != ospf->vrf_id) {
de11c1bc 2220 ospf_set_redist_vrf_bitmaps(ospf, true);
3d9f7302 2221
de11c1bc
IR
2222 /* start zebra redist to us for new vrf */
2223 ospf_zebra_vrf_register(ospf);
313d7993 2224
de11c1bc 2225 ret = ospf_sock_init(ospf);
3c0eb8fa
PG
2226 if (ret < 0 || ospf->fd <= 0)
2227 return 0;
996c9314
LB
2228 thread_add_read(master, ospf_read, ospf, ospf->fd,
2229 &ospf->t_read);
b5a8894d
CS
2230 ospf->oi_running = 1;
2231 ospf_router_id_update(ospf);
2232 }
2233 }
2234
2235 return 0;
2236}
2237
2238/* Disable OSPF VRF instance */
2239static int ospf_vrf_disable(struct vrf *vrf)
2240{
2241 struct ospf *ospf = NULL;
2242 vrf_id_t old_vrf_id = VRF_UNKNOWN;
2243
2244 if (vrf->vrf_id == VRF_DEFAULT)
2245 return 0;
2246
2247 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2248 zlog_debug("%s: VRF %s id %d disabled.", __func__, vrf->name,
2249 vrf->vrf_id);
b5a8894d
CS
2250
2251 ospf = ospf_lookup_by_name(vrf->name);
2252 if (ospf) {
2253 old_vrf_id = ospf->vrf_id;
2254
de11c1bc
IR
2255 ospf_zebra_vrf_deregister(ospf);
2256
2257 ospf_set_redist_vrf_bitmaps(ospf, false);
2258
b5a8894d
CS
2259 /* We have instance configured, unlink
2260 * from VRF and make it "down".
2261 */
2262 ospf_vrf_unlink(ospf, vrf);
2263 ospf->oi_running = 0;
2264 if (IS_DEBUG_OSPF_EVENT)
15569c58
DA
2265 zlog_debug("%s: ospf old_vrf_id %d unlinked", __func__,
2266 old_vrf_id);
b3d6bc6e 2267 thread_cancel(&ospf->t_read);
3c0eb8fa
PG
2268 close(ospf->fd);
2269 ospf->fd = -1;
b5a8894d
CS
2270 }
2271
2272 /* Note: This is a callback, the VRF will be deleted by the caller. */
2273 return 0;
2274}
2275
2276void ospf_vrf_init(void)
2277{
996c9314 2278 vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
b5c056fa 2279 ospf_vrf_delete, ospf_vrf_enable);
b5a8894d
CS
2280}
2281
2282void ospf_vrf_terminate(void)
2283{
2284 vrf_terminate();
2285}
2286
2287const char *ospf_vrf_id_to_name(vrf_id_t vrf_id)
2288{
2289 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
2290
2291 return vrf ? vrf->name : "NIL";
2292}
88b6b28e
DS
2293
2294const char *ospf_get_name(const struct ospf *ospf)
2295{
2296 if (ospf->name)
2297 return ospf->name;
2298 else
2299 return VRF_DEFAULT_NAME;
2300}