diff options
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/Makefile.am | 2 | ||||
-rw-r--r-- | ospfd/ospf_abr.c | 45 | ||||
-rw-r--r-- | ospfd/ospf_ase.c | 104 | ||||
-rw-r--r-- | ospfd/ospf_ase.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 42 | ||||
-rw-r--r-- | ospfd/ospf_interface.h | 11 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 24 | ||||
-rw-r--r-- | ospfd/ospf_main.c | 20 | ||||
-rw-r--r-- | ospfd/ospf_nsm.c | 24 | ||||
-rw-r--r-- | ospfd/ospf_nsm.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 117 | ||||
-rw-r--r-- | ospfd/ospf_packet.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_route.c | 67 | ||||
-rw-r--r-- | ospfd/ospf_route.h | 6 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 163 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 267 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 26 | ||||
-rw-r--r-- | ospfd/ospf_zebra.h | 2 | ||||
-rw-r--r-- | ospfd/ospfd.c | 281 | ||||
-rw-r--r-- | ospfd/ospfd.h | 13 |
20 files changed, 802 insertions, 417 deletions
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 2e4d5c8e..bed90d7b 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in. INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@ -DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" +DEFS = @DEFS@ $(LOCAL_OPTS) INSTALL_SDATA=@INSTALL@ -m 600 lib_LTLIBRARIES = libospf.la diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 7e32195b..def55f10 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -614,15 +614,6 @@ set_metric (struct ospf_lsa *lsa, u_int32_t metric) memcpy(header->metric, mp, 3); } -static int -ospf_abr_check_nssa_range (struct prefix_ipv4 *p, u_int32_t cost, - struct ospf_area *area) -{ - /* The Type-7 is tested against the aggregated prefix and forwarded - for lsa installation and flooding */ - return 0; -} - /* ospf_abr_translate_nssa */ static int ospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa) @@ -1578,42 +1569,6 @@ ospf_abr_send_nssa_aggregates (struct ospf *ospf) /* temporarily turned off */ } static void -ospf_abr_announce_nssa_defaults (struct ospf *ospf) /* By ABR-Translator */ -{ - struct listnode *node; - struct ospf_area *area; - - if (! IS_OSPF_ABR (ospf)) - return; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_stub_defaults(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): looking at area %s", - inet_ntoa (area->area_id)); - - if (area->external_routing != OSPF_AREA_NSSA) - continue; - - if (OSPF_IS_AREA_BACKBONE (area)) - continue; /* Sanity Check */ - - /* if (!TranslatorRole continue V 1.0 look for "always" conf */ - if (area->NSSATranslatorState) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): " - "announcing 0.0.0.0/0 to this nssa"); - /* ospf_abr_announce_nssa_asbr_to_as (&p, area->default_cost, area); */ - /*ospf_abr_announce_network_to_area (&p, area->default_cost, area);*/ - } - } -} - -static void ospf_abr_announce_stub_defaults (struct ospf *ospf) { struct listnode *node; diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 5d0cae42..c06f0178 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -31,6 +31,7 @@ #include "table.h" #include "vty.h" #include "log.h" +#include "workqueue.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -130,18 +131,6 @@ ospf_find_asbr_route_through_area (struct route_table *rtrs, return NULL; } -static void -ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop) -{ - struct listnode *node; - struct ospf_path *op; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op)) - if (op->nexthop.s_addr == 0) - op->nexthop.s_addr = nexthop.s_addr; -} - static int ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr) { @@ -284,8 +273,8 @@ ospf_ase_calculate_new_route (struct ospf_lsa *lsa, #define OSPF_ASE_CALC_INTERVAL 1 -int -ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) +static int +ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa *lsa) { u_int32_t metric; struct as_external_lsa *al; @@ -451,8 +440,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) /* if there is a Intra/Inter area route to the N do not install external route */ - if (rn = route_node_lookup (ospf->new_table, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_table, + (struct prefix *) &p))) { route_unlock_node(rn); if (rn->info == NULL) @@ -463,8 +452,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) } /* Find a route to the same dest */ /* If there is no route, create new one. */ - if (rn = route_node_lookup (ospf->new_external_route, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_external_route, + (struct prefix *) &p))) route_unlock_node(rn); if (!rn || (or = rn->info) == NULL) @@ -475,8 +464,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) ospf_route_add (ospf->new_external_route, &p, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); return 0; } else @@ -513,8 +500,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: New route is better"); ospf_route_subst (rn, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); + or = new; new = NULL; } @@ -531,8 +517,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: Routes are equal"); ospf_route_copy_nexthops (or, asbr_route->paths); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr); } } /* Make sure setting newly calculated ASBR route.*/ @@ -629,6 +613,50 @@ ospf_ase_compare_tables (struct route_table *new_external_route, return 0; } +static int ospf_ase_calculate_timer (struct thread *); + +static void ospf_ase_calc_completion (struct work_queue *wq) +{ + struct ospf *ospf = wq->spec.data; + + /* Compare old and new external routing table and install the + difference info zebra/kernel */ + ospf_ase_compare_tables (ospf->new_external_route, + ospf->old_external_route); + + /* Delete old external routing table */ + ospf_route_table_free (ospf->old_external_route); + ospf->old_external_route = ospf->new_external_route; + ospf->new_external_route = route_table_init (); + + /* another timer fired since, so another run might be needed */ + if (ospf->ase_calc && !ospf->t_ase_calc) + ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer, + ospf, 0); +} + +static wq_item_status +ospf_ase_calc_process (struct work_queue *wq, void *data) +{ + struct ospf_lsa *lsa = data; + ospf_ase_calculate_route (wq->spec.data, lsa); + ospf_lsa_unlock (&lsa); + return WQ_SUCCESS; +} + +static void +ospf_ase_calc_queue_init (struct ospf *ospf) +{ + ospf->ase_calc_queue = work_queue_new (master, "ase_calc_queue"); + + ospf->ase_calc_queue->spec.workfunc = &ospf_ase_calc_process; + ospf->ase_calc_queue->spec.completion_func = &ospf_ase_calc_completion; + + ospf->ase_calc_queue->spec.data = ospf; + ospf->ase_calc_queue->spec.max_retries = 0; + ospf->ase_calc_queue->spec.hold = 0; +} + static int ospf_ase_calculate_timer (struct thread *t) { @@ -645,9 +673,12 @@ ospf_ase_calculate_timer (struct thread *t) { ospf->ase_calc = 0; + if (!ospf->ase_calc_queue) + ospf_ase_calc_queue_init (ospf); + /* Calculate external route for each AS-external-LSA */ LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); /* This version simple adds to the table all NSSA areas */ if (ospf->anyNSSA) @@ -659,39 +690,22 @@ ospf_ase_calculate_timer (struct thread *t) if (area->external_routing == OSPF_AREA_NSSA) LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); } /* kevinm: And add the NSSA routes in ospf_top */ LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa) - ospf_ase_calculate_route(ospf,lsa); - - /* Compare old and new external routing table and install the - difference info zebra/kernel */ - ospf_ase_compare_tables (ospf->new_external_route, - ospf->old_external_route); - - /* Delete old external routing table */ - ospf_route_table_free (ospf->old_external_route); - ospf->old_external_route = ospf->new_external_route; - ospf->new_external_route = route_table_init (); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); } return 0; } void -ospf_ase_calculate_schedule (struct ospf *ospf) +ospf_ase_calculate_timer_add (struct ospf *ospf) { if (ospf == NULL) return; ospf->ase_calc = 1; -} - -void -ospf_ase_calculate_timer_add (struct ospf *ospf) -{ - if (ospf == NULL) - return; if (! ospf->t_ase_calc) ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer, diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h index e6a1b2fb..646a38c0 100644 --- a/ospfd/ospf_ase.h +++ b/ospfd/ospf_ase.h @@ -34,8 +34,6 @@ extern struct ospf_route *ospf_find_asbr_route_through_area (struct struct ospf_area *); -extern int ospf_ase_calculate_route (struct ospf *, struct ospf_lsa *); -extern void ospf_ase_calculate_schedule (struct ospf *); extern void ospf_ase_calculate_timer_add (struct ospf *); extern void ospf_ase_external_lsas_finish (struct route_table *); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 5c64ba29..33a83b4d 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -211,7 +211,9 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) } else return oi; - + + ospf_lsa_pos_set(-1,-1, oi); /* delete position in router LSA */ + /* Set zebra interface pointer. */ oi->ifp = ifp; oi->address = p; @@ -395,6 +397,29 @@ ospf_if_exists (struct ospf_interface *oic) return NULL; } +/* Lookup OSPF interface by router LSA posistion */ +struct ospf_interface * +ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end) + return oi; + } + return NULL; +} + +/* Set OSPF interface position in router LSA */ +void +ospf_lsa_pos_set(int pos_beg, int pos_end, struct ospf_interface *oi) +{ + oi->lsa_pos_beg = pos_beg; + oi->lsa_pos_end = pos_end; +} + struct ospf_interface * ospf_if_lookup_by_local_addr (struct ospf *ospf, struct interface *ifp, struct in_addr address) @@ -477,6 +502,20 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, return match; } + +struct ospf_interface * +ospf_if_lookup_by_ifindex(struct ospf_area *area, unsigned int ifindex) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (oi->ifp->ifindex == ifindex) + return oi; + } + return NULL; +} void ospf_if_stream_set (struct ospf_interface *oi) @@ -801,6 +840,7 @@ ospf_if_down (struct ospf_interface *oi) return 0; OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + ospf_lsa_pos_set(-1, -1, oi); /* delete position in router LSA */ /* Shutdown packet reception and sending */ ospf_if_stream_unset (oi); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 18b98cd0..82bf31a5 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -47,6 +47,7 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ + DECLARE_IF_PARAM (struct in_addr, if_area); /* Enable OSPF on this interface with area if_area */ DECLARE_IF_PARAM (u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 @@ -124,6 +125,10 @@ struct ospf_interface /* OSPF Area. */ struct ospf_area *area; +/* Position range in Router LSA */ + int lsa_pos_beg; /* inclusive, >= */ + int lsa_pos_end; /* exclusive, < */ + /* Interface data from zebra. */ struct interface *ifp; struct ospf_vl_data *vl_data; /* Data for Virtual Link */ @@ -242,6 +247,9 @@ extern int ospf_if_down (struct ospf_interface *); extern int ospf_if_is_up (struct ospf_interface *); extern struct ospf_interface *ospf_if_exists (struct ospf_interface *); +extern struct ospf_interface *ospf_if_lookup_by_lsa_pos (struct ospf_area *, + int); +extern void ospf_lsa_pos_set(int, int, struct ospf_interface *); extern struct ospf_interface *ospf_if_lookup_by_local_addr (struct ospf *, struct interface *, @@ -256,7 +264,8 @@ extern struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, struct interface *); extern struct ospf_interface *ospf_if_is_configured (struct ospf *, struct in_addr *); - +extern struct ospf_interface *ospf_if_lookup_by_ifindex(struct ospf_area *, + unsigned int); extern struct ospf_if_params *ospf_lookup_if_params (struct interface *, struct in_addr); extern struct ospf_if_params *ospf_get_if_params (struct interface *, diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 70504692..25bd754d 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -527,9 +527,16 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) { /* For unnumbered point-to-point networks, the Link Data field should specify the interface's MIB-II ifIndex value. */ - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + id.s_addr = htonl(oi->ifp->ifindex); + else + id = oi->address->u.prefix4; + + links += link_info_set (s, nbr->router_id, id, LSA_LINK_TYPE_POINTOPOINT, 0, cost); } + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + return links; /* Regardless of the state of the neighboring router, we must add a Type 3 link (stub network). @@ -651,9 +658,11 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) static int router_lsa_link_set (struct stream *s, struct ospf_area *area) { + struct ospf_host_route *host; + struct in_addr host_mask = {~0}; /* All ones */ struct listnode *node; struct ospf_interface *oi; - int links = 0; + int links = 0, old_links; for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) { @@ -664,6 +673,7 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) { if (oi->state != ISM_Down) { + old_links = links; /* Describe each link. */ switch (oi->type) { @@ -685,10 +695,14 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) case OSPF_IFTYPE_LOOPBACK: links += lsa_link_loopback_set (s, oi); } + ospf_lsa_pos_set(old_links, links, oi); } } } - + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (host->area == NULL || host->area == area) + links += link_info_set (s, host->host_addr, host_mask, + LSA_LINK_TYPE_STUB, 0, host->cost); return links; } @@ -2900,6 +2914,10 @@ ospf_maxage_lsa_remover (struct thread *thread) continue; } + /* TODO: maybe convert this function to a work-queue */ + if (thread_should_yield (thread)) + OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0); + /* Remove LSA from the LSDB */ if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)) if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 8b9a3458..0e9e182a 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -38,6 +38,7 @@ #include "memory.h" #include "privs.h" #include "sigevent.h" +#include "paths.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -72,12 +73,13 @@ struct zebra_privs_t ospfd_privs = }; /* Configuration filename and directory. */ -char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG; +char config_default[MAXPATHLEN]; /* OSPFd options. */ struct option longopts[] = { { "daemon", no_argument, NULL, 'd'}, + { "namespace", required_argument, NULL, 'N'}, { "config_file", required_argument, NULL, 'f'}, { "pid_file", required_argument, NULL, 'i'}, { "dryrun", no_argument, NULL, 'C'}, @@ -96,8 +98,11 @@ struct option longopts[] = /* Master of threads. */ struct thread_master *master; +/* pid_file default value */ +static char pid_file_default[MAXPATHLEN]; + /* Process ID saved for use by init system */ -const char *pid_file = PATH_OSPFD_PID; +const char *pid_file = pid_file_default; #ifdef SUPPORT_OSPF_API extern int ospf_apiserver_enable; @@ -114,6 +119,7 @@ usage (char *progname, int status) printf ("Usage : %s [OPTION...]\n\ Daemon which manages OSPF.\n\n\ -d, --daemon Runs in daemon mode\n\ +-N, --namespace Insert argument into all paths\n\ -f, --config_file Set configuration file name\n\ -i, --pid_file Set process identifier file name\n\ -A, --vty_addr Set vty's bind address\n\ @@ -214,7 +220,7 @@ main (int argc, char **argv) { int opt; - opt = getopt_long (argc, argv, "df:i:hA:P:u:g:avC", longopts, 0); + opt = getopt_long (argc, argv, "dN:f:i:hA:P:u:g:avC", longopts, 0); if (opt == EOF) break; @@ -226,6 +232,9 @@ main (int argc, char **argv) case 'd': daemon_mode = 1; break; + case 'N': + path_set_namespace (optarg); + break; case 'f': config_file = optarg; break; @@ -274,6 +283,9 @@ main (int argc, char **argv) } } + strcpy (config_default, path_config (OSPF_CONFIG_NAME)); + strcpy (pid_file_default, path_state (OSPF_PID_NAME)); + /* Initializations. */ master = om->master; @@ -324,7 +336,7 @@ main (int argc, char **argv) pid_output (pid_file); /* Create VTY socket */ - vty_serv_sock (vty_addr, vty_port, OSPF_VTYSH_PATH); + vty_serv_sock (vty_addr, vty_port, path_state (OSPF_VTY_NAME)); /* Print banner. */ zlog_notice ("OSPFd %s starting: vty@%d", QUAGGA_VERSION, vty_port); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index b15efbd6..26e32d9b 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -162,7 +162,7 @@ nsm_should_adj (struct ospf_neighbor *nbr) /* OSPF NSM functions. */ static int -nsm_hello_received (struct ospf_neighbor *nbr) +nsm_packet_received (struct ospf_neighbor *nbr) { /* Start or Restart Inactivity Timer. */ OSPF_NSM_TIMER_OFF (nbr->t_inactivity); @@ -408,7 +408,7 @@ struct { { /* DependUpon: dummy state. */ { NULL, NSM_DependUpon }, /* NoEvent */ - { NULL, NSM_DependUpon }, /* HelloReceived */ + { NULL, NSM_DependUpon }, /* PacketReceived */ { NULL, NSM_DependUpon }, /* Start */ { NULL, NSM_DependUpon }, /* 2-WayReceived */ { NULL, NSM_DependUpon }, /* NegotiationDone */ @@ -425,7 +425,7 @@ struct { { /* Deleted: dummy state. */ { NULL, NSM_Deleted }, /* NoEvent */ - { NULL, NSM_Deleted }, /* HelloReceived */ + { NULL, NSM_Deleted }, /* PacketReceived */ { NULL, NSM_Deleted }, /* Start */ { NULL, NSM_Deleted }, /* 2-WayReceived */ { NULL, NSM_Deleted }, /* NegotiationDone */ @@ -442,7 +442,7 @@ struct { { /* Down: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { nsm_start, NSM_Attempt }, /* Start */ { NULL, NSM_Down }, /* 2-WayReceived */ { NULL, NSM_Down }, /* NegotiationDone */ @@ -459,7 +459,7 @@ struct { { /* Attempt: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { NULL, NSM_Attempt }, /* Start */ { NULL, NSM_Attempt }, /* 2-WayReceived */ { NULL, NSM_Attempt }, /* NegotiationDone */ @@ -476,7 +476,7 @@ struct { { /* Init: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { NULL, NSM_Init }, /* Start */ { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ { NULL, NSM_Init }, /* NegotiationDone */ @@ -493,7 +493,7 @@ struct { { /* 2-Way: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_TwoWay }, /* HelloReceived */ + { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */ { NULL, NSM_TwoWay }, /* Start */ { NULL, NSM_TwoWay }, /* 2-WayReceived */ { NULL, NSM_TwoWay }, /* NegotiationDone */ @@ -510,7 +510,7 @@ struct { { /* ExStart: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_ExStart }, /* HelloReceived */ + { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */ { NULL, NSM_ExStart }, /* Start */ { NULL, NSM_ExStart }, /* 2-WayReceived */ { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ @@ -527,7 +527,7 @@ struct { { /* Exchange: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Exchange }, /* HelloReceived */ + { nsm_packet_received, NSM_Exchange }, /* PacketReceived */ { NULL, NSM_Exchange }, /* Start */ { NULL, NSM_Exchange }, /* 2-WayReceived */ { NULL, NSM_Exchange }, /* NegotiationDone */ @@ -544,7 +544,7 @@ struct { { /* Loading: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Loading }, /* HelloReceived */ + { nsm_packet_received, NSM_Loading }, /* PacketReceived */ { NULL, NSM_Loading }, /* Start */ { NULL, NSM_Loading }, /* 2-WayReceived */ { NULL, NSM_Loading }, /* NegotiationDone */ @@ -560,7 +560,7 @@ struct { }, { /* Full: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Full }, /* HelloReceived */ + { nsm_packet_received, NSM_Full }, /* PacketReceived */ { NULL, NSM_Full }, /* Start */ { NULL, NSM_Full }, /* 2-WayReceived */ { NULL, NSM_Full }, /* NegotiationDone */ @@ -579,7 +579,7 @@ struct { static const char *ospf_nsm_event_str[] = { "NoEvent", - "HelloReceived", + "PacketReceived", "Start", "2-WayReceived", "NegotiationDone", diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 1121dae6..4f2ae808 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -39,7 +39,7 @@ /* OSPF Neighbor State Machine Event. */ #define NSM_NoEvent 0 -#define NSM_HelloReceived 1 +#define NSM_PacketReceived 1 /* HelloReceived in the protocol */ #define NSM_Start 2 #define NSM_TwoWayReceived 3 #define NSM_NegotiationDone 4 diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index bc00def4..c4a6bf92 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op) fifo->count++; } +/* Add new packet to head of fifo. */ +static void +ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op) +{ + op->next = fifo->head; + + if (fifo->tail == NULL) + fifo->tail = op; + + fifo->head = op; + + fifo->count++; +} + /* Delete first packet from fifo. */ struct ospf_packet * ospf_fifo_pop (struct ospf_fifo *fifo) @@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op) /* ospf_fifo_debug (oi->obuf); */ } +static void +ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op) +{ + if (!oi->obuf) + { + zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, " + "destination %s) called with NULL obuf, ignoring " + "(please report this bug)!\n", + IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state), + ospf_packet_type_str[stream_getc_from(op->s, 1)], + inet_ntoa (op->dst)); + return; + } + + /* Add packet to head of queue. */ + ospf_fifo_push_head (oi->obuf, op); + + /* Debug of packet fifo*/ + /* ospf_fifo_debug (oi->obuf); */ +} + void ospf_packet_delete (struct ospf_interface *oi) { @@ -324,7 +359,7 @@ static int ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) { struct ospf_header *ospfh; - unsigned char digest[OSPF_AUTH_MD5_SIZE]; + unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; MD5_CTX ctx; void *ibuf; u_int32_t t; @@ -351,7 +386,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) /* Get MD5 Authentication key from auth_key list. */ if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - auth_key = (const u_int8_t *) ""; + auth_key = (const u_int8_t *) digest; else { ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); @@ -875,7 +910,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, old_state = nbr->state; /* Add event to thread. */ - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); /* RFC2328 Section 9.5.1 If the router is not eligible to become Designated Router, @@ -895,19 +930,19 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, if (oi->type == OSPF_IFTYPE_NBMA && (old_state == NSM_Down || old_state == NSM_Attempt)) { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); goto done; } if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors, size - OSPF_HELLO_MIN_SIZE)) { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived); nbr->options |= hello->options; } else { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); goto done; } @@ -1190,6 +1225,9 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } #endif /* HAVE_OPAQUE_LSA */ + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Process DD packet by neighbor status. */ switch (nbr->state) { @@ -1411,6 +1449,9 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Neighbor State should be Exchange or later. */ if (nbr->state != NSM_Exchange && nbr->state != NSM_Loading && @@ -1643,6 +1684,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Check neighbor state. */ if (nbr->state < NSM_Exchange) { @@ -1976,6 +2020,9 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + if (nbr->state < NSM_Exchange) { zlog_warn ("Link State Acknowledgment: " @@ -2953,8 +3000,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) return length; } -void -ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr) +static void +ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr) { struct ospf_packet *op; u_int16_t length = OSPF_HEADER_SIZE; @@ -2973,10 +3020,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr) /* Set packet length. */ op->length = length; - op->dst.s_addr = addr->s_addr; + op->dst.s_addr = addr; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); + /* Add packet to the top of the interface output queue, so that they + * can't get delayed by things like long queues of LS Update packets + */ + ospf_packet_add_top (oi, op); /* Hook thread to write packet. */ OSPF_ISM_WRITE_ON (oi->ospf); @@ -3007,7 +3056,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma) && oi->state != ISM_DR && oi->state != ISM_Backup) return; - ospf_hello_send_sub (oi, &nbr_nbma->addr); + ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr); } int @@ -3046,7 +3095,7 @@ ospf_hello_reply_timer (struct thread *thread) zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); - ospf_hello_send_sub (nbr->oi, &nbr->src); + ospf_hello_send_sub (nbr->oi, nbr->src.s_addr); return 0; } @@ -3055,27 +3104,10 @@ ospf_hello_reply_timer (struct thread *thread) void ospf_hello_send (struct ospf_interface *oi) { - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; - /* If this is passive interface, do not send OSPF Hello. */ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) return; - op = ospf_packet_new (oi->ifp->mtu); - - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_HELLO, oi, op->s); - - /* Prepare OSPF Hello body. */ - length += ospf_make_hello (oi, op->s); - - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); - - /* Set packet length. */ - op->length = length; - if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_neighbor *nbr; @@ -3104,33 +3136,16 @@ ospf_hello_send (struct ospf_interface *oi) if (nbr->priority == 0 && oi->state == ISM_DROther) continue; /* if oi->state == Waiting, send hello to all neighbors */ - { - struct ospf_packet *op_dup; - - op_dup = ospf_packet_dup(op); - op_dup->dst = nbr->src; - - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op_dup); - - OSPF_ISM_WRITE_ON (oi->ospf); - } + ospf_hello_send_sub (oi, nbr->src.s_addr); } - ospf_packet_free (op); } else { /* Decide destination address. */ if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - op->dst.s_addr = oi->vl_data->peer_addr.s_addr; - else - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); - - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr); + else + ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS)); } } diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h index 7b3d6866..9a472081 100644 --- a/ospfd/ospf_packet.h +++ b/ospfd/ospf_packet.h @@ -162,6 +162,5 @@ extern int ospf_ls_upd_timer (struct thread *); extern int ospf_ls_ack_timer (struct thread *); extern int ospf_poll_timer (struct thread *); extern int ospf_hello_reply_timer (struct thread *); -extern void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *); #endif /* _ZEBRA_OSPF_PACKET_H */ diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 267237b8..10608f50 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -272,61 +272,6 @@ ospf_route_install (struct ospf *ospf, struct route_table *rt) } } -static void -ospf_intra_route_add (struct route_table *rt, struct vertex *v, - struct ospf_area *area) -{ - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct ospf_path *path; - struct vertex_parent *parent; - struct listnode *node, *nnode; - - p.family = AF_INET; - p.prefix = v->id; - if (v->type == OSPF_VERTEX_ROUTER) - p.prefixlen = IPV4_MAX_BITLEN; - else - { - struct network_lsa *lsa = (struct network_lsa *) v->lsa; - p.prefixlen = ip_masklen (lsa->mask); - } - apply_mask_ipv4 (&p); - - rn = route_node_get (rt, (struct prefix *) &p); - if (rn->info) - { - zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id)); - route_unlock_node (rn); - return; - } - - or = ospf_route_new (); - - if (v->type == OSPF_VERTEX_NETWORK) - { - or->type = OSPF_DESTINATION_NETWORK; - - for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent)) - { - path = ospf_path_new (); - path->nexthop = parent->nexthop->router; - listnode_add (or->paths, path); - } - } - else - or->type = OSPF_DESTINATION_ROUTER; - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing= area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = v->distance; - - rn->info = or; -} - /* RFC2328 16.1. (4). For "router". */ void ospf_intra_add_router (struct route_table *rt, struct vertex *v, @@ -810,12 +755,18 @@ ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, { nexthop = vp->nexthop; - if (nexthop->oi != NULL) + if (nexthop->oi != NULL) { - if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) + if (!ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) { path = ospf_path_new (); - path->nexthop = nexthop->router; + + /* PtoP I/F's are always directly connected */ + if (if_is_pointopoint (nexthop->oi->ifp)) + path->nexthop.s_addr = INADDR_ANY; + else + path->nexthop = nexthop->router; + path->ifindex = nexthop->oi->ifp->ifindex; listnode_add (to->paths, path); } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 17ab68e5..5483aaf5 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -121,6 +121,12 @@ struct ospf_route } u; }; +struct ospf_host_route { + struct in_addr host_addr; + u_int32_t cost; /* i.e. metric. */ + struct ospf_area *area; /* NULL == all areas */ +}; + extern struct ospf_path *ospf_path_new (void); extern void ospf_path_free (struct ospf_path *); extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index ca200222..b06c7b9e 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -480,13 +480,15 @@ ospf_spf_add_parent (struct vertex *v, struct vertex *w, static unsigned int ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, struct vertex *w, struct router_lsa_link *l, - unsigned int distance) + unsigned int distance, int lsa_pos) { struct listnode *node, *nnode; struct vertex_nexthop *nh; struct vertex_parent *vp; struct ospf_interface *oi = NULL; unsigned int added = 0; + char buf1[BUFSIZ]; + char buf2[BUFSIZ]; if (IS_DEBUG_OSPF_EVENT) { @@ -505,30 +507,38 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, the OSPF interface connecting to the destination network/router. */ + /* we *must* be supplied with the link data */ + assert (l != NULL); + oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos); + if (!oi) + { + zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s", + __func__, lsa_pos, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + { + zlog_debug("%s: considering link:%s " + "type:%d link_id:%s link_data:%s", + __func__, oi->ifp->name, l->m[0].type, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + } + if (w->type == OSPF_VERTEX_ROUTER) { /* l is a link from v to w * l2 will be link from w to v */ struct router_lsa_link *l2 = NULL; - - /* we *must* be supplied with the link data */ - assert (l != NULL); - - if (IS_DEBUG_OSPF_EVENT) - { - char buf1[BUFSIZ]; - char buf2[BUFSIZ]; - - zlog_debug("ospf_nexthop_calculation(): considering link " - "type %d link_id %s link_data %s", - l->m[0].type, - inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), - inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); - } if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) { + struct in_addr nexthop; + /* If the destination is a router which connects to the calculating router via a Point-to-MultiPoint network, the destination's next hop IP address(es) @@ -539,68 +549,53 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, provides an IP address of the next hop router. At this point l is a link from V to W, and V is the - root ("us"). Find the local interface associated - with l (its address is in l->link_data). If it - is a point-to-multipoint interface, then look through - the links in the opposite direction (W to V). If - any of them have an address that lands within the + root ("us"). If it is a point-to-multipoint interface, + then look through the links in the opposite direction (W to V). + If any of them have an address that lands within the subnet declared by the PtMP link, then that link - is a constituent of the PtMP link, and its address is + is a constituent of the PtMP link, and its address is a nexthop address for V. */ - oi = ospf_if_is_configured (area->ospf, &l->link_data); - if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - { - struct prefix_ipv4 la; - - la.family = AF_INET; - la.prefixlen = oi->address->prefixlen; - - /* V links to W on PtMP interface - - find the interface address on W */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - la.prefix = l2->link_data; - - if (prefix_cmp ((struct prefix *) &la, - oi->address) == 0) - /* link_data is on our PtMP network */ - break; - } - } /* end l is on point-to-multipoint link */ - else - { - /* l is a regular point-to-point link. - Look for a link from W to V. - */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - oi = ospf_if_is_configured (area->ospf, - &(l2->link_data)); - - if (oi == NULL) - continue; - - if (!IPV4_ADDR_SAME (&oi->address->u.prefix4, - &l->link_data)) - continue; - - break; - } - } - - if (oi && l2) + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + { + added = 1; + nexthop.s_addr = 0; /* Nexthop not required */ + } + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + { + struct prefix_ipv4 la; + + la.family = AF_INET; + la.prefixlen = oi->address->prefixlen; + + /* V links to W on PtMP interface + - find the interface address on W */ + while ((l2 = ospf_get_next_link (w, v, l2))) + { + la.prefix = l2->link_data; + + if (prefix_cmp ((struct prefix *) &la, + oi->address) != 0) + continue; + /* link_data is on our PtMP network */ + added = 1; + nexthop = l2->link_data; + break; + } + } + + if (added) { /* found all necessary info to build nexthop */ nh = vertex_nexthop_new (); nh->oi = oi; - nh->router = l2->link_data; + nh->router = nexthop; ospf_spf_add_parent (v, w, nh, distance); return 1; } else - zlog_info("ospf_nexthop_calculation(): " - "could not determine nexthop for link"); + zlog_info("%s: could not determine nexthop for link %s", + __func__, oi->ifp->name); } /* end point-to-point link from V to W */ else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) { @@ -633,19 +628,13 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, else { assert(w->type == OSPF_VERTEX_NETWORK); - oi = ospf_if_is_configured (area->ospf, &(l->link_data)); - if (oi) - { - nh = vertex_nexthop_new (); - nh->oi = oi; - nh->router.s_addr = 0; - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } + + nh = vertex_nexthop_new (); + nh->oi = oi; + nh->router.s_addr = 0; /* Nexthop not required */ + ospf_spf_add_parent (v, w, nh, distance); + return 1; } - zlog_info("ospf_nexthop_calculation(): " - "Unknown attached link"); - return 0; } /* end V is the root */ /* Check if W's parent is a network connected to root. */ else if (v->type == OSPF_VERTEX_NETWORK) @@ -726,7 +715,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, u_char *lim; struct router_lsa_link *l = NULL; struct in_addr *r; - int type = 0; + int type = 0, lsa_pos=-1, lsa_pos_next=0; /* If this is a router-LSA, and bit V of the router-LSA (see Section A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */ @@ -754,7 +743,8 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, if (v->lsa->type == OSPF_ROUTER_LSA) { l = (struct router_lsa_link *) p; - + lsa_pos = lsa_pos_next; /* LSA link position */ + lsa_pos_next++; p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); @@ -876,7 +866,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, w = ospf_vertex_new (w_lsa); /* Calculate nexthop to W. */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) pqueue_enqueue (w, candidate); else if (IS_DEBUG_OSPF_EVENT) zlog_debug ("Nexthop Calc failed"); @@ -896,7 +886,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, { /* Found an equal-cost path to W. * Calculate nexthop of to W from V. */ - ospf_nexthop_calculation (area, v, w, l, distance); + ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos); } /* less than. */ else @@ -906,7 +896,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, * valid nexthop it will call spf_add_parents, which * will flush the old parents */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) /* Decrease the key of the node in the heap. * trickle-sort it up towards root, just in case this * node should now be the new root due the cost change. @@ -1045,6 +1035,7 @@ ospf_rtrs_free (struct route_table *rtrs) route_table_finish (rtrs); } +#if 0 static void ospf_rtrs_print (struct route_table *rtrs) { @@ -1104,6 +1095,7 @@ ospf_rtrs_print (struct route_table *rtrs) zlog_debug ("ospf_rtrs_print() end"); } +#endif /* Calculating the shortest-path tree for an area. */ static void @@ -1269,9 +1261,6 @@ ospf_spf_calculate_timer (struct thread *thread) /* If new Router Route is installed, then schedule re-calculate External routes. */ - if (1) - ospf_ase_calculate_schedule (ospf); - ospf_ase_calculate_timer_add (ospf); /* Update routing table. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index a3c39447..01e85c71 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -93,29 +93,6 @@ ospf_str2area_id (const char *str, struct in_addr *area_id, int *format) static int -str2distribute_source (const char *str, int *source) -{ - /* Sanity check. */ - if (str == NULL) - return 0; - - if (strncmp (str, "k", 1) == 0) - *source = ZEBRA_ROUTE_KERNEL; - else if (strncmp (str, "c", 1) == 0) - *source = ZEBRA_ROUTE_CONNECT; - else if (strncmp (str, "s", 1) == 0) - *source = ZEBRA_ROUTE_STATIC; - else if (strncmp (str, "r", 1) == 0) - *source = ZEBRA_ROUTE_RIP; - else if (strncmp (str, "b", 1) == 0) - *source = ZEBRA_ROUTE_BGP; - else - return 0; - - return 1; -} - -static int str2metric (const char *str, int *metric) { /* Sanity check. */ @@ -2862,6 +2839,9 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Internet Address %s/%d,", inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); + vty_out(vty, " Unnumbered: %s,", + CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED) ? "YES" : "NO"); + if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) { struct in_addr *dest; @@ -3751,7 +3731,7 @@ show_as_external_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) return 0; } -/* N.B. This function currently seems to be unused. */ +#if 0 static int show_as_external_lsa_stdvty (struct ospf_lsa *lsa) { @@ -3775,6 +3755,7 @@ show_as_external_lsa_stdvty (struct ospf_lsa *lsa) return 0; } +#endif /* Show AS-NSSA-LSA detail information. */ static int @@ -5792,6 +5773,71 @@ ALIAS (no_ip_ospf_transmit_delay, "OSPF interface commands\n" "Link state transmit delay\n") +DEFUN (ip_ospf_area, + ip_ospf_area_cmd, + "ip ospf area (A.B.C.D|<0-4294967295>)", + "IP Information\n" + "OSPF interface commands\n" + "Enable OSPF on this interface\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n") +{ + struct interface *ifp = vty->index; + int format, ret; + struct in_addr area_id; + struct ospf *ospf; + struct ospf_if_params *params; + + ret = ospf_str2area_id (argv[0], &area_id, &format); + + if (ret < 0) + { + vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s", + VTY_NEWLINE); + return CMD_WARNING; + } + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + { + vty_out (vty, "There is already a interface statement.%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (memcmp (ifp->name, "VLINK", 5) == 0) + { + vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + SET_IF_PARAM (params, if_area); + params->if_area = area_id; + ospf_interface_set (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_area, + no_ip_ospf_area_cmd, + "no ip ospf area", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disable OSPF on this interface\n") +{ + struct interface *ifp = vty->index; + struct ospf *ospf; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS (ifp); + if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) + return CMD_SUCCESS; + + UNSET_IF_PARAM (params, if_area); + + ospf_interface_unset (ifp); + return CMD_SUCCESS; +} + + DEFUN (ospf_redistribute_source_metric_type, ospf_redistribute_source_metric_type_routemap_cmd, @@ -5813,7 +5859,8 @@ DEFUN (ospf_redistribute_source_metric_type, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5874,7 +5921,8 @@ DEFUN (ospf_redistribute_source_type_metric, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5938,7 +5986,8 @@ DEFUN (ospf_redistribute_source_metric_routemap, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5971,7 +6020,8 @@ DEFUN (ospf_redistribute_source_type_routemap, int type = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5999,7 +6049,8 @@ DEFUN (ospf_redistribute_source_routemap, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; if (argc == 2) @@ -6020,7 +6071,8 @@ DEFUN (no_ospf_redistribute_source, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; ospf_routemap_unset (ospf, source); @@ -6039,7 +6091,8 @@ DEFUN (ospf_distribute_list_out, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_set (ospf, source, argv[0]); @@ -6057,7 +6110,8 @@ DEFUN (no_ospf_distribute_list_out, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_unset (ospf, source, argv[0]); @@ -7384,6 +7438,123 @@ DEFUN (show_ip_ospf_route, return CMD_SUCCESS; } +DEFUN (ip_ospf_host, + ip_ospf_host_cmd, + "ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>", + "OSPF specific commands\n" + "Add a host route to OPSF\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + u_int32_t cost; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + cost = strtol (argv[2], NULL, 10); + /* cost range is <0-65535>. */ + if (cost < 0 || cost > 65535) + { + vty_out (vty, "cost is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); /* returns if error */ + area = ospf_area_get (ospf, area_id, format); + } + + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (!node) + { + host = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf_host_route)); + listnode_add (ospf->hostlist, host); + } + host->host_addr = host_addr; + host->cost = cost; + host->area = area; + + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_host, + no_ip_ospf_host_cmd, + "no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)", + NO_STR + "OSPF specific commands\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); + area = ospf_area_get (ospf, area_id, format); + } + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (node) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + } + return CMD_SUCCESS; +} + const char *ospf_abr_type_str[] = { @@ -7591,6 +7762,14 @@ config_write_interface (struct vty *vty) vty_out (vty, "%s", VTY_NEWLINE); } + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) + { + vty_out (vty, " ip ospf area %s%s", + inet_ntoa (params->if_area), + VTY_NEWLINE); + } + /* MTU ignore print. */ if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) && params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) @@ -7965,6 +8144,7 @@ ospf_config_write (struct vty *vty) struct interface *ifp; struct ospf_interface *oi; struct listnode *node; + struct ospf_host_route *host; int write = 0; ospf = ospf_lookup (); @@ -8032,7 +8212,20 @@ ospf_config_write (struct vty *vty) /* passive-interface print. */ if (ospf->passive_interface_default == OSPF_IF_PASSIVE) vty_out (vty, " passive-interface default%s", VTY_NEWLINE); - + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + { + char buf[28]; + + if (host->area) + area_id2str(buf, sizeof(buf), host->area); + else + strcpy(buf, "all"); + vty_out (vty, " ip ospf host %s area %s cost %d%s", + inet_ntoa (host->host_addr), + buf, host->cost, VTY_NEWLINE); + } + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface) && IF_DEF_PARAMS (ifp)->passive_interface != @@ -8232,6 +8425,10 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd); + /* "ip ospf area" commands. */ + install_element (INTERFACE_NODE, &ip_ospf_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); + /* These commands are compatibitliy for previous version. */ install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd); @@ -8518,6 +8715,10 @@ ospf_vty_init (void) install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); + /* "ip ospf host" commands. */ + install_element (OSPF_NODE, &ip_ospf_host_cmd); + install_element (OSPF_NODE, &no_ip_ospf_host_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 6f0a71ff..484aba98 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -133,8 +133,9 @@ ospf_interface_delete (int command, struct zclient *zclient, if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug - ("Zebra: interface delete %s index %d flags %lld metric %d mtu %d", - ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); + ("Zebra: interface delete %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, + ifp->metric, ifp->mtu); #ifdef HAVE_SNMP ospf_snmp_if_delete (ifp); @@ -195,6 +196,17 @@ ospf_interface_state_up (int command, struct zclient *zclient, ospf_if_recalculate_output_cost (ifp); } + if (CHECK_FLAG(if_tmp.status ^ ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + { + if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) + zlog_debug ("Zebra: Interface[%s] Unnumbered state change %d -> %d.", + ifp->name, + if_tmp.status & ZEBRA_INTERFACE_UNNUMBERED, + ifp->status & ZEBRA_INTERFACE_UNNUMBERED); + + ospf_if_reset (ifp); + } + if (if_tmp.mtu != ifp->mtu) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) @@ -481,9 +493,9 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; @@ -503,9 +515,9 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; @@ -964,7 +976,7 @@ ospf_distribute_list_update_timer (struct thread *thread) /* Update distribute-list and set timer to apply access-list. */ void -ospf_distribute_list_update (struct ospf *ospf, int type) +ospf_distribute_list_update (struct ospf *ospf, unsigned long type) { struct route_table *rt; diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 3efd8958..b6419c8b 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -56,7 +56,7 @@ extern int ospf_redistribute_check (struct ospf *, struct external_info *, int *); extern int ospf_distribute_check_connected (struct ospf *, struct external_info *); -extern void ospf_distribute_list_update (struct ospf *, int); +extern void ospf_distribute_list_update (struct ospf *, unsigned long); extern int ospf_is_type_redistributed (int); extern void ospf_distance_reset (struct ospf *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 1f32a484..35c6b02b 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -231,7 +231,7 @@ ospf_new (void) } new->t_read = thread_add_read (master, ospf_read, new, new->fd); new->oi_write_q = list_new (); - + new->hostlist = list_new(); /* host route list */ return new; } @@ -401,6 +401,7 @@ ospf_finish_final (struct ospf *ospf) struct ospf_lsa *lsa; struct ospf_interface *oi; struct ospf_area *area; + struct ospf_host_route *host; struct ospf_vl_data *vl_data; struct listnode *node, *nnode; int i; @@ -471,6 +472,12 @@ ospf_finish_final (struct ospf *ospf) ospf_area_free (area); } + for (ALL_LIST_ELEMENTS (ospf->hostlist, node, nnode, host)) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + } + /* Cancel all timers. */ OSPF_TIMER_OFF (ospf->t_external_lsa); OSPF_TIMER_OFF (ospf->t_router_lsa_update); @@ -646,8 +653,32 @@ ospf_area_free (struct ospf_area *area) void ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) { + struct interface *ifp; + struct listnode *node; + struct ospf_if_params *params; + struct route_node *rn; + struct ospf_network *network; + struct ospf_host_route *host; struct ospf_area *area; + /* Check if any interface is a member of this area */ + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) + { + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area) + && IPV4_ADDR_SAME (&area_id, ¶ms->if_area)) + return; + } + /* Check if any network is a member of this area */ + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + { + network = rn->info; + if (network && IPV4_ADDR_SAME (&area_id, &network->area_id)) + { + route_unlock_node (rn); + return; + } + } area = ospf_area_lookup_by_area_id (ospf, area_id); if (area && listcount (area->oiflist) == 0 && @@ -660,6 +691,9 @@ ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) IMPORT_NAME (area) == NULL && area->auth_type == OSPF_AUTH_NULL) { + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (!host->area || host->area == area) + return; listnode_delete (ospf->areas, area); ospf_area_free (area); } @@ -701,6 +735,67 @@ ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi) listnode_add (area->oiflist, oi); } +void add_ospf_interface(struct interface *ifp, struct ospf_area *area, + struct connected *co) +{ + struct ospf_interface *oi; + + oi = ospf_if_new (area->ospf, ifp, co->address); + oi->connected = co; + + oi->area = area; + + oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); + oi->output_cost = ospf_if_get_output_cost (oi); + + /* Add pseudo neighbor. */ + ospf_nbr_add_self (oi); + + /* Relate ospf interface to ospf instance. */ + oi->ospf = area->ospf; + + /* update network type as interface flag */ + /* If network type is specified previously, + skip network type setting. */ + oi->type = IF_DEF_PARAMS (ifp)->type; + + ospf_area_add_if (oi->area, oi); + + /* if router_id is not configured, dont bring up + * interfaces. + * ospf_router_id_update() will call ospf_if_update + * whenever r-id is configured instead. + */ + if ((area->ospf->router_id.s_addr != 0) + && if_is_operative (ifp)) + ospf_if_up (oi); +} + +void update_redistributed(struct ospf *ospf, int add_to_ospf) +{ + struct route_node *rn; + struct external_info *ei; + + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) + if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) + for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); + rn; rn = route_next (rn)) + if ((ei = rn->info) != NULL) + if (add_to_ospf) + { + if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (!ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_flush (ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + } + else + { + if (!ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_originate (ospf, ei); + } +} + void ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) { @@ -754,16 +849,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - + update_redistributed(ospf, 1); /* interfaces possibly added */ ospf_area_check_free (ospf, area_id); return 1; @@ -795,12 +881,17 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, /* Find interfaces that not configured already. */ for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) { + struct ospf_if_params *params; int found = 0; struct connected *co = oi->connected; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - + continue; + + params = IF_DEF_PARAMS (oi->ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + continue; + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) { if (rn->info == NULL) @@ -819,18 +910,103 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, } /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); + update_redistributed(ospf, 0); /* interfaces possibly removed */ + return 1; +} + +int +ospf_interface_set (struct interface *ifp) +{ + struct ospf_area *area; + struct route_node *rn; + struct external_info *ei; + struct listnode *cnode; + struct connected *co; + struct ospf *ospf; + struct ospf_if_params *params; + struct in_addr area_id; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + params = IF_DEF_PARAMS (ifp); + area_id = params->if_area; + + area = ospf_area_get (ospf, area_id, ret); + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) + { + struct ospf_interface *oi; + + if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) + continue; + + oi = ospf_if_table_lookup(ifp, co->address); + if (oi) + { /* Just adjust area for existing interface */ + ospf_area_del_if (oi->area, oi); + oi->area = area; + ospf_area_add_if (oi->area, oi); + } + else + { + add_ospf_interface(ifp, area, co); + } + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 1); /* interface possibly added */ + ospf_area_check_free (ospf, area_id); + + return 1; +} + +int +ospf_interface_unset (struct interface *ifp) +{ + struct route_node *rn_oi, *rn; + struct ospf *ospf; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + /* Find interfaces that may need to be removed. */ + for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi)) + { + struct ospf_interface *oi; + struct connected *co; + int found = 0; + + if ( (oi = rn_oi->info) == NULL) + continue; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + co = oi->connected; + + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + { + if (rn->info == NULL) + continue; + + if (ospf_network_match_iface(co,&rn->p)) + { + found = 1; + route_unlock_node (rn); + break; + } + } + if (found == 0) + ospf_if_free (oi); + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 0); /* interfaces possibly removed */ return 1; } + /* Check whether interface matches given network * returns: 1, true. 0, false */ @@ -862,39 +1038,9 @@ ospf_network_run_interface (struct prefix *p, struct ospf_area *area, if (p->family == co->address->family && ! ospf_if_table_lookup(ifp, co->address) && ospf_network_match_iface(co,p)) - { - struct ospf_interface *oi; - - oi = ospf_if_new (area->ospf, ifp, co->address); - oi->connected = co; - - oi->area = area; - - oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); - oi->output_cost = ospf_if_get_output_cost (oi); - - /* Add pseudo neighbor. */ - ospf_nbr_add_self (oi); - - /* Relate ospf interface to ospf instance. */ - oi->ospf = area->ospf; - - /* update network type as interface flag */ - /* If network type is specified previously, - skip network type setting. */ - oi->type = IF_DEF_PARAMS (ifp)->type; - - ospf_area_add_if (oi->area, oi); - - /* if router_id is not configured, dont bring up - * interfaces. - * ospf_router_id_update() will call ospf_if_update - * whenever r-id is configured instead. - */ - if ((area->ospf->router_id.s_addr != 0) - && if_is_operative (ifp)) - ospf_if_up (oi); - } + { + add_ospf_interface(ifp, area, co); + } } } @@ -953,15 +1099,22 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) /* OSPF must be on and Router-ID must be configured. */ if (!ospf || ospf->router_id.s_addr == 0) return; - - /* Run each netowrk for this interface. */ - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - if (rn->info != NULL) - { - network = (struct ospf_network *) rn->info; - area = ospf_area_get (ospf, network->area_id, network->format); - ospf_network_run_interface (&rn->p, area, ifp); - } + + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area)) + { + ospf_interface_set (ifp); + } + else + { + /* Run each netowrk for this interface. */ + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + if (rn->info != NULL) + { + network = (struct ospf_network *) rn->info; + area = ospf_area_get (ospf, network->area_id, network->format); + ospf_network_run_interface (&rn->p, area, ifp); + } + } } void @@ -1205,6 +1358,7 @@ ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id, return 1; } +#if 0 /* XXX: unused? Leave for symmetry? */ static int ospf_area_nssa_translator_role_unset (struct ospf *ospf, @@ -1222,6 +1376,7 @@ ospf_area_nssa_translator_role_unset (struct ospf *ospf, return 1; } +#endif int ospf_area_export_list_set (struct ospf *ospf, diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index b24b3ced..6cde1099 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -48,7 +48,9 @@ #define OSPF_VL_IP_TTL 100 /* Default configuration file name for ospfd. */ -#define OSPF_DEFAULT_CONFIG "ospfd.conf" +#define OSPF_CONFIG_NAME "ospfd.conf" +#define OSPF_PID_NAME "ospfd.pid" +#define OSPF_VTY_NAME "ospfd.vty" /* Architectual Constants */ #ifdef DEBUG @@ -272,6 +274,9 @@ struct ospf struct stream *ibuf; struct list *oi_write_q; + /* queue for AS-External route calculation */ + struct work_queue *ase_calc_queue; + /* Distribute lists out of other route sources. */ struct { @@ -327,6 +332,9 @@ struct ospf u_int32_t rx_lsa_count; struct route_table *distance_table; + + /* Host route list */ + struct list *hostlist; }; /* OSPF area structure. */ @@ -607,6 +615,9 @@ extern struct ospf_area *ospf_area_lookup_by_area_id (struct ospf *, extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); +extern int ospf_interface_set (struct interface *ifp); +extern int ospf_interface_unset (struct interface *ifp); + extern void ospf_route_map_init (void); extern void ospf_snmp_init (void); |