Annotation of embedaddon/quagga/ospfd/ospfd.c, revision 1.1
1.1 ! misho 1: /* OSPF version 2 daemon program.
! 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
! 17: along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: 02111-1307, USA. */
! 20:
! 21: #include <zebra.h>
! 22:
! 23: #include "thread.h"
! 24: #include "vty.h"
! 25: #include "command.h"
! 26: #include "linklist.h"
! 27: #include "prefix.h"
! 28: #include "table.h"
! 29: #include "if.h"
! 30: #include "memory.h"
! 31: #include "stream.h"
! 32: #include "log.h"
! 33: #include "sockunion.h" /* for inet_aton () */
! 34: #include "zclient.h"
! 35: #include "plist.h"
! 36: #include "sockopt.h"
! 37:
! 38: #include "ospfd/ospfd.h"
! 39: #include "ospfd/ospf_network.h"
! 40: #include "ospfd/ospf_interface.h"
! 41: #include "ospfd/ospf_ism.h"
! 42: #include "ospfd/ospf_asbr.h"
! 43: #include "ospfd/ospf_lsa.h"
! 44: #include "ospfd/ospf_lsdb.h"
! 45: #include "ospfd/ospf_neighbor.h"
! 46: #include "ospfd/ospf_nsm.h"
! 47: #include "ospfd/ospf_spf.h"
! 48: #include "ospfd/ospf_packet.h"
! 49: #include "ospfd/ospf_dump.h"
! 50: #include "ospfd/ospf_zebra.h"
! 51: #include "ospfd/ospf_abr.h"
! 52: #include "ospfd/ospf_flood.h"
! 53: #include "ospfd/ospf_route.h"
! 54: #include "ospfd/ospf_ase.h"
! 55:
! 56:
! 57:
! 58: /* OSPF process wide configuration. */
! 59: static struct ospf_master ospf_master;
! 60:
! 61: /* OSPF process wide configuration pointer to export. */
! 62: struct ospf_master *om;
! 63:
! 64: extern struct zclient *zclient;
! 65: extern struct in_addr router_id_zebra;
! 66:
! 67:
! 68: static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
! 69: static void ospf_network_free (struct ospf *, struct ospf_network *);
! 70: static void ospf_area_free (struct ospf_area *);
! 71: static void ospf_network_run (struct prefix *, struct ospf_area *);
! 72: static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
! 73: struct interface *);
! 74: static int ospf_network_match_iface (const struct connected *,
! 75: const struct prefix *);
! 76: static void ospf_finish_final (struct ospf *);
! 77:
! 78: #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
! 79:
! 80: void
! 81: ospf_router_id_update (struct ospf *ospf)
! 82: {
! 83: struct in_addr router_id, router_id_old;
! 84: struct ospf_interface *oi;
! 85: struct interface *ifp;
! 86: struct listnode *node;
! 87:
! 88: if (IS_DEBUG_OSPF_EVENT)
! 89: zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id));
! 90:
! 91: router_id_old = ospf->router_id;
! 92:
! 93: /* Select the router ID based on these priorities:
! 94: 1. Statically assigned router ID is always the first choice.
! 95: 2. If there is no statically assigned router ID, then try to stick
! 96: with the most recent value, since changing router ID's is very
! 97: disruptive.
! 98: 3. Last choice: just go with whatever the zebra daemon recommends.
! 99: */
! 100: if (ospf->router_id_static.s_addr != 0)
! 101: router_id = ospf->router_id_static;
! 102: else if (ospf->router_id.s_addr != 0)
! 103: router_id = ospf->router_id;
! 104: else
! 105: router_id = router_id_zebra;
! 106:
! 107: ospf->router_id = router_id;
! 108:
! 109: if (IS_DEBUG_OSPF_EVENT)
! 110: zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id));
! 111:
! 112: if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
! 113: {
! 114: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
! 115: /* Update self-neighbor's router_id. */
! 116: oi->nbr_self->router_id = router_id;
! 117:
! 118: /* If AS-external-LSA is queued, then flush those LSAs. */
! 119: if (router_id_old.s_addr == 0 && ospf->external_origin)
! 120: {
! 121: int type;
! 122: /* Originate each redistributed external route. */
! 123: for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
! 124: if (ospf->external_origin & (1 << type))
! 125: thread_add_event (master, ospf_external_lsa_originate_timer,
! 126: ospf, type);
! 127: /* Originate Deafult. */
! 128: if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
! 129: thread_add_event (master, ospf_default_originate_timer, ospf, 0);
! 130:
! 131: ospf->external_origin = 0;
! 132: }
! 133:
! 134: /* update router-lsa's for each area */
! 135: ospf_router_lsa_update (ospf);
! 136:
! 137: /* update ospf_interface's */
! 138: for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
! 139: ospf_if_update (ospf, ifp);
! 140: }
! 141: }
! 142:
! 143: /* For OSPF area sort by area id. */
! 144: static int
! 145: ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
! 146: {
! 147: if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
! 148: return 1;
! 149: if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
! 150: return -1;
! 151: return 0;
! 152: }
! 153:
! 154: /* Allocate new ospf structure. */
! 155: static struct ospf *
! 156: ospf_new (void)
! 157: {
! 158: int i;
! 159:
! 160: struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
! 161:
! 162: new->router_id.s_addr = htonl (0);
! 163: new->router_id_static.s_addr = htonl (0);
! 164:
! 165: new->abr_type = OSPF_ABR_DEFAULT;
! 166: new->oiflist = list_new ();
! 167: new->vlinks = list_new ();
! 168: new->areas = list_new ();
! 169: new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
! 170: new->networks = route_table_init ();
! 171: new->nbr_nbma = route_table_init ();
! 172:
! 173: new->lsdb = ospf_lsdb_new ();
! 174:
! 175: new->default_originate = DEFAULT_ORIGINATE_NONE;
! 176:
! 177: new->passive_interface_default = OSPF_IF_ACTIVE;
! 178:
! 179: new->new_external_route = route_table_init ();
! 180: new->old_external_route = route_table_init ();
! 181: new->external_lsas = route_table_init ();
! 182:
! 183: new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED;
! 184: new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
! 185:
! 186: /* Distribute parameter init. */
! 187: for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
! 188: {
! 189: new->dmetric[i].type = -1;
! 190: new->dmetric[i].value = -1;
! 191: }
! 192: new->default_metric = -1;
! 193: new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
! 194:
! 195: /* SPF timer value init. */
! 196: new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
! 197: new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
! 198: new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
! 199: new->spf_hold_multiplier = 1;
! 200:
! 201: /* MaxAge init. */
! 202: new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
! 203: new->maxage_lsa = list_new ();
! 204: new->t_maxage_walker =
! 205: thread_add_timer (master, ospf_lsa_maxage_walker,
! 206: new, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
! 207:
! 208: /* Distance table init. */
! 209: new->distance_table = route_table_init ();
! 210:
! 211: new->lsa_refresh_queue.index = 0;
! 212: new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
! 213: new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
! 214: new, new->lsa_refresh_interval);
! 215: new->lsa_refresher_started = quagga_time (NULL);
! 216:
! 217: if ((new->fd = ospf_sock_init()) < 0)
! 218: {
! 219: zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
! 220: "a socket");
! 221: exit(1);
! 222: }
! 223: new->maxsndbuflen = getsockopt_so_sendbuf (new->fd);
! 224: if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
! 225: zlog_debug ("%s: starting with OSPF send buffer size %d",
! 226: __func__, new->maxsndbuflen);
! 227: if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
! 228: {
! 229: zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
! 230: OSPF_MAX_PACKET_SIZE+1);
! 231: exit(1);
! 232: }
! 233: new->t_read = thread_add_read (master, ospf_read, new, new->fd);
! 234: new->oi_write_q = list_new ();
! 235:
! 236: return new;
! 237: }
! 238:
! 239: struct ospf *
! 240: ospf_lookup ()
! 241: {
! 242: if (listcount (om->ospf) == 0)
! 243: return NULL;
! 244:
! 245: return listgetdata (listhead (om->ospf));
! 246: }
! 247:
! 248: static void
! 249: ospf_add (struct ospf *ospf)
! 250: {
! 251: listnode_add (om->ospf, ospf);
! 252: }
! 253:
! 254: static void
! 255: ospf_delete (struct ospf *ospf)
! 256: {
! 257: listnode_delete (om->ospf, ospf);
! 258: }
! 259:
! 260: struct ospf *
! 261: ospf_get ()
! 262: {
! 263: struct ospf *ospf;
! 264:
! 265: ospf = ospf_lookup ();
! 266: if (ospf == NULL)
! 267: {
! 268: ospf = ospf_new ();
! 269: ospf_add (ospf);
! 270:
! 271: if (ospf->router_id_static.s_addr == 0)
! 272: ospf_router_id_update (ospf);
! 273:
! 274: #ifdef HAVE_OPAQUE_LSA
! 275: ospf_opaque_type11_lsa_init (ospf);
! 276: #endif /* HAVE_OPAQUE_LSA */
! 277: }
! 278:
! 279: return ospf;
! 280: }
! 281:
! 282: /* Handle the second half of deferred shutdown. This is called either
! 283: * from the deferred-shutdown timer thread, or directly through
! 284: * ospf_deferred_shutdown_check.
! 285: *
! 286: * Function is to cleanup G-R state, if required then call ospf_finish_final
! 287: * to complete shutdown of this ospf instance. Possibly exit if the
! 288: * whole process is being shutdown and this was the last OSPF instance.
! 289: */
! 290: static void
! 291: ospf_deferred_shutdown_finish (struct ospf *ospf)
! 292: {
! 293: ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED;
! 294: OSPF_TIMER_OFF (ospf->t_deferred_shutdown);
! 295:
! 296: ospf_finish_final (ospf);
! 297:
! 298: /* *ospf is now invalid */
! 299:
! 300: /* ospfd being shut-down? If so, was this the last ospf instance? */
! 301: if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)
! 302: && (listcount (om->ospf) == 0))
! 303: exit (0);
! 304:
! 305: return;
! 306: }
! 307:
! 308: /* Timer thread for G-R */
! 309: static int
! 310: ospf_deferred_shutdown_timer (struct thread *t)
! 311: {
! 312: struct ospf *ospf = THREAD_ARG(t);
! 313:
! 314: ospf_deferred_shutdown_finish (ospf);
! 315:
! 316: return 0;
! 317: }
! 318:
! 319: /* Check whether deferred-shutdown must be scheduled, otherwise call
! 320: * down directly into second-half of instance shutdown.
! 321: */
! 322: static void
! 323: ospf_deferred_shutdown_check (struct ospf *ospf)
! 324: {
! 325: unsigned long timeout;
! 326: struct listnode *ln;
! 327: struct ospf_area *area;
! 328:
! 329: /* deferred shutdown already running? */
! 330: if (ospf->t_deferred_shutdown)
! 331: return;
! 332:
! 333: /* Should we try push out max-metric LSAs? */
! 334: if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED)
! 335: {
! 336: for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area))
! 337: {
! 338: SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
! 339:
! 340: if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
! 341: ospf_router_lsa_update_area (area);
! 342: }
! 343: timeout = ospf->stub_router_shutdown_time;
! 344: }
! 345: else
! 346: {
! 347: /* No timer needed */
! 348: ospf_deferred_shutdown_finish (ospf);
! 349: return;
! 350: }
! 351:
! 352: OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer,
! 353: timeout);
! 354: return;
! 355: }
! 356:
! 357: /* Shut down the entire process */
! 358: void
! 359: ospf_terminate (void)
! 360: {
! 361: struct ospf *ospf;
! 362: struct listnode *node, *nnode;
! 363:
! 364: /* shutdown already in progress */
! 365: if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN))
! 366: return;
! 367:
! 368: SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN);
! 369:
! 370: /* exit immediately if OSPF not actually running */
! 371: if (listcount(om->ospf) == 0)
! 372: exit(0);
! 373:
! 374: for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
! 375: ospf_finish (ospf);
! 376:
! 377: /* Deliberately go back up, hopefully to thread scheduler, as
! 378: * One or more ospf_finish()'s may have deferred shutdown to a timer
! 379: * thread
! 380: */
! 381: }
! 382:
! 383: void
! 384: ospf_finish (struct ospf *ospf)
! 385: {
! 386: /* let deferred shutdown decide */
! 387: ospf_deferred_shutdown_check (ospf);
! 388:
! 389: /* if ospf_deferred_shutdown returns, then ospf_finish_final is
! 390: * deferred to expiry of G-S timer thread. Return back up, hopefully
! 391: * to thread scheduler.
! 392: */
! 393: return;
! 394: }
! 395:
! 396: /* Final cleanup of ospf instance */
! 397: static void
! 398: ospf_finish_final (struct ospf *ospf)
! 399: {
! 400: struct route_node *rn;
! 401: struct ospf_nbr_nbma *nbr_nbma;
! 402: struct ospf_lsa *lsa;
! 403: struct ospf_interface *oi;
! 404: struct ospf_area *area;
! 405: struct ospf_vl_data *vl_data;
! 406: struct listnode *node, *nnode;
! 407: int i;
! 408:
! 409: #ifdef HAVE_OPAQUE_LSA
! 410: ospf_opaque_type11_lsa_term (ospf);
! 411: #endif /* HAVE_OPAQUE_LSA */
! 412:
! 413: /* be nice if this worked, but it doesn't */
! 414: /*ospf_flush_self_originated_lsas_now (ospf);*/
! 415:
! 416: /* Unregister redistribution */
! 417: for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
! 418: ospf_redistribute_unset (ospf, i);
! 419: ospf_redistribute_default_unset (ospf);
! 420:
! 421: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 422: ospf_remove_vls_through_area (ospf, area);
! 423:
! 424: for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
! 425: ospf_vl_delete (ospf, vl_data);
! 426:
! 427: list_delete (ospf->vlinks);
! 428:
! 429: /* Reset interface. */
! 430: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 431: ospf_if_free (oi);
! 432:
! 433: /* Clear static neighbors */
! 434: for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
! 435: if ((nbr_nbma = rn->info))
! 436: {
! 437: OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
! 438:
! 439: if (nbr_nbma->nbr)
! 440: {
! 441: nbr_nbma->nbr->nbr_nbma = NULL;
! 442: nbr_nbma->nbr = NULL;
! 443: }
! 444:
! 445: if (nbr_nbma->oi)
! 446: {
! 447: listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
! 448: nbr_nbma->oi = NULL;
! 449: }
! 450:
! 451: XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
! 452: }
! 453:
! 454: route_table_finish (ospf->nbr_nbma);
! 455:
! 456: /* Clear networks and Areas. */
! 457: for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
! 458: {
! 459: struct ospf_network *network;
! 460:
! 461: if ((network = rn->info) != NULL)
! 462: {
! 463: ospf_network_free (ospf, network);
! 464: rn->info = NULL;
! 465: route_unlock_node (rn);
! 466: }
! 467: }
! 468:
! 469: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 470: {
! 471: listnode_delete (ospf->areas, area);
! 472: ospf_area_free (area);
! 473: }
! 474:
! 475: /* Cancel all timers. */
! 476: OSPF_TIMER_OFF (ospf->t_external_lsa);
! 477: OSPF_TIMER_OFF (ospf->t_spf_calc);
! 478: OSPF_TIMER_OFF (ospf->t_ase_calc);
! 479: OSPF_TIMER_OFF (ospf->t_maxage);
! 480: OSPF_TIMER_OFF (ospf->t_maxage_walker);
! 481: OSPF_TIMER_OFF (ospf->t_abr_task);
! 482: OSPF_TIMER_OFF (ospf->t_asbr_check);
! 483: OSPF_TIMER_OFF (ospf->t_distribute_update);
! 484: OSPF_TIMER_OFF (ospf->t_lsa_refresher);
! 485: OSPF_TIMER_OFF (ospf->t_read);
! 486: OSPF_TIMER_OFF (ospf->t_write);
! 487: #ifdef HAVE_OPAQUE_LSA
! 488: OSPF_TIMER_OFF (ospf->t_opaque_lsa_self);
! 489: #endif
! 490:
! 491: close (ospf->fd);
! 492: stream_free(ospf->ibuf);
! 493:
! 494: #ifdef HAVE_OPAQUE_LSA
! 495: LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
! 496: ospf_discard_from_db (ospf, ospf->lsdb, lsa);
! 497: #endif /* HAVE_OPAQUE_LSA */
! 498: LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
! 499: ospf_discard_from_db (ospf, ospf->lsdb, lsa);
! 500:
! 501: ospf_lsdb_delete_all (ospf->lsdb);
! 502: ospf_lsdb_free (ospf->lsdb);
! 503:
! 504: for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
! 505: ospf_lsa_unlock (&lsa); /* maxage_lsa */
! 506:
! 507: list_delete (ospf->maxage_lsa);
! 508:
! 509: if (ospf->old_table)
! 510: ospf_route_table_free (ospf->old_table);
! 511: if (ospf->new_table)
! 512: {
! 513: ospf_route_delete (ospf->new_table);
! 514: ospf_route_table_free (ospf->new_table);
! 515: }
! 516: if (ospf->old_rtrs)
! 517: ospf_rtrs_free (ospf->old_rtrs);
! 518: if (ospf->new_rtrs)
! 519: ospf_rtrs_free (ospf->new_rtrs);
! 520: if (ospf->new_external_route)
! 521: {
! 522: ospf_route_delete (ospf->new_external_route);
! 523: ospf_route_table_free (ospf->new_external_route);
! 524: }
! 525: if (ospf->old_external_route)
! 526: {
! 527: ospf_route_delete (ospf->old_external_route);
! 528: ospf_route_table_free (ospf->old_external_route);
! 529: }
! 530: if (ospf->external_lsas)
! 531: {
! 532: ospf_ase_external_lsas_finish (ospf->external_lsas);
! 533: }
! 534:
! 535: list_delete (ospf->areas);
! 536:
! 537: for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
! 538: if (EXTERNAL_INFO (i) != NULL)
! 539: for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
! 540: {
! 541: if (rn->info == NULL)
! 542: continue;
! 543:
! 544: XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
! 545: rn->info = NULL;
! 546: route_unlock_node (rn);
! 547: }
! 548:
! 549: ospf_distance_reset (ospf);
! 550: route_table_finish (ospf->distance_table);
! 551:
! 552: ospf_delete (ospf);
! 553:
! 554: XFREE (MTYPE_OSPF_TOP, ospf);
! 555: }
! 556:
! 557:
! 558: /* allocate new OSPF Area object */
! 559: static struct ospf_area *
! 560: ospf_area_new (struct ospf *ospf, struct in_addr area_id)
! 561: {
! 562: struct ospf_area *new;
! 563:
! 564: /* Allocate new config_network. */
! 565: new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
! 566:
! 567: new->ospf = ospf;
! 568:
! 569: new->area_id = area_id;
! 570:
! 571: new->external_routing = OSPF_AREA_DEFAULT;
! 572: new->default_cost = 1;
! 573: new->auth_type = OSPF_AUTH_NULL;
! 574:
! 575: /* New LSDB init. */
! 576: new->lsdb = ospf_lsdb_new ();
! 577:
! 578: /* Self-originated LSAs initialize. */
! 579: new->router_lsa_self = NULL;
! 580:
! 581: #ifdef HAVE_OPAQUE_LSA
! 582: ospf_opaque_type10_lsa_init (new);
! 583: #endif /* HAVE_OPAQUE_LSA */
! 584:
! 585: new->oiflist = list_new ();
! 586: new->ranges = route_table_init ();
! 587:
! 588: if (area_id.s_addr == OSPF_AREA_BACKBONE)
! 589: ospf->backbone = new;
! 590:
! 591: return new;
! 592: }
! 593:
! 594: static void
! 595: ospf_area_free (struct ospf_area *area)
! 596: {
! 597: struct route_node *rn;
! 598: struct ospf_lsa *lsa;
! 599:
! 600: /* Free LSDBs. */
! 601: LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
! 602: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 603: LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
! 604: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 605: LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
! 606: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 607: LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
! 608: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 609:
! 610: LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
! 611: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 612: #ifdef HAVE_OPAQUE_LSA
! 613: LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
! 614: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 615: LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
! 616: ospf_discard_from_db (area->ospf, area->lsdb, lsa);
! 617: #endif /* HAVE_OPAQUE_LSA */
! 618:
! 619: ospf_lsdb_delete_all (area->lsdb);
! 620: ospf_lsdb_free (area->lsdb);
! 621:
! 622: ospf_lsa_unlock (&area->router_lsa_self);
! 623:
! 624: route_table_finish (area->ranges);
! 625: list_delete (area->oiflist);
! 626:
! 627: if (EXPORT_NAME (area))
! 628: free (EXPORT_NAME (area));
! 629:
! 630: if (IMPORT_NAME (area))
! 631: free (IMPORT_NAME (area));
! 632:
! 633: /* Cancel timer. */
! 634: OSPF_TIMER_OFF (area->t_stub_router);
! 635: #ifdef HAVE_OPAQUE_LSA
! 636: OSPF_TIMER_OFF (area->t_opaque_lsa_self);
! 637: #endif /* HAVE_OPAQUE_LSA */
! 638:
! 639: if (OSPF_IS_AREA_BACKBONE (area))
! 640: area->ospf->backbone = NULL;
! 641:
! 642: XFREE (MTYPE_OSPF_AREA, area);
! 643: }
! 644:
! 645: void
! 646: ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
! 647: {
! 648: struct ospf_area *area;
! 649:
! 650: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 651: if (area &&
! 652: listcount (area->oiflist) == 0 &&
! 653: area->ranges->top == NULL &&
! 654: area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
! 655: area->external_routing == OSPF_AREA_DEFAULT &&
! 656: area->no_summary == 0 &&
! 657: area->default_cost == 1 &&
! 658: EXPORT_NAME (area) == NULL &&
! 659: IMPORT_NAME (area) == NULL &&
! 660: area->auth_type == OSPF_AUTH_NULL)
! 661: {
! 662: listnode_delete (ospf->areas, area);
! 663: ospf_area_free (area);
! 664: }
! 665: }
! 666:
! 667: struct ospf_area *
! 668: ospf_area_get (struct ospf *ospf, struct in_addr area_id, int format)
! 669: {
! 670: struct ospf_area *area;
! 671:
! 672: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 673: if (!area)
! 674: {
! 675: area = ospf_area_new (ospf, area_id);
! 676: area->format = format;
! 677: listnode_add_sort (ospf->areas, area);
! 678: ospf_check_abr_status (ospf);
! 679: }
! 680:
! 681: return area;
! 682: }
! 683:
! 684: struct ospf_area *
! 685: ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id)
! 686: {
! 687: struct ospf_area *area;
! 688: struct listnode *node;
! 689:
! 690: for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
! 691: if (IPV4_ADDR_SAME (&area->area_id, &area_id))
! 692: return area;
! 693:
! 694: return NULL;
! 695: }
! 696:
! 697: void
! 698: ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
! 699: {
! 700: listnode_add (area->oiflist, oi);
! 701: }
! 702:
! 703: void
! 704: ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
! 705: {
! 706: listnode_delete (area->oiflist, oi);
! 707: }
! 708:
! 709:
! 710: /* Config network statement related functions. */
! 711: static struct ospf_network *
! 712: ospf_network_new (struct in_addr area_id, int format)
! 713: {
! 714: struct ospf_network *new;
! 715: new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
! 716:
! 717: new->area_id = area_id;
! 718: new->format = format;
! 719:
! 720: return new;
! 721: }
! 722:
! 723: static void
! 724: ospf_network_free (struct ospf *ospf, struct ospf_network *network)
! 725: {
! 726: ospf_area_check_free (ospf, network->area_id);
! 727: ospf_schedule_abr_task (ospf);
! 728: XFREE (MTYPE_OSPF_NETWORK, network);
! 729: }
! 730:
! 731: int
! 732: ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
! 733: struct in_addr area_id)
! 734: {
! 735: struct ospf_network *network;
! 736: struct ospf_area *area;
! 737: struct route_node *rn;
! 738: struct external_info *ei;
! 739: int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
! 740:
! 741: rn = route_node_get (ospf->networks, (struct prefix *)p);
! 742: if (rn->info)
! 743: {
! 744: /* There is already same network statement. */
! 745: route_unlock_node (rn);
! 746: return 0;
! 747: }
! 748:
! 749: rn->info = network = ospf_network_new (area_id, ret);
! 750: area = ospf_area_get (ospf, area_id, ret);
! 751:
! 752: /* Run network config now. */
! 753: ospf_network_run ((struct prefix *)p, area);
! 754:
! 755: /* Update connected redistribute. */
! 756: if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
! 757: if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
! 758: for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
! 759: rn; rn = route_next (rn))
! 760: if ((ei = rn->info) != NULL)
! 761: if (ospf_external_info_find_lsa (ospf, &ei->p))
! 762: if (!ospf_distribute_check_connected (ospf, ei))
! 763: ospf_external_lsa_flush (ospf, ei->type, &ei->p,
! 764: ei->ifindex /*, ei->nexthop */);
! 765:
! 766: ospf_area_check_free (ospf, area_id);
! 767:
! 768: return 1;
! 769: }
! 770:
! 771: int
! 772: ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
! 773: struct in_addr area_id)
! 774: {
! 775: struct route_node *rn;
! 776: struct ospf_network *network;
! 777: struct external_info *ei;
! 778: struct listnode *node, *nnode;
! 779: struct ospf_interface *oi;
! 780:
! 781: rn = route_node_lookup (ospf->networks, (struct prefix *)p);
! 782: if (rn == NULL)
! 783: return 0;
! 784:
! 785: network = rn->info;
! 786: route_unlock_node (rn);
! 787: if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
! 788: return 0;
! 789:
! 790: ospf_network_free (ospf, rn->info);
! 791: rn->info = NULL;
! 792: route_unlock_node (rn); /* initial reference */
! 793:
! 794: /* Find interfaces that not configured already. */
! 795: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 796: {
! 797: int found = 0;
! 798: struct connected *co = oi->connected;
! 799:
! 800: if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
! 801: continue;
! 802:
! 803: for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
! 804: {
! 805: if (rn->info == NULL)
! 806: continue;
! 807:
! 808: if (ospf_network_match_iface(co,&rn->p))
! 809: {
! 810: found = 1;
! 811: route_unlock_node (rn);
! 812: break;
! 813: }
! 814: }
! 815:
! 816: if (found == 0)
! 817: ospf_if_free (oi);
! 818: }
! 819:
! 820: /* Update connected redistribute. */
! 821: if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
! 822: if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
! 823: for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
! 824: rn; rn = route_next (rn))
! 825: if ((ei = rn->info) != NULL)
! 826: if (!ospf_external_info_find_lsa (ospf, &ei->p))
! 827: if (ospf_distribute_check_connected (ospf, ei))
! 828: ospf_external_lsa_originate (ospf, ei);
! 829:
! 830: return 1;
! 831: }
! 832:
! 833: /* Check whether interface matches given network
! 834: * returns: 1, true. 0, false
! 835: */
! 836: static int
! 837: ospf_network_match_iface(const struct connected *co, const struct prefix *net)
! 838: {
! 839: /* new approach: more elegant and conceptually clean */
! 840: return prefix_match(net, CONNECTED_PREFIX(co));
! 841: }
! 842:
! 843: static void
! 844: ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
! 845: struct interface *ifp)
! 846: {
! 847: struct listnode *cnode;
! 848: struct connected *co;
! 849:
! 850: if (memcmp (ifp->name, "VLINK", 5) == 0)
! 851: return;
! 852:
! 853: /* if interface prefix is match specified prefix,
! 854: then create socket and join multicast group. */
! 855: for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
! 856: {
! 857:
! 858: if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
! 859: continue;
! 860:
! 861: if (p->family == co->address->family
! 862: && ! ospf_if_table_lookup(ifp, co->address)
! 863: && ospf_network_match_iface(co,p))
! 864: {
! 865: struct ospf_interface *oi;
! 866:
! 867: oi = ospf_if_new (area->ospf, ifp, co->address);
! 868: oi->connected = co;
! 869:
! 870: oi->area = area;
! 871:
! 872: oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
! 873: oi->output_cost = ospf_if_get_output_cost (oi);
! 874:
! 875: /* Add pseudo neighbor. */
! 876: ospf_nbr_add_self (oi);
! 877:
! 878: /* Relate ospf interface to ospf instance. */
! 879: oi->ospf = area->ospf;
! 880:
! 881: /* update network type as interface flag */
! 882: /* If network type is specified previously,
! 883: skip network type setting. */
! 884: oi->type = IF_DEF_PARAMS (ifp)->type;
! 885:
! 886: ospf_area_add_if (oi->area, oi);
! 887:
! 888: /* if router_id is not configured, dont bring up
! 889: * interfaces.
! 890: * ospf_router_id_update() will call ospf_if_update
! 891: * whenever r-id is configured instead.
! 892: */
! 893: if ((area->ospf->router_id.s_addr != 0)
! 894: && if_is_operative (ifp))
! 895: ospf_if_up (oi);
! 896: }
! 897: }
! 898: }
! 899:
! 900: static void
! 901: ospf_network_run (struct prefix *p, struct ospf_area *area)
! 902: {
! 903: struct interface *ifp;
! 904: struct listnode *node;
! 905:
! 906: /* Schedule Router ID Update. */
! 907: if (area->ospf->router_id.s_addr == 0)
! 908: ospf_router_id_update (area->ospf);
! 909:
! 910: /* Get target interface. */
! 911: for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
! 912: ospf_network_run_interface (p, area, ifp);
! 913: }
! 914:
! 915: void
! 916: ospf_ls_upd_queue_empty (struct ospf_interface *oi)
! 917: {
! 918: struct route_node *rn;
! 919: struct listnode *node, *nnode;
! 920: struct list *lst;
! 921: struct ospf_lsa *lsa;
! 922:
! 923: /* empty ls update queue */
! 924: for (rn = route_top (oi->ls_upd_queue); rn;
! 925: rn = route_next (rn))
! 926: if ((lst = (struct list *) rn->info))
! 927: {
! 928: for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa))
! 929: ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
! 930: list_free (lst);
! 931: rn->info = NULL;
! 932: }
! 933:
! 934: /* remove update event */
! 935: if (oi->t_ls_upd_event)
! 936: {
! 937: thread_cancel (oi->t_ls_upd_event);
! 938: oi->t_ls_upd_event = NULL;
! 939: }
! 940: }
! 941:
! 942: void
! 943: ospf_if_update (struct ospf *ospf, struct interface *ifp)
! 944: {
! 945: struct route_node *rn;
! 946: struct ospf_network *network;
! 947: struct ospf_area *area;
! 948:
! 949: if (!ospf)
! 950: ospf = ospf_lookup ();
! 951:
! 952: /* OSPF must be on and Router-ID must be configured. */
! 953: if (!ospf || ospf->router_id.s_addr == 0)
! 954: return;
! 955:
! 956: /* Run each netowrk for this interface. */
! 957: for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
! 958: if (rn->info != NULL)
! 959: {
! 960: network = (struct ospf_network *) rn->info;
! 961: area = ospf_area_get (ospf, network->area_id, network->format);
! 962: ospf_network_run_interface (&rn->p, area, ifp);
! 963: }
! 964: }
! 965:
! 966: void
! 967: ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area)
! 968: {
! 969: struct listnode *node, *nnode;
! 970: struct ospf_vl_data *vl_data;
! 971:
! 972: for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
! 973: if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
! 974: ospf_vl_delete (ospf, vl_data);
! 975: }
! 976:
! 977:
! 978: static const struct message ospf_area_type_msg[] =
! 979: {
! 980: { OSPF_AREA_DEFAULT, "Default" },
! 981: { OSPF_AREA_STUB, "Stub" },
! 982: { OSPF_AREA_NSSA, "NSSA" },
! 983: };
! 984: static const int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
! 985:
! 986: static void
! 987: ospf_area_type_set (struct ospf_area *area, int type)
! 988: {
! 989: struct listnode *node;
! 990: struct ospf_interface *oi;
! 991:
! 992: if (area->external_routing == type)
! 993: {
! 994: if (IS_DEBUG_OSPF_EVENT)
! 995: zlog_debug ("Area[%s]: Types are the same, ignored.",
! 996: inet_ntoa (area->area_id));
! 997: return;
! 998: }
! 999:
! 1000: area->external_routing = type;
! 1001:
! 1002: if (IS_DEBUG_OSPF_EVENT)
! 1003: zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
! 1004: LOOKUP (ospf_area_type_msg, type));
! 1005:
! 1006: switch (area->external_routing)
! 1007: {
! 1008: case OSPF_AREA_DEFAULT:
! 1009: for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
! 1010: if (oi->nbr_self != NULL)
! 1011: {
! 1012: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
! 1013: SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
! 1014: }
! 1015: break;
! 1016: case OSPF_AREA_STUB:
! 1017: for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
! 1018: if (oi->nbr_self != NULL)
! 1019: {
! 1020: if (IS_DEBUG_OSPF_EVENT)
! 1021: zlog_debug ("setting options on %s accordingly", IF_NAME (oi));
! 1022: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
! 1023: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
! 1024: if (IS_DEBUG_OSPF_EVENT)
! 1025: zlog_debug ("options set on %s: %x",
! 1026: IF_NAME (oi), OPTIONS (oi));
! 1027: }
! 1028: break;
! 1029: case OSPF_AREA_NSSA:
! 1030: for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
! 1031: if (oi->nbr_self != NULL)
! 1032: {
! 1033: zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi));
! 1034: UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
! 1035: SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
! 1036: zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
! 1037: }
! 1038: break;
! 1039: default:
! 1040: break;
! 1041: }
! 1042:
! 1043: ospf_router_lsa_update_area (area);
! 1044: ospf_schedule_abr_task (area->ospf);
! 1045: }
! 1046:
! 1047: int
! 1048: ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
! 1049: {
! 1050: if (area->shortcut_configured == mode)
! 1051: return 0;
! 1052:
! 1053: area->shortcut_configured = mode;
! 1054: ospf_router_lsa_update_area (area);
! 1055: ospf_schedule_abr_task (ospf);
! 1056:
! 1057: ospf_area_check_free (ospf, area->area_id);
! 1058:
! 1059: return 1;
! 1060: }
! 1061:
! 1062: int
! 1063: ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
! 1064: {
! 1065: area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
! 1066: ospf_router_lsa_update_area (area);
! 1067: ospf_area_check_free (ospf, area->area_id);
! 1068: ospf_schedule_abr_task (ospf);
! 1069:
! 1070: return 1;
! 1071: }
! 1072:
! 1073: static int
! 1074: ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
! 1075: {
! 1076: struct ospf_vl_data *vl;
! 1077: struct listnode *node;
! 1078: int count = 0;
! 1079:
! 1080: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl))
! 1081: if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
! 1082: count++;
! 1083:
! 1084: return count;
! 1085: }
! 1086:
! 1087: int
! 1088: ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
! 1089: {
! 1090: struct ospf_area *area;
! 1091: int format = OSPF_AREA_ID_FORMAT_ADDRESS;
! 1092:
! 1093: area = ospf_area_get (ospf, area_id, format);
! 1094: if (ospf_area_vlink_count (ospf, area))
! 1095: return 0;
! 1096:
! 1097: if (area->external_routing != OSPF_AREA_STUB)
! 1098: ospf_area_type_set (area, OSPF_AREA_STUB);
! 1099:
! 1100: return 1;
! 1101: }
! 1102:
! 1103: int
! 1104: ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
! 1105: {
! 1106: struct ospf_area *area;
! 1107:
! 1108: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 1109: if (area == NULL)
! 1110: return 1;
! 1111:
! 1112: if (area->external_routing == OSPF_AREA_STUB)
! 1113: ospf_area_type_set (area, OSPF_AREA_DEFAULT);
! 1114:
! 1115: ospf_area_check_free (ospf, area_id);
! 1116:
! 1117: return 1;
! 1118: }
! 1119:
! 1120: int
! 1121: ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
! 1122: {
! 1123: struct ospf_area *area;
! 1124: int format = OSPF_AREA_ID_FORMAT_ADDRESS;
! 1125:
! 1126: area = ospf_area_get (ospf, area_id, format);
! 1127: area->no_summary = 1;
! 1128:
! 1129: return 1;
! 1130: }
! 1131:
! 1132: int
! 1133: ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
! 1134: {
! 1135: struct ospf_area *area;
! 1136:
! 1137: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 1138: if (area == NULL)
! 1139: return 0;
! 1140:
! 1141: area->no_summary = 0;
! 1142: ospf_area_check_free (ospf, area_id);
! 1143:
! 1144: return 1;
! 1145: }
! 1146:
! 1147: int
! 1148: ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
! 1149: {
! 1150: struct ospf_area *area;
! 1151: int format = OSPF_AREA_ID_FORMAT_ADDRESS;
! 1152:
! 1153: area = ospf_area_get (ospf, area_id, format);
! 1154: if (ospf_area_vlink_count (ospf, area))
! 1155: return 0;
! 1156:
! 1157: if (area->external_routing != OSPF_AREA_NSSA)
! 1158: {
! 1159: ospf_area_type_set (area, OSPF_AREA_NSSA);
! 1160: ospf->anyNSSA++;
! 1161: }
! 1162:
! 1163: /* set NSSA area defaults */
! 1164: area->no_summary = 0;
! 1165: area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
! 1166: area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
! 1167: area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
! 1168:
! 1169: return 1;
! 1170: }
! 1171:
! 1172: int
! 1173: ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
! 1174: {
! 1175: struct ospf_area *area;
! 1176:
! 1177: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 1178: if (area == NULL)
! 1179: return 0;
! 1180:
! 1181: if (area->external_routing == OSPF_AREA_NSSA)
! 1182: {
! 1183: ospf->anyNSSA--;
! 1184: ospf_area_type_set (area, OSPF_AREA_DEFAULT);
! 1185: }
! 1186:
! 1187: ospf_area_check_free (ospf, area_id);
! 1188:
! 1189: return 1;
! 1190: }
! 1191:
! 1192: int
! 1193: ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
! 1194: int role)
! 1195: {
! 1196: struct ospf_area *area;
! 1197:
! 1198: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 1199: if (area == NULL)
! 1200: return 0;
! 1201:
! 1202: area->NSSATranslatorRole = role;
! 1203:
! 1204: return 1;
! 1205: }
! 1206:
! 1207: /* XXX: unused? Leave for symmetry? */
! 1208: static int
! 1209: ospf_area_nssa_translator_role_unset (struct ospf *ospf,
! 1210: struct in_addr area_id)
! 1211: {
! 1212: struct ospf_area *area;
! 1213:
! 1214: area = ospf_area_lookup_by_area_id (ospf, area_id);
! 1215: if (area == NULL)
! 1216: return 0;
! 1217:
! 1218: area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
! 1219:
! 1220: ospf_area_check_free (ospf, area_id);
! 1221:
! 1222: return 1;
! 1223: }
! 1224:
! 1225: int
! 1226: ospf_area_export_list_set (struct ospf *ospf,
! 1227: struct ospf_area *area, const char *list_name)
! 1228: {
! 1229: struct access_list *list;
! 1230: list = access_list_lookup (AFI_IP, list_name);
! 1231:
! 1232: EXPORT_LIST (area) = list;
! 1233:
! 1234: if (EXPORT_NAME (area))
! 1235: free (EXPORT_NAME (area));
! 1236:
! 1237: EXPORT_NAME (area) = strdup (list_name);
! 1238: ospf_schedule_abr_task (ospf);
! 1239:
! 1240: return 1;
! 1241: }
! 1242:
! 1243: int
! 1244: ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area)
! 1245: {
! 1246:
! 1247: EXPORT_LIST (area) = 0;
! 1248:
! 1249: if (EXPORT_NAME (area))
! 1250: free (EXPORT_NAME (area));
! 1251:
! 1252: EXPORT_NAME (area) = NULL;
! 1253:
! 1254: ospf_area_check_free (ospf, area->area_id);
! 1255:
! 1256: ospf_schedule_abr_task (ospf);
! 1257:
! 1258: return 1;
! 1259: }
! 1260:
! 1261: int
! 1262: ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area,
! 1263: const char *name)
! 1264: {
! 1265: struct access_list *list;
! 1266: list = access_list_lookup (AFI_IP, name);
! 1267:
! 1268: IMPORT_LIST (area) = list;
! 1269:
! 1270: if (IMPORT_NAME (area))
! 1271: free (IMPORT_NAME (area));
! 1272:
! 1273: IMPORT_NAME (area) = strdup (name);
! 1274: ospf_schedule_abr_task (ospf);
! 1275:
! 1276: return 1;
! 1277: }
! 1278:
! 1279: int
! 1280: ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area)
! 1281: {
! 1282: IMPORT_LIST (area) = 0;
! 1283:
! 1284: if (IMPORT_NAME (area))
! 1285: free (IMPORT_NAME (area));
! 1286:
! 1287: IMPORT_NAME (area) = NULL;
! 1288: ospf_area_check_free (ospf, area->area_id);
! 1289:
! 1290: ospf_schedule_abr_task (ospf);
! 1291:
! 1292: return 1;
! 1293: }
! 1294:
! 1295: int
! 1296: ospf_timers_refresh_set (struct ospf *ospf, int interval)
! 1297: {
! 1298: int time_left;
! 1299:
! 1300: if (ospf->lsa_refresh_interval == interval)
! 1301: return 1;
! 1302:
! 1303: time_left = ospf->lsa_refresh_interval -
! 1304: (quagga_time (NULL) - ospf->lsa_refresher_started);
! 1305:
! 1306: if (time_left > interval)
! 1307: {
! 1308: OSPF_TIMER_OFF (ospf->t_lsa_refresher);
! 1309: ospf->t_lsa_refresher =
! 1310: thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
! 1311: }
! 1312: ospf->lsa_refresh_interval = interval;
! 1313:
! 1314: return 1;
! 1315: }
! 1316:
! 1317: int
! 1318: ospf_timers_refresh_unset (struct ospf *ospf)
! 1319: {
! 1320: int time_left;
! 1321:
! 1322: time_left = ospf->lsa_refresh_interval -
! 1323: (quagga_time (NULL) - ospf->lsa_refresher_started);
! 1324:
! 1325: if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
! 1326: {
! 1327: OSPF_TIMER_OFF (ospf->t_lsa_refresher);
! 1328: ospf->t_lsa_refresher =
! 1329: thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
! 1330: OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
! 1331: }
! 1332:
! 1333: ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
! 1334:
! 1335: return 1;
! 1336: }
! 1337:
! 1338:
! 1339: static struct ospf_nbr_nbma *
! 1340: ospf_nbr_nbma_new (void)
! 1341: {
! 1342: struct ospf_nbr_nbma *nbr_nbma;
! 1343:
! 1344: nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
! 1345: sizeof (struct ospf_nbr_nbma));
! 1346:
! 1347: nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
! 1348: nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
! 1349:
! 1350: return nbr_nbma;
! 1351: }
! 1352:
! 1353: static void
! 1354: ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
! 1355: {
! 1356: XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
! 1357: }
! 1358:
! 1359: static void
! 1360: ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
! 1361: {
! 1362: struct route_node *rn;
! 1363: struct prefix_ipv4 p;
! 1364:
! 1365: p.family = AF_INET;
! 1366: p.prefix = nbr_nbma->addr;
! 1367: p.prefixlen = IPV4_MAX_BITLEN;
! 1368:
! 1369: rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
! 1370: if (rn)
! 1371: {
! 1372: ospf_nbr_nbma_free (rn->info);
! 1373: rn->info = NULL;
! 1374: route_unlock_node (rn);
! 1375: route_unlock_node (rn);
! 1376: }
! 1377: }
! 1378:
! 1379: static void
! 1380: ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
! 1381: {
! 1382: OSPF_TIMER_OFF (nbr_nbma->t_poll);
! 1383:
! 1384: if (nbr_nbma->nbr)
! 1385: {
! 1386: nbr_nbma->nbr->nbr_nbma = NULL;
! 1387: OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
! 1388: }
! 1389:
! 1390: if (nbr_nbma->oi)
! 1391: listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
! 1392: }
! 1393:
! 1394: static void
! 1395: ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
! 1396: struct ospf_interface *oi)
! 1397: {
! 1398: struct ospf_neighbor *nbr;
! 1399: struct route_node *rn;
! 1400: struct prefix p;
! 1401:
! 1402: if (oi->type != OSPF_IFTYPE_NBMA)
! 1403: return;
! 1404:
! 1405: if (nbr_nbma->nbr != NULL)
! 1406: return;
! 1407:
! 1408: if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
! 1409: return;
! 1410:
! 1411: nbr_nbma->oi = oi;
! 1412: listnode_add (oi->nbr_nbma, nbr_nbma);
! 1413:
! 1414: /* Get neighbor information from table. */
! 1415: p.family = AF_INET;
! 1416: p.prefixlen = IPV4_MAX_BITLEN;
! 1417: p.u.prefix4 = nbr_nbma->addr;
! 1418:
! 1419: rn = route_node_get (oi->nbrs, (struct prefix *)&p);
! 1420: if (rn->info)
! 1421: {
! 1422: nbr = rn->info;
! 1423: nbr->nbr_nbma = nbr_nbma;
! 1424: nbr_nbma->nbr = nbr;
! 1425:
! 1426: route_unlock_node (rn);
! 1427: }
! 1428: else
! 1429: {
! 1430: nbr = rn->info = ospf_nbr_new (oi);
! 1431: nbr->state = NSM_Down;
! 1432: nbr->src = nbr_nbma->addr;
! 1433: nbr->nbr_nbma = nbr_nbma;
! 1434: nbr->priority = nbr_nbma->priority;
! 1435: nbr->address = p;
! 1436:
! 1437: nbr_nbma->nbr = nbr;
! 1438:
! 1439: OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
! 1440: }
! 1441: }
! 1442:
! 1443: void
! 1444: ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi)
! 1445: {
! 1446: struct ospf_nbr_nbma *nbr_nbma;
! 1447: struct route_node *rn;
! 1448: struct prefix_ipv4 p;
! 1449:
! 1450: if (oi->type != OSPF_IFTYPE_NBMA)
! 1451: return;
! 1452:
! 1453: for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
! 1454: if ((nbr_nbma = rn->info))
! 1455: if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
! 1456: {
! 1457: p.family = AF_INET;
! 1458: p.prefix = nbr_nbma->addr;
! 1459: p.prefixlen = IPV4_MAX_BITLEN;
! 1460:
! 1461: if (prefix_match (oi->address, (struct prefix *)&p))
! 1462: ospf_nbr_nbma_add (nbr_nbma, oi);
! 1463: }
! 1464: }
! 1465:
! 1466: struct ospf_nbr_nbma *
! 1467: ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
! 1468: {
! 1469: struct route_node *rn;
! 1470: struct prefix_ipv4 p;
! 1471:
! 1472: p.family = AF_INET;
! 1473: p.prefix = nbr_addr;
! 1474: p.prefixlen = IPV4_MAX_BITLEN;
! 1475:
! 1476: rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
! 1477: if (rn)
! 1478: {
! 1479: route_unlock_node (rn);
! 1480: return rn->info;
! 1481: }
! 1482: return NULL;
! 1483: }
! 1484:
! 1485: struct ospf_nbr_nbma *
! 1486: ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first)
! 1487: {
! 1488: #if 0
! 1489: struct ospf_nbr_nbma *nbr_nbma;
! 1490: struct listnode *node;
! 1491: #endif
! 1492:
! 1493: if (ospf == NULL)
! 1494: return NULL;
! 1495:
! 1496: #if 0
! 1497: for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
! 1498: {
! 1499: if (first)
! 1500: {
! 1501: *addr = nbr_nbma->addr;
! 1502: return nbr_nbma;
! 1503: }
! 1504: else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
! 1505: {
! 1506: *addr = nbr_nbma->addr;
! 1507: return nbr_nbma;
! 1508: }
! 1509: }
! 1510: #endif
! 1511: return NULL;
! 1512: }
! 1513:
! 1514: int
! 1515: ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
! 1516: {
! 1517: struct ospf_nbr_nbma *nbr_nbma;
! 1518: struct ospf_interface *oi;
! 1519: struct prefix_ipv4 p;
! 1520: struct route_node *rn;
! 1521: struct listnode *node;
! 1522:
! 1523: nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
! 1524: if (nbr_nbma)
! 1525: return 0;
! 1526:
! 1527: nbr_nbma = ospf_nbr_nbma_new ();
! 1528: nbr_nbma->addr = nbr_addr;
! 1529:
! 1530: p.family = AF_INET;
! 1531: p.prefix = nbr_addr;
! 1532: p.prefixlen = IPV4_MAX_BITLEN;
! 1533:
! 1534: rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
! 1535: rn->info = nbr_nbma;
! 1536:
! 1537: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
! 1538: {
! 1539: if (oi->type == OSPF_IFTYPE_NBMA)
! 1540: if (prefix_match (oi->address, (struct prefix *)&p))
! 1541: {
! 1542: ospf_nbr_nbma_add (nbr_nbma, oi);
! 1543: break;
! 1544: }
! 1545: }
! 1546:
! 1547: return 1;
! 1548: }
! 1549:
! 1550: int
! 1551: ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
! 1552: {
! 1553: struct ospf_nbr_nbma *nbr_nbma;
! 1554:
! 1555: nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
! 1556: if (nbr_nbma == NULL)
! 1557: return 0;
! 1558:
! 1559: ospf_nbr_nbma_down (nbr_nbma);
! 1560: ospf_nbr_nbma_delete (ospf, nbr_nbma);
! 1561:
! 1562: return 1;
! 1563: }
! 1564:
! 1565: int
! 1566: ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
! 1567: u_char priority)
! 1568: {
! 1569: struct ospf_nbr_nbma *nbr_nbma;
! 1570:
! 1571: nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
! 1572: if (nbr_nbma == NULL)
! 1573: return 0;
! 1574:
! 1575: if (nbr_nbma->priority != priority)
! 1576: nbr_nbma->priority = priority;
! 1577:
! 1578: return 1;
! 1579: }
! 1580:
! 1581: int
! 1582: ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
! 1583: {
! 1584: struct ospf_nbr_nbma *nbr_nbma;
! 1585:
! 1586: nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
! 1587: if (nbr_nbma == NULL)
! 1588: return 0;
! 1589:
! 1590: if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
! 1591: nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
! 1592:
! 1593: return 1;
! 1594: }
! 1595:
! 1596: int
! 1597: ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
! 1598: unsigned int interval)
! 1599: {
! 1600: struct ospf_nbr_nbma *nbr_nbma;
! 1601:
! 1602: nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
! 1603: if (nbr_nbma == NULL)
! 1604: return 0;
! 1605:
! 1606: if (nbr_nbma->v_poll != interval)
! 1607: {
! 1608: nbr_nbma->v_poll = interval;
! 1609: if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
! 1610: {
! 1611: OSPF_TIMER_OFF (nbr_nbma->t_poll);
! 1612: OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
! 1613: nbr_nbma->v_poll);
! 1614: }
! 1615: }
! 1616:
! 1617: return 1;
! 1618: }
! 1619:
! 1620: int
! 1621: ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
! 1622: {
! 1623: struct ospf_nbr_nbma *nbr_nbma;
! 1624:
! 1625: nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
! 1626: if (nbr_nbma == NULL)
! 1627: return 0;
! 1628:
! 1629: if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
! 1630: nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
! 1631:
! 1632: return 1;
! 1633: }
! 1634:
! 1635: void
! 1636: ospf_master_init ()
! 1637: {
! 1638: memset (&ospf_master, 0, sizeof (struct ospf_master));
! 1639:
! 1640: om = &ospf_master;
! 1641: om->ospf = list_new ();
! 1642: om->master = thread_master_create ();
! 1643: om->start_time = quagga_time (NULL);
! 1644: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>