diff options
-rw-r--r-- | bfdd/bfdd_nb_config.c | 1 | ||||
-rw-r--r-- | lib/routemap.c | 9 | ||||
-rw-r--r-- | m4/ax_python.m4 | 3 | ||||
-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 | ||||
-rwxr-xr-x | tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py | 12 | ||||
-rwxr-xr-x | tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py | 12 | ||||
-rw-r--r-- | tests/topotests/lib/bgp.py | 21 | ||||
-rw-r--r-- | tests/topotests/lib/common_config.py | 6 |
14 files changed, 355 insertions, 37 deletions
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index de11997d1..915a2f641 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -257,6 +257,7 @@ int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args *args) bp = nb_running_get_entry(args->dnode, NULL, true); bp->detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL); + bfd_profile_update(bp); return NB_OK; } diff --git a/lib/routemap.c b/lib/routemap.c index 7749ea4cc..1415a9e2e 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1692,14 +1692,19 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, * more noops, we retain this return value and * return this eventually if there are no * matches. + * If a best match route-map index already + * exists, do not reset the match_ret. */ - if (*match_ret != RMAP_NOMATCH) + if (!best_index && (*match_ret != RMAP_NOMATCH)) *match_ret = ret; } else { /* * ret is RMAP_NOMATCH. + * If a best match route-map index already + * exists, do not reset the match_ret. */ - *match_ret = ret; + if (!best_index) + *match_ret = ret; } } diff --git a/m4/ax_python.m4 b/m4/ax_python.m4 index 9f43ea0ab..91d12b99b 100644 --- a/m4/ax_python.m4 +++ b/m4/ax_python.m4 @@ -186,7 +186,8 @@ AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_MSG_RESULT([yes]) PYTHON_CFLAGS="`\"$pycfg\" --includes`" - if test x"${py_ver}" = x"3.8" || test x"{py_ver}" = x"3.9"; then + minor_ver=${py_ver#*\.} + if test $((minor_ver)) -gt 7; then PYTHON_LIBS="`\"$pycfg\" --ldflags --embed`" else PYTHON_LIBS="`\"$pycfg\" --ldflags`" 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 ea9c7c58c..f9cc474d5 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -686,6 +686,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; diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py index 087ba21e5..948f641af 100755 --- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py @@ -63,7 +63,7 @@ from lib.common_config import ( reset_config_on_routers, ) from lib.topolog import logger -from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify +from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp from lib.topojson import build_topo_from_json, build_config_from_json # Reading the data from JSON File for topology and configuration creation @@ -295,7 +295,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): addr_type, dut, input_dict_1, - next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)], + next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, ) assert result is True, "Testcase {} : Failed \n Error: {}".format( @@ -336,8 +336,12 @@ def test_ecmp_after_clear_bgp(request, test_type): tc_name, result ) - # Clear bgp - result = clear_bgp_and_verify(tgen, topo, dut) + # Clear BGP + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, dut) + + # Verify BGP convergence + result = verify_bgp_convergence(tgen, topo) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) for addr_type in ADDR_TYPES: diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py index 94409ff3e..5b997fdd1 100755 --- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py @@ -63,7 +63,7 @@ from lib.common_config import ( reset_config_on_routers, ) from lib.topolog import logger -from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify +from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp from lib.topojson import build_topo_from_json, build_config_from_json # Reading the data from JSON File for topology and configuration creation @@ -296,7 +296,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): addr_type, dut, input_dict_1, - next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)], + next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, ) assert result is True, "Testcase {} : Failed \n Error: {}".format( @@ -337,8 +337,12 @@ def test_ecmp_after_clear_bgp(request, test_type): tc_name, result ) - # Clear bgp - result = clear_bgp_and_verify(tgen, topo, dut) + # Clear BGP + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, dut) + + # Verify BGP convergence + result = verify_bgp_convergence(tgen, topo) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) for addr_type in ADDR_TYPES: diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index 44b733505..971bbd0f3 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -44,7 +44,6 @@ from lib.common_config import ( LOGDIR = "/tmp/topotests/" TMPDIR = None - def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True): """ API to configure bgp on router @@ -882,7 +881,7 @@ def verify_router_id(tgen, topo, input_dict): return True -@retry(attempts=44, wait=3, return_is_str=True) +@retry(attempts=50, wait=3, return_is_str=True) def verify_bgp_convergence(tgen, topo, dut=None): """ API will verify if BGP is converged with in the given time frame. @@ -1052,11 +1051,13 @@ def verify_bgp_convergence(tgen, topo, dut=None): if nh_state == "Established": no_of_peer += 1 - if no_of_peer == total_peer: - logger.info("[DUT: %s] VRF: %s, BGP is Converged", router, vrf) - else: - errormsg = "[DUT: %s] VRF: %s, BGP is not converged" % (router, vrf) - return errormsg + if no_of_peer == total_peer: + logger.info("[DUT: %s] VRF: %s, BGP is Converged for %s address-family", + router, vrf, addr_type) + else: + errormsg = ("[DUT: %s] VRF: %s, BGP is not converged for %s address-family" % + (router, vrf, addr_type)) + return errormsg logger.debug("Exiting API: verify_bgp_convergence()") return True @@ -1326,7 +1327,7 @@ def verify_as_numbers(tgen, topo, input_dict): return True -@retry(attempts=44, wait=3, return_is_str=True) +@retry(attempts=50, wait=3, return_is_str=True) def verify_bgp_convergence_from_running_config(tgen, dut=None): """ API to verify BGP convergence b/w loopback and physical interface. @@ -1470,7 +1471,7 @@ def clear_bgp_and_verify(tgen, topo, router): sleeptime = 3 # Verifying BGP convergence before bgp clear command - for retry in range(44): + for retry in range(50): # Waiting for BGP to converge logger.info( "Waiting for %s sec for BGP to converge on router" " %s...", @@ -1552,7 +1553,7 @@ def clear_bgp_and_verify(tgen, topo, router): peer_uptime_after_clear_bgp = {} # Verifying BGP convergence after bgp clear command - for retry in range(44): + for retry in range(50): # Waiting for BGP to converge logger.info( diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index fb82b5062..d72d0aa22 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -690,6 +690,12 @@ def start_topology(tgen): router_list = tgen.routers() for rname in ROUTER_LIST: router = router_list[rname] + + # It will help in debugging the failures, will give more details on which + # specific kernel version tests are failing + linux_ver = router.run("uname -a") + logger.info("Logging platform related details: \n %s \n", linux_ver) + try: os.chdir(TMPDIR) |