diff options
| author | Santosh P K <sapk@vmware.com> | 2020-05-03 02:25:55 -0700 |
|---|---|---|
| committer | Santosh P K <sapk@vmware.com> | 2020-07-07 04:53:14 -0700 |
| commit | 1febb13de7926e36cca08badfd960865d25b2cc6 (patch) | |
| tree | 37c3ee18a89e7f07c608a53ebc313bdc58069078 /ospfd/ospf_zebra.c | |
| parent | cba183561b53b3562ec7c4dd23115b02efc26e22 (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.c | 249 |
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; } |
