summaryrefslogtreecommitdiff
path: root/ospfd/ospf_zebra.c
diff options
context:
space:
mode:
authorSantosh P K <sapk@vmware.com>2020-05-03 02:25:55 -0700
committerSantosh P K <sapk@vmware.com>2020-07-07 04:53:14 -0700
commit1febb13de7926e36cca08badfd960865d25b2cc6 (patch)
tree37c3ee18a89e7f07c608a53ebc313bdc58069078 /ospfd/ospf_zebra.c
parentcba183561b53b3562ec7c4dd23115b02efc26e22 (diff)
ospf: Default-information originate with routemap
Default originate with route-map was broken. Routemap was not getting applied for redistribute route but was getting applied default route itself. No default route was originated even when routemap was satisfied. Signed-off-by: Santosh P K <sapk@vmware.com>
Diffstat (limited to 'ospfd/ospf_zebra.c')
-rw-r--r--ospfd/ospf_zebra.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 644ea7f922..04b500d662 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -56,6 +56,7 @@ DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table")
DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute")
DEFINE_MTYPE_STATIC(OSPFD, OSPF_DIST_ARGS, "OSPF Distribute arguments")
+
/* Zebra structure to hold current status. */
struct zclient *zclient = NULL;
@@ -397,6 +398,101 @@ struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,
return ext;
}
+/*
+ * Walk all the ei received from zebra for a route type and apply
+ * default route-map.
+ */
+bool ospf_external_default_routemap_apply_walk(struct ospf *ospf,
+ struct list *ext_list,
+ struct external_info *default_ei)
+{
+ struct listnode *node;
+ struct ospf_external *ext;
+ struct route_node *rn;
+ struct external_info *ei = NULL;
+ int ret = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ if (!ext->external_info)
+ continue;
+
+ for (rn = route_top(ext->external_info); rn;
+ rn = route_next(rn)) {
+ ei = rn->info;
+ if (!ei)
+ continue;
+ ret = ospf_external_info_apply_default_routemap(
+ ospf, ei, default_ei);
+ if (ret)
+ break;
+ }
+ }
+
+ if (ret && ei) {
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Default originate routemap permit ei: %s",
+ inet_ntoa(ei->p.prefix));
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Function to originate or flush default after applying
+ * route-map on all ei.
+ */
+static int ospf_external_lsa_default_routemap_timer(struct thread *thread)
+{
+ struct list *ext_list;
+ struct ospf *ospf = THREAD_ARG(thread);
+ struct prefix_ipv4 p;
+ int type;
+ int ret = 0;
+ struct ospf_lsa *lsa;
+ struct external_info *default_ei;
+
+ p.family = AF_INET;
+ p.prefixlen = 0;
+ p.prefix.s_addr = INADDR_ANY;
+
+ /* Get the default extenal info. */
+ default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
+ ospf->instance, &p);
+ if (!default_ei) {
+ /* Nothing to be done here. */
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Default originate info not present");
+ return 0;
+ }
+
+ /* For all the ei apply route-map */
+ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+ ext_list = ospf->external[type];
+ if (!ext_list || type == ZEBRA_ROUTE_OSPF)
+ continue;
+
+ ret = ospf_external_default_routemap_apply_walk(ospf, ext_list,
+ default_ei);
+ if (ret)
+ break;
+ }
+
+ /* Get the default LSA. */
+ lsa = ospf_external_info_find_lsa(ospf, &p);
+
+ /* If permit then originate default. */
+ if (ret && !lsa)
+ ospf_external_lsa_originate(ospf, default_ei);
+ else if (ret && lsa && IS_LSA_MAXAGE(lsa))
+ ospf_external_lsa_refresh(ospf, lsa, default_ei, true);
+ else if (!ret && lsa)
+ ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0);
+
+ return 1;
+}
+
+
void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)
{
struct ospf_external *ext;
@@ -414,6 +510,12 @@ void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)
XFREE(MTYPE_OSPF_EXTERNAL, ext);
}
+
+ /*
+ * Check if default needs to be flushed too.
+ */
+ thread_add_event(master, ospf_external_lsa_default_routemap_timer, ospf,
+ 0, &ospf->t_default_routemap_timer);
}
/* Update NHLFE for Prefix SID */
@@ -801,6 +903,132 @@ int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei)
return 1;
}
+
+/* Apply default route-map on ei received. */
+int ospf_external_info_apply_default_routemap(struct ospf *ospf,
+ struct external_info *ei,
+ struct external_info *default_ei)
+{
+ struct ospf_redist *red;
+ int type = default_ei->type;
+ struct prefix_ipv4 *p = &ei->p;
+ struct route_map_set_values save_values;
+
+
+ if (!ospf_external_lsa_originate_check(ospf, default_ei))
+ return 0;
+
+ save_values = default_ei->route_map_set;
+ ospf_reset_route_map_set_values(&default_ei->route_map_set);
+
+ /* apply route-map if needed */
+ red = ospf_redist_lookup(ospf, type, ospf->instance);
+ if (red && ROUTEMAP_NAME(red)) {
+ route_map_result_t ret;
+
+ ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p,
+ RMAP_OSPF, ei);
+
+ if (ret == RMAP_DENYMATCH) {
+ ei->route_map_set = save_values;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+/*
+ * Default originated is based on route-map condition then
+ * apply route-map on received external info. Originate or
+ * flush based on route-map condition.
+ */
+static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf,
+ struct external_info *ei,
+ int cmd)
+{
+ struct external_info *default_ei;
+ struct prefix_ipv4 p;
+ struct ospf_lsa *lsa;
+ int ret;
+
+ p.family = AF_INET;
+ p.prefixlen = 0;
+ p.prefix.s_addr = INADDR_ANY;
+
+
+ /* Get the default extenal info. */
+ default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
+ ospf->instance, &p);
+ if (!default_ei) {
+ /* Nothing to be done here. */
+ return false;
+ }
+
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Apply default originate routemap on ei: %s cmd: %d",
+ inet_ntoa(ei->p.prefix), cmd);
+
+ ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei);
+
+ /* If deny then nothing to be done both in add and del case. */
+ if (!ret) {
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Default originte routemap deny for ei: %s",
+ inet_ntoa(ei->p.prefix));
+ return false;
+ }
+
+ /* Get the default LSA. */
+ lsa = ospf_external_info_find_lsa(ospf, &p);
+
+ /* If this is add route and permit then ooriginate default. */
+ if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
+ /* If permit and default already advertise then return. */
+ if (lsa && !IS_LSA_MAXAGE(lsa)) {
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Defult lsa already originated");
+ return true;
+ }
+
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug("Originating/Refreshing default lsa");
+
+ if (lsa && IS_LSA_MAXAGE(lsa))
+ /* Refresh lsa.*/
+ ospf_external_lsa_refresh(ospf, lsa, default_ei, true);
+ else
+ /* If permit and default not advertised then advertise.
+ */
+ ospf_external_lsa_originate(ospf, default_ei);
+
+ } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) {
+ /* If deny and lsa is not originated then nothing to be done.*/
+ if (!lsa) {
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug(
+ "Default lsa not originated, not flushing");
+ return true;
+ }
+
+ if (IS_DEBUG_OSPF_DEFAULT_INFO)
+ zlog_debug(
+ "Running default route-map again as ei: %s deleted",
+ inet_ntoa(ei->p.prefix));
+ /*
+ * if this route delete was permitted then we need to check
+ * there are any other external info which can still trigger
+ * default route origination else flush it.
+ */
+ thread_add_event(master,
+ ospf_external_lsa_default_routemap_timer, ospf,
+ 0, &ospf->t_default_routemap_timer);
+ }
+
+ return true;
+}
+
/* return 1 if external LSA must be originated, 0 otherwise */
int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
int *changed)
@@ -812,6 +1040,10 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
unsigned short instance = is_prefix_default(&ei->p) ? 0 : ei->instance;
route_tag_t saved_tag = 0;
+ /* Default is handled differently. */
+ if (type == DEFAULT_ROUTE)
+ return 1;
+
if (changed)
*changed = 0;
@@ -1004,8 +1236,24 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
}
}
}
+
+ /*
+ * Check if default-information originate is
+ * with some routemap prefix/access list match.
+ */
+ ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
+
} else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
{
+ /*
+ * Check if default-information originate is
+ * with some routemap prefix/access list match.
+ * Apply before ei is deleted.
+ */
+ ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p);
+ if (ei)
+ ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
+
ospf_external_info_delete(ospf, rt_type, api.instance, p);
if (is_prefix_default(&p))
ospf_external_lsa_refresh_default(ospf);
@@ -1014,6 +1262,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
ifindex /*, nexthop */);
}
+
return 0;
}