summaryrefslogtreecommitdiffstats
path: root/ospfd
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/Makefile.am2
-rw-r--r--ospfd/ospf_abr.c45
-rw-r--r--ospfd/ospf_ase.c104
-rw-r--r--ospfd/ospf_ase.h2
-rw-r--r--ospfd/ospf_interface.c42
-rw-r--r--ospfd/ospf_interface.h11
-rw-r--r--ospfd/ospf_lsa.c24
-rw-r--r--ospfd/ospf_main.c20
-rw-r--r--ospfd/ospf_nsm.c24
-rw-r--r--ospfd/ospf_nsm.h2
-rw-r--r--ospfd/ospf_packet.c117
-rw-r--r--ospfd/ospf_packet.h1
-rw-r--r--ospfd/ospf_route.c67
-rw-r--r--ospfd/ospf_route.h6
-rw-r--r--ospfd/ospf_spf.c163
-rw-r--r--ospfd/ospf_vty.c267
-rw-r--r--ospfd/ospf_zebra.c26
-rw-r--r--ospfd/ospf_zebra.h2
-rw-r--r--ospfd/ospfd.c281
-rw-r--r--ospfd/ospfd.h13
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, &params->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);