summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el8
-rw-r--r--bgpd/bgp_debug.c14
-rw-r--r--bgpd/bgp_dump.c6
-rw-r--r--bgpd/bgp_nht.c62
-rw-r--r--bgpd/bgp_route.c26
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/rfapi/rfapi_import.c4
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c12
-rw-r--r--doc/developer/testing.rst1
-rw-r--r--doc/developer/topotests-jsontopo.rst88
-rw-r--r--eigrpd/eigrp_network.c3
-rw-r--r--eigrpd/eigrp_topology.c2
-rw-r--r--eigrpd/eigrp_zebra.c2
-rw-r--r--isisd/isis_circuit.c10
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--ldpd/ldp_zebra.c2
-rw-r--r--lib/if.c58
-rw-r--r--lib/if.h4
-rw-r--r--lib/prefix.c20
-rw-r--r--lib/prefix.h10
-rw-r--r--nhrpd/nhrp_interface.c2
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_interface.c3
-rw-r--r--ospfd/ospf_zebra.c4
-rw-r--r--pbrd/pbr_vty.c12
-rw-r--r--pbrd/pbr_zebra.c2
-rw-r--r--pimd/pim_neighbor.c2
-rw-r--r--pimd/pim_tlv.c3
-rw-r--r--pimd/pim_zebra.c2
-rw-r--r--ripd/rip_interface.c2
-rw-r--r--ripngd/ripng_interface.c2
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--staticd/static_zebra.c4
-rw-r--r--tests/topotests/bgp-path-attributes-topo1/bgp_path_attributes.json143
-rwxr-xr-xtests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py841
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/zebra.conf3
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/zebra.conf3
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/zebra.conf3
-rwxr-xr-xtests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py1
-rw-r--r--tests/topotests/lib/bgp.py19
-rw-r--r--tests/topotests/lib/common_config.py95
-rw-r--r--tests/topotests/lib/topogen.py5
-rw-r--r--zebra/connected.c4
-rw-r--r--zebra/interface.c10
-rw-r--r--zebra/redistribute.c8
-rw-r--r--zebra/zebra_rib.c13
-rw-r--r--zebra/zebra_vrf.c27
-rw-r--r--zebra/zebra_vrf.h10
-rw-r--r--zebra/zebra_vty.c12
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))
diff --git a/lib/if.c b/lib/if.c
index 7c3606bbbf..9d0f13ecbd 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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;
}
diff --git a/lib/if.h b/lib/if.h
index 6322290937..4ca2e79572 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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;