summaryrefslogtreecommitdiff
path: root/ospfd/ospfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospfd.c')
-rw-r--r--ospfd/ospfd.c204
1 files changed, 125 insertions, 79 deletions
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 0adf8a7b41..04397d50a5 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -87,13 +87,39 @@ static void ospf_finish_final(struct ospf *);
#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
-void ospf_router_id_update(struct ospf *ospf)
+int p_spaces_compare_func(const struct p_space *a, const struct p_space *b)
+{
+ if (a->protected_resource->type == OSPF_TI_LFA_LINK_PROTECTION
+ && b->protected_resource->type == OSPF_TI_LFA_LINK_PROTECTION)
+ return (a->protected_resource->link->link_id.s_addr
+ - b->protected_resource->link->link_id.s_addr);
+
+ if (a->protected_resource->type == OSPF_TI_LFA_NODE_PROTECTION
+ && b->protected_resource->type == OSPF_TI_LFA_NODE_PROTECTION)
+ return (a->protected_resource->router_id.s_addr
+ - b->protected_resource->router_id.s_addr);
+
+ /* This should not happen */
+ return 0;
+}
+
+int q_spaces_compare_func(const struct q_space *a, const struct q_space *b)
+{
+ return (a->root->id.s_addr - b->root->id.s_addr);
+}
+
+DECLARE_RBTREE_UNIQ(p_spaces, struct p_space, p_spaces_item,
+ p_spaces_compare_func)
+
+void ospf_process_refresh_data(struct ospf *ospf, bool reset)
{
struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
struct in_addr router_id, router_id_old;
struct ospf_interface *oi;
struct interface *ifp;
- struct listnode *node;
+ struct listnode *node, *nnode;
+ struct ospf_area *area;
+ bool rid_change = false;
if (!ospf->oi_running) {
if (IS_DEBUG_OSPF_EVENT)
@@ -126,8 +152,8 @@ void ospf_router_id_update(struct ospf *ospf)
zlog_debug("Router-ID[OLD:%pI4]: Update to %pI4",
&ospf->router_id, &router_id);
- if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) {
-
+ rid_change = !(IPV4_ADDR_SAME(&router_id_old, &router_id));
+ if (rid_change || (reset)) {
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
/* Some nbrs are identified by router_id, these needs
* to be rebuilt. Possible optimization would be to do
@@ -149,16 +175,8 @@ void ospf_router_id_update(struct ospf *ospf)
ospf_if_up(oi);
}
- /* Flush (inline) all external LSAs based on the OSPF_LSA_SELF
- * flag */
- if (ospf->lsdb) {
- struct route_node *rn;
- struct ospf_lsa *lsa;
-
- LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
- if (IS_LSA_SELF(lsa))
- ospf_lsa_flush_schedule(ospf, lsa);
- }
+ /* Flush (inline) all the self originated LSAs */
+ ospf_flush_self_originated_lsas_now(ospf);
ospf->router_id = router_id;
if (IS_DEBUG_OSPF_EVENT)
@@ -183,24 +201,81 @@ void ospf_router_id_update(struct ospf *ospf)
LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
/* AdvRouter and Router ID is the same. */
if (IPV4_ADDR_SAME(&lsa->data->adv_router,
- &ospf->router_id)) {
+ &ospf->router_id) && rid_change) {
SET_FLAG(lsa->flags,
OSPF_LSA_SELF_CHECKED);
SET_FLAG(lsa->flags, OSPF_LSA_SELF);
ospf_lsa_flush_schedule(ospf, lsa);
}
+ /* The above flush will send immediately
+ * So discard the LSA to originate new
+ */
+ ospf_discard_from_db(ospf, ospf->lsdb, lsa);
}
+
+ LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
+ ospf_discard_from_db(ospf, ospf->lsdb, lsa);
+
+ ospf_lsdb_delete_all(ospf->lsdb);
}
+ /* Delete the LSDB */
+ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
+ ospf_area_lsdb_discard_delete(area);
+
/* update router-lsa's for each area */
ospf_router_lsa_update(ospf);
/* update ospf_interface's */
- FOR_ALL_INTERFACES (vrf, ifp)
- ospf_if_update(ospf, ifp);
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ if (reset)
+ ospf_if_reset(ifp);
+ else
+ ospf_if_update(ospf, ifp);
+ }
ospf_external_lsa_rid_change(ospf);
}
+
+ ospf->inst_shutdown = 0;
+}
+
+void ospf_router_id_update(struct ospf *ospf)
+{
+ ospf_process_refresh_data(ospf, false);
+}
+
+void ospf_process_reset(struct ospf *ospf)
+{
+ ospf_process_refresh_data(ospf, true);
+}
+
+void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
+ const char *nbr_str)
+{
+ struct route_node *rn;
+ struct ospf_neighbor *nbr;
+ struct ospf_interface *oi;
+ struct listnode *node;
+
+ /* Clear only a particular nbr with nbr router id as nbr_id */
+ if (nbr_str != NULL) {
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+ nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &nbr_id);
+ if (nbr)
+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+ }
+ return;
+ }
+
+ /* send Neighbor event KillNbr to all associated neighbors. */
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if (nbr && (nbr != oi->nbr_self))
+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+ }
+ }
}
/* For OSPF area sort by area id. */
@@ -213,8 +288,7 @@ static int ospf_area_id_cmp(struct ospf_area *a1, struct ospf_area *a2)
return 0;
}
-/* Allocate new ospf structure. */
-static struct ospf *ospf_new(unsigned short instance, const char *name)
+struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
{
int i;
struct vrf *vrf = NULL;
@@ -289,8 +363,6 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
new->maxage_lsa = route_table_init();
new->t_maxage_walker = NULL;
- thread_add_timer(master, ospf_lsa_maxage_walker, new,
- OSPF_LSA_MAXAGE_CHECK_INTERVAL, &new->t_maxage_walker);
/* Distance table init. */
new->distance_table = route_table_init();
@@ -298,8 +370,6 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
new->lsa_refresh_queue.index = 0;
new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
new->t_lsa_refresher = NULL;
- thread_add_timer(master, ospf_lsa_refresh_walker, new,
- new->lsa_refresh_interval, &new->t_lsa_refresher);
new->lsa_refresher_started = monotime(NULL);
new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1);
@@ -317,6 +387,17 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
QOBJ_REG(new, ospf);
new->fd = -1;
+
+ return new;
+}
+
+/* Allocate new ospf structure. */
+static struct ospf *ospf_new(unsigned short instance, const char *name)
+{
+ struct ospf *new;
+
+ new = ospf_new_alloc(instance, name);
+
if ((ospf_sock_init(new)) < 0) {
if (new->vrf_id != VRF_UNKNOWN)
flog_err(
@@ -325,6 +406,12 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
__func__);
return new;
}
+
+ thread_add_timer(master, ospf_lsa_maxage_walker, new,
+ OSPF_LSA_MAXAGE_CHECK_INTERVAL, &new->t_maxage_walker);
+ thread_add_timer(master, ospf_lsa_refresh_walker, new,
+ new->lsa_refresh_interval, &new->t_lsa_refresher);
+
thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
return new;
@@ -836,8 +923,7 @@ static void ospf_finish_final(struct ospf *ospf)
/* allocate new OSPF Area object */
-static struct ospf_area *ospf_area_new(struct ospf *ospf,
- struct in_addr area_id)
+struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *new;
@@ -870,14 +956,11 @@ static struct ospf_area *ospf_area_new(struct ospf *ospf,
return new;
}
-static void ospf_area_free(struct ospf_area *area)
+void ospf_area_lsdb_discard_delete(struct ospf_area *area)
{
struct route_node *rn;
struct ospf_lsa *lsa;
- ospf_opaque_type10_lsa_term(area);
-
- /* Free LSDBs. */
LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
@@ -895,6 +978,15 @@ static void ospf_area_free(struct ospf_area *area)
ospf_discard_from_db(area->ospf, area->lsdb, lsa);
ospf_lsdb_delete_all(area->lsdb);
+}
+
+static void ospf_area_free(struct ospf_area *area)
+{
+ ospf_opaque_type10_lsa_term(area);
+
+ /* Free LSDBs. */
+ ospf_area_lsdb_discard_delete(area);
+
ospf_lsdb_free(area->lsdb);
ospf_lsa_unlock(&area->router_lsa_self);
@@ -978,7 +1070,8 @@ void ospf_area_del_if(struct ospf_area *area, struct ospf_interface *oi)
}
-static void add_ospf_interface(struct connected *co, struct ospf_area *area)
+struct ospf_interface *add_ospf_interface(struct connected *co,
+ struct ospf_area *area)
{
struct ospf_interface *oi;
@@ -1015,6 +1108,8 @@ static void add_ospf_interface(struct connected *co, struct ospf_area *area)
if ((area->ospf->router_id.s_addr != INADDR_ANY)
&& if_is_operative(co->ifp))
ospf_if_up(oi);
+
+ return oi;
}
static void update_redistributed(struct ospf *ospf, int add_to_ospf)
@@ -1644,26 +1739,6 @@ int ospf_area_nssa_translator_role_set(struct ospf *ospf,
return 1;
}
-#if 0
-/* XXX: unused? Leave for symmetry? */
-static int
-ospf_area_nssa_translator_role_unset (struct ospf *ospf,
- struct in_addr area_id)
-{
- struct ospf_area *area;
-
- area = ospf_area_lookup_by_area_id (ospf, area_id);
- if (area == NULL)
- return 0;
-
- area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
-
- ospf_area_check_free (ospf, area_id);
-
- return 1;
-}
-#endif
-
int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area,
const char *list_name)
{
@@ -1906,35 +1981,6 @@ struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *ospf,
return NULL;
}
-struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next(struct ospf *ospf,
- struct in_addr *addr, int first)
-{
-#if 0
- struct ospf_nbr_nbma *nbr_nbma;
- struct listnode *node;
-#endif
-
- if (ospf == NULL)
- return NULL;
-
-#if 0
- for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
- {
- if (first)
- {
- *addr = nbr_nbma->addr;
- return nbr_nbma;
- }
- else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
- {
- *addr = nbr_nbma->addr;
- return nbr_nbma;
- }
- }
-#endif
- return NULL;
-}
-
int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
{
struct ospf_nbr_nbma *nbr_nbma;