diff options
50 files changed, 1250 insertions, 327 deletions
diff --git a/.dir-locals.el b/.dir-locals.el index 21392ecf28..e47f245db7 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -2,7 +2,7 @@ ;;; For more information see (info "(emacs) Directory Variables") ;;; Match project coding conventions -((c-mode - (indent-tabs-mode . t) - (show-trailing-whitespace . t) - (c-basic-offset . 8))) +((c-mode . ((indent-tabs-mode . t) + (show-trailing-whitespace . t) + (c-basic-offset . 8) + ))) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index f476b16188..0e4c3a3e12 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -209,7 +209,7 @@ static void bgp_debug_list_free(struct list *list) listnode_delete(list, filter); if (filter->p) - prefix_free(filter->p); + prefix_free(&filter->p); if (filter->host) XFREE(MTYPE_BGP_DEBUG_STR, filter->host); @@ -323,7 +323,7 @@ static int bgp_debug_list_remove_entry(struct list *list, const char *host, } else if (p && filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) { listnode_delete(list, filter); - prefix_free(filter->p); + prefix_free(&filter->p); XFREE(MTYPE_BGP_DEBUG_FILTER, filter); return 1; } @@ -1412,7 +1412,7 @@ DEFPY (debug_bgp_update_prefix_afi_safi, ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); if (ret != CMD_SUCCESS) { - prefix_free(argv_p); + prefix_free(&argv_p); return ret; } @@ -1425,7 +1425,7 @@ DEFPY (debug_bgp_update_prefix_afi_safi, vty_out(vty, "BGP updates debugging is already enabled for %s\n", buf); - prefix_free(argv_p); + prefix_free(&argv_p); return CMD_SUCCESS; } @@ -1438,7 +1438,7 @@ DEFPY (debug_bgp_update_prefix_afi_safi, vty_out(vty, "BGP updates debugging is on for %s\n", buf); } - prefix_free(argv_p); + prefix_free(&argv_p); return CMD_SUCCESS; } @@ -1477,7 +1477,7 @@ DEFPY (no_debug_bgp_update_prefix_afi_safi, ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); if (ret != CMD_SUCCESS) { - prefix_free(argv_p); + prefix_free(&argv_p); return ret; } @@ -1505,7 +1505,7 @@ DEFPY (no_debug_bgp_update_prefix_afi_safi, vty_out(vty, "BGP updates debugging was not enabled for %s\n", buf); - prefix_free(argv_p); + prefix_free(&argv_p); return ret; } diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 640224e759..f850cb49cf 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -234,9 +234,9 @@ static void bgp_dump_routes_index_table(struct bgp *bgp) stream_put_in_addr(obuf, &bgp->router_id); /* View name */ - if (bgp->name) { - stream_putw(obuf, strlen(bgp->name)); - stream_put(obuf, bgp->name, strlen(bgp->name)); + if (bgp->name_pretty) { + stream_putw(obuf, strlen(bgp->name_pretty)); + stream_put(obuf, bgp->name_pretty, strlen(bgp->name_pretty)); } else { stream_putw(obuf, 0); } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 74c45ed447..915963fad8 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -91,8 +91,9 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc) if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) { if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; - zlog_debug("bgp_unlink_nexthop: freeing bnc %s", - bnc_str(bnc, buf, PREFIX2STR_BUFFER)); + zlog_debug("bgp_unlink_nexthop: freeing bnc %s(%s)", + bnc_str(bnc, buf, PREFIX2STR_BUFFER), + bnc->bgp->name_pretty); } unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); @@ -194,8 +195,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; - zlog_debug("Allocated bnc %s peer %p", - bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer); + zlog_debug("Allocated bnc %s(%s) peer %p", + bnc_str(bnc, buf, PREFIX2STR_BUFFER), + bnc->bgp->name_pretty, peer); } } @@ -291,16 +293,18 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); if (!rn) { if (BGP_DEBUG(nht, NHT)) - zlog_debug("Cannot find connected NHT node for peer %s", - peer->host); + zlog_debug( + "Cannot find connected NHT node for peer %s(%s)", + peer->host, peer->bgp->name_pretty); return; } bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) { if (BGP_DEBUG(nht, NHT)) - zlog_debug("Cannot find connected NHT node for peer %s on route_node as expected", - peer->host); + zlog_debug( + "Cannot find connected NHT node for peer %s(%s) on route_node as expected", + peer->host, peer->bgp->name_pretty); bgp_unlock_node(rn); return; } @@ -309,8 +313,9 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) if (bnc->nht_info != peer) { if (BGP_DEBUG(nht, NHT)) zlog_debug( - "Connected NHT %p node for peer %s points to %p", - bnc, peer->host, bnc->nht_info); + "Connected NHT %p node for peer %s(%s) points to %p", + bnc, peer->host, bnc->bgp->name_pretty, + bnc->nht_info); return; } @@ -318,8 +323,9 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) if (LIST_EMPTY(&(bnc->paths))) { if (BGP_DEBUG(nht, NHT)) - zlog_debug("Freeing connected NHT node %p for peer %s", - bnc, peer->host); + zlog_debug( + "Freeing connected NHT node %p for peer %s(%s)", + bnc, peer->host, bnc->bgp->name_pretty); unregister_zebra_rnh(bnc, 0); bgp_node_set_bgp_nexthop_info(bnc->node, NULL); bgp_unlock_node(bnc->node); @@ -350,8 +356,8 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) { if (BGP_DEBUG(nht, NHT)) - zlog_debug("%s: Failure to decode nexthop update", - __PRETTY_FUNCTION__); + zlog_debug("%s[%s]: Failure to decode nexthop update", + __PRETTY_FUNCTION__, bgp->name_pretty); return; } @@ -368,8 +374,8 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; prefix2str(&nhr.prefix, buf, sizeof(buf)); - zlog_debug("parse nexthop update(%s): rn not found", - buf); + zlog_debug("parse nexthop update(%s(%s)): rn not found", + buf, bgp->name_pretty); } return; } @@ -380,8 +386,9 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) char buf[PREFIX2STR_BUFFER]; prefix2str(&nhr.prefix, buf, sizeof(buf)); - zlog_debug("parse nexthop update(%s): bnc node info not found", - buf); + zlog_debug( + "parse nexthop update(%s(%s)): bnc node info not found", + buf, bgp->name_pretty); } bgp_unlock_node(rn); return; @@ -396,9 +403,10 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) char buf[PREFIX2STR_BUFFER]; prefix2str(&nhr.prefix, buf, sizeof(buf)); zlog_debug( - "%u: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x", - vrf_id, buf, nhr.metric, bnc->metric, nhr.nexthop_num, - bnc->nexthop_num, bnc->flags); + "%s(%u): Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x", + bnc->bgp->name_pretty, vrf_id, buf, nhr.metric, + bnc->metric, nhr.nexthop_num, bnc->nexthop_num, + bnc->flags); } if (nhr.metric != bnc->metric) @@ -622,7 +630,7 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) prefix2str(p, buf, PREFIX2STR_BUFFER); zlog_debug("%s: sending cmd %s for %s (vrf %s)", __func__, zserv_command_string(command), buf, - bnc->bgp->name); + bnc->bgp->name_pretty); } ret = zclient_send_rnh(zclient, command, p, exact_match, @@ -702,8 +710,9 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) char buf[PREFIX2STR_BUFFER]; bnc_str(bnc, buf, PREFIX2STR_BUFFER); zlog_debug( - "NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths", - buf, bnc->flags, bnc->change_flags); + "NH update for %s(%s) - flags 0x%x chgflags 0x%x - evaluate paths", + buf, bnc->bgp->name_pretty, bnc->flags, + bnc->change_flags); } LIST_FOREACH (path, &(bnc->paths), nh_thread) { @@ -790,8 +799,9 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) { if (BGP_DEBUG(nht, NHT)) - zlog_debug("%s: Updating peer (%s) status with NHT", - __FUNCTION__, peer->host); + zlog_debug("%s: Updating peer (%s(%s)) status with NHT", + __FUNCTION__, peer->host, + peer->bgp->name_pretty); bgp_fsm_event_update(peer, bgp_isvalid_nexthop(bnc)); SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 41e32b3112..2642266486 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1941,19 +1941,19 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, __func__, family2str(family)); subgroup_announce_reset_nhop(family, attr); } + } - /* If IPv6/MP and nexthop does not have any override and happens - * to - * be a link-local address, reset it so that we don't pass along - * the - * source's link-local IPv6 address to recipients who may not be - * on - * the same interface. - */ - if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) { - if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) - subgroup_announce_reset_nhop(AF_INET6, attr); - } + /* If IPv6/MP and nexthop does not have any override and happens + * to + * be a link-local address, reset it so that we don't pass along + * the + * source's link-local IPv6 address to recipients who may not be + * on + * the same interface. + */ + if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) { + if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) + subgroup_announce_reset_nhop(AF_INET6, attr); } return 1; @@ -10548,7 +10548,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, } ret = bgp_show(vty, bgp, afi, safi, type, p, 0); - prefix_free(p); + prefix_free(&p); return ret; } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 7923f076c1..d0a732b153 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -357,7 +357,7 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) bgp_connected_delete(bgp, ifc); } - connected_free(ifc); + connected_free(&ifc); return 0; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 06f6f933ac..7621d7ef0f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2586,7 +2586,7 @@ int peer_group_delete(struct peer_group *group) for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) { - prefix_free(prefix); + prefix_free(&prefix); } list_delete(&group->listen_range[afi]); } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index fe8e874440..660442b492 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -1512,7 +1512,7 @@ static int rfapiNhlAddNodeRoutes( } seen_nexthops = - skiplist_new(0, vnc_prefix_cmp, (void (*)(void *))prefix_free); + skiplist_new(0, vnc_prefix_cmp, prefix_free_lists); for (bpi = rn->info; bpi; bpi = bpi->next) { @@ -4359,7 +4359,7 @@ rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list, it->rt_import_list = ecommunity_dup(rt_import_list); it->rfg = rfg; it->monitor_exterior_orphans = - skiplist_new(0, NULL, (void (*)(void *))prefix_free); + skiplist_new(0, NULL, prefix_free_lists); /* * fill import route tables from RIBs diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index df06105535..6e8969ad18 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -1807,8 +1807,7 @@ static void vnc_import_bgp_exterior_add_route_it( RFAPI_MONITOR_EXTERIOR(rn)->source = skiplist_new( 0, NULL, - (void (*)(void *)) - prefix_free); + prefix_free_lists); agg_lock_node(rn); /* for skiplist */ } agg_lock_node(rn); /* for skiplist entry */ @@ -2194,8 +2193,7 @@ void vnc_import_bgp_exterior_add_route_interior( ->source) { RFAPI_MONITOR_EXTERIOR(rn_interior) ->source = skiplist_new( - 0, NULL, - (void (*)(void *))prefix_free); + 0, NULL, prefix_free_lists); agg_lock_node(rn_interior); } skiplist_insert( @@ -2337,8 +2335,7 @@ void vnc_import_bgp_exterior_add_route_interior( if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) { RFAPI_MONITOR_EXTERIOR(rn_interior)->source = skiplist_new( - 0, NULL, - (void (*)(void *))prefix_free); + 0, NULL, prefix_free_lists); agg_lock_node(rn_interior); /* sl */ } skiplist_insert( @@ -2527,8 +2524,7 @@ void vnc_import_bgp_exterior_del_route_interior( if (!RFAPI_MONITOR_EXTERIOR(par)->source) { RFAPI_MONITOR_EXTERIOR(par)->source = skiplist_new( - 0, NULL, - (void (*)(void *))prefix_free); + 0, NULL, prefix_free_lists); agg_lock_node(par); /* sl */ } skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source, diff --git a/doc/developer/testing.rst b/doc/developer/testing.rst index 6396faf9a6..5865a6becc 100644 --- a/doc/developer/testing.rst +++ b/doc/developer/testing.rst @@ -8,3 +8,4 @@ Testing :maxdepth: 2 topotests + topotests-jsontopo diff --git a/doc/developer/topotests-jsontopo.rst b/doc/developer/topotests-jsontopo.rst index 130f072b62..bbae80f11d 100644 --- a/doc/developer/topotests-jsontopo.rst +++ b/doc/developer/topotests-jsontopo.rst @@ -1,53 +1,50 @@ -.. role:: raw-html-m2r(raw) - :format: html +.. _topotests-json: -************************************* -FRRouting Topology Tests with Mininet -************************************* +Topotests with JSON +=================== Overview -======== +-------- On top of current topotests framework following enhancements are done: -#. Creating the topology and assigning IPs to router' interfaces dynamically.\ :raw-html-m2r:`<br>` - It is achieved by using json file, in which user specify the number of routers, - links to each router, interfaces for the routers and protocol configurations for - all routers. +* Creating the topology and assigning IPs to router' interfaces dynamically. + It is achieved by using json file, in which user specify the number of + routers, links to each router, interfaces for the routers and protocol + configurations for all routers. -#. Creating the configurations dynamically. It is achieved by using - /usr/lib/frr/frr-reload.py utility, which takes running configuration and the - newly created configuration for any particular router and creates a delta - file(diff file) and loads it to router. +* Creating the configurations dynamically. It is achieved by using + :file:`/usr/lib/frr/frr-reload.py` utility, which takes running configuration + and the newly created configuration for any particular router and creates a + delta file(diff file) and loads it to router. Logging of test case executions -=============================== +------------------------------- - -#. User can enable logging of testcases execution messages into log file by - adding "frrtest_log_dir = /tmp/topotests/" in pytest.ini file -#.Router's current configuration can be displyed on console or sent to logs by - adding "show_router_config = True" in pytest.ini file +* The user can enable logging of testcases execution messages into log file by + adding ``frrtest_log_dir = /tmp/topotests/`` in :file:`pytest.ini`. +* Router's current configuration can be displyed on console or sent to logs by + adding ``show_router_config = True`` in :file:`pytest.ini`. Log file name will be displayed when we start execution: .. code-block:: console - root@test:~/topotests/example-topojson-test/test_topo_json_single_link# python - test_topo_json_single_link.py Logs will be sent to logfile: + root@test:# python ./test_topo_json_single_link.py + + Logs will be sent to logfile: /tmp/topotests/test_topo_json_single_link_11:57:01.353797 Note: directory "/tmp/topotests/" is created by topotests by default, making use of same directory to save execution logs. - Guidelines -========== +---------- Writing New Tests ------------------ +^^^^^^^^^^^^^^^^^ This section will guide you in all recommended steps to produce a standard topology test. @@ -60,29 +57,30 @@ This is the recommended test writing routine: * Write the tests * Create a Pull Request + File Hierarchy --------------- +^^^^^^^^^^^^^^ Before starting to write any tests one must know the file hierarchy. The repository hierarchy looks like this: -.. code-block:: - - $ cd path/to/topotests - $ find ./* - ... - ./example-topojson-test # the basic example test topology-1 - ./example-topojson-test/test_example_topojson.json # input json file, having - topology, interfaces, bgp and other configuration - ./example-topojson-test/test_example_topojson.py # test script to write and - execute testcases - ... - ./lib # shared test/topology functions - ./lib/topojson.py # library to create topology and configurations dynamically - from json file - ./lib/common_config.py # library to create protocol's common configurations ex- - static_routes, prefix_lists, route_maps etc. - ./lib/bgp.py # library to create only bgp configurations +.. code-block:: console + + $ cd path/to/topotests + $ find ./* + ... + ./example-topojson-test # the basic example test topology-1 + ./example-topojson-test/test_example_topojson.json # input json file, having + topology, interfaces, bgp and other configuration + ./example-topojson-test/test_example_topojson.py # test script to write and + execute testcases + ... + ./lib # shared test/topology functions + ./lib/topojson.py # library to create topology and configurations dynamically + from json file + ./lib/common_config.py # library to create protocol's common configurations ex- + static_routes, prefix_lists, route_maps etc. + ./lib/bgp.py # library to create only bgp configurations Defining the Topology and initial configuration in JSON file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +323,7 @@ BGP neighborship with Multiple phy-links, sample JSON file:: ... -JSON File Explained +JSON File Explained """"""""""""""""""" Mandatory keywords/options in JSON: @@ -466,7 +464,7 @@ Example: * ``__main__`` initialization code (to support running the script directly) .. code-block:: python - + if **name** == '\ **main**\ ': sys.exit(pytest.main(["-s"])) diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 3e09ec41bb..324f309290 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -327,8 +327,7 @@ int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p) if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->u.prefix4)) return 0; - prefix_ipv4_free(rn->info); - rn->info = NULL; + prefix_ipv4_free((struct prefix_ipv4 **)&rn->info); route_unlock_node(rn); /* initial reference */ /* Find interfaces that not configured already. */ diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 9cc612eaf1..56dbe3d85e 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -197,7 +197,7 @@ void eigrp_prefix_entry_delete(struct eigrp *eigrp, struct route_table *table, list_delete(&pe->entries); list_delete(&pe->rij); eigrp_zebra_route_delete(eigrp, pe->destination); - prefix_free(pe->destination); + prefix_free(&pe->destination); rn->info = NULL; route_unlock_node(rn); // Lookup above diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 9a0fdda0f9..3205f13922 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -189,7 +189,7 @@ static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS) if (prefix_cmp(&ei->address, c->address) == 0) eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA); - connected_free(c); + connected_free(&c); return 0; } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 1d0e6549df..8343f7d85f 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -338,7 +338,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, if (ip) { listnode_delete(circuit->ip_addrs, ip); - prefix_ipv4_free(ip); + prefix_ipv4_free(&ip); if (circuit->area) lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); @@ -358,7 +358,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, zlog_warn("End of addresses"); } - prefix_ipv4_free(ipv4); + prefix_ipv4_free(&ipv4); } if (connected->address->family == AF_INET6) { ipv6 = prefix_ipv6_new(); @@ -374,7 +374,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, } if (ip6) { listnode_delete(circuit->ipv6_link, ip6); - prefix_ipv6_free(ip6); + prefix_ipv6_free(&ip6); found = 1; } } else { @@ -386,7 +386,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, } if (ip6) { listnode_delete(circuit->ipv6_non_link, ip6); - prefix_ipv6_free(ip6); + prefix_ipv6_free(&ip6); found = 1; } } @@ -417,7 +417,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); - prefix_ipv6_free(ipv6); + prefix_ipv6_free(&ipv6); } return; } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index bdf6869f5c..b4c699ccbb 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -128,7 +128,7 @@ static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS) if (if_is_operative(ifp)) isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c); - connected_free(c); + connected_free(&c); return 0; } diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 4df1fc0304..946b51e4ee 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -368,7 +368,7 @@ ldp_interface_address_delete(ZAPI_CALLBACK_ARGS) ifp = ifc->ifp; ifc2kaddr(ifp, ifc, &ka); - connected_free(ifc); + connected_free(&ifc); /* Filter invalid addresses. */ if (bad_addr(ka.af, &ka.addr)) @@ -140,6 +140,13 @@ static int if_cmp_index_func(const struct interface *ifp1, return ifp1->ifindex - ifp2->ifindex; } +static void ifp_connected_free(void *arg) +{ + struct connected *c = arg; + + connected_free(&c); +} + /* Create new interface structure. */ static struct interface *if_new(vrf_id_t vrf_id) { @@ -153,7 +160,7 @@ static struct interface *if_new(vrf_id_t vrf_id) ifp->vrf_id = vrf_id; ifp->connected = list_new(); - ifp->connected->del = (void (*)(void *))connected_free; + ifp->connected->del = ifp_connected_free; ifp->nbr_connected = list_new(); ifp->nbr_connected->del = (void (*)(void *))nbr_connected_free; @@ -178,7 +185,7 @@ void if_destroy_via_zapi(struct interface *ifp) if_set_index(ifp, IFINDEX_INTERNAL); if (!ifp->configured) - if_delete(ifp); + if_delete(&ifp); } void if_up_via_zapi(struct interface *ifp) @@ -276,27 +283,29 @@ void if_delete_retain(struct interface *ifp) } /* Delete and free interface structure. */ -void if_delete(struct interface *ifp) +void if_delete(struct interface **ifp) { + struct interface *ptr = *ifp; struct vrf *vrf; - vrf = vrf_lookup_by_id(ifp->vrf_id); + vrf = vrf_lookup_by_id(ptr->vrf_id); assert(vrf); - IFNAME_RB_REMOVE(vrf, ifp); - if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(vrf, ifp); + IFNAME_RB_REMOVE(vrf, ptr); + if (ptr->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(vrf, ptr); - if_delete_retain(ifp); + if_delete_retain(ptr); - list_delete(&ifp->connected); - list_delete(&ifp->nbr_connected); + list_delete(&ptr->connected); + list_delete(&ptr->nbr_connected); - if_link_params_free(ifp); + if_link_params_free(ptr); - XFREE(MTYPE_TMP, ifp->desc); + XFREE(MTYPE_TMP, ptr->desc); - XFREE(MTYPE_IF, ifp); + XFREE(MTYPE_IF, ptr); + *ifp = NULL; } /* Used only internally to check within VRF only */ @@ -866,24 +875,27 @@ struct nbr_connected *nbr_connected_new(void) } /* Free connected structure. */ -void connected_free(struct connected *connected) +void connected_free(struct connected **connected) { - if (connected->address) - prefix_free(connected->address); + struct connected *ptr = *connected; + + if (ptr->address) + prefix_free(&ptr->address); - if (connected->destination) - prefix_free(connected->destination); + if (ptr->destination) + prefix_free(&ptr->destination); - XFREE(MTYPE_CONNECTED_LABEL, connected->label); + XFREE(MTYPE_CONNECTED_LABEL, ptr->label); - XFREE(MTYPE_CONNECTED, connected); + XFREE(MTYPE_CONNECTED, ptr); + *connected = NULL; } /* Free nbr connected structure. */ void nbr_connected_free(struct nbr_connected *connected) { if (connected->address) - prefix_free(connected->address); + prefix_free(&connected->address); XFREE(MTYPE_NBR_CONNECTED, connected); } @@ -1159,7 +1171,7 @@ void if_terminate(struct vrf *vrf) ifp->node->info = NULL; route_unlock_node(ifp->node); } - if_delete(ifp); + if_delete(&ifp); } } @@ -1541,7 +1553,7 @@ static int lib_interface_destroy(enum nb_event event, ifp = nb_running_unset_entry(dnode); ifp->configured = false; - if_delete(ifp); + if_delete(&ifp); break; } @@ -513,7 +513,7 @@ extern void if_delete_retain(struct interface *); /* Delete and free the interface structure: calls if_delete_retain and then deletes it from the interface list and frees the structure. */ -extern void if_delete(struct interface *); +extern void if_delete(struct interface **ifp); extern int if_is_up(const struct interface *ifp); extern int if_is_running(const struct interface *ifp); @@ -543,7 +543,7 @@ extern ifindex_t ifname2ifindex(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new(void); -extern void connected_free(struct connected *); +extern void connected_free(struct connected **connected); extern void connected_add(struct interface *, struct connected *); extern struct connected * connected_add_by_prefix(struct interface *, struct prefix *, struct prefix *); diff --git a/lib/prefix.c b/lib/prefix.c index 5071ca8201..e2bf3b949c 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -905,9 +905,9 @@ struct prefix_ipv4 *prefix_ipv4_new(void) } /* Free prefix_ipv4 structure. */ -void prefix_ipv4_free(struct prefix_ipv4 *p) +void prefix_ipv4_free(struct prefix_ipv4 **p) { - prefix_free((struct prefix *)p); + prefix_free((struct prefix **)p); } /* If given string is valid return 1 else return 0 */ @@ -1077,9 +1077,9 @@ struct prefix_ipv6 *prefix_ipv6_new(void) } /* Free prefix for IPv6. */ -void prefix_ipv6_free(struct prefix_ipv6 *p) +void prefix_ipv6_free(struct prefix_ipv6 **p) { - prefix_free((struct prefix *)p); + prefix_free((struct prefix **)p); } /* If given string is valid return 1 else return 0 */ @@ -1484,10 +1484,18 @@ struct prefix *prefix_new(void) return p; } +void prefix_free_lists(void *arg) +{ + struct prefix *p = arg; + + prefix_free(&p); +} + /* Free prefix structure. */ -void prefix_free(struct prefix *p) +void prefix_free(struct prefix **p) { - XFREE(MTYPE_PREFIX, p); + XFREE(MTYPE_PREFIX, *p); + *p = NULL; } /* Utility function to convert ipv4 prefixes to Classful prefixes */ diff --git a/lib/prefix.h b/lib/prefix.h index 784927616a..7a93c766a3 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -396,7 +396,11 @@ extern unsigned int prefix6_bit(const struct in6_addr *prefix, const uint16_t prefixlen); extern struct prefix *prefix_new(void); -extern void prefix_free(struct prefix *); +extern void prefix_free(struct prefix **p); +/* + * Function to handle prefix_free being used as a del function. + */ +extern void prefix_free_lists(void *arg); extern const char *prefix_family_str(const struct prefix *); extern int prefix_blen(const struct prefix *); extern int str2prefix(const char *, struct prefix *); @@ -435,7 +439,7 @@ extern void prefix2sockunion(const struct prefix *, union sockunion *); extern int str2prefix_eth(const char *, struct prefix_eth *); extern struct prefix_ipv4 *prefix_ipv4_new(void); -extern void prefix_ipv4_free(struct prefix_ipv4 *); +extern void prefix_ipv4_free(struct prefix_ipv4 **p); extern int str2prefix_ipv4(const char *, struct prefix_ipv4 *); extern void apply_mask_ipv4(struct prefix_ipv4 *); @@ -460,7 +464,7 @@ extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen); extern int netmask_str2prefix_str(const char *, const char *, char *); extern struct prefix_ipv6 *prefix_ipv6_new(void); -extern void prefix_ipv6_free(struct prefix_ipv6 *); +extern void prefix_ipv6_free(struct prefix_ipv6 **p); extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *); extern void apply_mask_ipv6(struct prefix_ipv6 *); diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index e4f614c7c4..9f828a1c7d 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -364,7 +364,7 @@ int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS) nhrp_interface_update_address( ifc->ifp, family2afi(PREFIX_FAMILY(ifc->address)), 0); - connected_free(ifc); + connected_free(&ifc); return 0; } diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index d8a6a39e1e..6832737ada 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -143,7 +143,7 @@ static int ospf6_zebra_if_address_update_delete(ZAPI_CALLBACK_ARGS) ospf6_interface_state_update(c->ifp); } - connected_free(c); + connected_free(&c); return 0; } diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 1f5e0da944..5459e3b87c 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -902,11 +902,10 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, static void ospf_vl_if_delete(struct ospf_vl_data *vl_data) { - struct interface *ifp = vl_data->vl_oi->ifp; vl_data->vl_oi->address->u.prefix4.s_addr = 0; vl_data->vl_oi->address->prefixlen = 0; ospf_if_free(vl_data->vl_oi); - if_delete(ifp); + if_delete(&vl_data->vl_oi->ifp); vlink_count--; } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 5678d545ba..68d9d3bf83 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -150,7 +150,7 @@ static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS) rn = route_node_lookup(IF_OIFS(ifp), &p); if (!rn) { - connected_free(c); + connected_free(&c); return 0; } @@ -163,7 +163,7 @@ static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS) ospf_if_interface(c->ifp); - connected_free(c); + connected_free(&c); return 0; } diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 069b3e6c9b..e0fd147b0e 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -133,10 +133,8 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd, if (!pbrms->src) pbrms->src = prefix_new(); prefix_copy(pbrms->src, prefix); - } else { - prefix_free(pbrms->src); - pbrms->src = 0; - } + } else + prefix_free(&pbrms->src); pbr_map_check(pbrms); @@ -162,10 +160,8 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, if (!pbrms->dst) pbrms->dst = prefix_new(); prefix_copy(pbrms->dst, prefix); - } else { - prefix_free(pbrms->dst); - pbrms->dst = NULL; - } + } else + prefix_free(&pbrms->dst); pbr_map_check(pbrms); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 39e92467ab..719374e3b9 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -109,7 +109,7 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS) "%s: %s deleted %s", __PRETTY_FUNCTION__, c->ifp->name, prefix2str(c->address, buf, sizeof(buf))); - connected_free(c); + connected_free(&c); return 0; } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 722ecb2a72..3f2aaf2bbe 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -767,7 +767,7 @@ static void delete_from_neigh_addr(struct interface *ifp, other_neigh_str, ifp->name); listnode_delete(neigh->prefix_list, p); - prefix_free(p); + prefix_free(&p); } } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index d93a360448..4fe3237395 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -757,8 +757,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, */ if (!*hello_option_addr_list) { *hello_option_addr_list = list_new(); - (*hello_option_addr_list)->del = - (void (*)(void *))prefix_free; + (*hello_option_addr_list)->del = prefix_free_lists; } /* diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index dadcbbe65d..dfddee99d0 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -233,7 +233,7 @@ static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS) pim_i_am_rp_re_evaluate(pim); } - connected_free(c); + connected_free(&c); return 0; } diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 3173277ba7..4d48740606 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -648,7 +648,7 @@ int rip_interface_address_delete(ZAPI_CALLBACK_ARGS) rip_apply_address_del(ifc); } - connected_free(ifc); + connected_free(&ifc); } return 0; diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 9209a76460..97113a180f 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -430,7 +430,7 @@ int ripng_interface_address_delete(ZAPI_CALLBACK_ARGS) /* Check wether this prefix needs to be removed. */ ripng_apply_address_del(ifc); } - connected_free(ifc); + connected_free(&ifc); } return 0; diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index da2aa2f539..cd577e9051 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -73,7 +73,7 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS) if (!c) return 0; - connected_free(c); + connected_free(&c); return 0; } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 976f892efb..a474613b4d 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -79,7 +79,7 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS) if (!c) return 0; - connected_free(c); + connected_free(&c); return 0; } @@ -260,7 +260,7 @@ static void static_nht_hash_free(void *data) { struct static_nht_data *nhtd = data; - prefix_free(nhtd->nh); + prefix_free(&nhtd->nh); XFREE(MTYPE_TMP, nhtd); } diff --git a/tests/topotests/bgp-path-attributes-topo1/bgp_path_attributes.json b/tests/topotests/bgp-path-attributes-topo1/bgp_path_attributes.json index 15b7ec13be..de2bffa33d 100644 --- a/tests/topotests/bgp-path-attributes-topo1/bgp_path_attributes.json +++ b/tests/topotests/bgp-path-attributes-topo1/bgp_path_attributes.json @@ -12,6 +12,17 @@ "r2":{"ipv4":"auto", "ipv6":"auto"}, "r3":{"ipv4":"auto", "ipv6":"auto"} }, + "route_maps": { + "rmap_global": [{ + "action": "permit", + "set": { + "ipv6": { + "nexthop": "prefer-global" + } + } + } + ] + }, "bgp":{ "local_as":"555", "address_family": { @@ -20,8 +31,34 @@ "neighbor": { "r2": { "dest_link": { + "r1": { + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } + }, + "r3": { + "dest_link": { "r1": {} } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": { + "route_maps": [{ + "name": "rmap_global", + "direction": "in" + }] + } + } }, "r3": { "dest_link": { @@ -65,6 +102,27 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {} + } + }, + "r3": { + "dest_link": { + "r2": {} + } + }, + "r4": { + "dest_link": { + "r2-link1": {} + } + } + } + } } } } @@ -99,6 +157,27 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {} + } + }, + "r2": { + "dest_link": { + "r3": {} + } + }, + "r5": { + "dest_link": { + "r3": {} + } + } + } + } } } } @@ -128,6 +207,22 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r4-link1": {} + } + }, + "r6": { + "dest_link": { + "r4": {} + } + } + } + } } } } @@ -156,6 +251,22 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r5": {} + } + }, + "r7": { + "dest_link": { + "r5": {} + } + } + } + } } } } @@ -184,6 +295,22 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "r6": {} + } + }, + "r7": { + "dest_link": { + "r6": {} + } + } + } + } } } } @@ -212,6 +339,22 @@ } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r5": { + "dest_link": { + "r7": {} + } + }, + "r6": { + "dest_link": { + "r7": {} + } + } + } + } } } } diff --git a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py index 9f92b4b290..3b2d9c25d7 100755 --- a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py +++ b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py @@ -76,13 +76,14 @@ from lib.common_config import ( write_test_footer, reset_config_on_routers, verify_rib, create_static_routes, create_prefix_lists, verify_prefix_lists, - create_route_maps + create_route_maps, check_address_types ) from lib.topolog import logger from lib.bgp import ( verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify, verify_best_path_as_per_bgp_attribute, - verify_best_path_as_per_admin_distance + verify_best_path_as_per_admin_distance, modify_as_number, + verify_as_numbers ) from lib.topojson import build_topo_from_json, build_config_from_json @@ -95,6 +96,8 @@ try: except IOError: assert False, "Could not read file {}".format(jsonFile) +# Address read from env variables +ADDR_TYPES = check_address_types() #### class CreateTopo(Topo): @@ -119,6 +122,8 @@ def setup_module(mod): * `mod`: module name """ + global ADDR_TYPES + testsuite_run_time = time.asctime(time.localtime(time.time())) logger.info("Testsuite start time: %s", testsuite_run_time) logger.info("=" * 40) @@ -170,6 +175,7 @@ def teardown_module(): ## Testcases ## ##################################################### + def test_next_hop_attribute(request): """ Verifying route are not getting installed in, as next_hop is @@ -193,7 +199,7 @@ def test_next_hop_attribute(request): # Api call to advertise networks input_dict = { "r7": { - "bgp":{ + "bgp": { "address_family": { "ipv4": { "unicast": { @@ -206,6 +212,18 @@ def test_next_hop_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } @@ -218,9 +236,12 @@ def test_next_hop_attribute(request): # Verifying RIB routes dut = "r1" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False) - assert result is not True, "Testcase {} : Failed \n Error: Routes still" \ - " present in RIB".format(tc_name) + # Verification should fail as nexthop-self is not enabled + for addr_type in ADDR_TYPES: + result = verify_rib(tgen, addr_type, dut, input_dict, + protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "{} routes are not present in RIB".format(addr_type, tc_name) # Configure next-hop-self to bgp neighbor input_dict_1 = { @@ -237,6 +258,17 @@ def test_next_hop_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } + } + } + } } } } @@ -254,11 +286,23 @@ def test_next_hop_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + } + } + } } } } } } + result = create_router_bgp(tgen, topo, input_dict_1) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -266,9 +310,11 @@ def test_next_hop_attribute(request): # Verifying RIB routes dut = "r1" protocol = "bgp" - result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result) + for addr_type in ADDR_TYPES: + result = verify_rib(tgen, addr_type, dut, input_dict, + protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) write_test_footer(tc_name) @@ -305,6 +351,18 @@ def test_aspath_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } @@ -322,6 +380,17 @@ def test_aspath_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } + } + } + } } } } @@ -339,6 +408,17 @@ def test_aspath_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + } + } + } } } } @@ -351,11 +431,136 @@ def test_aspath_attribute(request): # Verifying best path dut = "r1" attribute = "aspath" - result = verify_best_path_as_per_bgp_attribute(tgen, "ipv4", dut, - input_dict, attribute) + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Modify AS-Path and verify best path is changed + # Create Prefix list + + input_dict_2 = { + "r3": { + "prefix_lists": { + "ipv4": { + "pf_ls_1_ipv4": [{ + "seqid": 10, + "network": "200.0.0.0/8", + "le": "32", + "action": "permit" + }] + }, + "ipv6": { + "pf_ls_1_ipv6": [{ + "seqid": 10, + "network": "200::/8", + "le": "128", + "action": "permit" + }] + } + } + } + } + result = create_prefix_lists(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Create route map + input_dict_3 = { + "r3": { + "route_maps": { + "RMAP_AS_PATH": [{ + "action": "permit", + "match": { + "ipv4": { + "prefix_lists": "pf_ls_1_ipv4" + } + }, + "set": { + "aspath": { + "as_num": "111 222", + "as_action": "prepend" + } + } + }, + { + "action": "permit", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_1_ipv6" + } + }, + "set": { + "aspath": { + "as_num": "111 222", + "as_action": "prepend" + } + } + }] + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Configure neighbor for route map + input_dict_4 = { + "r3": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r5": { + "dest_link": { + "r3": { + "route_maps": [ + {"name": "RMAP_AS_PATH", + "direction": "in"} + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r5": { + "dest_link": { + "r3": { + "route_maps": [ + {"name": "RMAP_AS_PATH", + "direction": "in"} + ] + } + } + } + } + } + } + } + } + } + } + result = create_router_bgp(tgen, topo, input_dict_4) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) + # Verifying best path + dut = "r1" + attribute = "aspath" + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + write_test_footer(tc_name) @@ -391,6 +596,18 @@ def test_localpref_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } @@ -408,6 +625,17 @@ def test_localpref_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } + } + } + } } } } @@ -425,11 +653,23 @@ def test_localpref_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + } + } + } } } } } } + result = create_router_bgp(tgen, topo, input_dict) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -439,12 +679,20 @@ def test_localpref_attribute(request): "r2": { "prefix_lists": { "ipv4": { - "pf_ls_1": [{ + "pf_ls_1_ipv4": [{ "seqid": 10, "network": "200.0.0.0/8", "le": "32", "action": "permit" }] + }, + "ipv6": { + "pf_ls_1_ipv6": [{ + "seqid": 10, + "network": "200::/8", + "le": "128", + "action": "permit" + }] } } } @@ -459,13 +707,26 @@ def test_localpref_attribute(request): "route_maps": { "RMAP_LOCAL_PREF": [{ "action": "permit", + "seq_id": "10", "match": { "ipv4": { - "prefix_lists": "pf_ls_1" + "prefix_lists": "pf_ls_1_ipv4" + } + }, + "set": { + "localpref": 1111 + } + }, + { + "action": "permit", + "seq_id": "20", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_1_ipv6" } }, "set": { - "localpref": 1000 + "localpref": 1111 } }] } @@ -483,9 +744,25 @@ def test_localpref_attribute(request): "ipv4": { "unicast": { "neighbor": { - "r1": { + "r4": { + "dest_link": { + "r2-link1": { + "route_maps": [ + {"name": "RMAP_LOCAL_PREF", + "direction": "in"} + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { "dest_link": { - "r2": { + "r2-link1": { "route_maps": [ {"name": "RMAP_LOCAL_PREF", "direction": "in"} @@ -500,7 +777,6 @@ def test_localpref_attribute(request): } } } - result = create_router_bgp(tgen, topo, input_dict_4) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -508,16 +784,66 @@ def test_localpref_attribute(request): # Verifying best path dut = "r1" attribute = "localpref" - result = verify_best_path_as_per_bgp_attribute(tgen, "ipv4", dut, - input_dict, attribute) + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Modify route map + input_dict_3 = { + "r2": { + "route_maps": { + "RMAP_LOCAL_PREF": [{ + "action": "permit", + "seq_id": "10", + "match": { + "ipv4": { + "prefix_lists": "pf_ls_1_ipv4" + } + }, + "set": { + "localpref": 50 + } + }, + { + "action": "permit", + "seq_id": "20", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_1_ipv6" + } + }, + "set": { + "localpref": 50 + } + }] + } + } + } + result = create_route_maps(tgen, input_dict_3) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) + # Verifying best path + dut = "r1" + attribute = "localpref" + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + write_test_footer(tc_name) def test_weight_attribute(request): - " Verifying WEIGHT attribute functionality" + """ + Test configure/modify weight attribute and + verify best path is installed as per highest weight + """ tgen = get_topogen() @@ -548,6 +874,18 @@ def test_weight_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } @@ -565,6 +903,17 @@ def test_weight_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } + } + } + } } } } @@ -582,6 +931,17 @@ def test_weight_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + } + } + } } } } @@ -596,12 +956,20 @@ def test_weight_attribute(request): "r1": { "prefix_lists": { "ipv4": { - "pf_ls_1": [{ + "pf_ls_1_ipv4": [{ "seqid": 10, "network": "200.0.0.0/8", "le": "32", "action": "permit" }] + }, + "ipv6": { + "pf_ls_1_ipv6": [{ + "seqid": 10, + "network": "200::/8", + "le": "128", + "action": "permit" + }] } } } @@ -616,9 +984,22 @@ def test_weight_attribute(request): "route_maps": { "RMAP_WEIGHT": [{ "action": "permit", + "seq_id": "5", "match": { "ipv4": { - "prefix_lists": "pf_ls_1" + "prefix_lists": "pf_ls_1_ipv4" + } + }, + "set": { + "weight": 500 + } + }, + { + "action": "permit", + "seq_id": "10", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_1_ipv6" } }, "set": { @@ -652,6 +1033,22 @@ def test_weight_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1": { + "route_maps": [ + {"name": "RMAP_WEIGHT", + "direction": "in"} + ] + } + } + } + } + } } } } @@ -664,16 +1061,66 @@ def test_weight_attribute(request): # Verifying best path dut = "r1" attribute = "weight" - result = verify_best_path_as_per_bgp_attribute(tgen, "ipv4", dut, - input_dict, attribute) + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Modify route map + input_dict_3 = { + "r1": { + "route_maps": { + "RMAP_WEIGHT": [{ + "action": "permit", + "seq_id": "5", + "match": { + "ipv4": { + "prefix_lists": "pf_ls_1_ipv4" + } + }, + "set": { + "weight": 1000 + } + }, + { + "action": "permit", + "seq_id": "10", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_1_ipv6" + } + }, + "set": { + "weight": 1000 + } + }] + } + } + } + result = create_route_maps(tgen, input_dict_3) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) + # Verifying best path + dut = "r1" + attribute = "weight" + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r7": input_dict["r7"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + write_test_footer(tc_name) def test_origin_attribute(request): - " Verifying ORIGIN attribute functionality" + """ + Test origin attribute and verify best path is + installed as per IGP>EGP>INCOMPLETE rule + """ tgen = get_topogen() @@ -704,6 +1151,18 @@ def test_origin_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } @@ -721,6 +1180,17 @@ def test_origin_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } + } + } + } } } } @@ -738,6 +1208,17 @@ def test_origin_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + } + } + } } } } @@ -752,6 +1233,14 @@ def test_origin_attribute(request): {"redist_type": "connected"} ] } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"}, + {"redist_type": "connected"} + ] + } } } } @@ -767,11 +1256,19 @@ def test_origin_attribute(request): "static_routes": [ { "network": "200.50.2.0/32", - "next_hop": "10.0.0.26" + "next_hop": "Null0" }, { "network": "200.60.2.0/32", - "next_hop": "10.0.0.26" + "next_hop": "Null0" + }, + { + "network": "200:50:2::/128", + "next_hop": "Null0" + }, + { + "network": "200:60:2::/128", + "next_hop": "Null0" } ] } @@ -780,23 +1277,24 @@ def test_origin_attribute(request): assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) - # Api call to redistribute static routes - - # Configure next-hop-self to bgp neighbor - # Verifying best path dut = "r1" attribute = "origin" - result = verify_best_path_as_per_bgp_attribute(tgen, "ipv4", dut, - input_dict, attribute) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result) + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + {"r4": input_dict["r4"]}, + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) write_test_footer(tc_name) def test_med_attribute(request): - " Verifying MED attribute functionality" + """ + Test configure/modify MED attribute and verify best path + is installed as per lowest med value + """ tgen = get_topogen() @@ -814,7 +1312,7 @@ def test_med_attribute(request): # Api call to advertise networks input_dict = { "r4": { - "bgp":{ + "bgp": { "address_family": { "ipv4": { "unicast": { @@ -827,49 +1325,102 @@ def test_med_attribute(request): } ] } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } + } + } + } + }, + "r5": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": "200.50.2.0/32" + }, + { + "network": "200.60.2.0/32" + } + ] + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": "200:50:2::/128" + }, + { + "network": "200:60:2::/128" + } + ] + } } } } } } + result = create_router_bgp(tgen, topo, input_dict) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) - # Api call to advertise networks - - - # Configure next-hop-self to bgp neighbor - - # Create Prefix list - input_dict_3 = { + input_dict_2 = { "r2": { "prefix_lists": { "ipv4": { - "pf_ls_r2": [{ + "pf_ls_r2_ipv4": [{ "seqid": 10, "network": "200.0.0.0/8", "le": "32", "action": "permit" }] + }, + "ipv6": { + "pf_ls_r2_ipv6": [{ + "seqid": 20, + "network": "200::/8", + "le": "128", + "action": "permit" + }] } } }, "r3": { "prefix_lists": { "ipv4": { - "pf_ls_r3": [{ + "pf_ls_r3_ipv4": [{ "seqid": 10, "network": "200.0.0.0/8", "le": "32", "action": "permit" }] + }, + "ipv6": { + "pf_ls_r3_ipv6": [{ + "seqid": 20, + "network": "200::/8", + "le": "128", + "action": "permit" + }] } } } } - result = create_prefix_lists(tgen, input_dict_3) + result = create_prefix_lists(tgen, input_dict_2) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -879,9 +1430,22 @@ def test_med_attribute(request): "route_maps": { "RMAP_MED_R2": [{ "action": "permit", + "seq_id": "10", "match": { "ipv4": { - "prefix_lists": "pf_ls_r2" + "prefix_lists": "pf_ls_r2_ipv4" + } + }, + "set": { + "med": 100 + } + }, + { + "action": "permit", + "seq_id": "20", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_r2_ipv6" } }, "set": { @@ -894,9 +1458,22 @@ def test_med_attribute(request): "route_maps": { "RMAP_MED_R3": [{ "action": "permit", + "seq_id": "10", "match": { "ipv4": { - "prefix_lists": "pf_ls_r3" + "prefix_lists": "pf_ls_r3_ipv4" + } + }, + "set": { + "med": 10 + } + }, + { + "action": "permit", + "seq_id": "20", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_r3_ipv6" } }, "set": { @@ -912,28 +1489,31 @@ def test_med_attribute(request): # Configure neighbor for route map input_dict_4 = { - "r5": { + "r2": { "bgp": { "address_family": { "ipv4": { "unicast": { - "advertise_networks": [ - { - "network": "200.50.2.0/32" + "neighbor": { + "r4": { + "dest_link": { + "r2-link1": { + "route_maps": [ + {"name": "RMAP_MED_R2", + "direction": "in"} + ] + } + } }, - { - "network": "200.60.2.0/32" + "r1": { + "dest_link": { + "r2": {"next_hop_self": True} + } } - ] + } } - } - } - } - }, - "r2": { - "bgp": { - "address_family": { - "ipv4": { + }, + "ipv6": { "unicast": { "neighbor": { "r4": { @@ -980,11 +1560,33 @@ def test_med_attribute(request): } } } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r3": {"next_hop_self": True} + } + }, + "r5": { + "dest_link": { + "r3": { + "route_maps": [ + {"name": "RMAP_MED_R3", + "direction": "in"} + ] + } + } + } + } + } } } } } } + result = create_router_bgp(tgen, topo, input_dict_4) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) @@ -992,12 +1594,58 @@ def test_med_attribute(request): # Verifying best path dut = "r1" attribute = "med" - result = verify_best_path_as_per_bgp_attribute(tgen, "ipv4", dut, + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, input_dict, attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # Modify route-map to set med value + input_dict_3 = { + "r3": { + "route_maps": { + "RMAP_MED_R3": [{ + "action": "permit", + "seq_id": "10", + "match": { + "ipv4": { + "prefix_lists": "pf_ls_r3_ipv4" + } + }, + "set": { + "med": 200 + } + }, + { + "action": "permit", + "seq_id": "20", + "match": { + "ipv6": { + "prefix_lists": "pf_ls_r3_ipv6" + } + }, + "set": { + "med": 200 + } + }] + } + } + } + + result = create_route_maps(tgen, input_dict_3) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result) - logger.info("Testcase %s :Passed \n", tc_name) + # Verifying best path + dut = "r1" + attribute = "med" + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut, + input_dict, attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + write_test_footer(tc_name) # Uncomment next line for debugging # tgen.mininet_cli() @@ -1032,6 +1680,16 @@ def test_admin_distance(request): "network": "200.50.2.0/32", "admin_distance": 60, "next_hop": "10.0.0.18" + }, + { + "network": "200:50:2::/128", + "admin_distance": 80, + "next_hop": "fd00::1" + }, + { + "network": "200:50:2::/128", + "admin_distance": 60, + "next_hop": "fd00::1" } ] } @@ -1052,6 +1710,14 @@ def test_admin_distance(request): {"redist_type": "connected"} ] } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"}, + {"redist_type": "connected"} + ] + } } } } @@ -1064,10 +1730,45 @@ def test_admin_distance(request): # Verifying best path dut = "r1" attribute = "admin_distance" - result = verify_best_path_as_per_admin_distance(tgen, "ipv4", dut, - input_dict, attribute) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result) + + input_dict = { + "ipv4": { + "r2": { + "static_routes": [{ + "network": "200.50.2.0/32", + "admin_distance": 80, + "next_hop": "10.0.0.14" + }, + { + "network": "200.50.2.0/32", + "admin_distance": 60, + "next_hop": "10.0.0.18" + } + ] + } + }, + "ipv6": { + "r2": { + "static_routes": [{ + "network": "200:50:2::/128", + "admin_distance": 80, + "next_hop": "fd00::1" + }, + { + "network": "200:50:2::/128", + "admin_distance": 60, + "next_hop": "fd00::1" + }] + } + } + } + + for addr_type in ADDR_TYPES: + result = verify_best_path_as_per_admin_distance(tgen, addr_type, dut, + input_dict[addr_type], + attribute) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) write_test_footer(tc_name) diff --git a/tests/topotests/ldp-vpls-topo1/r1/zebra.conf b/tests/topotests/ldp-vpls-topo1/r1/zebra.conf index edfa1780a9..ea047355ad 100644 --- a/tests/topotests/ldp-vpls-topo1/r1/zebra.conf +++ b/tests/topotests/ldp-vpls-topo1/r1/zebra.conf @@ -14,17 +14,14 @@ interface lo ! interface r1-eth0 description to s1 - no link-detect ! interface r1-eth1 description to s4 ip address 10.0.1.1/24 - no link-detect ! interface r1-eth2 description to s5 ip address 10.0.2.1/24 - no link-detect ! ip forwarding ! diff --git a/tests/topotests/ldp-vpls-topo1/r2/zebra.conf b/tests/topotests/ldp-vpls-topo1/r2/zebra.conf index 6b95efdce8..c244442876 100644 --- a/tests/topotests/ldp-vpls-topo1/r2/zebra.conf +++ b/tests/topotests/ldp-vpls-topo1/r2/zebra.conf @@ -13,17 +13,14 @@ interface lo ! interface r2-eth0 description to s2 - no link-detect ! interface r2-eth1 description to s4 ip address 10.0.1.2/24 - no link-detect ! interface r2-eth2 description to s6 ip address 10.0.3.2/24 - no link-detect ! ip forwarding ! diff --git a/tests/topotests/ldp-vpls-topo1/r3/zebra.conf b/tests/topotests/ldp-vpls-topo1/r3/zebra.conf index 85ec68ff32..6b1eaa2ca0 100644 --- a/tests/topotests/ldp-vpls-topo1/r3/zebra.conf +++ b/tests/topotests/ldp-vpls-topo1/r3/zebra.conf @@ -13,17 +13,14 @@ interface lo ! interface r3-eth0 description to s3 - no link-detect ! interface r3-eth1 description to s5 ip address 10.0.2.3/24 - no link-detect ! interface r3-eth2 description to s6 ip address 10.0.3.3/24 - no link-detect ! ip forwarding ! diff --git a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py index ce651c50cd..0fae64402a 100755 --- a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py +++ b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py @@ -257,6 +257,7 @@ def test_ldp_pseudowires_after_link_down(): # Shut down r1-r2 link */ tgen = get_topogen() tgen.gears['r1'].peer_link_enable('r1-eth1', False) + topotest.sleep(5, "Waiting for the network to reconverge") # check if the pseudowire is still up (using an alternate path for nexthop resolution) for rname in ['r1', 'r2', 'r3']: diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index 7ec584bf5f..a8354f4c77 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -112,6 +112,8 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False): input_dict = deepcopy(topo) else: topo = topo["routers"] + input_dict = deepcopy(input_dict) + for router in input_dict.keys(): if "bgp" not in input_dict[router]: logger.debug("Router %s: 'bgp' not present in input_dict", router) @@ -220,7 +222,7 @@ def __create_bgp_unicast_neighbor(tgen, topo, input_dict, router, logger.debug("Entering lib API: __create_bgp_unicast_neighbor()") add_neigh = True - if "router bgp "in config_data: + if "router bgp" in config_data: add_neigh = False bgp_data = input_dict[router]["bgp"]["address_family"] @@ -1366,7 +1368,7 @@ def verify_bgp_attributes(tgen, addr_type, dut, static_routes, rmap_name, logger.debug("Exiting lib API: verify_bgp_attributes()") return True -@retry(attempts=3, wait=2, return_is_str=True) +@retry(attempts=4, wait=2, return_is_str=True, initial_wait=2) def verify_best_path_as_per_bgp_attribute(tgen, addr_type, router, input_dict, attribute): """ @@ -1422,16 +1424,14 @@ def verify_best_path_as_per_bgp_attribute(tgen, addr_type, router, input_dict, rnode = tgen.routers()[router] - # TODO get addr_type from address - # Verifying show bgp json command = "show bgp {} json".format(addr_type) - sleep(2) + sleep(5) logger.info("Verifying router %s RIB for best path:", router) sh_ip_bgp_json = run_frr_cmd(rnode, command, isjson=True) for route_val in input_dict.values(): - net_data = route_val["bgp"]["address_family"]["ipv4"]["unicast"] + net_data = route_val["bgp"]["address_family"][addr_type]["unicast"] networks = net_data["advertise_networks"] for network in networks: route = network["network"] @@ -1503,8 +1503,8 @@ def verify_best_path_as_per_bgp_attribute(tgen, addr_type, router, input_dict, if route in rib_routes_json: st_found = True # Verify next_hop in rib_routes_json - if rib_routes_json[route][0]["nexthops"][0]["ip"] == \ - _next_hop: + if rib_routes_json[route][0]["nexthops"][0]["ip"] in \ + attribute_dict: nh_found = True else: errormsg = "Incorrect Nexthop for BGP route {} in " \ @@ -1526,7 +1526,6 @@ def verify_best_path_as_per_bgp_attribute(tgen, addr_type, router, input_dict, return True -@retry(attempts=3, wait=2, return_is_str=True) def verify_best_path_as_per_admin_distance(tgen, addr_type, router, input_dict, attribute): """ @@ -1568,7 +1567,7 @@ def verify_best_path_as_per_admin_distance(tgen, addr_type, router, input_dict, rnode = tgen.routers()[router] - sleep(2) + sleep(5) logger.info("Verifying router %s RIB for best path:", router) # Show ip route cmd diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 38b97cba2d..9f2fef52ea 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -1202,6 +1202,7 @@ def create_route_maps(tgen, input_dict, build=False): "large_comm_list", {}) set_action = set_data.setdefault("set_action", None) nexthop = set_data.setdefault("nexthop", None) + origin = set_data.setdefault("origin", None) # Local Preference if local_preference: @@ -1212,6 +1213,10 @@ def create_route_maps(tgen, input_dict, build=False): if metric: rmap_data.append("set metric {} \n".format(metric)) + # Origin + if origin: + rmap_data.append("set origin {} \n".format(origin)) + # AS Path Prepend if as_path: as_num = as_path.setdefault("as_num", None) @@ -1628,9 +1633,10 @@ def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): static_routes = input_dict[routerInput]["static_routes"] st_found = False nh_found = False - found_routes = [] - missing_routes = [] for static_route in static_routes: + found_routes = [] + missing_routes = [] + network = static_route["network"] if "no_of_ip" in static_route: no_of_ip = static_route["no_of_ip"] @@ -1667,6 +1673,7 @@ def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): return errormsg else: missing_routes.append(st_rt) + if nh_found: logger.info("Found next_hop %s for all routes in RIB of" " router %s\n", next_hop, dut) @@ -1679,37 +1686,69 @@ def verify_rib(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None): logger.info("Verified routes in router %s RIB, found routes" " are: %s\n", dut, found_routes) - advertise_network = input_dict[routerInput].setdefault( - "advertise_networks", {}) - if advertise_network: - found_routes = [] - missing_routes = [] - found = False - for advertise_network_dict in advertise_network: - start_ip = advertise_network_dict["network"] - if "no_of_network" in advertise_network_dict: - no_of_network = advertise_network_dict["no_of_network"] - else: - no_of_network = 0 + continue - # Generating IPs for verification - ip_list = generate_ips(start_ip, no_of_network) - for st_rt in ip_list: - st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) + if "bgp" in input_dict[routerInput]: + if 'advertise_networks' in input_dict[routerInput]["bgp"]\ + ["address_family"][addr_type]["unicast"]: - if st_rt in rib_routes_json: - found = True - found_routes.append(st_rt) + found_routes = [] + missing_routes = [] + advertise_network = input_dict[routerInput]["bgp"]\ + ["address_family"][addr_type]["unicast"]\ + ["advertise_networks"] + + for advertise_network_dict in advertise_network: + start_ip = advertise_network_dict["network"] + if "no_of_network" in advertise_network_dict: + no_of_network = advertise_network_dict["no_of_network"] else: - missing_routes.append(st_rt) + no_of_network = 1 + + # Generating IPs for verification + ip_list = generate_ips(start_ip, no_of_network) + for st_rt in ip_list: + st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) + + found = False + nh_found = False + if st_rt in rib_routes_json: + found = True + found_routes.append(st_rt) + + if next_hop: + if type(next_hop) is not list: + next_hop = [next_hop] + + for index, nh in enumerate(next_hop): + if rib_routes_json[st_rt][0]\ + ['nexthops'][index]['ip'] == nh: + nh_found = True + else: + errormsg=("Nexthop {} is Missing" + " for {} route {} in " + "RIB of router {}\n".\ + format(next_hop, + protocol, + st_rt, dut)) + return errormsg - if not found and len(missing_routes) > 0: - errormsg = "Missing route in RIB of router {}, are: {}" \ - " \n".format(dut, missing_routes) - return errormsg + else: + missing_routes.append(st_rt) - logger.info("Verified routes in router %s RIB, found routes" - " are: %s", dut, found_routes) + if nh_found: + logger.info("Found next_hop {} for all routes in RIB" + " of router {}\n".format(next_hop, dut)) + + if not found and len(missing_routes) > 0: + errormsg = ("Missing {} route in RIB of router {}, " + "routes: {} \n".\ + format(addr_type, dut, missing_routes)) + return errormsg + + logger.info("Verified {} routes in router {} RIB, found" + " routes are: {}\n".\ + format(addr_type, dut, found_routes)) logger.debug("Exiting lib API: verify_rib()") return True diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index d7145c3be0..6859f5a076 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -61,6 +61,7 @@ from mininet.cli import CLI from lib import topotest from lib.topolog import logger, logger_config +from lib.topotest import set_sysctl CWD = os.path.dirname(os.path.realpath(__file__)) @@ -676,6 +677,10 @@ class TopoRouter(TopoGear): if result != '': self.tgen.set_error(result) + else: + # Enable MPLS processing on all interfaces. + for interface in self.links.keys(): + set_sysctl(nrouter, 'net.mpls.conf.{}.input'.format(interface), 1) return result diff --git a/zebra/connected.c b/zebra/connected.c index 75f4f53bc6..0ff474d787 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -65,7 +65,7 @@ static void connected_withdraw(struct connected *ifc) if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { listnode_delete(ifc->ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } } @@ -177,7 +177,7 @@ static void connected_update(struct interface *ifp, struct connected *ifc) */ if (connected_same(current, ifc)) { /* nothing to do */ - connected_free(ifc); + connected_free(&ifc); return; } diff --git a/zebra/interface.c b/zebra/interface.c index daa93e36d1..eea80652e5 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -738,7 +738,7 @@ static void if_delete_connected(struct interface *ifp) ZEBRA_IFC_CONFIGURED)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } else last = node; } @@ -759,7 +759,7 @@ static void if_delete_connected(struct interface *ifp) last = node; else { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } } else { last = node; @@ -829,7 +829,7 @@ void if_delete_update(struct interface *ifp) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("interface %s is being deleted from the system", ifp->name); - if_delete(ifp); + if_delete(&ifp); } } @@ -2878,7 +2878,7 @@ static int ip_address_uninstall(struct vty *vty, struct interface *ifp, if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); return CMD_WARNING_CONFIG_FAILED; } @@ -3103,7 +3103,7 @@ static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); return CMD_WARNING_CONFIG_FAILED; } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4e0163f8ac..98603c9693 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -718,8 +718,8 @@ int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id, if (afi >= AFI_MAX) return (-1); - table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, vrf_id, - table_id); + table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, vrf_id, + table_id); if (table == NULL) { return 0; } else if (IS_ZEBRA_DEBUG_RIB) { @@ -830,8 +830,8 @@ static void zebra_import_table_rm_update_vrf_afi(struct zebra_vrf *zvrf, if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) return; - table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, - zvrf->vrf->vrf_id, table_id); + table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, + zvrf->vrf->vrf_id, table_id); if (!table) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("%s: Table id=%d not found", __func__, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index e0bf1a58f2..c24a518afb 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1575,10 +1575,9 @@ rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) /* Locate rn and re(s) from ctx */ - table = zebra_vrf_table_with_table_id(dplane_ctx_get_afi(ctx), - dplane_ctx_get_safi(ctx), - dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx)); + table = zebra_vrf_lookup_table_with_table_id( + dplane_ctx_get_afi(ctx), dplane_ctx_get_safi(ctx), + dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx)); if (table == NULL) { if (IS_ZEBRA_DEBUG_DPLANE) { zlog_debug("Failed to find route for ctx: no table for afi %d, safi %d, vrf %u", @@ -2664,7 +2663,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); + table = zebra_vrf_get_table_with_table_id(afi, safi, re->vrf_id, + re->table); if (!table) { if (re->ng) nexthop_group_delete(&re->ng); @@ -2809,7 +2809,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id, + table_id); if (!table) return; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index f425c0e49e..c392303760 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -343,13 +343,12 @@ int zebra_vrf_has_config(struct zebra_vrf *zvrf) * - case VRF backend is default : on default VRF only * - case VRF backend is netns : on all VRFs */ -struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, - vrf_id_t vrf_id, - uint32_t table_id) +struct route_table *zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id) { struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); struct other_route_table ort, *otable; - struct route_table *table; if (!zvrf) return NULL; @@ -364,9 +363,28 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, ort.safi = safi; ort.table_id = table_id; otable = otable_find(&zvrf->other_tables, &ort); + if (otable) return otable->table; + return NULL; +} + +struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); + struct other_route_table *otable; + struct route_table *table; + + table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id, + table_id); + + if (table) + goto done; + + /* Create it as an `other` table */ table = zebra_router_get_table(zvrf, table_id, afi, safi); otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable)); @@ -376,6 +394,7 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, otable->table = table; otable_add(&zvrf->other_tables, otable); +done: return table; } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 6c80f9bcb4..5448e17073 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -233,9 +233,13 @@ zvrf_other_table_compare_func(const struct other_route_table *a, DECLARE_RBTREE_UNIQ(otable, struct other_route_table, next, zvrf_other_table_compare_func) -struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, - vrf_id_t vrf_id, - uint32_t table_id); +extern struct route_table * +zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, + uint32_t table_id); +extern struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, + safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id); extern void zebra_vrf_update_all(struct zserv *client); extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9d17454730..12517f3135 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1708,10 +1708,9 @@ DEFPY (show_route_summary, if ((zvrf = vrf->info) == NULL) continue; - table = zebra_vrf_table_with_table_id(afi, - SAFI_UNICAST, - zvrf->vrf->vrf_id, - table_id); + table = zebra_vrf_lookup_table_with_table_id( + afi, SAFI_UNICAST, zvrf->vrf->vrf_id, table_id); + if (!table) continue; @@ -1726,9 +1725,8 @@ DEFPY (show_route_summary, if (vrf_name) VRF_GET_ID(vrf_id, vrf_name, false); - table = zebra_vrf_table_with_table_id(afi, - SAFI_UNICAST, - vrf_id, table_id); + table = zebra_vrf_lookup_table_with_table_id(afi, SAFI_UNICAST, + vrf_id, table_id); if (!table) return CMD_SUCCESS; |
