summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c1
-rw-r--r--bgpd/bgp_route.c56
-rw-r--r--bgpd/bgp_rpki.c2
-rw-r--r--bgpd/bgp_updgrp.c6
-rw-r--r--bgpd/bgp_updgrp_adv.c9
-rw-r--r--bgpd/bgp_vty.c24
-rw-r--r--bgpd/bgpd.c14
-rw-r--r--bgpd/bgpd.h19
-rw-r--r--doc/user/isisd.rst3
-rw-r--r--isisd/isis_cli.c24
-rw-r--r--isisd/isis_lsp.c11
-rw-r--r--isisd/isis_main.c35
-rw-r--r--isisd/isis_nb.c7
-rw-r--r--isisd/isis_nb.h4
-rw-r--r--isisd/isis_nb_config.c20
-rw-r--r--isisd/isisd.c13
-rw-r--r--isisd/isisd.h6
-rw-r--r--ldpd/adjacency.c4
-rw-r--r--ldpd/ldp_vty_exec.c20
-rw-r--r--lib/asn.c12
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/northbound.c19
-rw-r--r--lib/northbound.h22
-rw-r--r--lib/northbound_cli.c11
-rw-r--r--lib/northbound_confd.c2
-rw-r--r--lib/northbound_db.c2
-rw-r--r--lib/northbound_grpc.cpp4
-rw-r--r--lib/northbound_sysrepo.c2
-rw-r--r--lib/vty.c2
-rw-r--r--pimd/pim6_mld.c57
-rw-r--r--pimd/pim_cmd_common.c2
-rw-r--r--pimd/pim_hello.c2
-rw-r--r--pimd/pim_iface.c6
-rw-r--r--pimd/pim_mroute.c10
-rw-r--r--pimd/pim_nb_config.c2
-rw-r--r--pimd/pim_neighbor.c9
-rw-r--r--pimd/pim_neighbor.h2
-rw-r--r--pimd/pim_nht.c19
-rw-r--r--pimd/pim_pim.c4
-rw-r--r--pimd/pim_rpf.c4
-rw-r--r--pimd/pim_upstream.c10
-rw-r--r--pimd/pim_zebra.c3
-rw-r--r--tests/bgpd/test_peer_attr.c8
-rw-r--r--tests/bgpd/test_peer_attr.py2
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py17
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json49
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf13
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json26
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json18
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf10
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json38
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf25
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf7
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py94
-rw-r--r--tests/topotests/isis_topo1/test_isis_topo1.py61
-rw-r--r--tests/topotests/lib/ospf.py2
-rw-r--r--yang/frr-isisd.yang7
-rw-r--r--zebra/rt_netlink.c19
-rw-r--r--zebra/zapi_msg.c2
61 files changed, 676 insertions, 216 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 1e2698cd92..de77bd5304 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -4312,7 +4312,6 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
* if the peer belongs to us.
*/
if (bgp_confederation_peers_check(bgp, peer->as)) {
- aspath = aspath_dup(attr->aspath);
aspath = aspath_add_confed_seq(aspath,
peer->local_as);
} else {
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0beef97a04..1e9f9429c5 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -515,11 +515,19 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
size_t buf_len)
{
+ struct peer *peer;
+
+ if (pi->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_get_imported_bpi_ultimate(pi))
+ peer = bgp_get_imported_bpi_ultimate(pi)->peer;
+ else
+ peer = pi->peer;
+
if (pi->addpath_rx_id)
- snprintf(buf, buf_len, "path %s (addpath rxid %d)",
- pi->peer->host, pi->addpath_rx_id);
+ snprintf(buf, buf_len, "path %s (addpath rxid %d)", peer->host,
+ pi->addpath_rx_id);
else
- snprintf(buf, buf_len, "path %s", pi->peer->host);
+ snprintf(buf, buf_len, "path %s", peer->host);
}
@@ -581,6 +589,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
bool new_proxy;
bool new_origin, exist_origin;
struct bgp_path_info *bpi_ultimate;
+ struct peer *peer_new, *peer_exist;
*paths_eq = 0;
@@ -1081,9 +1090,21 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
}
+ if (exist->sub_type == BGP_ROUTE_IMPORTED) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
+ peer_exist = bpi_ultimate->peer;
+ } else
+ peer_exist = exist->peer;
+
+ if (new->sub_type == BGP_ROUTE_IMPORTED) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
+ peer_new = bpi_ultimate->peer;
+ } else
+ peer_new = new->peer;
+
/* 7. Peer type check. */
- new_sort = new->peer->sort;
- exist_sort = exist->peer->sort;
+ new_sort = peer_new->sort;
+ exist_sort = peer_exist->sort;
if (new_sort == BGP_PEER_EBGP
&& (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
@@ -1138,8 +1159,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
pair (newm, existm) with the cluster list length. Prefer the
path with smaller cluster list length. */
if (newm == existm) {
- if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
- peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
+ if (peer_sort_lookup(peer_new) == BGP_PEER_IBGP &&
+ peer_sort_lookup(peer_exist) == BGP_PEER_IBGP &&
(mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
@@ -1236,7 +1257,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
zlog_debug(
"%s: %s and %s are equal via multipath-relax",
pfx_buf, new_buf, exist_buf);
- } else if (new->peer->sort == BGP_PEER_IBGP) {
+ } else if (peer_new->sort == BGP_PEER_IBGP) {
if (aspath_cmp(new->attr->aspath,
exist->attr->aspath)) {
*paths_eq = 1;
@@ -1246,7 +1267,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
"%s: %s and %s are equal via matching aspaths",
pfx_buf, new_buf, exist_buf);
}
- } else if (new->peer->as == exist->peer->as) {
+ } else if (peer_new->as == peer_exist->as) {
*paths_eq = 1;
if (debug)
@@ -1326,11 +1347,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
new_id.s_addr = newattr->originator_id.s_addr;
else
- new_id.s_addr = new->peer->remote_id.s_addr;
+ new_id.s_addr = peer_new->remote_id.s_addr;
if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
exist_id.s_addr = existattr->originator_id.s_addr;
else
- exist_id.s_addr = exist->peer->remote_id.s_addr;
+ exist_id.s_addr = peer_exist->remote_id.s_addr;
if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
*reason = bgp_path_selection_router_id;
@@ -1397,16 +1418,17 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
/* locally configured routes to advertise do not have su_remote */
- if (new->peer->su_remote == NULL) {
+ if (peer_new->su_remote == NULL) {
*reason = bgp_path_selection_local_configured;
return 0;
}
- if (exist->peer->su_remote == NULL) {
+
+ if (peer_exist->su_remote == NULL) {
*reason = bgp_path_selection_local_configured;
return 1;
}
- ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
+ ret = sockunion_cmp(peer_new->su_remote, peer_exist->su_remote);
if (ret == 1) {
*reason = bgp_path_selection_neighbor_ip;
@@ -7638,9 +7660,11 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
/* If the bgp instance is being deleted or self peer is deleted
* then do not create aggregate route
*/
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
- || (bgp->peer_self == NULL))
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
+ (bgp->peer_self == NULL)) {
+ bgp_aggregate_free(aggregate);
return;
+ }
/* Initialize and test routes for MED difference. */
if (aggregate->match_med)
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 6ab9c2873d..32ca909fe6 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -281,7 +281,7 @@ static void print_record(const struct pfx_record *record, struct vty *vty,
if (!json) {
vty_out(vty, "%-40s %3u - %3u ", ip, record->min_len,
record->max_len);
- vty_out(vty, ASN_FORMAT(asnotation), &record->asn);
+ vty_out(vty, ASN_FORMAT(asnotation), (as_t *)&record->asn);
vty_out(vty, "\n");
} else {
json_record = json_object_new_object();
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index a32cdb1ba4..277492157f 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -317,7 +317,7 @@ static unsigned int updgrp_hash_key_make(const void *p)
const struct update_group *updgrp;
const struct peer *peer;
const struct bgp_filter *filter;
- uint32_t flags;
+ uint64_t flags;
uint32_t key;
afi_t afi;
safi_t safi;
@@ -501,8 +501,8 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
const struct update_group *grp2;
const struct peer *pe1;
const struct peer *pe2;
- uint32_t flags1;
- uint32_t flags2;
+ uint64_t flags1;
+ uint64_t flags2;
const struct bgp_filter *fl1;
const struct bgp_filter *fl2;
afi_t afi;
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 9eefd2a637..d6eb3ff20b 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -683,11 +683,14 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
&attr, NULL)) {
/* Check if route can be advertised */
if (advertise) {
- if (!bgp_check_withdrawal(bgp, dest))
+ if (!bgp_check_withdrawal(bgp, dest)) {
+ struct attr *adv_attr =
+ bgp_attr_intern(&attr);
+
bgp_adj_out_set_subgroup(
- dest, subgrp, &attr,
+ dest, subgrp, adv_attr,
ri);
- else
+ } else
bgp_adj_out_unset_subgroup(
dest, subgrp, 1,
bgp_addpath_id_for_peer(
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 8ef18a34d0..a1e9a9a8a9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -5671,7 +5671,7 @@ DEFPY(neighbor_capability_software_version,
}
static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
- afi_t afi, safi_t safi, uint32_t flag,
+ afi_t afi, safi_t safi, uint64_t flag,
int set)
{
int ret;
@@ -5690,13 +5690,13 @@ static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
}
static int peer_af_flag_set_vty(struct vty *vty, const char *peer_str,
- afi_t afi, safi_t safi, uint32_t flag)
+ afi_t afi, safi_t safi, uint64_t flag)
{
return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 1);
}
static int peer_af_flag_unset_vty(struct vty *vty, const char *peer_str,
- afi_t afi, safi_t safi, uint32_t flag)
+ afi_t afi, safi_t safi, uint64_t flag)
{
return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 0);
}
@@ -8893,7 +8893,7 @@ DEFPY(neighbor_path_attribute_discard,
{
struct peer *peer;
int idx = 0;
- const char *discard_attrs = NULL;
+ char *discard_attrs = NULL;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
@@ -8905,6 +8905,8 @@ DEFPY(neighbor_path_attribute_discard,
bgp_path_attribute_discard_vty(vty, peer, discard_attrs, true);
+ XFREE(MTYPE_TMP, discard_attrs);
+
return CMD_SUCCESS;
}
@@ -8920,7 +8922,7 @@ DEFPY(no_neighbor_path_attribute_discard,
{
struct peer *peer;
int idx = 0;
- const char *discard_attrs = NULL;
+ char *discard_attrs = NULL;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
@@ -8932,6 +8934,8 @@ DEFPY(no_neighbor_path_attribute_discard,
bgp_path_attribute_discard_vty(vty, peer, discard_attrs, false);
+ XFREE(MTYPE_TMP, discard_attrs);
+
return CMD_SUCCESS;
}
@@ -8946,7 +8950,7 @@ DEFPY(neighbor_path_attribute_treat_as_withdraw,
{
struct peer *peer;
int idx = 0;
- const char *withdraw_attrs = NULL;
+ char *withdraw_attrs = NULL;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
@@ -8958,6 +8962,8 @@ DEFPY(neighbor_path_attribute_treat_as_withdraw,
bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, true);
+ XFREE(MTYPE_TMP, withdraw_attrs);
+
return CMD_SUCCESS;
}
@@ -8973,7 +8979,7 @@ DEFPY(no_neighbor_path_attribute_treat_as_withdraw,
{
struct peer *peer;
int idx = 0;
- const char *withdraw_attrs = NULL;
+ char *withdraw_attrs = NULL;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
@@ -8985,6 +8991,8 @@ DEFPY(no_neighbor_path_attribute_treat_as_withdraw,
bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, false);
+ XFREE(MTYPE_TMP, withdraw_attrs);
+
return CMD_SUCCESS;
}
@@ -17154,7 +17162,7 @@ static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
return !peer_af_flag_check(peer, afi, safi, flag);
else
- return !!peer_af_flag_check(peer, afi, safi, flag);
+ return peer_af_flag_check(peer, afi, safi, flag);
}
return !!CHECK_FLAG(peer->af_flags_override[afi][safi], flag);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 0fd0dafa22..96c6a111ce 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -977,9 +977,10 @@ void peer_flag_inherit(struct peer *peer, uint64_t flag)
COND_FLAG(peer->flags, flag, group_val);
}
-int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
+bool peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag)
{
- return CHECK_FLAG(peer->af_flags[afi][safi], flag);
+ return !!CHECK_FLAG(peer->af_flags[afi][safi], flag);
}
void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
@@ -2725,7 +2726,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
static void peer_group2peer_config_copy(struct peer_group *group,
struct peer *peer)
{
- uint32_t flags_tmp;
+ uint64_t flags_tmp;
struct peer *conf;
bool config_node = !!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
@@ -4517,7 +4518,7 @@ static int peer_flag_action_set(const struct peer_flag_action *action_list,
return found;
}
-static void peer_flag_modify_action(struct peer *peer, uint32_t flag)
+static void peer_flag_modify_action(struct peer *peer, uint64_t flag)
{
if (flag == PEER_FLAG_SHUTDOWN) {
if (CHECK_FLAG(peer->flags, flag)) {
@@ -6312,8 +6313,11 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
&& old_replace_as == replace_as)
return 0;
peer->change_local_as = as;
- if (as_str)
+ if (as_str) {
+ if (peer->change_local_as_pretty)
+ XFREE(MTYPE_BGP, peer->change_local_as_pretty);
peer->change_local_as_pretty = XSTRDUP(MTYPE_BGP, as_str);
+ }
(void)peer_sort(peer);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 2a7c7a3143..c0dd8d5ef4 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1441,14 +1441,14 @@ struct peer {
#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1ULL << 19)
#define PEER_FLAG_AS_OVERRIDE (1ULL << 20)
#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1ULL << 21)
-#define PEER_FLAG_WEIGHT (1ULL << 24)
-#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1ULL << 25)
-#define PEER_FLAG_SEND_LARGE_COMMUNITY (1ULL << 26)
-#define PEER_FLAG_MAX_PREFIX_OUT (1ULL << 27)
-#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 28)
-#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)
-#define PEER_FLAG_SOO (1ULL << 30)
-#define PEER_FLAG_ACCEPT_OWN (1ULL << 31)
+#define PEER_FLAG_WEIGHT (1ULL << 22)
+#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1ULL << 23)
+#define PEER_FLAG_SEND_LARGE_COMMUNITY (1ULL << 24)
+#define PEER_FLAG_MAX_PREFIX_OUT (1ULL << 25)
+#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 26)
+#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 27)
+#define PEER_FLAG_SOO (1ULL << 28)
+#define PEER_FLAG_ACCEPT_OWN (1ULL << 63)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
@@ -2247,7 +2247,8 @@ extern int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi,
uint64_t flag);
extern int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi,
uint64_t flag);
-extern int peer_af_flag_check(struct peer *, afi_t, safi_t, uint32_t);
+extern bool peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag);
extern void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
uint64_t flag);
extern void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index 2b114ad127..d68fa67259 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -95,6 +95,9 @@ writing, *isisd* does not support multiple ISIS processes.
Configure the maximum size of generated LSPs, in bytes.
+.. clicmd:: advertise-passive-only
+
+ Advertise prefixes of passive interfaces only.
.. _isis-timer:
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 26ae2024b9..5c7f610881 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -892,6 +892,29 @@ void cli_show_isis_lsp_mtu(struct vty *vty, const struct lyd_node *dnode,
}
/*
+ * XPath: /frr-isisd:isis/instance/advertise-passive-only
+ */
+DEFPY_YANG(advertise_passive_only, advertise_passive_only_cmd,
+ "[no] advertise-passive-only",
+ NO_STR "Advertise prefixes of passive interfaces only\n")
+{
+ nb_cli_enqueue_change(vty, "./advertise-passive-only", NB_OP_MODIFY,
+ no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_advertise_passive_only(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " no");
+
+ vty_out(vty, " advertise-passive-only\n");
+}
+
+/*
* XPath: /frr-isisd:isis/instance/spf/minimum-interval
*/
DEFPY_YANG(spf_interval, spf_interval_cmd,
@@ -3151,6 +3174,7 @@ void isis_cli_init(void)
install_element(ISIS_NODE, &no_lsp_timers_cmd);
install_element(ISIS_NODE, &area_lsp_mtu_cmd);
install_element(ISIS_NODE, &no_area_lsp_mtu_cmd);
+ install_element(ISIS_NODE, &advertise_passive_only_cmd);
install_element(ISIS_NODE, &spf_interval_cmd);
install_element(ISIS_NODE, &no_spf_interval_cmd);
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 8c347ef813..4a332d0aed 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -1171,6 +1171,13 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
continue;
}
+ if (area->advertise_passive_only && !circuit->is_passive) {
+ lsp_debug(
+ "ISIS (%s): Circuit is not passive, ignoring.",
+ area->area_tag);
+ continue;
+ }
+
uint32_t metric = area->oldmetric
? circuit->metric[level - 1]
: circuit->te_metric[level - 1];
@@ -1364,6 +1371,10 @@ int lsp_generate(struct isis_area *area, int level)
if ((area == NULL) || (area->is_type & level) != level)
return ISIS_ERROR;
+ /* Check if config is still being processed */
+ if (thread_is_scheduled(t_isis_cfg))
+ return ISIS_OK;
+
memset(&lspid, 0, ISIS_SYS_ID_LEN + 2);
memcpy(&lspid, area->isis->sysid, ISIS_SYS_ID_LEN);
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 9b2bebb420..25ea187492 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -168,6 +168,40 @@ static const struct frr_yang_module_info *const isisd_yang_modules[] = {
};
/* clang-format on */
+
+static void isis_config_finish(struct thread *t)
+{
+ struct listnode *node, *inode;
+ struct isis *isis;
+ struct isis_area *area;
+
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
+ config_end_lsp_generate(area);
+ }
+}
+
+static void isis_config_start(void)
+{
+ /* Max wait time for config to load before generating lsp */
+#define ISIS_PRE_CONFIG_MAX_WAIT_SECONDS 600
+ THREAD_OFF(t_isis_cfg);
+ thread_add_timer(im->master, isis_config_finish, NULL,
+ ISIS_PRE_CONFIG_MAX_WAIT_SECONDS, &t_isis_cfg);
+}
+
+static void isis_config_end(void)
+{
+ /* If ISIS config processing thread isn't running, then
+ * we can return and rely it's properly handled.
+ */
+ if (!thread_is_scheduled(t_isis_cfg))
+ return;
+
+ THREAD_OFF(t_isis_cfg);
+ isis_config_finish(t_isis_cfg);
+}
+
#ifdef FABRICD
FRR_DAEMON_INFO(fabricd, OPEN_FABRIC, .vty_port = FABRICD_VTY_PORT,
@@ -231,6 +265,7 @@ int main(int argc, char **argv, char **envp)
/*
* initializations
*/
+ cmd_init_config_callbacks(isis_config_start, isis_config_end);
isis_error_init();
access_list_init();
access_list_add_hook(isis_filter_update);
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index bcda5bd6aa..5caa61a4d1 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -103,6 +103,13 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-isisd:isis/instance/advertise-passive-only",
+ .cbs = {
+ .cli_show = cli_show_advertise_passive_only,
+ .modify = isis_instance_advertise_passive_only_modify,
+ },
+ },
+ {
.xpath = "/frr-isisd:isis/instance/lsp/timers",
.cbs = {
.cli_show = cli_show_isis_lsp_timers,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index 1a2bd2deb8..c90f6dca37 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -29,6 +29,7 @@ int isis_instance_overload_on_startup_modify(struct nb_cb_modify_args *args);
int isis_instance_metric_style_modify(struct nb_cb_modify_args *args);
int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args);
int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args);
+int isis_instance_advertise_passive_only_modify(struct nb_cb_modify_args *args);
int isis_instance_lsp_refresh_interval_level_1_modify(
struct nb_cb_modify_args *args);
int isis_instance_lsp_refresh_interval_level_2_modify(
@@ -473,6 +474,9 @@ void cli_show_isis_lsp_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_lsp_mtu(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
+void cli_show_advertise_passive_only(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_spf_min_interval(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index a7c4e4f369..ea021a4ff5 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -420,6 +420,26 @@ int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args)
}
/*
+ * XPath: /frr-isisd:isis/instance/advertise-passive-only
+ */
+int isis_instance_advertise_passive_only_modify(struct nb_cb_modify_args *args)
+{
+ struct isis_area *area;
+ bool advertise_passive_only;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ advertise_passive_only = yang_dnode_get_bool(args->dnode, NULL);
+ area->advertise_passive_only = advertise_passive_only;
+
+ lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1);
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-isisd:isis/instance/lsp/timers/level-1/refresh-interval
*/
int isis_instance_lsp_refresh_interval_level_1_modify(
diff --git a/isisd/isisd.c b/isisd/isisd.c
index d9f8a262cb..852d7b88e8 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -87,6 +87,9 @@ static struct isis_master isis_master;
/* ISIS process wide configuration pointer to export. */
struct isis_master *im;
+/* ISIS config processing thread */
+struct thread *t_isis_cfg;
+
#ifndef FABRICD
DEFINE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area));
#endif /* ifndef FABRICD */
@@ -3234,6 +3237,16 @@ void isis_area_overload_on_startup_set(struct isis_area *area,
}
}
+void config_end_lsp_generate(struct isis_area *area)
+{
+ if (listcount(area->area_addrs) > 0) {
+ if (CHECK_FLAG(area->is_type, IS_LEVEL_1))
+ lsp_generate(area, IS_LEVEL_1);
+ if (CHECK_FLAG(area->is_type, IS_LEVEL_2))
+ lsp_generate(area, IS_LEVEL_2);
+ }
+}
+
/*
* Returns the path of the file (non-volatile memory) that contains restart
* information.
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 2052e8e3d9..0f1161e574 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -99,6 +99,8 @@ struct isis {
extern struct isis_master *im;
+extern struct thread *t_isis_cfg;
+
enum spf_tree_id {
SPFTREE_IPV4 = 0,
SPFTREE_IPV6,
@@ -171,6 +173,8 @@ struct isis_area {
bool overload_configured;
uint32_t overload_counter;
uint32_t overload_on_startup_time;
+ /* advertise prefixes of passive interfaces only? */
+ bool advertise_passive_only;
/* L1/L2 router identifier for inter-area traffic */
char attached_bit_send;
char attached_bit_rcv_ignore;
@@ -314,6 +318,8 @@ char *isis_restart_filepath(void);
void isis_restart_write_overload_time(struct isis_area *isis_area,
uint32_t overload_time);
uint32_t isis_restart_read_overload_time(struct isis_area *isis_area);
+void config_end_lsp_generate(struct isis_area *area);
+
/* YANG paths */
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
#define ISIS_SR "/frr-isisd:isis/instance/segment-routing"
diff --git a/ldpd/adjacency.c b/ldpd/adjacency.c
index 97e4c2ef01..42c3ef0535 100644
--- a/ldpd/adjacency.c
+++ b/ldpd/adjacency.c
@@ -170,7 +170,7 @@ static void adj_itimer(struct thread *thread)
log_debug("%s: lsr-id %pI4", __func__, &adj->lsr_id);
if (adj->source.type == HELLO_TARGETED) {
- if (!(adj->source.target->flags & F_TNBR_CONFIGURED) &&
+ if (!CHECK_FLAG(adj->source.target->flags, F_TNBR_CONFIGURED) &&
adj->source.target->pw_count == 0 &&
adj->source.target->rlfa_count == 0) {
/* remove dynamic targeted neighbor */
@@ -245,7 +245,7 @@ tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr)
struct tnbr *
tnbr_check(struct ldpd_conf *xconf, struct tnbr *tnbr)
{
- if (!(tnbr->flags & (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) &&
+ if (!CHECK_FLAG(tnbr->flags, (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) &&
tnbr->pw_count == 0 && tnbr->rlfa_count == 0) {
tnbr_del(xconf, tnbr);
return (NULL);
diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c
index b181e33a5b..906b5c1bf2 100644
--- a/ldpd/ldp_vty_exec.c
+++ b/ldpd/ldp_vty_exec.c
@@ -408,10 +408,10 @@ show_discovery_detail_msg(struct vty *vty, struct imsg *imsg,
rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
vty_out (vty, "Local:\n");
vty_out (vty, " LSR Id: %pI4:0\n",&rtr_id);
- if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
+ if (CHECK_FLAG(ldpd_conf->ipv4.flags, F_LDPD_AF_ENABLED))
vty_out (vty, " Transport Address (IPv4): %s\n",
log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
- if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
+ if (CHECK_FLAG(ldpd_conf->ipv6.flags, F_LDPD_AF_ENABLED))
vty_out (vty, " Transport Address (IPv6): %s\n",
log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
vty_out (vty, "Discovery Sources:\n");
@@ -524,10 +524,10 @@ show_discovery_detail_msg_json(struct imsg *imsg, struct show_params *params,
case IMSG_CTL_SHOW_DISCOVERY:
rtr_id.s_addr = ldp_rtr_id_get(ldpd_conf);
json_object_string_addf(json, "lsrId", "%pI4", &rtr_id);
- if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
+ if (CHECK_FLAG(ldpd_conf->ipv4.flags, F_LDPD_AF_ENABLED))
json_object_string_add(json, "transportAddressIPv4",
log_addr(AF_INET, &ldpd_conf->ipv4.trans_addr));
- if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
+ if (CHECK_FLAG(ldpd_conf->ipv6.flags, F_LDPD_AF_ENABLED))
json_object_string_add(json, "transportAddressIPv6",
log_addr(AF_INET6, &ldpd_conf->ipv6.trans_addr));
json_interfaces = json_object_new_object();
@@ -968,11 +968,11 @@ show_nbr_capabilities(struct vty *vty, struct ctl_nbr *nbr)
" - Typed Wildcard (0x050B)\n"
" - Unrecognized Notification (0x0603)\n");
vty_out (vty, " Capabilities Received:\n");
- if (nbr->flags & F_NBR_CAP_DYNAMIC)
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_DYNAMIC))
vty_out (vty," - Dynamic Announcement (0x0506)\n");
- if (nbr->flags & F_NBR_CAP_TWCARD)
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_TWCARD))
vty_out (vty, " - Typed Wildcard (0x050B)\n");
- if (nbr->flags & F_NBR_CAP_UNOTIF)
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_UNOTIF))
vty_out (vty," - Unrecognized Notification (0x0603)\n");
}
@@ -1037,7 +1037,7 @@ show_nbr_capabilities_json(struct ctl_nbr *nbr, json_object *json_nbr)
json_object_object_add(json_nbr, "receivedCapabilities", json_array);
/* Dynamic Announcement (0x0506) */
- if (nbr->flags & F_NBR_CAP_DYNAMIC) {
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_DYNAMIC)) {
json_cap = json_object_new_object();
json_object_string_add(json_cap, "description",
"Dynamic Announcement");
@@ -1046,7 +1046,7 @@ show_nbr_capabilities_json(struct ctl_nbr *nbr, json_object *json_nbr)
}
/* Typed Wildcard (0x050B) */
- if (nbr->flags & F_NBR_CAP_TWCARD) {
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_TWCARD)) {
json_cap = json_object_new_object();
json_object_string_add(json_cap, "description",
"Typed Wildcard");
@@ -1055,7 +1055,7 @@ show_nbr_capabilities_json(struct ctl_nbr *nbr, json_object *json_nbr)
}
/* Unrecognized Notification (0x0603) */
- if (nbr->flags & F_NBR_CAP_UNOTIF) {
+ if (CHECK_FLAG(nbr->flags, F_NBR_CAP_UNOTIF)) {
json_cap = json_object_new_object();
json_object_string_add(json_cap, "description",
"Unrecognized Notification");
diff --git a/lib/asn.c b/lib/asn.c
index c64666375d..4042f5846c 100644
--- a/lib/asn.c
+++ b/lib/asn.c
@@ -52,6 +52,10 @@ static bool asn_str2asn_internal(const char *asstring, as_t *asn,
if (!isdigit((unsigned char)*p))
goto end;
+ /* leading zero is forbidden */
+ if (*p == '0' && isdigit((unsigned char)*(p + 1)))
+ goto end;
+
temp_val = 0;
while (isdigit((unsigned char)*p)) {
digit = (*p) - '0';
@@ -65,11 +69,17 @@ static bool asn_str2asn_internal(const char *asstring, as_t *asn,
high = (uint32_t)temp_val;
if (*p == '.') { /* dot format */
p++;
- temp_val = 0;
+
if (*p == '\0' && partial) {
*partial = true;
goto end;
}
+
+ /* leading zero is forbidden */
+ if (*p == '0' && isdigit((unsigned char)*(p + 1)))
+ goto end;
+
+ temp_val = 0;
while (isdigit((unsigned char)*p)) {
digit = (*p) - '0';
temp_val *= 10;
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 0467dc1d7e..d1b7dd133e 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -992,7 +992,7 @@ static void frr_config_read_in(struct thread *t)
int ret;
context.client = NB_CLIENT_CLI;
- ret = nb_candidate_commit(&context, vty_shared_candidate_config,
+ ret = nb_candidate_commit(context, vty_shared_candidate_config,
true, "Read configuration file", NULL,
errmsg, sizeof(errmsg));
if (ret != NB_OK && ret != NB_ERR_NO_CHANGES)
diff --git a/lib/northbound.c b/lib/northbound.c
index b755264be1..6f2c522a29 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -61,7 +61,7 @@ static int nb_callback_configuration(struct nb_context *context,
struct nb_config_change *change,
char *errmsg, size_t errmsg_len);
static struct nb_transaction *
-nb_transaction_new(struct nb_context *context, struct nb_config *config,
+nb_transaction_new(struct nb_context context, struct nb_config *config,
struct nb_config_cbs *changes, const char *comment,
char *errmsg, size_t errmsg_len);
static void nb_transaction_free(struct nb_transaction *transaction);
@@ -835,7 +835,7 @@ int nb_candidate_validate(struct nb_context *context,
return ret;
}
-int nb_candidate_commit_prepare(struct nb_context *context,
+int nb_candidate_commit_prepare(struct nb_context context,
struct nb_config *candidate,
const char *comment,
struct nb_transaction **transaction,
@@ -860,9 +860,8 @@ int nb_candidate_commit_prepare(struct nb_context *context,
return NB_ERR_NO_CHANGES;
}
- if (nb_candidate_validate_code(context, candidate, &changes, errmsg,
- errmsg_len)
- != NB_OK) {
+ if (nb_candidate_validate_code(&context, candidate, &changes, errmsg,
+ errmsg_len) != NB_OK) {
flog_warn(EC_LIB_NB_CANDIDATE_INVALID,
"%s: failed to validate candidate configuration",
__func__);
@@ -913,7 +912,7 @@ void nb_candidate_commit_apply(struct nb_transaction *transaction,
nb_transaction_free(transaction);
}
-int nb_candidate_commit(struct nb_context *context, struct nb_config *candidate,
+int nb_candidate_commit(struct nb_context context, struct nb_config *candidate,
bool save_transaction, const char *comment,
uint32_t *transaction_id, char *errmsg,
size_t errmsg_len)
@@ -1411,13 +1410,13 @@ static int nb_callback_configuration(struct nb_context *context,
}
static struct nb_transaction *
-nb_transaction_new(struct nb_context *context, struct nb_config *config,
+nb_transaction_new(struct nb_context context, struct nb_config *config,
struct nb_config_cbs *changes, const char *comment,
char *errmsg, size_t errmsg_len)
{
struct nb_transaction *transaction;
- if (nb_running_lock_check(context->client, context->user)) {
+ if (nb_running_lock_check(context.client, context.user)) {
strlcpy(errmsg,
"running configuration is locked by another client",
errmsg_len);
@@ -1469,7 +1468,7 @@ static int nb_transaction_process(enum nb_event event,
break;
/* Call the appropriate callback. */
- ret = nb_callback_configuration(transaction->context, event,
+ ret = nb_callback_configuration(&transaction->context, event,
change, errmsg, errmsg_len);
switch (event) {
case NB_EV_PREPARE:
@@ -1584,7 +1583,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction,
/* Call the 'apply_finish' callbacks, sorted by their priorities. */
RB_FOREACH (cb, nb_config_cbs, &cbs)
- nb_callback_apply_finish(transaction->context, cb->nb_node,
+ nb_callback_apply_finish(&transaction->context, cb->nb_node,
cb->dnode, errmsg, errmsg_len);
/* Release memory. */
diff --git a/lib/northbound.h b/lib/northbound.h
index c132daebdb..152810b3a9 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -622,22 +622,6 @@ struct nb_context {
/* Northbound user (can be NULL). */
const void *user;
-
- /* Client-specific data. */
-#if 0
- union {
- struct {
- } cli;
- struct {
- } confd;
- struct {
- } sysrepo;
- struct {
- } grpc;
- struct {
- } pcep;
- } client_data;
-#endif
};
/* Northbound configuration. */
@@ -666,7 +650,7 @@ struct nb_config_change {
/* Northbound configuration transaction. */
struct nb_transaction {
- struct nb_context *context;
+ struct nb_context context;
char comment[80];
struct nb_config *config;
struct nb_config_cbs changes;
@@ -927,7 +911,7 @@ extern int nb_candidate_validate(struct nb_context *context,
* the candidate configuration.
* - NB_ERR for other errors.
*/
-extern int nb_candidate_commit_prepare(struct nb_context *context,
+extern int nb_candidate_commit_prepare(struct nb_context context,
struct nb_config *candidate,
const char *comment,
struct nb_transaction **transaction,
@@ -1014,7 +998,7 @@ extern void nb_candidate_commit_apply(struct nb_transaction *transaction,
* the candidate configuration.
* - NB_ERR for other errors.
*/
-extern int nb_candidate_commit(struct nb_context *context,
+extern int nb_candidate_commit(struct nb_context context,
struct nb_config *candidate,
bool save_transaction, const char *comment,
uint32_t *transaction_id, char *errmsg,
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 0dfa66b37e..fa5884fb78 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -46,7 +46,7 @@ static int nb_cli_classic_commit(struct vty *vty)
context.client = NB_CLIENT_CLI;
context.user = vty;
- ret = nb_candidate_commit(&context, vty->candidate_config, true, NULL,
+ ret = nb_candidate_commit(context, vty->candidate_config, true, NULL,
NULL, errmsg, sizeof(errmsg));
switch (ret) {
case NB_OK:
@@ -313,7 +313,7 @@ int nb_cli_confirmed_commit_rollback(struct vty *vty)
context.client = NB_CLIENT_CLI;
context.user = vty;
ret = nb_candidate_commit(
- &context, vty->confirmed_commit_rollback, true,
+ context, vty->confirmed_commit_rollback, true,
"Rollback to previous configuration - confirmed commit has timed out",
&transaction_id, errmsg, sizeof(errmsg));
if (ret == NB_OK) {
@@ -394,9 +394,8 @@ static int nb_cli_commit(struct vty *vty, bool force,
context.client = NB_CLIENT_CLI;
context.user = vty;
- ret = nb_candidate_commit(&context, vty->candidate_config, true,
- comment, &transaction_id, errmsg,
- sizeof(errmsg));
+ ret = nb_candidate_commit(context, vty->candidate_config, true, comment,
+ &transaction_id, errmsg, sizeof(errmsg));
/* Map northbound return code to CLI return code. */
switch (ret) {
@@ -1717,7 +1716,7 @@ static int nb_cli_rollback_configuration(struct vty *vty,
context.client = NB_CLIENT_CLI;
context.user = vty;
- ret = nb_candidate_commit(&context, candidate, true, comment, NULL,
+ ret = nb_candidate_commit(context, candidate, true, comment, NULL,
errmsg, sizeof(errmsg));
nb_config_free(candidate);
switch (ret) {
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
index 81ba313e81..2b57ff2707 100644
--- a/lib/northbound_confd.c
+++ b/lib/northbound_confd.c
@@ -311,7 +311,7 @@ static void frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen)
*/
transaction = NULL;
context.client = NB_CLIENT_CONFD;
- ret = nb_candidate_commit_prepare(&context, candidate, NULL,
+ ret = nb_candidate_commit_prepare(context, candidate, NULL,
&transaction, errmsg, sizeof(errmsg));
if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) {
enum confd_errcode errcode;
diff --git a/lib/northbound_db.c b/lib/northbound_db.c
index cefcfbcf1f..74abcde955 100644
--- a/lib/northbound_db.c
+++ b/lib/northbound_db.c
@@ -73,7 +73,7 @@ int nb_db_transaction_save(const struct nb_transaction *transaction,
if (!ss)
goto exit;
- client_name = nb_client_name(transaction->context->client);
+ client_name = nb_client_name(transaction->context.client);
/*
* Always record configurations in the XML format, save the default
* values too, as this covers the case where defaults may change.
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index f5d59d92d6..1459146eab 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -824,7 +824,7 @@ HandleUnaryCommit(UnaryRpcState<frr::CommitRequest, frr::CommitResponse> *tag)
case frr::CommitRequest::PREPARE:
grpc_debug("`-> Performing PREPARE");
ret = nb_candidate_commit_prepare(
- &context, candidate->config, comment.c_str(),
+ context, candidate->config, comment.c_str(),
&candidate->transaction, errmsg, sizeof(errmsg));
break;
case frr::CommitRequest::ABORT:
@@ -840,7 +840,7 @@ HandleUnaryCommit(UnaryRpcState<frr::CommitRequest, frr::CommitResponse> *tag)
break;
case frr::CommitRequest::ALL:
grpc_debug("`-> Performing ALL");
- ret = nb_candidate_commit(&context, candidate->config, true,
+ ret = nb_candidate_commit(context, candidate->config, true,
comment.c_str(), &transaction_id,
errmsg, sizeof(errmsg));
break;
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 824d81a51e..096414ff24 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -268,7 +268,7 @@ static int frr_sr_config_change_cb_prepare(sr_session_ctx_t *session,
* Validate the configuration changes and allocate all resources
* required to apply them.
*/
- ret = nb_candidate_commit_prepare(&context, candidate, NULL,
+ ret = nb_candidate_commit_prepare(context, candidate, NULL,
&transaction, errmsg, sizeof(errmsg));
if (ret != NB_OK && ret != NB_ERR_NO_CHANGES)
flog_warn(
diff --git a/lib/vty.c b/lib/vty.c
index 1854abb0bf..786271abe8 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2420,7 +2420,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp)
context.client = NB_CLIENT_CLI;
context.user = vty;
- ret = nb_candidate_commit(&context, vty->candidate_config, true,
+ ret = nb_candidate_commit(context, vty->candidate_config, true,
"Read configuration file", NULL,
errmsg, sizeof(errmsg));
if (ret != NB_OK && ret != NB_ERR_NO_CHANGES)
diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c
index 75d8098821..fcece56c6f 100644
--- a/pimd/pim6_mld.c
+++ b/pimd/pim6_mld.c
@@ -2380,24 +2380,18 @@ static void gm_show_if_one_detail(struct vty *vty, struct interface *ifp)
}
static void gm_show_if_one(struct vty *vty, struct interface *ifp,
- json_object *js_if)
+ json_object *js_if, struct ttable *tt)
{
struct pim_interface *pim_ifp = (struct pim_interface *)ifp->info;
struct gm_if *gm_ifp = pim_ifp->mld;
bool querier;
- if (!gm_ifp) {
- if (js_if)
- json_object_string_add(js_if, "state", "down");
- else
- vty_out(vty, "%-16s %5s\n", ifp->name, "down");
- return;
- }
-
querier = IPV6_ADDR_SAME(&gm_ifp->querier, &pim_ifp->ll_lowest);
if (js_if) {
json_object_string_add(js_if, "name", ifp->name);
+ json_object_string_addf(js_if, "address", "%pPA",
+ &pim_ifp->primary_address);
json_object_string_add(js_if, "state", "up");
json_object_string_addf(js_if, "version", "%d",
gm_ifp->cur_version);
@@ -2424,11 +2418,11 @@ static void gm_show_if_one(struct vty *vty, struct interface *ifp,
json_object_int_add(js_if, "timerLastMemberQueryIntervalMsec",
gm_ifp->cur_query_intv_trig);
} else {
- vty_out(vty, "%-16s %-5s %d %-25pPA %-5s %11pTH %pTVMs\n",
- ifp->name, "up", gm_ifp->cur_version, &gm_ifp->querier,
- querier ? "query" : "other",
- querier ? gm_ifp->t_query : gm_ifp->t_other_querier,
- &gm_ifp->started);
+ ttable_add_row(tt, "%s|%s|%pPAs|%d|%s|%pPAs|%pTH|%pTVMs",
+ ifp->name, "up", &pim_ifp->primary_address,
+ gm_ifp->cur_version, querier ? "local" : "other",
+ &gm_ifp->querier, gm_ifp->t_query,
+ &gm_ifp->started);
}
}
@@ -2436,13 +2430,27 @@ static void gm_show_if_vrf(struct vty *vty, struct vrf *vrf, const char *ifname,
bool detail, json_object *js)
{
struct interface *ifp;
- json_object *js_vrf;
+ json_object *js_vrf = NULL;
+ struct pim_interface *pim_ifp;
+ struct ttable *tt = NULL;
+ char *table = NULL;
if (js) {
js_vrf = json_object_new_object();
json_object_object_add(js, vrf->name, js_vrf);
}
+ if (!js && !detail) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|State|Address|V|Querier|QuerierIp|Query Timer|Uptime");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
+
FOR_ALL_INTERFACES (vrf, ifp) {
json_object *js_if = NULL;
@@ -2453,24 +2461,31 @@ static void gm_show_if_vrf(struct vty *vty, struct vrf *vrf, const char *ifname,
continue;
}
- if (!ifp->info)
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp || !pim_ifp->mld)
continue;
+
if (js) {
js_if = json_object_new_object();
json_object_object_add(js_vrf, ifp->name, js_if);
}
- gm_show_if_one(vty, ifp, js_if);
+ gm_show_if_one(vty, ifp, js_if, tt);
+ }
+
+ /* Dump the generated table. */
+ if (!js && !detail) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
}
}
static void gm_show_if(struct vty *vty, struct vrf *vrf, const char *ifname,
bool detail, json_object *js)
{
- if (!js && !detail)
- vty_out(vty, "%-16s %-5s V %-25s %-18s %s\n", "Interface",
- "State", "Querier", "Timer", "Uptime");
-
if (vrf)
gm_show_if_vrf(vty, vrf, ifname, detail, js);
else
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index c7b501ee14..75df09ec35 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -1385,7 +1385,7 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
nbr = pim_neighbor_find(
up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr);
+ up->rpf.rpf_addr, false);
if (nbr)
pim_time_timer_to_hhmmss(join_timer,
sizeof(join_timer),
diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c
index 8d19247415..978607d147 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -277,7 +277,7 @@ int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf,
New neighbor?
*/
- neigh = pim_neighbor_find(ifp, src_addr);
+ neigh = pim_neighbor_find(ifp, src_addr, false);
if (!neigh) {
/* Add as new neighbor */
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 0ba7b5a65e..d284912d1d 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1534,8 +1534,10 @@ void pim_if_create_pimreg(struct pim_instance *pim)
pim->vrf->name);
pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
- pim_if_new(pim->regiface, false, false, true,
- false /*vxlan_term*/);
+ if (!pim->regiface->info)
+ pim_if_new(pim->regiface, false, false, true,
+ false /*vxlan_term*/);
+
/*
* On vrf moves we delete the interface if there
* is nothing going on with it. We cannot have
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 02b50c9af2..adf0540f65 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -154,11 +154,15 @@ int pim_mroute_msg_nocache(int fd, struct interface *ifp, const kernmsg *msg)
sg.src = msg->msg_im_src;
sg.grp = msg->msg_im_dst;
- if (!pim_ifp) {
+
+ if (!pim_ifp || !pim_ifp->pim_enable) {
if (PIM_DEBUG_MROUTE)
zlog_debug(
- "%s: PIM not enabled on interface, dropping packet to %pSG",
- ifp->name, &sg);
+ "%s: %s on interface, dropping packet to %pSG",
+ ifp->name,
+ !pim_ifp ? "Multicast not enabled"
+ : "PIM not enabled",
+ &sg);
return 0;
}
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 36e90a9697..fa6f664149 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -157,10 +157,10 @@ static int pim_cmd_interface_delete(struct interface *ifp)
* pim_ifp->pim_neighbor_list.
*/
pim_sock_delete(ifp, "pim unconfigured on interface");
+ pim_upstream_nh_if_update(pim_ifp->pim, ifp);
if (!pim_ifp->gm_enable) {
pim_if_addr_del_all(ifp);
- pim_upstream_nh_if_update(pim_ifp->pim, ifp);
pim_if_delete(ifp);
}
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 9edc3c1af2..0b7ea0ad9d 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -406,7 +406,7 @@ struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
}
struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
- pim_addr source_addr)
+ pim_addr source_addr, bool secondary)
{
struct pim_interface *pim_ifp;
struct listnode *node;
@@ -425,6 +425,13 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
}
}
+ if (secondary) {
+ struct prefix p;
+
+ pim_addr_to_prefix(&p, source_addr);
+ return pim_neighbor_find_by_secondary(ifp, &p);
+ }
+
return NULL;
}
diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h
index e00f99fe26..f7375745a1 100644
--- a/pimd/pim_neighbor.h
+++ b/pimd/pim_neighbor.h
@@ -38,7 +38,7 @@ struct pim_neighbor {
void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);
void pim_neighbor_free(struct pim_neighbor *neigh);
struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
- pim_addr source_addr);
+ pim_addr source_addr, bool secondary);
struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
struct prefix *src);
struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp);
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index d73f366d43..d164e7ed81 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -307,12 +307,11 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr,
if (if_is_loopback(ifp) && if_is_loopback(src_ifp))
return true;
- nbr = pim_neighbor_find(ifp, znh->nexthop_addr);
+ nbr = pim_neighbor_find(ifp, znh->nexthop_addr, true);
if (!nbr)
continue;
- return znh->ifindex == src_ifp->ifindex &&
- (!pim_addr_cmp(znh->nexthop_addr, src_ip));
+ return znh->ifindex == src_ifp->ifindex;
}
return false;
}
@@ -373,12 +372,13 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr,
return true;
/* MRIB (IGP) may be pointing at a router where PIM is down */
- nbr = pim_neighbor_find(ifp, nhaddr);
+
+ nbr = pim_neighbor_find(ifp, nhaddr, true);
+
if (!nbr)
continue;
- return nh->ifindex == src_ifp->ifindex &&
- (!pim_addr_cmp(nhaddr, src_ip));
+ return nh->ifindex == src_ifp->ifindex;
}
return false;
}
@@ -561,7 +561,7 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
src)) {
nbr = pim_neighbor_find(
nexthop->interface,
- nexthop->mrib_nexthop_addr);
+ nexthop->mrib_nexthop_addr, true);
if (!nbr
&& !if_is_loopback(nexthop->interface)) {
if (PIM_DEBUG_PIM_NHT)
@@ -603,7 +603,7 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
#else
pim_addr nhaddr = nh_node->gate.ipv6;
#endif
- nbrs[i] = pim_neighbor_find(ifps[i], nhaddr);
+ nbrs[i] = pim_neighbor_find(ifps[i], nhaddr, true);
if (nbrs[i] || pim_if_connected_to_source(ifps[i], src))
num_nbrs++;
}
@@ -954,7 +954,8 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
pim->vrf->vrf_id);
if (ifps[i]) {
nbrs[i] = pim_neighbor_find(
- ifps[i], nexthop_tab[i].nexthop_addr);
+ ifps[i], nexthop_tab[i].nexthop_addr, true);
+
if (nbrs[i] || pim_if_connected_to_source(ifps[i], src))
num_nbrs++;
}
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index a7a8b05753..1248db3de4 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -289,7 +289,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len,
pim_msg_len - PIM_MSG_HEADER_LEN);
break;
case PIM_MSG_TYPE_JOIN_PRUNE:
- neigh = pim_neighbor_find(ifp, sg.src);
+ neigh = pim_neighbor_find(ifp, sg.src, false);
if (!neigh) {
if (PIM_DEBUG_PIM_PACKETS)
zlog_debug(
@@ -304,7 +304,7 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len,
pim_msg_len - PIM_MSG_HEADER_LEN);
break;
case PIM_MSG_TYPE_ASSERT:
- neigh = pim_neighbor_find(ifp, sg.src);
+ neigh = pim_neighbor_find(ifp, sg.src, false);
if (!neigh) {
if (PIM_DEBUG_PIM_PACKETS)
zlog_debug(
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 06765d93df..b17ae3131f 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -116,8 +116,8 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
i++;
} else if (neighbor_needed &&
!pim_if_connected_to_source(ifp, addr)) {
- nbr = pim_neighbor_find(ifp,
- nexthop_tab[i].nexthop_addr);
+ nbr = pim_neighbor_find(
+ ifp, nexthop_tab[i].nexthop_addr, true);
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug("ifp name: %s, pim nbr: %p",
ifp->name, nbr);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index d63d530f93..b0f1158596 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -327,7 +327,7 @@ static void join_timer_stop(struct pim_upstream *up)
if (up->rpf.source_nexthop.interface)
nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr);
+ up->rpf.rpf_addr, true);
if (nbr)
pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
@@ -341,7 +341,7 @@ void join_timer_start(struct pim_upstream *up)
if (up->rpf.source_nexthop.interface) {
nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr);
+ up->rpf.rpf_addr, true);
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug(
@@ -433,7 +433,8 @@ void pim_upstream_join_suppress(struct pim_upstream *up, pim_addr rpf,
else {
/* Remove it from jp agg from the nbr for suppression */
nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr);
+ up->rpf.rpf_addr, true);
+
if (nbr) {
join_timer_remain_msec =
pim_time_timer_remain_msec(nbr->jp_timer);
@@ -485,7 +486,8 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
struct pim_neighbor *nbr;
nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr);
+ up->rpf.rpf_addr, true);
+
if (nbr)
join_timer_remain_msec =
pim_time_timer_remain_msec(nbr->jp_timer);
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index e39eca7a2c..29aac7f1c7 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -257,7 +257,8 @@ void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
struct pim_neighbor *nbr;
nbr = pim_neighbor_find(old->source_nexthop.interface,
- old->rpf_addr);
+ old->rpf_addr, true);
+
if (nbr)
pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 652aaa25d4..dde38c8693 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -639,6 +639,14 @@ static struct test_peer_attr test_peer_attrs[] = {
.u.flag = PEER_FLAG_WEIGHT,
.handlers[0] = TEST_HANDLER(weight),
},
+ {
+ .cmd = "accept-own",
+ .peer_cmd = "accept-own",
+ .group_cmd = "accept-own",
+ .families[0] = {.afi = AFI_IP, .safi = SAFI_MPLS_VPN},
+ .families[1] = {.afi = AFI_IP6, .safi = SAFI_MPLS_VPN},
+ .u.flag = PEER_FLAG_ACCEPT_OWN,
+ },
{NULL}
};
/* clang-format on */
diff --git a/tests/bgpd/test_peer_attr.py b/tests/bgpd/test_peer_attr.py
index 16b441b25d..eb57618434 100644
--- a/tests/bgpd/test_peer_attr.py
+++ b/tests/bgpd/test_peer_attr.py
@@ -196,3 +196,5 @@ TestFlag.okfail("peer\\ipv4-unicast\\weight")
TestFlag.okfail("peer\\ipv4-multicast\\weight")
TestFlag.okfail("peer\\ipv6-unicast\\weight")
TestFlag.okfail("peer\\ipv6-multicast\\weight")
+TestFlag.okfail("peer\\ipv4-vpn\\accept-own")
+TestFlag.okfail("peer\\ipv6-vpn\\accept-own")
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
index 0b6152568d..a820b4b221 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
@@ -83,18 +83,9 @@ def test_bgp_gr_restart_retain_routes():
return topotest.json_cmp(output, expected)
def _bgp_check_kernel_retained_routes():
- output = (
- r2.cmd("ip route show 172.16.255.1/32 proto bgp dev r2-eth0")
- .replace("\n", "")
- .rstrip()
- )
- expected = "172.16.255.1 via 192.168.255.1 metric 20"
- diff = topotest.get_textdiff(
- output, expected, "Actual IP Routing Table", "Expected IP RoutingTable"
- )
- if diff:
- return False
- return True
+ output = json.loads(r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0"))
+ expected = [{"dst":"172.16.255.1","gateway":"192.168.255.1","metric":20}]
+ return topotest.json_cmp(output, expected)
step("Initial BGP converge")
test_func = functools.partial(_bgp_converge)
@@ -110,7 +101,7 @@ def test_bgp_gr_restart_retain_routes():
assert result is None, "Failed to see BGP retained routes on R2"
step("Check if routes (Kernel) are retained at R2")
- assert _bgp_check_kernel_retained_routes() == True
+ assert _bgp_check_kernel_retained_routes() is None, "Failed to retain BGP routes in kernel on R2"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json
new file mode 100644
index 0000000000..184ab312b6
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json
@@ -0,0 +1,49 @@
+{
+ "vrfName": "vrf1",
+ "localAS": 65500,
+ "routes":
+ {
+ "172.31.0.10/32": [
+ {
+ "prefix": "172.31.0.10",
+ "prefixLen": 32,
+ "network": "172.31.0.10\/32",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "192.168.0.3",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ },
+ {
+ "prefix": "172.31.0.10",
+ "prefixLen": 32,
+ "network": "172.31.0.10\/32",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "192.168.0.2",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "172.31.0.1/32": [
+ {
+ "prefix": "172.31.0.1",
+ "prefixLen": 32,
+ "network": "172.31.0.1\/32",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
index 2eebe5e6dd..0249279c65 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
@@ -1,16 +1,19 @@
router bgp 65500
- bgp router-id 1.1.1.1
+ bgp router-id 192.0.2.1
no bgp ebgp-requires-policy
- neighbor 10.125.0.2 remote-as 65501
+ neighbor 192.168.0.2 remote-as 65501
+ neighbor 192.168.0.3 remote-as 65501
address-family ipv4 unicast
- no neighbor 10.125.0.2 activate
+ no neighbor 192.168.0.3 activate
+ no neighbor 192.168.0.2 activate
exit-address-family
address-family ipv4 vpn
- neighbor 10.125.0.2 activate
+ neighbor 192.168.0.2 activate
+ neighbor 192.168.0.3 activate
exit-address-family
!
router bgp 65500 vrf vrf1
- bgp router-id 1.1.1.1
+ bgp router-id 192.0.2.1
address-family ipv4 unicast
redistribute connected
label vpn export 101
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
index da7d281833..79b020af76 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
@@ -1,8 +1,8 @@
{
- "10.200.0.0/24": [
+ "172.31.0.10/32": [
{
- "prefix": "10.200.0.0/24",
- "prefixLen": 24,
+ "prefix": "172.31.0.10/32",
+ "prefixLen": 32,
"protocol": "bgp",
"vrfName": "vrf1",
"selected": true,
@@ -13,7 +13,19 @@
{
"flags": 3,
"fib": true,
- "ip": "10.125.0.2",
+ "ip": "192.168.0.2",
+ "afi": "ipv4",
+ "interfaceName": "r1-eth0",
+ "vrf": "default",
+ "active": true,
+ "labels":[
+ 102
+ ]
+ },
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "192.168.0.3",
"afi": "ipv4",
"interfaceName": "r1-eth0",
"vrf": "default",
@@ -25,10 +37,10 @@
]
}
],
- "10.201.0.0/24": [
+ "172.31.0.1/32": [
{
- "prefix": "10.201.0.0/24",
- "prefixLen": 24,
+ "prefix": "172.31.0.1/32",
+ "prefixLen": 32,
"protocol": "connected",
"vrfName": "vrf1",
"selected": true,
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
index e9ae4e9831..f626e448a7 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
@@ -1,7 +1,7 @@
log stdout
interface r1-eth1 vrf vrf1
- ip address 10.201.0.1/24
+ ip address 172.31.0.1/32
!
interface r1-eth0
- ip address 10.125.0.1/24
+ ip address 192.168.0.1/24
!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
index 19797dd561..1fc3a4b89c 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
@@ -3,28 +3,28 @@
"localAS": 65501,
"routes":
{
- "10.201.0.0/24": [
+ "172.31.0.1/32": [
{
- "prefix": "10.201.0.0",
- "prefixLen": 24,
- "network": "10.201.0.0\/24",
+ "prefix": "172.31.0.1",
+ "prefixLen": 32,
+ "network": "172.31.0.1\/32",
"nhVrfName": "default",
"nexthops": [
{
- "ip": "10.125.0.1",
+ "ip": "192.168.0.1",
"afi": "ipv4",
"used": true
}
]
}
],
- "10.200.0.0/24": [
+ "172.31.0.10/32": [
{
"valid": true,
"bestpath": true,
- "prefix": "10.200.0.0",
- "prefixLen": 24,
- "network": "10.200.0.0\/24",
+ "prefix": "172.31.0.10",
+ "prefixLen": 32,
+ "network": "172.31.0.10\/32",
"nexthops": [
{
"ip": "0.0.0.0",
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
index e38c99d69c..e873469d79 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
@@ -1,16 +1,16 @@
router bgp 65501
- bgp router-id 2.2.2.2
+ bgp router-id 192.0.2.2
no bgp ebgp-requires-policy
- neighbor 10.125.0.1 remote-as 65500
+ neighbor 192.168.0.1 remote-as 65500
address-family ipv4 unicast
- no neighbor 10.125.0.1 activate
+ no neighbor 192.168.0.1 activate
exit-address-family
address-family ipv4 vpn
- neighbor 10.125.0.1 activate
+ neighbor 192.168.0.1 activate
exit-address-family
!
router bgp 65501 vrf vrf1
- bgp router-id 2.2.2.2
+ bgp router-id 192.0.2.2
address-family ipv4 unicast
redistribute connected
label vpn export 102
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
index 6c433aef2b..bbc524065d 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
@@ -1,7 +1,7 @@
log stdout
interface r2-eth1 vrf vrf1
- ip address 10.200.0.2/24
+ ip address 172.31.0.10/32
!
interface r2-eth0
- ip address 10.125.0.2/24
+ ip address 192.168.0.2/24
!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json
new file mode 100644
index 0000000000..19797dd561
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json
@@ -0,0 +1,38 @@
+{
+ "vrfName": "vrf1",
+ "localAS": 65501,
+ "routes":
+ {
+ "10.201.0.0/24": [
+ {
+ "prefix": "10.201.0.0",
+ "prefixLen": 24,
+ "network": "10.201.0.0\/24",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "10.125.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "10.200.0.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "prefix": "10.200.0.0",
+ "prefixLen": 24,
+ "network": "10.200.0.0\/24",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf
new file mode 100644
index 0000000000..a327638c69
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf
@@ -0,0 +1,25 @@
+router bgp 65501
+ bgp router-id 192.0.2.3
+ no bgp ebgp-requires-policy
+ neighbor 192.168.0.1 remote-as 65500
+ address-family ipv4 unicast
+ no neighbor 192.168.0.1 activate
+ exit-address-family
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 activate
+ exit-address-family
+!
+router bgp 65502 vrf vrf1
+ bgp router-id 192.0.2.3
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export 102
+ rd vpn export 444:3
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
+interface r3-eth0
+ mpls bgp forwarding
+!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf
new file mode 100644
index 0000000000..4412c04a2b
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf
@@ -0,0 +1,7 @@
+log stdout
+interface r3-eth1 vrf vrf1
+ ip address 172.31.0.10/32
+!
+interface r3-eth0
+ ip address 192.168.0.3/24
+!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
index 342bad20ab..61e1163c18 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
+++ b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
@@ -40,10 +40,12 @@ def build_topo(tgen):
# Create 2 routers.
tgen.add_router("r1")
tgen.add_router("r2")
+ tgen.add_router("r3")
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
switch = tgen.add_switch("s2")
switch.add_link(tgen.gears["r1"])
@@ -51,27 +53,38 @@ def build_topo(tgen):
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["r2"])
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r3"])
+
+
def _populate_iface():
tgen = get_topogen()
cmds_list = [
- 'ip link add vrf1 type vrf table 10',
- 'echo 100000 > /proc/sys/net/mpls/platform_labels',
- 'ip link set dev vrf1 up',
- 'ip link set dev {0}-eth1 master vrf1',
- 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
+ "ip link add vrf1 type vrf table 10",
+ "echo 100000 > /proc/sys/net/mpls/platform_labels",
+ "ip link set dev vrf1 up",
+ "ip link set dev {0}-eth1 master vrf1",
+ "echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input",
]
for cmd in cmds_list:
- input = cmd.format('r1', '1', '2')
- logger.info('input: ' + cmd)
- output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
- logger.info('output: ' + output)
+ input = cmd.format("r1")
+ logger.info("input: " + cmd)
+ output = tgen.net["r1"].cmd(cmd.format("r1"))
+ logger.info("output: " + output)
+
+ for cmd in cmds_list:
+ input = cmd.format("r2")
+ logger.info("input: " + cmd)
+ output = tgen.net["r2"].cmd(cmd.format("r2"))
+ logger.info("output: " + output)
for cmd in cmds_list:
- input = cmd.format('r2', '2', '1')
- logger.info('input: ' + cmd)
- output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
- logger.info('output: ' + output)
+ input = cmd.format("r3")
+ logger.info("input: " + cmd)
+ output = tgen.net["r3"].cmd(cmd.format("r3"))
+ logger.info("output: " + output)
+
def setup_module(mod):
"Sets up the pytest environment"
@@ -109,13 +122,13 @@ def test_protocols_convergence():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
logger.info("Dump some context for r1")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
router.vtysh_cmd("show running-config")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
logger.info("Dump some context for r2")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
@@ -124,11 +137,11 @@ def test_protocols_convergence():
# Check IPv4 routing tables on r1
logger.info("Checking IPv4 routes for convergence on r1")
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
- assert 0, 'ipv4_routes.json file not found'
+ assert 0, "ipv4_routes.json file not found"
return
expected = json.loads(open(json_file).read())
@@ -142,12 +155,52 @@ def test_protocols_convergence():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
+ # Check BGP IPv4 routing tables on r1
+ logger.info("Checking BGP IPv4 routes for convergence on r1")
+ router = tgen.gears["r1"]
+ json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ assert 0, "bgp_ipv4_routes.json file not found"
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp vrf vrf1 ipv4 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check BGP IPv4 imported entry is not detected as local
+ # "selectionReason": "Locally configured route"
+ donna = tgen.gears["r1"].vtysh_cmd(
+ "show bgp vrf vrf1 ipv4 172.31.0.10/32 json", isjson=True
+ )
+ routes = donna["paths"]
+ selectionReasonFound = False
+ for route in routes:
+ if "bestpath" not in route.keys():
+ continue
+ if "selectionReason" not in route["bestpath"].keys():
+ continue
+
+ if "Locally configured route" == route["bestpath"]["selectionReason"]:
+ assert 0, "imported prefix has wrong reason detected"
+
+ selectionReasonFound = True
+
+ if not selectionReasonFound:
+ assertmsg = '"{}" imported prefix has wrong reason detected'.format(router.name)
+ assert False, assertmsg
+
# Check BGP IPv4 routing tables on r2 not installed
logger.info("Checking BGP IPv4 routes for convergence on r2")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
- assert 0, 'bgp_ipv4_routes.json file not found'
+ assert 0, "bgp_ipv4_routes.json file not found"
expected = json.loads(open(json_file).read())
test_func = partial(
@@ -159,7 +212,8 @@ def test_protocols_convergence():
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
-
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py
index 608ef48ff4..baacba613d 100644
--- a/tests/topotests/isis_topo1/test_isis_topo1.py
+++ b/tests/topotests/isis_topo1/test_isis_topo1.py
@@ -520,6 +520,67 @@ def test_isis_overload_on_startup_override_timer():
check_lsp_overload_bit("r3", "r3.00-00", "0/0/1")
+def test_isis_advertise_passive_only():
+ """Check that we only advertise prefixes of passive interfaces when advertise-passive-only is enabled."""
+ tgen = get_topogen()
+ net = get_topogen().net
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing isis advertise-passive-only behavior")
+ expected_prefixes_no_advertise_passive_only = set(
+ ["10.0.20.0/24", "10.254.0.1/32", "2001:db8:f::1/128", "2001:db8:1:1::/64"]
+ )
+ expected_prefixes_advertise_passive_only = set(
+ ["10.254.0.1/32", "2001:db8:f::1/128"]
+ )
+ lsp_id = "r1.00-00"
+
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd(
+ """
+ configure
+ router isis 1
+ no redistribute ipv4 connected level-2
+ no redistribute ipv6 connected level-2
+ interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+ end
+ """
+ )
+
+ result = check_advertised_prefixes(
+ r1, lsp_id, expected_prefixes_no_advertise_passive_only
+ )
+ assert result is True, result
+
+ r1.vtysh_cmd(
+ """
+ configure
+ router isis 1
+ advertise-passive-only
+ end
+ """
+ )
+
+ result = check_advertised_prefixes(
+ r1, lsp_id, expected_prefixes_advertise_passive_only
+ )
+ assert result is True, result
+
+
+@retry(retry_timeout=5)
+def check_advertised_prefixes(router, lsp_id, expected_prefixes):
+ output = router.vtysh_cmd("show isis database detail {}".format(lsp_id))
+ prefixes = set(re.findall(r"IP(?:v6)? Reachability: (.*) \(Metric: 10\)", output))
+ if prefixes == expected_prefixes:
+ return True
+ return str({"expected_prefixes:": expected_prefixes, "prefixes": prefixes})
+
+
@retry(retry_timeout=200)
def _check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected):
"Verfiy overload bit in router's LSP"
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 7609c7f899..23b1f2e533 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -2816,7 +2816,7 @@ def get_ospf_database(tgen, topo, dut, input_dict, vrf=None, lsatype=None, rid=N
result = True
break
if (
- _age is not "get"
+ _age != "get"
and lsa["lsaAge"]
== show_ospf_json["routerLinkStates"][rtrlsa][
ospf_area
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index fd8a0de4ee..ff3ba5d12b 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -1178,6 +1178,13 @@ module frr-isisd {
"RFC6232";
}
+ leaf advertise-passive-only {
+ type boolean;
+ default "false";
+ description
+ "Advertise prefixes of passive interfaces only";
+ }
+
container lsp {
description
"Configuration of Link-State Packets (LSP) parameters";
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 900c6520d3..e4ddbd95d7 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2006,6 +2006,25 @@ static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla,
if (lla)
nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char ip_str[INET6_ADDRSTRLEN + 8];
+ struct interface *ifp = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(ns_id), ifindex);
+ if (ifp) {
+ if (family == AF_INET6)
+ snprintfrr(ip_str, sizeof(ip_str), "ipv6 %pI6",
+ (struct in6_addr *)addr);
+ else
+ snprintfrr(ip_str, sizeof(ip_str), "ipv4 %pI4",
+ (in_addr_t *)addr);
+ zlog_debug(
+ "%s: %s ifname %s ifindex %u addr %s mac %pEA vrf %s(%u)",
+ __func__, nl_msg_type_to_str(cmd), ifp->name,
+ ifindex, ip_str, (struct ethaddr *)lla,
+ vrf_id_to_name(ifp->vrf->vrf_id),
+ ifp->vrf->vrf_id);
+ }
+ }
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
false);
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 59152df2f1..1ff188c76d 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -121,8 +121,6 @@ static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop)
stream_putl(s, nexthop->ifindex);
break;
case NEXTHOP_TYPE_IPV6:
- stream_put(s, &nexthop->gate.ipv6, 16);
- break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_put(s, &nexthop->gate.ipv6, 16);
stream_putl(s, nexthop->ifindex);