summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md4
-rw-r--r--bfdd/bfd.c2
-rw-r--r--bfdd/bfd.h2
-rw-r--r--bgpd/bgp_aspath.c18
-rw-r--r--bgpd/bgp_attr.c103
-rw-r--r--bgpd/bgp_attr.h41
-rw-r--r--bgpd/bgp_clist.c4
-rw-r--r--bgpd/bgp_community.c13
-rw-r--r--bgpd/bgp_community.h3
-rw-r--r--bgpd/bgp_community_alias.c2
-rw-r--r--bgpd/bgp_conditional_adv.c2
-rw-r--r--bgpd/bgp_debug.c6
-rw-r--r--bgpd/bgp_ecommunity.c2
-rw-r--r--bgpd/bgp_evpn.c15
-rw-r--r--bgpd/bgp_evpn_mh.c34
-rw-r--r--bgpd/bgp_evpn_mh.h11
-rw-r--r--bgpd/bgp_evpn_vty.c40
-rw-r--r--bgpd/bgp_lcommunity.c15
-rw-r--r--bgpd/bgp_lcommunity.h3
-rw-r--r--bgpd/bgp_mpath.c12
-rw-r--r--bgpd/bgp_mplsvpn.c51
-rw-r--r--bgpd/bgp_mplsvpn.h4
-rw-r--r--bgpd/bgp_nht.c6
-rw-r--r--bgpd/bgp_packet.c2
-rw-r--r--bgpd/bgp_route.c35
-rw-r--r--bgpd/bgp_routemap.c35
-rw-r--r--bgpd/bgp_updgrp.c2
-rw-r--r--bgpd/bgp_updgrp.h9
-rw-r--r--bgpd/bgp_updgrp_adv.c2
-rw-r--r--bgpd/bgp_updgrp_packet.c6
-rw-r--r--bgpd/bgp_vty.c60
-rw-r--r--bgpd/bgpd.c36
-rw-r--r--bgpd/bgpd.h18
-rw-r--r--bgpd/rfapi/rfapi.c4
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c3
-rw-r--r--configure.ac16
-rw-r--r--debian/changelog6
-rw-r--r--debian/frr.logrotate4
-rw-r--r--debian/frr.postinst2
-rw-r--r--debian/frr.preinst1
-rw-r--r--doc/developer/building-frr-for-fedora.rst2
-rw-r--r--doc/developer/building-frr-for-opensuse.rst2
-rw-r--r--doc/developer/lists.rst6
-rw-r--r--doc/developer/static-linking.rst2
-rw-r--r--doc/developer/workflow.rst22
-rw-r--r--doc/user/basic.rst2
-rw-r--r--doc/user/bfd.rst2
-rw-r--r--doc/user/pimv6.rst8
-rw-r--r--doc/user/scripting.rst2
-rw-r--r--doc/user/zebra.rst19
-rw-r--r--isisd/isis_adjacency.c10
-rw-r--r--isisd/isis_circuit.c7
-rw-r--r--isisd/isis_dr.c3
-rw-r--r--isisd/isis_ldp_sync.c6
-rw-r--r--isisd/isis_nb_config.c48
-rw-r--r--isisd/isis_pdu.c2
-rw-r--r--isisd/isis_pdu.h2
-rw-r--r--isisd/isis_route.c2
-rw-r--r--isisd/isis_tlvs.c3
-rw-r--r--ldpd/ldpd.c2
-rw-r--r--lib/atomlist.c2
-rw-r--r--lib/base64.c4
-rw-r--r--lib/command_py.c3
-rw-r--r--lib/elf_py.c2
-rw-r--r--lib/plist.c4
-rw-r--r--lib/privs.c2
-rw-r--r--lib/route_types.txt2
-rw-r--r--lib/routemap_cli.c37
-rw-r--r--lib/subdir.am2
-rw-r--r--nhrpd/linux.c3
-rw-r--r--ospf6d/ospf6_flood.c43
-rw-r--r--ospf6d/ospf6_interface.c2
-rw-r--r--ospf6d/ospf6_lsdb.h2
-rw-r--r--ospfd/ospf_interface.c2
-rw-r--r--ospfd/ospf_ldp_sync.c6
-rw-r--r--ospfd/ospf_lsa.c4
-rw-r--r--ospfd/ospf_packet.c8
-rw-r--r--ospfd/ospf_spf.c2
-rw-r--r--pathd/path_ted.c4
-rw-r--r--pimd/pim6_cmd.c35
-rw-r--r--pimd/pim6_cmd.h1
-rw-r--r--pimd/pim_assert.c19
-rw-r--r--pimd/pim_bsm.c6
-rw-r--r--pimd/pim_cmd.c56
-rw-r--r--pimd/pim_cmd_common.c26
-rw-r--r--pimd/pim_cmd_common.h2
-rw-r--r--pimd/pim_iface.c3
-rw-r--r--pimd/pim_iface.h1
-rw-r--r--pimd/pim_ifchannel.c7
-rw-r--r--pimd/pim_igmp.c10
-rw-r--r--pimd/pim_igmpv3.c10
-rw-r--r--pimd/pim_mlag.c2
-rw-r--r--pimd/pim_mroute.c4
-rw-r--r--pimd/pim_oil.h10
-rw-r--r--pimd/pim_ssmpingd.c6
-rw-r--r--pimd/pim_tib.c8
-rw-r--r--pimd/pim_upstream.c12
-rw-r--r--pimd/pim_vty.c4
-rw-r--r--pimd/pim_zebra.c2
-rw-r--r--redhat/frr.logrotate8
-rw-r--r--redhat/frr.spec.in11
-rw-r--r--ripd/rip_offset.c4
-rw-r--r--ripd/ripd.h2
-rw-r--r--ripngd/ripng_offset.c4
-rw-r--r--tests/isisd/test_topologies.c2
-rw-r--r--tests/lib/test_table.c4
-rw-r--r--tests/topotests/bgp_auth/test_bgp_auth.py2
-rw-r--r--tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py2
-rwxr-xr-xtests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py2
-rwxr-xr-xtests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py2
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py2
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py10
-rw-r--r--tests/topotests/bgp_lu_topo1/test_bgp_lu.py2
-rw-r--r--tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py10
-rwxr-xr-xtests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py2
-rw-r--r--tests/topotests/grpc_basic/test_basic_grpc.py2
-rw-r--r--tests/topotests/lib/common_config.py9
-rw-r--r--tests/topotests/lib/ltemplate.py2
-rw-r--r--tests/topotests/lib/topogen.py2
-rw-r--r--tests/topotests/lib/topotest.py10
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py4
-rw-r--r--tests/topotests/multicast_pim_dr_nondr_test/__init__.py0
-rw-r--r--tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_ospf_topo2.json195
-rw-r--r--tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_static_routes_topo1.json85
-rw-r--r--tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_transit_router_topo3.json241
-rwxr-xr-xtests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_ospf_topo2.py1135
-rwxr-xr-xtests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_static_routes_topo1.py934
-rwxr-xr-xtests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_transit_router_topo3.py829
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py12
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py10
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py2
-rwxr-xr-xtests/topotests/simple_snmp_test/test_simple_snmp.py2
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py2
-rw-r--r--tests/topotests/zebra_multiple_connected/r1/ip_route.json62
-rw-r--r--tests/topotests/zebra_multiple_connected/r1/ip_route2.json102
-rw-r--r--tests/topotests/zebra_multiple_connected/r1/zebra.conf9
-rw-r--r--tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py162
-rw-r--r--tools/etc/rsyslog.d/45-frr.conf2
-rwxr-xr-xtools/frr-reload.py2
-rw-r--r--tools/frrinit.sh.in4
-rw-r--r--vtysh/vtysh.c22
-rw-r--r--watchfrr/watchfrr.c69
-rw-r--r--zebra/connected.c4
-rw-r--r--zebra/if_netlink.c8
-rw-r--r--zebra/interface.c2
-rw-r--r--zebra/rt_netlink.c8
-rw-r--r--zebra/rule_netlink.c3
-rw-r--r--zebra/subdir.am4
-rw-r--r--zebra/zebra_dplane.c2
-rw-r--r--zebra/zebra_evpn_mh.c41
-rw-r--r--zebra/zebra_evpn_mh.h11
-rw-r--r--zebra/zebra_fpm_netlink.c2
-rw-r--r--zebra/zebra_nhg.c102
-rw-r--r--zebra/zebra_script.c2
-rw-r--r--zebra/zebra_trace.c6
-rw-r--r--zebra/zebra_trace.h130
156 files changed, 4780 insertions, 668 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 8983b39eb3..895e8ad0dc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -50,8 +50,8 @@ A clear and concise description of what the bug is.
Put "x" in "[ ]" if you already tried following:
-->
-[ ] Did you check if this is a duplicate issue?
-[ ] Did you test it on the latest FRRouting/frr master branch?
+- [ ] Did you check if this is a duplicate issue?
+- [ ] Did you test it on the latest FRRouting/frr master branch?
**To Reproduce**
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 455dd9fe85..d52eeeddba 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -769,7 +769,7 @@ static void _bfd_session_update(struct bfd_session *bs,
* Apply profile last: it also calls `bfd_set_shutdown`.
*
* There is no problem calling `shutdown` twice if the value doesn't
- * change or if it is overriden by peer specific configuration.
+ * change or if it is overridden by peer specific configuration.
*/
if (bpc->bpc_has_profile)
bfd_profile_apply(bpc->bpc_profile, bs);
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 7ab5ef13b4..00cc431e10 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -724,7 +724,7 @@ void bfd_profile_free(struct bfd_profile *bp);
/**
* Apply a profile configuration to an existing BFD session. The non default
- * values will not be overriden.
+ * values will not be overridden.
*
* NOTE: if the profile doesn't exist yet, then the profile will be applied
* once it begins to exist.
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index dd27c9f6a1..fd644ebf0a 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -544,7 +544,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
seg = as->segments;
-/* ASN takes 5 to 10 chars plus seperator, see below.
+/* ASN takes 5 to 10 chars plus separator, see below.
* If there is one differing segment type, we need an additional
* 2 chars for segment delimiters, and the final '\0'.
* Hopefully this is large enough to avoid hitting the realloc
@@ -560,17 +560,17 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
while (seg) {
int i;
- char seperator;
+ char separator;
- /* Check AS type validity. Set seperator for segment */
+ /* Check AS type validity. Set separator for segment */
switch (seg->type) {
case AS_SET:
case AS_CONFED_SET:
- seperator = ',';
+ separator = ',';
break;
case AS_SEQUENCE:
case AS_CONFED_SEQUENCE:
- seperator = ' ';
+ separator = ' ';
break;
default:
XFREE(MTYPE_AS_STR, str_buf);
@@ -584,7 +584,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
/* We might need to increase str_buf, particularly if path has
* differing segments types, our initial guesstimate above will
- * have been wrong. Need 10 chars for ASN, a seperator each and
+ * have been wrong. Need 10 chars for ASN, a separator each and
* potentially two segment delimiters, plus a space between each
* segment and trailing zero.
*
@@ -607,7 +607,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
if (make_json)
jseg_list = json_object_new_array();
- /* write out the ASNs, with their seperators, bar the last one*/
+ /* write out the ASNs, with their separators, bar the last one*/
for (i = 0; i < seg->length; i++) {
if (make_json)
json_object_array_add(
@@ -619,7 +619,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
if (i < (seg->length - 1))
len += snprintf(str_buf + len, str_size - len,
- "%c", seperator);
+ "%c", separator);
}
if (make_json) {
@@ -1917,7 +1917,7 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
{
const char *p = buf;
- /* Skip seperators (space for sequences, ',' for sets). */
+ /* Skip separators (space for sequences, ',' for sets). */
while (isspace((unsigned char)*p) || *p == ',')
p++;
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 2f246e61d8..118931a4df 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -847,7 +847,7 @@ struct attr *bgp_attr_intern(struct attr *attr)
struct lcommunity *lcomm = NULL;
struct community *comm = NULL;
- /* Intern referenced strucutre. */
+ /* Intern referenced structure. */
if (attr->aspath) {
if (!attr->aspath->refcnt)
attr->aspath = aspath_intern(attr->aspath);
@@ -986,6 +986,10 @@ struct attr *bgp_attr_aggregate_intern(
attr.origin = origin;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ /* MED */
+ attr.med = 0;
+ attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
/* AS path attribute. */
if (aspath)
attr.aspath = aspath_intern(aspath);
@@ -1008,18 +1012,13 @@ struct attr *bgp_attr_aggregate_intern(
}
bgp_attr_set_community(&attr, community);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
}
- if (ecommunity) {
+ if (ecommunity)
bgp_attr_set_ecommunity(&attr, ecommunity);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- }
- if (lcommunity) {
+ if (lcommunity)
bgp_attr_set_lcommunity(&attr, lcommunity);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
- }
if (bgp_in_graceful_shutdown(bgp))
bgp_attr_add_gshut_community(&attr);
@@ -1096,22 +1095,18 @@ void bgp_attr_unintern_sub(struct attr *attr)
comm = bgp_attr_get_community(attr);
community_unintern(&comm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
bgp_attr_set_community(attr, NULL);
ecomm = bgp_attr_get_ecommunity(attr);
ecommunity_unintern(&ecomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
bgp_attr_set_ecommunity(attr, NULL);
ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
ecommunity_unintern(&ipv6_ecomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
bgp_attr_set_ipv6_ecommunity(attr, NULL);
lcomm = bgp_attr_get_lcommunity(attr);
lcommunity_unintern(&lcomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
bgp_attr_set_lcommunity(attr, NULL);
cluster = bgp_attr_get_cluster(attr);
@@ -1243,7 +1238,7 @@ void bgp_attr_flush(struct attr *attr)
* are partial/optional and hence where the error likely was not
* introduced by the sending neighbour.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
bgp_size_t length)
{
@@ -1450,7 +1445,8 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
}
/* Get origin attribute of the update message. */
-static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_origin(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -1520,8 +1516,8 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
return BGP_ATTR_PARSE_PROCEED;
}
-static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
- struct attr *const attr)
+static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
+ struct attr *const attr)
{
/* These checks were part of bgp_attr_aspath, but with
* as4 we should to check aspath things when
@@ -1603,8 +1599,8 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
/*
* Check that the nexthop attribute is valid.
*/
-bgp_attr_parse_ret_t
-bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
+enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
+ struct attr *attr)
{
in_addr_t nexthop_h;
@@ -1633,7 +1629,8 @@ bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
}
/* Nexthop attribute. */
-static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_nexthop(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -1655,7 +1652,7 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
}
/* MED atrribute. */
-static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -1678,7 +1675,7 @@ static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
}
/* Local preference attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_local_pref(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -1790,7 +1787,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
}
/* New Aggregator attribute */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
as_t *as4_aggregator_as,
struct in_addr *as4_aggregator_addr)
@@ -1834,7 +1831,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
struct aspath *as4_path, as_t as4_aggregator,
struct in_addr *as4_aggregator_addr)
@@ -1936,7 +1933,7 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
}
/* Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_community(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -1963,13 +1960,11 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
/* Originator ID attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -1997,7 +1992,7 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
}
/* Cluster list attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2268,7 +2263,7 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
}
/* Large Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_large_community(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2294,13 +2289,11 @@ bgp_attr_large_community(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
/* Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2332,8 +2325,6 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
-
/* Extract DF election preference and mobility sequence number */
attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
@@ -2376,7 +2367,7 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
}
/* IPv6 Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2403,8 +2394,6 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
@@ -2541,7 +2530,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
/* SRv6 Service Data Sub-Sub-TLV attribute
* draft-ietf-bess-srv6-services-07
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2622,7 +2611,7 @@ bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
/* SRv6 Service Sub-TLV attribute
* draft-ietf-bess-srv6-services-07
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -2631,7 +2620,7 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
uint8_t type, sid_flags;
uint16_t length, endpoint_behavior;
size_t headersz = sizeof(type) + sizeof(length);
- bgp_attr_parse_ret_t err;
+ enum bgp_attr_parse_ret err;
char buf[BUFSIZ];
if (STREAM_READABLE(peer->curr) < headersz) {
@@ -2717,8 +2706,9 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
* Read an individual SID value returning how much data we have read
* Returns 0 if there was an error that needs to be passed up the stack
*/
-static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
- struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_psid_sub(uint8_t type, uint16_t length,
+ struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
@@ -2925,11 +2915,11 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Prefix SID attribute
* draft-ietf-idr-bgp-prefix-sid-05
*/
-bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
+enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
- bgp_attr_parse_ret_t ret;
+ enum bgp_attr_parse_ret ret;
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
@@ -2988,7 +2978,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
/* PMSI tunnel attribute (RFC 6514)
* Basic validation checks done here.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
@@ -3036,7 +3026,8 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
}
/* BGP unknown attribute treatment. */
-static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_unknown(struct bgp_attr_parser_args *args)
{
bgp_size_t total = args->total;
struct transit *transit;
@@ -3141,11 +3132,12 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
/* Read attribute of update packet. This function is called from
bgp_update_receive() in bgp_packet.c. */
-bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
- bgp_size_t size, struct bgp_nlri *mp_update,
- struct bgp_nlri *mp_withdraw)
+enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
+ bgp_size_t size,
+ struct bgp_nlri *mp_update,
+ struct bgp_nlri *mp_withdraw)
{
- bgp_attr_parse_ret_t ret;
+ enum bgp_attr_parse_ret ret;
uint8_t flag = 0;
uint8_t type = 0;
bgp_size_t length;
@@ -4185,9 +4177,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
-
- if (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED) {
+ bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT) &&
+ from &&
+ CHECK_FLAG(from->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT);
+
+ if (peer->sort == BGP_PEER_IBGP ||
+ peer->sort == BGP_PEER_CONFED || transparent) {
if (ecomm->size * 8 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 1f199da161..ac5734ede6 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -370,25 +370,25 @@ struct transit {
? bgp_attr_get_cluster((attr))->length \
: 0)
-typedef enum {
+enum bgp_attr_parse_ret {
BGP_ATTR_PARSE_PROCEED = 0,
BGP_ATTR_PARSE_ERROR = -1,
BGP_ATTR_PARSE_WITHDRAW = -2,
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
- */
+ */
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
BGP_ATTR_PARSE_EOR = -4,
-} bgp_attr_parse_ret_t;
+};
struct bpacket_attr_vec_arr;
/* Prototypes. */
extern void bgp_attr_init(void);
extern void bgp_attr_finish(void);
-extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
- bgp_size_t, struct bgp_nlri *,
- struct bgp_nlri *);
+extern enum bgp_attr_parse_ret bgp_attr_parse(struct peer *, struct attr *,
+ bgp_size_t, struct bgp_nlri *,
+ struct bgp_nlri *);
extern struct attr *bgp_attr_intern(struct attr *attr);
extern void bgp_attr_unintern_sub(struct attr *);
extern void bgp_attr_unintern(struct attr **);
@@ -432,7 +432,7 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
-extern bgp_attr_parse_ret_t
+extern enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args *args);
extern struct bgp_attr_encap_subtlv *
@@ -471,8 +471,8 @@ extern void bgp_packet_mpunreach_prefix(
bool addpath_capable, uint32_t addpath_tx_id, struct attr *attr);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
-extern bgp_attr_parse_ret_t bgp_attr_nexthop_valid(struct peer *peer,
- struct attr *attr);
+extern enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
+ struct attr *attr);
static inline int bgp_rmap_nhop_changed(uint32_t out_rmap_flags,
uint32_t in_rmap_flags)
@@ -516,6 +516,11 @@ static inline void bgp_attr_set_ecommunity(struct attr *attr,
struct ecommunity *ecomm)
{
attr->ecommunity = ecomm;
+
+ if (ecomm)
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
+ else
+ UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
}
static inline struct lcommunity *
@@ -528,6 +533,12 @@ static inline void bgp_attr_set_lcommunity(struct attr *attr,
struct lcommunity *lcomm)
{
attr->lcommunity = lcomm;
+
+ if (lcomm)
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
+ else
+ UNSET_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
}
static inline struct community *bgp_attr_get_community(const struct attr *attr)
@@ -539,6 +550,11 @@ static inline void bgp_attr_set_community(struct attr *attr,
struct community *comm)
{
attr->community = comm;
+
+ if (comm)
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
+ else
+ UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
}
static inline struct ecommunity *
@@ -551,6 +567,13 @@ static inline void bgp_attr_set_ipv6_ecommunity(struct attr *attr,
struct ecommunity *ipv6_ecomm)
{
attr->ipv6_ecommunity = ipv6_ecomm;
+
+ if (ipv6_ecomm)
+ SET_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
+ else
+ UNSET_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
}
static inline struct transit *bgp_attr_get_transit(const struct attr *attr)
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 0e590a463c..0631f8b95a 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -557,7 +557,7 @@ static bool community_regexp_match(struct community *com, regex_t *reg)
if (com == NULL || com->size == 0)
str = "";
else
- str = community_str(com, false);
+ str = community_str(com, false, true);
regstr = bgp_alias2community_str(str);
@@ -631,7 +631,7 @@ static bool lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
if (com == NULL || com->size == 0)
str = "";
else
- str = lcommunity_str(com, false);
+ str = lcommunity_str(com, false, true);
regstr = bgp_alias2community_str(str);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 6e6a3cd587..78cf9ea76c 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -200,7 +200,8 @@ struct community *community_uniq_sort(struct community *com)
0xFFFFFF04 "no-peer"
For other values, "AS:VAL" format is used. */
-static void set_community_string(struct community *com, bool make_json)
+static void set_community_string(struct community *com, bool make_json,
+ bool translate_alias)
{
int i;
char *str;
@@ -447,7 +448,9 @@ static void set_community_string(struct community *com, bool make_json)
val = comval & 0xFFFF;
char buf[32];
snprintf(buf, sizeof(buf), "%u:%d", as, val);
- const char *com2alias = bgp_community2alias(buf);
+ const char *com2alias =
+ translate_alias ? bgp_community2alias(buf)
+ : buf;
strlcat(str, com2alias, len);
if (make_json) {
@@ -487,7 +490,7 @@ struct community *community_intern(struct community *com)
/* Make string. */
if (!find->str)
- set_community_string(find, false);
+ set_community_string(find, false, true);
return find;
}
@@ -548,7 +551,7 @@ struct community *community_dup(struct community *com)
}
/* Return string representation of communities attribute. */
-char *community_str(struct community *com, bool make_json)
+char *community_str(struct community *com, bool make_json, bool translate_alias)
{
if (!com)
return NULL;
@@ -557,7 +560,7 @@ char *community_str(struct community *com, bool make_json)
XFREE(MTYPE_COMMUNITY_STR, com->str);
if (!com->str)
- set_community_string(com, make_json);
+ set_community_string(com, make_json, translate_alias);
return com->str;
}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index 2a1fbf526a..6f0ae0235c 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -76,7 +76,8 @@ extern struct community *community_uniq_sort(struct community *);
extern struct community *community_parse(uint32_t *, unsigned short);
extern struct community *community_intern(struct community *);
extern void community_unintern(struct community **);
-extern char *community_str(struct community *, bool make_json);
+extern char *community_str(struct community *, bool make_json,
+ bool translate_alias);
extern unsigned int community_hash_make(const struct community *);
extern struct community *community_str2com(const char *);
extern bool community_match(const struct community *, const struct community *);
diff --git a/bgpd/bgp_community_alias.c b/bgpd/bgp_community_alias.c
index 2c86efb5a0..caf469c0f7 100644
--- a/bgpd/bgp_community_alias.c
+++ b/bgpd/bgp_community_alias.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "zebra.h"
+
#include "memory.h"
#include "lib/jhash.h"
#include "frrstr.h"
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index f72a373a1c..dd1510a678 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -300,7 +300,7 @@ void bgp_conditional_adv_enable(struct peer *peer, afi_t afi, safi_t safi)
*/
peer->advmap_config_change[afi][safi] = true;
- /* advertise-map is already configured on atleast one of its
+ /* advertise-map is already configured on at least one of its
* neighbors (AFI/SAFI). So just increment the counter.
*/
if (++bgp->condition_filter_count > 1) {
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 5d14ff0fa6..49003e9428 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -411,12 +411,14 @@ bool bgp_dump_attr(struct attr *attr, char *buf, size_t size)
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)))
snprintf(buf + strlen(buf), size - strlen(buf),
", community %s",
- community_str(bgp_attr_get_community(attr), false));
+ community_str(bgp_attr_get_community(attr), false,
+ true));
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)))
snprintf(buf + strlen(buf), size - strlen(buf),
", large-community %s",
- lcommunity_str(bgp_attr_get_lcommunity(attr), false));
+ lcommunity_str(bgp_attr_get_lcommunity(attr), false,
+ true));
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
snprintf(buf + strlen(buf), size - strlen(buf),
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 08caa24a1b..4120524e63 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -210,7 +210,7 @@ ecommunity_uniq_sort_internal(struct ecommunity *ecom,
return new;
}
-/* This function takes pointer to Extended Communites strucutre then
+/* This function takes pointer to Extended Communites structure then
* create a new Extended Communities structure by uniq and sort each
* Extended Communities value.
*/
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 9f3f8389ad..fbb0d2272a 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -759,8 +759,6 @@ static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf,
ecommunity_add_val(bgp_attr_get_ecommunity(attr), &eval_rmac,
true, true);
}
-
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
/*
@@ -870,8 +868,6 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
attr, ecommunity_merge(bgp_attr_get_ecommunity(attr),
&ecom_na));
}
-
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
/*
@@ -3370,7 +3366,9 @@ static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi,
assert(attr);
- /* Only type-2, type-3, type-4 and type-5 are supported currently */
+ /* Only type-1, type-2, type-3, type-4 and type-5
+ * are supported currently
+ */
if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
|| evp->prefix.route_type == BGP_EVPN_IMET_ROUTE
|| evp->prefix.route_type == BGP_EVPN_ES_ROUTE
@@ -3475,7 +3473,7 @@ static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi,
if (evp->prefix.route_type == BGP_EVPN_ES_ROUTE) {
/* we will match based on the entire esi to avoid
- * imoort of an es route for esi2 into esi1
+ * import of an es route for esi2 into esi1
*/
es = bgp_evpn_es_find(&evp->prefix.es_addr.esi);
if (es && bgp_evpn_is_es_local(es))
@@ -6101,8 +6099,9 @@ bool bgp_evpn_is_prefix_nht_supported(const struct prefix *pfx)
* EVPN routes should be marked as valid only if the nexthop is
* reachable. Only if this happens, the route should be imported
* (into VNI or VRF routing tables) and/or advertised.
- * Note: This is currently applied for EVPN type-2, type-3 and
- * type-5 routes. It may be tweaked later on for other routes, or
+ * Note: This is currently applied for EVPN type-1, type-2,
+ * type-3, type-4 and type-5 routes.
+ * It may be tweaked later on for other routes, or
* even removed completely when all routes are handled.
*/
if (pfx && pfx->family == AF_EVPN
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 858fee50b3..6db4cba44d 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -287,7 +287,7 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
return ret;
}
-/* Install or unistall a Tyoe-4 route in the per-ES routing table */
+/* Install or unistall a Type-4 route in the per-ES routing table */
int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
afi_t afi, safi_t safi, struct prefix_evpn *evp,
struct bgp_path_info *pi, int install)
@@ -378,16 +378,16 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
remote_pi = tmp_pi;
}
- /* we don't expect to see a remote_ri at this point as
+ /* we don't expect to see a remote_pi at this point as
* an ES route has {esi, vtep_ip} as the key in the ES-rt-table
* in the VNI-rt-table.
*/
if (remote_pi) {
flog_err(
EC_BGP_ES_INVALID,
- "%u ERROR: local es route for ESI: %s Vtep %pI4 also learnt from remote",
+ "%u ERROR: local es route for ESI: %s vtep %pI4 also learnt from remote",
bgp->vrf_id, es ? es->esi_str : "Null",
- &es->originator_ip);
+ es ? &es->originator_ip : NULL);
return -1;
}
@@ -622,8 +622,6 @@ static void bgp_evpn_type4_route_extcomm_build(struct bgp_evpn_es *es,
bgp_attr_set_ecommunity(
attr,
ecommunity_merge(bgp_attr_get_ecommunity(attr), &ecom_df));
-
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
/* Create or update local type-4 route */
@@ -904,8 +902,6 @@ bgp_evpn_type1_es_route_extcomm_build(struct bgp_evpn_es_frag *es_frag,
ecom));
}
}
-
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
/* Extended communities associated with EAD-per-EVI */
@@ -932,8 +928,6 @@ static void bgp_evpn_type1_evi_route_extcomm_build(struct bgp_evpn_es *es,
bgp_attr_set_ecommunity(
attr,
ecommunity_merge(bgp_attr_get_ecommunity(attr), ecom));
-
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
/* Update EVPN EAD (type-1) route -
@@ -1688,7 +1682,7 @@ static bool bgp_evpn_is_macip_path(struct bgp_path_info *pi)
* This is done indirectly by re-attempting an install of the
* route in the associated VRFs. As a part of the VRF install use
* of l3 NHG is evaluated and this results in the
- * attr.es_flag ATTR_ES_USE_L3_NHG being set or cleared.
+ * attr.es_flag ATTR_ES_L3_NHG_USE being set or cleared.
*/
static void
bgp_evpn_es_path_update_on_es_vrf_chg(struct bgp_evpn_es_vrf *es_vrf,
@@ -2875,7 +2869,7 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
static bool bgp_evpn_l3nhg_zebra_ok(struct bgp_evpn_es_vrf *es_vrf)
{
- if (!bgp_mh_info->host_routes_use_l3nhg && !bgp_mh_info->install_l3nhg)
+ if (!bgp_mh_info->host_routes_use_l3nhg)
return false;
/* Check socket. */
@@ -3449,14 +3443,11 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
new_active ? "active" : "inactive");
/* add VTEP to parent es */
- if (new_active) {
- struct bgp_evpn_es_vtep *es_vtep;
-
- es_vtep = bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es,
- evi_vtep->vtep_ip, false /*esr*/,
- 0, 0);
- evi_vtep->es_vtep = es_vtep;
- } else {
+ if (new_active)
+ evi_vtep->es_vtep = bgp_evpn_es_vtep_add(
+ bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip,
+ false /*esr*/, 0, 0);
+ else {
if (evi_vtep->es_vtep) {
bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
false /*esr*/);
@@ -4401,14 +4392,12 @@ static uint32_t bgp_evpn_es_run_consistency_checks(struct bgp_evpn_es *es)
static void bgp_evpn_run_consistency_checks(struct thread *t)
{
int proc_cnt = 0;
- int es_cnt = 0;
struct listnode *node;
struct listnode *nextnode;
struct bgp_evpn_es *es;
for (ALL_LIST_ELEMENTS(bgp_mh_info->pend_es_list,
node, nextnode, es)) {
- ++es_cnt;
++proc_cnt;
/* run consistency checks on the ES and remove it from the
* pending list
@@ -4948,7 +4937,6 @@ void bgp_evpn_mh_init(void)
/* config knobs - XXX add cli to control it */
bgp_mh_info->ead_evi_adv_for_down_links = true;
bgp_mh_info->consistency_checking = true;
- bgp_mh_info->install_l3nhg = false;
bgp_mh_info->host_routes_use_l3nhg = BGP_EVPN_MH_USE_ES_L3NHG_DEF;
bgp_mh_info->suppress_l3_ecomm_on_inactive_es = true;
bgp_mh_info->bgp_evpn_nh_setup = true;
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index d9e2e72e4f..dc3fe44776 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -50,7 +50,9 @@ struct bgp_evpn_es_frag {
/* RD for this ES fragment */
struct prefix_rd prd;
- /* Memory used for linking bgp_evpn_es_rd to bgp_evpn_es->rd_list */
+ /* Memory used for linking bgp_evpn_es_frag to
+ * bgp_evpn_es->es_frag_list
+ */
struct listnode es_listnode;
/* List of ES-EVIs associated with this fragment */
@@ -59,11 +61,11 @@ struct bgp_evpn_es_frag {
/* Ethernet Segment entry -
* - Local and remote ESs are maintained in a global RB tree,
- * bgp_mh_info->es_rb_tree using ESI as key
+ * bgp_mh_info->es_rb_tree using ESI as key
* - Local ESs are received from zebra (BGP_EVPNES_LOCAL)
* - Remotes ESs are implicitly created (by reference) by a remote ES-EVI
* (BGP_EVPNES_REMOTE)
- * - An ES can be simulatenously LOCAL and REMOTE; infact all LOCAL ESs are
+ * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are
* expected to have REMOTE ES peers.
*/
struct bgp_evpn_es {
@@ -101,7 +103,7 @@ struct bgp_evpn_es {
*/
struct listnode pend_es_listnode;
- /* [EVPNES_LOCAL] List of RDs for this ES (bgp_evpn_es_rd) */
+ /* [EVPNES_LOCAL] List of RDs for this ES (bgp_evpn_es_frag) */
struct list *es_frag_list;
struct bgp_evpn_es_frag *es_base_frag;
@@ -319,7 +321,6 @@ struct bgp_evpn_mh_info {
/* Enable ES consistency checking */
bool consistency_checking;
/* Use L3 NHGs for host routes in symmetric IRB */
- bool install_l3nhg;
bool host_routes_use_l3nhg;
/* Some vendors are not generating the EAD-per-EVI route. This knob
* can be turned off to activate a remote ES-PE when the EAD-per-ES
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 5f519e84ed..109de1efb2 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3867,19 +3867,19 @@ DEFUN (bgp_evpn_advertise_type5,
if (!(afi == AFI_IP || afi == AFI_IP6)) {
vty_out(vty,
- "%%only ipv4 or ipv6 address families are supported\n");
+ "%% Only ipv4 or ipv6 address families are supported\n");
return CMD_WARNING;
}
if (safi != SAFI_UNICAST) {
vty_out(vty,
- "%%only ipv4 unicast or ipv6 unicast are supported\n");
+ "%% Only ipv4 unicast or ipv6 unicast are supported\n");
return CMD_WARNING;
}
if ((oly != OVERLAY_INDEX_TYPE_NONE)
&& (oly != OVERLAY_INDEX_GATEWAY_IP)) {
- vty_out(vty, "%%Unknown overlay-index type specified\n");
+ vty_out(vty, "%% Unknown overlay-index type specified\n");
return CMD_WARNING;
}
@@ -4058,13 +4058,13 @@ DEFUN (no_bgp_evpn_advertise_type5,
if (!(afi == AFI_IP || afi == AFI_IP6)) {
vty_out(vty,
- "%%only ipv4 or ipv6 address families are supported\n");
+ "%% Only ipv4 or ipv6 address families are supported\n");
return CMD_WARNING;
}
if (safi != SAFI_UNICAST) {
vty_out(vty,
- "%%only ipv4 unicast or ipv6 unicast are supported\n");
+ "%% Only ipv4 unicast or ipv6 unicast are supported\n");
return CMD_WARNING;
}
@@ -4495,7 +4495,7 @@ DEFPY(show_bgp_l2vpn_evpn_es,
if (esi_str) {
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
bgp_evpn_es_show_esi(vty, &esi, uj);
@@ -4517,7 +4517,7 @@ DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
if (esi_str) {
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
@@ -5132,7 +5132,7 @@ DEFPY_HIDDEN(
if (esi_str) {
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
esi_p = &esi;
@@ -5165,7 +5165,7 @@ DEFPY_HIDDEN(
if (esi_str) {
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
esi_p = &esi;
@@ -5267,19 +5267,19 @@ DEFPY_HIDDEN(test_es_add,
bgp = bgp_get_evpn();
if (!bgp) {
- vty_out(vty, "%%EVPN BGP instance not yet created\n");
+ vty_out(vty, "%% EVPN BGP instance not yet created\n");
return CMD_WARNING;
}
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
if (no) {
ret = bgp_evpn_local_es_del(bgp, &esi);
if (ret == -1) {
- vty_out(vty, "%%Failed to delete ES\n");
+ vty_out(vty, "%% Failed to delete ES\n");
return CMD_WARNING;
}
} else {
@@ -5292,7 +5292,7 @@ DEFPY_HIDDEN(test_es_add,
ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
EVPN_MH_DF_PREF_MIN, false);
if (ret == -1) {
- vty_out(vty, "%%Failed to add ES\n");
+ vty_out(vty, "%% Failed to add ES\n");
return CMD_WARNING;
}
}
@@ -5316,25 +5316,25 @@ DEFPY_HIDDEN(test_es_vni_add,
bgp = bgp_get_evpn();
if (!bgp) {
- vty_out(vty, "%%EVPN BGP instance not yet created\n");
+ vty_out(vty, "%% EVPN BGP instance not yet created\n");
return CMD_WARNING;
}
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%%Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI\n");
return CMD_WARNING;
}
if (no) {
ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
if (ret == -1) {
- vty_out(vty, "%%Failed to deref ES VNI\n");
+ vty_out(vty, "%% Failed to deref ES VNI\n");
return CMD_WARNING;
}
} else {
ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
if (ret == -1) {
- vty_out(vty, "%%Failed to ref ES VNI\n");
+ vty_out(vty, "%% Failed to ref ES VNI\n");
return CMD_WARNING;
}
}
@@ -5747,9 +5747,13 @@ DEFUN (show_bgp_vrf_l3vni_info,
name = argv[idx_vrf]->arg;
bgp = bgp_lookup_by_name(name);
+ if (strmatch(name, VRF_DEFAULT_NAME))
+ bgp = bgp_get_default();
+
if (!bgp) {
if (!uj)
- vty_out(vty, "BGP instance for VRF %s not found", name);
+ vty_out(vty, "BGP instance for VRF %s not found\n",
+ name);
else {
json_object_string_add(json, "warning",
"BGP instance not found");
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index 60ad75c73b..e0cca50d89 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -103,7 +103,7 @@ static bool lcommunity_add_val(struct lcommunity *lcom,
return true;
}
-/* This function takes pointer to Large Communites strucutre then
+/* This function takes pointer to Large Communites structure then
create a new Large Communities structure by uniq and sort each
Large Communities value. */
struct lcommunity *lcommunity_uniq_sort(struct lcommunity *lcom)
@@ -175,7 +175,8 @@ struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
return lcom1;
}
-static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
+static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
+ bool translate_alias)
{
int i;
int len;
@@ -228,7 +229,8 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
local2);
- const char *com2alias = bgp_community2alias(lcsb);
+ const char *com2alias =
+ translate_alias ? bgp_community2alias(lcsb) : lcsb;
len = strlcat(str_buf, com2alias, str_buf_sz);
assert((unsigned int)len < str_buf_sz);
@@ -264,7 +266,7 @@ struct lcommunity *lcommunity_intern(struct lcommunity *lcom)
find->refcnt++;
if (!find->str)
- set_lcommunity_string(find, false);
+ set_lcommunity_string(find, false, true);
return find;
}
@@ -291,7 +293,8 @@ void lcommunity_unintern(struct lcommunity **lcom)
}
/* Return string representation of lcommunities attribute. */
-char *lcommunity_str(struct lcommunity *lcom, bool make_json)
+char *lcommunity_str(struct lcommunity *lcom, bool make_json,
+ bool translate_alias)
{
if (!lcom)
return NULL;
@@ -300,7 +303,7 @@ char *lcommunity_str(struct lcommunity *lcom, bool make_json)
XFREE(MTYPE_LCOMMUNITY_STR, lcom->str);
if (!lcom->str)
- set_lcommunity_string(lcom, make_json);
+ set_lcommunity_string(lcom, make_json, translate_alias);
return lcom->str;
}
diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h
index 6ccb6b7879..b9b5fe35d5 100644
--- a/bgpd/bgp_lcommunity.h
+++ b/bgpd/bgp_lcommunity.h
@@ -69,7 +69,8 @@ extern struct hash *lcommunity_hash(void);
extern struct lcommunity *lcommunity_str2com(const char *);
extern bool lcommunity_match(const struct lcommunity *,
const struct lcommunity *);
-extern char *lcommunity_str(struct lcommunity *, bool make_json);
+extern char *lcommunity_str(struct lcommunity *, bool make_json,
+ bool translate_alias);
extern bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 6e695d0301..6cd6ddd9dd 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -905,18 +905,12 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
attr.aspath = aspath;
attr.origin = origin;
- if (community) {
+ if (community)
bgp_attr_set_community(&attr, community);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
- }
- if (ecomm) {
+ if (ecomm)
bgp_attr_set_ecommunity(&attr, ecomm);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- }
- if (lcomm) {
+ if (lcomm)
bgp_attr_set_lcommunity(&attr, lcomm);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
- }
/* Zap multipath attr nexthop so we set nexthop to self */
attr.nexthop.s_addr = INADDR_ANY;
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 08a68d0c12..b3d8d1b82d 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -516,28 +516,35 @@ static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
}
/*
+ * This function generates a new SID based on bgp->srv6_locator_chunks and
+ * index. The locator and generated SID are stored in arguments sid_locator
+ * and sid, respectively.
+ *
* if index != 0: try to allocate as index-mode
* else: try to allocate as auto-mode
*/
static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
- struct in6_addr *sid_locator)
+ struct in6_addr *sid_locator,
+ struct in6_addr *sid)
{
struct listnode *node;
struct srv6_locator_chunk *chunk;
- struct in6_addr sid_buf;
bool alloced = false;
int label = 0;
+ uint8_t offset = 0;
- if (!bgp || !sid_locator)
+ if (!bgp || !sid_locator || !sid)
return false;
for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
*sid_locator = chunk->prefix.prefix;
- sid_buf = chunk->prefix.prefix;
+ *sid = chunk->prefix.prefix;
+ offset = chunk->block_bits_length + chunk->node_bits_length;
+
if (index != 0) {
label = index << 12;
- transpose_sid(&sid_buf, label, 64, 16);
- if (sid_exist(bgp, &sid_buf))
+ transpose_sid(sid, label, offset, 16);
+ if (sid_exist(bgp, sid))
return false;
alloced = true;
break;
@@ -545,8 +552,8 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
for (size_t i = 1; i < 255; i++) {
label = i << 12;
- transpose_sid(&sid_buf, label, 64, 16);
- if (sid_exist(bgp, &sid_buf))
+ transpose_sid(sid, label, offset, 16);
+ if (sid_exist(bgp, sid))
continue;
alloced = true;
break;
@@ -556,7 +563,7 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
if (!alloced)
return 0;
- sid_register(bgp, &sid_buf, bgp->srv6_locator_name);
+ sid_register(bgp, sid, bgp->srv6_locator_name);
return label;
}
@@ -600,20 +607,19 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
tovpn_sid_locator =
XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
- tovpn_sid_transpose_label =
- alloc_new_sid(bgp_vpn, tovpn_sid_index, tovpn_sid_locator);
+ tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
+
+ tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
+ tovpn_sid_locator, tovpn_sid);
+
if (tovpn_sid_transpose_label == 0) {
zlog_debug("%s: not allocated new sid for vrf %s: afi %s",
__func__, bgp_vrf->name_pretty, afi2str(afi));
+ XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid_locator);
+ XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
return;
}
- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
- *tovpn_sid = *tovpn_sid_locator;
- transpose_sid(tovpn_sid, tovpn_sid_transpose_label,
- BGP_PREFIX_SID_SRV6_TRANSPOSITION_OFFSET,
- BGP_PREFIX_SID_SRV6_TRANSPOSITION_LENGTH);
-
if (debug) {
inet_ntop(AF_INET6, tovpn_sid, buf, sizeof(buf));
zlog_debug("%s: new sid %s allocated for vrf %s: afi %s",
@@ -1147,7 +1153,6 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
.rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
}
bgp_attr_set_ecommunity(&static_attr, new_ecom);
- SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
if (debug && bgp_attr_get_ecommunity(&static_attr)) {
char *s = ecommunity_ecom2str(
@@ -1511,8 +1516,6 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
bgp_attr_set_ecommunity(&static_attr, new_ecom);
if (new_ecom->size == 0) {
- UNSET_FLAG(static_attr.flag,
- ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
ecommunity_free(&new_ecom);
bgp_attr_set_ecommunity(&static_attr, NULL);
}
@@ -1924,7 +1927,7 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
struct bgp *bgp_import;
struct listnode *node;
struct ecommunity *ecom;
- vpn_policy_direction_t idir, edir;
+ enum vpn_policy_direction idir, edir;
/*
* Router-id change that is not explicitly configured
@@ -2037,7 +2040,7 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi)
{
const char *export_name;
- vpn_policy_direction_t idir, edir;
+ enum vpn_policy_direction idir, edir;
char *vname, *tmp_name;
char buf[RD_ADDRSTRLEN];
struct ecommunity *ecom;
@@ -2166,7 +2169,7 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi)
{
const char *export_name, *tmp_name;
- vpn_policy_direction_t idir, edir;
+ enum vpn_policy_direction idir, edir;
char *vname;
struct ecommunity *ecom = NULL;
struct listnode *node;
@@ -3089,7 +3092,7 @@ void bgp_vpn_leak_export(struct bgp *from_bgp)
char *vname;
struct listnode *node, *next;
struct ecommunity *ecom;
- vpn_policy_direction_t idir, edir;
+ enum vpn_policy_direction idir, edir;
safi_t safi = SAFI_UNICAST;
struct bgp *to_bgp;
int debug;
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 5bf772fefe..8c2eae279c 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -205,7 +205,7 @@ static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
return 1;
}
-static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
+static inline void vpn_leak_prechange(enum vpn_policy_direction direction,
afi_t afi, struct bgp *bgp_vpn,
struct bgp *bgp_vrf)
{
@@ -225,7 +225,7 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
}
}
-static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
+static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
afi_t afi, struct bgp *bgp_vpn,
struct bgp *bgp_vrf)
{
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index d3ebc0e6a2..dc4f30a906 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -323,7 +323,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
pi->extra->igpmetric = 0;
} else if (peer) {
/*
- * Let's not accidently save the peer data for a peer
+ * Let's not accidentally save the peer data for a peer
* we are going to throw away in a second or so.
* When we come back around we'll fix up this
* data properly in replace_nexthop_by_peer
@@ -589,6 +589,10 @@ static void bgp_nht_ifp_handle(struct interface *ifp, bool up)
if (!bgp)
return;
+ bgp_nht_ifp_table_handle(bgp, &bgp->nexthop_cache_table[AFI_IP], ifp,
+ up);
+ bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP], ifp,
+ up);
bgp_nht_ifp_table_handle(bgp, &bgp->nexthop_cache_table[AFI_IP6], ifp,
up);
bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP6], ifp,
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 8b8fcf58c0..b0d852ee63 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1679,7 +1679,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
*
* Complicates the flow a little though..
*/
- bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
+ enum bgp_attr_parse_ret attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
/* This define morphs the update case into a withdraw when lower levels
* have signalled an error condition where this is best.
*/
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 72eba2c3be..7e2cb5c70c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -565,8 +565,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
{
const struct prefix *new_p;
struct attr *newattr, *existattr;
- bgp_peer_sort_t new_sort;
- bgp_peer_sort_t exist_sort;
+ enum bgp_peer_sort new_sort;
+ enum bgp_peer_sort exist_sort;
uint32_t new_pref;
uint32_t exist_pref;
uint32_t new_med;
@@ -1253,10 +1253,10 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
}
- /* 13. Router-ID comparision. */
+ /* 13. Router-ID comparison. */
/* If one of the paths is "stale", the corresponding peer router-id will
* be 0 and would always win over the other path. If originator id is
- * used for the comparision, it will decide which path is better.
+ * used for the comparison, it will decide which path is better.
*/
if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
new_id.s_addr = newattr->originator_id.s_addr;
@@ -1285,7 +1285,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 0;
}
- /* 14. Cluster length comparision. */
+ /* 14. Cluster length comparison. */
new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
@@ -1309,7 +1309,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 0;
}
- /* 15. Neighbor address comparision. */
+ /* 15. Neighbor address comparison. */
/* Do this only if neither path is "stale" as stale paths do not have
* valid peer information (as the connection may or may not be up).
*/
@@ -1598,7 +1598,7 @@ static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
/* Route map apply. */
if (rmap) {
memset(&rmap_path, 0, sizeof(struct bgp_path_info));
- /* Duplicate current value to new strucutre for modification. */
+ /* Duplicate current value to new structure for modification. */
rmap_path.peer = peer;
rmap_path.attr = attr;
rmap_path.extra = &extra;
@@ -1655,7 +1655,7 @@ static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
memset(&rmap_path, 0, sizeof(struct bgp_path_info));
/* Route map apply. */
- /* Duplicate current value to new strucutre for modification. */
+ /* Duplicate current value to new structure for modification. */
rmap_path.peer = peer;
rmap_path.attr = attr;
@@ -1769,7 +1769,6 @@ void bgp_attr_add_llgr_community(struct attr *attr)
community_free(&llgr);
bgp_attr_set_community(attr, new);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
}
void bgp_attr_add_gshut_community(struct attr *attr)
@@ -1798,7 +1797,6 @@ void bgp_attr_add_gshut_community(struct attr *attr)
community_free(&gshut);
bgp_attr_set_community(attr, new);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
/* When we add the graceful-shutdown community we must also
* lower the local-preference */
@@ -3711,7 +3709,6 @@ static void bgp_attr_add_no_export_community(struct attr *attr)
community_free(&no_export);
bgp_attr_set_community(attr, new);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
}
int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
@@ -8189,14 +8186,16 @@ DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
"[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
"as-set$as_set_s"
"|summary-only$summary_only"
- "|route-map WORD$rmap_name"
+ "|route-map RMAP_NAME$rmap_name"
"|origin <egp|igp|incomplete>$origin_s"
"|matching-MED-only$match_med"
- "|suppress-map WORD$suppress_map"
+ "|suppress-map RMAP_NAME$suppress_map"
"}]",
NO_STR
"Configure BGP aggregate entries\n"
- "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
+ "Aggregate prefix\n"
+ "Aggregate address\n"
+ "Aggregate mask\n"
"Generate AS set path information\n"
"Filter more specific routes from updates\n"
"Apply route map to aggregate network\n"
@@ -8251,10 +8250,10 @@ DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
"[no] aggregate-address X:X::X:X/M$prefix [{"
"as-set$as_set_s"
"|summary-only$summary_only"
- "|route-map WORD$rmap_name"
+ "|route-map RMAP_NAME$rmap_name"
"|origin <egp|igp|incomplete>$origin_s"
"|matching-MED-only$match_med"
- "|suppress-map WORD$suppress_map"
+ "|suppress-map RMAP_NAME$suppress_map"
"}]",
NO_STR
"Configure BGP aggregate entries\n"
@@ -10506,7 +10505,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (json_paths) {
if (!bgp_attr_get_community(attr)->json)
community_str(bgp_attr_get_community(attr),
- true);
+ true, true);
json_object_lock(bgp_attr_get_community(attr)->json);
json_object_object_add(
json_path, "community",
@@ -10537,7 +10536,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (json_paths) {
if (!bgp_attr_get_lcommunity(attr)->json)
lcommunity_str(bgp_attr_get_lcommunity(attr),
- true);
+ true, true);
json_object_lock(bgp_attr_get_lcommunity(attr)->json);
json_object_object_add(
json_path, "largeCommunity",
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 1d87641a2d..6c303a9e5f 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2199,7 +2199,6 @@ route_set_community(void *rule, const struct prefix *prefix, void *object)
/* "none" case. */
if (rcs->none) {
- attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
bgp_attr_set_community(attr, NULL);
/* See the longer comment down below. */
if (old && old->refcnt == 0)
@@ -2227,8 +2226,6 @@ route_set_community(void *rule, const struct prefix *prefix, void *object)
/* will be interned by caller if required */
bgp_attr_set_community(attr, new);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
-
return RMAP_OKAY;
}
@@ -2313,7 +2310,6 @@ route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
/* "none" case. */
if (rcs->none) {
- attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
bgp_attr_set_lcommunity(attr, NULL);
/* See the longer comment down below. */
@@ -2341,8 +2337,6 @@ route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
/* will be intern()'d or attr_flush()'d by bgp_update_main() */
bgp_attr_set_lcommunity(attr, new);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
-
return RMAP_OKAY;
}
@@ -2438,13 +2432,9 @@ route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
if (new->size == 0) {
bgp_attr_set_lcommunity(path->attr, NULL);
- path->attr->flag &=
- ~ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
lcommunity_free(&new);
} else {
bgp_attr_set_lcommunity(path->attr, new);
- path->attr->flag |=
- ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
}
}
@@ -2526,12 +2516,9 @@ route_set_community_delete(void *rule, const struct prefix *prefix,
if (new->size == 0) {
bgp_attr_set_community(path->attr, NULL);
- path->attr->flag &=
- ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
community_free(&new);
} else {
bgp_attr_set_community(path->attr, new);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
}
}
@@ -2597,7 +2584,6 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
attr = path->attr;
if (rcs->none) {
- attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
bgp_attr_set_ecommunity(attr, NULL);
return RMAP_OKAY;
}
@@ -2624,8 +2610,6 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
/* will be intern()'d or attr_flush()'d by bgp_update_main() */
bgp_attr_set_ecommunity(path->attr, new_ecom);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
-
return RMAP_OKAY;
}
@@ -2787,7 +2771,6 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
/* new_ecom will be intern()'d or attr_flush()'d in call stack */
bgp_attr_set_ecommunity(path->attr, new_ecom);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
/* Mark that route-map has set link bandwidth; used in attribute
* setting decisions.
@@ -3809,6 +3792,14 @@ static void bgp_route_map_update_peer_group(const char *rmap_name,
if (filter->usmap.name
&& (strcmp(rmap_name, filter->usmap.name) == 0))
filter->usmap.map = map;
+
+ if (filter->advmap.aname &&
+ (strcmp(rmap_name, filter->advmap.aname) == 0))
+ filter->advmap.amap = map;
+
+ if (filter->advmap.cname &&
+ (strcmp(rmap_name, filter->advmap.cname) == 0))
+ filter->advmap.cmap = map;
}
}
}
@@ -5562,19 +5553,19 @@ DEFUN_YANG (set_community,
str = buffer_getstr(b);
buffer_free(b);
- if (str) {
+ if (str)
com = community_str2com(str);
- XFREE(MTYPE_TMP, str);
- }
/* Can't compile user input into communities attribute. */
if (!com) {
- vty_out(vty, "%% Malformed communities attribute\n");
+ vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
+ XFREE(MTYPE_TMP, str);
return CMD_WARNING_CONFIG_FAILED;
}
+ XFREE(MTYPE_TMP, str);
/* Set communites attribute string. */
- str = community_str(com, false);
+ str = community_str(com, false, false);
if (additive) {
size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index aa3e44318a..e85118e588 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -1463,7 +1463,7 @@ static int update_group_periodic_merge_walkcb(struct update_group *updgrp,
* over multiple statements. Useful to set dirty flag on
* update groups.
*/
-void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
+void update_group_policy_update(struct bgp *bgp, enum bgp_policy_type ptype,
const char *pname, int route_update,
int start_event)
{
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 0e10341bc4..e3309ab7c5 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -74,7 +74,7 @@
| PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
| PEER_CAP_ENHE_AF_NEGO)
-typedef enum { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX } bpacket_attr_vec_type;
+enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX };
typedef struct {
uint32_t flags;
@@ -288,7 +288,7 @@ struct updwalk_context {
struct bgp_path_info *pi;
uint64_t updgrp_id;
uint64_t subgrp_id;
- bgp_policy_type_e policy_type;
+ enum bgp_policy_type policy_type;
const char *policy_name;
int policy_event_start_flag;
int policy_route_update;
@@ -368,7 +368,8 @@ extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
extern bool update_subgroup_check_merge(struct update_subgroup *, const char *);
extern bool update_subgroup_trigger_merge_check(struct update_subgroup *,
int force);
-extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
+extern void update_group_policy_update(struct bgp *bgp,
+ enum bgp_policy_type ptype,
const char *pname, int route_update,
int start_event);
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
@@ -409,7 +410,7 @@ extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
struct peer_af *paf);
extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
- bpacket_attr_vec_type type,
+ enum bpacket_attr_vec_type type,
struct stream *s, struct attr *attr);
extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
struct attr *attr,
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 0d8ee79ae5..87558f9c35 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -818,6 +818,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
assert(attr.aspath);
attr.local_pref = bgp->default_local_pref;
+ attr.med = 0;
+ attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
/* IPv6 global nexthop must be included. */
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index cf24e1d689..c4a3ca7500 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -1240,7 +1240,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
static void
bpacket_vec_arr_inherit_attr_flags(struct bpacket_attr_vec_arr *vecarr,
- bpacket_attr_vec_type type,
+ enum bpacket_attr_vec_type type,
struct attr *attr)
{
if (CHECK_FLAG(attr->rmap_change_flags,
@@ -1291,8 +1291,8 @@ void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr)
/* Setup a particular node entry in the vecarr */
void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
- bpacket_attr_vec_type type, struct stream *s,
- struct attr *attr)
+ enum bpacket_attr_vec_type type,
+ struct stream *s, struct attr *attr)
{
if (!vecarr)
return;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 941696ab74..2aa77576a1 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -934,12 +934,12 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
switch (error) {
case BGP_ERR_AF_UNCONFIGURED:
vty_out(vty,
- "%%BGP: Enable %s address family for the neighbor %s\n",
+ "%% BGP: Enable %s address family for the neighbor %s\n",
get_afi_safi_str(afi, safi, false), peer->host);
break;
case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
vty_out(vty,
- "%%BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
+ "%% BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
peer->host);
break;
default:
@@ -1086,7 +1086,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
peer = peer_lookup(bgp, &su);
if (!peer) {
vty_out(vty,
- "%%BGP: Unknown neighbor - \"%s\"\n",
+ "%% BGP: Unknown neighbor - \"%s\"\n",
arg);
return CMD_WARNING;
}
@@ -1113,7 +1113,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
group = peer_group_lookup(bgp, arg);
if (!group) {
- vty_out(vty, "%%BGP: No such peer-group %s\n", arg);
+ vty_out(vty, "%% BGP: No such peer-group %s\n", arg);
return CMD_WARNING;
}
@@ -1128,7 +1128,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
- "%%BGP: No %s peer belonging to peer-group %s is configured\n",
+ "%% BGP: No %s peer belonging to peer-group %s is configured\n",
get_afi_safi_str(afi, safi, false), arg);
return CMD_SUCCESS;
@@ -1163,7 +1163,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
- "%%BGP: No external %s peer is configured\n",
+ "%% BGP: No external %s peer is configured\n",
get_afi_safi_str(afi, safi, false));
return CMD_SUCCESS;
@@ -1200,7 +1200,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
- "%%BGP: No %s peer is configured with AS %s\n",
+ "%% BGP: No %s peer is configured with AS %s\n",
get_afi_safi_str(afi, safi, false), arg);
return CMD_SUCCESS;
@@ -7434,7 +7434,7 @@ DEFPY (bgp_condadv_period,
DEFPY (neighbor_advertise_map,
neighbor_advertise_map_cmd,
- "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map RMAP_NAME$advertise_str <exist-map|non-exist-map>$exist RMAP_NAME$condition_str",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
@@ -7455,7 +7455,7 @@ DEFPY (neighbor_advertise_map,
}
ALIAS_HIDDEN(neighbor_advertise_map, neighbor_advertise_map_hidden_cmd,
- "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map RMAP_NAME$advertise_str <exist-map|non-exist-map>$exist RMAP_NAME$condition_str",
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Route-map to conditionally advertise routes\n"
"Name of advertise map\n"
@@ -8700,7 +8700,7 @@ DEFPY (af_rt_vpn_imexport,
int ret;
struct ecommunity *ecom = NULL;
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
- vpn_policy_direction_t dir;
+ enum vpn_policy_direction dir;
afi_t afi;
int idx = 0;
bool yes = true;
@@ -8780,7 +8780,7 @@ DEFPY (af_route_map_vpn_imexport,
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
- vpn_policy_direction_t dir;
+ enum vpn_policy_direction dir;
afi_t afi;
int idx = 0;
bool yes = true;
@@ -8843,7 +8843,7 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
"name of route-map\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- vpn_policy_direction_t dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ enum vpn_policy_direction dir = BGP_VPN_POLICY_DIR_FROMVPN;
afi_t afi;
struct bgp *bgp_default;
@@ -8896,7 +8896,7 @@ DEFPY(af_no_import_vrf_route_map, af_no_import_vrf_route_map_cmd,
"name of route-map\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- vpn_policy_direction_t dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ enum vpn_policy_direction dir = BGP_VPN_POLICY_DIR_FROMVPN;
afi_t afi;
afi = vpn_policy_getafi(vty, bgp, true);
@@ -9027,7 +9027,7 @@ DEFPY (bgp_imexport_vpn,
int idx = 0;
bool yes = true;
int flag;
- vpn_policy_direction_t dir;
+ enum vpn_policy_direction dir;
if (argv_find(argv, argc, "no", &idx))
yes = false;
@@ -12559,6 +12559,18 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
else
json_object_boolean_false_add(
json_neigh, "extendedOptionalParametersLength");
+
+ /* Conditional advertisements */
+ json_object_int_add(
+ json_neigh,
+ "bgpTimerConfiguredConditionalAdvertisementsSec",
+ bgp->condition_check_period);
+ if (thread_is_scheduled(bgp->t_condition_check))
+ json_object_int_add(
+ json_neigh,
+ "bgpTimerUntilConditionalAdvertisementsSec",
+ thread_timer_remain_second(
+ bgp->t_condition_check));
} else {
/* Administrative shutdown. */
if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)
@@ -12636,6 +12648,16 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
vty_out(vty,
" Extended Optional Parameters Length is enabled\n");
+
+ /* Conditional advertisements */
+ vty_out(vty,
+ " Configured conditional advertisements interval is %d seconds\n",
+ bgp->condition_check_period);
+ if (thread_is_scheduled(bgp->t_condition_check))
+ vty_out(vty,
+ " Time until conditional advertisements begin is %lu seconds\n",
+ thread_timer_remain_second(
+ bgp->t_condition_check));
}
/* Capability. */
if (peer_established(p) &&
@@ -14473,7 +14495,7 @@ static void community_show_all_iterator(struct hash_bucket *bucket,
com = (struct community *)bucket->data;
vty_out(vty, "[%p] (%ld) %s\n", (void *)com, com->refcnt,
- community_str(com, false));
+ community_str(com, false, false));
}
/* Show BGP's community internal data. */
@@ -14502,7 +14524,7 @@ static void lcommunity_show_all_iterator(struct hash_bucket *bucket,
lcom = (struct lcommunity *)bucket->data;
vty_out(vty, "[%p] (%ld) %s\n", (void *)lcom, lcom->refcnt,
- lcommunity_str(lcom, false));
+ lcommunity_str(lcom, false, false));
}
/* Show BGP's community internal data. */
@@ -14604,7 +14626,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
char *vname;
char buf1[INET6_ADDRSTRLEN];
char *ecom_str;
- vpn_policy_direction_t dir;
+ enum vpn_policy_direction dir;
if (json) {
json_object *json_import_vrfs = NULL;
@@ -19354,9 +19376,9 @@ static const char *community_list_config_str(struct community_entry *entry)
str = "";
else {
if (entry->style == COMMUNITY_LIST_STANDARD)
- str = community_str(entry->u.com, false);
+ str = community_str(entry->u.com, false, false);
else if (entry->style == LARGE_COMMUNITY_LIST_STANDARD)
- str = lcommunity_str(entry->u.lcom, false);
+ str = lcommunity_str(entry->u.lcom, false, false);
else
str = entry->config;
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 6f06ad5a40..a2361758dc 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -565,7 +565,7 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as)
AS change. Just Reset EBGP sessions, not CONFED sessions. If we
were not doing confederation before, reset all EBGP sessions. */
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- bgp_peer_sort_t ptype = peer_sort(peer);
+ enum bgp_peer_sort ptype = peer_sort(peer);
/* We're looking for peers who's AS is not local or part of our
confederation. */
@@ -1004,7 +1004,7 @@ void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
}
/* Check peer's AS number and determines if this peer is IBGP or EBGP */
-static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
+static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
{
struct bgp *bgp;
@@ -1091,13 +1091,13 @@ static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
}
/* Calculate and cache the peer "sort" */
-bgp_peer_sort_t peer_sort(struct peer *peer)
+enum bgp_peer_sort peer_sort(struct peer *peer)
{
peer->sort = peer_calc_sort(peer);
return peer->sort;
}
-bgp_peer_sort_t peer_sort_lookup(struct peer *peer)
+enum bgp_peer_sort peer_sort_lookup(struct peer *peer)
{
return peer->sort;
}
@@ -1826,7 +1826,7 @@ int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
- bgp_peer_sort_t origtype, newtype;
+ enum bgp_peer_sort origtype, newtype;
/* Stop peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -1931,8 +1931,8 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
return BGP_ERR_PEER_GROUP_MEMBER;
}
- bgp_peer_sort_t peer_sort_type =
- peer_sort(peer->group->conf);
+ enum bgp_peer_sort peer_sort_type =
+ peer_sort(peer->group->conf);
/* Explicit AS numbers used, compare AS numbers */
if (as_type == AS_SPECIFIED) {
@@ -2103,6 +2103,20 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
}
+ /* Conditional Advertisements */
+ if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ADVERTISE_MAP)) {
+ PEER_STR_ATTR_INHERIT(peer, group,
+ filter[afi][safi].advmap.aname,
+ MTYPE_BGP_FILTER_NAME);
+ PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.amap);
+ PEER_STR_ATTR_INHERIT(peer, group,
+ filter[afi][safi].advmap.cname,
+ MTYPE_BGP_FILTER_NAME);
+ PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.cmap);
+ PEER_ATTR_INHERIT(peer, group,
+ filter[afi][safi].advmap.condition);
+ }
+
if (peer->addpath_type[afi][safi] == BGP_ADDPATH_NONE) {
peer->addpath_type[afi][safi] = conf->addpath_type[afi][safi];
bgp_addpath_type_changed(conf->bgp);
@@ -2898,7 +2912,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
int first_member = 0;
afi_t afi;
safi_t safi;
- bgp_peer_sort_t ptype, gtype;
+ enum bgp_peer_sort ptype, gtype;
/* Lookup the peer. */
if (!peer)
@@ -3766,7 +3780,7 @@ void bgp_free(struct bgp *bgp)
XFREE(MTYPE_BGP_EVPN_INFO, bgp->evpn_info);
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- vpn_policy_direction_t dir;
+ enum vpn_policy_direction dir;
if (bgp->vpn_policy[afi].import_vrf)
list_delete(&bgp->vpn_policy[afi].import_vrf);
@@ -4542,7 +4556,7 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
struct peer *member;
struct listnode *node, *nnode;
struct peer_flag_action action;
- bgp_peer_sort_t ptype;
+ enum bgp_peer_sort ptype;
memset(&action, 0, sizeof(struct peer_flag_action));
size = sizeof(peer_af_flag_action_list)
@@ -5909,7 +5923,7 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
- bgp_peer_sort_t ptype = peer_sort(peer);
+ enum bgp_peer_sort ptype = peer_sort(peer);
if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 360bcc39c4..dfed9f2ae9 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -192,11 +192,11 @@ struct bgp_redist {
struct bgp_rmap rmap;
};
-typedef enum {
+enum vpn_policy_direction {
BGP_VPN_POLICY_DIR_FROMVPN = 0,
BGP_VPN_POLICY_DIR_TOVPN = 1,
BGP_VPN_POLICY_DIR_MAX = 2
-} vpn_policy_direction_t;
+};
struct vpn_policy {
struct bgp *bgp; /* parent */
@@ -901,13 +901,13 @@ struct bgp_filter {
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
a peer who's AS is part of our Confederation. */
-typedef enum {
+enum bgp_peer_sort {
BGP_PEER_UNSPECIFIED,
BGP_PEER_IBGP,
BGP_PEER_EBGP,
BGP_PEER_INTERNAL,
BGP_PEER_CONFED,
-} bgp_peer_sort_t;
+};
/* BGP message header and packet size. */
#define BGP_MARKER_SIZE 16
@@ -1084,7 +1084,7 @@ struct peer {
/* Peer's local AS number. */
as_t local_as;
- bgp_peer_sort_t sort;
+ enum bgp_peer_sort sort;
/* Peer's Change local AS number. */
as_t change_local_as;
@@ -1968,12 +1968,12 @@ enum bgp_create_error_code {
/*
* Enumeration of different policy kinds a peer can be configured with.
*/
-typedef enum {
+enum bgp_policy_type {
BGP_POLICY_ROUTE_MAP,
BGP_POLICY_FILTER_LIST,
BGP_POLICY_PREFIX_LIST,
BGP_POLICY_DISTRIBUTE_LIST,
-} bgp_policy_type_e;
+};
/* peer_flag_change_type. */
enum peer_change_type {
@@ -2025,8 +2025,8 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *);
#define peer_unlock(A) peer_unlock_with_caller(__FUNCTION__, (A))
#define peer_lock(B) peer_lock_with_caller(__FUNCTION__, (B))
-extern bgp_peer_sort_t peer_sort(struct peer *peer);
-extern bgp_peer_sort_t peer_sort_lookup(struct peer *peer);
+extern enum bgp_peer_sort peer_sort(struct peer *peer);
+extern enum bgp_peer_sort peer_sort_lookup(struct peer *peer);
extern bool peer_active(struct peer *);
extern bool peer_active_nego(struct peer *);
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index c96c321d76..3aa8868374 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -832,9 +832,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
struct ecommunity *ecomm = bgp_attr_get_ecommunity(&attr);
- if (ecomm->size) {
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- } else {
+ if (!ecomm->size) {
ecommunity_free(&ecomm);
bgp_attr_set_ecommunity(&attr, NULL);
}
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index f4f2e11391..c479b4d65a 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -650,9 +650,6 @@ encap_attr_export(struct attr *new, struct attr *orig,
} else {
bgp_attr_set_ecommunity(new, ecom_ro);
}
- if (ecom_ro) {
- new->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- }
/*
* Set MED
diff --git a/configure.ac b/configure.ac
index c636fade70..0a6bdd1d73 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,7 +58,7 @@ elif test "$host" != "$build"; then
AC_MSG_NOTICE([...])
AC_MSG_NOTICE([... cross-compilation: creating hosttools directory and self-configuring for build platform tools])
- AC_MSG_NOTICE([... use HOST_CPPFLAGS / HOST_CFLAGS / HOST_LDFLAGS if neccessary])
+ AC_MSG_NOTICE([... use HOST_CPPFLAGS / HOST_CFLAGS / HOST_LDFLAGS if necessary])
AC_MSG_NOTICE([...])
(
@@ -330,7 +330,21 @@ LDFLAGS="$LDFLAGS -g"
AM_CONDITIONAL([DEV_BUILD], [test "$enable_dev_build" = "yes"])
+dnl -fms-extensions causes clang to have a built-in __wchar_t on OpenBSD,
+dnl which just straight up breaks compiling any code.
+dnl (2022-04-04 / OpenBSD 7 / clang 11.1.0)
+AH_VERBATIM([OpenBSD], [
+#ifdef __OpenBSD__
+#define __wchar_t __wchar_t_ignore
+#include <stdint.h>
+#undef __wchar_t
+#endif
+])
+
dnl always want these CFLAGS
+AC_C_FLAG([-fms-extensions], [
+ AC_MSG_ERROR([$CC does not support unnamed struct fields (-fms-extensions)])
+])
AC_C_FLAG([-fno-omit-frame-pointer])
AC_C_FLAG([-funwind-tables])
AC_C_FLAG([-Wall])
diff --git a/debian/changelog b/debian/changelog
index 2b28c4c6dc..f3e42199de 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -989,7 +989,7 @@ quagga (0.98.3-6) testing-proposed-updates; urgency=high
quagga (0.98.3-5) unstable; urgency=high
* The patch which tried to remove the OpenSSL dependency, which is
- not only unneccessary but also a violation of the licence and thus RC,
+ not only unnecessary but also a violation of the licence and thus RC,
stopped working a while ago, since autoreconf is no longer run before
building the binaries. So now ./configure is patched directly (thanks
to Faidon Liambotis for reporting). Closes: #306840
@@ -1370,7 +1370,7 @@ quagga (0.96.4x-3) unstable; urgency=low
* Made the directory (but not the config/log files!) world accessible
again on user request (thanks to Anand Kumria)). Closes: #213129
* No longer providing sample configuration in /etc/quagga/. They are
- now only available in /usr/share/doc/quagga/ to avoid accidently
+ now only available in /usr/share/doc/quagga/ to avoid accidentally
using them without changing the adresses (thanks to Marc Haber).
Closes: #215918
@@ -1430,7 +1430,7 @@ quagga (0.96.3-1) unstable; urgency=medium
quagga (0.96.2-9) unstable; urgency=medium
- * Removed /usr/share/info/dir.* which were accidently there and prevented
+ * Removed /usr/share/info/dir.* which were accidentally there and prevented
the installation by dpkg (thanks to Simon Raven). Closes: #212614
* Reworded package description (thanks to Anand Kumria). Closes: #213125
* Added french debconf translation (thanks to Christian Perrier).
diff --git a/debian/frr.logrotate b/debian/frr.logrotate
index a56a908bdf..1e0e726cb4 100644
--- a/debian/frr.logrotate
+++ b/debian/frr.logrotate
@@ -4,7 +4,7 @@
missingok
compress
rotate 14
- create 640 frr frrvty
+ create 0640 frr frr
postrotate
pid=$(lsof -t -a -c /syslog/ /var/log/frr/* 2>/dev/null)
@@ -17,7 +17,7 @@
# open, as well as the daemons, so always signal the daemons.
# It's safe, a NOP if (only) syslog is being used.
for i in babeld bgpd eigrpd isisd ldpd nhrpd ospf6d ospfd sharpd \
- pimd ripd ripngd zebra pbrd staticd bfdd fabricd vrrpd; do
+ pimd ripd ripngd zebra pathd pbrd staticd bfdd fabricd vrrpd; do
if [ -e /var/run/frr/$i.pid ] ; then
pids="$pids $(cat /var/run/frr/$i.pid)"
fi
diff --git a/debian/frr.postinst b/debian/frr.postinst
index 505ff8eaf8..4e23cd3cec 100644
--- a/debian/frr.postinst
+++ b/debian/frr.postinst
@@ -16,7 +16,7 @@ adduser \
frr
usermod -a -G frrvty frr
-mkdir -p /var/log/frr
+mkdir -m 0755 -p /var/log/frr
mkdir -p /etc/frr
diff --git a/debian/frr.preinst b/debian/frr.preinst
index 0e10e39247..2af5a4ed8f 100644
--- a/debian/frr.preinst
+++ b/debian/frr.preinst
@@ -73,6 +73,7 @@ EOF
-o -f /etc/frr/eigrpd.conf \
-o -f /etc/frr/babeld.conf \
-o -f /etc/frr/pbrd.conf \
+ -o -f /etc/frr/pathd.conf \
-o -f /etc/frr/bfdd.conf; then
# no explicit statement, but some split config file exists
# => need to fix vtysh.conf & frr.conf in postinst
diff --git a/doc/developer/building-frr-for-fedora.rst b/doc/developer/building-frr-for-fedora.rst
index dc869ece10..aa10f1118d 100644
--- a/doc/developer/building-frr-for-fedora.rst
+++ b/doc/developer/building-frr-for-fedora.rst
@@ -81,7 +81,7 @@ content:
MPLS must be invidividually enabled on each interface that requires it. See
the example in the config block above.
-Load the modifed sysctls on the system:
+Load the modified sysctls on the system:
.. code-block:: console
diff --git a/doc/developer/building-frr-for-opensuse.rst b/doc/developer/building-frr-for-opensuse.rst
index d9800a1638..38346fe881 100644
--- a/doc/developer/building-frr-for-opensuse.rst
+++ b/doc/developer/building-frr-for-opensuse.rst
@@ -85,7 +85,7 @@ content:
MPLS must be invidividually enabled on each interface that requires it. See
the example in the config block above.
-Load the modifed sysctls on the system:
+Load the modified sysctls on the system:
.. code-block:: console
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index 4eaa85115e..ccac10aab9 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -62,7 +62,7 @@ in the future:
The APIs are all designed to be as type-safe as possible. This means that
there will be a compiler warning when an item doesn't match the container, or
the return value has a different type, or other similar situations. **You
-should never use casts with these APIs.** If a cast is neccessary in relation
+should never use casts with these APIs.** If a cast is necessary in relation
to these APIs, there is probably something wrong with the overall design.
Only the following pieces use dynamically allocated memory:
@@ -143,7 +143,7 @@ Each of the data structures has a ``PREDECL_*`` and a ``DECLARE_*`` macro to
set up an "instantiation" of the container. This works somewhat similar to C++
templating, though much simpler.
-**In all following text, the Z prefix is replaced with a name choosen
+**In all following text, the Z prefix is replaced with a name chosen
for the instance of the datastructure.**
The common setup pattern will look like this:
@@ -650,7 +650,7 @@ Atomic lists
`atomlist.h` provides an unsorted and a sorted atomic single-linked list.
Since atomic memory accesses can be considerably slower than plain memory
accessses (depending on the CPU type), these lists should only be used where
-neccessary.
+necessary.
The following guarantees are provided regarding concurrent access:
diff --git a/doc/developer/static-linking.rst b/doc/developer/static-linking.rst
index 1e45c48dc3..5342fbfbf6 100644
--- a/doc/developer/static-linking.rst
+++ b/doc/developer/static-linking.rst
@@ -64,7 +64,7 @@ like this:
Hopefully you get a nice, usable, PIC ``libpcre.a``.
So now we have to link all these static libraries into FRR. Rather than modify
-FRR to accomodate this, the best option is to create an archive with all of
+FRR to accommodate this, the best option is to create an archive with all of
libyang's dependencies. Then to avoid making any changes to FRR build foo,
rename this ``libyang.a`` and copy it over the usual static library location.
Ugly but it works. To do this, go into your libyang build directory, which
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index af8756a909..adab9725d9 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -623,6 +623,8 @@ Please copy-paste this header verbatim. In particular:
- Do not replace "This program" with "FRR"
- Do not change the address of the FSF
+- keep ``#include <zebra.h>``. The absolute first header included in any C
+ file **must** be either ``zebra.h`` or ``config.h`` (with HAVE_CONFIG_H guard)
Adding Copyright Claims to Existing Files
-----------------------------------------
@@ -895,6 +897,26 @@ necessary replacements.
| u_long | unsigned long |
+-----------+--------------------------+
+FRR also uses unnamed struct fields, enabled with ``-fms-extensions`` (cf.
+https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html). The following two
+patterns can/should be used where contextually appropriate:
+
+.. code-block:: c
+
+ struct outer {
+ struct inner;
+ };
+
+.. code-block:: c
+
+ struct outer {
+ union {
+ struct inner;
+ struct inner inner_name;
+ };
+ };
+
+
.. _style-exceptions:
Exceptions
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index ea4b3f41f3..42faefd10b 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -471,7 +471,7 @@ recommendations apply in regards to upgrades:
for differences against your old configuration. If any defaults changed
that affect your setup, lines may appear or disappear. If a new line
appears, it was previously the default (or not supported) and is now
- neccessary to retain previous behavior. If a line disappears, it
+ necessary to retain previous behavior. If a line disappears, it
previously wasn't the default, but now is, so it is no longer necessary.
3. Check the log files for deprecation warnings by using ``grep -i deprecat``.
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index 14aacc0f6b..c47ed04f63 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -236,7 +236,7 @@ BFD Peer Specific Commands
Notes:
- - Profile configurations can be overriden on a peer basis by specifying
+ - Profile configurations can be overridden on a peer basis by specifying
non-default parameters in peer configuration node.
- Non existing profiles can be configured and they will only be applied
once they start to exist.
diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst
index e71cf4631c..f0946a13f7 100644
--- a/doc/user/pimv6.rst
+++ b/doc/user/pimv6.rst
@@ -113,6 +113,14 @@ Certain signals have special meanings to *pim6d*.
notifications to the kernel. This command is vrf aware, to configure for a
vrf, enter the vrf submode.
+.. clicmd:: ipv6 ssmpingd [X:X::X:X]
+
+ Enable ipv6 ssmpingd configuration. A network level management tool
+ to check whether one can receive multicast packets via SSM from host.
+ The host target given to ssmping must run the ssmpingd daemon which listens
+ for IPv4 and IPv6 unicast requests. When it receives one, it responds to a
+ well known SSM multicast group which ssmping just have joined.
+
.. _pimv6-interface-configuration:
PIMv6 Interface Configuration
diff --git a/doc/user/scripting.rst b/doc/user/scripting.rst
index badc82c500..42855de1ab 100644
--- a/doc/user/scripting.rst
+++ b/doc/user/scripting.rst
@@ -58,7 +58,7 @@ The documentation for :ref:`on-rib-process-dplane-results` tells us its
arguments. Here, the destination prefix for a route is being logged out.
Scripts live in :file:`/etc/frr/scripts/` by default. This is configurable at
-compile time via ``--with-scriptdir``. It may be overriden at runtime with the
+compile time via ``--with-scriptdir``. It may be overridden at runtime with the
``--scriptdir`` daemon option.
The documentation for :ref:`on-rib-process-dplane-results` indicates that the
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index cd220a4141..29f305520a 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -283,6 +283,17 @@ the default route.
Allow IPv6 nexthop tracking to resolve via the default route. This parameter
is configured per-VRF, so the command is also available in the VRF subnode.
+.. clicmd:: show ip nht [vrf NAME] [A.B.C.D|X:X::X:X] [mrib]
+
+ Show nexthop tracking status for address resolution. If vrf is not specified
+ then display the default vrf. If ``all`` is specified show all vrf address
+ resolution output. If an ipv4 or ipv6 address is not specified then display
+ all addresses tracked, else display the requested address. The mrib keyword
+ indicates that the operator wants to see the multicast rib address resolution
+ table. An alternative form of the command is ``show ip import-check`` and this
+ form of the command is deprecated at this point in time.
+
+
Administrative Distance
=======================
@@ -290,7 +301,7 @@ Administrative distance allows FRR to make decisions about what routes
should be installed in the rib based upon the originating protocol.
The lowest Admin Distance is the route selected. This is purely a
subjective decision about ordering and care has been taken to choose
-the same distances that other routing suites have choosen.
+the same distances that other routing suites have chosen.
+------------+-----------+
| Protocol | Distance |
@@ -350,7 +361,7 @@ has multiple routes for the same prefix from multiple sources. An example
here would be if someone else was running another routing suite besides
FRR at the same time, the kernel must choose what route to use to forward
on. FRR choose the value of 20 because of two reasons. FRR wanted a
-value small enough to be choosen but large enough that the operator could
+value small enough to be chosen but large enough that the operator could
allow route prioritization by the kernel when multiple routing suites are
being run and FRR wanted to take advantage of Route Replace semantics that
the linux kernel offers. In order for Route Replacement semantics to
@@ -541,7 +552,7 @@ via a ``ip route show X`` command:
nexthop via 192.168.161.9 dev enp39s0 weight 1
Once installed into the FIB, FRR currently has little control over what
-nexthops are choosen to forward packets on. Currently the Linux kernel
+nexthops are chosen to forward packets on. Currently the Linux kernel
has a ``fib_multipath_hash_policy`` sysctl which dictates how the hashing
algorithm is used to forward packets.
@@ -1182,7 +1193,7 @@ zebra Terminal Mode Commands
Display statistics about clients that are connected to zebra. This is
useful for debugging and seeing how much data is being passed between
- zebra and it's clients. If the summary form of the command is choosen
+ zebra and it's clients. If the summary form of the command is chosen
a table is displayed with shortened information.
.. clicmd:: show zebra router table summary
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 2729dce382..11f17ec7bf 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -31,6 +31,7 @@
#include "thread.h"
#include "if.h"
#include "stream.h"
+#include "bfd.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
@@ -814,6 +815,15 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, " %s\n", buf);
}
}
+ if (adj->circuit && adj->circuit->bfd_config.enabled) {
+ vty_out(vty, " BFD is %s%s\n",
+ adj->bfd_session ? "active, status "
+ : "configured",
+ !adj->bfd_session
+ ? ""
+ : bfd_get_status_str(bfd_sess_status(
+ adj->bfd_session)));
+ }
for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
const char *adj_type;
const char *backup;
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index c7bf1e2012..fedceed3bb 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -661,8 +661,11 @@ int isis_circuit_up(struct isis_circuit *circuit)
"Interface MTU %zu on %s is too low to support area lsp mtu %u!",
isis_circuit_pdu_size(circuit),
circuit->interface->name, circuit->area->lsp_mtu);
- isis_circuit_update_all_srmflags(circuit, 0);
- return ISIS_ERROR;
+
+ /* Allow ISIS to continue configuration. With this
+ * configuration failure ISIS will attempt to send lsp
+ * packets but will fail until the mtu is configured properly
+ */
}
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c
index 78197974d7..27b7388072 100644
--- a/isisd/isis_dr.c
+++ b/isisd/isis_dr.c
@@ -217,7 +217,8 @@ int isis_dr_resign(struct isis_circuit *circuit, int level)
{
uint8_t id[ISIS_SYS_ID_LEN + 2];
- zlog_debug("isis_dr_resign l%d", level);
+ if (IS_DEBUG_EVENTS)
+ zlog_debug("isis_dr_resign l%d", level);
circuit->u.bc.is_dr[level - 1] = 0;
circuit->u.bc.run_dr_elect[level - 1] = 0;
diff --git a/isisd/isis_ldp_sync.c b/isisd/isis_ldp_sync.c
index 3c68b8d15f..fb605eb07a 100644
--- a/isisd/isis_ldp_sync.c
+++ b/isisd/isis_ldp_sync.c
@@ -479,9 +479,9 @@ void isis_if_ldp_sync_enable(struct isis_circuit *circuit)
struct isis_area *area = circuit->area;
/* called when setting LDP-SYNC at the global level:
- * specifed on interface overrides global config
+ * specified on interface overrides global config
* if ptop link send msg to LDP indicating ldp-sync enabled
- */
+ */
if (if_is_loopback(circuit->interface))
return;
@@ -541,7 +541,7 @@ void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit)
struct isis_area *area = circuit->area;
/* called when setting LDP-SYNC at the global level:
- * specifed on interface overrides global config.
+ * specified on interface overrides global config.
*/
if (if_is_loopback(circuit->interface))
return;
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index de7797813a..cf4c2aea0a 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -393,30 +393,11 @@ int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args)
*/
int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args)
{
- struct listnode *node;
- struct isis_circuit *circuit;
uint16_t lsp_mtu = yang_dnode_get_uint16(args->dnode, NULL);
struct isis_area *area;
switch (args->event) {
case NB_EV_VALIDATE:
- area = nb_running_get_entry(args->dnode, NULL, false);
- if (!area)
- break;
- for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
- if (circuit->state != C_STATE_INIT
- && circuit->state != C_STATE_UP)
- continue;
- if (lsp_mtu > isis_circuit_pdu_size(circuit)) {
- snprintf(
- args->errmsg, args->errmsg_len,
- "ISIS area contains circuit %s, which has a maximum PDU size of %zu",
- circuit->interface->name,
- isis_circuit_pdu_size(circuit));
- return NB_ERR_VALIDATION;
- }
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
@@ -2552,43 +2533,14 @@ int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args)
*/
int lib_interface_isis_create(struct nb_cb_create_args *args)
{
- struct isis_area *area = NULL;
struct interface *ifp;
struct isis_circuit *circuit = NULL;
const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
- uint32_t min_mtu, actual_mtu;
switch (args->event) {
case NB_EV_PREPARE:
case NB_EV_ABORT:
- break;
case NB_EV_VALIDATE:
- /* check if interface mtu is sufficient. If the area has not
- * been created yet, assume default MTU for the area
- */
- ifp = nb_running_get_entry(args->dnode, NULL, false);
- /* zebra might not know yet about the MTU - nothing we can do */
- if (!ifp || ifp->mtu == 0)
- break;
- actual_mtu =
- if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
-
- area = isis_area_lookup(area_tag, ifp->vrf->vrf_id);
- if (area)
- min_mtu = area->lsp_mtu;
- else
-#ifndef FABRICD
- min_mtu = yang_get_default_uint16(
- "/frr-isisd:isis/instance/lsp/mtu");
-#else
- min_mtu = DEFAULT_LSP_MTU;
-#endif /* ifndef FABRICD */
- if (actual_mtu < min_mtu) {
- snprintf(args->errmsg, args->errmsg_len,
- "Interface %s has MTU %u, minimum MTU for the area is %u",
- ifp->name, actual_mtu, min_mtu);
- return NB_ERR_VALIDATION;
- }
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 1a54d47f3c..016efd5cd7 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -2103,7 +2103,7 @@ void send_hello_sched(struct isis_circuit *circuit, int level, long delay)
/*
- * Count the maximum number of lsps that can be accomodated by a given size.
+ * Count the maximum number of lsps that can be accommodated by a given size.
*/
#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN)
static uint16_t get_max_lsp_count(uint16_t size)
diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h
index b2e43781f6..b4018995d5 100644
--- a/isisd/isis_pdu.h
+++ b/isisd/isis_pdu.h
@@ -142,7 +142,7 @@ struct isis_lsp_hdr {
/*
* Since the length field of LSP Entries TLV is one byte long, and each LSP
* entry is LSP_ENTRIES_LEN (16) bytes long, the maximum number of LSP entries
- * can be accomodated in a TLV is
+ * can be accommodated in a TLV is
* 255 / 16 = 15.
*
* Therefore, the maximum length of the LSP Entries TLV is
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index 764a0b0cd3..9f8f639e5d 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -443,7 +443,7 @@ void isis_route_delete(struct isis_area *area, struct route_node *rode,
if (rinfo == NULL) {
if (IS_DEBUG_RTE_EVENTS)
zlog_debug(
- "ISIS-Rte: tried to delete non-existant route %s",
+ "ISIS-Rte: tried to delete non-existent route %s",
buff);
return;
}
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index d3d59fb435..3ba5c6ccfa 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -22,8 +22,9 @@
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
-#include <json-c/json_object.h>
+
#include <zebra.h>
+#include <json-c/json_object.h>
#ifdef CRYPTO_INTERNAL
#include "md5.h"
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index a78d2b25d6..796cf11798 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -1790,7 +1790,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
previous_pw_type = l2vpn->pw_type;
previous_mtu = l2vpn->mtu;
- /* merge intefaces */
+ /* merge interfaces */
RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
/* find deleted interfaces */
if (l2vpn_if_find(xl, lif->ifname) == NULL) {
diff --git a/lib/atomlist.c b/lib/atomlist.c
index b7c9516a00..2631d4fa78 100644
--- a/lib/atomlist.c
+++ b/lib/atomlist.c
@@ -267,7 +267,7 @@ static void atomsort_del_core(struct atomsort_head *h,
memory_order_consume);
/* track the beginning of a chain of deleted items
- * this is neccessary to make this lock-free; we can
+ * this is necessary to make this lock-free; we can
* complete deletions started by other threads.
*/
if (!atomptr_l(prevval)) {
diff --git a/lib/base64.c b/lib/base64.c
index e3f238969b..6f0be039f1 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -3,6 +3,10 @@
* For details, see http://sourceforge.net/projects/libb64
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "base64.h"
static const int CHARS_PER_LINE = 72;
diff --git a/lib/command_py.c b/lib/command_py.c
index 90344ae1e5..6301eec5e8 100644
--- a/lib/command_py.c
+++ b/lib/command_py.c
@@ -28,6 +28,9 @@
* setup & these trample over each other.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <Python.h>
#include "structmember.h"
#include <string.h>
diff --git a/lib/elf_py.c b/lib/elf_py.c
index 5289faece4..75d2d6007f 100644
--- a/lib/elf_py.c
+++ b/lib/elf_py.c
@@ -50,10 +50,10 @@
#define PY_SSIZE_T_CLEAN
-#include <Python.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <Python.h>
#include "structmember.h"
#include <string.h>
#include <stdlib.h>
diff --git a/lib/plist.c b/lib/plist.c
index e7647fb2a7..d8ef9dcbd5 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1568,8 +1568,10 @@ static void prefix_list_reset_afi(afi_t afi, int orf)
if (master == NULL)
return;
- while ((plist = plist_pop(&master->str)))
+ while ((plist = plist_first(&master->str))) {
prefix_list_delete(plist);
+ plist_pop(&master->str);
+ }
master->recent = NULL;
}
diff --git a/lib/privs.c b/lib/privs.c
index b3f51267d1..24a15a0c0b 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -684,7 +684,7 @@ void zprivs_init(struct zebra_privs_t *zprivs)
#else /* !HAVE_CAPABILITIES */
/* we dont have caps. we'll need to maintain rid and saved uid
- * and change euid back to saved uid (who we presume has all neccessary
+ * and change euid back to saved uid (who we presume has all necessary
* privileges) whenever we are asked to raise our privileges.
*
* This is not worth that much security wise, but all we can do.
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 77639070c9..a82273a6dc 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -3,7 +3,7 @@
# Used to construct route_types.c and route_types.h
#
# comma-seperated fields of either 2 fields (help strings) or 7 fields.
-# White space before and after the comma seperators is stripped.
+# White space before and after the comma separators is stripped.
# Lines /beginning/ with # are comments.
#
####
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index 5597064d20..315007be1c 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -1434,41 +1434,6 @@ void route_map_optimization_disabled_show(struct vty *vty,
name);
}
-#if CONFDATE > 20220409
-CPP_NOTICE("Time to remove old route-map optimization command")
-#endif
-
-DEFPY_HIDDEN(
- routemap_optimization, routemap_optimization_cmd,
- "[no] route-map optimization",
- NO_STR
- "route-map\n"
- "optimization\n")
-{
- const struct lyd_node *rmi_dnode;
- const char *rm_name;
- char xpath[XPATH_MAXLEN];
-
- vty_out(vty,
- "%% This command is deprecated. Please, use `route-map NAME optimization` from the config node.\n");
-
- rmi_dnode =
- yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
- if (!rmi_dnode) {
- vty_out(vty, "%% Failed to get RMI dnode in candidate DB\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- rm_name = yang_dnode_get_string(rmi_dnode, "../name");
-
- snprintf(
- xpath, sizeof(xpath),
- "/frr-route-map:lib/route-map[name='%s']/optimization-disabled",
- rm_name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false");
- return nb_cli_apply_changes(vty, NULL);
-}
-
static int route_map_config_write(struct vty *vty)
{
const struct lyd_node *dnode;
@@ -1587,6 +1552,4 @@ void route_map_cli_init(void)
install_element(RMAP_NODE, &set_srte_color_cmd);
install_element(RMAP_NODE, &no_set_srte_color_cmd);
-
- install_element(RMAP_NODE, &routemap_optimization_cmd);
}
diff --git a/lib/subdir.am b/lib/subdir.am
index d1df9cb3d9..c3899c4e0f 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -588,7 +588,7 @@ DISTCLEANFILES += lib/route_types.h
if GIT_VERSION
# bit of a trick here to always have up-to-date git stamps without triggering
-# unneccessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
+# unnecessary rebuilds. .PHONY causes the .tmp file to be rebuilt always,
# but if we use that on gitversion.h it'll ripple through the .c file deps.
# (even if gitversion.h's file timestamp doesn't change, make will think it
# did, because of .PHONY...)
diff --git a/nhrpd/linux.c b/nhrpd/linux.c
index 4986bfb99c..75e9f37a68 100644
--- a/nhrpd/linux.c
+++ b/nhrpd/linux.c
@@ -7,8 +7,9 @@
* (at your option) any later version.
*/
-#include <errno.h>
#include "zebra.h"
+
+#include <errno.h>
#include <linux/if_packet.h>
#include "nhrp_protocol.h"
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index cc82084e5e..bc9e2c3405 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -878,6 +878,28 @@ static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa,
return 0;
}
+static bool ospf6_lsa_check_min_arrival(struct ospf6_lsa *lsa,
+ struct ospf6_neighbor *from)
+{
+ struct timeval now, res;
+ unsigned int time_delta_ms;
+
+ monotime(&now);
+ timersub(&now, &lsa->installed, &res);
+ time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
+
+ if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) {
+ if (IS_OSPF6_DEBUG_FLOODING ||
+ IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
+ zlog_debug(
+ "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
+ time_delta_ms,
+ from->ospf6_if->area->ospf6->lsa_minarrival);
+ return true;
+ }
+ return false;
+}
+
/* RFC2328 section 13 The Flooding Procedure */
void ospf6_receive_lsa(struct ospf6_neighbor *from,
struct ospf6_lsa_header *lsa_header)
@@ -885,7 +907,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
int ismore_recent;
int is_debug = 0;
- unsigned int time_delta_ms;
ismore_recent = 1;
assert(from);
@@ -993,19 +1014,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
/* (a) MinLSArrival check */
if (old) {
- struct timeval now, res;
- monotime(&now);
- timersub(&now, &old->installed, &res);
- time_delta_ms =
- (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
- if (time_delta_ms
- < from->ospf6_if->area->ospf6->lsa_minarrival) {
- if (is_debug)
- zlog_debug(
- "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
- time_delta_ms,
- from->ospf6_if->area->ospf6
- ->lsa_minarrival);
+ if (ospf6_lsa_check_min_arrival(old, from)) {
ospf6_lsa_delete(new);
return; /* examin next lsa */
}
@@ -1222,7 +1231,11 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
__PRETTY_FUNCTION__, old->name);
}
- /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
+ /* MinLSArrival check as per RFC 2328 13 (8) */
+ if (ospf6_lsa_check_min_arrival(old, from)) {
+ ospf6_lsa_delete(new);
+ return; /* examin next lsa */
+ }
ospf6_lsdb_add(ospf6_lsa_copy(old),
from->lsupdate_list);
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index b9ee3c3403..55f1a1c7b5 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -158,7 +158,7 @@ static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
ospf6 = oi->interface->vrf->info;
refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
- /* A specifed ip ospf cost overrides a calculated one. */
+ /* A specified ip ospf cost overrides a calculated one. */
if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
cost = oi->cost;
else {
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 07c331af64..a3a4d5bb9f 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -71,7 +71,7 @@ extern struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
* Since we are locking the lsa in ospf6_lsdb_head
* and then unlocking it in ospf6_lsa_unlock, when
* we cache the next pointer we need to increment
- * the lock for the lsa so we don't accidently free
+ * the lock for the lsa so we don't accidentally free
* it really early.
*/
#define ALL_LSDB(lsdb, lsa, lsanext) \
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 2626cccc37..5df2ecf070 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -102,7 +102,7 @@ int ospf_if_get_output_cost(struct ospf_interface *oi)
: OSPF_DEFAULT_BANDWIDTH;
refbw = oi->ospf->ref_bandwidth;
- /* A specifed ip ospf cost overrides a calculated one. */
+ /* A specified ip ospf cost overrides a calculated one. */
if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), output_cost_cmd)
|| OSPF_IF_PARAM_CONFIGURED(oi->params, output_cost_cmd))
cost = OSPF_IF_PARAM(oi, output_cost_cmd);
diff --git a/ospfd/ospf_ldp_sync.c b/ospfd/ospf_ldp_sync.c
index f6c1b43610..b4d770d48a 100644
--- a/ospfd/ospf_ldp_sync.c
+++ b/ospfd/ospf_ldp_sync.c
@@ -141,7 +141,7 @@ void ospf_ldp_sync_if_init(struct ospf_interface *oi)
ldp_sync_info = params->ldp_sync_info;
- /* specifed on interface overrides global config. */
+ /* specified on interface overrides global config. */
if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
ldp_sync_info->holddown = oi->ospf->ldp_sync_cmd.holddown;
@@ -441,7 +441,7 @@ void ospf_if_set_ldp_sync_enable(struct ospf *ospf, struct interface *ifp)
struct ldp_sync_info *ldp_sync_info;
/* called when setting LDP-SYNC at the global level:
- * specifed on interface overrides global config
+ * specified on interface overrides global config
* if ptop link send msg to LDP indicating ldp-sync enabled
*/
if (if_is_loopback(ifp))
@@ -479,7 +479,7 @@ void ospf_if_set_ldp_sync_holddown(struct ospf *ospf, struct interface *ifp)
struct ldp_sync_info *ldp_sync_info;
/* called when setting LDP-SYNC at the global level:
- * specifed on interface overrides global config.
+ * specified on interface overrides global config.
*/
if (if_is_loopback(ifp))
return;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 3ad7ca7d1b..59e1b73d24 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -450,7 +450,7 @@ char link_info_set(struct stream **s, struct in_addr id, struct in_addr data,
/* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits
* vast majority of cases. Some rare routers with lots of links need
* more.
- * we try accomodate those here.
+ * we try accommodate those here.
*/
if (STREAM_WRITEABLE(*s) < OSPF_ROUTER_LSA_LINK_SIZE) {
size_t ret = OSPF_MAX_LSA_SIZE;
@@ -2858,7 +2858,7 @@ struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi,
update is needed */
old = ospf_lsdb_lookup(lsdb, lsa);
- /* Do comparision and record if recalc needed. */
+ /* Do comparison and record if recalc needed. */
rt_recalc = 0;
if (old == NULL || ospf_lsa_different(old, lsa, false)) {
/* Ref rfc3623 section 3.2.3
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index c2bd7a0796..55a010a293 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -3515,7 +3515,7 @@ static int ospf_make_ls_req_func(struct stream *s, uint16_t *length,
/* LS Request packet overflows interface MTU
* delta is just number of bytes required for 1 LS Req
* ospf_packet_max will return the number of bytes can
- * be accomodated without ospf header. So length+delta
+ * be accommodated without ospf header. So length+delta
* can be compared to ospf_packet_max
* to check if it can fit another lsreq in the same packet.
*/
@@ -3601,7 +3601,7 @@ static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update,
zlog_debug("%s: List Iteration %d LSA[%s]", __func__,
count, dump_lsa_key(lsa));
- /* Will it fit? Minimum it has to fit atleast one */
+ /* Will it fit? Minimum it has to fit at least one */
if ((length + delta + ntohs(lsa->data->length) > size_noauth) &&
(count > 0))
break;
@@ -3649,7 +3649,7 @@ static int ospf_make_ls_ack(struct ospf_interface *oi, struct list *ack,
/* LS Ack packet overflows interface MTU
* delta is just number of bytes required for
* 1 LS Ack(1 LS Hdr) ospf_packet_max will return
- * the number of bytes can be accomodated without
+ * the number of bytes can be accommodated without
* ospf header. So length+delta can be compared
* against ospf_packet_max to check if it can fit
* another ls header in the same packet.
@@ -3966,7 +3966,7 @@ void ospf_ls_upd_send_lsa(struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
list_delete(&update);
}
-/* Determine size for packet. Must be at least big enough to accomodate next
+/* Determine size for packet. Must be at least big enough to accommodate next
* LSA on list, which may be bigger than MTU size.
*
* Return pointer to new ospf_packet
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index f763400212..baf02365a2 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -678,7 +678,7 @@ static void ospf_spf_flush_parents(struct vertex *w)
/*
* Consider supplied next-hop for inclusion to the supplied list of
- * equal-cost next-hops, adjust list as neccessary.
+ * equal-cost next-hops, adjust list as necessary.
*/
static void ospf_spf_add_parent(struct vertex *v, struct vertex *w,
struct vertex_nexthop *newhop,
diff --git a/pathd/path_ted.c b/pathd/path_ted.c
index 7477444104..270c664daf 100644
--- a/pathd/path_ted.c
+++ b/pathd/path_ted.c
@@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include "stdlib.h"
-
#include <zebra.h>
+#include <stdlib.h>
+
#include "memory.h"
#include "log.h"
#include "command.h"
diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c
index 5d7a63372f..ce26f912f4 100644
--- a/pimd/pim6_cmd.c
+++ b/pimd/pim6_cmd.c
@@ -170,7 +170,7 @@ DEFPY (ipv6_pim_rp_keep_alive,
"ipv6 pim rp keep-alive-timer (1-65535)$kat",
IPV6_STR
PIM_STR
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"Keep alive Timer\n"
"Seconds\n")
{
@@ -183,7 +183,7 @@ DEFPY (no_ipv6_pim_rp_keep_alive,
NO_STR
IPV6_STR
PIM_STR
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"Keep alive Timer\n"
IGNORED_IN_NO_STR)
{
@@ -451,6 +451,33 @@ DEFPY (no_ipv6_pim_rp_prefix_list,
return pim_process_no_rp_plist_cmd(vty, rp_str, plist);
}
+
+DEFPY (ipv6_ssmpingd,
+ ipv6_ssmpingd_cmd,
+ "ipv6 ssmpingd [X:X::X:X]$source",
+ IPV6_STR
+ CONF_SSMPINGD_STR
+ "Source address\n")
+{
+ const char *src_str = (source_str) ? source_str : "::";
+
+ return pim_process_ssmpingd_cmd(vty, NB_OP_CREATE, src_str);
+}
+
+
+DEFPY (no_ipv6_ssmpingd,
+ no_ipv6_ssmpingd_cmd,
+ "no ipv6 ssmpingd [X:X::X:X]$source",
+ NO_STR
+ IPV6_STR
+ CONF_SSMPINGD_STR
+ "Source address\n")
+{
+ const char *src_str = (source_str) ? source_str : "::";
+
+ return pim_process_ssmpingd_cmd(vty, NB_OP_DESTROY, src_str);
+}
+
DEFPY (interface_ipv6_mld_join,
interface_ipv6_mld_join_cmd,
"ipv6 mld join X:X::X:X$group [X:X::X:X$source]",
@@ -1588,6 +1615,10 @@ void pim_cmd_init(void)
install_element(VRF_NODE, &ipv6_pim_rp_prefix_list_cmd);
install_element(CONFIG_NODE, &no_ipv6_pim_rp_prefix_list_cmd);
install_element(VRF_NODE, &no_ipv6_pim_rp_prefix_list_cmd);
+ install_element(CONFIG_NODE, &ipv6_ssmpingd_cmd);
+ install_element(VRF_NODE, &ipv6_ssmpingd_cmd);
+ install_element(CONFIG_NODE, &no_ipv6_ssmpingd_cmd);
+ install_element(VRF_NODE, &no_ipv6_ssmpingd_cmd);
install_element(INTERFACE_NODE, &interface_ipv6_mld_cmd);
install_element(INTERFACE_NODE, &interface_no_ipv6_mld_cmd);
install_element(INTERFACE_NODE, &interface_ipv6_mld_join_cmd);
diff --git a/pimd/pim6_cmd.h b/pimd/pim6_cmd.h
index ac5eb3f9bf..d6853a7410 100644
--- a/pimd/pim6_cmd.h
+++ b/pimd/pim6_cmd.h
@@ -43,6 +43,7 @@
#define DEBUG_MLD_EVENTS_STR "MLD protocol events\n"
#define DEBUG_MLD_PACKETS_STR "MLD protocol packets\n"
#define DEBUG_MLD_TRACE_STR "MLD internal daemon activity\n"
+#define CONF_SSMPINGD_STR "Enable ssmpingd operation\n"
void pim_cmd_init(void);
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index cbd44388c1..7d924d6505 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -34,6 +34,7 @@
#include "pim_hello.h"
#include "pim_macro.h"
#include "pim_assert.h"
+#include "pim_zebra.h"
#include "pim_ifchannel.h"
static int assert_action_a3(struct pim_ifchannel *ch);
@@ -50,6 +51,8 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
int winner_changed = !!pim_addr_cmp(ch->ifassert_winner, winner);
int metric_changed = !pim_assert_metric_match(
&ch->ifassert_winner_metric, &winner_metric);
+ enum pim_rpf_result rpf_result;
+ struct pim_rpf old_rpf;
if (PIM_DEBUG_PIM_EVENTS) {
if (ch->ifassert_state != new_state) {
@@ -74,6 +77,22 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
ch->ifassert_creation = pim_time_monotonic_sec();
if (winner_changed || metric_changed) {
+ if (winner_changed) {
+ old_rpf.source_nexthop.interface =
+ ch->upstream->rpf.source_nexthop.interface;
+ rpf_result = pim_rpf_update(pim_ifp->pim, ch->upstream,
+ &old_rpf, __func__);
+ if (rpf_result == PIM_RPF_CHANGED ||
+ (rpf_result == PIM_RPF_FAILURE &&
+ old_rpf.source_nexthop.interface))
+ pim_zebra_upstream_rpf_changed(
+ pim_ifp->pim, ch->upstream, &old_rpf);
+ /* update kernel multicast forwarding cache (MFC) */
+ if (ch->upstream->rpf.source_nexthop.interface &&
+ ch->upstream->channel_oil)
+ pim_upstream_mroute_iif_update(
+ ch->upstream->channel_oil, __func__);
+ }
pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
pim_ifchannel_update_could_assert(ch);
pim_ifchannel_update_assert_tracking_desired(ch);
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 0e91773be7..003ce47432 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -849,9 +849,9 @@ static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
this_pkt_rem = pim_mtu - (PIM_BSM_HDR_LEN
+ PIM_MSG_HEADER_LEN);
- /* If pkt can't accomodate next group + atleast
- * one rp, we must break out of this inner loop
- * and process next RP
+ /* If pkt can't accommodate next group + at
+ * least one rp, we must break out of this inner
+ * loop and process next RP
*/
if (total_rp_cnt == this_rp_cnt)
break;
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 78fc975787..9d95408cbe 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1523,7 +1523,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
else
vty_out(vty,
- "Interface Address Group Source Timer Fwd Uptime \n");
+ "Interface Group Source Timer Fwd Uptime \n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -4065,8 +4065,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
json_object_boolean_true_add(
json_ifp_out, "protocolPim");
- if (c_oil->oif_flags[oif_vif_index]
- & PIM_OIF_FLAG_PROTO_IGMP)
+ if (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_GM)
json_object_boolean_true_add(
json_ifp_out, "protocolIgmp");
@@ -4110,8 +4110,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
strlcpy(proto, "PIM", sizeof(proto));
}
- if (c_oil->oif_flags[oif_vif_index]
- & PIM_OIF_FLAG_PROTO_IGMP) {
+ if (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_GM) {
strlcpy(proto, "IGMP", sizeof(proto));
}
@@ -4909,7 +4909,7 @@ DEFPY (ip_pim_rp_keep_alive,
"ip pim rp keep-alive-timer (1-65535)$kat",
IP_STR
"pim multicast routing\n"
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"Keep alive Timer\n"
"Seconds\n")
{
@@ -4922,7 +4922,7 @@ DEFUN (no_ip_pim_rp_keep_alive,
NO_STR
IP_STR
"pim multicast routing\n"
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"Keep alive Timer\n"
IGNORED_IN_NO_STR)
{
@@ -5062,7 +5062,7 @@ DEFPY (ip_pim_rp,
"ip pim rp A.B.C.D$rp [A.B.C.D/M]$gp",
IP_STR
"pim multicast routing\n"
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"ip address of RP\n"
"Group Address range to cover\n")
{
@@ -5090,7 +5090,7 @@ DEFPY (no_ip_pim_rp,
NO_STR
IP_STR
"pim multicast routing\n"
- "Rendevous Point\n"
+ "Rendezvous Point\n"
"ip address of RP\n"
"Group Address range to cover\n")
{
@@ -5314,24 +5314,9 @@ DEFUN (ip_ssmpingd,
"Source address\n")
{
int idx_ipv4 = 2;
- const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
- const char *vrfname;
- char ssmpingd_ip_xpath[XPATH_MAXLEN];
-
- vrfname = pim_cli_get_vrf_name(vty);
- if (vrfname == NULL)
- return CMD_WARNING_CONFIG_FAILED;
-
- snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
- FRR_PIM_VRF_XPATH,
- "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
- strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
- sizeof(ssmpingd_ip_xpath));
+ const char *src_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
- nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE,
- source_str);
-
- return nb_cli_apply_changes(vty, NULL);
+ return pim_process_ssmpingd_cmd(vty, NB_OP_CREATE, src_str);
}
DEFUN (no_ip_ssmpingd,
@@ -5342,25 +5327,10 @@ DEFUN (no_ip_ssmpingd,
CONF_SSMPINGD_STR
"Source address\n")
{
- const char *vrfname;
int idx_ipv4 = 3;
- const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
- char ssmpingd_ip_xpath[XPATH_MAXLEN];
-
- vrfname = pim_cli_get_vrf_name(vty);
- if (vrfname == NULL)
- return CMD_WARNING_CONFIG_FAILED;
-
- snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
- FRR_PIM_VRF_XPATH,
- "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
- strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
- sizeof(ssmpingd_ip_xpath));
+ const char *src_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
- nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_DESTROY,
- source_str);
-
- return nb_cli_apply_changes(vty, NULL);
+ return pim_process_ssmpingd_cmd(vty, NB_OP_DESTROY, src_str);
}
DEFUN (ip_pim_ecmp,
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index 0992a60de9..f7cd0dceab 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -1166,7 +1166,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
out_ifname,
(c_oil->oif_flags
[oif_vif_index] &
- PIM_OIF_FLAG_PROTO_IGMP)
+ PIM_OIF_FLAG_PROTO_GM)
? 'I'
: ' ',
(c_oil->oif_flags
@@ -1194,7 +1194,7 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
out_ifname,
(c_oil->oif_flags
[oif_vif_index] &
- PIM_OIF_FLAG_PROTO_IGMP)
+ PIM_OIF_FLAG_PROTO_GM)
? 'I'
: ' ',
(c_oil->oif_flags
@@ -2840,3 +2840,25 @@ int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
FRR_PIM_AF_XPATH_VAL);
}
+
+
+int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
+ const char *src_str)
+{
+ const char *vrfname;
+ char ssmpingd_ip_xpath[XPATH_MAXLEN];
+
+ vrfname = pim_cli_get_vrf_name(vty);
+ if (vrfname == NULL)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
+ FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ FRR_PIM_AF_XPATH_VAL);
+ strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
+ sizeof(ssmpingd_ip_xpath));
+
+ nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h
index 3bcd0d5d6d..f5e0ef5878 100644
--- a/pimd/pim_cmd_common.h
+++ b/pimd/pim_cmd_common.h
@@ -102,6 +102,8 @@ int gm_process_no_last_member_query_count_cmd(struct vty *vty);
int gm_process_last_member_query_interval_cmd(struct vty *vty,
const char *lmqi_str);
int gm_process_no_last_member_query_interval_cmd(struct vty *vty);
+int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
+ const char *src_str);
/*
* Special Macro to allow us to get the correct pim_instance
*/
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index a644d9cfec..b98e64adfe 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -123,7 +123,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
- pim_ifp->options = 0;
pim_ifp->pim = ifp->vrf->info;
pim_ifp->mroute_vif_index = -1;
@@ -1526,7 +1525,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp)
/*
* PIM wants to have an interface pointer for everything it does.
* The pimreg is a special interface that we have that is not
- * quite an inteface but a VIF is created for it.
+ * quite an interface but a VIF is created for it.
*/
void pim_if_create_pimreg(struct pim_instance *pim)
{
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index b0f7e52ac2..3535db70a8 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -75,7 +75,6 @@ struct pim_interface {
bool igmp_enable : 1;
- uint32_t options; /* bit vector */
ifindex_t mroute_vif_index;
struct pim_instance *pim;
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 54cd824f9e..40aaf1877c 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -138,7 +138,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
if (ch->upstream->channel_oil) {
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
- mask |= PIM_OIF_FLAG_PROTO_IGMP;
+ mask |= PIM_OIF_FLAG_PROTO_GM;
/*
* A S,G RPT channel can have an empty oil, we also
@@ -1227,14 +1227,13 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, pim_sgaddr *sg,
== PREFIX_DENY) {
pim_channel_add_oif(
up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP,
+ PIM_OIF_FLAG_PROTO_GM,
__func__);
}
}
} else
pim_channel_add_oif(up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP,
- __func__);
+ PIM_OIF_FLAG_PROTO_GM, __func__);
}
return 1;
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 08cc0b8fc4..0dce8faa90 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -242,8 +242,7 @@ void igmp_source_forward_stop(struct gm_source *source)
/* This socket is used for TXing IGMP packets only, IGMP RX happens
* in pim_mroute_msg()
*/
-static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp,
- uint32_t pim_options)
+static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp)
{
int fd;
int join = 0;
@@ -669,7 +668,7 @@ static int igmp_v1_recv_report(struct gm_sock *igmp, struct in_addr from,
if (pim_is_group_filtered(ifp->info, &group_addr))
return -1;
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return -1;
@@ -1254,14 +1253,11 @@ struct gm_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
struct in_addr ifaddr, struct interface *ifp,
bool mtrace_only)
{
- struct pim_interface *pim_ifp;
struct gm_sock *igmp;
struct sockaddr_in sin;
int fd;
- pim_ifp = ifp->info;
-
- fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options);
+ fd = igmp_sock_open(ifaddr, ifp);
if (fd < 0) {
zlog_warn("Could not open IGMP socket for %pI4 on %s",
&ifaddr, ifp->name);
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index fb9b385338..933b43cd98 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -516,7 +516,7 @@ static void allow(struct gm_sock *igmp, struct in_addr from,
return;
}
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return;
@@ -669,7 +669,7 @@ void igmpv3_report_isex(struct gm_sock *igmp, struct in_addr from,
if (pim_is_group_filtered(ifp->info, &group_addr))
return;
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return;
@@ -790,7 +790,7 @@ void igmpv3_report_toin(struct gm_sock *igmp, struct in_addr from,
* entry is present, the request is ignored.
*/
if (num_sources) {
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return;
@@ -944,7 +944,7 @@ void igmpv3_report_toex(struct gm_sock *igmp, struct in_addr from,
on_trace(__func__, ifp, from, group_addr, num_sources, sources);
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return;
@@ -1465,7 +1465,7 @@ void igmpv3_report_block(struct gm_sock *igmp, struct in_addr from,
on_trace(__func__, ifp, from, group_addr, num_sources, sources);
- /* non-existant group is created as INCLUDE {empty} */
+ /* non-existent group is created as INCLUDE {empty} */
group = igmp_add_group_by_addr(igmp, group_addr);
if (!group) {
return;
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index 68f77ad6d9..9763a79a8d 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -1015,7 +1015,7 @@ void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
if (router->pim_mlag_intf_cnt == 1) {
/*
- * atleast one Interface is configured for MLAG, send register
+ * at least one Interface is configured for MLAG, send register
* to Zebra for receiving MLAG Updates
*/
pim_mlag_register();
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 3015c4a61b..43d05dfe9c 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -739,8 +739,8 @@ bool pim_mroute_allow_iif_in_oil(struct channel_oil *c_oil,
pim_ifp = ifp_out->info;
if (!pim_ifp)
return false;
- if ((c_oil->oif_flags[oif_index] & PIM_OIF_FLAG_PROTO_IGMP) &&
- PIM_I_am_DR(pim_ifp))
+ if ((c_oil->oif_flags[oif_index] & PIM_OIF_FLAG_PROTO_GM) &&
+ PIM_I_am_DR(pim_ifp))
return true;
return false;
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 21047177ea..eed4b203cd 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -27,18 +27,18 @@ struct pim_interface;
/*
* Where did we get this (S,G) from?
*
- * IGMP - Learned from IGMP
+ * GM - Learned from IGMP/MLD
* PIM - Learned from PIM
* SOURCE - Learned from Source multicast packet received
* STAR - Inherited
*/
-#define PIM_OIF_FLAG_PROTO_IGMP (1 << 0)
+#define PIM_OIF_FLAG_PROTO_GM (1 << 0)
#define PIM_OIF_FLAG_PROTO_PIM (1 << 1)
#define PIM_OIF_FLAG_PROTO_STAR (1 << 2)
#define PIM_OIF_FLAG_PROTO_VXLAN (1 << 3)
-#define PIM_OIF_FLAG_PROTO_ANY \
- (PIM_OIF_FLAG_PROTO_IGMP | PIM_OIF_FLAG_PROTO_PIM \
- | PIM_OIF_FLAG_PROTO_STAR | PIM_OIF_FLAG_PROTO_VXLAN)
+#define PIM_OIF_FLAG_PROTO_ANY \
+ (PIM_OIF_FLAG_PROTO_GM | PIM_OIF_FLAG_PROTO_PIM | \
+ PIM_OIF_FLAG_PROTO_STAR | PIM_OIF_FLAG_PROTO_VXLAN)
/* OIF is present in the OIL but must not be used for forwarding traffic */
#define PIM_OIF_FLAG_MUTE (1 << 4)
diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c
index afa7e37da1..d86be85bd8 100644
--- a/pimd/pim_ssmpingd.c
+++ b/pimd/pim_ssmpingd.c
@@ -361,10 +361,8 @@ int pim_ssmpingd_start(struct pim_instance *pim, pim_addr source_addr)
return 0;
}
- {
- zlog_info("%s: starting ssmpingd for source %pPAs", __func__,
- &source_addr);
- }
+ zlog_info("%s: starting ssmpingd for source %pPAs", __func__,
+ &source_addr);
ss = ssmpingd_new(pim, source_addr);
if (!ss) {
diff --git a/pimd/pim_tib.c b/pimd/pim_tib.c
index 838f11211e..80e75f1b09 100644
--- a/pimd/pim_tib.c
+++ b/pimd/pim_tib.c
@@ -110,8 +110,8 @@ bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg,
if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) {
int result;
- result = pim_channel_add_oif(*oilp, oif,
- PIM_OIF_FLAG_PROTO_IGMP, __func__);
+ result = pim_channel_add_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
+ __func__);
if (result) {
if (PIM_DEBUG_MROUTE)
zlog_warn("%s: add_oif() failed with return=%d",
@@ -136,7 +136,7 @@ bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg,
"%s: Failure to add local membership for %pSG",
__func__, &sg);
- pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_IGMP,
+ pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
__func__);
return false;
}
@@ -160,7 +160,7 @@ void tib_sg_gm_prune(struct pim_instance *pim, pim_sgaddr sg,
fixes the issue without ill effect, similar to
pim_forward_stop below.
*/
- result = pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_IGMP,
+ result = pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
__func__);
if (result) {
if (PIM_DEBUG_IGMP_TRACE)
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index af1254f791..2b5b4bcf53 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -1838,7 +1838,7 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
flag = PIM_OIF_FLAG_PROTO_STAR;
else {
if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
- flag = PIM_OIF_FLAG_PROTO_IGMP;
+ flag = PIM_OIF_FLAG_PROTO_GM;
if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
flag |= PIM_OIF_FLAG_PROTO_PIM;
if (starch)
@@ -2062,6 +2062,7 @@ static bool pim_upstream_sg_running_proc(struct pim_upstream *up)
if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
(up->rpf.source_nexthop.interface)) {
pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
+ pim_upstream_update_could_assert(up);
}
return rv;
@@ -2116,7 +2117,7 @@ void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
continue;
pim_channel_add_oif(up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP, __func__);
+ PIM_OIF_FLAG_PROTO_GM, __func__);
}
}
@@ -2161,18 +2162,17 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
if (!nlist) {
pim_channel_del_oif(up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP, __func__);
+ PIM_OIF_FLAG_PROTO_GM, __func__);
continue;
}
pim_addr_to_prefix(&g, up->sg.grp);
apply_new = prefix_list_apply(np, &g);
if (apply_new == PREFIX_DENY)
pim_channel_add_oif(up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP,
- __func__);
+ PIM_OIF_FLAG_PROTO_GM, __func__);
else
pim_channel_del_oif(up->channel_oil, pim->regiface,
- PIM_OIF_FLAG_PROTO_IGMP, __func__);
+ PIM_OIF_FLAG_PROTO_GM, __func__);
}
}
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index b360181f43..b0db6b4d96 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -264,8 +264,8 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
struct ssmpingd_sock *ss;
++writes;
for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
- vty_out(vty, "%sip ssmpingd %pPA\n", spaces,
- &ss->source_addr);
+ vty_out(vty, "%s" PIM_AF_NAME " ssmpingd %pPA\n",
+ spaces, &ss->source_addr);
++writes;
}
}
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 4bed8d5b73..4135ae0408 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -499,7 +499,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
ch->interface->name, &up->upstream_addr);
if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
- mask = PIM_OIF_FLAG_PROTO_IGMP;
+ mask = PIM_OIF_FLAG_PROTO_GM;
if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
mask |= PIM_OIF_FLAG_PROTO_PIM;
diff --git a/redhat/frr.logrotate b/redhat/frr.logrotate
index 22b2332b7c..04ae96b654 100644
--- a/redhat/frr.logrotate
+++ b/redhat/frr.logrotate
@@ -110,6 +110,14 @@
endscript
}
+/var/log/frr/pathd.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/pathd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
/var/log/frr/pbrd.log {
notifempty
missingok
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 740cfe498a..73c214ea2e 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -260,7 +260,7 @@ Group: System Environment/Daemons
Requires: %{name} = %{version}-%{release}
%description devel
-The frr-devel package contains the header and object files neccessary for
+The frr-devel package contains the header and object files necessary for
developing OSPF-API and frr applications.
@@ -432,7 +432,8 @@ popd
%install
mkdir -p %{buildroot}%{_sysconfdir}/{frr,sysconfig,logrotate.d,pam.d,default} \
- %{buildroot}%{_localstatedir}/log/frr %{buildroot}%{_infodir}
+ %{buildroot}%{_infodir}
+mkdir -m 0755 -p %{buildroot}%{_localstatedir}/log/frr
make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install
# Remove this file, as it is uninstalled and causes errors when building on RH9
@@ -639,11 +640,11 @@ fi
/usr/share/yang/*.yang
%if 0%{?frr_user:1}
%dir %attr(751,%{frr_user},%{frr_user}) %{configdir}
- %dir %attr(750,%{frr_user},%{frr_user}) %{_localstatedir}/log/frr
+ %dir %attr(755,%{frr_user},%{frr_user}) %{_localstatedir}/log/frr
%dir %attr(751,%{frr_user},%{frr_user}) %{rundir}
%else
%dir %attr(750,root,root) %{configdir}
- %dir %attr(750,root,root) %{_localstatedir}/log/frr
+ %dir %attr(755,root,root) %{_localstatedir}/log/frr
%dir %attr(750,root,root) %{rundir}
%endif
%{_infodir}/frr.info.gz
@@ -918,7 +919,7 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
- Add ability to show BGP routes from a particular table version
- Add support for for RFC 8050 (MRT add-path)
- Add SNMP support for MPLS VPN
-- Add `show bgp summary wide` command to show more detailed output
+- Add `show bgp summary wide` command to show more detailed output
on wide terminals
- Add ability for peer-groups to have `ttl-security hops` configured
- Add support for conditional Advertisement
diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c
index 4034fe8424..d499229340 100644
--- a/ripd/rip_offset.c
+++ b/ripd/rip_offset.c
@@ -78,7 +78,7 @@ struct rip_offset_list *rip_offset_list_lookup(struct rip *rip,
return NULL;
}
-/* If metric is modifed return 1. */
+/* If metric is modified return 1. */
int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
@@ -115,7 +115,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp,
return 0;
}
-/* If metric is modifed return 1. */
+/* If metric is modified return 1. */
int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp,
uint32_t *metric)
{
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 85aac985f5..f26dcd8775 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -526,7 +526,7 @@ extern void rip_cli_init(void);
extern struct zebra_privs_t ripd_privs;
extern struct rip_instance_head rip_instances;
-/* Master thread strucutre. */
+/* Master thread structure. */
extern struct thread_master *master;
DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc));
diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c
index efce8a0926..38c69f1b75 100644
--- a/ripngd/ripng_offset.c
+++ b/ripngd/ripng_offset.c
@@ -85,7 +85,7 @@ struct ripng_offset_list *ripng_offset_list_lookup(struct ripng *ripng,
return NULL;
}
-/* If metric is modifed return 1. */
+/* If metric is modified return 1. */
int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric)
{
@@ -123,7 +123,7 @@ int ripng_offset_list_apply_in(struct ripng *ripng, struct prefix_ipv6 *p,
return 0;
}
-/* If metric is modifed return 1. */
+/* If metric is modified return 1. */
int ripng_offset_list_apply_out(struct ripng *ripng, struct prefix_ipv6 *p,
struct interface *ifp, uint8_t *metric)
{
diff --git a/tests/isisd/test_topologies.c b/tests/isisd/test_topologies.c
index ca103948f3..b3e500a33c 100644
--- a/tests/isisd/test_topologies.c
+++ b/tests/isisd/test_topologies.c
@@ -31,7 +31,7 @@
* - The Router-ID is 10.0.255.X, where X is the node number;
* - The default link metric is 10;
* - When SR is enabled, Adj-SIDs and Prefix-SIDs are generated automatically;
- * - When SR is enabled, the default SRGB is [16000-23999] (can be overriden).
+ * - When SR is enabled, the default SRGB is [16000-23999] (can be overridden).
*
* Test topology 1:
* ================
diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c
index 9b6539e3bc..cef93ad0c5 100644
--- a/tests/lib/test_table.c
+++ b/tests/lib/test_table.c
@@ -382,7 +382,7 @@ static void verify_prefix_iter_cmp(const char *p1, const char *p2,
assert(exp_result == result);
/*
- * Also check the reverse comparision.
+ * Also check the reverse comparison.
*/
result = route_table_prefix_iter_cmp((struct prefix *)&p2_pfx,
(struct prefix *)&p1_pfx);
@@ -398,7 +398,7 @@ static void verify_prefix_iter_cmp(const char *p1, const char *p2,
/*
* test_prefix_iter_cmp
*
- * Tests comparision of prefixes according to order of iteration.
+ * Tests comparison of prefixes according to order of iteration.
*/
static void test_prefix_iter_cmp(void)
{
diff --git a/tests/topotests/bgp_auth/test_bgp_auth.py b/tests/topotests/bgp_auth/test_bgp_auth.py
index f01c7f206a..9e8136c17b 100644
--- a/tests/topotests/bgp_auth/test_bgp_auth.py
+++ b/tests/topotests/bgp_auth/test_bgp_auth.py
@@ -158,7 +158,7 @@ def setup_module(mod):
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
router.load_config(TopoRouter.RD_OSPF)
diff --git a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
index 600bf3adc0..b18e32f6bd 100644
--- a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
+++ b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
@@ -371,7 +371,7 @@ def test_bgp_timers_functionality(request):
# Creating configuration from JSON
reset_config_on_routers(tgen)
- # Api call to modfiy BGP timerse
+ # Api call to modify BGP timerse
input_dict = {
"r1": {
"bgp": {
diff --git a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
index c594079d4f..86a8751621 100755
--- a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
+++ b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
@@ -192,7 +192,7 @@ def setup_module(mod):
pe.cmd_raises("sysctl -w net.ipv4.udp_l3mdev_accept={}".format(l3mdev_accept))
pe.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for (name, router) in tgen.routers().items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(name))
diff --git a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
index 40972d4a6a..5d0a326afb 100755
--- a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
+++ b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
@@ -118,7 +118,7 @@ def setup_module(mod):
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
index a5c833dc5d..e60552ed10 100644
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
@@ -1041,7 +1041,7 @@ def test_BGP_GR_15_p2(request):
logger.info(
"[Step 2] : Test Setup "
"[Helper Mode]R6-----R1[Restart Mode]"
- "--------R2[Helper Mode] Initilized"
+ "--------R2[Helper Mode] Initialized"
)
# Configure graceful-restart
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
index 8671a79323..1df77ebeb2 100644
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
@@ -456,7 +456,7 @@ def test_BGP_GR_20_p1(request):
reset_config_on_routers(tgen)
logger.info(
- "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized"
+ "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initialized"
)
# Configure graceful-restart
@@ -602,7 +602,7 @@ def test_BGP_GR_21_p2(request):
reset_config_on_routers(tgen)
logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized"
+ "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initialized"
)
# Configure graceful-restart
@@ -676,7 +676,7 @@ def test_BGP_GR_21_p2(request):
logger.info(
"[Step 2] : Test Setup "
"[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R6[Helper Mode] Initilized"
+ "--------R6[Helper Mode] Initialized"
)
# Configure graceful-restart
@@ -821,7 +821,7 @@ def test_BGP_GR_22_p2(request):
reset_config_on_routers(tgen)
logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized"
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initialized"
)
# Configure graceful-restart
@@ -901,7 +901,7 @@ def test_BGP_GR_22_p2(request):
logger.info(
"[Step 2] : Test Setup "
"[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R3[Helper Mode] Initilized"
+ "--------R3[Helper Mode] Initialized"
)
# Configure graceful-restart
diff --git a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
index 8941854593..8955f2794d 100644
--- a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
+++ b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
@@ -92,7 +92,7 @@ def setup_module(mod):
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
diff --git a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
index 35e81d1c62..04ebe61a02 100644
--- a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
+++ b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
@@ -1224,7 +1224,7 @@ def test_shut_noshut_p1(request):
result = create_router_bgp(tgen, topo, input_dict_3)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- step("Api call to modfiy BGP timers")
+ step("Api call to modify BGP timers")
input_dict_4 = {
"r1": {
@@ -1757,7 +1757,7 @@ def test_vrf_vlan_routing_table_p1(request):
tc_name, result
)
- step("Api call to modfiy BGP timers")
+ step("Api call to modify BGP timers")
input_dict_4 = {
"r3": {
@@ -2422,7 +2422,7 @@ def test_delete_and_re_add_vrf_p1(request):
result = verify_rib(tgen, addr_type, dut, input_dict_2)
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- step("Api call to modfiy BGP timers")
+ step("Api call to modify BGP timers")
input_dict_4 = {
"r1": {
@@ -3034,7 +3034,7 @@ def test_vrf_name_significance_p1(request):
result = verify_rib(tgen, addr_type, dut, input_dict_4)
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- step("Api call to modfiy BGP timers")
+ step("Api call to modify BGP timers")
input_dict_4 = {
"r3": {
@@ -3437,7 +3437,7 @@ def test_vrf_name_significance_p1(request):
result = create_router_bgp(tgen, topo_modify["routers"])
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Api call to modfiy BGP timers")
+ step("Api call to modify BGP timers")
input_dict_4 = {
"r3": {
diff --git a/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py b/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
index 0d27474cbd..d612ad2c94 100755
--- a/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
+++ b/tests/topotests/bgp_snmp_mplsl3vpn/test_bgp_snmp_mplsvpn.py
@@ -154,7 +154,7 @@ def setup_module(mod):
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
diff --git a/tests/topotests/grpc_basic/test_basic_grpc.py b/tests/topotests/grpc_basic/test_basic_grpc.py
index b6812a5afc..6bd0be9fd9 100644
--- a/tests/topotests/grpc_basic/test_basic_grpc.py
+++ b/tests/topotests/grpc_basic/test_basic_grpc.py
@@ -122,7 +122,7 @@ def test_get_config(tgen):
nrepeat = 5
r1 = tgen.gears["r1"]
- step("'GET' inteface config 10 times, once per invocation")
+ step("'GET' interface config 10 times, once per invocation")
for i in range(0, nrepeat):
output = run_grpc_client(r1, GRPCP_ZEBRA, "GET,/frr-interface:lib")
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 564571c929..5a5c7e3df4 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -1186,12 +1186,14 @@ def add_interfaces_to_vlan(tgen, input_dict):
interface, vlan_intf, vlan
)
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
- rnode.run(cmd)
+ result = rnode.run(cmd)
+ logger.info("result %s", result)
# Bringing interface up
cmd = "ip link set {} up".format(vlan_intf)
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
- rnode.run(cmd)
+ result = rnode.run(cmd)
+ logger.info("result %s", result)
# Assigning IP address
ifaddr = ipaddress.ip_interface(
@@ -1204,7 +1206,8 @@ def add_interfaces_to_vlan(tgen, input_dict):
ifaddr.version, vlan_intf, ifaddr
)
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
- rnode.run(cmd)
+ result = rnode.run(cmd)
+ logger.info("result %s", result)
def tcpdump_capture_start(
diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py
index 18882285ed..2544023c43 100644
--- a/tests/topotests/lib/ltemplate.py
+++ b/tests/topotests/lib/ltemplate.py
@@ -93,7 +93,7 @@ class LTemplate:
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
logger.info("Setting up %s" % rname)
for rd_val in TopoRouter.RD:
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 4ed5b2f825..c04506f47e 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -443,7 +443,7 @@ class Topogen(object):
def start_router(self, router=None):
"""
Call the router startRouter method.
- If no router is specified it is called for all registred routers.
+ If no router is specified it is called for all registered routers.
"""
if router is None:
# pylint: disable=r1704
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index e786ae02cd..27b566a8f5 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -746,7 +746,7 @@ def proto_name_to_number(protocol):
def ip4_route(node):
"""
Gets a structured return of the command 'ip route'. It can be used in
- conjuction with json_cmp() to provide accurate assert explanations.
+ conjunction with json_cmp() to provide accurate assert explanations.
Return example:
{
@@ -787,7 +787,7 @@ def ip4_route(node):
def ip4_vrf_route(node):
"""
Gets a structured return of the command 'ip route show vrf {0}-cust1'.
- It can be used in conjuction with json_cmp() to provide accurate assert explanations.
+ It can be used in conjunction with json_cmp() to provide accurate assert explanations.
Return example:
{
@@ -831,7 +831,7 @@ def ip4_vrf_route(node):
def ip6_route(node):
"""
Gets a structured return of the command 'ip -6 route'. It can be used in
- conjuction with json_cmp() to provide accurate assert explanations.
+ conjunction with json_cmp() to provide accurate assert explanations.
Return example:
{
@@ -871,7 +871,7 @@ def ip6_route(node):
def ip6_vrf_route(node):
"""
Gets a structured return of the command 'ip -6 route show vrf {0}-cust1'.
- It can be used in conjuction with json_cmp() to provide accurate assert explanations.
+ It can be used in conjunction with json_cmp() to provide accurate assert explanations.
Return example:
{
@@ -913,7 +913,7 @@ def ip6_vrf_route(node):
def ip_rules(node):
"""
Gets a structured return of the command 'ip rule'. It can be used in
- conjuction with json_cmp() to provide accurate assert explanations.
+ conjunction with json_cmp() to provide accurate assert explanations.
Return example:
[
diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
index 1a55d6d9f1..1762535cee 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -34,7 +34,7 @@ Tests covered in this suite
3.2 Verify if no forwarding bit is set , FRR is not forwarding the
BSM to other PIM nbrs
3.3 Verify multicast BSM is sent to new router when unicast BSM is disabled
-4.1 Verfiy BSM arrived on non bsm capable interface is dropped and
+4.1 Verify BSM arrived on non bsm capable interface is dropped and
not processed
4.2 Verify group to RP info updated correctly in FRR node, after shut and
no-shut of BSM enable interfaces
@@ -865,7 +865,7 @@ def test_new_router_fwd_p0(request):
def test_int_bsm_config_p1(request):
"""
- 1. Verfiy BSM arrived on non bsm capable interface is dropped and
+ 1. Verify BSM arrived on non bsm capable interface is dropped and
not processed
2. Verify group to RP info updated correctly in FRR node, after shut and
no-shut of BSM enable interfaces
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/__init__.py b/tests/topotests/multicast_pim_dr_nondr_test/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/__init__.py
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_ospf_topo2.json b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_ospf_topo2.json
new file mode 100644
index 0000000000..4a4eb9a0f0
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_ospf_topo2.json
@@ -0,0 +1,195 @@
+{
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 24,
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24, "link_local": "disable"},
+ "lo_prefix": {"ipv4": "1.0.", "v4mask": 32},
+ "switches": {
+ "s1": {
+ "links": {
+ "i1": {"ipv4": "auto"},
+ "r1": {"ipv4": "auto", "pim": "enable"},
+ "r2": {"ipv4": "auto", "pim": "enable"}
+ }
+ }
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r4": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r4": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r4": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r4": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r1": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r2": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r5": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r1": {},
+ "r2": {},
+ "r5": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r4": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "i2": {
+ "ipv4": "auto",
+ "pim": "enable"
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r4": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "i1": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback"}
+ }
+ },
+ "i2": {
+ "links": {
+ "r5": {"ipv4": "auto"}
+ }
+ }
+ }
+}
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_static_routes_topo1.json b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_static_routes_topo1.json
new file mode 100644
index 0000000000..9d7d766536
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_static_routes_topo1.json
@@ -0,0 +1,85 @@
+{
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 24,
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24, "link_local": "disable"},
+ "lo_prefix": {"ipv4": "1.0.", "v4mask": 32},
+ "switches": {
+ "s1": {
+ "links": {
+ "i1": {"ipv4": "auto"},
+ "r1": {"ipv4": "auto", "pim": "enable"},
+ "r2": {"ipv4": "auto", "pim": "enable"},
+ "r3": {"ipv4": "auto", "pim": "enable"}
+ }
+ }
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback", "pim": "enable"},
+ "r4": {"ipv4": "auto", "pim": "enable"}
+ },
+ "static_routes": [{
+ "network": ["10.0.0.1/24", "1.0.5.17/32"],
+ "next_hop": "10.0.1.2"
+ }]
+ },
+ "r2": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback", "pim": "enable"},
+ "r4": {"ipv4": "auto", "pim": "enable"}
+ },
+ "static_routes": [{
+ "network": ["10.0.0.1/24", "1.0.5.17/32"],
+ "next_hop": "10.0.2.2"
+ }]
+ },
+ "r3": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback", "pim": "enable"}
+ },
+ "static_routes": [{
+ "network": ["10.0.0.1/24", "1.0.5.17/32"],
+ "next_hop": "10.1.1.1"
+ }]
+ },
+ "r4": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback", "pim": "enable"},
+ "r1": {"ipv4": "auto", "pim": "enable"},
+ "r2": {"ipv4": "auto", "pim": "enable"},
+ "r5": {"ipv4": "auto", "pim": "enable"}
+ },
+ "static_routes": [
+ {
+ "network": ["10.1.1.4/24"],
+ "next_hop": "10.0.2.1"
+ },
+ {
+ "network": ["10.0.0.1/24"],
+ "next_hop": "10.0.3.2"
+ }]
+ },
+ "r5": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback", "pim": "enable"},
+ "r4": {"ipv4": "auto", "pim": "enable"},
+ "i2": {"ipv4": "auto", "pim": "enable"}
+ },
+ "static_routes": [{
+ "network": ["10.1.1.4/24", "1.0.5.17/32"],
+ "next_hop": "10.0.3.1"
+ }]
+ },
+ "i1": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback"}
+ }
+ },
+ "i2": {
+ "links": {
+ "r5": {"ipv4": "auto"}
+ }
+ }
+ }
+}
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_transit_router_topo3.json b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_transit_router_topo3.json
new file mode 100644
index 0000000000..f078657862
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/pim_dr_nondr_with_transit_router_topo3.json
@@ -0,0 +1,241 @@
+{
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 24,
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24, "link_local": "disable"},
+ "lo_prefix": {"ipv4": "1.0.", "v4mask": 32},
+ "switches": {
+ "s1": {
+ "links": {
+ "i1": {"ipv4": "auto"},
+ "r1": {"ipv4": "auto", "pim": "enable"},
+ "r2": {"ipv4": "auto", "pim": "enable"}
+ }
+ }
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r6": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r6": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r6": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r6": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r6": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r5": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r6": {},
+ "r5": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r4": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "i2": {
+ "ipv4": "auto",
+ "pim": "enable"
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r4": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r6": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "type": "loopback",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r1": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r2": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r4": {
+ "ipv4": "auto",
+ "pim": "enable",
+ "ospf": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf": {
+ "neighbors": {
+ "r1": {},
+ "r2": {},
+ "r4": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "i1": {
+ "links": {
+ "lo": {"ipv4": "auto", "type": "loopback"}
+ }
+ },
+ "i2": {
+ "links": {
+ "r5": {"ipv4": "auto"}
+ }
+ }
+ }
+}
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_ospf_topo2.py b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_ospf_topo2.py
new file mode 100755
index 0000000000..1adc034206
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_ospf_topo2.py
@@ -0,0 +1,1135 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test multicast pim sm:
+
+Test steps
+- Create topology (setup module)
+- Bring up topology
+
+Following tests are covered:
+1. Configure IGMP local join on DR and non DR
+"""
+
+import os
+import sys
+import json
+import time
+import datetime
+from time import sleep
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ step,
+ reset_config_on_routers,
+ shutdown_bringup_interface,
+ apply_raw_config,
+ add_interfaces_to_vlan,
+ kill_router_daemons,
+ start_router_daemons,
+ create_static_routes,
+ check_router_status,
+ topo_daemons,
+ required_linux_kernel_version,
+)
+from lib.pim import (
+ create_pim_config,
+ create_igmp_config,
+ verify_ip_mroutes,
+ clear_ip_mroute,
+ clear_ip_pim_interface_traffic,
+ verify_pim_config,
+ verify_upstream_iif,
+ verify_multicast_traffic,
+ verify_multicast_flag_state,
+ verify_igmp_groups,
+ McastTesterHelper
+)
+from lib.topolog import logger
+from lib.topojson import build_config_from_json
+
+HELLO_TIMER = 1
+HOLD_TIMER = 3
+
+pytestmark = [pytest.mark.pimd]
+
+TOPOLOGY = """
+
+Descripton: Configuring OSPF on r1/r2/r4/r5 for RP reachablility.
+IPs are assigned automatically to routers, start IP and subnet is defined in respective JSON file
+JSON snippet:
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24},
+
+ r5 ------- i2
+ 10.0.3.2/24| 10.0.0.2/24
+ |
+ 10.0.3.1/24|
+ ------------ r4 ----------
+ | 10.0.1.2/24 10.0.2.2/24 |
+ 10.0.1.1/24 | | 10.0.2.1/24
+ r1 ----------- s1 ---------- r2
+ 10.0.4.2/24 | 10.0.4.3/24
+ |
+ |10.0.4.1/24
+ i1
+
+ Description:
+ i1, i2 - FRR running iperf to send IGMP
+ join and traffic
+ r1, r2, r4, r5 - FRR router
+ s1 - OVS switch
+"""
+
+# Global variables
+VLAN_1 = 2501
+GROUP_RANGE = "225.0.0.0/8"
+IGMP_JOIN = "225.1.1.1"
+VLAN_INTF_ADRESS_1 = "10.0.8.3/24"
+SAME_VLAN_IP_1 = {"ip": "10.1.1.1", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_2 = {"ip": "10.1.1.2", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_3 = {"ip": "10.1.1.3", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_4 = {"ip": "10.1.1.4", "subnet": "255.255.255.0", "cidr": "24"}
+GROUP_RANGE_1 = ["225.1.1.1/32", "225.1.1.2/32"]
+IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2"]
+GROUP_RANGE_2 = ["226.1.1.1/32", "226.1.1.2/32"]
+IGMP_JOIN_RANGE_2 = ["226.1.1.1", "226.1.1.2"]
+GROUP_RANGE_3 = ["227.1.1.1/32", "227.1.1.2/32"]
+IGMP_JOIN_RANGE_3 = ["227.1.1.1", "227.1.1.2"]
+
+intf_r1_s1 = None
+intf_r1_s1_addr = None
+intf_r2_s1 = None
+intf_r2_s1_addr = None
+intf_r3_s1 = None
+intf_r3_s1_addr = None
+intf_i1_s1 = None
+intf_i1_s1_addr = None
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.19")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+ logger.info("Master Topology: \n {}".format(TOPOLOGY))
+
+ logger.info("Running setup_module to create topology")
+
+ testdir = os.path.dirname(os.path.realpath(__file__))
+ json_file = "{}/pim_dr_nondr_with_ospf_topo2.json".format(testdir)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, tgen.json_topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, tgen.json_topo)
+
+ # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
+ global app_helper
+ app_helper = McastTesterHelper(tgen)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ app_helper.cleanup()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Local APIs
+#
+#####################################################
+
+
+def pre_config_for_receiver_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for receiver test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r2_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r2_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Send IGMP join for groups 226.1.1.1 to 226.1.1.5")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_join("i1", IGMP_JOIN_RANGE_1, join_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Enable OSPF between r1 and r2")
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip ospf area 0.0.0.0",
+ "ip ospf dead-interval 4",
+ "ip ospf hello-interval 1",
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Start traffic from R4 connected source")
+
+ result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+def pre_config_for_source_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for source test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r2_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r2_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "Configure IGMP and PIM on switch connected receiver nodes , "
+ "configure PIM nbr with hello timer 1"
+ )
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure IGMP on R5 port and send IGMP join for groups " "(226.1.1.1-5)")
+
+ intf_r5_i2 = topo["routers"]["r5"]["links"]["i2"]["interface"]
+ input_dict = {
+ "r5": {"igmp": {"interfaces": {intf_r5_i2: {"igmp": {"version": "2"}}}}}
+ }
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ result = app_helper.run_join("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Enable OSPF between r1 and r2")
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip ospf area 0.0.0.0",
+ "ip ospf dead-interval 4",
+ "ip ospf hello-interval 1",
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Start traffic from Source node")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_traffic("i1", IGMP_JOIN_RANGE_1, bind_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_configuring_igmp_local_join_on_reciever_dr_non_dr_nodes_p1(request):
+ """
+ Configure IGMP local join on DR and non DR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ app_helper.stop_all_hosts()
+ clear_ip_mroute(tgen)
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ clear_ip_pim_interface_traffic(tgen, topo)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure R1 is DR initially configuring highest IP on R1 and R2 "
+ "second highest, R1 is lower"
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ vlan_input = {
+ "r1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_r1_s1: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "r2": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_r2_s1: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r2_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1 + GROUP_RANGE_3,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Send IGMP local join for groups 226.1.1.1 to 226.1.1.5")
+
+ vlan_intf_r1_s1 = "{}.{}".format(intf_r1_s1, VLAN_1)
+ input_dict = {
+ "r1": {
+ "igmp": {
+ "interfaces": {
+ vlan_intf_r1_s1: {
+ "igmp": {"version": "2", "join": IGMP_JOIN_RANGE_1}
+ }
+ }
+ }
+ }
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Enable OSPF between all the nodes")
+
+ step("Configure local join on R1 for group range (227.1.1.1)")
+
+ vlan_intf_r1_s1 = "{}.{}".format(intf_r1_s1, VLAN_1)
+ input_dict = {
+ "r1": {
+ "igmp": {
+ "interfaces": {
+ vlan_intf_r1_s1: {
+ "igmp": {"version": "2", "join": IGMP_JOIN_RANGE_3}
+ }
+ }
+ }
+ }
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Start traffic from R4 connected source")
+
+ input_src = {"i2": topo["routers"]["i2"]["links"]["r5"]["interface"]}
+
+ result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3, "r5")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R1, R2 and R2 has IGMP groups for 226.x.x.x and 227.1.1.1 groups")
+
+ intf_r1_s1 = "{}.{}".format(
+ topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
+ )
+ intf_r2_s1 = "{}.{}".format(
+ topo["routers"]["r2"]["links"]["s1"]["interface"], VLAN_1
+ )
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ result = verify_igmp_groups(
+ tgen, dut, intf, IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R1 is DR, R2 has 226.x.x.x and 227.1.1.1 (*,G) mroute with SC flag")
+ step("(S,G) mroute for 226.1.1.1 group present on R2")
+
+ source_i2 = topo["routers"]["i2"]["links"]["r5"]["ipv4"].split("/")[0]
+ input_dict_r2 = [
+ {
+ "dut": "r2",
+ "src_address": "*",
+ "iif": topo["routers"]["r2"]["links"]["r4"]["interface"],
+ "oil": "{}.{}".format(
+ topo["routers"]["r2"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ }
+ ]
+
+ for data in input_dict_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, flag in zip(["r2"], ["SC"]):
+ step("{} has (*,G) flag as {}".format(dut, flag))
+ result = verify_multicast_flag_state(tgen, dut, "*", IGMP_JOIN_RANGE_1, flag)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Delete local join from DR node")
+ input_dict = {
+ "r1": {
+ "igmp": {
+ "interfaces": {
+ vlan_intf_r1_s1: {
+ "igmp": {
+ "version": "2",
+ "join": IGMP_JOIN_RANGE_3,
+ "delete_attr": True,
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step(
+ "After removing local join 227.1.1.1 group removed from IGMP join "
+ "of R1, R2 node , using 'show ip igmp groups json'"
+ )
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ result = verify_igmp_groups(tgen, dut, intf, IGMP_JOIN_RANGE_3, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "IGMP groups are still present \n Error: {}".format(tc_name, result)
+ )
+
+ step("(*,G) mroute for 227.1.1.1 group removed from R1 node")
+ step(
+ "After remove of local join from R1 and R2 node verify (*,G) and (S,G) "
+ "mroutes should not present on R1, R2 and R3 nodes"
+ )
+
+ for data in input_dict_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_3,
+ data["iif"],
+ data["oil"],
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "mroutes are still present \n Error: {}".format(tc_name, result)
+ )
+
+ step("Configure local join on R2 for group range (227.1.1.1)")
+
+ input_dict = {
+ "r2": {
+ "igmp": {
+ "interfaces": {
+ intf_r2_s1: {"igmp": {"version": "2", "join": IGMP_JOIN_RANGE_3}}
+ }
+ }
+ }
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step(
+ "After configuring local join on R2 non DR node, IGMP groups for 26.x.x.x and "
+ "227.1.1.1 present on all the nodes"
+ )
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ result = verify_igmp_groups(
+ tgen, dut, intf, IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R2 has 227.1.1.1 (*,G) mroute with SC flag")
+
+ for dut, flag in zip(["r2"], ["SC"]):
+ step("{} has (*,G) flag as {}".format(dut, flag))
+ result = verify_multicast_flag_state(tgen, dut, "*", IGMP_JOIN_RANGE_3, flag)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure local join on R1 for group range (227.1.1.1)")
+
+ input_dict = {
+ "r1": {
+ "igmp": {
+ "interfaces": {
+ vlan_intf_r1_s1: {
+ "igmp": {"version": "2", "join": IGMP_JOIN_RANGE_3}
+ }
+ }
+ }
+ }
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step(
+ "After configuring 227.1.1.1 on R1 node, verify no change on IGMP groups on all the nodes"
+ )
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ result = verify_igmp_groups(
+ tgen, dut, intf, IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R2 has 227.1.1.1 (*,G) mroute with SC flag")
+
+ step("r2 has (*,G) flag as SC")
+ result = verify_multicast_flag_state(tgen, "r2", "*", IGMP_JOIN_RANGE_3, "SC")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R1 should not have (*,G) join and (S,G) join present")
+
+ input_dict_r1 = [
+ {
+ "dut": "r1",
+ "src_address": "*",
+ "iif": topo["routers"]["r1"]["links"]["r4"]["interface"],
+ "oil": "{}.{}".format(
+ topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ },
+ {
+ "dut": "r1",
+ "src_address": source_i2,
+ "iif": topo["routers"]["r1"]["links"]["r4"]["interface"],
+ "oil": "{}.{}".format(
+ topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ },
+ ]
+
+ for data in input_dict_r1:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3,
+ data["iif"],
+ data["oil"],
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Mroutes are still present \n Error: {}".format(tc_name, result)
+ )
+
+ step("Remove local join from DR and Non DR node")
+
+ input_dict = {
+ "r1": {
+ "igmp": {
+ "interfaces": {
+ vlan_intf_r1_s1: {
+ "igmp": {
+ "version": "2",
+ "join": IGMP_JOIN_RANGE_3,
+ "delete_attr": True,
+ }
+ }
+ }
+ }
+ },
+ "r2": {
+ "igmp": {
+ "interfaces": {
+ intf_r2_s1: {
+ "igmp": {
+ "version": "2",
+ "join": IGMP_JOIN_RANGE_3,
+ "delete_attr": True,
+ }
+ }
+ }
+ }
+ },
+ }
+
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step(
+ "After remove of local join from R1 and R2 node verify (*,G) and (S,G) mroutes "
+ "should not present on R1, R2 nodes"
+ )
+
+ for data in input_dict_r1:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3,
+ data["iif"],
+ data["oil"],
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Mroutes are still present \n Error: {}".format(tc_name, result)
+ )
+
+ for data in input_dict_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1 + IGMP_JOIN_RANGE_3,
+ data["iif"],
+ data["oil"],
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Mroutes are still present \n Error: {}".format(tc_name, result)
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_static_routes_topo1.py b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_static_routes_topo1.py
new file mode 100755
index 0000000000..aa7448f354
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_static_routes_topo1.py
@@ -0,0 +1,934 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test multicast pim sm:
+
+Test steps
+- Create topology (setup module)
+- Bring up topology
+
+Following tests are covered:
+1. Verify mroute while rebooting DR /Non DR nodes( r1, r2 , r3 on all the nodes)
+"""
+
+import os
+import sys
+import json
+import time
+import datetime
+from time import sleep
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ step,
+ reset_config_on_routers,
+ apply_raw_config,
+ add_interfaces_to_vlan,
+ stop_router,
+ start_router,
+ check_router_status,
+ topo_daemons,
+ required_linux_kernel_version,
+)
+from lib.pim import (
+ create_pim_config,
+ create_igmp_config,
+ verify_ip_mroutes,
+ clear_ip_mroute,
+ clear_ip_pim_interface_traffic,
+ verify_pim_config,
+ verify_upstream_iif,
+ verify_multicast_flag_state,
+ McastTesterHelper,
+)
+from lib.topolog import logger
+from lib.topojson import build_config_from_json
+
+HELLO_TIMER = 1
+HOLD_TIMER = 3
+
+pytestmark = [pytest.mark.pimd]
+
+TOPOLOGY = """
+
+Descripton: Configuring static routes on r1/r2/r3/r4/r5 for RP reachablility.
+IPs are assigned automatically to routers, start IP and subnet is defined in respective JSON file
+JSON snippet:
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24},
+
+ r5 ------- i2
+ 10.0.3.2/24| 10.0.0.2/24
+ |
+ 10.0.3.1/24|
+ ------------ r4 ----------
+ | 10.0.1.2/24 10.0.2.2/24 |
+ 10.0.1.1/24 | | 10.0.2.1/24
+ r1 ----------- s1 ---------- r2
+ 10.0.4.2/24 | 10.0.4.3/24
+ |
+ |10.0.4.4/24
+ i1 -------- r3
+ 10.0.4.1/24
+ Description:
+ i1, i2 - FRR running iperf to send IGMP
+ join and traffic
+ r1, r2, r3, r4, r5 - FRR ruter
+ s1 - OVS switch
+"""
+
+# Global variables
+VLAN_1 = 2501
+GROUP_RANGE = "225.0.0.0/8"
+IGMP_JOIN = "225.1.1.1"
+VLAN_INTF_ADRESS_1 = "10.0.8.3/24"
+SAME_VLAN_IP_1 = {"ip": "10.1.1.1", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_2 = {"ip": "10.1.1.2", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_3 = {"ip": "10.1.1.3", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_4 = {"ip": "10.1.1.4", "subnet": "255.255.255.0", "cidr": "24"}
+GROUP_RANGE_1 = [
+ "225.1.1.1/32",
+ "225.1.1.2/32",
+ "225.1.1.3/32",
+ "225.1.1.4/32",
+ "225.1.1.5/32",
+]
+IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
+GROUP_RANGE_2 = [
+ "226.1.1.1/32",
+ "226.1.1.2/32",
+ "226.1.1.3/32",
+ "226.1.1.4/32",
+ "226.1.1.5/32",
+]
+IGMP_JOIN_RANGE_2 = ["226.1.1.1", "226.1.1.2", "226.1.1.3", "226.1.1.4", "226.1.1.5"]
+GROUP_RANGE_3 = [
+ "227.1.1.1/32",
+ "227.1.1.2/32",
+ "227.1.1.3/32",
+ "227.1.1.4/32",
+ "227.1.1.5/32",
+]
+IGMP_JOIN_RANGE_3 = ["227.1.1.1", "227.1.1.2", "227.1.1.3", "227.1.1.4", "227.1.1.5"]
+
+intf_r1_s1 = None
+intf_r1_s1_addr = None
+intf_r2_s1 = None
+intf_r2_s1_addr = None
+intf_r3_s1 = None
+intf_r3_s1_addr = None
+intf_i1_s1 = None
+intf_i1_s1_addr = None
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.19")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+ logger.info("Master Topology: \n {}".format(TOPOLOGY))
+
+ logger.info("Running setup_module to create topology")
+
+ testdir = os.path.dirname(os.path.realpath(__file__))
+ json_file = "{}/pim_dr_nondr_with_static_routes_topo1.json".format(testdir)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, tgen.json_topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, tgen.json_topo)
+
+ # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
+ global app_helper
+ app_helper = McastTesterHelper(tgen)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ app_helper.cleanup()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+#####################################################
+#
+# Local APIs
+#
+#####################################################
+
+
+def pre_config_for_receiver_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for receiver test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_r3_s1, intf_r3_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_r3_s1 = topo["routers"]["r3"]["links"]["s1"]["interface"]
+ intf_r3_s1_addr = topo["routers"]["r3"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r3_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r3_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "r2": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_r2_s1: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_3["ip"],
+ "subnet": SAME_VLAN_IP_3["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r3": {
+ "raw_config": [
+ "interface {}".format(intf_r3_s1),
+ "no ip address {}".format(intf_r3_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r2_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_3["ip"], SAME_VLAN_IP_3["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2", "r3"], [intf_r1_s1, intf_r2_s1, intf_r3_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Send IGMP join for groups 226.1.1.1 to 226.1.1.5")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_join("i1", IGMP_JOIN_RANGE_1, join_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Using static routes instead OSPF: Enable OSPF between all the nodes")
+
+ step("Start traffic from R4 connected source")
+
+ result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+def pre_config_for_source_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for source test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_r3_s1, intf_r3_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_r3_s1 = topo["routers"]["r3"]["links"]["s1"]["interface"]
+ intf_r3_s1_addr = topo["routers"]["r3"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r3_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r3_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "r2": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_r2_s1: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_3["ip"],
+ "subnet": SAME_VLAN_IP_3["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r3": {
+ "raw_config": [
+ "interface {}".format(intf_r3_s1),
+ "no ip address {}".format(intf_r3_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "Configure IGMP and PIM on switch connected receiver nodes , "
+ "configure PIM nbr with hello timer 1"
+ )
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r2_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_3["ip"], SAME_VLAN_IP_3["cidr"]),
+ "ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2", "r3"], [intf_r1_s1, intf_r2_s1, intf_r3_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure IGMP on R5 port and send IGMP join for groups " "(226.1.1.1-5)")
+
+ intf_r5_i2 = topo["routers"]["r5"]["links"]["i2"]["interface"]
+ input_dict = {
+ "r5": {"igmp": {"interfaces": {intf_r5_i2: {"igmp": {"version": "2"}}}}}
+ }
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ input_src = {"i2": topo["routers"]["i2"]["links"]["r5"]["interface"]}
+
+ result = app_helper.run_join("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Using static routes instead OSPF: Enable OSPF between all the nodes")
+
+ step("Start traffic from Source node")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_traffic("i1", IGMP_JOIN_RANGE_1, bind_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_pim_source_dr_functionality_while_rebooting_dr_non_dr_nodes_p1(request):
+ """
+ Verify mroute while rebooting DR /Non DR nodes( r1, r2 , r3 on all the nodes)
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ app_helper.stop_all_hosts()
+ clear_ip_mroute(tgen)
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ clear_ip_pim_interface_traffic(tgen, topo)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ result = pre_config_for_source_dr_tests(tgen, topo, tc_name, "r1", "r3")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R1 is the DR , verify using 'show ip pim interface json'")
+
+ vlan_intf_r1_s1 = "{}.{}".format(intf_r1_s1, VLAN_1)
+ input_dict_dr = {
+ "r1": {
+ "pim": {
+ "interfaces": {vlan_intf_r1_s1: {"drAddress": SAME_VLAN_IP_3["ip"]}}
+ }
+ }
+ }
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "R2 is transit router for R3 to reach R4, mroute should have (s, g) mroute with "
+ "OIL towards R4, using 'show ip mroute json'"
+ )
+ step(
+ "R2 (s, g) upstream should be in join state verify using "
+ "'show ip pim upstream json'"
+ )
+ step(
+ "R1 has (S, G) mroute with NONE OIL and upstream as not joined, verify using "
+ "'show ip mroute json' 'show ip pim upstream json'"
+ )
+
+ source_i1 = SAME_VLAN_IP_4["ip"]
+ input_dict_r1_r2 = [
+ {
+ "dut": "r1",
+ "src_address": source_i1,
+ "oil": "none",
+ "iif": "{}.{}".format(
+ topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ },
+ {
+ "dut": "r2",
+ "src_address": source_i1,
+ "oil": topo["routers"]["r2"]["links"]["r4"]["interface"],
+ "iif": "{}.{}".format(
+ topo["routers"]["r2"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ },
+ ]
+
+ for data in input_dict_r1_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ if data["dut"] == "r2":
+ result = verify_upstream_iif(
+ tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(
+ tc_name, result
+ )
+ else:
+ result = verify_upstream_iif(
+ tgen,
+ data["dut"],
+ data["iif"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Upstream is still joined state \n Error: {}".format(tc_name, result)
+ )
+
+ step("Reboot R3 node")
+ stop_router(tgen, "r3")
+
+ step("After reboot of R3 verify R1 became DR, using 'show ip pim interface json'")
+
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R3 should not have any mroute and upstream")
+ step("R2 has mroute with OIL towards R4 /R1 , verify using 'show ip mroute'")
+ step(
+ "R2 has upstream with Join RejP state verify using 'show ip pim upstream json'"
+ )
+ step("R1 has mroute with none OIL and upstream with Not Join")
+
+ for data in input_dict_r1_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ if data["dut"] == "r2":
+ result = verify_upstream_iif(
+ tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(
+ tc_name, result
+ )
+ else:
+ result = verify_upstream_iif(
+ tgen,
+ data["dut"],
+ data["iif"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Upstream is still joined state \n Error: {}".format(tc_name, result)
+ )
+
+ step("Reboot R2 node")
+ stop_router(tgen, "r2")
+
+ step("After reboot of R2, R1 became DR verify using 'show ip pim interface json'")
+
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "R3 and R2 should not have any mroute and upstream , verify using "
+ "'show ip mroute json' 'show ip pim upstream json'"
+ )
+ step("R1 has mroute created with OIL towards R4 , using 'show ip mroute json'")
+ step(
+ "R1 has upstream with Join Rej Prune , verify using 'show ip pim upstream json'"
+ )
+
+ for data in input_dict_r1_r2:
+ if data["dut"] == "r1":
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_upstream_iif(
+ tgen,
+ data["dut"],
+ data["iif"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Upstream is still joined state \n Error: {}".format(tc_name, result)
+ )
+
+ step("Reboot R1 node using FRR stop")
+ stop_router(tgen, "r1")
+
+ step(
+ "After stop of all the routers, verify upstream and mroutes should "
+ "not present in any of them"
+ )
+
+ for data in input_dict_r1_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ expected=False,
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "mroutes are still present \n Error: {}".format(tc_name, result)
+ )
+
+ step("start FRR for all the nodes")
+ start_router(tgen, "r1")
+ start_router(tgen, "r2")
+ start_router(tgen, "r3")
+
+ step("After start of all the routers, R1 became DR")
+
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for data in input_dict_r1_r2:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ if data["dut"] == "r2":
+ result = verify_upstream_iif(
+ tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_transit_router_topo3.py b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_transit_router_topo3.py
new file mode 100755
index 0000000000..1e290a0348
--- /dev/null
+++ b/tests/topotests/multicast_pim_dr_nondr_test/test_pim_dr_nondr_with_transit_router_topo3.py
@@ -0,0 +1,829 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test multicast pim sm:
+
+Test steps
+- Create topology (setup module)
+- Bring up topology
+
+Following tests are covered:
+1. Verify mroutes when transit router present between RP and Source DR
+"""
+
+import os
+import sys
+import json
+import time
+import datetime
+from time import sleep
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ step,
+ reset_config_on_routers,
+ apply_raw_config,
+ add_interfaces_to_vlan,
+ check_router_status,
+ topo_daemons,
+ required_linux_kernel_version,
+)
+from lib.pim import (
+ create_pim_config,
+ create_igmp_config,
+ verify_ip_mroutes,
+ clear_ip_mroute,
+ clear_ip_pim_interface_traffic,
+ verify_pim_config,
+ verify_upstream_iif,
+ verify_multicast_traffic,
+ McastTesterHelper,
+)
+from lib.topolog import logger
+from lib.topojson import build_config_from_json
+
+HELLO_TIMER = 1
+HOLD_TIMER = 3
+
+pytestmark = [pytest.mark.pimd]
+
+TOPOLOGY = """
+
+Descripton: Configuring OSPF on r1/r2/r4/r5/r6 for RP reachablility, We have r6 as a transit router between
+ r1/r2 and r4.
+IPs are assigned automatically to routers, start IP and subnet is defined in respective JSON file
+JSON snippet:
+ "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 24},
+
+ r5 ------- i2
+ 10.0.3.2/24| 10.0.0.2/24
+ |
+ 10.0.3.1/24|
+ r4
+ |10.0.4.1/24
+ |
+ 10.0.4.2/24|
+ ------------ r6 ----------
+ | 10.0.1.2/24 10.0.2.2/24 |
+ 10.0.1.1/24 | | 10.0.2.1/24
+ r1 ----------- s1 ---------- r2
+ 10.0.5.2/24 | 10.0.5.3/24
+ |
+ |10.0.5.1/24
+ i1
+
+
+
+ Description:
+ i1, i2 - FRR running iperf to send IGMP
+ join and traffic
+ r1, r2, r4, r5, r6 - FRR ruter
+ s1 - OVS switch
+"""
+
+# Global variables
+VLAN_1 = 2501
+GROUP_RANGE = "225.0.0.0/8"
+IGMP_JOIN = "225.1.1.1"
+VLAN_INTF_ADRESS_1 = "10.0.8.3/24"
+SAME_VLAN_IP_1 = {"ip": "10.1.1.1", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_2 = {"ip": "10.1.1.2", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_3 = {"ip": "10.1.1.3", "subnet": "255.255.255.0", "cidr": "24"}
+SAME_VLAN_IP_4 = {"ip": "10.1.1.4", "subnet": "255.255.255.0", "cidr": "24"}
+GROUP_RANGE_1 = [
+ "225.1.1.1/32",
+ "225.1.1.2/32",
+ "225.1.1.3/32",
+ "225.1.1.4/32",
+ "225.1.1.5/32",
+]
+IGMP_JOIN_RANGE_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
+GROUP_RANGE_2 = [
+ "226.1.1.1/32",
+ "226.1.1.2/32",
+ "226.1.1.3/32",
+ "226.1.1.4/32",
+ "226.1.1.5/32",
+]
+IGMP_JOIN_RANGE_2 = ["226.1.1.1", "226.1.1.2", "226.1.1.3", "226.1.1.4", "226.1.1.5"]
+GROUP_RANGE_3 = [
+ "227.1.1.1/32",
+ "227.1.1.2/32",
+ "227.1.1.3/32",
+ "227.1.1.4/32",
+ "227.1.1.5/32",
+]
+IGMP_JOIN_RANGE_3 = ["227.1.1.1", "227.1.1.2", "227.1.1.3", "227.1.1.4", "227.1.1.5"]
+
+intf_r1_s1 = None
+intf_r1_s1_addr = None
+intf_r2_s1 = None
+intf_r2_s1_addr = None
+intf_r3_s1 = None
+intf_r3_s1_addr = None
+intf_i1_s1 = None
+intf_i1_s1_addr = None
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.19")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+ logger.info("Master Topology: \n {}".format(TOPOLOGY))
+
+ logger.info("Running setup_module to create topology")
+
+ testdir = os.path.dirname(os.path.realpath(__file__))
+ json_file = "{}/pim_dr_nondr_with_transit_router_topo3.json".format(testdir)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, tgen.json_topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, tgen.json_topo)
+
+ # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
+ global app_helper
+ app_helper = McastTesterHelper(tgen)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ app_helper.cleanup()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Local APIs
+#
+#####################################################
+
+
+def pre_config_for_receiver_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for receiver test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r2_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r2_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ "ip igmp",
+ "ip igmp version 2",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Send IGMP join for groups 226.1.1.1 to 226.1.1.5")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_join("i1", IGMP_JOIN_RANGE_1, join_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Enable OSPF between r1 and r2")
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip ospf area 0.0.0.0",
+ "ip ospf dead-interval 4",
+ "ip ospf hello-interval 1",
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Start traffic from R4 connected source")
+
+ result = app_helper.run_traffic("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+def pre_config_for_source_dr_tests(
+ tgen, topo, tc_name, highest_priority, lowest_priority
+):
+ """
+ API to do common pre-configuration for source test cases
+
+ parameters:
+ -----------
+ * `tgen`: topogen object
+ * `topo`: input json data
+ * `tc_name`: caller test case name
+ * `highest_priority`: router which will be having highest DR priority
+ * `lowest_priority`: router which will be having lowest DR priority
+ """
+
+ global intf_r1_s1, intf_r1_s1_addr, intf_r2_s1, intf_r2_s1_addr, intf_i1_s1, intf_i1_s1_addr
+
+ step("Configure IGMP and PIM on switch connected receiver nodes")
+ step("Configure PIM on all upstream interfaces")
+
+ step("Configure link between R1, R2 ,R3 and receiver on" " same vlan")
+ step(
+ "Make sure {0} is DR initially configuring highest IP on {0} and R2 "
+ "second highest, {1} is lower".format(highest_priority, lowest_priority)
+ )
+
+ intf_r1_s1 = topo["routers"]["r1"]["links"]["s1"]["interface"]
+ intf_r1_s1_addr = topo["routers"]["r1"]["links"]["s1"]["ipv4"]
+
+ intf_r2_s1 = topo["routers"]["r2"]["links"]["s1"]["interface"]
+ intf_r2_s1_addr = topo["routers"]["r2"]["links"]["s1"]["ipv4"]
+
+ intf_i1_s1 = topo["routers"]["i1"]["links"]["s1"]["interface"]
+ intf_i1_s1_addr = topo["routers"]["i1"]["links"]["s1"]["ipv4"]
+
+ if lowest_priority == "r1":
+ lowest_pr_intf = intf_r1_s1
+ else:
+ lowest_pr_intf = intf_r2_s1
+
+ if highest_priority == "r1":
+ highest_pr_intf = intf_r1_s1
+ else:
+ highest_pr_intf = intf_r2_s1
+
+ vlan_input = {
+ lowest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ lowest_pr_intf: {
+ "ip": SAME_VLAN_IP_1["ip"],
+ "subnet": SAME_VLAN_IP_1["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ highest_priority: {
+ "vlan": {
+ VLAN_1: [
+ {
+ highest_pr_intf: {
+ "ip": SAME_VLAN_IP_2["ip"],
+ "subnet": SAME_VLAN_IP_2["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ "i1": {
+ "vlan": {
+ VLAN_1: [
+ {
+ intf_i1_s1: {
+ "ip": SAME_VLAN_IP_4["ip"],
+ "subnet": SAME_VLAN_IP_4["subnet"],
+ }
+ }
+ ]
+ }
+ },
+ }
+
+ add_interfaces_to_vlan(tgen, vlan_input)
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}".format(intf_r1_s1),
+ "no ip address {}".format(intf_r1_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}".format(intf_r2_s1),
+ "no ip address {}".format(intf_r2_s1_addr),
+ "no ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}".format(intf_i1_s1),
+ "no ip address {}".format(intf_i1_s1_addr),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "Configure IGMP and PIM on switch connected receiver nodes , "
+ "configure PIM nbr with hello timer 1"
+ )
+
+ raw_config = {
+ lowest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(lowest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ "ip pim",
+ ]
+ },
+ highest_priority: {
+ "raw_config": [
+ "interface {}.{}".format(highest_pr_intf, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ "ip pim",
+ ]
+ },
+ "i1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_i1_s1, VLAN_1),
+ "ip address {}/{}".format(SAME_VLAN_IP_4["ip"], SAME_VLAN_IP_4["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip pim hello {} {}".format(HELLO_TIMER, HOLD_TIMER),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure R4 as RP on all the nodes for group range 224.0.0.0/24")
+
+ input_dict = {
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": topo["routers"]["r4"]["links"]["lo"]["ipv4"].split(
+ "/"
+ )[0],
+ "group_addr_range": GROUP_RANGE_1,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Configure IGMP on R5 port and send IGMP join for groups " "(226.1.1.1-5)")
+
+ intf_r5_i2 = topo["routers"]["r5"]["links"]["i2"]["interface"]
+ input_dict = {
+ "r5": {"igmp": {"interfaces": {intf_r5_i2: {"igmp": {"version": "2"}}}}}
+ }
+ result = create_igmp_config(tgen, topo, input_dict)
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ result = app_helper.run_join("i2", IGMP_JOIN_RANGE_1, "r5")
+ assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
+
+ step("Enable OSPF between r1 and r2")
+
+ for dut, intf in zip(["r1", "r2"], [intf_r1_s1, intf_r2_s1]):
+ raw_config = {
+ dut: {
+ "raw_config": [
+ "interface {}.{}".format(intf, VLAN_1),
+ "ip ospf area 0.0.0.0",
+ "ip ospf dead-interval 4",
+ "ip ospf hello-interval 1",
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Start traffic from Source node")
+
+ vlan_intf_i1_s1 = "{}.{}".format(intf_i1_s1, VLAN_1)
+ result = app_helper.run_traffic("i1", IGMP_JOIN_RANGE_1, bind_intf=vlan_intf_i1_s1)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ return True
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_mroute_when_transit_router_present_between_rp_and_source_dr_p1(request):
+ """
+ Verify mroutes when transit router present between RP and Source DR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ app_helper.stop_all_hosts()
+ clear_ip_mroute(tgen)
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ clear_ip_pim_interface_traffic(tgen, topo)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ result = pre_config_for_source_dr_tests(tgen, topo, tc_name, "r1", "r2")
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Taken care in base config: Add router R6 between RP and R1 , R2")
+
+ step("R1 is the DR, mroute and upstream created on R1")
+
+ vlan_intf_r1_s1 = "{}.{}".format(intf_r1_s1, VLAN_1)
+ input_dict_dr = {
+ "r1": {
+ "pim": {
+ "interfaces": {vlan_intf_r1_s1: {"drAddress": SAME_VLAN_IP_2["ip"]}}
+ }
+ }
+ }
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("On R1 Mroute OIL towards R6, upstream in join Rej Prune state")
+
+ source_i1 = SAME_VLAN_IP_4["ip"]
+ input_dict_r1 = [
+ {
+ "dut": "r1",
+ "src_address": source_i1,
+ "oil": topo["routers"]["r1"]["links"]["r6"]["interface"],
+ "iif": "{}.{}".format(
+ topo["routers"]["r1"]["links"]["s1"]["interface"], VLAN_1
+ ),
+ }
+ ]
+
+ for data in input_dict_r1:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ result = verify_upstream_iif(
+ tgen, data["dut"], data["iif"], data["src_address"], IGMP_JOIN_RANGE_1
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "R5 have mroute created and traffic is received, verify using "
+ "'show ip mroute json' 'show ip multicast json'"
+ )
+
+ input_dict_r5 = [
+ {
+ "dut": "r5",
+ "src_address": "*",
+ "iif": topo["routers"]["r5"]["links"]["r4"]["interface"],
+ "oil": topo["routers"]["r5"]["links"]["i2"]["interface"],
+ },
+ {
+ "dut": "r5",
+ "src_address": source_i1,
+ "iif": topo["routers"]["r5"]["links"]["r4"]["interface"],
+ "oil": topo["routers"]["r5"]["links"]["i2"]["interface"],
+ },
+ ]
+
+ for data in input_dict_r5:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ input_dict_traffic_r5 = {
+ "r5": {
+ "traffic_received": [topo["routers"]["r5"]["links"]["r4"]["interface"]],
+ "traffic_sent": [topo["routers"]["r5"]["links"]["i2"]["interface"]],
+ }
+ }
+
+ result = verify_multicast_traffic(tgen, input_dict_traffic_r5)
+ assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+ step("Make R2 as DR configuring higher priority value")
+
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r1_s1, VLAN_1),
+ "no ip address {}/{}".format(
+ SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_1["cidr"]
+ ),
+ "ip address {}/{}".format(SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]),
+ ]
+ },
+ "r2": {
+ "raw_config": [
+ "interface {}.{}".format(intf_r2_s1, VLAN_1),
+ "no ip address {}/{}".format(
+ SAME_VLAN_IP_1["ip"], SAME_VLAN_IP_1["cidr"]
+ ),
+ "ip address {}/{}".format(SAME_VLAN_IP_2["ip"], SAME_VLAN_IP_2["cidr"]),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("R2 is the DR, mroute and upstream created on R2")
+
+ vlan_intf_r2_s1 = "{}.{}".format(intf_r2_s1, VLAN_1)
+ input_dict_dr = {
+ "r2": {
+ "pim": {
+ "interfaces": {vlan_intf_r2_s1: {"drAddress": SAME_VLAN_IP_2["ip"]}}
+ }
+ }
+ }
+ result = verify_pim_config(tgen, input_dict_dr)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "R5 have mroute created and traffic is received, verify using "
+ "'show ip mroute json' 'show ip multicast json'"
+ )
+
+ for data in input_dict_r5:
+ result = verify_ip_mroutes(
+ tgen,
+ data["dut"],
+ data["src_address"],
+ IGMP_JOIN_RANGE_1,
+ data["iif"],
+ data["oil"],
+ )
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ result = verify_multicast_traffic(tgen, input_dict_traffic_r5)
+ assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
index 304128e44c..6f3867cc2c 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
@@ -2834,9 +2834,7 @@ def test_mroute_after_removing_RP_sending_IGMP_prune_p2(request):
intf_f1_i8 = topo["routers"]["f1"]["links"]["i8"]["interface"]
input_traffic = {"f1": {"traffic_sent": [intf_f1_i8]}}
- traffic_before = verify_multicast_traffic(
- tgen, input_traffic, return_traffic=True, expected=False
- )
+ traffic_before = verify_multicast_traffic(tgen, input_traffic, return_traffic=True)
assert isinstance(traffic_before, dict), (
"Testcase {} : Failed \n traffic_before is not dictionary \n "
"Error: {}".format(tc_name, result)
@@ -2861,9 +2859,7 @@ def test_mroute_after_removing_RP_sending_IGMP_prune_p2(request):
intf_f1_i8 = topo["routers"]["f1"]["links"]["i8"]["interface"]
input_traffic = {"f1": {"traffic_sent": [intf_f1_i8]}}
- traffic_after = verify_multicast_traffic(
- tgen, input_traffic, return_traffic=True, expected=False
- )
+ traffic_after = verify_multicast_traffic(tgen, input_traffic, return_traffic=True)
assert isinstance(traffic_after, dict), (
"Testcase {} : Failed \n traffic_after is not dictionary \n "
"Error: {}".format(tc_name, result)
@@ -3274,8 +3270,6 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
intf_r2_l1 = topo["routers"]["r2"]["links"]["l1"]["interface"]
shutdown_bringup_interface(tgen, "r2", intf_r2_l1, False)
- app_helper.stop_host("i2")
-
step("Verify RP info after Shut the link from FHR to RP from RP node")
dut = "l1"
rp_address = "1.0.5.17"
@@ -3426,8 +3420,6 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
step("Verify PIM Nbrs after Shut the link from FHR to RP from FHR node")
- app_helper.stop_host("i6")
-
step("Verify RP info after Shut the link from FHR to RP from FHR node")
dut = "l1"
rp_address = "1.0.5.17"
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 210f960b60..b9a7cc7cd7 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
@@ -69,7 +69,7 @@ TC_18 : Verify RPF interface updated in mroute when higher preferred RP gets
deleted
TC_19 : Verify IIF and OIL in "show ip pim state" updated when higher
preferred overlapping RP is deleted
-TC_20 : Verfiy PIM upstream IIF updated when higher preferred overlapping RP
+TC_20 : Verify PIM upstream IIF updated when higher preferred overlapping RP
deleted
TC_21_1 : Verify OIF and RFP for (*,G) and (S,G) when static RP configure in
LHR router
@@ -94,7 +94,7 @@ TC_30 : Verify IIF and OIL change to other path after shut the primary path
TC_31 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
shut the RPF interface.
TC_32 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
- shut the RPF inteface
+ shut the RPF interface
"""
import os
@@ -1157,7 +1157,7 @@ def test_send_join_on_higher_preffered_rp_p1(request):
gets deleted
TC_19_P1 : Verify IIF and OIL in "show ip pim state" updated when higher
preferred overlapping RP is deleted
- TC_20_P1 : Verfiy PIM upstream IIF updated when higher preferred
+ TC_20_P1 : Verify PIM upstream IIF updated when higher preferred
overlapping RP deleted
Topology used:
@@ -1354,7 +1354,7 @@ def test_send_join_on_higher_preffered_rp_p1(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "r1 : Verfiy upstream IIF updated when higher preferred overlapping"
+ "r1 : Verify upstream IIF updated when higher preferred overlapping"
"RP deleted"
)
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
@@ -3820,7 +3820,7 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
def test_delete_RP_shut_noshut_RP_interface_p1(request):
"""
TC_32_P1: Verify RP info and (*,G) mroute after deleting the RP and shut/
- no shut the RPF inteface
+ no shut the RPF interface
Topology used:
________r2_____
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
index 01ddbc1521..5903649d67 100644
--- a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
@@ -79,7 +79,7 @@ def setup_module(mod):
# This is a sample of configuration loading.
router_list = tgen.routers()
- # For all registred routers, load the zebra and ospf configuration file
+ # For all registered routers, load the zebra and ospf configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
diff --git a/tests/topotests/simple_snmp_test/test_simple_snmp.py b/tests/topotests/simple_snmp_test/test_simple_snmp.py
index 35f0210134..1ca06c6571 100755
--- a/tests/topotests/simple_snmp_test/test_simple_snmp.py
+++ b/tests/topotests/simple_snmp_test/test_simple_snmp.py
@@ -69,7 +69,7 @@ def setup_module(mod):
router_list = tgen.routers()
- # For all registred routers, load the zebra configuration file
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
index 8c97d6cb7e..d5e5148eae 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
@@ -175,7 +175,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
)
for addr_type in ADDR_TYPES:
- # Api call to modfiy BGP timerse
+ # Api call to modify BGP timerse
input_dict = {
"r2": {
"bgp": {
diff --git a/tests/topotests/zebra_multiple_connected/r1/ip_route.json b/tests/topotests/zebra_multiple_connected/r1/ip_route.json
new file mode 100644
index 0000000000..c29f2f9786
--- /dev/null
+++ b/tests/topotests/zebra_multiple_connected/r1/ip_route.json
@@ -0,0 +1,62 @@
+{
+ "10.0.1.0/24":[
+ {
+ "prefix":"10.0.1.0/24",
+ "prefixLen":24,
+ "protocol":"connected",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0/24",
+ "prefixLen":24,
+ "protocol":"connected",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.1.1/32":[
+ {
+ "prefix":"192.168.1.1/32",
+ "prefixLen":32,
+ "protocol":"kernel",
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.99",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/zebra_multiple_connected/r1/ip_route2.json b/tests/topotests/zebra_multiple_connected/r1/ip_route2.json
new file mode 100644
index 0000000000..26995654f7
--- /dev/null
+++ b/tests/topotests/zebra_multiple_connected/r1/ip_route2.json
@@ -0,0 +1,102 @@
+{
+ "10.0.1.0/24":[
+ {
+ "prefix":"10.0.1.0/24",
+ "prefixLen":24,
+ "protocol":"connected",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0/24",
+ "prefixLen":24,
+ "protocol":"connected",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.30/32":[
+ {
+ "prefix":"10.0.1.30/32",
+ "prefixLen":32,
+ "protocol":"kernel",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.9.9.0/24":[
+ {
+ "prefix":"10.9.9.0/24",
+ "prefixLen":24,
+ "protocol":"kernel",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.30",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.1.1/32":[
+ {
+ "prefix":"192.168.1.1/32",
+ "prefixLen":32,
+ "protocol":"kernel",
+ "vrfName":"default",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.99",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/zebra_multiple_connected/r1/zebra.conf b/tests/topotests/zebra_multiple_connected/r1/zebra.conf
new file mode 100644
index 0000000000..81adcadea8
--- /dev/null
+++ b/tests/topotests/zebra_multiple_connected/r1/zebra.conf
@@ -0,0 +1,9 @@
+interface r1-eth0
+ ip address 10.0.1.1/24
+!
+interface r1-eth1
+ ip address 10.0.1.2/24
+!
+interface r1-eth2
+ ip address 10.0.1.3/24
+! \ No newline at end of file
diff --git a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py
new file mode 100644
index 0000000000..8882cf5bda
--- /dev/null
+++ b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+
+#
+# test_zebra_multiple_connected.py
+#
+# Copyright (c) 2022 by
+# Nvidia Corporation
+# Donald Sharp
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_zebra_multiple_connected.py: Testing multiple connected
+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ # On main router
+ # First switch is for a dummy interface (for local network)
+ switch = tgen.add_switch("sw1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Switches for zebra
+ # switch 2 switch is for connection to zebra router
+ switch = tgen.add_switch("sw2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # switch 4 is stub on remote zebra router
+ switch = tgen.add_switch("sw4")
+ switch.add_link(tgen.gears["r3"])
+
+ # switch 3 is between zebra routers
+ switch = tgen.add_switch("sw3")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+
+def setup_module(module):
+ "Setup topology"
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_zebra_connected_multiple():
+ "Test multiple connected routes that have a kernel route pointing at one"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+ router.run("ip route add 192.168.1.1/32 via 10.0.1.99 dev r1-eth1")
+ router.run("ip link add dummy1 type dummy")
+ router.run("ip link set dummy1 up")
+ router.run("ip link set dummy1 down")
+
+ routes = "{}/{}/ip_route.json".format(CWD, router.name)
+ expected = json.loads(open(routes).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route json", expected
+ )
+
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assert result is None, "Kernel route is missing from zebra"
+
+
+def test_zebra_system_recursion():
+ "Test a system route recursing through another system route"
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+ router.run("ip route add 10.0.1.30/32 dev r1-eth1")
+ router.run("ip route add 10.9.9.0/24 via 10.0.1.30 dev r1-eth1")
+ router.run("ip link add dummy2 type dummy")
+ router.run("ip link set dummy2 up")
+ router.run("ip link set dummy2 down")
+
+ routes = "{}/{}/ip_route2.json".format(CWD, router.name)
+ expected = json.loads(open(routes).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route json", expected
+ )
+
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assert result is None, "Kernel route is missing from zebra"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tools/etc/rsyslog.d/45-frr.conf b/tools/etc/rsyslog.d/45-frr.conf
index feeeb13f13..469e95ed73 100644
--- a/tools/etc/rsyslog.d/45-frr.conf
+++ b/tools/etc/rsyslog.d/45-frr.conf
@@ -14,6 +14,7 @@ if $programname == 'babeld' or
$programname == 'ospf6d' or
$programname == 'ospfd' or
$programname == 'pimd' or
+ $programname == 'pathd' or
$programname == 'ripd' or
$programname == 'ripngd' or
$programname == 'vrrpd' or
@@ -32,6 +33,7 @@ if $programname == 'babeld' or
$programname == 'ospf6d' or
$programname == 'ospfd' or
$programname == 'pimd' or
+ $programname == 'pathd' or
$programname == 'ripd' or
$programname == 'ripngd' or
$programname == 'vrrpd' or
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index 2b76c43f7b..4f30f7fbd8 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1752,7 +1752,7 @@ if __name__ == "__main__":
elif args.reload:
if not os.path.isdir("/var/log/frr/"):
- os.makedirs("/var/log/frr/")
+ os.makedirs("/var/log/frr/", mode=0o0755)
logging.basicConfig(
filename="/var/log/frr/frr-reload.log",
diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in
index df5f0853da..bc93ea33f0 100644
--- a/tools/frrinit.sh.in
+++ b/tools/frrinit.sh.in
@@ -127,6 +127,8 @@ reload)
;;
*)
- log_failure_msg "Unknown command: $1" >&2
+ echo "Usage:"
+ echo " ${0} (start|stop|restart|force-reload|reload|status)"
exit 1
+ ;;
esac
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index e3e61d1229..74886254bd 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -3204,7 +3204,7 @@ DEFUN (vtysh_write_terminal,
"Skip \"Building configuration...\" header\n")
{
unsigned int i;
- char line[] = "do write terminal\n";
+ char line[] = "do write terminal";
if (!strcmp(argv[argc - 1]->arg, "no-header"))
argc--;
@@ -3283,7 +3283,7 @@ static void backup_config_file(const char *fbackup)
int vtysh_write_config_integrated(void)
{
unsigned int i;
- char line[] = "do write terminal\n";
+ char line[] = "do write terminal";
FILE *fp;
int fd;
#ifdef FRR_USER
@@ -3361,6 +3361,18 @@ int vtysh_write_config_integrated(void)
err++;
}
+ if (fflush(fp) != 0) {
+ printf("%% Warning: fflush() failed on %s: %s\n", frr_config,
+ safe_strerror(errno));
+ err++;
+ }
+
+ if (fsync(fd) < 0) {
+ printf("%% Warning: fsync() failed on %s: %s\n", frr_config,
+ safe_strerror(errno));
+ err++;
+ }
+
fclose(fp);
printf("Integrated configuration saved to %s\n", frr_config);
@@ -3396,7 +3408,7 @@ DEFUN (vtysh_write_memory,
"Write configuration to the file (same as write memory)\n")
{
int ret = CMD_SUCCESS;
- char line[] = "do write memory\n";
+ char line[] = "do write memory";
unsigned int i;
vty_out(vty, "Note: this version of vtysh never writes vtysh.conf\n");
@@ -3723,7 +3735,7 @@ DEFPY (vtysh_terminal_monitor,
"Receive log messages to active VTY session\n"
DAEMONS_STR)
{
- static const char line[] = "terminal monitor\n";
+ static const char line[] = "terminal monitor";
int ret_all = CMD_SUCCESS, ret, fd;
size_t i, ok = 0;
@@ -3775,7 +3787,7 @@ DEFPY (no_vtysh_terminal_monitor,
"Receive log messages to active VTY session\n"
DAEMONS_STR)
{
- static const char line[] = "no terminal monitor\n";
+ static const char line[] = "no terminal monitor";
int ret_all = CMD_SUCCESS, ret;
size_t i, ok = 0;
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index 4f50da380c..51e4f802c9 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -54,6 +54,7 @@
#define DEFAULT_LOGLEVEL LOG_INFO
#define DEFAULT_MIN_RESTART 60
#define DEFAULT_MAX_RESTART 600
+#define DEFAULT_OPERATIONAL_TIMEOUT 60
#define DEFAULT_RESTART_CMD WATCHFRR_SH_PATH " restart %s"
#define DEFAULT_START_CMD WATCHFRR_SH_PATH " start %s"
@@ -70,14 +71,14 @@ struct thread_master *master;
static bool watch_only = false;
const char *pathspace;
-typedef enum {
+enum restart_phase {
PHASE_NONE = 0,
PHASE_INIT,
PHASE_STOPS_PENDING,
PHASE_WAITING_DOWN,
PHASE_ZEBRA_RESTART_PENDING,
PHASE_WAITING_ZEBRA_UP
-} restart_phase_t;
+};
static const char *const phase_str[] = {
"Idle",
@@ -103,15 +104,17 @@ struct restart_info {
};
static struct global_state {
- restart_phase_t phase;
+ enum restart_phase phase;
struct thread *t_phase_hanging;
struct thread *t_startup_timeout;
+ struct thread *t_operational;
const char *vtydir;
long period;
long timeout;
long restart_timeout;
long min_restart_interval;
long max_restart_interval;
+ long operational_timeout;
struct daemon *daemons;
const char *restart_command;
const char *start_command;
@@ -131,18 +134,19 @@ static struct global_state {
.loglevel = DEFAULT_LOGLEVEL,
.min_restart_interval = DEFAULT_MIN_RESTART,
.max_restart_interval = DEFAULT_MAX_RESTART,
+ .operational_timeout = DEFAULT_OPERATIONAL_TIMEOUT,
.restart_command = DEFAULT_RESTART_CMD,
.start_command = DEFAULT_START_CMD,
.stop_command = DEFAULT_STOP_CMD,
};
-typedef enum {
+enum daemon_state {
DAEMON_INIT,
DAEMON_DOWN,
DAEMON_CONNECTING,
DAEMON_UP,
DAEMON_UNRESPONSIVE
-} daemon_state_t;
+};
#define IS_UP(DMN) \
(((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE))
@@ -153,7 +157,7 @@ static const char *const state_str[] = {
struct daemon {
const char *name;
- daemon_state_t state;
+ enum daemon_state state;
int fd;
struct timeval echo_sent;
unsigned int connect_tries;
@@ -177,6 +181,7 @@ struct daemon {
#define OPTION_MAXRESTART 2001
#define OPTION_DRY 2002
#define OPTION_NETNS 2003
+#define OPTION_MAXOPERATIONAL 2004
static const struct option longopts[] = {
{"daemon", no_argument, NULL, 'd'},
@@ -191,6 +196,7 @@ static const struct option longopts[] = {
{"dry", no_argument, NULL, OPTION_DRY},
{"min-restart-interval", required_argument, NULL, OPTION_MINRESTART},
{"max-restart-interval", required_argument, NULL, OPTION_MAXRESTART},
+ {"operational-timeout", required_argument, NULL, OPTION_MAXOPERATIONAL},
{"pid-file", required_argument, NULL, 'p'},
{"blank-string", required_argument, NULL, 'b'},
#ifdef GNU_LINUX
@@ -265,6 +271,9 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
--max-restart-interval\n\
Set the maximum seconds to wait between invocations of daemon\n\
restart commands (default is %d).\n\
+ --operational-timeout\n\
+ Set the time before systemd is notified that we are considered\n\
+ operational again after a daemon restart (default is %d).\n\
-i, --interval Set the status polling interval in seconds (default is %d)\n\
-t, --timeout Set the unresponsiveness timeout in seconds (default is %d)\n\
-T, --restart-timeout\n\
@@ -296,10 +305,10 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
-v, --version Print program version\n\
-h, --help Display this help and exit\n",
frr_vtydir, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG,
- DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD,
- DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT,
- DEFAULT_RESTART_CMD, DEFAULT_START_CMD, DEFAULT_STOP_CMD,
- frr_vtydir);
+ DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART,
+ DEFAULT_OPERATIONAL_TIMEOUT, DEFAULT_PERIOD, DEFAULT_TIMEOUT,
+ DEFAULT_RESTART_TIMEOUT, DEFAULT_RESTART_CMD, DEFAULT_START_CMD,
+ DEFAULT_STOP_CMD, frr_vtydir);
}
static pid_t run_background(char *shell_cmd)
@@ -502,8 +511,6 @@ static int run_job(struct restart_info *restart, const char *cmdtype,
restart->pid = 0;
}
- systemd_send_status("FRR Operational");
-
/* Calculate the new restart interval. */
if (update_interval) {
if (delay.tv_sec > 2 * gs.max_restart_interval)
@@ -584,6 +591,11 @@ static void restart_done(struct daemon *dmn)
SET_WAKEUP_DOWN(dmn);
}
+static void daemon_restarting_operational(struct thread *thread)
+{
+ systemd_send_status("FRR Operational");
+}
+
static void daemon_down(struct daemon *dmn, const char *why)
{
if (IS_UP(dmn) || (dmn->state == DAEMON_INIT))
@@ -603,6 +615,8 @@ static void daemon_down(struct daemon *dmn, const char *why)
THREAD_OFF(dmn->t_wakeup);
if (try_connect(dmn) < 0)
SET_WAKEUP_DOWN(dmn);
+
+ systemd_send_status("FRR partially operational");
phase_check();
}
@@ -721,8 +735,15 @@ static void daemon_up(struct daemon *dmn, const char *why)
gs.numdown--;
dmn->connect_tries = 0;
zlog_notice("%s state -> up : %s", dmn->name, why);
- if (gs.numdown == 0)
+ if (gs.numdown == 0) {
daemon_send_ready(0);
+
+ THREAD_OFF(gs.t_operational);
+
+ thread_add_timer(master, daemon_restarting_operational, NULL,
+ gs.operational_timeout, &gs.t_operational);
+ }
+
SET_WAKEUP_ECHO(dmn);
phase_check();
}
@@ -848,7 +869,7 @@ static void phase_hanging(struct thread *t_hanging)
gs.phase = PHASE_NONE;
}
-static void set_phase(restart_phase_t new_phase)
+static void set_phase(enum restart_phase new_phase)
{
gs.phase = new_phase;
thread_cancel(&gs.t_phase_hanging);
@@ -889,6 +910,7 @@ static void phase_check(void)
case PHASE_WAITING_DOWN:
if (gs.numdown + IS_UP(gs.special) < gs.numdaemons)
break;
+ systemd_send_status("Phased Restart");
zlog_info("Phased restart: all routing daemons now down.");
run_job(&gs.special->restart, "restart", gs.restart_command, 1,
1);
@@ -898,6 +920,7 @@ static void phase_check(void)
case PHASE_ZEBRA_RESTART_PENDING:
if (gs.special->restart.pid)
break;
+ systemd_send_status("Zebra Restarting");
zlog_info("Phased restart: %s restart job completed.",
gs.special->name);
set_phase(PHASE_WAITING_ZEBRA_UP);
@@ -1030,6 +1053,12 @@ void watchfrr_status(struct vty *vty)
struct timeval delay;
vty_out(vty, "watchfrr global phase: %s\n", phase_str[gs.phase]);
+ vty_out(vty, " Restart Command: %pSQq\n", gs.restart_command);
+ vty_out(vty, " Start Command: %pSQq\n", gs.start_command);
+ vty_out(vty, " Stop Command: %pSQq\n", gs.stop_command);
+ vty_out(vty, " Min Restart Interval: %ld\n", gs.min_restart_interval);
+ vty_out(vty, " Max Restart Interval: %ld\n", gs.max_restart_interval);
+ vty_out(vty, " Restart Timeout: %ld\n", gs.restart_timeout);
if (gs.restart.pid)
vty_out(vty, " global restart running, pid %ld\n",
(long)gs.restart.pid);
@@ -1395,6 +1424,18 @@ int main(int argc, char **argv)
frr_help_exit(1);
}
} break;
+ case OPTION_MAXOPERATIONAL: {
+ char garbage[3];
+
+ if ((sscanf(optarg, "%ld%1s", &gs.operational_timeout,
+ garbage) != 1) ||
+ (gs.max_restart_interval < 0)) {
+ fprintf(stderr,
+ "Invalid Operational_timeout argument: %s\n",
+ optarg);
+ frr_help_exit(1);
+ }
+ } break;
case OPTION_NETNS:
netns_en = true;
if (optarg && strchr(optarg, '/')) {
diff --git a/zebra/connected.c b/zebra/connected.c
index 4f4e8be34b..eb2720335e 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -327,6 +327,8 @@ void connected_add_ipv4(struct interface *ifp, int flags,
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+ if (!if_is_operative(ifp))
+ SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
/* Allocate new connected address. */
p = prefix_ipv4_new();
@@ -548,6 +550,8 @@ void connected_add_ipv6(struct interface *ifp, int flags,
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+ if (!if_is_operative(ifp))
+ SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
/* Allocate new connected address. */
p = prefix_ipv6_new();
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 873aea236d..ffd52da8d8 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -75,6 +75,7 @@
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_l2.h"
#include "zebra/netconf_netlink.h"
+#include "zebra/zebra_trace.h"
extern struct zebra_privs_t zserv_privs;
uint8_t frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
@@ -965,6 +966,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ns_id_t link_nsid = ns_id;
uint8_t bypass = 0;
+ frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup);
+
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
@@ -1119,6 +1122,9 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
char buf[256];
} req;
+ frrtrace(4, frr_zebra, netlink_request_intf_addr, netlink_cmd, family,
+ type, filter_mask);
+
/* Form the request, specifying filter (rtattr) if needed. */
memset(&req, 0, sizeof(req));
req.n.nlmsg_type = type;
@@ -1373,6 +1379,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint32_t metric = METRIC_MAX;
uint32_t kernel_flags = 0;
+ frrtrace(3, frr_zebra, netlink_interface_addr, h, ns_id, startup);
+
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
diff --git a/zebra/interface.c b/zebra/interface.c
index a70326ebb3..677ec4650f 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -958,7 +958,7 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
/*
* We need to note whether or not we originated a v6
* neighbor entry for this interface. So that when
- * someone unwisely accidently deletes this entry
+ * someone unwisely accidentally deletes this entry
* we can shove it back in.
*/
zif->v6_2_v4_ll_neigh_entry = !!add;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 2ff083dec5..7b377aad6d 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -79,6 +79,7 @@
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_evpn_mh.h"
+#include "zebra/zebra_trace.h"
#ifndef AF_MPLS
#define AF_MPLS 28
@@ -700,6 +701,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
void *src = NULL; /* IPv6 srcdest source prefix */
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
+ frrtrace(3, frr_zebra, netlink_route_change_read_unicast, h, ns_id,
+ startup);
+
rtm = NLMSG_DATA(h);
if (startup && h->nlmsg_type != RTM_NEWROUTE)
@@ -2906,6 +2910,8 @@ int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint8_t grp_count = 0;
struct rtattr *tb[NHA_MAX + 1] = {};
+ frrtrace(3, frr_zebra, netlink_nexthop_change, h, ns_id, startup);
+
nhm = NLMSG_DATA(h);
if (ns_id)
@@ -3802,7 +3808,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* interface
* and is linked to the bridge
* (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
- * inteface
+ * interface
* itself
*/
if (IS_ZEBRA_IF_VLAN(ifp)) {
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index fbf2620375..135f065428 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -42,6 +42,7 @@
#include "zebra/zebra_pbr.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_dplane.h"
+#include "zebra/zebra_trace.h"
/* definitions */
@@ -243,6 +244,8 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint8_t proto = 0;
uint8_t ip_proto = 0;
+ frrtrace(3, frr_zebra, netlink_rule_change, h, ns_id, startup);
+
/* Basic validation followed by extracting attributes. */
if (h->nlmsg_type != RTM_NEWRULE && h->nlmsg_type != RTM_DELRULE)
return 0;
diff --git a/zebra/subdir.am b/zebra/subdir.am
index 8cb1237c22..a09b895cee 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -50,7 +50,7 @@ man8 += $(MANBUILD)/frr-zebra.8
## endif ZEBRA
endif
-zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP)
+zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP) $(UST_LIBS)
if HAVE_PROTOBUF3
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
zebra/zebra_mlag.$(OBJEXT): mlag/mlag.pb-c.h
@@ -120,6 +120,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_routemap_nb_config.c \
zebra/zebra_script.c \
zebra/zebra_srte.c \
+ zebra/zebra_trace.c \
zebra/zebra_vrf.c \
zebra/zebra_vty.c \
zebra/zebra_vxlan.c \
@@ -191,6 +192,7 @@ noinst_HEADERS += \
zebra/zebra_router.h \
zebra/zebra_script.h \
zebra/zebra_srte.h \
+ zebra/zebra_trace.h \
zebra/zebra_vrf.h \
zebra/zebra_vxlan.h \
zebra/zebra_vxlan_private.h \
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index d034c8f306..4e753c9d1a 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -2679,7 +2679,7 @@ done:
}
/**
- * dplane_ctx_intf_init() - Initialize a context block for a inteface update
+ * dplane_ctx_intf_init() - Initialize a context block for a interface update
*
* @ctx: Dataplane context to init
* @op: Operation being performed
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 02eda4a438..b1e48374c4 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -3286,7 +3286,7 @@ DEFPY_HIDDEN(zebra_evpn_es_bypass, zebra_evpn_es_bypass_cmd,
} else {
if (!zebra_evpn_is_if_es_capable(zif)) {
vty_out(vty,
- "%%DF bypass cannot be associated with this interface type\n");
+ "%% DF bypass cannot be associated with this interface type\n");
return CMD_WARNING;
}
zebra_evpn_es_bypass_cfg_update(zif, true);
@@ -3311,7 +3311,7 @@ DEFPY(zebra_evpn_es_pref, zebra_evpn_es_pref_cmd,
} else {
if (!zebra_evpn_is_if_es_capable(zif)) {
vty_out(vty,
- "%%DF preference cannot be associated with this interface type\n");
+ "%% DF preference cannot be associated with this interface type\n");
return CMD_WARNING;
}
zebra_evpn_es_df_pref_update(zif, df_pref);
@@ -3341,25 +3341,26 @@ DEFPY(zebra_evpn_es_sys_mac,
ret = zebra_evpn_es_sys_mac_update(zif, &zero_mac);
if (ret == -1) {
- vty_out(vty, "%%Failed to clear ES sysmac\n");
+ vty_out(vty, "%% Failed to clear ES sysmac\n");
return CMD_WARNING;
}
} else {
if (!zebra_evpn_is_if_es_capable(zif)) {
vty_out(vty,
- "%%ESI cannot be associated with this interface type\n");
+ "%% ESI cannot be associated with this interface type\n");
return CMD_WARNING;
}
if (!mac || is_zero_mac(&mac->eth_addr)) {
- vty_out(vty, "%%ES sysmac value is invalid\n");
+ vty_out(vty, "%% ES sysmac value is invalid\n");
return CMD_WARNING;
}
ret = zebra_evpn_es_sys_mac_update(zif, &mac->eth_addr);
if (ret == -1) {
- vty_out(vty, "%%ESI already exists on a different interface\n");
+ vty_out(vty,
+ "%% ESI already exists on a different interface\n");
return CMD_WARNING;
}
}
@@ -3392,25 +3393,27 @@ DEFPY(zebra_evpn_es_id,
ret = zebra_evpn_es_type0_esi_update(zif, zero_esi);
if (ret == -1) {
- vty_out(vty, "%%Failed to clear ES local id\n");
+ vty_out(vty,
+ "%% Failed to clear ES local id or ESI name\n");
return CMD_WARNING;
}
} else {
if (!zebra_evpn_is_if_es_capable(zif)) {
vty_out(vty,
- "%%ESI cannot be associated with this interface type\n");
+ "%% ESI cannot be associated with this interface type\n");
return CMD_WARNING;
}
if (esi_str) {
if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%% Malformed ESI\n");
+ vty_out(vty, "%% Malformed ESI name\n");
return CMD_WARNING;
}
ret = zebra_evpn_es_type0_esi_update(zif, &esi);
} else {
if (!es_lid) {
- vty_out(vty, "%%Specify local ES ID\n");
+ vty_out(vty,
+ "%% Specify ES local id or ESI name\n");
return CMD_WARNING;
}
ret = zebra_evpn_es_lid_update(zif, es_lid);
@@ -3418,7 +3421,7 @@ DEFPY(zebra_evpn_es_id,
if (ret == -1) {
vty_out(vty,
- "%%ESI already exists on a different interface\n");
+ "%% ESI already exists on a different interface\n");
return CMD_WARNING;
}
}
@@ -3758,18 +3761,10 @@ static inline bool zebra_evpn_mh_is_all_uplinks_down(void)
static void zebra_evpn_mh_uplink_oper_flags_update(struct zebra_if *zif,
bool set)
{
- if (set) {
- if (if_is_operative(zif->ifp)) {
- if (!(zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP)) {
- zif->flags |= ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP;
- ++zmh_info->uplink_oper_up_cnt;
- }
- } else {
- if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) {
- zif->flags &= ~ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP;
- if (zmh_info->uplink_oper_up_cnt)
- --zmh_info->uplink_oper_up_cnt;
- }
+ if (set && if_is_operative(zif->ifp)) {
+ if (!(zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP)) {
+ zif->flags |= ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP;
+ ++zmh_info->uplink_oper_up_cnt;
}
} else {
if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) {
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index ce7b920de1..7e288853bb 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -369,17 +369,6 @@ extern void zebra_evpn_mh_json(json_object *json);
extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
struct zebra_evpn_es **local_es);
extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
-extern int zebra_evpn_mh_startup_delay_update(struct vty *vty,
- uint32_t duration,
- bool set_default);
-extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif);
-extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif,
- bool clear,
- const char *caller);
-extern bool zebra_evpn_is_es_bond(struct interface *ifp);
-extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
-extern void zebra_evpn_mh_print(struct vty *vty);
-extern void zebra_evpn_mh_json(json_object *json);
extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
struct zebra_if *br_zif, bool is_up);
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index ec22c5dd48..d4aced47f9 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -398,7 +398,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
req->r.rtm_family = ri->af;
/*
- * rtm_table field is a uchar field which can accomodate table_id less
+ * rtm_table field is a uchar field which can accommodate table_id less
* than 256.
* To support table id greater than 255, if the table_id is greater than
* 255, set rtm_table to RT_TABLE_UNSPEC and add RTA_TABLE attribute
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 1b926dba5f..069d35c6a3 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -43,6 +43,7 @@
#include "zebra_dplane.h"
#include "zebra/interface.h"
#include "zebra/zapi_msg.h"
+#include "zebra/rib.h"
DEFINE_MTYPE_STATIC(ZEBRA, NHG, "Nexthop Group Entry");
DEFINE_MTYPE_STATIC(ZEBRA, NHG_CONNECTED, "Nexthop Group Connected");
@@ -1960,6 +1961,61 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
}
/*
+ * So this nexthop resolution has decided that a connected route
+ * is the correct choice. At this point in time if FRR has multiple
+ * connected routes that all point to the same prefix one will be
+ * selected, *but* the particular interface may not be the one
+ * that the nexthop points at. Let's look at all the available
+ * connected routes on this node and if any of them auto match
+ * the routes nexthops ifindex that is good enough for a match
+ *
+ * This code is depending on the fact that a nexthop->ifindex is 0
+ * if it is not known, if this assumption changes, yummy!
+ * Additionally a ifindx of 0 means figure it out for us.
+ */
+static struct route_entry *
+zebra_nhg_connected_ifindex(struct route_node *rn, struct route_entry *match,
+ int32_t curr_ifindex)
+{
+ struct nexthop *newhop = match->nhe->nhg.nexthop;
+ struct route_entry *re;
+
+ assert(newhop); /* What a kick in the patooey */
+
+ if (curr_ifindex == 0)
+ return match;
+
+ if (curr_ifindex == newhop->ifindex)
+ return match;
+
+ /*
+ * At this point we know that this route is matching a connected
+ * but there are possibly a bunch of connected routes that are
+ * alive that should be considered as well. So let's iterate over
+ * all the re's and see if they are connected as well and maybe one
+ * of those ifindexes match as well.
+ */
+ RNODE_FOREACH_RE (rn, re) {
+ if (re->type != ZEBRA_ROUTE_CONNECT)
+ continue;
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+ continue;
+
+ /*
+ * zebra has a connected route that is not removed
+ * let's test if it is good
+ */
+ newhop = re->nhe->nhg.nexthop;
+ assert(newhop);
+ if (curr_ifindex == newhop->ifindex)
+ return re;
+ }
+
+ return match;
+}
+
+/*
* Given a nexthop we need to properly recursively resolve,
* do a table lookup to find and match if at all possible.
* Set the nexthop->ifindex and resolution info as appropriate.
@@ -2209,25 +2265,25 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
continue;
}
- if (match->type == ZEBRA_ROUTE_CONNECT) {
- /* Directly point connected route. */
+ if ((match->type == ZEBRA_ROUTE_CONNECT) ||
+ (RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type))) {
+ match = zebra_nhg_connected_ifindex(rn, match,
+ nexthop->ifindex);
+
newhop = match->nhe->nhg.nexthop;
- if (newhop) {
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- || nexthop->type == NEXTHOP_TYPE_IPV6)
- nexthop->ifindex = newhop->ifindex;
- else if (nexthop->ifindex != newhop->ifindex) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%s: %pNHv given ifindex does not match nexthops ifindex found found: %pNHv",
- __func__, nexthop,
- newhop);
- /*
- * NEXTHOP_TYPE_*_IFINDEX but ifindex
- * doesn't match what we found.
- */
- return 0;
- }
+ if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
+ nexthop->type == NEXTHOP_TYPE_IPV6)
+ nexthop->ifindex = newhop->ifindex;
+ else if (nexthop->ifindex != newhop->ifindex) {
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug(
+ "%s: %pNHv given ifindex does not match nexthops ifindex found: %pNHv",
+ __func__, nexthop, newhop);
+ /*
+ * NEXTHOP_TYPE_*_IFINDEX but ifindex
+ * doesn't match what we found.
+ */
+ return 0;
}
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
@@ -2946,10 +3002,12 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
nhe->zapi_session, nhe->id,
ZAPI_NHG_FAIL_INSTALL);
- flog_err(
- EC_ZEBRA_DP_INSTALL_FAIL,
- "Failed to install Nexthop ID (%u) into the kernel",
- nhe->id);
+ if (!(zebra_nhg_proto_nexthops_only() &&
+ !PROTO_OWNED(nhe)))
+ flog_err(
+ EC_ZEBRA_DP_INSTALL_FAIL,
+ "Failed to install Nexthop ID (%u) into the kernel",
+ nhe->id);
}
break;
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index 9805390a6d..d247f87708 100644
--- a/zebra/zebra_script.c
+++ b/zebra/zebra_script.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "zebra.h"
+
#include "zebra_script.h"
#ifdef HAVE_SCRIPTING
diff --git a/zebra/zebra_trace.c b/zebra/zebra_trace.c
new file mode 100644
index 0000000000..fef5ad20ac
--- /dev/null
+++ b/zebra/zebra_trace.c
@@ -0,0 +1,6 @@
+#define TRACEPOINT_CREATE_PROBES
+#define TRACEPOINT_DEFINE
+
+#include <zebra.h>
+
+#include "zebra_trace.h"
diff --git a/zebra/zebra_trace.h b/zebra/zebra_trace.h
new file mode 100644
index 0000000000..49a0c8e793
--- /dev/null
+++ b/zebra/zebra_trace.h
@@ -0,0 +1,130 @@
+/* Tracing for zebra
+ *
+ * Copyright (C) 2020 NVIDIA Corporation
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined(__ZEBRA_TRACE_H__) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define __ZEBRA_TRACE_H__
+
+#include "lib/trace.h"
+
+#ifdef HAVE_LTTNG
+
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER frr_zebra
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "zebra/zebra_trace.h"
+
+#include <lttng/tracepoint.h>
+
+#include <lib/ns.h>
+#include <lib/table.h>
+
+#include <zebra/zebra_ns.h>
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_request_intf_addr,
+ TP_ARGS(struct nlsock *, netlink_cmd,
+ int, family,
+ int, type,
+ uint32_t, filter_mask),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, netlink_cmd, netlink_cmd)
+ ctf_integer(int, family, family)
+ ctf_integer(int, type, type)
+ ctf_integer(uint32_t, filter_mask, filter_mask)
+ )
+ )
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_interface,
+ TP_ARGS(
+ struct nlmsghdr *, header,
+ ns_id_t, ns_id,
+ int, startup),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, header, header)
+ ctf_integer(uint32_t, ns_id, ns_id)
+ ctf_integer(uint32_t, startup, startup)
+ )
+ )
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_nexthop_change,
+ TP_ARGS(
+ struct nlmsghdr *, header,
+ ns_id_t, ns_id,
+ int, startup),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, header, header)
+ ctf_integer(uint32_t, ns_id, ns_id)
+ ctf_integer(uint32_t, startup, startup)
+ )
+ )
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_interface_addr,
+ TP_ARGS(
+ struct nlmsghdr *, header,
+ ns_id_t, ns_id,
+ int, startup),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, header, header)
+ ctf_integer(uint32_t, ns_id, ns_id)
+ ctf_integer(uint32_t, startup, startup)
+ )
+ )
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_route_change_read_unicast,
+ TP_ARGS(
+ struct nlmsghdr *, header,
+ ns_id_t, ns_id,
+ int, startup),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, header, header)
+ ctf_integer(uint32_t, ns_id, ns_id)
+ ctf_integer(uint32_t, startup, startup)
+ )
+ )
+
+TRACEPOINT_EVENT(
+ frr_zebra,
+ netlink_rule_change,
+ TP_ARGS(
+ struct nlmsghdr *, header,
+ ns_id_t, ns_id,
+ int, startup),
+ TP_FIELDS(
+ ctf_integer_hex(intptr_t, header, header)
+ ctf_integer(uint32_t, ns_id, ns_id)
+ ctf_integer(uint32_t, startup, startup)
+ )
+ )
+
+#include <lttng/tracepoint-event.h>
+
+#endif /* HAVE_LTTNG */
+
+#endif /* __ZEBRA_TRACE_H__ */