diff options
author | Santosh P K <sapk@vmware.com> | 2020-05-03 11:25:55 +0200 |
---|---|---|
committer | Santosh P K <sapk@vmware.com> | 2020-07-07 13:53:14 +0200 |
commit | 1febb13de7926e36cca08badfd960865d25b2cc6 (patch) | |
tree | 37c3ee18a89e7f07c608a53ebc313bdc58069078 /ospfd | |
parent | Merge pull request #6390 from opensourcerouting/bfd-cp-fix (diff) | |
download | frr-1febb13de7926e36cca08badfd960865d25b2cc6.tar.xz frr-1febb13de7926e36cca08badfd960865d25b2cc6.zip |
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')
-rw-r--r-- | ospfd/ospf_dump.c | 40 | ||||
-rw-r--r-- | ospfd/ospf_dump.h | 4 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 25 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 249 | ||||
-rw-r--r-- | ospfd/ospf_zebra.h | 7 | ||||
-rw-r--r-- | ospfd/ospfd.c | 1 | ||||
-rw-r--r-- | ospfd/ospfd.h | 2 |
7 files changed, 312 insertions, 16 deletions
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 3dcb2b481..dcc479def 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -53,10 +53,11 @@ unsigned long conf_debug_ospf_nssa = 0; unsigned long conf_debug_ospf_te = 0; unsigned long conf_debug_ospf_ext = 0; unsigned long conf_debug_ospf_sr = 0; +unsigned long conf_debug_ospf_defaultinfo = 0; /* Enable debug option variables -- valid only session. */ unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0}; -unsigned long term_debug_ospf_event = 0; +unsigned long term_debug_ospf_event; unsigned long term_debug_ospf_ism = 0; unsigned long term_debug_ospf_nsm = 0; unsigned long term_debug_ospf_lsa = 0; @@ -65,6 +66,7 @@ unsigned long term_debug_ospf_nssa = 0; unsigned long term_debug_ospf_te = 0; unsigned long term_debug_ospf_ext = 0; unsigned long term_debug_ospf_sr = 0; +unsigned long term_debug_ospf_defaultinfo; const char *ospf_redist_string(unsigned int route_type) { @@ -1447,6 +1449,33 @@ DEFUN (no_debug_ospf_sr, return CMD_SUCCESS; } +DEFUN (debug_ospf_default_info, + debug_ospf_default_info_cmd, + "debug ospf default-information", + DEBUG_STR + OSPF_STR + "OSPF default information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(defaultinfo, DEFAULTINFO); + TERM_DEBUG_ON(defaultinfo, DEFAULTINFO); + return CMD_SUCCESS; +} + +DEFUN (no_debug_ospf_default_info, + no_debug_ospf_default_info_cmd, + "no debug ospf default-information", + NO_STR + DEBUG_STR + OSPF_STR + "OSPF default information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(defaultinfo, DEFAULTINFO); + TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO); + return CMD_SUCCESS; +} + DEFUN (no_debug_ospf, no_debug_ospf_cmd, "no debug ospf", @@ -1475,6 +1504,7 @@ DEFUN (no_debug_ospf, DEBUG_OFF(zebra, ZEBRA); DEBUG_OFF(zebra, ZEBRA_INTERFACE); DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + DEBUG_OFF(defaultinfo, DEFAULTINFO); for (i = 0; i < 5; i++) DEBUG_PACKET_OFF(i, flag); @@ -1501,6 +1531,7 @@ DEFUN (no_debug_ospf, TERM_DEBUG_OFF(zebra, ZEBRA); TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE); TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO); return CMD_SUCCESS; } @@ -1595,6 +1626,9 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf) " OSPF Zebra redistribute debugging is on\n"); } + if (IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) == OSPF_DEBUG_DEFAULTINFO) + vty_out(vty, "OSPF default information is on\n"); + /* Show debug status for NSSA. */ if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA) vty_out(vty, " OSPF NSSA debugging is on\n"); @@ -1797,6 +1831,7 @@ void ospf_debug_init(void) install_element(ENABLE_NODE, &debug_ospf_nssa_cmd); install_element(ENABLE_NODE, &debug_ospf_te_cmd); install_element(ENABLE_NODE, &debug_ospf_sr_cmd); + install_element(ENABLE_NODE, &debug_ospf_default_info_cmd); install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd); install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd); install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd); @@ -1805,6 +1840,7 @@ void ospf_debug_init(void) install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd); install_element(ENABLE_NODE, &no_debug_ospf_te_cmd); install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd); install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd); install_element(ENABLE_NODE, &debug_ospf_packet_cmd); @@ -1834,6 +1870,7 @@ void ospf_debug_init(void) install_element(CONFIG_NODE, &debug_ospf_nssa_cmd); install_element(CONFIG_NODE, &debug_ospf_te_cmd); install_element(CONFIG_NODE, &debug_ospf_sr_cmd); + install_element(CONFIG_NODE, &debug_ospf_default_info_cmd); install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd); install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd); install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd); @@ -1841,6 +1878,7 @@ void ospf_debug_init(void) install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd); install_element(CONFIG_NODE, &no_debug_ospf_te_cmd); install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd); install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd); install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index 6b2ebb125..8c01977ff 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -59,6 +59,7 @@ #define OSPF_DEBUG_TE 0x04 #define OSPF_DEBUG_EXT 0x08 #define OSPF_DEBUG_SR 0x10 +#define OSPF_DEBUG_DEFAULTINFO 0x20 /* Macro for setting debug option. */ #define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b) @@ -104,6 +105,8 @@ #define IS_DEBUG_OSPF_SR IS_DEBUG_OSPF(sr, SR) +#define IS_DEBUG_OSPF_DEFAULT_INFO IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) + #define IS_CONF_DEBUG_OSPF_PACKET(a, b) \ (conf_debug_ospf_packet[a] & OSPF_DEBUG_##b) #define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b) @@ -122,6 +125,7 @@ extern unsigned long term_debug_ospf_nssa; extern unsigned long term_debug_ospf_te; extern unsigned long term_debug_ospf_ext; extern unsigned long term_debug_ospf_sr; +extern unsigned long term_debug_ospf_defaultinfo; /* Message Strings. */ extern char *ospf_lsa_type_str[]; diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index d089ea76c..07feb2482 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2032,18 +2032,22 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, static struct external_info *ospf_default_external_info(struct ospf *ospf) { int type; - struct route_node *rn; struct prefix_ipv4 p; + struct external_info *default_ei; + int ret = 0; p.family = AF_INET; p.prefix.s_addr = 0; p.prefixlen = 0; + default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, + ospf->instance, &p); + if (!default_ei) + return NULL; + /* First, lookup redistributed default route. */ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; if (type == ZEBRA_ROUTE_OSPF) continue; @@ -2052,17 +2056,10 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf) if (!ext_list) continue; - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { - rn = route_node_lookup(ext->external_info, - (struct prefix *)&p); - if (rn != NULL) { - route_unlock_node(rn); - assert(rn->info); - if (ospf_redistribute_check(ospf, rn->info, - NULL)) - return rn->info; - } - } + ret = ospf_external_default_routemap_apply_walk(ospf, ext_list, + default_ei); + if (ret) + return default_ei; } return NULL; diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 644ea7f92..04b500d66 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; } diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 253d2e0a3..80abf6236 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -92,5 +92,10 @@ extern int ospf_distance_unset(struct vty *, struct ospf *, const char *, extern void ospf_zebra_init(struct thread_master *, unsigned short); extern void ospf_zebra_vrf_register(struct ospf *ospf); extern void ospf_zebra_vrf_deregister(struct ospf *ospf); - +bool ospf_external_default_routemap_apply_walk( + struct ospf *ospf, struct list *ext_list, + struct external_info *default_ei); +int ospf_external_info_apply_default_routemap(struct ospf *ospf, + struct external_info *ei, + struct external_info *default_ei); #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index cdfcaa44d..3b1fbb367 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -674,6 +674,7 @@ static void ospf_finish_final(struct ospf *ospf) OSPF_TIMER_OFF(ospf->t_lsa_refresher); OSPF_TIMER_OFF(ospf->t_opaque_lsa_self); OSPF_TIMER_OFF(ospf->t_sr_update); + OSPF_TIMER_OFF(ospf->t_default_routemap_timer); LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa) ospf_discard_from_db(ospf, ospf->lsdb, lsa); diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 5e91e6f8e..cdeaa38dc 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -249,6 +249,8 @@ struct ospf { struct thread *t_write; #define OSPF_WRITE_INTERFACE_COUNT_DEFAULT 20 + struct thread *t_default_routemap_timer; + int write_oi_count; /* Num of packets sent per thread invocation */ struct thread *t_read; int fd; |