summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn_vty.c6
-rw-r--r--bgpd/bgp_flowspec_util.c8
-rw-r--r--bgpd/bgp_updgrp_adv.c2
-rw-r--r--bgpd/bgp_vty.c222
-rw-r--r--bgpd/bgpd.c33
-rw-r--r--bgpd/bgpd.h59
-rw-r--r--doc/user/basic.rst4
-rw-r--r--doc/user/bgp.rst70
-rw-r--r--doc/user/ipv6.rst5
-rw-r--r--doc/user/ospf6d.rst14
-rw-r--r--doc/user/ospfd.rst4
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--eigrpd/eigrp_network.c2
-rw-r--r--isisd/isis_cli.c4
-rw-r--r--isisd/isis_zebra.c5
-rw-r--r--lib/command.c9
-rw-r--r--lib/prefix.h8
-rw-r--r--lib/routemap.h5
-rw-r--r--lib/zclient.c16
-rw-r--r--lib/zclient.h3
-rw-r--r--ospf6d/ospf6_asbr.c31
-rw-r--r--ospf6d/ospf6_asbr.h1
-rw-r--r--ospf6d/ospf6_interface.c6
-rw-r--r--ospf6d/ospf6_interface.h1
-rw-r--r--ospf6d/ospf6_lsa.c2
-rw-r--r--ospf6d/ospf6_message.c7
-rw-r--r--ospf6d/ospf6_top.c93
-rw-r--r--ospf6d/ospf6_top.h4
-rw-r--r--ospf6d/ospf6_zebra.c11
-rw-r--r--ospf6d/ospf6d.c1
-rw-r--r--ospf6d/subdir.am1
-rw-r--r--ospfd/ospf_interface.c7
-rw-r--r--ospfd/ospf_zebra.c5
-rw-r--r--pathd/pathd.c2
-rw-r--r--pimd/pim_cmd.c15
-rw-r--r--tests/bgpd/test_peer_attr.c1
-rw-r--r--tests/topotests/bgp_default_afi_safi/__init__.py (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/__init__.py)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r1/bgpd.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/bgpd.conf)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r1/zebra.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/zebra.conf)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r2/bgpd.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/bgpd.conf)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r2/zebra.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/zebra.conf)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r3/bgpd.conf5
-rw-r--r--tests/topotests/bgp_default_afi_safi/r3/zebra.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/zebra.conf)0
-rw-r--r--tests/topotests/bgp_default_afi_safi/r4/bgpd.conf (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/bgpd.conf)1
-rw-r--r--tests/topotests/bgp_default_afi_safi/r4/zebra.conf6
-rw-r--r--tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py (renamed from tests/topotests/bgp_default_ipv4_ipv6_unicast/test_bgp-default-ipv4-ipv6-unicast.py)43
-rw-r--r--tests/topotests/lib/bgp.py34
-rw-r--r--tests/topotests/lib/common_config.py165
-rw-r--r--tests/topotests/lib/ospf.py24
-rw-r--r--tests/topotests/lib/pim.py36
-rw-r--r--tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py3
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py116
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_authentication.py8
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py8
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py4
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py4
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py2
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py9
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py11
-rw-r--r--zebra/connected.c12
-rw-r--r--zebra/main.c1
-rw-r--r--zebra/rib.h18
-rw-r--r--zebra/rtadv.c409
-rw-r--r--zebra/rtadv.h3
-rw-r--r--zebra/zebra_router.c2
-rw-r--r--zebra/zebra_router.h3
-rw-r--r--zebra/zebra_vrf.c2
67 files changed, 1109 insertions, 494 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 190323859f..2bda5dbf9a 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -63,10 +63,8 @@ int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx,
enum overlay_index_type *oly)
{
*oly = OVERLAY_INDEX_TYPE_NONE;
- if (argv_find(argv, argc, "gateway-ip", oly_idx)) {
- if (oly)
- *oly = OVERLAY_INDEX_GATEWAY_IP;
- }
+ if (argv_find(argv, argc, "gateway-ip", oly_idx))
+ *oly = OVERLAY_INDEX_GATEWAY_IP;
return 1;
}
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 23baa0184e..348dc7c9d1 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -227,12 +227,8 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
BGP_FLOWSPEC_STRING_DISPLAY_MAX);
break;
case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
- if (prefix) {
- if (prefix_local.family == AF_INET)
- PREFIX_COPY_IPV4(prefix, &prefix_local);
- else
- PREFIX_COPY_IPV6(prefix, &prefix_local);
- }
+ if (prefix)
+ prefix_copy(prefix, &prefix_local);
break;
case BGP_FLOWSPEC_VALIDATE_ONLY:
default:
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 4dd7597e5f..18829aa747 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -839,6 +839,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
bgp_dest_get_prefix(dest), &tmp_pi);
if (ret == RMAP_DENYMATCH) {
+ /* The aspath belongs to 'attr' */
+ tmp_attr.aspath = NULL;
bgp_attr_flush(&tmp_attr);
continue;
} else {
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index de4f5a59b6..e713894eb1 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -470,6 +470,74 @@ int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index,
return ret;
}
+/*
+ * Convert an afi_t/safi_t pair to matching BGP_DEFAULT_AF* flag.
+ *
+ * afi
+ * address-family identifier
+ *
+ * safi
+ * subsequent address-family identifier
+ *
+ * Returns:
+ * default_af string corresponding to the supplied afi/safi pair.
+ * If afi/safi is invalid or if flag for afi/safi doesn't exist,
+ * return -1.
+ */
+static const char *get_bgp_default_af_flag(afi_t afi, safi_t safi)
+{
+ switch (afi) {
+ case AFI_IP:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return "ipv4-unicast";
+ case SAFI_MULTICAST:
+ return "ipv4-multicast";
+ case SAFI_MPLS_VPN:
+ return "ipv4-vpn";
+ case SAFI_ENCAP:
+ return "ipv4-encap";
+ case SAFI_LABELED_UNICAST:
+ return "ipv4-labeled-unicast";
+ case SAFI_FLOWSPEC:
+ return "ipv4-flowspec";
+ default:
+ return "unknown-afi/safi";
+ }
+ break;
+ case AFI_IP6:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return "ipv6-unicast";
+ case SAFI_MULTICAST:
+ return "ipv6-multicast";
+ case SAFI_MPLS_VPN:
+ return "ipv6-vpn";
+ case SAFI_ENCAP:
+ return "ipv6-encap";
+ case SAFI_LABELED_UNICAST:
+ return "ipv6-labeled-unicast";
+ case SAFI_FLOWSPEC:
+ return "ipv6-flowspec";
+ default:
+ return "unknown-afi/safi";
+ }
+ break;
+ case AFI_L2VPN:
+ switch (safi) {
+ case SAFI_EVPN:
+ return "l2vpn-evpn";
+ default:
+ return "unknown-afi/safi";
+ }
+ case AFI_UNSPEC:
+ case AFI_MAX:
+ return "unknown-afi/safi";
+ }
+ /* all AFIs are accounted for above, so this shouldn't happen */
+ return "unknown-afi/safi";
+}
+
int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
enum bgp_instance_type inst_type)
{
@@ -3741,52 +3809,60 @@ DEFPY (no_bgp_bestpath_bw,
return CMD_SUCCESS;
}
-/* "no bgp default ipv6-unicast". */
-DEFUN(no_bgp_default_ipv6_unicast, no_bgp_default_ipv6_unicast_cmd,
- "no bgp default ipv6-unicast", NO_STR
+DEFPY(bgp_default_afi_safi, bgp_default_afi_safi_cmd,
+ "[no] bgp default <ipv4-unicast|"
+ "ipv4-multicast|"
+ "ipv4-vpn|"
+ "ipv4-labeled-unicast|"
+ "ipv4-flowspec|"
+ "ipv6-unicast|"
+ "ipv6-multicast|"
+ "ipv6-vpn|"
+ "ipv6-labeled-unicast|"
+ "ipv6-flowspec|"
+ "l2vpn-evpn>$afi_safi",
+ NO_STR
"BGP specific commands\n"
"Configure BGP defaults\n"
- "Activate ipv6-unicast for a peer by default\n")
+ "Activate ipv4-unicast for a peer by default\n"
+ "Activate ipv4-multicast for a peer by default\n"
+ "Activate ipv4-vpn for a peer by default\n"
+ "Activate ipv4-labeled-unicast for a peer by default\n"
+ "Activate ipv4-flowspec for a peer by default\n"
+ "Activate ipv6-unicast for a peer by default\n"
+ "Activate ipv6-multicast for a peer by default\n"
+ "Activate ipv6-vpn for a peer by default\n"
+ "Activate ipv6-labeled-unicast for a peer by default\n"
+ "Activate ipv6-flowspec for a peer by default\n"
+ "Activate l2vpn-evpn for a peer by default\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- UNSET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6);
- return CMD_SUCCESS;
-}
+ char afi_safi_str[strlen(afi_safi) + 1];
+ char *afi_safi_str_tok;
-DEFUN(bgp_default_ipv6_unicast, bgp_default_ipv6_unicast_cmd,
- "bgp default ipv6-unicast",
- "BGP specific commands\n"
- "Configure BGP defaults\n"
- "Activate ipv6-unicast for a peer by default\n")
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- SET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6);
- return CMD_SUCCESS;
-}
+ strlcpy(afi_safi_str, afi_safi, sizeof(afi_safi_str));
+ char *afi_str = strtok_r(afi_safi_str, "-", &afi_safi_str_tok);
+ char *safi_str = strtok_r(NULL, "-", &afi_safi_str_tok);
+ afi_t afi = bgp_vty_afi_from_str(afi_str);
+ safi_t safi;
-/* "no bgp default ipv4-unicast". */
-DEFUN (no_bgp_default_ipv4_unicast,
- no_bgp_default_ipv4_unicast_cmd,
- "no bgp default ipv4-unicast",
- NO_STR
- "BGP specific commands\n"
- "Configure BGP defaults\n"
- "Activate ipv4-unicast for a peer by default\n")
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- SET_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4);
- return CMD_SUCCESS;
-}
+ if (strmatch(safi_str, "labeled"))
+ safi = bgp_vty_safi_from_str("labeled-unicast");
+ else
+ safi = bgp_vty_safi_from_str(safi_str);
+
+ if (no)
+ bgp->default_af[afi][safi] = false;
+ else {
+ if ((safi == SAFI_LABELED_UNICAST
+ && bgp->default_af[afi][SAFI_UNICAST])
+ || (safi == SAFI_UNICAST
+ && bgp->default_af[afi][SAFI_LABELED_UNICAST]))
+ bgp_vty_return(vty, BGP_ERR_PEER_SAFI_CONFLICT);
+ else
+ bgp->default_af[afi][safi] = true;
+ }
-DEFUN (bgp_default_ipv4_unicast,
- bgp_default_ipv4_unicast_cmd,
- "bgp default ipv4-unicast",
- "BGP specific commands\n"
- "Configure BGP defaults\n"
- "Activate ipv4-unicast for a peer by default\n")
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- UNSET_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4);
return CMD_SUCCESS;
}
@@ -17436,41 +17512,14 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
} else {
if (peer->afc[afi][safi]) {
- if ((afi == AFI_IP || afi == AFI_IP6)
- && safi == SAFI_UNICAST) {
- if (afi == AFI_IP
- && CHECK_FLAG(bgp->flags,
- BGP_FLAG_NO_DEFAULT_IPV4)) {
- vty_out(vty, " neighbor %s activate\n",
- addr);
- } else if (afi == AFI_IP6
- && !CHECK_FLAG(
- bgp->flags,
- BGP_FLAG_DEFAULT_IPV6)) {
- vty_out(vty, " neighbor %s activate\n",
- addr);
- }
- } else {
+ if (safi == SAFI_ENCAP)
+ vty_out(vty, " neighbor %s activate\n", addr);
+ else if (!bgp->default_af[afi][safi])
vty_out(vty, " neighbor %s activate\n", addr);
- }
} else {
- if ((afi == AFI_IP || afi == AFI_IP6)
- && safi == SAFI_UNICAST) {
- if (afi == AFI_IP
- && !CHECK_FLAG(bgp->flags,
- BGP_FLAG_NO_DEFAULT_IPV4)) {
- vty_out(vty,
- " no neighbor %s activate\n",
- addr);
- } else if (afi == AFI_IP6
- && CHECK_FLAG(
- bgp->flags,
- BGP_FLAG_DEFAULT_IPV6)) {
- vty_out(vty,
- " no neighbor %s activate\n",
- addr);
- }
- }
+ if (bgp->default_af[afi][safi])
+ vty_out(vty, " no neighbor %s activate\n",
+ addr);
}
}
@@ -17796,6 +17845,8 @@ int bgp_config_write(struct vty *vty)
struct peer *peer;
struct listnode *node, *nnode;
struct listnode *mnode, *mnnode;
+ afi_t afi;
+ safi_t safi;
if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
vty_out(vty, "bgp route-map delay-timer %u\n",
@@ -17886,13 +17937,17 @@ int bgp_config_write(struct vty *vty)
? ""
: "no ");
- /* BGP default ipv4-unicast. */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4))
- vty_out(vty, " no bgp default ipv4-unicast\n");
-
- /* BGP default ipv6-unicast. */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6))
- vty_out(vty, " bgp default ipv6-unicast\n");
+ /* BGP default <afi>-<safi> */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (afi == AFI_IP && safi == SAFI_UNICAST) {
+ if (!bgp->default_af[afi][safi])
+ vty_out(vty, " no bgp default %s\n",
+ get_bgp_default_af_flag(afi,
+ safi));
+ } else if (bgp->default_af[afi][safi])
+ vty_out(vty, " bgp default %s\n",
+ get_bgp_default_af_flag(afi, safi));
+ }
/* BGP default local-preference. */
if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
@@ -18586,13 +18641,8 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_bestpath_bw_cmd);
install_element(BGP_NODE, &no_bgp_bestpath_bw_cmd);
- /* "no bgp default ipv4-unicast" commands. */
- install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd);
- install_element(BGP_NODE, &bgp_default_ipv4_unicast_cmd);
-
- /* "no bgp default ipv6-unicast" commands. */
- install_element(BGP_NODE, &no_bgp_default_ipv6_unicast_cmd);
- install_element(BGP_NODE, &bgp_default_ipv6_unicast_cmd);
+ /* "no bgp default <afi>-<safi>" commands. */
+ install_element(BGP_NODE, &bgp_default_afi_safi_cmd);
/* "bgp network import-check" commands. */
install_element(BGP_NODE, &bgp_network_import_check_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 49562e5874..197133cbb4 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1538,7 +1538,7 @@ static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer,
*/
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
if (ifc->address && (ifc->address->family == AF_INET)) {
- PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
+ prefix_copy(&p, CONNECTED_PREFIX(ifc));
if (p.prefixlen == 30) {
peer->su.sa.sa_family = AF_INET;
addr = ntohl(p.u.prefix4.s_addr);
@@ -1776,22 +1776,15 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
- /* If address family is IPv4 and `bgp default ipv4-unicast` (default),
- * then activate the neighbor for this AF.
- * If address family is IPv6 and `bgp default ipv6-unicast`
- * (non-default), then activate the neighbor for this AF.
+ /* If 'bgp default <afi>-<safi>' is configured, then activate the
+ * neighbor for the corresponding address family. IPv4 Unicast is
+ * the only address family enabled by default without expliict
+ * configuration.
*/
FOREACH_AFI_SAFI (afi, safi) {
- if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) {
- if ((afi == AFI_IP
- && !CHECK_FLAG(bgp->flags,
- BGP_FLAG_NO_DEFAULT_IPV4))
- || (afi == AFI_IP6
- && CHECK_FLAG(bgp->flags,
- BGP_FLAG_DEFAULT_IPV6))) {
- peer->afc[afi][safi] = 1;
- peer_af_create(peer, afi, safi);
- }
+ if (bgp->default_af[afi][safi]) {
+ peer->afc[afi][safi] = 1;
+ peer_af_create(peer, afi, safi);
}
}
@@ -2585,6 +2578,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
{
struct peer_group *group;
afi_t afi;
+ safi_t safi;
group = peer_group_lookup(bgp, name);
if (group)
@@ -2598,10 +2592,10 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
for (afi = AFI_IP; afi < AFI_MAX; afi++)
group->listen_range[afi] = list_new();
group->conf = peer_new(bgp);
- if (!CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4))
- group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6))
- group->conf->afc[AFI_IP6][SAFI_UNICAST] = 1;
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (bgp->default_af[afi][safi])
+ group->conf->afc[afi][safi] = 1;
+ }
XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
group->conf->group = group;
@@ -3244,6 +3238,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
memory_order_relaxed);
bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
+ bgp->default_af[AFI_IP][SAFI_UNICAST] = true;
QOBJ_REG(bgp, bgp);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 776f4b0a21..d2e8cce997 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -464,38 +464,41 @@ struct bgp {
#define BGP_FLAG_DETERMINISTIC_MED (1 << 1)
#define BGP_FLAG_MED_MISSING_AS_WORST (1 << 2)
#define BGP_FLAG_MED_CONFED (1 << 3)
-#define BGP_FLAG_NO_DEFAULT_IPV4 (1 << 4)
-#define BGP_FLAG_NO_CLIENT_TO_CLIENT (1 << 5)
-#define BGP_FLAG_COMPARE_ROUTER_ID (1 << 7)
-#define BGP_FLAG_ASPATH_IGNORE (1 << 8)
-#define BGP_FLAG_IMPORT_CHECK (1 << 9)
-#define BGP_FLAG_NO_FAST_EXT_FAILOVER (1 << 10)
-#define BGP_FLAG_LOG_NEIGHBOR_CHANGES (1 << 11)
+#define BGP_FLAG_NO_CLIENT_TO_CLIENT (1 << 4)
+#define BGP_FLAG_COMPARE_ROUTER_ID (1 << 5)
+#define BGP_FLAG_ASPATH_IGNORE (1 << 6)
+#define BGP_FLAG_IMPORT_CHECK (1 << 7)
+#define BGP_FLAG_NO_FAST_EXT_FAILOVER (1 << 8)
+#define BGP_FLAG_LOG_NEIGHBOR_CHANGES (1 << 9)
/* This flag is set when we have full BGP Graceful-Restart mode enable */
-#define BGP_FLAG_GRACEFUL_RESTART (1 << 12)
-
-#define BGP_FLAG_ASPATH_CONFED (1 << 13)
-#define BGP_FLAG_ASPATH_MULTIPATH_RELAX (1 << 14)
-#define BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY (1 << 15)
-#define BGP_FLAG_DISABLE_NH_CONNECTED_CHK (1 << 16)
-#define BGP_FLAG_MULTIPATH_RELAX_AS_SET (1 << 17)
-#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18)
-#define BGP_FLAG_SHOW_HOSTNAME (1 << 19)
-#define BGP_FLAG_GR_PRESERVE_FWD (1 << 20)
-#define BGP_FLAG_GRACEFUL_SHUTDOWN (1 << 21)
-#define BGP_FLAG_DELETE_IN_PROGRESS (1 << 22)
-#define BGP_FLAG_SELECT_DEFER_DISABLE (1 << 23)
-#define BGP_FLAG_GR_DISABLE_EOR (1 << 24)
-#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25)
-#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26)
+#define BGP_FLAG_GRACEFUL_RESTART (1 << 10)
+
+#define BGP_FLAG_ASPATH_CONFED (1 << 11)
+#define BGP_FLAG_ASPATH_MULTIPATH_RELAX (1 << 12)
+#define BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY (1 << 13)
+#define BGP_FLAG_DISABLE_NH_CONNECTED_CHK (1 << 14)
+#define BGP_FLAG_MULTIPATH_RELAX_AS_SET (1 << 15)
+#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 16)
+#define BGP_FLAG_SHOW_HOSTNAME (1 << 17)
+#define BGP_FLAG_GR_PRESERVE_FWD (1 << 18)
+#define BGP_FLAG_GRACEFUL_SHUTDOWN (1 << 19)
+#define BGP_FLAG_DELETE_IN_PROGRESS (1 << 20)
+#define BGP_FLAG_SELECT_DEFER_DISABLE (1 << 21)
+#define BGP_FLAG_GR_DISABLE_EOR (1 << 22)
+#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 23)
+#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 24)
/* This flag is set if the instance is in administrative shutdown */
-#define BGP_FLAG_SHUTDOWN (1 << 27)
-#define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 28)
-#define BGP_FLAG_SUPPRESS_DUPLICATES (1 << 29)
-#define BGP_FLAG_DEFAULT_IPV6 (1 << 30)
-#define BGP_FLAG_PEERTYPE_MULTIPATH_RELAX (1 << 31)
+#define BGP_FLAG_SHUTDOWN (1 << 25)
+#define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 26)
+#define BGP_FLAG_SUPPRESS_DUPLICATES (1 << 27)
+#define BGP_FLAG_PEERTYPE_MULTIPATH_RELAX (1 << 29)
+
+ /* BGP default address-families.
+ * New peers inherit enabled afi/safis from bgp instance.
+ */
+ uint16_t default_af[AFI_MAX][SAFI_MAX];
enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE]
[BGP_GLOBAL_GR_EVENT_CMD];
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index 92357bec83..16708adb50 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -66,10 +66,6 @@ Basic Config Commands
Set domainname of the router. It is only for current ``vtysh``, it will not
be saved to any configuration file even with ``write file``.
-.. clicmd:: domainname DOMAINNAME
-
- Set domainname of the router.
-
.. clicmd:: password PASSWORD
Set password for vty interface. The ``no`` form of the command deletes the
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 7f23f7a633..b5950538dd 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1597,16 +1597,67 @@ Configuring Peers
.. clicmd:: bgp default ipv4-unicast
- This command allows the user to specify that v4 peering is turned
- on by default or not. This command defaults to on and is not displayed.
+ This command allows the user to specify that the IPv4 Unicast address
+ family is turned on by default or not. This command defaults to on
+ and is not displayed.
The `no bgp default ipv4-unicast` form of the command is displayed.
+.. clicmd:: bgp default ipv4-multicast
+
+ This command allows the user to specify that the IPv4 Multicast address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv4-multicast` form of the command is displayed.
+
+.. clicmd:: bgp default ipv4-vpn
+
+ This command allows the user to specify that the IPv4 MPLS VPN address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv4-vpn` form of the command is displayed.
+
+.. clicmd:: bgp default ipv4-flowspec
+
+ This command allows the user to specify that the IPv4 Flowspec address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv4-flowspec` form of the command is displayed.
+
.. clicmd:: bgp default ipv6-unicast
- This command allows the user to specify that v6 peering is turned
- on by default or not. This command defaults to off and is not displayed.
+ This command allows the user to specify that the IPv6 Unicast address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
The `bgp default ipv6-unicast` form of the command is displayed.
+.. clicmd:: bgp default ipv6-multicast
+
+ This command allows the user to specify that the IPv6 Multicast address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv6-multicast` form of the command is displayed.
+
+.. clicmd:: bgp default ipv6-vpn
+
+ This command allows the user to specify that the IPv6 MPLS VPN address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv6-vpn` form of the command is displayed.
+
+.. clicmd:: bgp default ipv6-flowspec
+
+ This command allows the user to specify that the IPv6 Flowspec address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default ipv6-flowspec` form of the command is displayed.
+
+.. clicmd:: bgp default l2vpn-evpn
+
+ This command allows the user to specify that the L2VPN EVPN address
+ family is turned on by default or not. This command defaults to off
+ and is not displayed.
+ The `bgp default l2vpn-evpn` form of the command is displayed.
+
.. clicmd:: bgp default show-hostname
This command shows the hostname of the peer in certain BGP commands
@@ -2727,10 +2778,12 @@ Host1 MAC/IP as type-2 route which is used to resolve host1 gateway IP.
PE2 receives this type-5 route and imports it into the vrf based on route
targets. BGP prefix imported into the vrf uses gateway IP as its BGP nexthop.
This route is installed into zebra if following conditions are satisfied:
+
1. Gateway IP nexthop is L3 reachable.
2. PE2 has received EVPN type-2 route with IP field set to gateway IP.
Topology requirements:
+
1. This feature is supported for asymmetric routing model only. While
sending packets to SN1, ingress PE (PE2) performs routing and
egress PE (PE1) performs only bridging.
@@ -2749,8 +2802,7 @@ route with gateway IP.
1. CLI to add gateway IP while generating EVPN type-5 route from a BGP IPv4/IPv6
prefix:
-.. index:: advertise <ipv4|ipv6> unicast [gateway-ip]
-.. clicmd:: [no] advertise <ipv4|ipv6> unicast [gateway-ip]
+.. clicmd:: advertise <ipv4|ipv6> unicast [gateway-ip]
When this CLI is configured for a BGP vrf under L2VPN EVPN address family, EVPN
type-5 routes are generated for BGP prefixes in the vrf. Nexthop of the BGP
@@ -2761,8 +2813,7 @@ routes are generated without overlay index.
2. Add gateway IP to EVPN type-5 route using a route-map:
-.. index:: set evpn gateway-ip <ipv4|ipv6> <addr>
-.. clicmd:: [no] set evpn gateway-ip <ipv4|ipv6> <addr>
+.. clicmd:: set evpn gateway-ip <ipv4|ipv6> <addr>
When route-map with above set clause is applied as outbound policy in BGP, it
will set the gateway-ip in EVPN type-5 NLRI.
@@ -2786,8 +2837,7 @@ A PE that receives a type-5 route with gateway IP overlay index should have
"enable-resolve-overlay-index" configuration enabled to recursively resolve the
overlay index nexthop and install the prefix into zebra.
-.. index:: enable-resolve-overlay-index
-.. clicmd:: [no] enable-resolve-overlay-index
+.. clicmd:: enable-resolve-overlay-index
Example configuration:
diff --git a/doc/user/ipv6.rst b/doc/user/ipv6.rst
index 089fae39b1..4f01061e7b 100644
--- a/doc/user/ipv6.rst
+++ b/doc/user/ipv6.rst
@@ -17,6 +17,11 @@ no longer possible.
Router Advertisement
====================
+.. clicmd:: show ipv6 nd ra-interfaces [vrf <VRFNAME|all>]
+
+ Show configured route advertisement interfaces. VRF subcommand only
+ applicable for netns-based vrfs.
+
.. clicmd:: ipv6 nd suppress-ra
Don't send router advertisement messages. The ``no`` form of this command
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 7c01b6f136..04ee1643d8 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -77,20 +77,26 @@ OSPF6 router
of packets to process before returning. The default value of this parameter
is 20.
+.. clicmd:: clear ipv6 ospf6 process [vrf NAME]
+
+ This command clears up the database and routing tables and resets the
+ neighborship by restarting the interface state machine. This will be
+ helpful when there is a change in router-id and if user wants the router-id
+ change to take effect, user can use this cli instead of restarting the
+ ospf6d daemon.
.. _ospf6-area:
OSPF6 area
==========
-.. index:: [no] area A.B.C.D nssa
-.. clicmd:: [no] area A.B.C.D nssa
+.. clicmd:: area A.B.C.D nssa
NSSA Support in OSPFv3
=======================
The configuration of NSSA areas in OSPFv3 is supported using the CLI command
-area A.B.C.D nssa in ospf6 router configuration mode.
+``area A.B.C.D nssa`` in ospf6 router configuration mode.
The following functionalities are implemented as per RFC 3101:
1. Advertising Type-7 LSA into NSSA area when external route is redistributed
@@ -98,7 +104,7 @@ The following functionalities are implemented as per RFC 3101:
2. Processing Type-7 LSA received from neighbor and installing route in the
route table
3. Support for NSSA ABR functionality which is generating Type-5 LSA when
- backbone area is configured. Currently translation od TYpe-7 LSA to Type-5 LSA
+ backbone area is configured. Currently translation of Type-7 LSA to Type-5 LSA
is enabled by default.
4. Support for NSSA Translator functionality when there are multiple NSSA ABR
in an area
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 692ce8c1b2..8d67ec865f 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -80,11 +80,13 @@ Routers
To start OSPF process you have to specify the OSPF router.
-.. clicmd:: router ospf [(1-65535)] vrf NAME
+.. clicmd:: router ospf [{(1-65535)|vrf NAME}]
Enable or disable the OSPF process.
+ Multiple instances don't support `vrf NAME`.
+
.. clicmd:: ospf router-id A.B.C.D
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index ee9da63445..3654801100 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -647,7 +647,6 @@ FRR's cli or frr.conf or zebra.conf. This section shows how
to configure SRv6 on FRR. Of course SRv6 can be used as standalone,
and this section also helps that case.
-.. index:: show segment-routing srv6 locator [json]
.. clicmd:: show segment-routing srv6 locator [json]
This command dump SRv6-locator configured on zebra. SRv6-locator is used
@@ -666,7 +665,6 @@ and this section also helps that case.
loc1 1 2001:db8:1:1::/64 Up
loc2 2 2001:db8:2:2::/64 Up
-.. index:: show segment-routing srv6 locator NAME detail [json]
.. clicmd:: show segment-routing srv6 locator NAME detail [json]
As shown in the example, by specifying the name of the locator, you
@@ -696,29 +694,24 @@ and this section also helps that case.
Chunks:
- prefix: 2001:db8:2:2::/64, owner: sharp
-.. index:: segment-routing
.. clicmd:: segment-routing
Move from configure mode to segment-routing node.
-.. index:: srv6
.. clicmd:: srv6
Move from segment-routing node to srv6 node.
-.. index:: locators
.. clicmd:: locators
Move from srv6 node to locator node. In this locator node, user can
configure detailed settings such as the actual srv6 locator.
-.. index:: locator NAME
.. clicmd:: locator NAME
Create a new locator. If the name of an existing locator is specified,
move to specified locator's configuration node to change the settings it.
-.. index:: prefix X:X::X:X/M [function-bits-length 32]
.. clicmd:: prefix X:X::X:X/M [function-bits-length 32]
Set the ipv6 prefix block of the locator. SRv6 locator is defined by
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c
index 69dcc20253..9a5fbc52b4 100644
--- a/eigrpd/eigrp_network.c
+++ b/eigrpd/eigrp_network.c
@@ -219,7 +219,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix *p)
}
struct prefix *pref = prefix_new();
- PREFIX_COPY_IPV4(pref, p);
+ prefix_copy(pref, p);
rn->info = (void *)pref;
/* Schedule Router ID Update. */
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 366d544d1f..ef86d47b22 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -1196,7 +1196,7 @@ DEFPY_YANG(no_isis_mpls_te_on, no_isis_mpls_te_on_cmd, "no mpls-te [on]",
void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
- vty_out(vty, " mpls-te on\n");
+ vty_out(vty, " mpls-te on\n");
}
/*
@@ -1229,7 +1229,7 @@ DEFPY_YANG(no_isis_mpls_te_router_addr, no_isis_mpls_te_router_addr_cmd,
void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
- vty_out(vty, " mpls-te router-address %s\n",
+ vty_out(vty, " mpls-te router-address %s\n",
yang_dnode_get_string(dnode, NULL));
}
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 0142e30b2b..2c05cb8277 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -145,10 +145,11 @@ static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
+ bool changed = false;
- ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id);
+ ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed);
- if (ifp == NULL)
+ if (ifp == NULL || !changed)
return 0;
/* Update TE TLV */
diff --git a/lib/command.c b/lib/command.c
index e00d84a051..560d4a09f8 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -255,6 +255,9 @@ static bool cmd_hash_cmp(const void *a, const void *b)
/* Install top node of command vector. */
void install_node(struct cmd_node *node)
{
+#define CMD_HASH_STR_SIZE 256
+ char hash_name[CMD_HASH_STR_SIZE];
+
vector_set_index(cmdvec, node->node, node);
node->cmdgraph = graph_new();
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
@@ -263,8 +266,10 @@ void install_node(struct cmd_node *node)
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
graph_new_node(node->cmdgraph, token,
(void (*)(void *)) & cmd_token_del);
- node->cmd_hash = hash_create_size(16, cmd_hash_key, cmd_hash_cmp,
- "Command Hash");
+
+ snprintf(hash_name, sizeof(hash_name), "Command Hash: %s", node->name);
+ node->cmd_hash =
+ hash_create_size(16, cmd_hash_key, cmd_hash_cmp, hash_name);
}
/* Return prompt character of specified node. */
diff --git a/lib/prefix.h b/lib/prefix.h
index 217a23d561..c47e701dfd 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -481,11 +481,6 @@ extern void prefix_ipv4_free(struct prefix_ipv4 **p);
extern int str2prefix_ipv4(const char *, struct prefix_ipv4 *);
extern void apply_mask_ipv4(struct prefix_ipv4 *);
-#define PREFIX_COPY(DST, SRC) \
- *((struct prefix *)(DST)) = *((const struct prefix *)(SRC))
-#define PREFIX_COPY_IPV4(DST, SRC) \
- *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC))
-
extern int prefix_ipv4_any(const struct prefix_ipv4 *);
extern void apply_classful_mask_ipv4(struct prefix_ipv4 *);
@@ -503,9 +498,6 @@ extern void prefix_ipv6_free(struct prefix_ipv6 **p);
extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *);
extern void apply_mask_ipv6(struct prefix_ipv6 *);
-#define PREFIX_COPY_IPV6(DST, SRC) \
- *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC))
-
extern int ip6_masklen(struct in6_addr);
extern void masklen2ip6(const int, struct in6_addr *);
diff --git a/lib/routemap.h b/lib/routemap.h
index 4d76ae1536..4a40ec08b9 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -194,6 +194,11 @@ struct route_map_index {
};
DECLARE_QOBJ_TYPE(route_map_index);
+/* route map maximum length. Not strictly the maximum xpath length but cannot be
+ * greater
+ */
+#define RMAP_NAME_MAXLEN XPATH_MAXLEN
+
/* Route map list structure. */
struct route_map {
/* Name of route map. */
diff --git a/lib/zclient.c b/lib/zclient.c
index 4a70881b57..ffae1332af 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2269,10 +2269,13 @@ stream_failure:
}
struct interface *zebra_interface_link_params_read(struct stream *s,
- vrf_id_t vrf_id)
+ vrf_id_t vrf_id,
+ bool *changed)
{
struct if_link_params *iflp;
+ struct if_link_params iflp_copy;
ifindex_t ifindex;
+ bool params_changed = false;
STREAM_GETL(s, ifindex);
@@ -2285,12 +2288,23 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
return NULL;
}
+ if (ifp->link_params == NULL)
+ params_changed = true;
+
if ((iflp = if_link_params_get(ifp)) == NULL)
return NULL;
+ memcpy(&iflp_copy, iflp, sizeof(iflp_copy));
+
if (link_params_set_value(s, iflp) != 0)
goto stream_failure;
+ if (memcmp(&iflp_copy, iflp, sizeof(iflp_copy)))
+ params_changed = true;
+
+ if (changed)
+ *changed = params_changed;
+
return ifp;
stream_failure:
diff --git a/lib/zclient.h b/lib/zclient.h
index 48de3425be..a25c5800b7 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -1043,7 +1043,8 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
extern int zebra_router_id_update_read(struct stream *s, struct prefix *rid);
extern struct interface *zebra_interface_link_params_read(struct stream *s,
- vrf_id_t vrf_id);
+ vrf_id_t vrf_id,
+ bool *changed);
extern size_t zebra_interface_link_params_write(struct stream *,
struct interface *);
extern enum zclient_send_status
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index ba355a347e..d7307fe375 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -2478,7 +2478,7 @@ void ospf6_asbr_init(void)
install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd);
}
-void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6)
+void ospf6_asbr_redistribute_disable(struct ospf6 *ospf6)
{
int type;
struct ospf6_redist *red;
@@ -2500,6 +2500,35 @@ void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6)
}
}
+void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6)
+{
+ int type;
+ struct ospf6_redist *red;
+ char buf[RMAP_NAME_MAXLEN];
+
+ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+ buf[0] = '\0';
+ if (type == ZEBRA_ROUTE_OSPF6)
+ continue;
+ red = ospf6_redist_lookup(ospf6, type, 0);
+ if (!red)
+ continue;
+
+ if (type == DEFAULT_ROUTE) {
+ ospf6_redistribute_default_set(
+ ospf6, ospf6->default_originate);
+ continue;
+ }
+ if (ROUTEMAP_NAME(red))
+ strlcpy(buf, ROUTEMAP_NAME(red), sizeof(buf));
+
+ ospf6_asbr_redistribute_unset(ospf6, red, type);
+ if (buf[0])
+ ospf6_asbr_routemap_set(red, buf);
+ ospf6_asbr_redistribute_set(ospf6, type);
+ }
+}
+
void ospf6_asbr_terminate(void)
{
/* Cleanup route maps */
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 418c157f36..8f2135ef30 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -93,6 +93,7 @@ extern int ospf6_redistribute_config_write(struct vty *vty,
struct ospf6 *ospf6);
extern void ospf6_asbr_init(void);
+extern void ospf6_asbr_redistribute_disable(struct ospf6 *ospf6);
extern void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6);
extern void ospf6_asbr_terminate(void);
extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *);
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 553967e2e3..1e75fc60f6 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -2695,7 +2695,7 @@ void ospf6_interface_init(void)
}
/* Clear the specified interface structure */
-static void ospf6_interface_clear(struct vty *vty, struct interface *ifp)
+void ospf6_interface_clear(struct interface *ifp)
{
struct ospf6_interface *oi;
@@ -2733,7 +2733,7 @@ DEFUN (clear_ipv6_ospf6_interface,
if (argc == 4) /* Clear all the ospfv3 interfaces. */
{
FOR_ALL_INTERFACES (vrf, ifp)
- ospf6_interface_clear(vty, ifp);
+ ospf6_interface_clear(ifp);
} else /* Interface name is specified. */
{
if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg,
@@ -2743,7 +2743,7 @@ DEFUN (clear_ipv6_ospf6_interface,
argv[idx_ifname]->arg);
return CMD_WARNING;
}
- ospf6_interface_clear(vty, ifp);
+ ospf6_interface_clear(ifp);
}
return CMD_SUCCESS;
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index 530efc3bd2..c9cd74b691 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -213,6 +213,7 @@ extern int backup_seen(struct thread *);
extern int neighbor_change(struct thread *);
extern void ospf6_interface_init(void);
+extern void ospf6_interface_clear(struct interface *ifp);
extern void install_element_ospf6_clear_interface(void);
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index d627194252..bab5fdaae8 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -659,7 +659,7 @@ void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
adv_router);
json_object_int_add(json_obj, "lsSequenceNumber",
(unsigned long)ntohl(lsa->header->seqnum));
- json_object_int_add(json_obj, "checkSum",
+ json_object_int_add(json_obj, "checksum",
ntohs(lsa->header->checksum));
json_object_int_add(json_obj, "length",
ntohs(lsa->header->length));
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 5f23aab80a..817e5372ea 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -1709,6 +1709,13 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
return OSPF6_READ_CONTINUE;
}
+ /*
+ * Drop packet destined to another VRF.
+ * This happens when raw_l3mdev_accept is set to 1.
+ */
+ if (ospf6->vrf_id != oi->interface->vrf_id)
+ return OSPF6_READ_CONTINUE;
+
oh = (struct ospf6_header *)recvbuf;
if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
return OSPF6_READ_CONTINUE;
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 6cea5032bd..6f40989efd 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -63,6 +63,10 @@ FRR_CFG_DEFAULT_BOOL(OSPF6_LOG_ADJACENCY_CHANGES,
{ .val_bool = false },
);
+#ifndef VTYSH_EXTRACT_PL
+#include "ospf6d/ospf6_top_clippy.c"
+#endif
+
/* global ospf6d variable */
static struct ospf6_master ospf6_master;
struct ospf6_master *om6;
@@ -512,7 +516,7 @@ static void ospf6_disable(struct ospf6 *o)
/* XXX: This also changes persistent settings */
/* Unregister redistribution */
- ospf6_asbr_redistribute_reset(o);
+ ospf6_asbr_redistribute_disable(o);
ospf6_lsdb_remove_all(o->lsdb);
ospf6_route_remove_all(o->route_table);
@@ -598,7 +602,7 @@ void ospf6_router_id_update(struct ospf6 *ospf6)
if (ospf6->router_id_static != 0)
ospf6->router_id = ospf6->router_id_static;
else
- ospf6->router_id = om6->zebra_router_id;
+ ospf6->router_id = ospf6->router_id_zebra;
}
/* start ospf6 */
@@ -649,6 +653,78 @@ DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
return CMD_SUCCESS;
}
+static void ospf6_db_clear(struct ospf6 *ospf6)
+{
+ struct ospf6_interface *oi;
+ struct interface *ifp;
+ struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
+ struct listnode *node, *nnode;
+ struct ospf6_area *oa;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ if (if_is_operative(ifp) && ifp->info != NULL) {
+ oi = (struct ospf6_interface *)ifp->info;
+ ospf6_lsdb_remove_all(oi->lsdb);
+ ospf6_lsdb_remove_all(oi->lsdb_self);
+ ospf6_lsdb_remove_all(oi->lsupdate_list);
+ ospf6_lsdb_remove_all(oi->lsack_list);
+ }
+ }
+
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
+ ospf6_lsdb_remove_all(oa->lsdb);
+ ospf6_lsdb_remove_all(oa->lsdb_self);
+
+ ospf6_spf_table_finish(oa->spf_table);
+ ospf6_route_remove_all(oa->route_table);
+ }
+
+ ospf6_lsdb_remove_all(ospf6->lsdb);
+ ospf6_lsdb_remove_all(ospf6->lsdb_self);
+ ospf6_route_remove_all(ospf6->route_table);
+ ospf6_route_remove_all(ospf6->brouter_table);
+}
+
+static void ospf6_process_reset(struct ospf6 *ospf6)
+{
+ struct interface *ifp;
+ struct vrf *vrf = vrf_lookup_by_id(ospf6->vrf_id);
+
+ ospf6_flush_self_originated_lsas_now(ospf6);
+ ospf6->inst_shutdown = 0;
+ ospf6_db_clear(ospf6);
+
+ ospf6_router_id_update(ospf6);
+
+ ospf6_asbr_redistribute_reset(ospf6);
+ FOR_ALL_INTERFACES (vrf, ifp)
+ ospf6_interface_clear(ifp);
+}
+
+DEFPY (clear_router_ospf6,
+ clear_router_ospf6_cmd,
+ "clear ipv6 ospf6 process [vrf NAME$name]",
+ CLEAR_STR
+ IP6_STR
+ OSPF6_STR
+ "Reset OSPF Process\n"
+ VRF_CMD_HELP_STR)
+{
+ struct ospf6 *ospf6;
+ const char *vrf_name = VRF_DEFAULT_NAME;
+
+ if (name != NULL)
+ vrf_name = name;
+
+ ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
+ if (ospf6 == NULL)
+ vty_out(vty, "OSPFv3 is not configured\n");
+ else
+ ospf6_process_reset(ospf6);
+
+ return CMD_SUCCESS;
+}
+
/* change Router_ID commands. */
DEFUN(ospf6_router_id,
ospf6_router_id_cmd,
@@ -679,7 +755,7 @@ DEFUN(ospf6_router_id,
for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
if (oa->full_nbrs) {
vty_out(vty,
- "For this router-id change to take effect, save config and restart ospf6d\n");
+ "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n");
return CMD_SUCCESS;
}
}
@@ -705,13 +781,13 @@ DEFUN(no_ospf6_router_id,
for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
if (oa->full_nbrs) {
vty_out(vty,
- "For this router-id change to take effect, save config and restart ospf6d\n");
+ "For this router-id change to take effect, run the \"clear ipv6 ospf6 process\" command\n");
return CMD_SUCCESS;
}
}
o->router_id = 0;
- if (o->router_id_zebra.s_addr)
- o->router_id = (uint32_t)o->router_id_zebra.s_addr;
+ if (o->router_id_zebra)
+ o->router_id = o->router_id_zebra;
return CMD_SUCCESS;
}
@@ -1708,6 +1784,11 @@ static struct cmd_node ospf6_node = {
.config_write = config_write_ospf6,
};
+void install_element_ospf6_clear_process(void)
+{
+ install_element(ENABLE_NODE, &clear_router_ospf6_cmd);
+}
+
/* Install ospf related commands. */
void ospf6_top_init(void)
{
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 5b739ac76b..f0251bcb62 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -29,7 +29,6 @@ struct ospf6_master {
struct list *ospf6;
/* OSPFv3 thread master. */
struct thread_master *master;
- in_addr_t zebra_router_id;
};
/* ospf6->config_flags */
@@ -71,7 +70,7 @@ struct ospf6 {
/* static router id */
in_addr_t router_id_static;
- struct in_addr router_id_zebra;
+ in_addr_t router_id_zebra;
/* start time */
struct timeval starttime;
@@ -173,6 +172,7 @@ extern struct ospf6_master *om6;
/* prototypes */
extern void ospf6_master_init(struct thread_master *master);
+extern void install_element_ospf6_clear_process(void);
extern void ospf6_top_init(void);
extern void ospf6_delete(struct ospf6 *o);
extern void ospf6_router_id_update(struct ospf6 *ospf6);
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 170d545c49..a7e15c68ae 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -90,15 +90,16 @@ static int ospf6_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
zebra_router_id_update_read(zclient->ibuf, &router_id);
- om6->zebra_router_id = router_id.u.prefix4.s_addr;
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug("Zebra router-id update %pI4 vrf %s id %u",
+ &router_id.u.prefix4, ospf6_vrf_id_to_name(vrf_id),
+ vrf_id);
+
o = ospf6_lookup_by_vrf_id(vrf_id);
if (o == NULL)
return 0;
- o->router_id_zebra = router_id.u.prefix4;
- if (IS_OSPF6_DEBUG_ZEBRA(RECV))
- zlog_debug("%s: zebra router-id %pI4 update", __func__,
- &router_id.u.prefix4);
+ o->router_id_zebra = router_id.u.prefix4.s_addr;
ospf6_router_id_update(o);
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 65f0aa664e..fb6ac4402a 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -1425,6 +1425,7 @@ void ospf6_init(struct thread_master *master)
install_element_ospf6_debug_flood();
install_element_ospf6_debug_nssa();
+ install_element_ospf6_clear_process();
install_element_ospf6_clear_interface();
install_element(ENABLE_NODE, &show_debugging_ospf6_cmd);
diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am
index 2e1891be71..2b7bce5392 100644
--- a/ospf6d/subdir.am
+++ b/ospf6d/subdir.am
@@ -88,6 +88,7 @@ ospf6d_ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la
clippy_scan += \
+ ospf6d/ospf6_top.c \
ospf6d/ospf6_asbr.c \
# end
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index b4e318d1d1..b3aba247df 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -50,6 +50,7 @@
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_te.h"
DEFINE_QOBJ_TYPE(ospf_interface);
DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
@@ -1354,6 +1355,9 @@ static int ospf_ifp_create(struct interface *ifp)
ospf_if_update(ospf, ifp);
+ if (HAS_LINK_PARAMS(ifp))
+ ospf_mpls_te_update_if(ifp);
+
hook_call(ospf_if_update, ifp);
return 0;
@@ -1392,6 +1396,9 @@ static int ospf_ifp_up(struct interface *ifp)
ospf_if_up(oi);
}
+ if (HAS_LINK_PARAMS(ifp))
+ ospf_mpls_te_update_if(ifp);
+
return 0;
}
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 5853b506f8..df112edc68 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -163,10 +163,11 @@ static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS)
static int ospf_interface_link_params(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
+ bool changed = false;
- ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id);
+ ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed);
- if (ifp == NULL)
+ if (ifp == NULL || !changed)
return 0;
/* Update TE TLV */
diff --git a/pathd/pathd.c b/pathd/pathd.c
index 022813a497..90b8727284 100644
--- a/pathd/pathd.c
+++ b/pathd/pathd.c
@@ -666,7 +666,7 @@ struct srte_candidate *srte_candidate_add(struct srte_policy *policy,
candidate->preference = preference;
candidate->policy = policy;
candidate->type = SRTE_CANDIDATE_TYPE_UNDEFINED;
- candidate->discriminator = rand();
+ candidate->discriminator = frr_weak_random();
candidate->protocol_origin = origin;
if (originator != NULL) {
strlcpy(candidate->originator, originator,
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 544cc6630d..c4afd04a07 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -6323,7 +6323,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
if (!uj && !found_oif) {
vty_out(vty,
- "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
+ "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
src_str, grp_str, state_str, "none", in_ifname,
"none", 0, "--:--:--");
}
@@ -6430,10 +6430,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
json_ifp_out);
} else {
vty_out(vty,
- "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
- src_str, grp_str, proto, in_ifname,
- out_ifname, ttl, oif_uptime,
- pim->vrf->name);
+ "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
+ src_str, grp_str, "-", proto, in_ifname,
+ out_ifname, ttl, oif_uptime);
if (first && !fill) {
src_str[0] = '\0';
grp_str[0] = '\0';
@@ -6445,9 +6444,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
if (!uj && !found_oif) {
vty_out(vty,
- "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
- src_str, grp_str, proto, in_ifname, "none", 0,
- "--:--:--", pim->vrf->name);
+ "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
+ src_str, grp_str, "-", proto, in_ifname, "none",
+ 0, "--:--:--");
}
}
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 44b55a2381..45e9912a31 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -31,6 +31,7 @@
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_network.h"
#include "lib/routing_nb.h"
+#include "lib/northbound_cli.h"
#include "bgpd/bgp_nb.h"
#ifdef ENABLE_BGP_VNC
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/__init__.py b/tests/topotests/bgp_default_afi_safi/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/__init__.py
+++ b/tests/topotests/bgp_default_afi_safi/__init__.py
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r1/bgpd.conf
index bf39152ea8..bf39152ea8 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/bgpd.conf
+++ b/tests/topotests/bgp_default_afi_safi/r1/bgpd.conf
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/zebra.conf b/tests/topotests/bgp_default_afi_safi/r1/zebra.conf
index 697765168d..697765168d 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/zebra.conf
+++ b/tests/topotests/bgp_default_afi_safi/r1/zebra.conf
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r2/bgpd.conf
index abbd1b86fa..abbd1b86fa 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/bgpd.conf
+++ b/tests/topotests/bgp_default_afi_safi/r2/bgpd.conf
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/zebra.conf b/tests/topotests/bgp_default_afi_safi/r2/zebra.conf
index 606c17bec9..606c17bec9 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/zebra.conf
+++ b/tests/topotests/bgp_default_afi_safi/r2/zebra.conf
diff --git a/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf
new file mode 100644
index 0000000000..f3ec3f06c5
--- /dev/null
+++ b/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf
@@ -0,0 +1,5 @@
+!
+router bgp 65001
+ no bgp default ipv4-unicast
+ bgp default l2vpn-evpn
+!
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/zebra.conf b/tests/topotests/bgp_default_afi_safi/r3/zebra.conf
index e9fdfb70c5..e9fdfb70c5 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/zebra.conf
+++ b/tests/topotests/bgp_default_afi_safi/r3/zebra.conf
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r4/bgpd.conf
index a405c047ca..8a6af55ee7 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/bgpd.conf
+++ b/tests/topotests/bgp_default_afi_safi/r4/bgpd.conf
@@ -1,4 +1,5 @@
!
router bgp 65001
bgp default ipv6-unicast
+ bgp default l2vpn-evpn
!
diff --git a/tests/topotests/bgp_default_afi_safi/r4/zebra.conf b/tests/topotests/bgp_default_afi_safi/r4/zebra.conf
new file mode 100644
index 0000000000..e9fdfb70c5
--- /dev/null
+++ b/tests/topotests/bgp_default_afi_safi/r4/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 192.168.255.3/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/test_bgp-default-ipv4-ipv6-unicast.py b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
index f9aa94fd14..28117b7fe4 100644
--- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/test_bgp-default-ipv4-ipv6-unicast.py
+++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
@@ -20,12 +20,13 @@
#
"""
-Test if `bgp default ipv4-unicast` and `bgp default ipv6-unicast`
-commands work as expected.
+Test if `bgp default ipv4-unicast`, `bgp default ipv6-unicast`
+and `bgp default l2vpn-evpn` commands work as expected.
STEP 1: 'Check if neighbor 192.168.255.254 is enabled for ipv4 address-family only'
STEP 2: 'Check if neighbor 192.168.255.254 is enabled for ipv6 address-family only'
-STEP 3: 'Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families'
+STEP 3: 'Check if neighbor 192.168.255.254 is enabled for l2vpn evpn address-family only'
+STEP 4: 'Check if neighbor 192.168.255.254 is enabled for ipv4/ipv6 unicast and l2vpn evpn address-families'
"""
import os
@@ -98,7 +99,7 @@ def test_bgp_default_ipv4_ipv6_unicast():
output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp summary json"))
- if "ipv4Unicast" in output and "ipv6Unicast" not in output:
+ if len(output.keys()) == 1 and "ipv4Unicast" in output:
return True
return False
@@ -113,28 +114,48 @@ def test_bgp_default_ipv4_ipv6_unicast():
output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp summary json"))
- if "ipv4Unicast" not in output and "ipv6Unicast" in output:
+ if len(output.keys()) == 1 and "ipv6Unicast" in output:
return True
return False
assert _bgp_neighbor_ipv6_af_only() == True
- step(
- "Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families"
- )
+ step("Check if neighbor 192.168.255.254 is enabled for evpn address-family only")
- def _bgp_neighbor_ipv4_and_ipv6_af():
+ def _bgp_neighbor_evpn_af_only():
tgen.gears["r3"].vtysh_cmd(
"conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external"
)
output = json.loads(tgen.gears["r3"].vtysh_cmd("show bgp summary json"))
- if "ipv4Unicast" in output and "ipv6Unicast" in output:
+ if len(output.keys()) == 1 and "l2VpnEvpn" in output:
+ return True
+ return False
+
+ assert _bgp_neighbor_evpn_af_only() == True
+
+ step(
+ "Check if neighbor 192.168.255.254 is enabled for ipv4/ipv6 unicast and evpn address-families"
+ )
+
+ def _bgp_neighbor_ipv4_ipv6_and_evpn_af():
+ tgen.gears["r4"].vtysh_cmd(
+ "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external"
+ )
+
+ output = json.loads(tgen.gears["r4"].vtysh_cmd("show bgp summary json"))
+
+ if (
+ len(output.keys()) == 3
+ and "ipv4Unicast" in output
+ and "ipv6Unicast" in output
+ and "l2VpnEvpn" in output
+ ):
return True
return False
- assert _bgp_neighbor_ipv4_and_ipv6_af() == True
+ assert _bgp_neighbor_ipv4_ipv6_and_evpn_af() == True
if __name__ == "__main__":
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index db7b3586f1..a236a916b5 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -989,7 +989,7 @@ def modify_bgp_config_when_bgpd_down(tgen, topo, input_dict):
#############################################
# Verification APIs
#############################################
-@retry(attempts=4, wait=2, return_is_str=True)
+@retry(retry_timeout=8)
def verify_router_id(tgen, topo, input_dict, expected=True):
"""
Running command "show ip bgp json" for DUT and reading router-id
@@ -1061,7 +1061,7 @@ def verify_router_id(tgen, topo, input_dict, expected=True):
return True
-@retry(attempts=50, wait=3, return_is_str=True)
+@retry(retry_timeout=150)
def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
"""
API will verify if BGP is converged with in the given time frame.
@@ -1266,7 +1266,7 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
return True
-@retry(attempts=4, wait=4, return_is_str=True)
+@retry(retry_timeout=16)
def verify_bgp_community(
tgen, addr_type, router, network, input_dict=None, vrf=None, bestpath=False, expected=True
):
@@ -1427,7 +1427,7 @@ def modify_as_number(tgen, topo, input_dict):
return True
-@retry(attempts=4, wait=2, return_is_str=True)
+@retry(retry_timeout=8)
def verify_as_numbers(tgen, topo, input_dict, expected=True):
"""
This API is to verify AS numbers for given DUT by running
@@ -1527,7 +1527,7 @@ def verify_as_numbers(tgen, topo, input_dict, expected=True):
return True
-@retry(attempts=50, wait=3, return_is_str=True)
+@retry(retry_timeout=150)
def verify_bgp_convergence_from_running_config(tgen, dut=None, expected=True):
"""
API to verify BGP convergence b/w loopback and physical interface.
@@ -2083,7 +2083,7 @@ def verify_bgp_timers_and_functionality(tgen, topo, input_dict):
return True
-@retry(attempts=4, wait=4, return_is_str=True)
+@retry(retry_timeout=16)
def verify_bgp_attributes(
tgen,
addr_type,
@@ -2223,7 +2223,7 @@ def verify_bgp_attributes(
return True
-@retry(attempts=4, wait=2, return_is_str=True)
+@retry(retry_timeout=8)
def verify_best_path_as_per_bgp_attribute(
tgen, addr_type, router, input_dict, attribute, expected=True
):
@@ -2429,7 +2429,7 @@ def verify_best_path_as_per_bgp_attribute(
return True
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_best_path_as_per_admin_distance(
tgen, addr_type, router, input_dict, attribute, expected=True
):
@@ -2543,7 +2543,7 @@ def verify_best_path_as_per_admin_distance(
return True
-@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
+@retry(retry_timeout=10, initial_wait=2)
def verify_bgp_rib(
tgen, addr_type, dut, input_dict, next_hop=None, aspath=None, multi_nh=None, expected=True
):
@@ -2846,7 +2846,7 @@ def verify_bgp_rib(
return True
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_graceful_restart(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
"""
This API is to verify verify_graceful_restart configuration of DUT and
@@ -3096,7 +3096,7 @@ def verify_graceful_restart(tgen, topo, addr_type, input_dict, dut, peer, expect
return True
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_r_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
"""
This API is to verify r_bit in the BGP gr capability advertised
@@ -3216,7 +3216,7 @@ def verify_r_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
return True
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_eor(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
"""
This API is to verify EOR
@@ -3379,7 +3379,7 @@ def verify_eor(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
return True
-@retry(attempts=4, wait=2, return_is_str=True)
+@retry(retry_timeout=8)
def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
"""
This API is to verify f_bit in the BGP gr capability advertised
@@ -3520,7 +3520,7 @@ def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
return True
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer):
"""
This API is to verify graceful restart timers, configured and recieved
@@ -3648,7 +3648,7 @@ def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer)
return True
-@retry(attempts=4, wait=2, return_is_str=True)
+@retry(retry_timeout=8)
def verify_gr_address_family(tgen, topo, addr_type, addr_family, dut, expected=True):
"""
This API is to verify gr_address_family in the BGP gr capability advertised
@@ -3739,7 +3739,7 @@ def verify_gr_address_family(tgen, topo, addr_type, addr_family, dut, expected=T
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_attributes_for_evpn_routes(
tgen,
topo,
@@ -4139,7 +4139,7 @@ def verify_attributes_for_evpn_routes(
return False
-@retry(attempts=5, wait=2, return_is_str=True)
+@retry(retry_timeout=10)
def verify_evpn_routes(
tgen, topo, dut, input_dict, routeType=5, EthTag=0, next_hop=None, expected=True
):
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 3f78f020bc..9e38608631 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -19,7 +19,7 @@
#
from collections import OrderedDict
-from datetime import datetime
+from datetime import datetime, timedelta
from time import sleep
from copy import deepcopy
from subprocess import call
@@ -37,12 +37,14 @@ import socket
import ipaddress
import platform
-if sys.version_info[0] > 2:
- import io
- import configparser
-else:
- import StringIO
+try:
+ # Imports from python2
+ from StringIO import StringIO
import ConfigParser as configparser
+except ImportError:
+ # Imports from python3
+ from io import StringIO
+ import configparser
from lib.topolog import logger, logger_config
from lib.topogen import TopoRouter, get_topogen
@@ -136,6 +138,12 @@ DEBUG_LOGS = {
],
}
+def is_string(value):
+ try:
+ return isinstance(value, basestring)
+ except NameError:
+ return isinstance(value, str)
+
if config.has_option("topogen", "verbosity"):
loglevel = config.get("topogen", "verbosity")
loglevel = loglevel.upper()
@@ -448,16 +456,6 @@ def check_router_status(tgen):
return True
-def getStrIO():
- """
- Return a StringIO object appropriate for the current python version.
- """
- if sys.version_info[0] > 2:
- return io.StringIO()
- else:
- return StringIO.StringIO()
-
-
def reset_config_on_routers(tgen, routerName=None):
"""
Resets configuration on routers to the snapshot created using input JSON
@@ -529,7 +527,7 @@ def reset_config_on_routers(tgen, routerName=None):
raise InvalidCLIError("Unknown error in %s", output)
f = open(dname, "r")
- delta = getStrIO()
+ delta = StringIO()
delta.write("configure terminal\n")
t_delta = f.read()
@@ -563,7 +561,7 @@ def reset_config_on_routers(tgen, routerName=None):
output = router.vtysh_multicmd(delta.getvalue(), pretty_output=False)
delta.close()
- delta = getStrIO()
+ delta = StringIO()
cfg = router.run("vtysh -c 'show running'")
for line in cfg.split("\n"):
line = line.strip()
@@ -1619,60 +1617,99 @@ def interface_status(tgen, topo, input_dict):
return True
-def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0, return_is_dict=False):
+def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75):
"""
- Retries function execution, if return is an errormsg or exception
-
- * `attempts`: Number of attempts to make
- * `wait`: Number of seconds to wait between each attempt
- * `return_is_str`: Return val is an errormsg in case of failure
- * `initial_wait`: Sleeps for this much seconds before executing function
-
+ Fixture: Retries function while it's return value is an errormsg (str), False, or it raises an exception.
+
+ * `retry_timeout`: Retry for at least this many seconds; after waiting initial_wait seconds
+ * `initial_wait`: Sleeps for this many seconds before first executing function
+ * `expected`: if False then the return logic is inverted, except for exceptions,
+ (i.e., a False or errmsg (str) function return ends the retry loop,
+ and returns that False or str value)
+ * `diag_pct`: Percentage of `retry_timeout` to keep testing after negative result would have
+ been returned in order to see if a positive result comes after. This is an
+ important diagnostic tool, and normally should not be disabled. Calls to wrapped
+ functions though, can override the `diag_pct` value to make it larger in case more
+ diagnostic retrying is appropriate.
"""
def _retry(func):
@wraps(func)
def func_retry(*args, **kwargs):
- _wait = kwargs.pop("wait", wait)
- _attempts = kwargs.pop("attempts", attempts)
- _attempts = int(_attempts)
- if _attempts < 0:
- raise ValueError("attempts must be 0 or greater")
+ # We will continue to retry diag_pct of the timeout value to see if test would have passed with a
+ # longer retry timeout value.
+ saved_failure = None
+
+ retry_sleep = 2
+
+ # Allow the wrapped function's args to override the fixtures
+ _retry_timeout = kwargs.pop("retry_timeout", retry_timeout)
+ _expected = kwargs.pop("expected", expected)
+ _initial_wait = kwargs.pop("initial_wait", initial_wait)
+ _diag_pct = kwargs.pop("diag_pct", diag_pct)
+
+ start_time = datetime.now()
+ retry_until = datetime.now() + timedelta(seconds=_retry_timeout + _initial_wait)
if initial_wait > 0:
logger.info("Waiting for [%s]s as initial delay", initial_wait)
sleep(initial_wait)
- _return_is_str = kwargs.pop("return_is_str", return_is_str)
- _return_is_dict = kwargs.pop("return_is_str", return_is_dict)
- _expected = kwargs.setdefault("expected", True)
- kwargs.pop("expected")
- for i in range(1, _attempts + 1):
+ invert_logic = not _expected
+ while True:
+ seconds_left = (retry_until - datetime.now()).total_seconds()
try:
ret = func(*args, **kwargs)
logger.debug("Function returned %s", ret)
- if _return_is_str and isinstance(ret, bool) and _expected:
- return ret
- if (
- isinstance(ret, str) or isinstance(ret, unicode)
- ) and _expected is False:
- return ret
- if _return_is_dict and isinstance(ret, dict):
- return ret
-
- if _attempts == i:
- generate_support_bundle()
- return ret
- except Exception as err:
- if _attempts == i:
- generate_support_bundle()
- logger.info("Max number of attempts (%r) reached", _attempts)
- raise
- else:
- logger.info("Function returned %s", err)
- if i < _attempts:
- logger.info("Retry [#%r] after sleeping for %ss" % (i, _wait))
- sleep(_wait)
+
+ negative_result = ret is False or is_string(ret)
+ if negative_result == invert_logic:
+ # Simple case, successful result in time
+ if not saved_failure:
+ return ret
+
+ # Positive result, but happened after timeout failure, very important to
+ # note for fixing tests.
+ logger.warning("RETRY DIAGNOSTIC: SUCCEED after FAILED with requested timeout of %.1fs; however, succeeded in %.1fs, investigate timeout timing",
+ _retry_timeout, (datetime.now() - start_time).total_seconds())
+ if isinstance(saved_failure, Exception):
+ raise saved_failure # pylint: disable=E0702
+ return saved_failure
+
+ except Exception as error:
+ logger.info("Function raised exception: %s", str(error))
+ ret = error
+
+ if seconds_left < 0 and saved_failure:
+ logger.info("RETRY DIAGNOSTIC: Retry timeout reached, still failing")
+ if isinstance(saved_failure, Exception):
+ raise saved_failure # pylint: disable=E0702
+ return saved_failure
+
+ if seconds_left < 0:
+ logger.info("Retry timeout of %ds reached", _retry_timeout)
+
+ saved_failure = ret
+ retry_extra_delta = timedelta(seconds=seconds_left + _retry_timeout * _diag_pct)
+ retry_until = datetime.now() + retry_extra_delta
+ seconds_left = retry_extra_delta.total_seconds()
+
+ # Generate bundle after setting remaining diagnostic retry time
+ generate_support_bundle()
+
+ # If user has disabled diagnostic retries return now
+ if not _diag_pct:
+ if isinstance(saved_failure, Exception):
+ raise saved_failure
+ return saved_failure
+
+ if saved_failure:
+ logger.info("RETRY DIAG: [failure] Sleeping %ds until next retry with %.1f retry time left - too see if timeout was too short",
+ retry_sleep, seconds_left)
+ else:
+ logger.info("Sleeping %ds until next retry with %.1f retry time left",
+ retry_sleep, seconds_left)
+ sleep(retry_sleep)
func_retry._original = func
return func_retry
@@ -2881,7 +2918,7 @@ def configure_interface_mac(tgen, input_dict):
#############################################
# Verification APIs
#############################################
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_rib(
tgen,
addr_type,
@@ -3290,7 +3327,7 @@ def verify_rib(
return True
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
"""
Data will be read from input_dict or input JSON file, API will generate
@@ -3694,7 +3731,7 @@ def verify_prefix_lists(tgen, input_dict):
return True
-@retry(attempts=3, wait=4, return_is_str=True)
+@retry(retry_timeout=12)
def verify_route_maps(tgen, input_dict):
"""
Running "show route-map" command and verifying given route-map
@@ -3746,7 +3783,7 @@ def verify_route_maps(tgen, input_dict):
return True
-@retry(attempts=4, wait=4, return_is_str=True)
+@retry(retry_timeout=16)
def verify_bgp_community(tgen, addr_type, router, network, input_dict=None):
"""
API to veiryf BGP large community is attached in route for any given
@@ -3982,7 +4019,7 @@ def verify_cli_json(tgen, input_dict):
return True
-@retry(attempts=3, wait=4, return_is_str=True)
+@retry(retry_timeout=12)
def verify_evpn_vni(tgen, input_dict):
"""
API to verify evpn vni details using "show evpn vni detail json"
@@ -4100,7 +4137,7 @@ def verify_evpn_vni(tgen, input_dict):
return False
-@retry(attempts=3, wait=4, return_is_str=True)
+@retry(retry_timeout=12)
def verify_vrf_vni(tgen, input_dict):
"""
API to verify vrf vni details using "show vrf vni json"
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 3f39b93d8c..dc9fe0fcca 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -579,7 +579,7 @@ def redistribute_ospf(tgen, topo, dut, route_type, **kwargs):
################################
# Verification procs
################################
-@retry(attempts=40, wait=2, return_is_str=True)
+@retry(retry_timeout=80)
def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expected=True):
"""
This API is to verify ospf neighborship by running
@@ -774,7 +774,7 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expec
################################
# Verification procs
################################
-@retry(attempts=10, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False):
"""
This API is to verify ospf neighborship by running
@@ -959,7 +959,7 @@ def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False):
return result
-@retry(attempts=21, wait=2, return_is_str=True)
+@retry(retry_timeout=40)
def verify_ospf_rib(
tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None, expected=True
):
@@ -1236,7 +1236,7 @@ def verify_ospf_rib(
return result
-@retry(attempts=10, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def verify_ospf_interface(tgen, topo, dut=None, lan=False, input_dict=None, expected=True):
"""
This API is to verify ospf routes by running
@@ -1326,7 +1326,7 @@ def verify_ospf_interface(tgen, topo, dut=None, lan=False, input_dict=None, expe
return result
-@retry(attempts=11, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def verify_ospf_database(tgen, topo, dut, input_dict, expected=True):
"""
This API is to verify ospf lsa's by running
@@ -1490,7 +1490,7 @@ def verify_ospf_database(tgen, topo, dut, input_dict, expected=True):
return result
-@retry(attempts=10, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True):
"""
This API is to verify ospf routes by running
@@ -1571,7 +1571,7 @@ def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True):
-@retry(attempts=10, wait=3, return_is_str=True)
+@retry(retry_timeout=30)
def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None,
tag=None, metric=None, fib=None):
"""
@@ -1811,7 +1811,7 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None,
return result
-@retry(attempts=3, wait=2, return_is_str=True)
+@retry(retry_timeout=6)
def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None):
"""
This API is to verify ospf routes by running
@@ -1905,7 +1905,7 @@ def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None):
return result
-@retry(attempts=11, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def verify_ospf6_database(tgen, topo, dut, input_dict):
"""
This API is to verify ospf lsa's by running
@@ -2176,9 +2176,9 @@ def config_ospf6_interface (tgen, topo, input_dict=None, build=False,
config_data = []
for lnk in input_dict[router]['links'].keys():
if "ospf6" not in input_dict[router]['links'][lnk]:
- logger.debug("Router %s: ospf6 configs is not present in"
- "input_dict, passed input_dict", router,
- input_dict)
+ logger.debug("Router %s: ospf6 config is not present in"
+ "input_dict, passed input_dict %s", router,
+ str(input_dict))
continue
ospf_data = input_dict[router]['links'][lnk]['ospf6']
data_ospf_area = ospf_data.setdefault("area", None)
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py
index ce90717fa4..7de1c7a2f9 100644
--- a/tests/topotests/lib/pim.py
+++ b/tests/topotests/lib/pim.py
@@ -495,7 +495,7 @@ def configure_pim_force_expire(tgen, topo, input_dict, build=False):
#############################################
# Verification APIs
#############################################
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_pim_neighbors(tgen, topo, dut=None, iface=None, nbr_ip=None, expected=True):
"""
Verify all PIM neighbors are up and running, config is verified
@@ -619,7 +619,7 @@ def verify_pim_neighbors(tgen, topo, dut=None, iface=None, nbr_ip=None, expected
return True
-@retry(attempts=21, wait=2, return_is_str=True)
+@retry(retry_timeout=40)
def verify_igmp_groups(tgen, dut, interface, group_addresses, expected=True):
"""
Verify IGMP groups are received from an intended interface
@@ -693,7 +693,7 @@ def verify_igmp_groups(tgen, dut, interface, group_addresses, expected=True):
return True
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_upstream_iif(
tgen, dut, iif, src_address, group_addresses, joinState=None, refCount=1, expected=True
):
@@ -847,7 +847,7 @@ def verify_upstream_iif(
return True
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, expected=True):
"""
Verify join state is updated correctly and join timer is
@@ -966,7 +966,7 @@ def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, ex
return True
-@retry(attempts=41, wait=2, return_is_dict=True)
+@retry(retry_timeout=80)
def verify_ip_mroutes(
tgen, dut, src_address, group_addresses, iif, oil, return_uptime=False, mwait=0, expected=True
):
@@ -1163,7 +1163,7 @@ def verify_ip_mroutes(
return True if return_uptime == False else uptime_dict
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_pim_rp_info(
tgen, topo, dut, group_addresses, oif=None, rp=None, source=None, iamrp=None, expected=True
):
@@ -1320,7 +1320,7 @@ def verify_pim_rp_info(
return True
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_pim_state(
tgen, dut, iif, oil, group_addresses, src_address=None, installed_fl=None, expected=True
):
@@ -1490,7 +1490,7 @@ def verify_pim_interface_traffic(tgen, input_dict):
return output_dict
-@retry(attempts=21, wait=2, return_is_str=True)
+@retry(retry_timeout=40)
def verify_pim_interface(tgen, topo, dut, interface=None, interface_ip=None, expected=True):
"""
Verify all PIM interface are up and running, config is verified
@@ -1797,7 +1797,7 @@ def clear_ip_igmp_interfaces(tgen, dut):
return True
-@retry(attempts=10, wait=2, return_is_str=True)
+@retry(retry_timeout=20)
def clear_ip_mroute_verify(tgen, dut, expected=True):
"""
Clear ip mroute by running "clear ip mroute" cli and verify
@@ -2173,7 +2173,7 @@ def find_rp_from_bsrp_info(tgen, dut, bsr, grp=None):
return rp_details
-@retry(attempts=6, wait=2, return_is_str=True)
+@retry(retry_timeout=12)
def verify_pim_grp_rp_source(tgen, topo, dut, grp_addr, rp_source, rpadd=None, expected=True):
"""
Verify pim rp info by running "show ip pim rp-info" cli
@@ -2276,7 +2276,7 @@ def verify_pim_grp_rp_source(tgen, topo, dut, grp_addr, rp_source, rpadd=None, e
return errormsg
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_pim_bsr(tgen, topo, dut, bsr_ip, expected=True):
"""
Verify all PIM interface are up and running, config is verified
@@ -2332,7 +2332,7 @@ def verify_pim_bsr(tgen, topo, dut, bsr_ip, expected=True):
return True
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_ip_pim_upstream_rpf(tgen, topo, dut, interface, group_addresses, rp=None, expected=True):
"""
Verify IP PIM upstream rpf, config is verified
@@ -2530,7 +2530,7 @@ def enable_disable_pim_bsm(tgen, router, intf, enable=True):
return result
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_ip_pim_join(tgen, topo, dut, interface, group_addresses, src_address=None, expected=True):
"""
Verify ip pim join by running "show ip pim join" cli
@@ -2621,7 +2621,7 @@ def verify_ip_pim_join(tgen, topo, dut, interface, group_addresses, src_address=
return True
-@retry(attempts=31, wait=2, return_is_dict=True)
+@retry(retry_timeout=60)
def verify_igmp_config(tgen, input_dict, stats_return=False, expected=True):
"""
Verify igmp interface details, verifying following configs:
@@ -2911,7 +2911,7 @@ def verify_igmp_config(tgen, input_dict, stats_return=False, expected=True):
return True if stats_return == False else igmp_stats
-@retry(attempts=31, wait=2, return_is_str=True)
+@retry(retry_timeout=60)
def verify_pim_config(tgen, input_dict, expected=True):
"""
Verify pim interface details, verifying following configs:
@@ -3037,7 +3037,7 @@ def verify_pim_config(tgen, input_dict, expected=True):
return True
-@retry(attempts=21, wait=2, return_is_dict=True)
+@retry(retry_timeout=40)
def verify_multicast_traffic(tgen, input_dict, return_traffic=False, expected=True):
"""
Verify multicast traffic by running
@@ -3280,7 +3280,7 @@ def get_refCount_for_mroute(tgen, dut, iif, src_address, group_addresses):
return refCount
-@retry(attempts=21, wait=2, return_is_str=True)
+@retry(retry_timeout=40)
def verify_multicast_flag_state(tgen, dut, src_address, group_addresses, flag, expected=True):
"""
Verify flag state for mroutes and make sure (*, G)/(S, G) are having
@@ -3375,7 +3375,7 @@ def verify_multicast_flag_state(tgen, dut, src_address, group_addresses, flag, e
return True
-@retry(attempts=21, wait=2, return_is_str=True)
+@retry(retry_timeout=40)
def verify_igmp_interface(tgen, topo, dut, igmp_iface, interface_ip, expected=True):
"""
Verify all IGMP interface are up and running, config is verified
diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
index 199746d5f6..60bd6de35d 100644
--- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
+++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
@@ -456,7 +456,7 @@ def test_starg_mroute_p0(request):
# Verify mroute not installed
step("Verify mroute not installed in l1")
result = verify_ip_mroutes(
- tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, wait=20, expected=False
+ tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, retry_timeout=20, expected=False
)
assert (
result is not True
@@ -705,6 +705,7 @@ def test_RP_priority_p0(request):
), "Testcase {} :Failed \n Error : rp expected {} rp received {}".format(
tc_name,
rp_add1,
+ rp2[group] if group in rp2 else None
)
# Verify if that rp is installed
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
index 7bef57b629..d73e8dc9e8 100755
--- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
@@ -424,7 +424,7 @@ def test_add_delete_static_RP_p0(request):
step("r1: Verify show ip igmp group without any IGMP join")
dut = "r1"
interface = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS)
+ result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: igmp group present without any IGMP join \n Error: {}".format(
@@ -495,7 +495,7 @@ def test_add_delete_static_RP_p0(request):
step("r1: Verify RP info")
result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
assert (
result is not True
@@ -504,14 +504,14 @@ def test_add_delete_static_RP_p0(request):
)
step("r1: Verify upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream IIF interface present \n Error: {}".format(tc_name, result)
)
step("r1: Verify upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream join state is up and join timer is running \n Error: {}".format(
@@ -519,14 +519,15 @@ def test_add_delete_static_RP_p0(request):
)
)
+ # 20
step("r1: Verify PIM state")
- result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS)
+ result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert result is not True, "Testcase {} :Failed \n Error: {}".format(
tc_name, result
)
step("r1: Verify ip mroutes")
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: mroutes are still present \n Error: {}".format(
@@ -686,7 +687,9 @@ def test_SPT_RPT_path_same_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format(
@@ -819,7 +822,7 @@ def test_not_reachable_static_RP_p0(request):
"r1 : OIL should be same and IIF should be cleared on R1 verify"
"using show ip pim state"
)
- result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS)
+ result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"OIL is not same and IIF is not cleared on R1 \n Error: {}".format(
@@ -828,7 +831,7 @@ def test_not_reachable_static_RP_p0(request):
)
step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream IIF is not unknown \n Error: {}".format(tc_name, result)
@@ -838,7 +841,7 @@ def test_not_reachable_static_RP_p0(request):
"r1: join state should not be joined and join timer should stop,"
"verify using show ip pim upstream"
)
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: join state is joined and timer is not stopped \n Error: {}".format(
@@ -861,7 +864,7 @@ def test_not_reachable_static_RP_p0(request):
assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result)
step("r1: (*, G) cleared from mroute table using show ip mroute")
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: (*, G) are not cleared from mroute table \n Error: {}".format(
@@ -932,7 +935,7 @@ def test_add_RP_after_join_received_p1(request):
rp_address = "1.0.2.17"
iif = "r1-r2-eth1"
result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
assert (
result is not True
@@ -959,7 +962,7 @@ def test_add_RP_after_join_received_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r1: Verify upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream IFF interface is present \n Error: {}".format(tc_name, result)
@@ -967,7 +970,7 @@ def test_add_RP_after_join_received_p1(request):
step("r1: Verify upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream join state is joined and timer is running \n Error: {}".format(
@@ -976,7 +979,7 @@ def test_add_RP_after_join_received_p1(request):
)
step("r1: Verify PIM state")
- result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS)
+ result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
@@ -984,7 +987,7 @@ def test_add_RP_after_join_received_p1(request):
)
step("r1: Verify ip mroutes")
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
@@ -1114,14 +1117,14 @@ def test_reachable_static_RP_after_join_p0(request):
step("r1 : Verify upstream IIF interface")
iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream IIF interface is present\n Error: {}".format(tc_name, result)
)
step("r1 : Verify upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: upstream join state is joined and timer is running\n Error: {}".format(
@@ -1130,7 +1133,7 @@ def test_reachable_static_RP_after_join_p0(request):
)
step("r1 : Verify PIM state")
- result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS)
+ result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
@@ -1138,7 +1141,7 @@ def test_reachable_static_RP_after_join_p0(request):
)
step("r1 : Verify ip mroutes")
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
@@ -1385,7 +1388,9 @@ def test_send_join_on_higher_preffered_rp_p1(request):
step("r1 : Verify rp-info for group 225.1.1.1")
iif = "r1-r4-eth3"
- result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_RANGE, oif, rp_address_2, SOURCE)
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE, oif, rp_address_2, SOURCE, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r1: rp-info is present for group 225.1.1.1 \n Error: {}".format(
@@ -1643,7 +1648,9 @@ def test_RP_configured_as_LHR_1_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S, G) upstream join state is joined and join"
@@ -1850,7 +1857,9 @@ def test_RP_configured_as_LHR_2_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2058,7 +2067,9 @@ def test_RP_configured_as_FHR_1_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2267,7 +2278,9 @@ def test_RP_configured_as_FHR_2_p2(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2394,7 +2407,9 @@ def test_SPT_RPT_path_different_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2416,7 +2431,9 @@ def test_SPT_RPT_path_different_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
assert result is not True, (
"Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2645,7 +2662,8 @@ def test_restart_pimd_process_p2(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
@@ -2663,6 +2681,7 @@ def test_restart_pimd_process_p2(request):
oil = "r1-r0-eth0"
logger.info("waiting for 10 sec to make sure old mroute time is higher")
sleep(10)
+ # Why do we then wait 60 seconds below before checking the routes?
uptime_before = verify_ip_mroutes(
tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=60
)
@@ -2679,6 +2698,7 @@ def test_restart_pimd_process_p2(request):
logger.info("Waiting for 5sec to get PIMd restarted and mroute" " re-learned..")
sleep(5)
+ # Why do we then wait 10 seconds below before checking the routes?
uptime_after = verify_ip_mroutes(
tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=10
)
@@ -2814,7 +2834,7 @@ def test_multiple_groups_same_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -2838,7 +2858,7 @@ def test_multiple_groups_same_RP_address_p2(request):
step("r2: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -2959,7 +2979,7 @@ def test_multiple_groups_same_RP_address_p2(request):
step("r2: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -2981,7 +3001,7 @@ def test_multiple_groups_same_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3163,7 +3183,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r2: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3187,7 +3207,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3259,7 +3279,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r4: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3283,7 +3303,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
assert result is not True, "Testcase {} :Failed \n Error: {}".format(
tc_name, result
@@ -3436,7 +3456,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r2: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3460,7 +3480,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3532,7 +3552,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r4: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3556,7 +3576,7 @@ def test_multiple_groups_different_RP_address_p2(request):
step("r3: Verify (S, G) upstream join state and join timer")
result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -3682,14 +3702,14 @@ def test_shutdown_primary_path_p1(request):
step(
"Verify after shut of R1 to R3 link , verify (*,G) entries got"
- "cleared from all the node R1, R2, R3"
+ " cleared from all the node R1, R2, R3"
)
step("r1: Verify (*, G) ip mroutes")
dut = "r1"
iif = "r1-r3-eth2"
oif = "r1-r0-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
@@ -3701,7 +3721,7 @@ def test_shutdown_primary_path_p1(request):
dut = "r2"
iif = "lo"
oif = "r2-r3-eth1"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
@@ -3713,7 +3733,7 @@ def test_shutdown_primary_path_p1(request):
dut = "r3"
iif = "r3-r2-eth1"
oif = "r3-r1-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
@@ -3878,7 +3898,7 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
dut = "r1"
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
@@ -3890,7 +3910,7 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
@@ -4005,7 +4025,7 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
dut = "r1"
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
@@ -4017,7 +4037,7 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
- result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py
index 9c3be58937..a7f2893eab 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py
@@ -257,7 +257,7 @@ def test_ospf_authentication_simple_pass_tc28_p1(request):
sleep(6)
dut = "r2"
ospf_covergence = verify_ospf_neighbor(
- tgen, topo, dut=dut, expected=False, attempts=5
+ tgen, topo, dut=dut, expected=False, retry_timeout=10
)
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
ospf_covergence
@@ -395,7 +395,7 @@ def test_ospf_authentication_md5_tc29_p1(request):
sleep(6)
dut = "r1"
ospf_covergence = verify_ospf_neighbor(
- tgen, topo, dut=dut, expected=False, attempts=3
+ tgen, topo, dut=dut, expected=False, retry_timeout=6
)
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
ospf_covergence
@@ -460,7 +460,7 @@ def test_ospf_authentication_md5_tc29_p1(request):
sleep(6)
dut = "r2"
ospf_covergence = verify_ospf_neighbor(
- tgen, topo, dut=dut, expected=False, attempts=5
+ tgen, topo, dut=dut, expected=False, retry_timeout=10
)
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
ospf_covergence
@@ -610,7 +610,7 @@ def test_ospf_authentication_different_auths_tc30_p1(request):
step("Verify that the neighbour is not FULL between R1 and R2.")
dut = "r1"
ospf_covergence = verify_ospf_neighbor(
- tgen, topo, dut=dut, expected=False, attempts=5
+ tgen, topo, dut=dut, expected=False, retry_timeout=10
)
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
ospf_covergence
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
index 1aabc06db0..49ecaac9f7 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
@@ -326,7 +326,7 @@ def test_ospf_ecmp_tc16_p0(request):
step("Verify that route is withdrawn from R2.")
dut = "r1"
result = verify_ospf_rib(
- tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
+ tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False
)
assert (
result is not True
@@ -342,7 +342,7 @@ def test_ospf_ecmp_tc16_p0(request):
input_dict,
protocol=protocol,
next_hop=nh,
- attempts=5,
+ retry_timeout=10,
expected=False,
)
assert (
@@ -434,7 +434,7 @@ def test_ospf_ecmp_tc17_p0(request):
step("Verify that route is withdrawn from R2.")
dut = "r1"
result = verify_ospf_rib(
- tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
+ tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False
)
assert (
result is not True
@@ -450,7 +450,7 @@ def test_ospf_ecmp_tc17_p0(request):
input_dict,
protocol=protocol,
next_hop=nh,
- attempts=5,
+ retry_timeout=10,
expected=False,
)
assert (
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
index e6dc18a434..47c6c45e39 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
@@ -305,7 +305,7 @@ def test_ospf_lan_ecmp_tc18_p0(request):
step("Verify that all the routes are withdrawn from R0")
dut = "r1"
result = verify_ospf_rib(
- tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
+ tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False
)
assert (
result is not True
@@ -321,7 +321,7 @@ def test_ospf_lan_ecmp_tc18_p0(request):
input_dict,
protocol=protocol,
next_hop=nh,
- attempts=5,
+ retry_timeout=10,
expected=False,
)
assert (
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
index 7864d0307a..0848f6c94a 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
@@ -501,7 +501,7 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
- result = verify_ospf_rib(tgen, dut, input_dict, attempts=2, expected=False)
+ result = verify_ospf_rib(tgen, dut, input_dict, retry_timeout=4, expected=False)
assert (
result is not True
), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
@@ -509,7 +509,7 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
)
result = verify_rib(
- tgen, "ipv4", dut, input_dict, protocol=protocol, attempts=2, expected=False
+ tgen, "ipv4", dut, input_dict, protocol=protocol, retry_timeout=4, expected=False
)
assert (
result is not True
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index 9dfde325f6..f17346d5b1 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -263,7 +263,7 @@ def test_ospf_redistribution_tc5_p0(request):
input_dict,
protocol=protocol,
next_hop=nh,
- attempts=5,
+ retry_timeout=10,
expected=False,
)
assert result is not True, (
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
index bbb4370a93..2c44ec2351 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
@@ -690,9 +690,8 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request):
next_hop=nh,
protocol=protocol,
fib=True,
+ retry_timeout=6,
expected=False,
- wait=2,
- attempts=3,
)
assert (
result is not True
@@ -804,8 +803,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request):
protocol=protocol,
fib=True,
expected=False,
- wait=2,
- attempts=3,
+ retry_timeout=6,
)
assert (
result is not True
@@ -1283,8 +1281,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request):
protocol=protocol,
fib=True,
expected=False,
- wait=2,
- attempts=3,
+ retry_timeout=6,
)
assert (
result is not True
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
index ee0e01b411..85b9e8b543 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
@@ -695,12 +695,11 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
protocol=protocol,
fib=True,
expected=False,
- wait=2,
- attempts=3,
+ retry_timeout=6,
)
assert (
result is not True
- ), "Testcase {} : Failed \nError: Routes " " are missing in RIB".format(tc_name)
+ ), "Testcase {} : Failed \nError: Routes " " are present in RIB".format(tc_name)
step(
"Remove the static route configured with nexthop N1 to N8, one"
@@ -808,8 +807,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
protocol=protocol,
fib=True,
expected=False,
- wait=2,
- attempts=3,
+ retry_timeout=6,
)
assert (
result is not True
@@ -1512,8 +1510,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ibgp(request):
protocol=protocol,
fib=True,
expected=False,
- wait=2,
- attempts=3,
+ retry_timeout=6,
)
assert (
result is not True
diff --git a/zebra/connected.c b/zebra/connected.c
index d110ccf6dd..dc7193eb4c 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -198,7 +198,7 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
void connected_up(struct interface *ifp, struct connected *ifc)
{
afi_t afi;
- struct prefix p = {0};
+ struct prefix p;
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
@@ -225,7 +225,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Ensure 'down' flag is cleared */
UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
- PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
+ prefix_copy(&p, CONNECTED_PREFIX(ifc));
/* Apply mask to the network. */
apply_mask(&p);
@@ -277,9 +277,9 @@ void connected_up(struct interface *ifp, struct connected *ifc)
* resolve to the same network and mask
*/
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
- struct prefix cp = {0};
+ struct prefix cp;
- PREFIX_COPY(&cp, CONNECTED_PREFIX(c));
+ prefix_copy(&cp, CONNECTED_PREFIX(c));
apply_mask(&cp);
if (prefix_same(&cp, &p) &&
@@ -412,7 +412,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
return;
}
- PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
+ prefix_copy(&p, CONNECTED_PREFIX(ifc));
/* Apply mask to the network. */
apply_mask(&p);
@@ -450,7 +450,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
struct prefix cp;
- PREFIX_COPY(&cp, CONNECTED_PREFIX(c));
+ prefix_copy(&cp, CONNECTED_PREFIX(c));
apply_mask(&cp);
if (prefix_same(&p, &cp) &&
diff --git a/zebra/main.c b/zebra/main.c
index e36af51005..bded50149f 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -186,7 +186,6 @@ static void sigint(void)
work_queue_free_and_null(&zrouter.lsp_process_q);
vrf_terminate();
- rtadv_terminate();
ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
zebra_ns_notify_close();
diff --git a/zebra/rib.h b/zebra/rib.h
index 957f38602a..b7ffb9ce8d 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -288,16 +288,30 @@ DECLARE_LIST(re_list, struct route_entry, next);
#define RNODE_NEXT_RE(rn, re) RE_DEST_NEXT_ROUTE(rib_dest_from_rnode(rn), re)
#if defined(HAVE_RTADV)
+PREDECL_SORTLIST_UNIQ(adv_if_list);
/* Structure which hold status of router advertisement. */
struct rtadv {
int sock;
- int adv_if_count;
- int adv_msec_if_count;
+ struct adv_if_list_head adv_if;
+ struct adv_if_list_head adv_msec_if;
struct thread *ra_read;
struct thread *ra_timer;
};
+
+/* adv list node */
+struct adv_if {
+ char name[INTERFACE_NAMSIZ];
+ struct adv_if_list_item list_item;
+};
+
+static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
+{
+ return if_cmp_name_func(a->name, b->name);
+}
+
+DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
#endif /* HAVE_RTADV */
/*
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 1e06b3e0e9..8cb0223a46 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -54,6 +54,7 @@ extern struct zebra_privs_t zserv_privs;
#endif
DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
+DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
#ifdef OPEN_BSD
#include <netinet/icmp6.h>
@@ -92,11 +93,13 @@ static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
static int if_join_all_router(int, struct interface *);
static int if_leave_all_router(int, struct interface *);
-static int rtadv_get_socket(struct zebra_vrf *zvrf)
+static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
{
- if (zvrf->rtadv.sock > 0)
- return zvrf->rtadv.sock;
- return zrouter.rtadv_sock;
+ /* We use the default vrf for rtadv handling except in netns */
+ if (!vrf_is_backend_netns())
+ return vrf_info_lookup(VRF_DEFAULT);
+
+ return vrf_info_lookup(ifp->vrf_id);
}
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
@@ -480,7 +483,7 @@ static int rtadv_timer(struct thread *thread)
int period;
zvrf->rtadv.ra_timer = NULL;
- if (zvrf->rtadv.adv_msec_if_count == 0) {
+ if (adv_if_list_count(&zvrf->rtadv.adv_msec_if) == 0) {
period = 1000; /* 1 s */
rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
} else {
@@ -520,8 +523,8 @@ static int rtadv_timer(struct thread *thread)
ifp->ifindex);
}
- rtadv_send_packet(rtadv_get_socket(zvrf),
- ifp, RA_ENABLE);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp,
+ RA_ENABLE);
} else {
zif->rtadv.AdvIntervalTimer -= period;
if (zif->rtadv.AdvIntervalTimer <= 0) {
@@ -534,8 +537,8 @@ static int rtadv_timer(struct thread *thread)
zif->rtadv
.MaxRtrAdvInterval;
rtadv_send_packet(
- rtadv_get_socket(zvrf),
- ifp, RA_ENABLE);
+ zvrf->rtadv.sock, ifp,
+ RA_ENABLE);
}
}
}
@@ -546,9 +549,10 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp)
{
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf;
struct zebra_if *zif;
+ zvrf = rtadv_interface_get_zvrf(ifp);
assert(zvrf);
zif = ifp->info;
@@ -565,7 +569,7 @@ static void rtadv_process_solicit(struct interface *ifp)
if ((zif->rtadv.UseFastRexmit)
|| (zif->rtadv.AdvIntervalTimer <=
(zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_ENABLE);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_ENABLE);
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
} else
zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
@@ -788,7 +792,7 @@ static int rtadv_read(struct thread *thread)
zvrf->rtadv.ra_read = NULL;
/* Register myself. */
- rtadv_event(zvrf, RTADV_READ, sock);
+ rtadv_event(zvrf, RTADV_READ, 0);
len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
&hoplimit);
@@ -862,6 +866,201 @@ static int rtadv_make_socket(ns_id_t ns_id)
return sock;
}
+static struct adv_if *adv_if_new(const char *name)
+{
+ struct adv_if *new;
+
+ new = XCALLOC(MTYPE_ADV_IF, sizeof(struct adv_if));
+
+ strlcpy(new->name, name, sizeof(new->name));
+
+ return new;
+}
+
+static void adv_if_free(struct adv_if *adv_if)
+{
+ XFREE(MTYPE_ADV_IF, adv_if);
+}
+
+static bool adv_if_is_empty_internal(const struct adv_if_list_head *adv_if_head)
+{
+ return adv_if_list_count(adv_if_head) ? false : true;
+}
+
+static struct adv_if *adv_if_add_internal(struct adv_if_list_head *adv_if_head,
+ const char *name)
+{
+ struct adv_if adv_if_lookup = {};
+ struct adv_if *adv_if = NULL;
+
+ strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
+ adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ adv_if = adv_if_new(adv_if_lookup.name);
+ adv_if_list_add(adv_if_head, adv_if);
+
+ return NULL;
+}
+
+static struct adv_if *adv_if_del_internal(struct adv_if_list_head *adv_if_head,
+ const char *name)
+{
+ struct adv_if adv_if_lookup = {};
+ struct adv_if *adv_if = NULL;
+
+ strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
+ adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ adv_if_list_del(adv_if_head, adv_if);
+
+ return adv_if;
+}
+
+static void adv_if_clean_internal(struct adv_if_list_head *adv_if_head)
+{
+ struct adv_if *node = NULL;
+
+ if (!adv_if_is_empty_internal(adv_if_head)) {
+ frr_each_safe (adv_if_list, adv_if_head, node) {
+ adv_if_list_del(adv_if_head, node);
+ adv_if_free(node);
+ }
+ }
+
+ adv_if_list_fini(adv_if_head);
+}
+
+
+/*
+ * Add to list. On Success, return NULL, otherwise return already existing
+ * adv_if.
+ */
+static struct adv_if *adv_if_add(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_add_internal(&zvrf->rtadv.adv_if, name);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ return NULL;
+}
+
+/*
+ * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
+ * frees.
+ */
+static struct adv_if *adv_if_del(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_del_internal(&zvrf->rtadv.adv_if, name);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ return adv_if;
+}
+
+/*
+ * Add to list. On Success, return NULL, otherwise return already existing
+ * adv_if.
+ */
+static struct adv_if *adv_msec_if_add(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_add_internal(&zvrf->rtadv.adv_msec_if, name);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ return NULL;
+}
+
+/*
+ * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
+ * frees.
+ */
+static struct adv_if *adv_msec_if_del(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_del_internal(&zvrf->rtadv.adv_msec_if, name);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ return adv_if;
+}
+
+/* Clean adv_if list, called on vrf terminate */
+static void adv_if_clean(struct zebra_vrf *zvrf)
+{
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf),
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ adv_if_clean_internal(&zvrf->rtadv.adv_if);
+}
+
+/* Clean adv_msec_if list, called on vrf terminate */
+static void adv_msec_if_clean(struct zebra_vrf *zvrf)
+{
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf),
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ adv_if_clean_internal(&zvrf->rtadv.adv_msec_if);
+}
+
static struct rtadv_prefix *rtadv_prefix_new(void)
{
return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
@@ -1006,30 +1205,34 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if = NULL;
zif = ifp->info;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+
+ zvrf = rtadv_interface_get_zvrf(ifp);
if (status == RA_SUPPRESS) {
/* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) {
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
- RA_SUPPRESS);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
- zvrf->rtadv.adv_if_count--;
- if_leave_all_router(rtadv_get_socket(zvrf), ifp);
+ adv_if = adv_if_del(zvrf, ifp->name);
+ if (adv_if == NULL)
+ return; /* Nothing to delete */
+
+ adv_if_free(adv_if);
+
+ if_leave_all_router(zvrf->rtadv.sock, ifp);
- if (zvrf->rtadv.adv_if_count == 0)
+ if (adv_if_list_count(&zvrf->rtadv.adv_if) == 0)
rtadv_event(zvrf, RTADV_STOP, 0);
}
} else {
if (!zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0;
- zvrf->rtadv.adv_if_count++;
-
if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
&& zif->rtadv.UseFastRexmit) {
/*
@@ -1041,11 +1244,14 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
RTADV_NUM_FAST_REXMITS;
}
- if_join_all_router(rtadv_get_socket(zvrf), ifp);
+ adv_if = adv_if_add(zvrf, ifp->name);
+ if (adv_if != NULL)
+ return; /* Alread added */
+
+ if_join_all_router(zvrf->rtadv.sock, ifp);
- if (zvrf->rtadv.adv_if_count == 1)
- rtadv_event(zvrf, RTADV_START,
- rtadv_get_socket(zvrf));
+ if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
+ rtadv_event(zvrf, RTADV_START, 0);
}
}
}
@@ -1092,7 +1298,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto));
return;
}
- if (ifp->vrf_id != zvrf_id(zvrf)) {
+ if (vrf_is_backend_netns() && ifp->vrf_id != zvrf_id(zvrf)) {
struct vrf *vrf = zvrf->vrf;
zlog_debug(
@@ -1136,10 +1342,10 @@ void rtadv_stop_ra(struct interface *ifp)
struct zebra_vrf *zvrf;
zif = ifp->info;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
if (zif->rtadv.AdvSendAdvertisements)
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_SUPPRESS);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
}
/*
@@ -1179,6 +1385,76 @@ void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
}
+static void show_zvrf_rtadv_adv_if_helper(struct vty *vty,
+ struct adv_if_list_head *adv_if_head)
+{
+ struct adv_if *node = NULL;
+
+ if (!adv_if_is_empty_internal(adv_if_head)) {
+ frr_each (adv_if_list, adv_if_head, node) {
+ vty_out(vty, " %s\n", node->name);
+ }
+ }
+
+ vty_out(vty, "\n");
+}
+
+static void show_zvrf_rtadv_helper(struct vty *vty, struct zebra_vrf *zvrf)
+{
+ vty_out(vty, "VRF: %s\n", zvrf_name(zvrf));
+ vty_out(vty, " Interfaces:\n");
+ show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_if);
+
+ vty_out(vty, " Interfaces(msec):\n");
+ show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_msec_if);
+}
+
+DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
+ "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
+ SHOW_STR IP6_STR
+ "Neighbor discovery\n"
+ "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR)
+{
+ struct zebra_vrf *zvrf = NULL;
+
+ if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
+ vty_out(vty,
+ "%% VRF subcommand only applicable for netns-based vrfs.\n");
+ return CMD_WARNING;
+ }
+
+ if (vrf_all) {
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf->info;
+ if (!zvrf)
+ continue;
+
+ show_zvrf_rtadv_helper(vty, zvrf);
+ }
+
+ return CMD_SUCCESS;
+ }
+
+ if (vrf_name)
+ zvrf = zebra_vrf_lookup_by_name(vrf_name);
+ else
+ zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
+
+ if (!zvrf) {
+ vty_out(vty, "%% VRF '%s' specified does not exist\n",
+ vrf_name);
+ return CMD_WARNING;
+ }
+
+ show_zvrf_rtadv_helper(vty, zvrf);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ipv6_nd_ra_fast_retrans,
ipv6_nd_ra_fast_retrans_cmd,
"ipv6 nd ra-fast-retrans",
@@ -1379,8 +1655,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1390,11 +1667,14 @@ DEFUN (ipv6_nd_ra_interval_msec,
return CMD_WARNING_CONFIG_FAILED;
}
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
if (interval % 1000)
- zvrf->rtadv.adv_msec_if_count++;
+ (void)adv_msec_if_add(zvrf, ifp->name);
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
@@ -1417,8 +1697,9 @@ DEFUN (ipv6_nd_ra_interval,
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1428,8 +1709,11 @@ DEFUN (ipv6_nd_ra_interval,
return CMD_WARNING_CONFIG_FAILED;
}
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
/* convert to milliseconds */
interval = interval * 1000;
@@ -1456,11 +1740,15 @@ DEFUN (no_ipv6_nd_ra_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = NULL;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
@@ -2451,7 +2739,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
- struct rtadv *rtadv = &zvrf->rtadv;
+ struct rtadv *rtadv;
if (IS_ZEBRA_DEBUG_EVENT) {
struct vrf *vrf = zvrf->vrf;
@@ -2460,9 +2748,11 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
VRF_LOGNAME(vrf), event, val);
}
+ rtadv = &zvrf->rtadv;
+
switch (event) {
case RTADV_START:
- thread_add_read(zrouter.master, rtadv_read, zvrf, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
&rtadv->ra_read);
thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
&rtadv->ra_timer);
@@ -2480,7 +2770,7 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
&rtadv->ra_timer);
break;
case RTADV_READ:
- thread_add_read(zrouter.master, rtadv_read, zvrf, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
&rtadv->ra_read);
break;
default:
@@ -2489,37 +2779,27 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
return;
}
-void rtadv_init(struct zebra_vrf *zvrf)
+void rtadv_vrf_init(struct zebra_vrf *zvrf)
{
- if (vrf_is_backend_netns()) {
- zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
- zrouter.rtadv_sock = -1;
- } else {
- zvrf->rtadv.sock = -1;
- if (zrouter.rtadv_sock < 0)
- zrouter.rtadv_sock =
- rtadv_make_socket(zvrf->zns->ns_id);
- }
+ if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
+ return;
+
+ zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
}
void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
{
+ if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
+ return;
+
rtadv_event(zvrf, RTADV_STOP, 0);
if (zvrf->rtadv.sock >= 0) {
close(zvrf->rtadv.sock);
zvrf->rtadv.sock = -1;
}
- zvrf->rtadv.adv_if_count = 0;
- zvrf->rtadv.adv_msec_if_count = 0;
-}
-
-void rtadv_terminate(void)
-{
- if (zrouter.rtadv_sock >= 0) {
- close(zrouter.rtadv_sock);
- zrouter.rtadv_sock = -1;
- }
+ adv_if_clean(zvrf);
+ adv_msec_if_clean(zvrf);
}
void rtadv_cmd_init(void)
@@ -2527,6 +2807,8 @@ void rtadv_cmd_init(void)
hook_register(zebra_if_extra_info, nd_dump_vty);
hook_register(zebra_if_config_wr, rtadv_config_write);
+ install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
+
install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
@@ -2629,14 +2911,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
}
#else
-void rtadv_init(struct zebra_vrf *zvrf)
-{
- /* Empty.*/;
-}
-void rtadv_terminate(void)
+void rtadv_vrf_init(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
+
void rtadv_cmd_init(void)
{
/* Empty.*/;
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index d7a1ccfb29..7b71ee45a2 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -152,9 +152,8 @@ enum ipv6_nd_suppress_ra_status {
RA_SUPPRESS,
};
-extern void rtadv_init(struct zebra_vrf *zvrf);
+extern void rtadv_vrf_init(struct zebra_vrf *zvrf);
extern void rtadv_vrf_terminate(struct zebra_vrf *zvrf);
-extern void rtadv_terminate(void);
extern void rtadv_stop_ra(struct interface *ifp);
extern void rtadv_stop_ra_all(void);
extern void rtadv_cmd_init(void);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 5a00f3155d..d930f59866 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -268,8 +268,6 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
- zrouter.rtadv_sock = -1;
-
zebra_vxlan_init();
zebra_mlag_init();
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 08c5fcaf8d..408f9cbee5 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -162,9 +162,6 @@ struct zebra_router {
struct hash *iptable_hash;
- /* used if vrf backend is not network namespace */
- int rtadv_sock;
-
/* A sequence number used for tracking routes */
_Atomic uint32_t sequence_num;
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index a0c63e4202..2430b51989 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -131,7 +131,7 @@ static int zebra_vrf_enable(struct vrf *vrf)
else
zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
#if defined(HAVE_RTADV)
- rtadv_init(zvrf);
+ rtadv_vrf_init(zvrf);
#endif
/* Inform clients that the VRF is now active. This is an