summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el4
-rw-r--r--bgpd/bgp_attr.c6
-rw-r--r--bgpd/bgp_attr.h6
-rw-r--r--bgpd/bgp_route.c7
-rw-r--r--bgpd/bgp_route.h5
-rw-r--r--bgpd/bgp_updgrp_adv.c24
-rw-r--r--bgpd/bgp_vty.c24
-rw-r--r--bgpd/bgp_zebra.c33
-rw-r--r--doc/developer/cli.rst171
-rw-r--r--doc/developer/topotests.rst42
-rw-r--r--eigrpd/eigrp_northbound.c17
-rw-r--r--isisd/isis_snmp.c21
-rw-r--r--lib/command.c1
-rw-r--r--lib/command_graph.c4
-rw-r--r--lib/command_graph.h1
-rw-r--r--lib/command_lex.l1
-rw-r--r--lib/command_match.c25
-rw-r--r--lib/command_parse.y16
-rw-r--r--lib/command_py.c39
-rw-r--r--lib/nexthop.c5
-rw-r--r--lib/nexthop.h3
-rw-r--r--lib/routemap.c17
-rw-r--r--lib/routemap.h9
-rw-r--r--lib/vrf.c15
-rw-r--r--lib/vrf.h1
-rw-r--r--ospf6d/ospf6_abr.c13
-rw-r--r--ospf6d/ospf6_area.h14
-rw-r--r--ospf6d/ospf6_asbr.c21
-rw-r--r--ospf6d/ospf6_interface.h22
-rw-r--r--ospf6d/ospf6_intra.c20
-rw-r--r--ospf6d/ospf6_intra.h10
-rw-r--r--ospf6d/ospf6_lsa.h19
-rw-r--r--ospf6d/ospf6_neighbor.h32
-rw-r--r--ospf6d/ospf6_nssa.h10
-rw-r--r--ospf6d/ospf6_route.h8
-rw-r--r--ospf6d/ospf6_zebra.h19
-rw-r--r--pathd/path_cli.c9
-rw-r--r--tests/lib/cli/test_cli.c4
-rw-r--r--tests/lib/cli/test_cli.in17
-rw-r--r--tests/lib/cli/test_cli.refout.in96
-rw-r--r--tests/lib/test_nexthop.c6
-rw-r--r--tests/topotests/all_protocol_startup/test_all_protocol_startup.py6
-rw-r--r--tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py8
-rw-r--r--tests/topotests/bgp_evpn_overlay_index_gateway/host2/zebra.conf2
-rwxr-xr-xtests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py7
-rw-r--r--tests/topotests/example_test/r1/zebra.conf8
-rw-r--r--tests/topotests/example_test/r2/zebra.conf4
-rw-r--r--tests/topotests/example_test/test_template.py140
-rw-r--r--tests/topotests/lib/common_config.py1
-rw-r--r--tests/topotests/lib/topotest.py13
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py26
-rw-r--r--tests/topotests/route_scale/scale_test_common.py (renamed from tests/topotests/route_scale/test_route_scale.py)68
-rw-r--r--tests/topotests/route_scale/test_route_scale1.py77
-rw-r--r--tests/topotests/route_scale/test_route_scale2.py77
-rw-r--r--tests/topotests/zebra_netlink/r1/sharpd.conf0
-rw-r--r--tests/topotests/zebra_netlink/r1/v4_route.json2302
-rw-r--r--tests/topotests/zebra_netlink/test_zebra_netlink.py95
-rw-r--r--tests/zebra/test_lm_plugin.c6
-rw-r--r--tools/permutations.c16
-rw-r--r--zebra/zapi_msg.c3
-rw-r--r--zebra/zebra_evpn_neigh.c2
-rw-r--r--zebra/zebra_fpm.c6
-rw-r--r--zebra/zebra_fpm_netlink.c7
-rw-r--r--zebra/zebra_fpm_private.h2
-rw-r--r--zebra/zebra_ptm.c8
-rw-r--r--zebra/zebra_vty.c14
66 files changed, 1035 insertions, 2680 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index 1332f7b6a2..b2d7cf376d 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -5,6 +5,4 @@
((c-mode . ((indent-tabs-mode . t)
(show-trailing-whitespace . t)
(c-basic-offset . 8)))
- (json-mode . ((js-indent-level 4)))
- (python-mode . ((python-formatter . black)
- (python-fill-column . 88))))
+ (json-mode . ((js-indent-level 4))))
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index f1c953f21d..eeb0ac5c6a 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -691,6 +691,8 @@ unsigned int attrhash_key_make(const void *p)
key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
MIX(attr->rmap_table_id);
+ MIX(attr->nh_type);
+ MIX(attr->bh_type);
return key;
}
@@ -747,7 +749,9 @@ bool attrhash_cmp(const void *p1, const void *p2)
&& attr1->distance == attr2->distance
&& srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
&& srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
- && attr1->srte_color == attr2->srte_color)
+ && attr1->srte_color == attr2->srte_color
+ && attr1->nh_type == attr2->nh_type
+ && attr1->bh_type == attr2->bh_type)
return true;
}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index a583581030..6c49cf509f 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -307,6 +307,12 @@ struct attr {
/* EVPN DF preference and algorithm for DF election on local ESs */
uint16_t df_pref;
uint8_t df_alg;
+
+ /* Nexthop type */
+ enum nexthop_types_t nh_type;
+
+ /* If NEXTHOP_TYPE_BLACKHOLE, then blackhole type */
+ enum blackhole_type bh_type;
};
/* rmap_change_flags definition */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b164d710a5..db0ee58e72 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -8066,8 +8066,9 @@ DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const union g_addr *nexthop, ifindex_t ifindex,
enum nexthop_types_t nhtype, uint8_t distance,
- uint32_t metric, uint8_t type,
- unsigned short instance, route_tag_t tag)
+ enum blackhole_type bhtype, uint32_t metric,
+ uint8_t type, unsigned short instance,
+ route_tag_t tag)
{
struct bgp_path_info *new;
struct bgp_path_info *bpi;
@@ -8109,8 +8110,10 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
break;
}
+ attr.bh_type = bhtype;
break;
}
+ attr.nh_type = nhtype;
attr.nh_ifindex = ifindex;
attr.med = metric;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 75da2723e6..d052a3f408 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -642,8 +642,9 @@ extern bool bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const union g_addr *nexthop, ifindex_t ifindex,
enum nexthop_types_t nhtype, uint8_t distance,
- uint32_t metric, uint8_t type,
- unsigned short instance, route_tag_t tag);
+ enum blackhole_type bhtype, uint32_t metric,
+ uint8_t type, unsigned short instance,
+ route_tag_t tag);
extern void bgp_redistribute_delete(struct bgp *, struct prefix *, uint8_t,
unsigned short);
extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, unsigned short);
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 9c2288cba3..3b7ee8b0b6 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -812,6 +812,10 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
}
if (peer->default_rmap[afi][safi].name) {
+ struct bgp_path_info tmp_pi = {0};
+
+ tmp_pi.peer = bgp->peer_self;
+
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
/* Iterate over the RIB to see if we can announce
@@ -825,24 +829,16 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
pi = pi->next) {
- struct attr tmp_attr;
- struct bgp_path_info tmp_pi;
- struct bgp_path_info_extra tmp_pie;
+ struct attr tmp_attr = attr;
- tmp_attr = *pi->attr;
- tmp_attr.aspath = attr.aspath;
+ tmp_pi.attr = &tmp_attr;
- prep_for_rmap_apply(&tmp_pi, &tmp_pie, dest, pi,
- pi->peer, &tmp_attr);
-
- ret = route_map_apply(
+ ret = route_map_apply_ext(
peer->default_rmap[afi][safi].map,
- bgp_dest_get_prefix(dest), &tmp_pi);
+ bgp_dest_get_prefix(dest), pi, &tmp_pi);
if (ret == RMAP_DENYMATCH) {
- /* The aspath belongs to 'attr' */
- tmp_attr.aspath = NULL;
- bgp_attr_flush(&tmp_attr);
+ bgp_attr_undup(&tmp_attr, &attr);
continue;
} else {
new_attr = bgp_attr_intern(&tmp_attr);
@@ -939,6 +935,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
subgroup_default_update_packet(subgrp, new_attr, from);
}
}
+
+ aspath_unintern(&attr.aspath);
}
/*
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 6e427c0b7c..2f9b8b86cf 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9974,21 +9974,12 @@ static void bgp_show_failed_summary(struct vty *vty, struct bgp *bgp,
}
}
-/* If the peer's description includes whitespaces
- * then return the first occurrence. Also strip description
- * to the given size if needed.
- */
+/* Strip peer's description to the given size. */
static char *bgp_peer_description_stripped(char *desc, uint32_t size)
{
static char stripped[BUFSIZ];
- char *pnt;
uint32_t len = size > strlen(desc) ? strlen(desc) : size;
- pnt = strchr(desc, ' ');
- if (pnt)
- len = size > (uint32_t)(pnt - desc) ? (uint32_t)(pnt - desc)
- : size;
-
strlcpy(stripped, desc, len + 1);
return stripped;
@@ -10020,7 +10011,15 @@ static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
return false;
}
-/* Show BGP peer's summary information. */
+/* Show BGP peer's summary information.
+ *
+ * Peer's description is stripped according to if `wide` option is given
+ * or not.
+ *
+ * When adding new columns to `show bgp summary` output, please make
+ * sure `Desc` is the lastest column to show because it can contain
+ * whitespaces and the whole output will be tricky.
+ */
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
struct peer *fpeer, int as_type, as_t as,
uint16_t show_flags)
@@ -10685,6 +10684,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
vty_out(vty, " %8u", 0);
}
+ /* Make sure `Desc` column is the lastest in
+ * the output.
+ */
if (peer->desc)
vty_out(vty, " %s",
bgp_peer_description_stripped(
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 5ef49e5108..b0d0c844f3 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -472,8 +472,9 @@ static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS)
static int zebra_read_route(ZAPI_CALLBACK_ARGS)
{
enum nexthop_types_t nhtype;
+ enum blackhole_type bhtype = BLACKHOLE_UNSPEC;
struct zapi_route api;
- union g_addr nexthop;
+ union g_addr nexthop = {};
ifindex_t ifindex;
int add, i;
struct bgp *bgp;
@@ -494,10 +495,16 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
&& IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
return 0;
- nexthop = api.nexthops[0].gate;
ifindex = api.nexthops[0].ifindex;
nhtype = api.nexthops[0].type;
+ /* api_nh structure has union of gate and bh_type */
+ if (nhtype == NEXTHOP_TYPE_BLACKHOLE) {
+ /* bh_type is only applicable if NEXTHOP_TYPE_BLACKHOLE*/
+ bhtype = api.nexthops[0].bh_type;
+ } else
+ nexthop = api.nexthops[0].gate;
+
add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
if (add) {
/*
@@ -517,8 +524,8 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
/* Now perform the add/update. */
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
- nhtype, api.distance, api.metric, api.type,
- api.instance, api.tag);
+ nhtype, bhtype, api.distance, api.metric,
+ api.type, api.instance, api.tag);
} else {
bgp_redistribute_delete(bgp, &api.prefix, api.type,
api.instance);
@@ -1076,8 +1083,10 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
* a VRF (which are programmed as onlink on l3-vni SVI) as well as
* connected routes leaked into a VRF.
*/
- if (is_evpn) {
-
+ if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) {
+ api_nh->type = attr->nh_type;
+ api_nh->bh_type = attr->bh_type;
+ } else if (is_evpn) {
/*
* If the nexthop is EVPN overlay index gateway IP,
* treat the nexthop as NEXTHOP_TYPE_IPV4
@@ -1090,8 +1099,7 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
api_nh->ifindex = nh_bgp->l3vni_svi_ifindex;
}
- } else if (nh_othervrf &&
- api_nh->gate.ipv4.s_addr == INADDR_ANY) {
+ } else if (nh_othervrf && api_nh->gate.ipv4.s_addr == INADDR_ANY) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = attr->nh_ifindex;
} else
@@ -1113,8 +1121,10 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
attr = pi->attr;
api_nh->vrf_id = nh_bgp->vrf_id;
- if (is_evpn) {
-
+ if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) {
+ api_nh->type = attr->nh_type;
+ api_nh->bh_type = attr->bh_type;
+ } else if (is_evpn) {
/*
* If the nexthop is EVPN overlay index gateway IP,
* treat the nexthop as NEXTHOP_TYPE_IPV4
@@ -1169,7 +1179,8 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
api_nh->ifindex = 0;
}
}
- if (nexthop)
+ /* api_nh structure has union of gate and bh_type */
+ if (nexthop && api_nh->type != NEXTHOP_TYPE_BLACKHOLE)
api_nh->gate.ipv6 = *nexthop;
return true;
diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst
index edabe61d92..9254eb4739 100644
--- a/doc/developer/cli.rst
+++ b/doc/developer/cli.rst
@@ -139,6 +139,7 @@ by the parser.
selector: "<" `selector_seq_seq` ">" `varname_token`
: "{" `selector_seq_seq` "}" `varname_token`
: "[" `selector_seq_seq` "]" `varname_token`
+ : "![" `selector_seq_seq` "]" `varname_token`
selector_seq_seq: `selector_seq_seq` "|" `selector_token_seq`
: `selector_token_seq`
selector_token_seq: `selector_token_seq` `selector_token`
@@ -218,6 +219,10 @@ one-or-more selection and repetition.
provide mutual exclusion. User input matches at most one option.
- ``[square brackets]`` -- Contains sequences of tokens that can be omitted.
``[<a|b>]`` can be shortened to ``[a|b]``.
+- ``![exclamation square brackets]`` -- same as ``[square brackets]``, but
+ only allow skipping the contents if the command input starts with ``no``.
+ (For cases where the positive command needs a parameter, but the parameter
+ is optional for the negative case.)
- ``{curly|braces}`` -- similar to angle brackets, but instead of mutual
exclusion, curly braces indicate that one or more of the pipe-separated
sequences may be provided in any order.
@@ -767,6 +772,172 @@ User input:
``ip`` partially matches ``ipv6`` but exactly matches ``ip``, so ``ip`` will
win.
+Adding a CLI Node
+-----------------
+
+To add a new CLI node, you should:
+
+- define a new numerical node constant
+- define a node structure in the relevant daemon
+- call ``install_node()`` in the relevant daemon
+- define and install the new node in vtysh
+- define corresponding node entry commands in daemon and vtysh
+- add a new entry to the ``ctx_keywords`` dictionary in ``tools/frr-reload.py``
+
+Defining the numerical node constant
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Add your new node value to the enum before ``NODE_TYPE_MAX`` in
+``lib/command.h``:
+
+.. code-block:: c
+
+ enum node_type {
+ AUTH_NODE, // Authentication mode of vty interface.
+ VIEW_NODE, // View node. Default mode of vty interface.
+ [...]
+ MY_NEW_NODE,
+ NODE_TYPE_MAX, // maximum
+ };
+
+Defining a node structure
+^^^^^^^^^^^^^^^^^^^^^^^^^
+In your daemon-specific code where you define your new commands that
+attach to the new node, add a node definition:
+
+.. code-block:: c
+
+ static struct cmd_node my_new_node = {
+ .name = "my new node name",
+ .node = MY_NEW_NODE, // enum node_type lib/command.h
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(my-new-node-prompt)# ",
+ .config_write = my_new_node_config_write,
+ };
+
+You will need to define ``my_new_node_config_write(struct vty \*vty)``
+(or omit this field if you have no relevant configuration to save).
+
+Calling ``install_node()``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+In the daemon's initialization function, before installing your new commands
+with ``install_element()``, add a call ``install_node(&my_new_node)``.
+
+Defining and installing the new node in vtysh
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The build tools automatically collect command definitions for vtysh.
+However, new nodes must be coded in vtysh specifically.
+
+In ``vtysh/vtysh.c``, define a stripped-down node structure and
+call ``install_node()``:
+
+.. code-block:: c
+
+ static struct cmd_node my_new_node = {
+ .name = "my new node name",
+ .node = MY_NEW_NODE, /* enum node_type lib/command.h */
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(my-new-node-prompt)# ",
+ };
+ [...]
+ void vtysh_init_vty(void)
+ {
+ [...]
+ install_node(&my_new_node)
+ [...]
+ }
+
+Defining corresponding node entry commands in daemon and vtysh
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The command that descends into the new node is typically programmed
+with ``VTY_PUSH_CONTEXT`` or equivalent in the daemon's CLI handler function.
+(If the CLI has been updated to use the new northbound architecture,
+``VTY_PUSH_XPATH`` is used instead.)
+
+In vtysh, you must implement a corresponding node change so that vtysh
+tracks the daemon's movement through the node tree.
+
+Although the build tools typically scan daemon code for CLI definitions
+to replicate their parsing in vtysh, the node-descent function in the
+daemon must be blocked from this replication so that a hand-coded
+skeleton can be written in ``vtysh.c``.
+
+Accordingly, use one of the ``*_NOSH`` macros such as ``DEFUN_NOSH``,
+``DEFPY_NOSH``, or ``DEFUN_YANG_NOSH`` for the daemon's node-descent
+CLI definition, and use ``DEFUNSH`` in ``vtysh.c`` for the vtysh equivalent.
+
+.. seealso:: :ref:`vtysh-special-defuns`
+
+Examples:
+
+``zebra_whatever.c``
+
+.. code-block:: c
+
+ DEFPY_NOSH(my_new_node,
+ my_new_node_cmd,
+ "my-new-node foo",
+ "New Thing\n"
+ "A foo\n")
+ {
+ [...]
+ VTY_PUSH_CONTEXT(MY_NEW_NODE, bar);
+ [...]
+ }
+
+
+``ripd_whatever.c``
+
+.. code-block:: c
+
+ DEFPY_YANG_NOSH(my_new_node,
+ my_new_node_cmd,
+ "my-new-node foo",
+ "New Thing\n"
+ "A foo\n")
+ {
+ [...]
+ VTY_PUSH_XPATH(MY_NEW_NODE, xbar);
+ [...]
+ }
+
+
+``vtysh.c``
+
+.. code-block:: c
+
+ DEFUNSH(VTYSH_ZEBRA, my_new_node,
+ my_new_node_cmd,
+ "my-new-node foo",
+ "New Thing\n"
+ "A foo\n")
+ {
+ vty->node = MY_NEW_NODE;
+ return CMD_SUCCESS;
+ }
+ [...]
+ install_element(CONFIG_NODE, &my_new_node_cmd);
+
+
+Adding a new entry to the ``ctx_keywords`` dictionary
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In file ``tools/frr-reload.py``, the ``ctx_keywords`` dictionary
+describes the various node relationships.
+Add a new node entry at the appropriate level in this dictionary.
+
+.. code-block:: python
+
+ ctx_keywords = {
+ [...]
+ "key chain ": {
+ "key ": {}
+ },
+ [...]
+ "my-new-node": {},
+ [...]
+ }
+
+
+
Inspection & Debugging
----------------------
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
index fa6a1ba660..c52d210ee5 100644
--- a/doc/developer/topotests.rst
+++ b/doc/developer/topotests.rst
@@ -983,22 +983,20 @@ Writing Tests
"""""""""""""
Test topologies should always be bootstrapped from
-:file:`tests/topotests/example-test/test_template.py` because it contains
+:file:`tests/topotests/example_test/test_template.py` because it contains
important boilerplate code that can't be avoided, like:
Example:
.. code:: py
- # For all registered routers, load the zebra configuration file
- CWD = os.path.dirname(os.path.realpath(__file__))
- for rname, router in router_list.items():
- router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname))
- )
- # os.path.join() joins the CWD string with arguments adding the necessary
- # slashes ('/'). Arguments must not begin with '/'.
+ # For all routers arrange for:
+ # - starting zebra using config file from <rtrname>/zebra.conf
+ # - starting ospfd using an empty config file.
+ for rname, router in router_list.items():
+ router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ router.load_config(TopoRouter.RD_OSPF)
+
- The topology definition or build function
@@ -1013,27 +1011,31 @@ Example:
# topology build code
...
-- pytest ``setup_module()`` and ``teardown_module()`` to start the topology
+- pytest setup/teardown fixture to start the topology and supply `tgen` argument
+ to tests.
.. code:: py
- def setup_module(module):
+
+ @pytest.fixture(scope="module")
+ def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
tgen = Topogen(topodef, module.__name__)
# or
tgen = Topogen(build_topo, module.__name__)
- tgen.start_topology('debug')
+ ...
- def teardown_module(_m):
- tgen = get_topogen()
- tgen.stop_topology()
+ # Start and configure the router daemons
+ tgen.start_router()
-- ``__main__`` initialization code (to support running the script directly)
+ # Provide tgen as argument to each test function
+ yield tgen
-.. code:: py
+ # Teardown after last test runs
+ tgen.stop_topology()
- if __name__ == '__main__':
- sys.exit(pytest.main(["-s"]))
Requirements:
diff --git a/eigrpd/eigrp_northbound.c b/eigrpd/eigrp_northbound.c
index 482667f633..3ad711164b 100644
--- a/eigrpd/eigrp_northbound.c
+++ b/eigrpd/eigrp_northbound.c
@@ -79,6 +79,7 @@ static int eigrpd_instance_create(struct nb_cb_create_args *args)
{
struct eigrp *eigrp;
const char *vrf;
+ struct vrf *pVrf;
vrf_id_t vrfid;
switch (args->event) {
@@ -87,7 +88,12 @@ static int eigrpd_instance_create(struct nb_cb_create_args *args)
break;
case NB_EV_PREPARE:
vrf = yang_dnode_get_string(args->dnode, "./vrf");
- vrfid = vrf_name_to_id(vrf);
+
+ pVrf = vrf_lookup_by_name(vrf);
+ if (pVrf)
+ vrfid = pVrf->vrf_id;
+ else
+ vrfid = VRF_DEFAULT;
eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
vrfid);
@@ -719,12 +725,19 @@ static int eigrpd_instance_redistribute_create(struct nb_cb_create_args *args)
struct eigrp *eigrp;
uint32_t proto;
vrf_id_t vrfid;
+ struct vrf *pVrf;
switch (args->event) {
case NB_EV_VALIDATE:
proto = yang_dnode_get_enum(args->dnode, "./protocol");
vrfname = yang_dnode_get_string(args->dnode, "../vrf");
- vrfid = vrf_name_to_id(vrfname);
+
+ pVrf = vrf_lookup_by_name(vrfname);
+ if (pVrf)
+ vrfid = pVrf->vrf_id;
+ else
+ vrfid = VRF_DEFAULT;
+
if (vrf_bitmap_check(zclient->redist[AFI_IP][proto], vrfid))
return NB_ERR_INCONSISTENCY;
break;
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
index d530faa151..c530eb9169 100644
--- a/isisd/isis_snmp.c
+++ b/isisd/isis_snmp.c
@@ -283,13 +283,6 @@ SNMP_LOCAL_VARIABLES
*
* 2. I could be replaced in unit test environment
*/
-#ifndef ISIS_SNMP_HAVE_TIME_FUNC
-static uint32_t isis_snmp_time(void)
-{
- return (uint32_t)time(NULL);
-}
-
-#endif
/* ISIS-MIB instances. */
static oid isis_oid[] = {ISIS_MIB};
@@ -2083,7 +2076,7 @@ static uint8_t *isis_snmp_find_circ(struct variable *v, oid *name,
struct isis_circuit *circuit;
uint32_t up_ticks;
uint32_t delta_ticks;
- uint32_t now_time;
+ time_t now_time;
int res;
*write_method = NULL;
@@ -2191,7 +2184,7 @@ static uint8_t *isis_snmp_find_circ(struct variable *v, oid *name,
return SNMP_INTEGER(0);
up_ticks = (uint32_t)netsnmp_get_agent_uptime();
- now_time = isis_snmp_time();
+ now_time = time(NULL);
if (circuit->last_uptime >= now_time)
return SNMP_INTEGER(up_ticks);
@@ -2501,11 +2494,11 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
oid *oid_idx;
size_t oid_idx_len;
int res;
- uint32_t val;
+ time_t val;
struct isis_adjacency *adj;
uint32_t up_ticks;
uint32_t delta_ticks;
- uint32_t now_time;
+ time_t now_time;
*write_method = NULL;
@@ -2577,7 +2570,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
* It seems that we want remaining timer
*/
if (adj->last_upd != 0) {
- val = isis_snmp_time();
+ val = time(NULL);
if (val < (adj->last_upd + adj->hold_time))
return SNMP_INTEGER(adj->last_upd
+ adj->hold_time - val);
@@ -2594,7 +2587,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
up_ticks = (uint32_t)netsnmp_get_agent_uptime();
- now_time = isis_snmp_time();
+ now_time = time(NULL);
if (adj->last_flap >= now_time)
return SNMP_INTEGER(up_ticks);
@@ -2853,7 +2846,7 @@ static int isis_snmp_trap_throttle(oid trap_id)
if (isis == NULL || !isis->snmp_notifications || !smux_enabled())
return 0;
- time_now = isis_snmp_time();
+ time_now = time(NULL);
if ((isis_snmp_trap_timestamp[trap_id] + 5) > time_now)
/* Throttle trap rate at 1 in 5 secs */
diff --git a/lib/command.c b/lib/command.c
index fcaf466c65..53aa064705 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -74,6 +74,7 @@ const struct message tokennames[] = {
item(JOIN_TKN),
item(START_TKN),
item(END_TKN),
+ item(NEG_ONLY_TKN),
{0},
};
/* clang-format on */
diff --git a/lib/command_graph.c b/lib/command_graph.c
index c6c3840455..15c8302e63 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -388,6 +388,7 @@ static void cmd_node_names(struct graph_node *gn, struct graph_node *join,
case START_TKN:
case JOIN_TKN:
+ case NEG_ONLY_TKN:
/* "<foo|bar> WORD" -> word is not "bar" or "foo" */
prevname = NULL;
break;
@@ -511,6 +512,9 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
case JOIN_TKN:
color = "#ddaaff";
break;
+ case NEG_ONLY_TKN:
+ color = "#ffddaa";
+ break;
case WORD_TKN:
color = "#ffffff";
break;
diff --git a/lib/command_graph.h b/lib/command_graph.h
index 2754dca67d..c20c9874c2 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -64,6 +64,7 @@ enum cmd_token_type {
JOIN_TKN, // marks subgraph end
START_TKN, // first token in line
END_TKN, // last token in line
+ NEG_ONLY_TKN, // filter token, match if "no ..." command
SPECIAL_TKN = FORK_TKN,
};
diff --git a/lib/command_lex.l b/lib/command_lex.l
index 9c096995f5..ec366ce7e1 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -82,6 +82,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
{VARIABLE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return VARIABLE;}
{WORD} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return WORD;}
{RANGE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return RANGE;}
+!\[ {yylval->string = NULL; return EXCL_BRACKET;}
. {return yytext[0];}
%%
diff --git a/lib/command_match.c b/lib/command_match.c
index 5703510148..56a7ae422b 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -42,7 +42,7 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack");
/* matcher helper prototypes */
static int add_nexthops(struct list *, struct graph_node *,
- struct graph_node **, size_t);
+ struct graph_node **, size_t, bool);
static enum matcher_rv command_match_r(struct graph_node *, vector,
unsigned int, struct graph_node **,
@@ -79,6 +79,13 @@ static enum match_type match_variable(struct cmd_token *, const char *);
static enum match_type match_mac(const char *, bool);
+static bool is_neg(vector vline, size_t idx)
+{
+ if (idx >= vector_active(vline))
+ return false;
+ return !strcmp(vector_slot(vline, idx), "no");
+}
+
enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
struct list **argv, const struct cmd_element **el)
{
@@ -248,7 +255,7 @@ static enum matcher_rv command_match_r(struct graph_node *start, vector vline,
// get all possible nexthops
struct list *next = list_new();
- add_nexthops(next, start, NULL, 0);
+ add_nexthops(next, start, NULL, 0, is_neg(vline, 1));
// determine the best match
for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) {
@@ -349,6 +356,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
{
// pointer to next input token to match
char *input_token;
+ bool neg = is_neg(vline, 0);
struct list *
current =
@@ -363,7 +371,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
// add all children of start node to list
struct graph_node *start = vector_slot(graph->nodes, 0);
- add_nexthops(next, start, &start, 0);
+ add_nexthops(next, start, &start, 0, neg);
unsigned int idx;
for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++) {
@@ -428,7 +436,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
listnode_add(next, newstack);
} else if (matchtype >= minmatch)
add_nexthops(next, gstack[0], gstack,
- idx + 1);
+ idx + 1, neg);
break;
default:
trace_matcher("no_match\n");
@@ -478,7 +486,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
* output, instead of direct node pointers!
*/
static int add_nexthops(struct list *list, struct graph_node *node,
- struct graph_node **stack, size_t stackpos)
+ struct graph_node **stack, size_t stackpos, bool neg)
{
int added = 0;
struct graph_node *child;
@@ -494,8 +502,13 @@ static int add_nexthops(struct list *list, struct graph_node *node,
if (j != stackpos)
continue;
}
+
+ if (token->type == NEG_ONLY_TKN && !neg)
+ continue;
+
if (token->type >= SPECIAL_TKN && token->type != END_TKN) {
- added += add_nexthops(list, child, stack, stackpos);
+ added +=
+ add_nexthops(list, child, stack, stackpos, neg);
} else {
if (stack) {
nextstack = XMALLOC(
diff --git a/lib/command_parse.y b/lib/command_parse.y
index f5e42cc304..3e2cdc79af 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -105,6 +105,9 @@
%token <string> MAC
%token <string> MAC_PREFIX
+/* special syntax, value is irrelevant */
+%token <string> EXCL_BRACKET
+
/* union types for parsed rules */
%type <node> start
%type <node> literal_token
@@ -372,6 +375,19 @@ selector: '[' selector_seq_seq ']' varname_token
}
;
+/* ![option] productions */
+selector: EXCL_BRACKET selector_seq_seq ']' varname_token
+{
+ struct graph_node *neg_only = new_token_node (ctx, NEG_ONLY_TKN, NULL, NULL);
+
+ $$ = $2;
+ graph_add_edge ($$.start, neg_only);
+ graph_add_edge (neg_only, $$.end);
+ cmd_token_varname_set ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
+}
+;
+
%%
#undef scanner
diff --git a/lib/command_py.c b/lib/command_py.c
index 7f19008fbf..90344ae1e5 100644
--- a/lib/command_py.c
+++ b/lib/command_py.c
@@ -197,21 +197,30 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,
if (gn->data) {
struct cmd_token *tok = gn->data;
switch (tok->type) {
-#define item(x) case x: wrap->type = #x; break;
- item(WORD_TKN) // words
- item(VARIABLE_TKN) // almost anything
- item(RANGE_TKN) // integer range
- item(IPV4_TKN) // IPV4 addresses
- item(IPV4_PREFIX_TKN) // IPV4 network prefixes
- item(IPV6_TKN) // IPV6 prefixes
- item(IPV6_PREFIX_TKN) // IPV6 network prefixes
- item(MAC_TKN) // MAC address
- item(MAC_PREFIX_TKN) // MAC address with mask
-
- /* plumbing types */
- item(FORK_TKN) item(JOIN_TKN) item(START_TKN)
- item(END_TKN) default
- : wrap->type = "???";
+#define item(x) \
+ case x: \
+ wrap->type = #x; \
+ break /* no semicolon */
+
+ item(WORD_TKN); // words
+ item(VARIABLE_TKN); // almost anything
+ item(RANGE_TKN); // integer range
+ item(IPV4_TKN); // IPV4 addresses
+ item(IPV4_PREFIX_TKN); // IPV4 network prefixes
+ item(IPV6_TKN); // IPV6 prefixes
+ item(IPV6_PREFIX_TKN); // IPV6 network prefixes
+ item(MAC_TKN); // MAC address
+ item(MAC_PREFIX_TKN); // MAC address with mask
+
+ /* plumbing types */
+ item(FORK_TKN);
+ item(JOIN_TKN);
+ item(START_TKN);
+ item(END_TKN);
+ item(NEG_ONLY_TKN);
+#undef item
+ default:
+ wrap->type = "???";
}
wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED);
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 23e3a2b733..98409c76c5 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -519,12 +519,13 @@ struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6,
return nexthop;
}
-struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type)
+struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type,
+ vrf_id_t nh_vrf_id)
{
struct nexthop *nexthop;
nexthop = nexthop_new();
- nexthop->vrf_id = VRF_DEFAULT;
+ nexthop->vrf_id = nh_vrf_id;
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
nexthop->bh_type = bh_type;
diff --git a/lib/nexthop.h b/lib/nexthop.h
index dd65509aec..320b46315e 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -182,7 +182,8 @@ struct nexthop *nexthop_from_ipv6(const struct in6_addr *ipv6,
vrf_id_t vrf_id);
struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6,
ifindex_t ifindex, vrf_id_t vrf_id);
-struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type);
+struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type,
+ vrf_id_t nh_vrf_id);
/*
* Hash a nexthop. Suitable for use with hash tables.
diff --git a/lib/routemap.c b/lib/routemap.c
index 594dcf97cb..5c60b7d1c6 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -2488,8 +2488,9 @@ void route_map_notify_pentry_dependencies(const char *affected_name,
We need to make sure our route-map processing matches the above
*/
-route_map_result_t route_map_apply(struct route_map *map,
- const struct prefix *prefix, void *object)
+route_map_result_t route_map_apply_ext(struct route_map *map,
+ const struct prefix *prefix,
+ void *match_object, void *set_object)
{
static int recursion = 0;
enum route_map_cmd_result_t match_ret = RMAP_NOMATCH;
@@ -2516,7 +2517,7 @@ route_map_result_t route_map_apply(struct route_map *map,
if ((!map->optimization_disabled)
&& (map->ipv4_prefix_table || map->ipv6_prefix_table)) {
- index = route_map_get_index(map, prefix, object,
+ index = route_map_get_index(map, prefix, match_object,
(uint8_t *)&match_ret);
if (index) {
index->applied++;
@@ -2551,7 +2552,7 @@ route_map_result_t route_map_apply(struct route_map *map,
index->applied++;
/* Apply this index. */
match_ret = route_map_apply_match(&index->match_list,
- prefix, object);
+ prefix, match_object);
if (rmap_debug) {
zlog_debug(
"Route-map: %s, sequence: %d, prefix: %pFX, result: %s",
@@ -2610,7 +2611,7 @@ route_map_result_t route_map_apply(struct route_map *map,
* return code.
*/
(void)(*set->cmd->func_apply)(
- set->value, prefix, object);
+ set->value, prefix, set_object);
/* Call another route-map if available */
if (index->nextrm) {
@@ -2622,8 +2623,10 @@ route_map_result_t route_map_apply(struct route_map *map,
jump to it */
{
recursion++;
- ret = route_map_apply(
- nextrm, prefix, object);
+ ret = route_map_apply_ext(
+ nextrm, prefix,
+ match_object,
+ set_object);
recursion--;
}
diff --git a/lib/routemap.h b/lib/routemap.h
index b356dbf52e..2c8eb24537 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -443,9 +443,12 @@ extern struct route_map *route_map_lookup_by_name(const char *name);
struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *name);
/* Apply route map to the object. */
-extern route_map_result_t route_map_apply(struct route_map *map,
- const struct prefix *prefix,
- void *object);
+extern route_map_result_t route_map_apply_ext(struct route_map *map,
+ const struct prefix *prefix,
+ void *match_object,
+ void *set_object);
+#define route_map_apply(map, prefix, object) \
+ route_map_apply_ext(map, prefix, object, object)
extern void route_map_add_hook(void (*func)(const char *));
extern void route_map_delete_hook(void (*func)(const char *));
diff --git a/lib/vrf.c b/lib/vrf.c
index f9307d3039..198d5253c8 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -384,21 +384,6 @@ const char *vrf_id_to_name(vrf_id_t vrf_id)
return VRF_LOGNAME(vrf);
}
-vrf_id_t vrf_name_to_id(const char *name)
-{
- struct vrf *vrf;
- vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
- // id/ routine not used.
-
- if (!name)
- return vrf_id;
- vrf = vrf_lookup_by_name(name);
- if (vrf)
- vrf_id = vrf->vrf_id;
-
- return vrf_id;
-}
-
/* Get the data pointer of the specified VRF. If not found, create one. */
void *vrf_info_get(vrf_id_t vrf_id)
{
diff --git a/lib/vrf.h b/lib/vrf.h
index 9949ec4112..dab83d42da 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -119,7 +119,6 @@ extern struct vrf *vrf_lookup_by_name(const char *);
extern struct vrf *vrf_get(vrf_id_t, const char *);
extern struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name);
extern const char *vrf_id_to_name(vrf_id_t vrf_id);
-extern vrf_id_t vrf_name_to_id(const char *);
#define VRF_LOGNAME(V) V ? V->name : "Unknown"
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index aa85475678..fe1845907f 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -1201,9 +1201,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
__func__, &prefix, listcount(old->paths));
}
for (old_route = old; old_route; old_route = old_route->next) {
- if (!ospf6_route_is_same(old_route, route) ||
- (old_route->type != route->type) ||
- (old_route->path.type != route->path.type))
+
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
+ */
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if ((old_route->type != route->type)
+ || (old_route->path.type != route->path.type))
continue;
if ((ospf6_route_cmp(route, old_route) != 0)) {
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index b2a275d745..aed9589bfb 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -149,16 +149,18 @@ extern void area_id2str(char *buf, int len, uint32_t area_id, int area_id_fmt);
extern int ospf6_area_cmp(void *va, void *vb);
-extern struct ospf6_area *ospf6_area_create(uint32_t, struct ospf6 *, int);
-extern void ospf6_area_delete(struct ospf6_area *);
-extern struct ospf6_area *ospf6_area_lookup(uint32_t, struct ospf6 *);
+extern struct ospf6_area *ospf6_area_create(uint32_t area_id,
+ struct ospf6 *ospf6, int df);
+extern void ospf6_area_delete(struct ospf6_area *oa);
+extern struct ospf6_area *ospf6_area_lookup(uint32_t area_id,
+ struct ospf6 *ospf6);
extern struct ospf6_area *ospf6_area_lookup_by_area_id(uint32_t area_id);
extern void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area);
-extern void ospf6_area_enable(struct ospf6_area *);
-extern void ospf6_area_disable(struct ospf6_area *);
+extern void ospf6_area_enable(struct ospf6_area *oa);
+extern void ospf6_area_disable(struct ospf6_area *oa);
-extern void ospf6_area_show(struct vty *, struct ospf6_area *,
+extern void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
json_object *json_areas, bool use_json);
extern void ospf6_area_plist_update(struct prefix_list *plist, int add);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index b5bf81c213..90c9fdf23a 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -262,8 +262,14 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
next_route = old_route->next;
- if (!ospf6_route_is_same(old_route, route)
- || (old_route->path.type != route->path.type))
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
+ */
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if (old_route->path.type != route->path.type)
continue;
/* Current and New route has same origin,
@@ -367,11 +373,14 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
/* Add new route */
for (old_route = old; old_route; old_route = old_route->next) {
- /* Current and New Route prefix or route type
- * is not same skip this current node.
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
*/
- if (!ospf6_route_is_same(old_route, route)
- || (old_route->path.type != route->path.type))
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if (old_route->path.type != route->path.type)
continue;
/* Old Route and New Route have Equal Cost, Merge NHs */
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index ccdf8b1c8f..ee24b989bd 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -193,23 +193,23 @@ extern void ospf6_interface_stop(struct ospf6_interface *oi);
extern struct ospf6_interface *
ospf6_interface_lookup_by_ifindex(ifindex_t, vrf_id_t vrf_id);
-extern struct ospf6_interface *ospf6_interface_create(struct interface *);
-extern void ospf6_interface_delete(struct ospf6_interface *);
+extern struct ospf6_interface *ospf6_interface_create(struct interface *ifp);
+extern void ospf6_interface_delete(struct ospf6_interface *oi);
-extern void ospf6_interface_enable(struct ospf6_interface *);
-extern void ospf6_interface_disable(struct ospf6_interface *);
+extern void ospf6_interface_enable(struct ospf6_interface *oi);
+extern void ospf6_interface_disable(struct ospf6_interface *oi);
-extern void ospf6_interface_state_update(struct interface *);
-extern void ospf6_interface_connected_route_update(struct interface *);
+extern void ospf6_interface_state_update(struct interface *ifp);
+extern void ospf6_interface_connected_route_update(struct interface *ifp);
extern struct in6_addr *
ospf6_interface_get_global_address(struct interface *ifp);
/* interface event */
-extern int interface_up(struct thread *);
-extern int interface_down(struct thread *);
-extern int wait_timer(struct thread *);
-extern int backup_seen(struct thread *);
-extern int neighbor_change(struct thread *);
+extern int interface_up(struct thread *thread);
+extern int interface_down(struct thread *thread);
+extern int wait_timer(struct thread *thread);
+extern int backup_seen(struct thread *thread);
+extern int neighbor_change(struct thread *thread);
extern void ospf6_interface_init(void);
extern void ospf6_interface_clear(struct interface *ifp);
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index e4db8f3a02..06a950156b 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1470,8 +1470,14 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
for (old_route = old; old_route; old_route = old_route->next) {
bool route_updated = false;
- if (!ospf6_route_is_same(old_route, route) ||
- (old_route->path.type != route->path.type))
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
+ */
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if (old_route->path.type != route->path.type)
continue;
/* Current and New route has same origin,
@@ -1569,8 +1575,14 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
for (old_route = old; old_route; old_route = old_route->next) {
- if (!ospf6_route_is_same(old_route, route) ||
- (old_route->path.type != route->path.type))
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
+ */
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if (old_route->path.type != route->path.type)
continue;
/* Old Route and New Route have Equal Cost, Merge NHs */
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 9c29681dee..4031ffe689 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -221,11 +221,11 @@ extern char *ospf6_network_lsdesc_lookup(uint32_t router_id,
struct ospf6_lsa *lsa);
extern int ospf6_router_is_stub_router(struct ospf6_lsa *lsa);
-extern int ospf6_router_lsa_originate(struct thread *);
-extern int ospf6_network_lsa_originate(struct thread *);
-extern int ospf6_link_lsa_originate(struct thread *);
-extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *);
-extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *);
+extern int ospf6_router_lsa_originate(struct thread *thread);
+extern int ospf6_network_lsa_originate(struct thread *thread);
+extern int ospf6_link_lsa_originate(struct thread *thread);
+extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread);
+extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread);
extern void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa);
extern void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa);
extern int ospf6_orig_as_external_lsa(struct thread *thread);
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index a8ed9132dd..c271965fe7 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -231,10 +231,11 @@ extern int metric_type(struct ospf6 *ospf6, int type, uint8_t instance);
extern int metric_value(struct ospf6 *ospf6, int type, uint8_t instance);
extern int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
extern int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
-extern uint16_t ospf6_lsa_age_current(struct ospf6_lsa *);
-extern void ospf6_lsa_age_update_to_send(struct ospf6_lsa *, uint32_t);
-extern void ospf6_lsa_premature_aging(struct ospf6_lsa *);
-extern int ospf6_lsa_compare(struct ospf6_lsa *, struct ospf6_lsa *);
+extern uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa);
+extern void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa,
+ uint32_t transdelay);
+extern void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa);
+extern int ospf6_lsa_compare(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
extern char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size);
extern void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header);
@@ -254,16 +255,16 @@ extern struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header);
extern struct ospf6_lsa *
ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header);
extern void ospf6_lsa_delete(struct ospf6_lsa *lsa);
-extern struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *);
+extern struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa);
extern struct ospf6_lsa *ospf6_lsa_lock(struct ospf6_lsa *lsa);
extern struct ospf6_lsa *ospf6_lsa_unlock(struct ospf6_lsa *lsa);
-extern int ospf6_lsa_expire(struct thread *);
-extern int ospf6_lsa_refresh(struct thread *);
+extern int ospf6_lsa_expire(struct thread *thread);
+extern int ospf6_lsa_refresh(struct thread *thread);
-extern unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *);
-extern int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *);
+extern unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsah);
+extern int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsah);
extern int ospf6_lsa_prohibited_duration(uint16_t type, uint32_t id,
uint32_t adv_router, void *scope);
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index a229897226..30e044da4b 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -183,24 +183,24 @@ extern const char *const ospf6_neighbor_state_str[];
int ospf6_neighbor_cmp(void *va, void *vb);
void ospf6_neighbor_dbex_init(struct ospf6_neighbor *on);
-struct ospf6_neighbor *ospf6_neighbor_lookup(uint32_t,
- struct ospf6_interface *);
-struct ospf6_neighbor *ospf6_neighbor_create(uint32_t,
- struct ospf6_interface *);
-void ospf6_neighbor_delete(struct ospf6_neighbor *);
+struct ospf6_neighbor *ospf6_neighbor_lookup(uint32_t router_id,
+ struct ospf6_interface *oi);
+struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
+ struct ospf6_interface *oi);
+void ospf6_neighbor_delete(struct ospf6_neighbor *on);
/* Neighbor event */
-extern int hello_received(struct thread *);
-extern int twoway_received(struct thread *);
-extern int negotiation_done(struct thread *);
-extern int exchange_done(struct thread *);
-extern int loading_done(struct thread *);
-extern int adj_ok(struct thread *);
-extern int seqnumber_mismatch(struct thread *);
-extern int bad_lsreq(struct thread *);
-extern int oneway_received(struct thread *);
-extern int inactivity_timer(struct thread *);
-extern void ospf6_check_nbr_loading(struct ospf6_neighbor *);
+extern int hello_received(struct thread *thread);
+extern int twoway_received(struct thread *thread);
+extern int negotiation_done(struct thread *thread);
+extern int exchange_done(struct thread *thread);
+extern int loading_done(struct thread *thread);
+extern int adj_ok(struct thread *thread);
+extern int seqnumber_mismatch(struct thread *thread);
+extern int bad_lsreq(struct thread *thread);
+extern int oneway_received(struct thread *thread);
+extern int inactivity_timer(struct thread *thread);
+extern void ospf6_check_nbr_loading(struct ospf6_neighbor *on);
extern void ospf6_neighbor_init(void);
extern int config_write_ospf6_debug_neighbor(struct vty *vty);
diff --git a/ospf6d/ospf6_nssa.h b/ospf6d/ospf6_nssa.h
index 454bdd7fe2..631503edc6 100644
--- a/ospf6d/ospf6_nssa.h
+++ b/ospf6d/ospf6_nssa.h
@@ -52,11 +52,11 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area);
int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area);
extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p);
-extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *,
- struct ospf6_lsa *,
- struct ospf6_lsa *);
-extern struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *,
- struct ospf6_lsa *);
+extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa,
+ struct ospf6_lsa *type7,
+ struct ospf6_lsa *type5);
+extern struct ospf6_lsa *
+ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7);
extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6);
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 991720ec2e..54baaee638 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -343,7 +343,7 @@ extern int ospf6_route_get_first_nh_index(struct ospf6_route *route);
ospf6_add_nexthop(route->nh_list, ifindex, addr)
extern struct ospf6_route *ospf6_route_create(struct ospf6 *ospf6);
-extern void ospf6_route_delete(struct ospf6_route *);
+extern void ospf6_route_delete(struct ospf6_route *route);
extern struct ospf6_route *ospf6_route_copy(struct ospf6_route *route);
extern int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb);
@@ -384,8 +384,10 @@ extern void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
json_object *json, bool use_json);
-extern int ospf6_route_table_show(struct vty *, int, int, struct cmd_token **,
- struct ospf6_route_table *, bool use_json);
+extern int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
+ struct cmd_token **argv,
+ struct ospf6_route_table *table,
+ bool use_json);
extern int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
struct cmd_token **argv,
struct ospf6_route_table *table);
diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h
index a3ccc3d38d..e25f6bf80d 100644
--- a/ospf6d/ospf6_zebra.h
+++ b/ospf6d/ospf6_zebra.h
@@ -54,20 +54,23 @@ extern void ospf6_zebra_redistribute(int, vrf_id_t vrf_id);
extern void ospf6_zebra_no_redistribute(int, vrf_id_t vrf_id);
#define ospf6_zebra_is_redistribute(type, vrf_id) \
vrf_bitmap_check(zclient->redist[AFI_IP6][type], vrf_id)
-extern void ospf6_zebra_init(struct thread_master *);
+extern void ospf6_zebra_init(struct thread_master *tm);
extern void ospf6_zebra_add_discard(struct ospf6_route *request,
struct ospf6 *ospf6);
extern void ospf6_zebra_delete_discard(struct ospf6_route *request,
struct ospf6 *ospf6);
-extern void ospf6_distance_reset(struct ospf6 *);
-extern uint8_t ospf6_distance_apply(struct prefix_ipv6 *, struct ospf6_route *,
- struct ospf6 *);
+extern void ospf6_distance_reset(struct ospf6 *ospf6);
+extern uint8_t ospf6_distance_apply(struct prefix_ipv6 *p,
+ struct ospf6_route * or,
+ struct ospf6 *ospf6);
-extern int ospf6_distance_set(struct vty *, struct ospf6 *, const char *,
- const char *, const char *);
-extern int ospf6_distance_unset(struct vty *, struct ospf6 *, const char *,
- const char *, const char *);
+extern int ospf6_distance_set(struct vty *vty, struct ospf6 *ospf6,
+ const char *distance_str, const char *ip_str,
+ const char *access_list_str);
+extern int ospf6_distance_unset(struct vty *vty, struct ospf6 *ospf6,
+ const char *distance_str, const char *ip_str,
+ const char *access_list_str);
extern int config_write_ospf6_debug_zebra(struct vty *vty);
extern void install_element_ospf6_debug_zebra(void);
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index bd629a2b70..46242fd05a 100644
--- a/pathd/path_cli.c
+++ b/pathd/path_cli.c
@@ -352,7 +352,16 @@ static int segment_list_has_src_dst(
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_adjacency");
node_src_id = adj_src_ipv6_str;
+ } else {
+ /*
+ * This is just to make the compiler happy about
+ * node_src_id not being initialized. This
+ * should never happen unless we change the cli
+ * function.
+ */
+ assert(!"We must have a adj_src_ipv4_str or a adj_src_ipv6_str");
}
+
/* addresses */
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
index_str);
diff --git a/tests/lib/cli/test_cli.c b/tests/lib/cli/test_cli.c
index 8dba1e29f0..f8d74018dd 100644
--- a/tests/lib/cli/test_cli.c
+++ b/tests/lib/cli/test_cli.c
@@ -40,6 +40,8 @@ DUMMY_DEFUN(cmd12, "alt a A.B.C.D");
DUMMY_DEFUN(cmd13, "alt a X:X::X:X");
DUMMY_DEFUN(cmd14,
"pat g { foo A.B.C.D$foo|foo|bar X:X::X:X$bar| baz } [final]");
+DUMMY_DEFUN(cmd15, "no pat g ![ WORD ]");
+DUMMY_DEFUN(cmd16, "[no] pat h {foo ![A.B.C.D$foo]|bar X:X::X:X$bar} final");
#include "tests/lib/cli/test_cli_clippy.c"
@@ -81,5 +83,7 @@ void test_init(int argc, char **argv)
install_element(ENABLE_NODE, &cmd13_cmd);
}
install_element(ENABLE_NODE, &cmd14_cmd);
+ install_element(ENABLE_NODE, &cmd15_cmd);
+ install_element(ENABLE_NODE, &cmd16_cmd);
install_element(ENABLE_NODE, &magic_test_cmd);
}
diff --git a/tests/lib/cli/test_cli.in b/tests/lib/cli/test_cli.in
index 5c146ef984..bd685a6231 100644
--- a/tests/lib/cli/test_cli.in
+++ b/tests/lib/cli/test_cli.in
@@ -74,6 +74,23 @@ pat f
pat f foo
pat f key
+no pat g
+no pat g test
+no pat g test more
+
+pat h foo ?1.2.3.4 final
+no pat h foo ?1.2.3.4 final
+pat h foo final
+no pat h foo final
+pat h bar final
+no pat h bar final
+pat h bar 1::2 final
+no pat h bar 1::2 final
+pat h bar 1::2 foo final
+no pat h bar 1::2 foo final
+pat h bar 1::2 foo 1.2.3.4 final
+no pat h bar 1::2 foo 1.2.3.4 final
+
alt a a?b
alt a 1 .2?.3.4
alt a 1 :2? ::?3
diff --git a/tests/lib/cli/test_cli.refout.in b/tests/lib/cli/test_cli.refout.in
index 1f38e08b20..84365810d5 100644
--- a/tests/lib/cli/test_cli.refout.in
+++ b/tests/lib/cli/test_cli.refout.in
@@ -147,7 +147,7 @@ test# papat
% Command incomplete.
test# pat
a b c d e f
-g
+g h
test# pat
% Command incomplete.
test#
@@ -263,6 +263,100 @@ cmd10 with 3 args.
[01] f@(null): f
[02] key@(null): key
test#
+test# no pat g
+cmd15 with 3 args.
+[00] no@(null): no
+[01] pat@(null): pat
+[02] g@(null): g
+test# no pat g test
+cmd15 with 4 args.
+[00] no@(null): no
+[01] pat@(null): pat
+[02] g@(null): g
+[03] WORD@g: test
+test# no pat g test more
+% [NONE] Unknown command: no pat g test more
+test#
+test# pat h foo
+ A.B.C.D 04
+test# pat h foo 1.2.3.4 final
+cmd16 with 5 args.
+[00] pat@(null): pat
+[01] h@(null): h
+[02] foo@(null): foo
+[03] A.B.C.D@foo: 1.2.3.4
+[04] final@(null): final
+test# no pat h foo
+ A.B.C.D 04
+ bar 05
+ final 07
+test# no pat h foo 1.2.3.4 final
+cmd16 with 6 args.
+[00] no@no: no
+[01] pat@(null): pat
+[02] h@(null): h
+[03] foo@(null): foo
+[04] A.B.C.D@foo: 1.2.3.4
+[05] final@(null): final
+test# pat h foo final
+% [NONE] Unknown command: pat h foo final
+test# no pat h foo final
+cmd16 with 5 args.
+[00] no@no: no
+[01] pat@(null): pat
+[02] h@(null): h
+[03] foo@(null): foo
+[04] final@(null): final
+test# pat h bar final
+% [NONE] Unknown command: pat h bar final
+test# no pat h bar final
+% [NONE] Unknown command: no pat h bar final
+test# pat h bar 1::2 final
+cmd16 with 5 args.
+[00] pat@(null): pat
+[01] h@(null): h
+[02] bar@(null): bar
+[03] X:X::X:X@bar: 1::2
+[04] final@(null): final
+test# no pat h bar 1::2 final
+cmd16 with 6 args.
+[00] no@no: no
+[01] pat@(null): pat
+[02] h@(null): h
+[03] bar@(null): bar
+[04] X:X::X:X@bar: 1::2
+[05] final@(null): final
+test# pat h bar 1::2 foo final
+% [NONE] Unknown command: pat h bar 1::2 foo final
+test# no pat h bar 1::2 foo final
+cmd16 with 7 args.
+[00] no@no: no
+[01] pat@(null): pat
+[02] h@(null): h
+[03] bar@(null): bar
+[04] X:X::X:X@bar: 1::2
+[05] foo@(null): foo
+[06] final@(null): final
+test# pat h bar 1::2 foo 1.2.3.4 final
+cmd16 with 7 args.
+[00] pat@(null): pat
+[01] h@(null): h
+[02] bar@(null): bar
+[03] X:X::X:X@bar: 1::2
+[04] foo@(null): foo
+[05] A.B.C.D@foo: 1.2.3.4
+[06] final@(null): final
+test# no pat h bar 1::2 foo 1.2.3.4 final
+cmd16 with 8 args.
+[00] no@no: no
+[01] pat@(null): pat
+[02] h@(null): h
+[03] bar@(null): bar
+[04] X:X::X:X@bar: 1::2
+[05] foo@(null): foo
+[06] A.B.C.D@foo: 1.2.3.4
+[07] final@(null): final
+test#
test# alt a
test# alt a a
WORD 02
diff --git a/tests/lib/test_nexthop.c b/tests/lib/test_nexthop.c
index 659d207b4e..7cf687dffe 100644
--- a/tests/lib/test_nexthop.c
+++ b/tests/lib/test_nexthop.c
@@ -112,15 +112,15 @@ static void test_run_first(void)
nexthop_free(nh2);
/* Blackhole */
- nh1 = nexthop_from_blackhole(BLACKHOLE_REJECT);
- nh2 = nexthop_from_blackhole(BLACKHOLE_REJECT);
+ nh1 = nexthop_from_blackhole(BLACKHOLE_REJECT, 0);
+ nh2 = nexthop_from_blackhole(BLACKHOLE_REJECT, 0);
ret = nexthop_cmp_basic(nh1, nh2);
assert(ret == 0);
nexthop_free(nh2);
- nh2 = nexthop_from_blackhole(BLACKHOLE_NULL);
+ nh2 = nexthop_from_blackhole(BLACKHOLE_NULL, 0);
ret = nexthop_cmp_basic(nh1, nh2);
assert(ret != 0);
diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
index b1203570a1..1b99fcea1f 100644
--- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
+++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
@@ -932,6 +932,9 @@ def test_bgp_summary():
# Remove Unknown Summary (all of it)
actual = re.sub(r"Unknown Summary \(VRF default\):", "", actual)
actual = re.sub(r"No Unknown neighbor is configured", "", actual)
+ # Make Connect/Active/Idle the same (change them all to Active)
+ actual = re.sub(r" Connect ", " Active ", actual)
+ actual = re.sub(r" Idle ", " Active ", actual)
actual = re.sub(
r"IPv4 labeled-unicast Summary \(VRF default\):", "", actual
@@ -1089,6 +1092,9 @@ def test_bgp_ipv6_summary():
# Remove Unknown Summary (all of it)
actual = re.sub(r"Unknown Summary \(VRF default\):", "", actual)
actual = re.sub(r"No Unknown neighbor is configured", "", actual)
+ # Make Connect/Active/Idle the same (change them all to Active)
+ actual = re.sub(r" Connect ", " Active ", actual)
+ actual = re.sub(r" Idle ", " Active ", actual)
# Remove Labeled Unicast Summary (all of it)
actual = re.sub(
diff --git a/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py b/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py
index 27451ec7b3..c890b0d7dc 100644
--- a/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py
+++ b/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py
@@ -92,7 +92,13 @@ def test_bgp_default_originate_route_map():
def _bgp_default_route_has_metric(router):
output = json.loads(router.vtysh_cmd("show ip bgp 0.0.0.0/0 json"))
expected = {
- "paths": [{"aspath": {"string": "65000 65000 65000 65000"}, "metric": 123}]
+ "paths": [
+ {
+ "aspath": {"string": "65000 65000 65000 65000"},
+ "metric": 123,
+ "community": None,
+ }
+ ]
}
return topotest.json_cmp(output, expected)
diff --git a/tests/topotests/bgp_evpn_overlay_index_gateway/host2/zebra.conf b/tests/topotests/bgp_evpn_overlay_index_gateway/host2/zebra.conf
index 9135545c58..b9f80f112d 100644
--- a/tests/topotests/bgp_evpn_overlay_index_gateway/host2/zebra.conf
+++ b/tests/topotests/bgp_evpn_overlay_index_gateway/host2/zebra.conf
@@ -1,4 +1,4 @@
!
-int host1-eth0
+int host2-eth0
ip address 50.0.1.21/24
ipv6 address 50:0:1::21/48
diff --git a/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py b/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
index 3e6e417211..0d27474cbd 100755
--- a/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
+++ b/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
@@ -151,13 +151,6 @@ def setup_module(mod):
r1.run("sysctl -w net.mpls.conf.r1-eth0.input=1")
r1.run("sysctl -w net.mpls.conf.r1-eth1.input=1")
r1.run("sysctl -w net.mpls.conf.r1-eth2.input=1")
- r2.run("sysctl -w net.mpls.conf.r1-eth0.input=1")
- r2.run("sysctl -w net.mpls.conf.r1-eth1.input=1")
- r3.run("sysctl -w net.mpls.conf.r1-eth0.input=1")
- r3.run("sysctl -w net.mpls.conf.r1-eth1.input=1")
- r3.run("sysctl -w net.mpls.conf.r1-eth2.input=1")
- r4.run("sysctl -w net.mpls.conf.r1-eth0.input=1")
- r4.run("sysctl -w net.mpls.conf.r1-eth1.input=1")
router_list = tgen.routers()
diff --git a/tests/topotests/example_test/r1/zebra.conf b/tests/topotests/example_test/r1/zebra.conf
new file mode 100644
index 0000000000..b733b7b03c
--- /dev/null
+++ b/tests/topotests/example_test/r1/zebra.conf
@@ -0,0 +1,8 @@
+interface r1-eth0
+ ip address 192.168.1.1/24
+
+interface r1-eth1
+ ip address 192.168.2.1/24
+
+interface r1-eth2
+ ip address 192.168.3.1/24 \ No newline at end of file
diff --git a/tests/topotests/example_test/r2/zebra.conf b/tests/topotests/example_test/r2/zebra.conf
new file mode 100644
index 0000000000..c0921f54c9
--- /dev/null
+++ b/tests/topotests/example_test/r2/zebra.conf
@@ -0,0 +1,4 @@
+interface r2-eth0
+ ip address 192.168.1.2/24
+interface r2-eth1
+ ip address 192.168.3.2/24
diff --git a/tests/topotests/example_test/test_template.py b/tests/topotests/example_test/test_template.py
index e94bb905a5..4c073f259c 100644
--- a/tests/topotests/example_test/test_template.py
+++ b/tests/topotests/example_test/test_template.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
#
# <template>.py
# Part of NetDEF Topology Tests
@@ -29,54 +29,69 @@
import sys
import pytest
-# Import topogen and topotest helpers
-from lib.topogen import Topogen, TopoRouter, get_topogen
-
+from lib.topogen import Topogen, TopoRouter
+from lib.topolog import logger
# TODO: select markers based on daemons used during test
# pytest module level markers
-"""
-pytestmark = pytest.mark.bfdd # single marker
pytestmark = [
- pytest.mark.bgpd,
- pytest.mark.ospfd,
- pytest.mark.ospf6d
-] # multiple markers
-"""
-
-
+ # pytest.mark.babeld,
+ # pytest.mark.bfdd,
+ # pytest.mark.bgpd,
+ # pytest.mark.eigrpd,
+ # pytest.mark.isisd,
+ # pytest.mark.ldpd,
+ # pytest.mark.nhrpd,
+ # pytest.mark.ospf6d,
+ pytest.mark.ospfd,
+ # pytest.mark.pathd,
+ # pytest.mark.pbrd,
+ # pytest.mark.pimd,
+ # pytest.mark.ripd,
+ # pytest.mark.ripngd,
+ # pytest.mark.sharpd,
+ # pytest.mark.staticd,
+ # pytest.mark.vrrpd,
+]
+
+# Function we pass to Topogen to create the topology
def build_topo(tgen):
"Build function"
# Create 2 routers
- for routern in range(1, 3):
- tgen.add_router("r{}".format(routern))
+ r1 = tgen.add_router("r1")
+ r2 = tgen.add_router("r2")
- # Create a switch with just one router connected to it to simulate a
- # empty network.
+ # Create a p2p connection between r1 and r2
+ tgen.add_link(r1, r2)
+
+ # Create a switch with one router connected to it to simulate a empty network.
switch = tgen.add_switch("s1")
- switch.add_link(tgen.gears["r1"])
+ switch.add_link(r1)
- # Create a connection between r1 and r2
+ # Create a p2p connection between r1 and r2
switch = tgen.add_switch("s2")
- switch.add_link(tgen.gears["r1"])
- switch.add_link(tgen.gears["r2"])
+ switch.add_link(r1)
+ switch.add_link(r2)
-def setup_module(mod):
- "Sets up the pytest environment"
+# New form of setup/teardown using pytest fixture
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
# This function initiates the topology build with Topogen...
- tgen = Topogen(build_topo, mod.__name__)
+ tgen = Topogen(build_topo, request.module.__name__)
- # The basic topology above could also have be more easily specified using a
- # dictionary, remove the build_topo function and use the following instead:
+ # A basic topology similar to the above could also have be more easily specified
+ # using a # dictionary, remove the build_topo function and use the following
+ # instead:
#
# topodef = {
# "s1": "r1"
# "s2": ("r1", "r2")
# }
- # tgen = Topogen(topodef, mod.__name__)
+ # tgen = Topogen(topodef, request.module.__name__)
# ... and here it calls initialization functions.
tgen.start_topology()
@@ -84,42 +99,69 @@ def setup_module(mod):
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
- # CWD = os.path.dirname(os.path.realpath(__file__))
+ # For all routers arrange for:
+ # - starting zebra using config file from <rtrname>/zebra.conf
+ # - starting ospfd using an empty config file.
for rname, router in router_list.items():
- router.load_config(
- TopoRouter.RD_ZEBRA,
- # Uncomment next line to load configuration from ./router/zebra.conf
- # os.path.join(CWD, '{}/zebra.conf'.format(rname))
- )
+ router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ router.load_config(TopoRouter.RD_OSPF)
- # After loading the configurations, this function loads configured daemons.
+ # Start and configure the router daemons
tgen.start_router()
+ # Provide tgen as argument to each test function
+ yield tgen
-def teardown_module(mod):
- "Teardown the pytest environment"
- tgen = get_topogen()
-
- # This function tears down the whole topology.
+ # Teardown after last test runs
tgen.stop_topology()
-def test_call_cli():
- "Dummy test that just calls tgen.cli() so we can interact with the build."
- tgen = get_topogen()
- # Don't run this test if we have any failure.
+# Fixture that executes before each test
+@pytest.fixture(autouse=True)
+def skip_on_failure(tgen):
if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
+ pytest.skip("skipped because of previous test failure")
+
+
+# ===================
+# The tests functions
+# ===================
+
- # logger.info("calling CLI")
- # tgen.cli()
+def test_get_version(tgen):
+ "Test the logs the FRR version"
+
+ r1 = tgen.gears["r1"]
+ version = r1.vtysh_cmd("show version")
+ logger.info("FRR version is: " + version)
+
+
+def test_connectivity(tgen):
+ "Test the logs the FRR version"
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+ output = r1.cmd_raises("ping -c1 192.168.1.2")
+ output = r2.cmd_raises("ping -c1 192.168.3.1")
+
+
+@pytest.mark.xfail
+def test_expect_failure(tgen):
+ "A test that is current expected to fail but should be fixed"
+
+ assert False, "Example of temporary expected failure that will eventually be fixed"
+
+
+@pytest.mark.skip
+def test_will_be_skipped(tgen):
+ "A test that will be skipped"
+ assert False
# Memory leak test template
-def test_memory_leak():
+def test_memory_leak(tgen):
"Run the memory leak test and report results."
- tgen = get_topogen()
+
if not tgen.is_memleak_enabled():
pytest.skip("Memory leak test/report is disabled")
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 54020d2ff9..1bce3c6bb2 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -44,6 +44,7 @@ from lib.micronet import comm_error
from lib.topogen import TopoRouter, get_topogen
from lib.topolog import get_logger, logger
from lib.topotest import frr_unicode, interface_set_status, version_cmp
+from lib import topotest
FRRCFG_FILE = "frr_json.conf"
FRRCFG_BKUP_FILE = "frr_json_initial.conf"
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 1b26ddc1b5..b98698185c 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -439,6 +439,19 @@ def run_and_expect_type(func, etype, count=20, wait=3, avalue=None):
return (False, result)
+def router_json_cmp_retry(router, cmd, data, exact=False, retry_timeout=10.0):
+ """
+ Runs `cmd` that returns JSON data (normally the command ends with 'json')
+ and compare with `data` contents. Retry by default for 10 seconds
+ """
+
+ def test_func():
+ return router_json_cmp(router, cmd, data, exact)
+
+ ok, _ = run_and_expect(test_func, None, int(retry_timeout), 1)
+ return ok
+
+
def int2dpid(dpid):
"Converting Integer to DPID"
diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
index 3e14ab7164..dc14bc6468 100755
--- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
+++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
@@ -90,7 +90,6 @@ from lib.pim import (
clear_ip_mroute,
clear_ip_pim_interface_traffic,
verify_igmp_config,
- clear_ip_mroute_verify,
McastTesterHelper,
)
from lib.topolog import logger
@@ -549,17 +548,11 @@ def test_clear_pim_neighbors_and_mroute_p0(request):
result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1, "f1")
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
- step("Clear the mroute on l1, wait for 5 sec")
- result = clear_ip_mroute_verify(tgen, "l1")
- assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
-
step(
- "After clear ip mroute (*,g) entries are re-populated again"
- " with same OIL and IIF, verify using 'show ip mroute' and "
- " 'show ip pim upstream' "
+ "Verify clear ip mroute (*,g) entries are populated by using "
+ "'show ip mroute' cli"
)
- source = topo["routers"]["i2"]["links"]["f1"]["ipv4"].split("/")[0]
input_dict = [
{"dut": "l1", "src_address": "*", "iif": "l1-c1-eth0", "oil": "l1-i1-eth1"}
]
@@ -570,6 +563,21 @@ def test_clear_pim_neighbors_and_mroute_p0(request):
)
assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result)
+ step("Clear mroutes on l1")
+ clear_ip_mroute(tgen, "l1")
+
+ step(
+ "After clear ip mroute (*,g) entries are re-populated again"
+ " with same OIL and IIF, verify using 'show ip mroute' and "
+ " 'show ip pim upstream' "
+ )
+
+ for data in input_dict:
+ result = verify_ip_mroutes(
+ tgen, data["dut"], data["src_address"], IGMP_JOIN, data["iif"], data["oil"]
+ )
+ assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result)
+
step(
"Verify 'show ip pim upstream' showing correct OIL and IIF" " on all the nodes"
)
diff --git a/tests/topotests/route_scale/test_route_scale.py b/tests/topotests/route_scale/scale_test_common.py
index fefeccd5e7..3557cb4413 100644
--- a/tests/topotests/route_scale/test_route_scale.py
+++ b/tests/topotests/route_scale/scale_test_common.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
-# test_route_scale.py
+# scale_test_common.py
#
# Copyright (c) 2020 by
# Cumulus Networks, Inc.
@@ -23,7 +23,7 @@
#
"""
-test_route_scale.py: Testing route scale
+scale_test_common.py: Common routines for testing route scale
"""
@@ -45,9 +45,6 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.sharpd]
-
-
#####################################################
##
## Network Topology Definition
@@ -55,7 +52,7 @@ pytestmark = [pytest.mark.sharpd]
#####################################################
-def build(tgen):
+def scale_build_common(tgen):
"Build function"
# Populate routers
@@ -68,16 +65,9 @@ def build(tgen):
switch.add_link(tgen.gears["r1"])
-#####################################################
-##
-## Tests starting
-##
-#####################################################
-
-
-def setup_module(module):
+def scale_setup_module(module):
"Setup topology"
- tgen = Topogen(build, module.__name__)
+ tgen = Topogen(scale_build_common, module.__name__)
tgen.start_topology()
router_list = tgen.routers()
@@ -93,7 +83,7 @@ def setup_module(module):
# tgen.mininet_cli()
-def teardown_module(_mod):
+def scale_teardown_module(_mod):
"Teardown the pytest environment"
tgen = get_topogen()
@@ -101,7 +91,7 @@ def teardown_module(_mod):
tgen.stop_topology()
-def test_converge_protocols():
+def scale_converge_protocols():
"Wait for protocol convergence"
tgen = get_topogen()
@@ -156,7 +146,7 @@ def run_one_setup(r1, s):
logger.info(output)
-def test_route_install():
+def route_install_helper(iter):
"Test route install for a variety of ecmp"
tgen = get_topogen()
@@ -166,6 +156,16 @@ def test_route_install():
r1 = tgen.gears["r1"]
+ # Avoid top ecmp case for runs with < 4G memory
+ output = tgen.net.cmd_raises("free")
+ m = re.search("Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output)
+ total_mem = int(m.group(2))
+ if total_mem < 4000000 and iter == 5:
+ logger.info(
+ "Limited memory available: {}, skipping x32 testcase".format(total_mem)
+ )
+ return;
+
installed_file = "{}/r1/installed.routes.json".format(CWD)
expected_installed = json.loads(open(installed_file).read())
@@ -196,38 +196,20 @@ def test_route_install():
# Build up a list of dicts with params for each step of the test;
# use defaults where the step doesn't supply a value
scale_setups = []
- for s in scale_steps:
- d = dict(zip(scale_keys, s))
- for k in scale_keys:
- if k not in d:
- d[k] = scale_defaults[k]
+ s = scale_steps[iter]
- scale_setups.append(d)
+ d = dict(zip(scale_keys, s))
+ for k in scale_keys:
+ if k not in d:
+ d[k] = scale_defaults[k]
- # Avoid top ecmp case for runs with < 4G memory
- output = tgen.net.cmd_raises("free")
- m = re.search("Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output)
- total_mem = int(m.group(2))
- if total_mem < 4000000:
- logger.info(
- "Limited memory available: {}, skipping x32 testcase".format(total_mem)
- )
- scale_setups = scale_setups[0:-1]
-
- # Run each step using the dicts we've built
- for s in scale_setups:
- run_one_setup(r1, s)
+ run_one_setup(r1, d)
# Mem leak testcase
-def test_memory_leak():
+def scale_test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
-
-
-if __name__ == "__main__":
- args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args))
diff --git a/tests/topotests/route_scale/test_route_scale1.py b/tests/topotests/route_scale/test_route_scale1.py
new file mode 100644
index 0000000000..b563883b45
--- /dev/null
+++ b/tests/topotests/route_scale/test_route_scale1.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+#
+# test_route_scale1.py
+#
+# Copyright (c) 2021 by
+# Nvidia, Inc.
+# Donald Sharp
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_route_scale1.py: Testing route scale
+
+"""
+import os
+import re
+import sys
+import pytest
+import json
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+
+
+pytestmark = [pytest.mark.sharpd]
+
+def build(tgen):
+ scale_build_common(tgen)
+
+def setup_module(module):
+ scale_setup_module(module)
+
+def teardown_module(_mod):
+ scale_teardown_module(_mod)
+
+def test_converge_protocols():
+ scale_converge_protocols()
+
+def test_route_install_2nh():
+ route_install_helper(1)
+
+def test_route_install_4nh():
+ route_install_helper(2)
+
+def test_route_install_16nh():
+ route_install_helper(4)
+
+def test_memory_leak():
+ scale_test_memory_leak()
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/route_scale/test_route_scale2.py b/tests/topotests/route_scale/test_route_scale2.py
new file mode 100644
index 0000000000..7045995f26
--- /dev/null
+++ b/tests/topotests/route_scale/test_route_scale2.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+#
+# test_route_scale2.py
+#
+# Copyright (c) 2022 by
+# Nvidia, Inc.
+# Donald Sharp
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NVIDIA BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_route_scale2.py: Testing route scale
+
+"""
+import os
+import re
+import sys
+import pytest
+import json
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+
+
+pytestmark = [pytest.mark.sharpd]
+
+def build(tgen):
+ scale_build_common(tgen)
+
+def setup_module(module):
+ scale_setup_module(module)
+
+def teardown_module(_mod):
+ scale_teardown_module(_mod)
+
+def test_converge_protocols():
+ scale_converge_protocols()
+
+def test_route_install_1nh():
+ route_install_helper(0)
+
+def test_route_install_8nh():
+ route_install_helper(3)
+
+def test_route_install_32nh():
+ route_install_helper(5)
+
+def test_memory_leak():
+ scale_test_memory_leak()
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_netlink/r1/sharpd.conf b/tests/topotests/zebra_netlink/r1/sharpd.conf
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/topotests/zebra_netlink/r1/sharpd.conf
+++ /dev/null
diff --git a/tests/topotests/zebra_netlink/r1/v4_route.json b/tests/topotests/zebra_netlink/r1/v4_route.json
deleted file mode 100644
index 39041ebc95..0000000000
--- a/tests/topotests/zebra_netlink/r1/v4_route.json
+++ /dev/null
@@ -1,2302 +0,0 @@
-{
- "2.1.3.7\/32":[
- {
- "prefix":"2.1.3.7\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.8\/32":[
- {
- "prefix":"2.1.3.8\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.9\/32":[
- {
- "prefix":"2.1.3.9\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.10\/32":[
- {
- "prefix":"2.1.3.10\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.11\/32":[
- {
- "prefix":"2.1.3.11\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.12\/32":[
- {
- "prefix":"2.1.3.12\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.13\/32":[
- {
- "prefix":"2.1.3.13\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.14\/32":[
- {
- "prefix":"2.1.3.14\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.15\/32":[
- {
- "prefix":"2.1.3.15\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.16\/32":[
- {
- "prefix":"2.1.3.16\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.17\/32":[
- {
- "prefix":"2.1.3.17\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.18\/32":[
- {
- "prefix":"2.1.3.18\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.19\/32":[
- {
- "prefix":"2.1.3.19\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.20\/32":[
- {
- "prefix":"2.1.3.20\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.21\/32":[
- {
- "prefix":"2.1.3.21\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.22\/32":[
- {
- "prefix":"2.1.3.22\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.23\/32":[
- {
- "prefix":"2.1.3.23\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.24\/32":[
- {
- "prefix":"2.1.3.24\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.25\/32":[
- {
- "prefix":"2.1.3.25\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.26\/32":[
- {
- "prefix":"2.1.3.26\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.27\/32":[
- {
- "prefix":"2.1.3.27\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.28\/32":[
- {
- "prefix":"2.1.3.28\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.29\/32":[
- {
- "prefix":"2.1.3.29\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.30\/32":[
- {
- "prefix":"2.1.3.30\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.31\/32":[
- {
- "prefix":"2.1.3.31\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.32\/32":[
- {
- "prefix":"2.1.3.32\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.33\/32":[
- {
- "prefix":"2.1.3.33\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.34\/32":[
- {
- "prefix":"2.1.3.34\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.35\/32":[
- {
- "prefix":"2.1.3.35\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.36\/32":[
- {
- "prefix":"2.1.3.36\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.37\/32":[
- {
- "prefix":"2.1.3.37\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.38\/32":[
- {
- "prefix":"2.1.3.38\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.39\/32":[
- {
- "prefix":"2.1.3.39\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.40\/32":[
- {
- "prefix":"2.1.3.40\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.41\/32":[
- {
- "prefix":"2.1.3.41\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.42\/32":[
- {
- "prefix":"2.1.3.42\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.43\/32":[
- {
- "prefix":"2.1.3.43\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.44\/32":[
- {
- "prefix":"2.1.3.44\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.45\/32":[
- {
- "prefix":"2.1.3.45\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.46\/32":[
- {
- "prefix":"2.1.3.46\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.47\/32":[
- {
- "prefix":"2.1.3.47\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.48\/32":[
- {
- "prefix":"2.1.3.48\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.49\/32":[
- {
- "prefix":"2.1.3.49\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.50\/32":[
- {
- "prefix":"2.1.3.50\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.51\/32":[
- {
- "prefix":"2.1.3.51\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.52\/32":[
- {
- "prefix":"2.1.3.52\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.53\/32":[
- {
- "prefix":"2.1.3.53\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.54\/32":[
- {
- "prefix":"2.1.3.54\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.55\/32":[
- {
- "prefix":"2.1.3.55\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.56\/32":[
- {
- "prefix":"2.1.3.56\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.57\/32":[
- {
- "prefix":"2.1.3.57\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.58\/32":[
- {
- "prefix":"2.1.3.58\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.59\/32":[
- {
- "prefix":"2.1.3.59\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.60\/32":[
- {
- "prefix":"2.1.3.60\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.61\/32":[
- {
- "prefix":"2.1.3.61\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.62\/32":[
- {
- "prefix":"2.1.3.62\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.63\/32":[
- {
- "prefix":"2.1.3.63\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.64\/32":[
- {
- "prefix":"2.1.3.64\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.65\/32":[
- {
- "prefix":"2.1.3.65\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.66\/32":[
- {
- "prefix":"2.1.3.66\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.67\/32":[
- {
- "prefix":"2.1.3.67\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.68\/32":[
- {
- "prefix":"2.1.3.68\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.69\/32":[
- {
- "prefix":"2.1.3.69\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.70\/32":[
- {
- "prefix":"2.1.3.70\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.71\/32":[
- {
- "prefix":"2.1.3.71\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.72\/32":[
- {
- "prefix":"2.1.3.72\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.73\/32":[
- {
- "prefix":"2.1.3.73\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.74\/32":[
- {
- "prefix":"2.1.3.74\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.75\/32":[
- {
- "prefix":"2.1.3.75\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.76\/32":[
- {
- "prefix":"2.1.3.76\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.77\/32":[
- {
- "prefix":"2.1.3.77\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.78\/32":[
- {
- "prefix":"2.1.3.78\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.79\/32":[
- {
- "prefix":"2.1.3.79\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.80\/32":[
- {
- "prefix":"2.1.3.80\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.81\/32":[
- {
- "prefix":"2.1.3.81\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.82\/32":[
- {
- "prefix":"2.1.3.82\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.83\/32":[
- {
- "prefix":"2.1.3.83\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.84\/32":[
- {
- "prefix":"2.1.3.84\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.85\/32":[
- {
- "prefix":"2.1.3.85\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.86\/32":[
- {
- "prefix":"2.1.3.86\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.87\/32":[
- {
- "prefix":"2.1.3.87\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.88\/32":[
- {
- "prefix":"2.1.3.88\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.89\/32":[
- {
- "prefix":"2.1.3.89\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.90\/32":[
- {
- "prefix":"2.1.3.90\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.91\/32":[
- {
- "prefix":"2.1.3.91\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.92\/32":[
- {
- "prefix":"2.1.3.92\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.93\/32":[
- {
- "prefix":"2.1.3.93\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.94\/32":[
- {
- "prefix":"2.1.3.94\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.95\/32":[
- {
- "prefix":"2.1.3.95\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.96\/32":[
- {
- "prefix":"2.1.3.96\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.97\/32":[
- {
- "prefix":"2.1.3.97\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.98\/32":[
- {
- "prefix":"2.1.3.98\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.99\/32":[
- {
- "prefix":"2.1.3.99\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.100\/32":[
- {
- "prefix":"2.1.3.100\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.101\/32":[
- {
- "prefix":"2.1.3.101\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.102\/32":[
- {
- "prefix":"2.1.3.102\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.103\/32":[
- {
- "prefix":"2.1.3.103\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.104\/32":[
- {
- "prefix":"2.1.3.104\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.105\/32":[
- {
- "prefix":"2.1.3.105\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ],
- "2.1.3.106\/32":[
- {
- "prefix":"2.1.3.106\/32",
- "protocol":"sharp",
- "selected":true,
- "destSelected":true,
- "distance":150,
- "metric":0,
- "installed":true,
- "table":254,
- "nexthops":[
- {
- "flags":3,
- "fib":true,
- "ip":"192.168.1.1",
- "afi":"ipv4",
- "interfaceName":"r1-eth0",
- "active":true,
- "weight":1
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py
index 05cc0ae4a1..ca90c5cb15 100644
--- a/tests/topotests/zebra_netlink/test_zebra_netlink.py
+++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py
@@ -24,21 +24,15 @@
test_zebra_netlink.py: Test some basic interactions with kernel using Netlink
"""
-
-import os
-import sys
-import pytest
+# pylint: disable=C0413
+import ipaddress
import json
+import sys
from functools import partial
-# Save the Current Working Directory to find configuration files.
-CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, "../"))
-
-# pylint: disable=C0413
-# Import topogen and topotest helpers
+import pytest
from lib import topotest
-from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topogen import Topogen, TopoRouter
from lib.topolog import logger
@@ -52,62 +46,73 @@ pytestmark = [pytest.mark.sharpd]
#####################################################
-def setup_module(mod):
+@pytest.fixture(scope="module")
+def tgen(request):
"Sets up the pytest environment"
topodef = {"s1": ("r1")}
- tgen = Topogen(topodef, mod.__name__)
+ tgen = Topogen(topodef, request.module.__name__)
tgen.start_topology()
+ # Initialize all routers.
router_list = tgen.routers()
for rname, router in router_list.items():
- router.load_config(
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
- )
-
- router.load_config(
- TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
- )
+ router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
+ router.load_config(TopoRouter.RD_SHARP)
- # Initialize all routers.
tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
-def teardown_module(_mod):
- "Teardown the pytest environment"
- tgen = get_topogen()
-
- # This function tears down the whole topology.
- tgen.stop_topology()
+@pytest.fixture(autouse=True)
+def skip_on_failure(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip("skipped because of previous test failure")
-def test_zebra_netlink_batching():
+def test_zebra_netlink_batching(tgen):
"Test the situation where dataplane fills netlink send buffer entirely."
logger.info(
"Test the situation where dataplane fills netlink send buffer entirely."
)
- tgen = get_topogen()
- if tgen.routers_have_failure():
- pytest.skip("skipped because of previous test failure")
r1 = tgen.gears["r1"]
# Reduce the size of the buffer to hit the limit.
r1.vtysh_cmd("conf t\nzebra kernel netlink batch-tx-buf 256 256")
- r1.vtysh_cmd("sharp install routes 2.1.3.7 nexthop 192.168.1.1 100")
- json_file = "{}/r1/v4_route.json".format(CWD)
- expected = json.loads(open(json_file).read())
- test_func = partial(
- topotest.router_json_cmp,
- r1,
- "show ip route json",
- expected,
- )
- _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
- assertmsg = '"r1" JSON output mismatches'
- assert result is None, assertmsg
-
- r1.vtysh_cmd("sharp remove routes 2.1.3.7 100")
+ count = 100
+ r1.vtysh_cmd("sharp install routes 2.1.3.7 nexthop 192.168.1.1 " + str(count))
+
+ # Generate expected results
+ entry = {
+ "protocol": "sharp",
+ "distance": 150,
+ "metric": 0,
+ "installed": True,
+ "table": 254,
+ "nexthops": [
+ {
+ "fib": True,
+ "ip": "192.168.1.1",
+ "afi": "ipv4",
+ "interfaceName": "r1-eth0",
+ "active": True,
+ "weight": 1,
+ }
+ ],
+ }
+
+ match = {}
+ base = int(ipaddress.ip_address(u"2.1.3.7"))
+ for i in range(base, base + count):
+ pfx = str(ipaddress.ip_network((i, 32)))
+ match[pfx] = [dict(entry, prefix=pfx)]
+
+ ok = topotest.router_json_cmp_retry(r1, "show ip route json", match)
+ assert ok, '"r1" JSON output mismatches'
+
+ r1.vtysh_cmd("sharp remove routes 2.1.3.7 " + str(count))
if __name__ == "__main__":
diff --git a/tests/zebra/test_lm_plugin.c b/tests/zebra/test_lm_plugin.c
index 4a9344fee4..ecfb085793 100644
--- a/tests/zebra/test_lm_plugin.c
+++ b/tests/zebra/test_lm_plugin.c
@@ -77,7 +77,7 @@ static int lm_release_chunk_pi(struct zserv *client, uint32_t start,
/* use external allocations */
-static void lp_plugin_init()
+static void lp_plugin_init(void)
{
/* register our own hooks */
hook_register(lm_client_connect, test_client_connect);
@@ -86,7 +86,7 @@ static void lp_plugin_init()
hook_register(lm_release_chunk, lm_release_chunk_pi);
}
-static void lp_plugin_cleanup()
+static void lp_plugin_cleanup(void)
{
/* register our own hooks */
hook_unregister(lm_client_connect, test_client_connect);
@@ -98,7 +98,7 @@ static void lp_plugin_cleanup()
/* tests */
-static void test_lp_plugin()
+static void test_lp_plugin(void)
{
struct label_manager_chunk *lmc;
diff --git a/tools/permutations.c b/tools/permutations.c
index f51d4a4ec9..b280cc15b1 100644
--- a/tools/permutations.c
+++ b/tools/permutations.c
@@ -61,9 +61,22 @@ void permute(struct graph_node *start)
struct cmd_token *stok = start->data;
struct graph_node *gnn;
struct listnode *ln;
+ bool is_neg = false;
// recursive dfs
listnode_add(position, start);
+
+ for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) {
+ struct cmd_token *tok = gnn->data;
+
+ if (tok->type == WORD_TKN && !strcmp(tok->text, "no")) {
+ is_neg = true;
+ break;
+ }
+ if (tok->type < SPECIAL_TKN)
+ break;
+ }
+
for (unsigned int i = 0; i < vector_active(start->to); i++) {
struct graph_node *gn = vector_slot(start->to, i);
struct cmd_token *tok = gn->data;
@@ -82,6 +95,9 @@ void permute(struct graph_node *start)
fprintf(stdout, "\n");
} else {
bool skip = false;
+
+ if (tok->type == NEG_ONLY_TKN && !is_neg)
+ continue;
if (stok->type == FORK_TKN && tok->type != FORK_TKN)
for (ALL_LIST_ELEMENTS_RO(position, ln, gnn))
if (gnn == gn) {
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 72c7071502..9ffbcc9223 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1611,7 +1611,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
zlog_debug("%s: nh blackhole %d",
__func__, api_nh->bh_type);
- nexthop = nexthop_from_blackhole(api_nh->bh_type);
+ nexthop =
+ nexthop_from_blackhole(api_nh->bh_type, api_nh->vrf_id);
break;
}
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 08ff7011e2..af46ea6d7a 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -2113,12 +2113,12 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
"sync->remote neigh vni %u ip %pIA mac %pEA seq %d f0x%x",
n->zevpn->vni, &n->ip, &n->emac,
seq, n->flags);
- zebra_evpn_neigh_clear_sync_info(n);
if (IS_ZEBRA_NEIGH_ACTIVE(n))
zebra_evpn_neigh_send_del_to_client(
zevpn->vni, &n->ip, &n->emac,
n->flags, n->state,
false /*force*/);
+ zebra_evpn_neigh_clear_sync_info(n);
}
if (memcmp(&n->emac, &mac->macaddr,
sizeof(struct ethaddr))
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 64366d6f4f..8caabf19e7 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -292,6 +292,9 @@ static void zfpm_start_connect_timer(const char *reason);
static void zfpm_start_stats_timer(void);
static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac);
+static const char ipv4_ll_buf[16] = "169.254.0.1";
+union g_addr ipv4ll_gateway;
+
/*
* zfpm_thread_should_yield
*/
@@ -1993,6 +1996,9 @@ static int zfpm_init(struct thread_master *master)
zfpm_stats_init(&zfpm_g->last_ivl_stats);
zfpm_stats_init(&zfpm_g->cumulative_stats);
+ memset(&ipv4ll_gateway, 0, sizeof(ipv4ll_gateway));
+ inet_pton(AF_INET, ipv4_ll_buf, &ipv4ll_gateway.ipv4);
+
install_node(&zebra_node);
install_element(ENABLE_NODE, &show_zebra_fpm_stats_cmd);
install_element(ENABLE_NODE, &clear_zebra_fpm_stats_cmd);
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index efbd078a52..68fb044353 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -189,7 +189,12 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri,
if (nexthop->type == NEXTHOP_TYPE_IPV6
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
- nhi.gateway = &nexthop->gate;
+ /* Special handling for IPv4 route with IPv6 Link Local next hop
+ */
+ if (ri->af == AF_INET)
+ nhi.gateway = &ipv4ll_gateway;
+ else
+ nhi.gateway = &nexthop->gate;
}
if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h
index c169ee8c22..13415c7e1d 100644
--- a/zebra/zebra_fpm_private.h
+++ b/zebra/zebra_fpm_private.h
@@ -97,6 +97,8 @@ extern int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest);
+extern union g_addr ipv4ll_gateway;
+
#ifdef __cplusplus
}
#endif
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 7e9382518f..e17465b112 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -520,7 +520,13 @@ static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt,
if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) {
vrf_id = ifp->vrf_id;
} else {
- vrf_id = vrf_name_to_id(vrf_str);
+ struct vrf *pVrf;
+
+ pVrf = vrf_lookup_by_name(vrf_str);
+ if (pVrf)
+ vrf_id = pVrf->vrf_id;
+ else
+ vrf_id = VRF_DEFAULT;
}
if (!strcmp(bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index b204b30ca7..1c8a1ad09a 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -357,9 +357,11 @@ static void show_nexthop_detail_helper(struct vty *vty,
break;
}
- if ((re->vrf_id != nexthop->vrf_id)
- && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
- vty_out(vty, "(vrf %s)", vrf_id_to_name(nexthop->vrf_id));
+ if (re->vrf_id != nexthop->vrf_id) {
+ struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
+
+ vty_out(vty, "(vrf %s)", VRF_LOGNAME(vrf));
+ }
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
vty_out(vty, " (duplicate nexthop removed)");
@@ -607,8 +609,7 @@ static void show_route_nexthop_helper(struct vty *vty,
break;
}
- if ((re == NULL || (nexthop->vrf_id != re->vrf_id))
- && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
+ if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
@@ -780,8 +781,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
break;
}
- if ((nexthop->vrf_id != re->vrf_id)
- && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
+ if (nexthop->vrf_id != re->vrf_id)
json_object_string_add(json_nexthop, "vrf",
vrf_id_to_name(nexthop->vrf_id));