summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/message.c91
-rw-r--r--babeld/message.h1
-rw-r--r--babeld/util.h6
-rw-r--r--bgpd/bgp_flowspec_util.c17
-rw-r--r--bgpd/bgp_vty.c23
-rw-r--r--configure.ac15
-rw-r--r--doc/user/mgmtd.rst43
-rw-r--r--isisd/isis_flex_algo.c3
-rw-r--r--isisd/isis_lsp.c5
-rw-r--r--isisd/isis_spf.c8
-rw-r--r--isisd/isisd.c4
-rw-r--r--ldpd/labelmapping.c236
-rw-r--r--ldpd/lde_lib.c70
-rw-r--r--ldpd/ldpe.c59
-rw-r--r--lib/command.c12
-rw-r--r--lib/flex_algo.c93
-rw-r--r--lib/flex_algo.h10
-rw-r--r--lib/link_state.c16
-rw-r--r--lib/log_vty.c11
-rw-r--r--lib/mgmt_be_client.c165
-rw-r--r--lib/mgmt_be_client.h14
-rw-r--r--lib/mgmt_fe_client.c83
-rw-r--r--lib/mgmt_fe_client.h14
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/vty.c18
-rw-r--r--lib/vty.h1
-rw-r--r--mgmtd/mgmt.c9
-rw-r--r--mgmtd/mgmt.h26
-rw-r--r--mgmtd/mgmt_be_adapter.c24
-rw-r--r--mgmtd/mgmt_be_server.c12
-rw-r--r--mgmtd/mgmt_ds.c12
-rw-r--r--mgmtd/mgmt_ds.h3
-rw-r--r--mgmtd/mgmt_fe_adapter.c28
-rw-r--r--mgmtd/mgmt_fe_server.c12
-rw-r--r--mgmtd/mgmt_history.c54
-rw-r--r--mgmtd/mgmt_history.h38
-rw-r--r--mgmtd/mgmt_txn.c14
-rw-r--r--mgmtd/mgmt_vty.c55
-rw-r--r--ospfd/ospf_vty.c9
-rw-r--r--pimd/pim6_mld.c15
-rw-r--r--pimd/pim_mroute.c2
-rw-r--r--pimd/pim_neighbor.c6
-rw-r--r--pimd/pim_oil.c25
-rw-r--r--pimd/pim_oil.h1
-rw-r--r--python/xref2vtysh.py2
-rw-r--r--ripd/rip_bfd.c2
-rw-r--r--ripd/rip_bfd.h2
-rw-r--r--ripd/rip_interface.c8
-rw-r--r--ripd/rip_nb_config.c2
-rw-r--r--ripd/ripd.c6
-rw-r--r--staticd/static_vty.c3
-rw-r--r--tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf1
-rw-r--r--tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py5
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf16
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf16
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf79
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json169
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json23
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json53
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json23
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json54
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json77
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json107
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json77
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json106
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json54
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json53
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json106
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json106
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json77
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json22
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json112
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json106
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf43
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf80
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json169
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json106
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json112
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf43
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py453
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf2
-rw-r--r--tests/topotests/lib/topogen.py6
-rw-r--r--tests/topotests/ospf_basic_functionality/ospf_lan.json10
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py14
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r2/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r3/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r4/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/ra/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/rb/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/rc/frr.conf4
-rw-r--r--tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py39
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/interface.c5
-rw-r--r--zebra/zebra_evpn_mh.c3
-rw-r--r--zebra/zebra_rnh.c14
113 files changed, 3829 insertions, 598 deletions
diff --git a/babeld/message.c b/babeld/message.c
index 15d772eb46..d4ddebff08 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -48,6 +48,13 @@ static const unsigned char tlv_min_length[MESSAGE_MAX + 1] =
[ MESSAGE_MH_REQUEST ] = 14,
};
+/* Checks whether an AE exists or must be silently ignored */
+static bool
+known_ae(int ae)
+{
+ return ae <= 4;
+}
+
/* Parse a network prefix, encoded in the somewhat baroque compressed
representation used by Babel. Return the number of bytes parsed. */
static int
@@ -277,6 +284,62 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
}
static int
+parse_request_subtlv(int ae, const unsigned char *a, int alen,
+ unsigned char *src_prefix, unsigned char *src_plen)
+{
+ int type, len, i = 0;
+ int have_src_prefix = 0;
+
+ while(i < alen) {
+ type = a[0];
+ if(type == SUBTLV_PAD1) {
+ i++;
+ continue;
+ }
+
+ if(i + 2 > alen)
+ goto fail;
+
+ len = a[i + 1];
+ if(i + 2 + len > alen)
+ goto fail;
+
+ if(type == SUBTLV_PADN) {
+ /* Nothing to do. */
+ } else if(type == SUBTLV_SOURCE_PREFIX) {
+ int rc;
+ if(len < 1)
+ goto fail;
+ if(a[i + 2] == 0)
+ goto fail;
+ if(have_src_prefix != 0)
+ goto fail;
+ rc = network_prefix(ae, a[i + 2], 0, a + i + 3, NULL,
+ len - 1, src_prefix);
+ if(rc < 0)
+ goto fail;
+ if(ae==1)
+ *src_plen = a[i + 2] + 96;
+ else
+ *src_plen = a[i + 2];
+ have_src_prefix = 1;
+ } else {
+ debugf(BABEL_DEBUG_COMMON,"Received unknown%s Route Request sub-TLV %d.",
+ ((type & 0x80) != 0) ? " mandatory" : "", type);
+ if((type & 0x80) != 0)
+ return -1;
+ }
+
+ i += len + 2;
+ }
+ return 1;
+
+ fail:
+ flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Route Request.");
+ return -1;
+}
+
+static int
network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r)
{
@@ -612,8 +675,14 @@ parse_packet(const unsigned char *from, struct interface *ifp,
interval, neigh, nh, channels,
channels_len(channels));
} else if(type == MESSAGE_REQUEST) {
- unsigned char prefix[16], plen;
- int rc;
+ unsigned char prefix[16], src_prefix[16], plen, src_plen;
+ int rc, is_ss;
+ if(len < 2) goto fail;
+ if(!known_ae(message[2])) {
+ debugf(BABEL_DEBUG_COMMON,"Received request with unknown AE %d. Ignoring.",
+ message[2]);
+ goto done;
+ }
rc = network_prefix(message[2], message[3], 0,
message + 4, NULL, len - 2, prefix);
if(rc < 0) goto fail;
@@ -621,8 +690,26 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.",
message[2] == 0 ? "any" : format_prefix(prefix, plen),
format_address(from), ifp->name);
+ if(message[2] == 1) {
+ v4tov6(src_prefix, zeroes);
+ src_plen = 96;
+ } else {
+ memcpy(src_prefix, zeroes, 16);
+ src_plen = 0;
+ }
+ rc = parse_request_subtlv(message[2], message + 4 + rc,
+ len - 2 - rc, src_prefix, &src_plen);
+ if(rc < 0)
+ goto done;
+ is_ss = !is_default(src_prefix, src_plen);
if(message[2] == 0) {
struct babel_interface *neigh_ifp =babel_get_if_nfo(neigh->ifp);
+ if(is_ss) {
+ /* Wildcard requests don't carry a source prefix. */
+ flog_err(EC_BABEL_PACKET,
+ "Received source-specific wildcard request.");
+ goto done;
+ }
/* If a neighbour is requesting a full route dump from us,
we might as well send it an IHU. */
send_ihu(neigh, NULL);
diff --git a/babeld/message.h b/babeld/message.h
index 0797a5a77d..7cf062a888 100644
--- a/babeld/message.h
+++ b/babeld/message.h
@@ -34,6 +34,7 @@ Copyright (c) 2007, 2008 by Juliusz Chroboczek
#define SUBTLV_PADN 1
#define SUBTLV_DIVERSITY 2 /* Also known as babelz. */
#define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */
+#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */
#define SUBTLV_MANDATORY 0x80
extern unsigned short myseqno;
diff --git a/babeld/util.h b/babeld/util.h
index 8535d4dd6a..ddc6a70d43 100644
--- a/babeld/util.h
+++ b/babeld/util.h
@@ -104,6 +104,12 @@ void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src);
int daemonise(void);
extern const unsigned char v4prefix[16];
+static inline bool
+is_default(const unsigned char *prefix, int plen)
+{
+ return plen == 0 || (plen == 96 && v4mapped(prefix));
+}
+
/* If debugging is disabled, we want to avoid calling format_address
for every omitted debugging message. So debug is a macro. But
vararg macros are not portable. */
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 326d7f2efb..66426ab32f 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -185,16 +185,23 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
offset++;
}
/* Prefix length check. */
- if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8)
+ if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8) {
*error = -1;
+ return offset;
+ }
/* When packet overflow occur return immediately. */
- if (psize + offset > max_len)
+ if (psize + offset > max_len) {
*error = -1;
+ return offset;
+ }
/* Defensive coding, double-check
* the psize fits in a struct prefix
*/
- if (psize > (ssize_t)sizeof(prefix_local.u))
+ if (psize > (ssize_t)sizeof(prefix_local.u)) {
*error = -1;
+ return offset;
+ }
+
memcpy(&prefix_local.u.prefix, &nlri_ptr[offset], psize);
offset += psize;
switch (type) {
@@ -352,8 +359,10 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
*error = 0;
do {
- if (loop > BGP_PBR_MATCH_VAL_MAX)
+ if (loop > BGP_PBR_MATCH_VAL_MAX) {
*error = -2;
+ return offset;
+ }
hex2bin(&nlri_ptr[offset], op);
/* if first element, AND bit can not be set */
if (op[1] == 1 && loop == 0)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 05ad4d97e5..ccf198c392 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9292,9 +9292,24 @@ DEFPY (af_sid_vpn_export,
return CMD_WARNING_CONFIG_FAILED;
if (!yes) {
- /* implement me */
- vty_out(vty, "It's not implemented\n");
- return CMD_WARNING_CONFIG_FAILED;
+ /* when SID is not set, do nothing */
+ if ((bgp->vpn_policy[afi].tovpn_sid_index == 0) &&
+ !CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO))
+ return CMD_SUCCESS;
+
+ /* pre-change */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+ bgp->vpn_policy[afi].tovpn_sid_index = 0;
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO);
+
+ /* post-change */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
}
if (bgp->tovpn_sid_index != 0 ||
@@ -9333,7 +9348,7 @@ DEFPY (af_sid_vpn_export,
zlog_debug("%s: auto sid alloc.", __func__);
SET_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_SID_AUTO);
- } else {
+ } else if (sid_idx != 0) {
/* SID allocation index-mode */
if (debug)
zlog_debug("%s: idx %ld sid alloc.", __func__, sid_idx);
diff --git a/configure.ac b/configure.ac
index 79288c67e9..b9af768641 100644
--- a/configure.ac
+++ b/configure.ac
@@ -691,6 +691,8 @@ AC_ARG_ENABLE([ospfapi],
AC_ARG_ENABLE([ospfclient],
AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI,
(this is the default if --disable-ospfapi is set)]))
+AC_ARG_WITH([log_timestamp_precision],
+ AS_HELP_STRING([--with-log-timestamp-precision=ARG], [set startup log timestamp precision, ARG must be 0-12]))
AC_ARG_ENABLE([multipath],
AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit]))
AC_ARG_WITH([service_timeout],
@@ -962,8 +964,19 @@ esac
AC_DEFINE_UNQUOTED([MULTIPATH_NUM], [$MPATH_NUM], [Maximum number of paths for a route])
-AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use])
+case "${with_log_timestamp_precision}" in
+[[0-9]|1[012]])
+;;
+"")
+;;
+*)
+AC_MSG_FAILURE([Please specify a number from 0-12 for log precision ARG])
+;;
+esac
+with_log_timestamp_precision=${with_log_timestamp_precision:-0}
+AC_DEFINE_UNQUOTED([LOG_TIMESTAMP_PRECISION], [${with_log_timestamp_precision}], [Startup zlog timestamp precision])
+AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use])
TIMEOUT_MIN=2
case "${with_service_timeout}" in
diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst
index 6614a568f8..737eb57c85 100644
--- a/doc/user/mgmtd.rst
+++ b/doc/user/mgmtd.rst
@@ -364,3 +364,46 @@ MGMT Show commands
.. clicmd:: show mgmt commit-history
This command dumps details of upto last 10 commits handled by MGMTd.
+
+
+MGMT Daemon debug commands
+==========================
+
+The following debug commands enable debugging within the management daemon:
+
+.. clicmd:: [no] debug mgmt backend
+
+ Enable[/Disable] debugging messages related to backend operations within the
+ management daemon.
+
+.. clicmd:: [no] debug mgmt datastore
+
+ Enable[/Disable] debugging messages related to YANG datastore operations
+ within the management daemon.
+
+.. clicmd:: [no] debug mgmt frontend
+
+ Enable[/Disable] debugging messages related to frontend operations within the
+ management daemon.
+
+.. clicmd:: [no] debug mgmt transaction
+
+ Enable[/Disable] debugging messages related to transactions within the
+ management daemon.
+
+
+MGMT Client debug commands
+==========================
+
+The following debug commands enable debugging within the management front and
+backend clients:
+
+.. clicmd:: [no] debug mgmt client backend
+
+ Enable[/Disable] debugging messages related to backend operations inside the
+ backend mgmtd clients.
+
+.. clicmd:: [no] debug mgmt client frontend
+
+ Enable[/Disable] debugging messages related to frontend operations inside the
+ frontend mgmtd clients.
diff --git a/isisd/isis_flex_algo.c b/isisd/isis_flex_algo.c
index 0efc519eab..ef30987b8e 100644
--- a/isisd/isis_flex_algo.c
+++ b/isisd/isis_flex_algo.c
@@ -45,7 +45,7 @@ void *isis_flex_algo_data_alloc(void *voidarg)
struct isis_flex_algo_alloc_arg *arg = voidarg;
struct isis_flex_algo_data *data;
- data = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*data));
+ data = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct isis_flex_algo_data));
for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) {
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
@@ -70,6 +70,7 @@ void isis_flex_algo_data_free(void *voiddata)
if (data->spftree[tree][level - 1])
isis_spftree_del(
data->spftree[tree][level - 1]);
+ XFREE(MTYPE_FLEX_ALGO, data);
}
static struct isis_router_cap_fad *
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index c07083a06d..950d5f359c 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -1191,8 +1191,11 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
rcap_fad = NULL;
if (!isis_flex_algo_elected_supported_local_fad(
- fa->algorithm, area, &rcap_fad))
+ fa->algorithm, area, &rcap_fad)) {
+ fa->state = false;
continue;
+ }
+ fa->state = true;
lsp_debug("ISIS (%s): SR Algorithm %u",
area->area_tag, fa->algorithm);
rcap->algo[fa->algorithm] = fa->algorithm;
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 466e96b3a2..de467c8262 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -393,14 +393,14 @@ static void _isis_spftree_del(struct isis_spftree *spftree)
isis_vertex_queue_free(&spftree->paths);
isis_route_table_info_free(spftree->route_table->info);
isis_route_table_info_free(spftree->route_table_backup->info);
+ route_table_finish(spftree->route_table);
+ route_table_finish(spftree->route_table_backup);
}
void isis_spftree_del(struct isis_spftree *spftree)
{
_isis_spftree_del(spftree);
- route_table_finish(spftree->route_table);
- route_table_finish(spftree->route_table_backup);
spftree->route_table = NULL;
XFREE(MTYPE_ISIS_SPFTREE, spftree);
@@ -1886,8 +1886,8 @@ void isis_run_spf(struct isis_spftree *spftree)
* Flexible-Algorithm.
*/
if (flex_algo_id_valid(spftree->algorithm) &&
- !isis_flex_algo_elected_supported(spftree->algorithm,
- spftree->area)) {
+ !flex_algo_get_state(spftree->area->flex_algos,
+ spftree->algorithm)) {
if (!CHECK_FLAG(spftree->flags, F_SPFTREE_DISABLED)) {
isis_spftree_clear(spftree);
SET_FLAG(spftree->flags, F_SPFTREE_DISABLED);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 4b01a18ecd..ea304ba5ef 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -520,6 +520,10 @@ void isis_area_destroy(struct isis_area *area)
isis_area_invalidate_routes(area, area->is_type);
isis_area_verify_routes(area);
+#ifndef FABRICD
+ flex_algos_free(area->flex_algos);
+#endif /* ifndef FABRICD */
+
isis_sr_area_term(area);
isis_mpls_te_term(area);
diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c
index dcaf1cc10b..3c5a5d9991 100644
--- a/ldpd/labelmapping.c
+++ b/ldpd/labelmapping.c
@@ -47,12 +47,11 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
while ((me = TAILQ_FIRST(mh)) != NULL) {
/* generate pdu */
if (first) {
- if ((buf = ibuf_open(nbr->max_pdu_len +
- LDP_HDR_DEAD_LEN)) == NULL)
+ if ((buf = ibuf_open(nbr->max_pdu_len + LDP_HDR_DEAD_LEN)) == NULL)
fatal(__func__);
/* real size will be set up later */
- err |= gen_ldp_hdr(buf, 0);
+ SET_FLAG(err, gen_ldp_hdr(buf, 0));
size = LDP_HDR_SIZE;
first = 0;
@@ -63,9 +62,9 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
msg_size += len_fec_tlv(&me->map);
if (me->map.label != NO_LABEL)
msg_size += LABEL_TLV_SIZE;
- if (me->map.flags & F_MAP_REQ_ID)
+ if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID))
msg_size += REQID_TLV_SIZE;
- if (me->map.flags & F_MAP_STATUS)
+ if (CHECK_FLAG(me->map.flags, F_MAP_STATUS))
msg_size += STATUS_SIZE;
/* maximum pdu length exceeded, we need a new ldp pdu */
@@ -78,17 +77,17 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
size += msg_size;
/* append message and tlvs */
- err |= gen_msg_hdr(buf, type, msg_size);
- err |= gen_fec_tlv(buf, &me->map);
+ SET_FLAG(err, gen_msg_hdr(buf, type, msg_size));
+ SET_FLAG(err, gen_fec_tlv(buf, &me->map));
if (me->map.label != NO_LABEL)
- err |= gen_label_tlv(buf, me->map.label);
- if (me->map.flags & F_MAP_REQ_ID)
- err |= gen_reqid_tlv(buf, me->map.requestid);
- if (me->map.flags & F_MAP_PW_STATUS)
- err |= gen_pw_status_tlv(buf, me->map.pw_status);
- if (me->map.flags & F_MAP_STATUS)
- err |= gen_status_tlv(buf, me->map.st.status_code,
- me->map.st.msg_id, me->map.st.msg_type);
+ SET_FLAG(err, gen_label_tlv(buf, me->map.label));
+ if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID))
+ SET_FLAG(err, gen_reqid_tlv(buf, me->map.requestid));
+ if (CHECK_FLAG(me->map.flags, F_MAP_PW_STATUS))
+ SET_FLAG(err, gen_pw_status_tlv(buf, me->map.pw_status));
+ if (CHECK_FLAG(me->map.flags, F_MAP_STATUS))
+ SET_FLAG(err, gen_status_tlv(buf, me->map.st.status_code,
+ me->map.st.msg_id, me->map.st.msg_type));
if (err) {
ibuf_free(buf);
mapping_list_clr(mh);
@@ -172,15 +171,13 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
memset(&map, 0, sizeof(map));
map.msg_id = msg.id;
- if ((tlen = tlv_decode_fec_elm(nbr, &msg, buf, feclen,
- &map)) == -1)
+ if ((tlen = tlv_decode_fec_elm(nbr, &msg, buf, feclen, &map)) == -1)
goto err;
if (map.type == MAP_TYPE_PWID &&
- !(map.flags & F_MAP_PW_ID) &&
+ !CHECK_FLAG(map.flags, F_MAP_PW_ID) &&
type != MSG_TYPE_LABELWITHDRAW &&
type != MSG_TYPE_LABELRELEASE) {
- send_notification(nbr->tcp, S_MISS_MSG, msg.id,
- msg.type);
+ send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type);
goto err;
}
@@ -193,8 +190,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
case MSG_TYPE_LABELMAPPING:
case MSG_TYPE_LABELREQUEST:
case MSG_TYPE_LABELABORTREQ:
- session_shutdown(nbr, S_UNKNOWN_FEC, msg.id,
- msg.type);
+ session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, msg.type);
goto err;
default:
break;
@@ -211,8 +207,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
switch (type) {
case MSG_TYPE_LABELMAPPING:
case MSG_TYPE_LABELABORTREQ:
- session_shutdown(nbr, S_UNKNOWN_FEC, msg.id,
- msg.type);
+ session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, msg.type);
goto err;
default:
break;
@@ -223,8 +218,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
* LDP supports the use of multiple FEC Elements per
* FEC for the Label Mapping message only.
*/
- if (type != MSG_TYPE_LABELMAPPING &&
- tlen != feclen) {
+ if (type != MSG_TYPE_LABELMAPPING && tlen != feclen) {
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
}
@@ -262,10 +256,10 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
* For Label Mapping messages the Label TLV is mandatory and
* should appear right after the FEC TLV.
*/
- if (current_tlv == 1 && type == MSG_TYPE_LABELMAPPING &&
- !(tlv_type & TLV_TYPE_GENERICLABEL)) {
- send_notification(nbr->tcp, S_MISS_MSG, msg.id,
- msg.type);
+ if (current_tlv == 1 &&
+ type == MSG_TYPE_LABELMAPPING &&
+ !CHECK_FLAG(tlv_type, TLV_TYPE_GENERICLABEL)) {
+ send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type);
goto err;
}
@@ -275,12 +269,11 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
case MSG_TYPE_LABELMAPPING:
case MSG_TYPE_LABELREQUEST:
if (tlv_len != REQID_TLV_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
goto err;
}
- flags |= F_MAP_REQ_ID;
+ SET_FLAG(flags, F_MAP_REQ_ID);
memcpy(&reqbuf, buf, sizeof(reqbuf));
reqid = ntohl(reqbuf);
break;
@@ -299,8 +292,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
case MSG_TYPE_LABELWITHDRAW:
case MSG_TYPE_LABELRELEASE:
if (tlv_len != LABEL_TLV_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
goto err;
}
@@ -312,8 +304,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
label != MPLS_LABEL_IPV4_EXPLICIT_NULL &&
label != MPLS_LABEL_IPV6_EXPLICIT_NULL &&
label != MPLS_LABEL_IMPLICIT_NULL)) {
- session_shutdown(nbr, S_BAD_TLV_VAL,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
}
break;
@@ -329,8 +320,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
case MSG_TYPE_LABELWITHDRAW:
case MSG_TYPE_LABELRELEASE:
/* unsupported */
- session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
- msg.type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
break;
default:
@@ -340,8 +330,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
break;
case TLV_TYPE_STATUS:
if (tlv_len != STATUS_TLV_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
- msg.type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
goto err;
}
/* ignore */
@@ -350,12 +339,11 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
switch (type) {
case MSG_TYPE_LABELMAPPING:
if (tlv_len != PW_STATUS_TLV_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
goto err;
}
- flags |= F_MAP_PW_STATUS;
+ SET_FLAG(flags, F_MAP_PW_STATUS);
memcpy(&statusbuf, buf, sizeof(statusbuf));
pw_status = ntohl(statusbuf);
break;
@@ -365,7 +353,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
}
break;
default:
- if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
+ if (!CHECK_FLAG(ntohs(tlv.type), UNKNOWN_FLAG))
send_notification_rtlvs(nbr, S_UNKNOWN_TLV,
msg.id, msg.type, tlv_type, tlv_len, buf);
/* ignore unknown tlv */
@@ -380,14 +368,13 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
while ((me = TAILQ_FIRST(&mh)) != NULL) {
int imsg_type = IMSG_NONE;
- me->map.flags |= flags;
+ SET_FLAG(me->map.flags, flags);
switch (me->map.type) {
case MAP_TYPE_PREFIX:
switch (me->map.fec.prefix.af) {
case AF_INET:
if (label == MPLS_LABEL_IPV6_EXPLICIT_NULL) {
- session_shutdown(nbr, S_BAD_TLV_VAL,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
}
if (!nbr->v4_enabled)
@@ -395,8 +382,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
break;
case AF_INET6:
if (label == MPLS_LABEL_IPV4_EXPLICIT_NULL) {
- session_shutdown(nbr, S_BAD_TLV_VAL,
- msg.id, msg.type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
}
if (!nbr->v6_enabled)
@@ -408,18 +394,17 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
break;
case MAP_TYPE_PWID:
if (label <= MPLS_LABEL_RESERVED_MAX) {
- session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
- msg.type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
goto err;
}
- if (me->map.flags & F_MAP_PW_STATUS)
+ if (CHECK_FLAG(me->map.flags, F_MAP_PW_STATUS))
me->map.pw_status = pw_status;
break;
default:
break;
}
me->map.label = label;
- if (me->map.flags & F_MAP_REQ_ID)
+ if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID))
me->map.requestid = reqid;
log_msg_mapping(0, type, nbr, &me->map);
@@ -513,11 +498,11 @@ len_fec_tlv(struct map *map)
break;
case MAP_TYPE_PWID:
len += FEC_PWID_ELM_MIN_LEN;
- if (map->flags & F_MAP_PW_ID)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_ID))
len += PW_STATUS_TLV_LEN;
- if (map->flags & F_MAP_PW_IFMTU)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU))
len += FEC_SUBTLV_IFMTU_SIZE;
- if (map->flags & F_MAP_PW_STATUS)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_STATUS))
len += PW_STATUS_TLV_SIZE;
break;
case MAP_TYPE_TYPED_WCARD:
@@ -552,15 +537,15 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
switch (map->type) {
case MAP_TYPE_WILDCARD:
ft.length = htons(sizeof(uint8_t));
- err |= ibuf_add(buf, &ft, sizeof(ft));
- err |= ibuf_add(buf, &map->type, sizeof(map->type));
+ SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft)));
+ SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(map->type)));
break;
case MAP_TYPE_PREFIX:
len = PREFIX_SIZE(map->fec.prefix.prefixlen);
ft.length = htons(sizeof(map->type) + sizeof(family) +
sizeof(map->fec.prefix.prefixlen) + len);
- err |= ibuf_add(buf, &ft, sizeof(ft));
- err |= ibuf_add(buf, &map->type, sizeof(map->type));
+ SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft)));
+ SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(map->type)));
switch (map->fec.prefix.af) {
case AF_INET:
family = htons(AF_IPV4);
@@ -572,45 +557,45 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
fatalx("gen_fec_tlv: unknown af");
break;
}
- err |= ibuf_add(buf, &family, sizeof(family));
- err |= ibuf_add(buf, &map->fec.prefix.prefixlen,
- sizeof(map->fec.prefix.prefixlen));
+ SET_FLAG(err, ibuf_add(buf, &family, sizeof(family)));
+ SET_FLAG(err, ibuf_add(buf, &map->fec.prefix.prefixlen,
+ sizeof(map->fec.prefix.prefixlen)));
if (len)
- err |= ibuf_add(buf, &map->fec.prefix.prefix, len);
+ SET_FLAG(err, ibuf_add(buf, &map->fec.prefix.prefix, len));
break;
case MAP_TYPE_PWID:
- if (map->flags & F_MAP_PW_ID)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_ID))
pw_len += FEC_PWID_SIZE;
- if (map->flags & F_MAP_PW_IFMTU)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU))
pw_len += FEC_SUBTLV_IFMTU_SIZE;
len = FEC_PWID_ELM_MIN_LEN + pw_len;
ft.length = htons(len);
- err |= ibuf_add(buf, &ft, sizeof(ft));
+ SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft)));
- err |= ibuf_add(buf, &map->type, sizeof(uint8_t));
+ SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(uint8_t)));
pw_type = map->fec.pwid.type;
- if (map->flags & F_MAP_PW_CWORD)
- pw_type |= CONTROL_WORD_FLAG;
+ if (CHECK_FLAG(map->flags, F_MAP_PW_CWORD))
+ SET_FLAG(pw_type, CONTROL_WORD_FLAG);
pw_type = htons(pw_type);
- err |= ibuf_add(buf, &pw_type, sizeof(uint16_t));
- err |= ibuf_add(buf, &pw_len, sizeof(uint8_t));
+ SET_FLAG(err, ibuf_add(buf, &pw_type, sizeof(uint16_t)));
+ SET_FLAG(err, ibuf_add(buf, &pw_len, sizeof(uint8_t)));
group_id = htonl(map->fec.pwid.group_id);
- err |= ibuf_add(buf, &group_id, sizeof(uint32_t));
- if (map->flags & F_MAP_PW_ID) {
+ SET_FLAG(err, ibuf_add(buf, &group_id, sizeof(uint32_t)));
+ if (CHECK_FLAG(map->flags, F_MAP_PW_ID)) {
pwid = htonl(map->fec.pwid.pwid);
- err |= ibuf_add(buf, &pwid, sizeof(uint32_t));
+ SET_FLAG(err, ibuf_add(buf, &pwid, sizeof(uint32_t)));
}
- if (map->flags & F_MAP_PW_IFMTU) {
+ if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) {
struct subtlv stlv;
stlv.type = SUBTLV_IFMTU;
stlv.length = FEC_SUBTLV_IFMTU_SIZE;
- err |= ibuf_add(buf, &stlv, sizeof(uint16_t));
+ SET_FLAG(err, ibuf_add(buf, &stlv, sizeof(uint16_t)));
ifmtu = htons(map->fec.pwid.ifmtu);
- err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t));
+ SET_FLAG(err, ibuf_add(buf, &ifmtu, sizeof(uint16_t)));
}
break;
case MAP_TYPE_TYPED_WCARD:
@@ -624,14 +609,14 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
fatalx("gen_fec_tlv: unexpected fec type");
}
ft.length = htons(len);
- err |= ibuf_add(buf, &ft, sizeof(ft));
- err |= ibuf_add(buf, &map->type, sizeof(uint8_t));
- err |= ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t));
+ SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft)));
+ SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(uint8_t)));
+ SET_FLAG(err, ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t)));
switch (map->fec.twcard.type) {
case MAP_TYPE_PREFIX:
twcard_len = sizeof(uint16_t);
- err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
+ SET_FLAG(err, ibuf_add(buf, &twcard_len, sizeof(uint8_t)));
switch (map->fec.twcard.u.prefix_af) {
case AF_INET:
@@ -645,13 +630,13 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
break;
}
- err |= ibuf_add(buf, &family, sizeof(uint16_t));
+ SET_FLAG(err, ibuf_add(buf, &family, sizeof(uint16_t)));
break;
case MAP_TYPE_PWID:
twcard_len = sizeof(uint16_t);
- err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
+ SET_FLAG(err, ibuf_add(buf, &twcard_len, sizeof(uint8_t)));
pw_type = htons(map->fec.twcard.u.pw_type);
- err |= ibuf_add(buf, &pw_type, sizeof(uint16_t));
+ SET_FLAG(err, ibuf_add(buf, &pw_type, sizeof(uint16_t)));
break;
default:
fatalx("gen_fec_tlv: unexpected fec type");
@@ -679,21 +664,18 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
if (len == FEC_ELM_WCARD_LEN)
return (off);
else {
- session_shutdown(nbr, S_BAD_TLV_VAL, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type);
return (-1);
}
break;
case MAP_TYPE_PREFIX:
if (len < FEC_ELM_PREFIX_MIN_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
/* Address Family */
- memcpy(&map->fec.prefix.af, buf + off,
- sizeof(map->fec.prefix.af));
+ memcpy(&map->fec.prefix.af, buf + off, sizeof(map->fec.prefix.af));
off += sizeof(map->fec.prefix.af);
map->fec.prefix.af = ntohs(map->fec.prefix.af);
switch (map->fec.prefix.af) {
@@ -704,8 +686,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
map->fec.prefix.af = AF_INET6;
break;
default:
- send_notification(nbr->tcp, S_UNSUP_ADDR, msg->id,
- msg->type);
+ send_notification(nbr->tcp, S_UNSUP_ADDR, msg->id, msg->type);
return (-1);
}
@@ -716,19 +697,16 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
&& map->fec.prefix.prefixlen > IPV4_MAX_BITLEN)
|| (map->fec.prefix.af == AF_IPV6
&& map->fec.prefix.prefixlen > IPV6_MAX_BITLEN)) {
- session_shutdown(nbr, S_BAD_TLV_VAL, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type);
return (-1);
}
if (len < off + PREFIX_SIZE(map->fec.prefix.prefixlen)) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
/* Prefix */
- memset(&map->fec.prefix.prefix, 0,
- sizeof(map->fec.prefix.prefix));
+ memset(&map->fec.prefix.prefix, 0, sizeof(map->fec.prefix.prefix));
memcpy(&map->fec.prefix.prefix, buf + off,
PREFIX_SIZE(map->fec.prefix.prefixlen));
@@ -739,17 +717,16 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
return (off + PREFIX_SIZE(map->fec.prefix.prefixlen));
case MAP_TYPE_PWID:
if (len < FEC_PWID_ELM_MIN_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
/* PW type */
memcpy(&map->fec.pwid.type, buf + off, sizeof(uint16_t));
map->fec.pwid.type = ntohs(map->fec.pwid.type);
- if (map->fec.pwid.type & CONTROL_WORD_FLAG) {
- map->flags |= F_MAP_PW_CWORD;
- map->fec.pwid.type &= ~CONTROL_WORD_FLAG;
+ if (CHECK_FLAG(map->fec.pwid.type, CONTROL_WORD_FLAG)) {
+ SET_FLAG(map->flags, F_MAP_PW_CWORD);
+ UNSET_FLAG(map->fec.pwid.type, CONTROL_WORD_FLAG);
}
off += sizeof(uint16_t);
@@ -758,8 +735,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
off += sizeof(uint8_t);
if (len != FEC_PWID_ELM_MIN_LEN + pw_len) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
@@ -773,14 +749,13 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
return (off);
if (pw_len < sizeof(uint32_t)) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
memcpy(&map->fec.pwid.pwid, buf + off, sizeof(uint32_t));
map->fec.pwid.pwid = ntohl(map->fec.pwid.pwid);
- map->flags |= F_MAP_PW_ID;
+ SET_FLAG(map->flags, F_MAP_PW_ID);
off += sizeof(uint32_t);
pw_len -= sizeof(uint32_t);
@@ -789,29 +764,26 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
struct subtlv stlv;
if (pw_len < sizeof(stlv)) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
memcpy(&stlv, buf + off, sizeof(stlv));
if (stlv.length > pw_len) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
switch (stlv.type) {
case SUBTLV_IFMTU:
if (stlv.length != FEC_SUBTLV_IFMTU_SIZE) {
- session_shutdown(nbr, S_BAD_TLV_LEN,
- msg->id, msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
memcpy(&map->fec.pwid.ifmtu, buf + off +
SUBTLV_HDR_SIZE, sizeof(uint16_t));
map->fec.pwid.ifmtu = ntohs(map->fec.pwid.ifmtu);
- map->flags |= F_MAP_PW_IFMTU;
+ SET_FLAG(map->flags, F_MAP_PW_IFMTU);
break;
default:
/* ignore */
@@ -824,8 +796,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
return (off);
case MAP_TYPE_TYPED_WCARD:
if (len < FEC_ELM_TWCARD_MIN_LEN) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
@@ -834,23 +805,19 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
memcpy(&twcard_len, buf + off, sizeof(uint8_t));
off += sizeof(uint8_t);
if (len != FEC_ELM_TWCARD_MIN_LEN + twcard_len) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
switch (map->fec.twcard.type) {
case MAP_TYPE_PREFIX:
if (twcard_len != sizeof(uint16_t)) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
- memcpy(&map->fec.twcard.u.prefix_af, buf + off,
- sizeof(uint16_t));
- map->fec.twcard.u.prefix_af =
- ntohs(map->fec.twcard.u.prefix_af);
+ memcpy(&map->fec.twcard.u.prefix_af, buf + off, sizeof(uint16_t));
+ map->fec.twcard.u.prefix_af = ntohs(map->fec.twcard.u.prefix_af);
off += sizeof(uint16_t);
switch (map->fec.twcard.u.prefix_af) {
@@ -861,29 +828,24 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
map->fec.twcard.u.prefix_af = AF_INET6;
break;
default:
- session_shutdown(nbr, S_BAD_TLV_VAL, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type);
return (-1);
}
break;
case MAP_TYPE_PWID:
if (twcard_len != sizeof(uint16_t)) {
- session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
- msg->type);
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type);
return (-1);
}
- memcpy(&map->fec.twcard.u.pw_type, buf + off,
- sizeof(uint16_t));
- map->fec.twcard.u.pw_type =
- ntohs(map->fec.twcard.u.pw_type);
+ memcpy(&map->fec.twcard.u.pw_type, buf + off, sizeof(uint16_t));
+ map->fec.twcard.u.pw_type = ntohs(map->fec.twcard.u.pw_type);
/* ignore the reserved bit as per RFC 6667 */
map->fec.twcard.u.pw_type &= ~PW_TWCARD_RESERVED_BIT;
off += sizeof(uint16_t);
break;
default:
- send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id,
- msg->type);
+ send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, msg->type);
return (-1);
}
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index 470580ff5e..cb6b8986b8 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -47,11 +47,9 @@ fec_compare(const struct fec *a, const struct fec *b)
switch (a->type) {
case FEC_TYPE_IPV4:
- if (ntohl(a->u.ipv4.prefix.s_addr) <
- ntohl(b->u.ipv4.prefix.s_addr))
+ if (ntohl(a->u.ipv4.prefix.s_addr) < ntohl(b->u.ipv4.prefix.s_addr))
return (-1);
- if (ntohl(a->u.ipv4.prefix.s_addr) >
- ntohl(b->u.ipv4.prefix.s_addr))
+ if (ntohl(a->u.ipv4.prefix.s_addr) > ntohl(b->u.ipv4.prefix.s_addr))
return (1);
if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen)
return (-1);
@@ -79,11 +77,9 @@ fec_compare(const struct fec *a, const struct fec *b)
return (-1);
if (a->u.pwid.pwid > b->u.pwid.pwid)
return (1);
- if (ntohl(a->u.pwid.lsr_id.s_addr) <
- ntohl(b->u.pwid.lsr_id.s_addr))
+ if (ntohl(a->u.pwid.lsr_id.s_addr) < ntohl(b->u.pwid.lsr_id.s_addr))
return (-1);
- if (ntohl(a->u.pwid.lsr_id.s_addr) >
- ntohl(b->u.pwid.lsr_id.s_addr))
+ if (ntohl(a->u.pwid.lsr_id.s_addr) > ntohl(b->u.pwid.lsr_id.s_addr))
return (1);
return (0);
}
@@ -261,8 +257,7 @@ fec_add(struct fec *fec)
fn->pw_remote_status = PW_FORWARDING;
if (fec_insert(&ft, &fn->fec))
- log_warnx("failed to add %s to ft tree",
- log_fec(&fn->fec));
+ log_warnx("failed to add %s to ft tree", log_fec(&fn->fec));
return (fn);
}
@@ -338,14 +333,14 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
* installing in kernel and sending to peer
*/
iface = if_lookup(ldeconf, ifindex);
- if ((ldeconf->flags & F_LDPD_ORDERED_CONTROL) &&
+ if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL) &&
!connected && iface != NULL && fec->type != FEC_TYPE_PWID)
- fnh->flags |= F_FEC_NH_DEFER;
+ SET_FLAG(fnh->flags, F_FEC_NH_DEFER);
}
- fnh->flags |= F_FEC_NH_NEW;
+ SET_FLAG(fnh->flags, F_FEC_NH_NEW);
if (connected)
- fnh->flags |= F_FEC_NH_CONNECTED;
+ SET_FLAG(fnh->flags, F_FEC_NH_CONNECTED);
}
void
@@ -388,22 +383,22 @@ lde_kernel_update(struct fec *fec)
return;
LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
- if (fnh->flags & F_FEC_NH_NEW) {
- fnh->flags &= ~F_FEC_NH_NEW;
+ if (CHECK_FLAG(fnh->flags, F_FEC_NH_NEW)) {
+ UNSET_FLAG(fnh->flags, F_FEC_NH_NEW);
/*
* if LDP configured on interface or a static route
* clear flag else treat fec as a connected route
*/
- if (ldeconf->flags & F_LDPD_ENABLED) {
+ if (CHECK_FLAG(ldeconf->flags, F_LDPD_ENABLED)) {
iface = if_lookup(ldeconf,fnh->ifindex);
- if (fnh->flags & F_FEC_NH_CONNECTED ||
+ if (CHECK_FLAG(fnh->flags, F_FEC_NH_CONNECTED) ||
iface ||
fnh->route_type == ZEBRA_ROUTE_STATIC)
- fnh->flags &=~F_FEC_NH_NO_LDP;
+ UNSET_FLAG(fnh->flags, F_FEC_NH_NO_LDP);
else
- fnh->flags |= F_FEC_NH_NO_LDP;
+ SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP);
} else
- fnh->flags |= F_FEC_NH_NO_LDP;
+ SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP);
} else {
lde_send_delete_klabel(fn, fnh);
fec_nh_del(fnh);
@@ -510,7 +505,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping)
/* RFC 4447 control word and status tlv negotiation */
if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map)) {
- if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS)
+ if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS))
fn->pw_remote_status = map->pw_status;
return;
@@ -534,8 +529,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping)
* the possibility of multipath.
*/
LIST_FOREACH(fnh, &fn->nexthops, entry) {
- if (lde_address_find(ln, fnh->af,
- &fnh->nexthop) == NULL)
+ if (lde_address_find(ln, fnh->af, &fnh->nexthop) == NULL)
continue;
lde_send_delete_klabel(fn, fnh);
@@ -561,9 +555,9 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping)
* NH so clear flag and send labelmap msg to
* peer
*/
- if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) {
send_map = true;
- fnh->flags &= ~F_FEC_NH_DEFER;
+ UNSET_FLAG(fnh->flags, F_FEC_NH_DEFER);
}
fnh->remote_label = map->label;
if (fn->local_label != NO_LABEL)
@@ -575,9 +569,9 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping)
continue;
pw->remote_group = map->fec.pwid.group_id;
- if (map->flags & F_MAP_PW_IFMTU)
+ if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU))
pw->remote_mtu = map->fec.pwid.ifmtu;
- if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS) {
+ if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) {
pw->remote_status = map->pw_status;
fn->pw_remote_status = map->pw_status;
}
@@ -726,7 +720,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
/* wildcard label release */
if (map->type == MAP_TYPE_WILDCARD ||
map->type == MAP_TYPE_TYPED_WCARD ||
- (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
+ (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) {
lde_check_release_wcard(map, ln);
return;
}
@@ -818,7 +812,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
/* wildcard label withdraw */
if (map->type == MAP_TYPE_WILDCARD ||
map->type == MAP_TYPE_TYPED_WCARD ||
- (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
+ (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) {
lde_check_withdraw_wcard(map, ln);
return;
}
@@ -868,7 +862,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
return;
/* Ordered Control: additional withdraw steps */
- if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) {
/* LWd.8: for each neighbor other that src of withdraw msg */
RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) {
if (ln->peerid == lnbr->peerid)
@@ -929,8 +923,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
default:
break;
}
- if (map->label != NO_LABEL && map->label !=
- fnh->remote_label)
+ if (map->label != NO_LABEL && map->label != fnh->remote_label)
continue;
lde_send_delete_klabel(fn, fnh);
@@ -941,8 +934,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
lde_rlfa_update_clients(f, ln, MPLS_INVALID_LABEL);
/* LWd.3: check previously received label mapping */
- if (me && (map->label == NO_LABEL ||
- map->label == me->map.label))
+ if (me && (map->label == NO_LABEL || map->label == me->map.label))
/*
* LWd.4: remove record of previously received
* label mapping
@@ -953,7 +945,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
continue;
/* Ordered Control: additional withdraw steps */
- if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) {
+ if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) {
/*
* LWd.8: for each neighbor other that src of
* withdraw msg
@@ -965,16 +957,14 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
/* LWd.9: check if previously sent a label
* mapping
*/
- me = (struct lde_map *)fec_find(
- &lnbr->sent_map, &fn->fec);
+ me = (struct lde_map *)fec_find(&lnbr->sent_map, &fn->fec);
/*
* LWd.10: does label sent to peer "map" to
* withdraw label
*/
if (me && lde_nbr_is_nexthop(fn, lnbr))
/* LWd.11: send label withdraw */
- lde_send_labelwithdraw(lnbr, fn, NULL,
- NULL);
+ lde_send_labelwithdraw(lnbr, fn, NULL, NULL);
}
}
}
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index d3193b16d7..e66b9e92dd 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -257,8 +257,7 @@ ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
{
if (iev_lde->ibuf.fd == -1)
return (0);
- return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
- data, datalen));
+ return (imsg_compose_event(iev_lde, type, peerid, pid, -1, data, datalen));
}
/* ARGSUSED */
@@ -309,8 +308,7 @@ static void ldpe_dispatch_main(struct event *thread)
switch (imsg.hdr.type) {
case IMSG_IFSTATUS:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct kif))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kif))
fatalx("IFSTATUS imsg with wrong len");
kif = imsg.data;
@@ -336,15 +334,13 @@ static void ldpe_dispatch_main(struct event *thread)
}
break;
case IMSG_NEWADDR:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct kaddr))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr))
fatalx("NEWADDR imsg with wrong len");
if_addr_add(imsg.data);
break;
case IMSG_DELADDR:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct kaddr))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr))
fatalx("DELADDR imsg with wrong len");
if_addr_del(imsg.data);
@@ -369,8 +365,7 @@ static void ldpe_dispatch_main(struct event *thread)
iev_lde->ev_write = NULL;
break;
case IMSG_INIT:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ldpd_init))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldpd_init))
fatalx("INIT imsg with wrong len");
memcpy(&init, imsg.data, sizeof(init));
@@ -398,14 +393,11 @@ static void ldpe_dispatch_main(struct event *thread)
disc_socket = -1;
edisc_socket = -1;
session_socket = -1;
- if ((ldp_af_conf_get(leconf, af))->flags &
- F_LDPD_AF_ENABLED)
- ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
- af, NULL, 0);
+ if (CHECK_FLAG((ldp_af_conf_get(leconf, af))->flags, F_LDPD_AF_ENABLED))
+ ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, af, NULL, 0);
break;
case IMSG_SOCKET_NET:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(enum socket_type))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(enum socket_type))
fatalx("SOCKET_NET imsg with wrong len");
socket_type = imsg.data;
@@ -434,15 +426,13 @@ static void ldpe_dispatch_main(struct event *thread)
break;
}
- ldpe_setup_sockets(af, disc_socket, edisc_socket,
- session_socket);
+ ldpe_setup_sockets(af, disc_socket, edisc_socket, session_socket);
if_update_all(af);
tnbr_update_all(af);
RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
if (nbr->af != af)
continue;
- nbr->laddr = (ldp_af_conf_get(leconf,
- af))->trans_addr;
+ nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr;
#ifdef __OpenBSD__
nbrp = nbr_params_find(leconf, nbr->id);
if (nbrp) {
@@ -456,8 +446,7 @@ static void ldpe_dispatch_main(struct event *thread)
}
break;
case IMSG_RTRID_UPDATE:
- memcpy(&global.rtr_id, imsg.data,
- sizeof(global.rtr_id));
+ memcpy(&global.rtr_id, imsg.data, sizeof(global.rtr_id));
if (leconf->rtr_id.s_addr == INADDR_ANY) {
ldpe_reset_nbrs(AF_UNSPEC);
}
@@ -465,8 +454,7 @@ static void ldpe_dispatch_main(struct event *thread)
tnbr_update_all(AF_UNSPEC);
break;
case IMSG_RECONF_CONF:
- if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
- NULL)
+ if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL)
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
@@ -546,16 +534,13 @@ static void ldpe_dispatch_main(struct event *thread)
memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
break;
case IMSG_FILTER_UPDATE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ldp_access)) {
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldp_access)) {
log_warnx("%s: wrong imsg len", __func__);
break;
}
laccess = imsg.data;
- ldpe_check_filter_af(AF_INET, &leconf->ipv4,
- laccess->name);
- ldpe_check_filter_af(AF_INET6, &leconf->ipv6,
- laccess->name);
+ ldpe_check_filter_af(AF_INET, &leconf->ipv4, laccess->name);
+ ldpe_check_filter_af(AF_INET6, &leconf->ipv6, laccess->name);
break;
case IMSG_LDP_SYNC_IF_STATE_REQUEST:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -605,8 +590,7 @@ static void ldpe_dispatch_main(struct event *thread)
}
break;
default:
- log_debug("%s: error handling imsg %d",
- __func__, imsg.hdr.type);
+ log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type);
break;
}
imsg_free(&imsg);
@@ -650,8 +634,7 @@ static void ldpe_dispatch_lde(struct event *thread)
case IMSG_RELEASE_ADD:
case IMSG_REQUEST_ADD:
case IMSG_WITHDRAW_ADD:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(struct map))
+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct map))
fatalx("invalid size of map request");
map = imsg.data;
@@ -706,8 +689,7 @@ static void ldpe_dispatch_lde(struct event *thread)
}
break;
case IMSG_NOTIFICATION_SEND:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(struct notify_msg))
+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct notify_msg))
fatalx("invalid size of OE request");
nm = imsg.data;
@@ -741,8 +723,7 @@ static void ldpe_dispatch_lde(struct event *thread)
session_shutdown(nbr,S_SHUTDOWN,0,0);
break;
default:
- log_debug("%s: error handling imsg %d",
- __func__, imsg.hdr.type);
+ log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type);
break;
}
imsg_free(&imsg);
@@ -860,7 +841,7 @@ ldpe_remove_dynamic_tnbrs(int af)
if (tnbr->af != af)
continue;
- tnbr->flags &= ~F_TNBR_DYNAMIC;
+ UNSET_FLAG(tnbr->flags, F_TNBR_DYNAMIC);
tnbr_check(leconf, tnbr);
}
}
diff --git a/lib/command.c b/lib/command.c
index 97ea200ff4..7a7ce3f5dc 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -31,6 +31,8 @@
#include "jhash.h"
#include "hook.h"
#include "lib_errors.h"
+#include "mgmt_be_client.h"
+#include "mgmt_fe_client.h"
#include "northbound_cli.h"
#include "network.h"
#include "routemap.h"
@@ -1301,6 +1303,14 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num)
while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
++(*line_num);
+ if (vty_log_commands) {
+ int len = strlen(vty->buf);
+
+ /* now log the command */
+ zlog_notice("config-from-file# %.*s", len ? len - 1 : 0,
+ vty->buf);
+ }
+
ret = command_config_read_one_line(vty, NULL, *line_num, 0);
if (ret != CMD_SUCCESS && ret != CMD_WARNING
@@ -2438,6 +2448,8 @@ const char *host_config_get(void)
void cmd_show_lib_debugs(struct vty *vty)
{
route_map_show_debug(vty);
+ mgmt_debug_be_client_show_debug(vty);
+ mgmt_debug_fe_client_show_debug(vty);
}
void install_default(enum node_type node)
diff --git a/lib/flex_algo.c b/lib/flex_algo.c
index bafbf8b779..f48117ff1b 100644
--- a/lib/flex_algo.c
+++ b/lib/flex_algo.c
@@ -17,26 +17,42 @@
#include "flex_algo.h"
-DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo Definition");
+DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO_DATABASE, "Flex-Algo database");
+DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo algorithm information");
+
+static void _flex_algo_delete(struct flex_algos *flex_algos,
+ struct flex_algo *fa);
struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator,
flex_algo_releaser_t releaser)
{
struct flex_algos *flex_algos;
- flex_algos = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*flex_algos));
+ flex_algos =
+ XCALLOC(MTYPE_FLEX_ALGO_DATABASE, sizeof(struct flex_algos));
flex_algos->flex_algos = list_new();
flex_algos->allocator = allocator;
flex_algos->releaser = releaser;
return flex_algos;
}
+void flex_algos_free(struct flex_algos *flex_algos)
+{
+ struct listnode *node, *nnode;
+ struct flex_algo *fa;
+
+ for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa))
+ _flex_algo_delete(flex_algos, fa);
+ list_delete(&flex_algos->flex_algos);
+ XFREE(MTYPE_FLEX_ALGO_DATABASE, flex_algos);
+}
+
struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos,
uint8_t algorithm, void *arg)
{
struct flex_algo *fa;
- fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*fa));
+ fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct flex_algo));
fa->algorithm = algorithm;
if (flex_algos->allocator)
fa->data = flex_algos->allocator(arg);
@@ -47,6 +63,31 @@ struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos,
return fa;
}
+static void _flex_algo_delete(struct flex_algos *flex_algos,
+ struct flex_algo *fa)
+{
+ if (flex_algos->releaser)
+ flex_algos->releaser(fa->data);
+ admin_group_term(&fa->admin_group_exclude_any);
+ admin_group_term(&fa->admin_group_include_any);
+ admin_group_term(&fa->admin_group_include_all);
+ listnode_delete(flex_algos->flex_algos, fa);
+ XFREE(MTYPE_FLEX_ALGO, fa);
+}
+
+
+void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm)
+{
+ struct listnode *node, *nnode;
+ struct flex_algo *fa;
+
+ for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) {
+ if (fa->algorithm != algorithm)
+ continue;
+ _flex_algo_delete(flex_algos, fa);
+ }
+}
+
/**
* @brief Look up the local flex-algo object by its algorithm number.
* @param algorithm flex-algo algorithm number
@@ -79,6 +120,12 @@ bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2)
return false;
if (fa1->metric_type != fa2->metric_type)
return false;
+ if (fa1->exclude_srlg != fa2->exclude_srlg)
+ return false;
+ if (fa1->flags != fa2->flags)
+ return false;
+ if (fa1->unsupported_subtlv != fa2->unsupported_subtlv)
+ return false;
if (!admin_group_cmp(&fa1->admin_group_exclude_any,
&fa2->admin_group_exclude_any))
@@ -93,25 +140,6 @@ bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2)
return true;
}
-void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm)
-{
- struct listnode *node, *nnode;
- struct flex_algo *fa;
-
- for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) {
- if (fa->algorithm != algorithm)
- continue;
- if (flex_algos->releaser)
- flex_algos->releaser(fa->data);
- admin_group_term(&fa->admin_group_exclude_any);
- admin_group_term(&fa->admin_group_include_any);
- admin_group_term(&fa->admin_group_include_all);
- listnode_delete(flex_algos->flex_algos, fa);
- XFREE(MTYPE_FLEX_ALGO, fa);
- return;
- }
-}
-
/**
* Check SR Algorithm is Flex-Algo
* according to RFC9350 section 4
@@ -140,3 +168,24 @@ char *flex_algo_metric_type_print(char *type_str, size_t sz,
}
return type_str;
}
+
+bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm)
+{
+ struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm);
+
+ if (!fa)
+ return false;
+
+ return fa->state;
+}
+
+void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm,
+ bool state)
+{
+ struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm);
+
+ if (!fa)
+ return;
+
+ fa->state = state;
+}
diff --git a/lib/flex_algo.h b/lib/flex_algo.h
index e012f46862..e617e7cae8 100644
--- a/lib/flex_algo.h
+++ b/lib/flex_algo.h
@@ -83,6 +83,11 @@ struct flex_algo {
#define FLEX_ALGO_IP 0x04
uint8_t dataplanes;
+ /* True if the Algorithm is locally enabled (ie. a definition has been
+ * found and is supported).
+ */
+ bool state;
+
/*
* This property can be freely extended among different routing
* protocols. Since Flex-Algo is an IGP protocol agnostic, both IS-IS
@@ -107,6 +112,7 @@ struct flex_algos {
*/
struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator,
flex_algo_releaser_t releaser);
+void flex_algos_free(struct flex_algos *flex_algos);
struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos,
uint8_t algorithm, void *arg);
struct flex_algo *flex_algo_lookup(struct flex_algos *flex_algos,
@@ -118,4 +124,8 @@ bool flex_algo_id_valid(uint16_t algorithm);
char *flex_algo_metric_type_print(char *type_str, size_t sz,
enum flex_algo_metric_type metric_type);
+bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm);
+
+void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm,
+ bool state);
#endif /* _FRR_FLEX_ALGO_H */
diff --git a/lib/link_state.c b/lib/link_state.c
index 752030cd47..58727a568b 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -497,7 +497,6 @@ void ls_vertex_del(struct ls_ted *ted, struct ls_vertex *vertex)
/* Then remove Vertex from Link State Data Base and free memory */
vertices_del(&ted->vertices, vertex);
XFREE(MTYPE_LS_DB, vertex);
- vertex = NULL;
}
void ls_vertex_del_all(struct ls_ted *ted, struct ls_vertex *vertex)
@@ -956,7 +955,10 @@ struct ls_subnet *ls_find_subnet(struct ls_ted *ted,
{
struct ls_subnet subnet = {};
- subnet.key = *prefix;
+ if (!prefix)
+ return NULL;
+
+ prefix_copy(&subnet.key, prefix);
return subnets_find(&ted->subnets, &subnet);
}
@@ -1779,9 +1781,10 @@ struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg,
case LS_MSG_EVENT_DELETE:
vertex = ls_find_vertex_by_id(ted, node->adv);
if (vertex) {
- if (delete)
+ if (delete) {
ls_vertex_del_all(ted, vertex);
- else
+ vertex = NULL;
+ } else
vertex->status = DELETE;
}
break;
@@ -1858,9 +1861,10 @@ struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
case LS_MSG_EVENT_DELETE:
subnet = ls_find_subnet(ted, &pref->pref);
if (subnet) {
- if (delete)
+ if (delete) {
ls_subnet_del_all(ted, subnet);
- else
+ subnet = NULL;
+ } else
subnet->status = DELETE;
}
break;
diff --git a/lib/log_vty.c b/lib/log_vty.c
index fc28ffc6fa..26e608d16b 100644
--- a/lib/log_vty.c
+++ b/lib/log_vty.c
@@ -34,18 +34,23 @@ static int log_cmdline_syslog_lvl = ZLOG_DISABLED;
static struct zlog_cfg_file zt_file_cmdline = {
.prio_min = ZLOG_DISABLED,
+ .ts_subsec = LOG_TIMESTAMP_PRECISION,
};
static struct zlog_cfg_file zt_file = {
.prio_min = ZLOG_DISABLED,
+ .ts_subsec = LOG_TIMESTAMP_PRECISION,
};
static struct zlog_cfg_filterfile zt_filterfile = {
- .parent = {
- .prio_min = ZLOG_DISABLED,
- },
+ .parent =
+ {
+ .prio_min = ZLOG_DISABLED,
+ .ts_subsec = LOG_TIMESTAMP_PRECISION,
+ },
};
static struct zlog_cfg_file zt_stdout_file = {
.prio_min = ZLOG_DISABLED,
+ .ts_subsec = LOG_TIMESTAMP_PRECISION,
};
static struct zlog_cfg_5424 zt_stdout_journald = {
.prio_min = ZLOG_DISABLED,
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index 7437eedfc7..9427f7cf3d 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -6,29 +6,25 @@
*/
#include <zebra.h>
+#include "debug.h"
#include "libfrr.h"
#include "mgmtd/mgmt.h"
#include "mgmt_be_client.h"
#include "mgmt_msg.h"
#include "mgmt_pb.h"
#include "network.h"
+#include "northbound.h"
#include "stream.h"
#include "sockopt.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
+#include "lib/mgmt_be_client_clippy.c"
+
#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_be_client) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+ DEBUGD(&mgmt_dbg_be_client, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
+#define MGMTD_DBG_BE_CLIENT_CHECK() \
+ DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL)
DEFINE_MTYPE_STATIC(LIB, MGMTD_BE_BATCH,
"MGMTD backend transaction batch data");
@@ -118,8 +114,6 @@ struct mgmt_be_client_ctx {
struct nb_config *candidate_config;
struct nb_config *running_config;
- unsigned long num_batch_find;
- unsigned long avg_batch_find_tm;
unsigned long num_edit_nb_cfg;
unsigned long avg_edit_nb_cfg_tm;
unsigned long num_prep_nb_cfg;
@@ -136,7 +130,7 @@ struct mgmt_be_client_ctx {
#define FOREACH_BE_TXN_IN_LIST(client_ctx, txn) \
frr_each_safe (mgmt_be_txns, &(client_ctx)->txn_head, (txn))
-static bool mgmt_debug_be_client;
+struct debug mgmt_dbg_be_client = {0, "Management backend client operations"};
static struct mgmt_be_client_ctx mgmt_be_client_ctx = {
.conn_fd = -1,
@@ -479,7 +473,6 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
bool error;
char err_buf[BUFSIZ];
size_t num_processed;
- bool debug_be = mgmt_debug_be_client;
int err;
assert(txn && txn->client_ctx);
@@ -499,8 +492,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
* interested in validating it.
*/
error = false;
- if (debug_be)
- gettimeofday(&edit_nb_cfg_start, NULL);
+
+ gettimeofday(&edit_nb_cfg_start, NULL);
nb_candidate_edit_config_changes(
client_ctx->candidate_config,
txn_req->req.set_cfg.cfg_changes,
@@ -516,16 +509,14 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
err_buf);
return -1;
}
- if (debug_be) {
- gettimeofday(&edit_nb_cfg_end, NULL);
- edit_nb_cfg_tm = timeval_elapsed(
- edit_nb_cfg_end, edit_nb_cfg_start);
- client_ctx->avg_edit_nb_cfg_tm =
- ((client_ctx->avg_edit_nb_cfg_tm
- * client_ctx->num_edit_nb_cfg)
- + edit_nb_cfg_tm)
- / (client_ctx->num_edit_nb_cfg + 1);
- }
+ gettimeofday(&edit_nb_cfg_end, NULL);
+ edit_nb_cfg_tm = timeval_elapsed(edit_nb_cfg_end,
+ edit_nb_cfg_start);
+ client_ctx->avg_edit_nb_cfg_tm =
+ ((client_ctx->avg_edit_nb_cfg_tm *
+ client_ctx->num_edit_nb_cfg) +
+ edit_nb_cfg_tm) /
+ (client_ctx->num_edit_nb_cfg + 1);
client_ctx->num_edit_nb_cfg++;
}
@@ -540,8 +531,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
*/
nb_ctx.client = NB_CLIENT_CLI;
nb_ctx.user = (void *)client_ctx->client_params.user_data;
- if (debug_be)
- gettimeofday(&prep_nb_cfg_start, NULL);
+
+ gettimeofday(&prep_nb_cfg_start, NULL);
err = nb_candidate_commit_prepare(nb_ctx, client_ctx->candidate_config,
"MGMTD Backend Txn", &txn->nb_txn,
#ifdef MGMTD_LOCAL_VALIDATIONS_ENABLED
@@ -569,16 +560,13 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
"Prepared configs for Txn %llx, %u Batches! successfully!",
(unsigned long long)txn->txn_id,
(uint32_t)num_processed);
- if (debug_be) {
- gettimeofday(&prep_nb_cfg_end, NULL);
- prep_nb_cfg_tm =
- timeval_elapsed(prep_nb_cfg_end, prep_nb_cfg_start);
- client_ctx->avg_prep_nb_cfg_tm =
- ((client_ctx->avg_prep_nb_cfg_tm
- * client_ctx->num_prep_nb_cfg)
- + prep_nb_cfg_tm)
- / (client_ctx->num_prep_nb_cfg + 1);
- }
+
+ gettimeofday(&prep_nb_cfg_end, NULL);
+ prep_nb_cfg_tm = timeval_elapsed(prep_nb_cfg_end, prep_nb_cfg_start);
+ client_ctx->avg_prep_nb_cfg_tm = ((client_ctx->avg_prep_nb_cfg_tm *
+ client_ctx->num_prep_nb_cfg) +
+ prep_nb_cfg_tm) /
+ (client_ctx->num_prep_nb_cfg + 1);
client_ctx->num_prep_nb_cfg++;
FOREACH_BE_TXN_BATCH_IN_LIST (txn, batch) {
@@ -593,12 +581,10 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn)
}
}
- if (debug_be)
- MGMTD_BE_CLIENT_DBG(
- "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u",
- client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm,
- client_ctx->avg_prep_nb_cfg_tm,
- (uint32_t)num_processed);
+ MGMTD_BE_CLIENT_DBG(
+ "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u",
+ client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm,
+ client_ctx->avg_prep_nb_cfg_tm, (uint32_t)num_processed);
if (error)
mgmt_be_txn_cfg_abort(txn);
@@ -736,7 +722,6 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn)
char err_buf[BUFSIZ];
size_t num_processed;
static uint64_t batch_ids[MGMTD_BE_MAX_BATCH_IDS_IN_REQ];
- bool debug_be = mgmt_debug_be_client;
assert(txn && txn->client_ctx);
client_ctx = txn->client_ctx;
@@ -747,20 +732,16 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn)
/*
* Now apply all the batches we have applied in one go.
*/
- if (debug_be)
- gettimeofday(&apply_nb_cfg_start, NULL);
+ gettimeofday(&apply_nb_cfg_start, NULL);
(void)nb_candidate_commit_apply(txn->nb_txn, true, &txn->nb_txn_id,
err_buf, sizeof(err_buf) - 1);
- if (debug_be) {
- gettimeofday(&apply_nb_cfg_end, NULL);
- apply_nb_cfg_tm =
- timeval_elapsed(apply_nb_cfg_end, apply_nb_cfg_start);
- client_ctx->avg_apply_nb_cfg_tm =
- ((client_ctx->avg_apply_nb_cfg_tm
- * client_ctx->num_apply_nb_cfg)
- + apply_nb_cfg_tm)
- / (client_ctx->num_apply_nb_cfg + 1);
- }
+ gettimeofday(&apply_nb_cfg_end, NULL);
+
+ apply_nb_cfg_tm = timeval_elapsed(apply_nb_cfg_end, apply_nb_cfg_start);
+ client_ctx->avg_apply_nb_cfg_tm = ((client_ctx->avg_apply_nb_cfg_tm *
+ client_ctx->num_apply_nb_cfg) +
+ apply_nb_cfg_tm) /
+ (client_ctx->num_apply_nb_cfg + 1);
client_ctx->num_apply_nb_cfg++;
txn->nb_txn = NULL;
@@ -789,10 +770,8 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn)
mgmt_be_send_apply_reply(client_ctx, txn->txn_id, batch_ids,
num_processed, true, NULL);
- if (debug_be)
- MGMTD_BE_CLIENT_DBG("Nb-apply-duration %lu (avg: %lu) uSec",
- apply_nb_cfg_tm,
- client_ctx->avg_apply_nb_cfg_tm);
+ MGMTD_BE_CLIENT_DBG("Nb-apply-duration %lu (avg: %lu) uSec",
+ apply_nb_cfg_tm, client_ctx->avg_apply_nb_cfg_tm);
return 0;
}
@@ -903,7 +882,7 @@ static void mgmt_be_client_proc_msgbufs(struct event *thread)
struct mgmt_be_client_ctx *client_ctx = EVENT_ARG(thread);
if (mgmt_msg_procbufs(&client_ctx->mstate, mgmt_be_client_process_msg,
- client_ctx, mgmt_debug_be_client))
+ client_ctx, MGMTD_DBG_BE_CLIENT_CHECK()))
mgmt_be_client_register_event(client_ctx, MGMTD_BE_PROC_MSG);
}
@@ -913,7 +892,7 @@ static void mgmt_be_client_read(struct event *thread)
enum mgmt_msg_rsched rv;
rv = mgmt_msg_read(&client_ctx->mstate, client_ctx->conn_fd,
- mgmt_debug_be_client);
+ MGMTD_DBG_BE_CLIENT_CHECK());
if (rv == MSR_DISCONNECT) {
mgmt_be_server_disconnect(client_ctx, true);
return;
@@ -958,7 +937,7 @@ static int mgmt_be_client_send_msg(struct mgmt_be_client_ctx *client_ctx,
&client_ctx->mstate, be_msg,
mgmtd__be_message__get_packed_size(be_msg),
(size_t(*)(void *, void *))mgmtd__be_message__pack,
- mgmt_debug_be_client);
+ MGMTD_DBG_BE_CLIENT_CHECK());
mgmt_be_client_sched_msg_write(client_ctx);
return rv;
}
@@ -969,7 +948,7 @@ static void mgmt_be_client_write(struct event *thread)
enum mgmt_msg_wsched rv;
rv = mgmt_msg_write(&client_ctx->mstate, client_ctx->conn_fd,
- mgmt_debug_be_client);
+ MGMTD_DBG_BE_CLIENT_CHECK());
if (rv == MSW_SCHED_STREAM)
mgmt_be_client_register_event(client_ctx, MGMTD_BE_CONN_WRITE);
else if (rv == MSW_DISCONNECT)
@@ -1017,7 +996,7 @@ static int mgmt_be_send_subscr_req(struct mgmt_be_client_ctx *client_ctx,
static void mgmt_be_server_connect(struct mgmt_be_client_ctx *client_ctx)
{
- const char *dbgtag = mgmt_debug_be_client ? "BE-client" : NULL;
+ const char *dbgtag = MGMTD_DBG_BE_CLIENT_CHECK() ? "BE-client" : NULL;
assert(client_ctx->conn_fd == -1);
client_ctx->conn_fd = mgmt_msg_connect(
@@ -1097,7 +1076,47 @@ mgmt_be_client_schedule_conn_retry(struct mgmt_be_client_ctx *client_ctx,
&client_ctx->conn_retry_tmr);
}
-extern struct nb_config *running_config;
+DEFPY(debug_mgmt_client_be, debug_mgmt_client_be_cmd,
+ "[no] debug mgmt client backend",
+ NO_STR DEBUG_STR MGMTD_STR
+ "client\n"
+ "backend\n")
+{
+ uint32_t mode = DEBUG_NODE2MODE(vty->node);
+
+ DEBUG_MODE_SET(&mgmt_dbg_be_client, mode, !no);
+
+ return CMD_SUCCESS;
+}
+
+static void mgmt_debug_client_be_set_all(uint32_t flags, bool set)
+{
+ DEBUG_FLAGS_SET(&mgmt_dbg_be_client, flags, set);
+}
+
+static int mgmt_debug_be_client_config_write(struct vty *vty)
+{
+ if (DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_CONF))
+ vty_out(vty, "debug mgmt client frontend\n");
+
+ return 1;
+}
+
+void mgmt_debug_be_client_show_debug(struct vty *vty)
+{
+ if (MGMTD_DBG_BE_CLIENT_CHECK())
+ vty_out(vty, "debug mgmt client backend\n");
+}
+
+static struct debug_callbacks mgmt_dbg_be_client_cbs = {
+ .debug_set_all = mgmt_debug_client_be_set_all};
+
+static struct cmd_node mgmt_dbg_node = {
+ .name = "mgmt backend client",
+ .node = DEBUG_NODE,
+ .prompt = "",
+ .config_write = mgmt_debug_be_client_config_write,
+};
/*
* Initialize library and try connecting with MGMTD.
@@ -1134,6 +1153,16 @@ uintptr_t mgmt_be_client_lib_init(struct mgmt_be_client_params *params,
return (uintptr_t)&mgmt_be_client_ctx;
}
+
+void mgmt_be_client_lib_vty_init(void)
+{
+ debug_init(&mgmt_dbg_be_client_cbs);
+ install_node(&mgmt_dbg_node);
+ install_element(ENABLE_NODE, &debug_mgmt_client_be_cmd);
+ install_element(CONFIG_NODE, &debug_mgmt_client_be_cmd);
+}
+
+
/*
* Subscribe with MGMTD for one or more YANG subtree(s).
*/
diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h
index db427457a4..d4f2d86fdf 100644
--- a/lib/mgmt_be_client.h
+++ b/lib/mgmt_be_client.h
@@ -192,6 +192,20 @@ extern uintptr_t mgmt_be_client_lib_init(struct mgmt_be_client_params *params,
struct event_loop *master_thread);
/*
+ * Initialize library vty (adds debug support).
+ *
+ * This call should be added to your component when enabling other vty code to
+ * enable mgmtd client debugs. When adding, one needs to also add a their
+ * component in `xref2vtysh.py` as well.
+ */
+extern void mgmt_be_client_lib_vty_init(void);
+
+/*
+ * Print enabled debugging commands.
+ */
+extern void mgmt_debug_be_client_show_debug(struct vty *vty);
+
+/*
* Subscribe with MGMTD for one or more YANG subtree(s).
*
* lib_hndl
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index 7cb9aa3def..b8266bfa82 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -6,6 +6,7 @@
*/
#include <zebra.h>
+#include "debug.h"
#include "memory.h"
#include "libfrr.h"
#include "mgmt_fe_client.h"
@@ -15,20 +16,14 @@
#include "stream.h"
#include "sockopt.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
-#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_fe_client) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
-#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
+#include "lib/mgmt_fe_client_clippy.c"
+
+#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
+ DEBUGD(&mgmt_dbg_fe_client, "%s:" fmt, __func__, ##__VA_ARGS__)
+#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
+#define MGMTD_DBG_FE_CLIENT_CHECK() \
+ DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL)
struct mgmt_fe_client_ctx;
@@ -69,7 +64,7 @@ struct mgmt_fe_client_ctx {
#define FOREACH_SESSION_IN_LIST(client_ctx, session) \
frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session))
-static bool mgmt_debug_fe_client;
+struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
static struct mgmt_fe_client_ctx mgmt_fe_client_ctx = {
.conn_fd = -1,
@@ -169,7 +164,7 @@ static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx *client_ctx,
&client_ctx->mstate, fe_msg,
mgmtd__fe_message__get_packed_size(fe_msg),
(size_t(*)(void *, void *))mgmtd__fe_message__pack,
- mgmt_debug_fe_client);
+ MGMTD_DBG_FE_CLIENT_CHECK());
mgmt_fe_client_sched_msg_write(client_ctx);
return rv;
}
@@ -181,7 +176,7 @@ static void mgmt_fe_client_write(struct event *thread)
client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread);
rv = mgmt_msg_write(&client_ctx->mstate, client_ctx->conn_fd,
- mgmt_debug_fe_client);
+ MGMTD_DBG_FE_CLIENT_CHECK());
if (rv == MSW_SCHED_STREAM)
mgmt_fe_client_register_event(client_ctx, MGMTD_FE_CONN_WRITE);
else if (rv == MSW_DISCONNECT)
@@ -679,7 +674,7 @@ static void mgmt_fe_client_proc_msgbufs(struct event *thread)
client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread);
if (mgmt_msg_procbufs(&client_ctx->mstate, mgmt_fe_client_process_msg,
- client_ctx, mgmt_debug_fe_client))
+ client_ctx, MGMTD_DBG_FE_CLIENT_CHECK()))
mgmt_fe_client_register_event(client_ctx, MGMTD_FE_PROC_MSG);
}
@@ -691,7 +686,7 @@ static void mgmt_fe_client_read(struct event *thread)
client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread);
rv = mgmt_msg_read(&client_ctx->mstate, client_ctx->conn_fd,
- mgmt_debug_fe_client);
+ MGMTD_DBG_FE_CLIENT_CHECK());
if (rv == MSR_DISCONNECT) {
mgmt_fe_server_disconnect(client_ctx, true);
return;
@@ -703,7 +698,7 @@ static void mgmt_fe_client_read(struct event *thread)
static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx *client_ctx)
{
- const char *dbgtag = mgmt_debug_fe_client ? "FE-client" : NULL;
+ const char *dbgtag = MGMTD_DBG_FE_CLIENT_CHECK() ? "FE-client" : NULL;
assert(client_ctx->conn_fd == -1);
client_ctx->conn_fd = mgmt_msg_connect(
@@ -779,6 +774,48 @@ static void mgmt_fe_client_schedule_conn_retry(
&client_ctx->conn_retry_tmr);
}
+DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
+ "[no] debug mgmt client frontend",
+ NO_STR DEBUG_STR MGMTD_STR
+ "client\n"
+ "frontend\n")
+{
+ uint32_t mode = DEBUG_NODE2MODE(vty->node);
+
+ DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no);
+
+ return CMD_SUCCESS;
+}
+
+static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set)
+{
+ DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set);
+}
+
+static int mgmt_debug_fe_client_config_write(struct vty *vty)
+{
+ if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF))
+ vty_out(vty, "debug mgmt client frontend\n");
+
+ return CMD_SUCCESS;
+}
+
+void mgmt_debug_fe_client_show_debug(struct vty *vty)
+{
+ if (MGMTD_DBG_FE_CLIENT_CHECK())
+ vty_out(vty, "debug mgmt client frontend\n");
+}
+
+static struct debug_callbacks mgmt_dbg_fe_client_cbs = {
+ .debug_set_all = mgmt_debug_client_fe_set_all};
+
+static struct cmd_node mgmt_dbg_node = {
+ .name = "mgmt client frontend",
+ .node = DEBUG_NODE,
+ .prompt = "",
+ .config_write = mgmt_debug_fe_client_config_write,
+};
+
/*
* Initialize library and try connecting with MGMTD.
*/
@@ -809,6 +846,14 @@ uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params,
return (uintptr_t)&mgmt_fe_client_ctx;
}
+void mgmt_fe_client_lib_vty_init(void)
+{
+ debug_init(&mgmt_dbg_fe_client_cbs);
+ install_node(&mgmt_dbg_node);
+ install_element(ENABLE_NODE, &debug_mgmt_client_fe_cmd);
+ install_element(CONFIG_NODE, &debug_mgmt_client_fe_cmd);
+}
+
/*
* Create a new Session for a Frontend Client connection.
*/
diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h
index aa3371f03c..94867787d9 100644
--- a/lib/mgmt_fe_client.h
+++ b/lib/mgmt_fe_client.h
@@ -134,6 +134,20 @@ extern uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params,
struct event_loop *master_thread);
/*
+ * Initialize library vty (adds debug support).
+ *
+ * This call should be added to your component when enabling other vty code to
+ * enable mgmtd client debugs. When adding, one needs to also add a their
+ * component in `xref2vtysh.py` as well.
+ */
+extern void mgmt_fe_client_lib_vty_init(void);
+
+/*
+ * Print enabled debugging commands.
+ */
+extern void mgmt_debug_fe_client_show_debug(struct vty *vty);
+
+/*
* Create a new Session for a Frontend Client connection.
*
* lib_hndl
diff --git a/lib/subdir.am b/lib/subdir.am
index 7ae82d5a69..c046c3c43c 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -179,6 +179,8 @@ clippy_scan += \
lib/filter_cli.c \
lib/if_rmap.c \
lib/log_vty.c \
+ lib/mgmt_be_client.c \
+ lib/mgmt_fe_client.c \
lib/nexthop_group.c \
lib/northbound_cli.c \
lib/plist.c \
diff --git a/lib/vty.c b/lib/vty.c
index c6134fe07f..d6a0dba206 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -125,8 +125,8 @@ static int no_password_check = 0;
/* Integrated configuration file path */
static char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
-static bool do_log_commands;
-static bool do_log_commands_perm;
+bool vty_log_commands;
+static bool vty_log_commands_perm;
void vty_mgmt_resume_response(struct vty *vty, bool success)
{
@@ -508,7 +508,7 @@ static int vty_command(struct vty *vty, char *buf)
/*
* Log non empty command lines
*/
- if (do_log_commands &&
+ if (vty_log_commands &&
strncmp(buf, "echo PING", strlen("echo PING")) != 0)
cp = buf;
if (cp != NULL) {
@@ -3160,15 +3160,15 @@ DEFPY (log_commands,
"Log all commands\n")
{
if (no) {
- if (do_log_commands_perm) {
+ if (vty_log_commands_perm) {
vty_out(vty,
"Daemon started with permanent logging turned on for commands, ignoring\n");
return CMD_WARNING;
}
- do_log_commands = false;
+ vty_log_commands = false;
} else
- do_log_commands = true;
+ vty_log_commands = true;
return CMD_SUCCESS;
}
@@ -3196,7 +3196,7 @@ static int vty_config_write(struct vty *vty)
vty_endframe(vty, "exit\n");
- if (do_log_commands)
+ if (vty_log_commands)
vty_out(vty, "log commands\n");
vty_out(vty, "!\n");
@@ -3677,8 +3677,8 @@ void vty_init(struct event_loop *master_thread, bool do_command_logging)
install_element(CONFIG_NODE, &log_commands_cmd);
if (do_command_logging) {
- do_log_commands = true;
- do_log_commands_perm = true;
+ vty_log_commands = true;
+ vty_log_commands_perm = true;
}
install_element(ENABLE_NODE, &terminal_monitor_cmd);
diff --git a/lib/vty.h b/lib/vty.h
index 5114238f6a..560748d91d 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -335,6 +335,7 @@ struct vty_arg {
#endif
extern struct nb_config *vty_mgmt_candidate_config;
+extern bool vty_log_commands;
/* Prototypes. */
extern void vty_init(struct event_loop *m, bool do_command_logging);
diff --git a/mgmtd/mgmt.c b/mgmtd/mgmt.c
index a5c0eb34a3..7a65a19f55 100644
--- a/mgmtd/mgmt.c
+++ b/mgmtd/mgmt.c
@@ -7,6 +7,7 @@
*/
#include <zebra.h>
+#include "debug.h"
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_be_server.h"
#include "mgmtd/mgmt_be_adapter.h"
@@ -16,10 +17,10 @@
#include "mgmtd/mgmt_history.h"
#include "mgmtd/mgmt_memory.h"
-bool mgmt_debug_be;
-bool mgmt_debug_fe;
-bool mgmt_debug_ds;
-bool mgmt_debug_txn;
+struct debug mgmt_debug_be = {.desc = "Management backend adapater"};
+struct debug mgmt_debug_ds = {.desc = "Management datastore"};
+struct debug mgmt_debug_fe = {.desc = "Management frontend adapater"};
+struct debug mgmt_debug_txn = {.desc = "Management transaction"};
/* MGMTD process wide configuration. */
static struct mgmt_master mgmt_master;
diff --git a/mgmtd/mgmt.h b/mgmtd/mgmt.h
index 9579b02230..603296bb38 100644
--- a/mgmtd/mgmt.h
+++ b/mgmtd/mgmt.h
@@ -9,6 +9,7 @@
#ifndef _FRR_MGMTD_H
#define _FRR_MGMTD_H
+#include "debug.h"
#include "vrf.h"
#include "defaults.h"
#include "stream.h"
@@ -23,10 +24,15 @@
#define MGMTD_SOCKET_BUF_SIZE 65535
#define MGMTD_MAX_COMMIT_LIST 10
-extern bool mgmt_debug_be;
-extern bool mgmt_debug_fe;
-extern bool mgmt_debug_ds;
-extern bool mgmt_debug_txn;
+extern struct debug mgmt_debug_be;
+extern struct debug mgmt_debug_ds;
+extern struct debug mgmt_debug_fe;
+extern struct debug mgmt_debug_txn;
+
+#define MGMT_DEBUG_BE_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)
+#define MGMT_DEBUG_DS_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_ds, DEBUG_MODE_ALL)
+#define MGMT_DEBUG_FE_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_fe, DEBUG_MODE_ALL)
+#define MGMT_DEBUG_TXN_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_tx, DEBUG_MODE_ALL)
struct mgmt_txn_ctx;
@@ -102,16 +108,4 @@ extern void mgmt_master_init(struct event_loop *master, const int buffer_size);
extern void mgmt_init(void);
extern void mgmt_vty_init(void);
-static inline char *mgmt_realtime_to_string(struct timeval *tv, char *buf,
- size_t sz)
-{
- struct tm tm;
- size_t n;
-
- localtime_r((const time_t *)&tv->tv_sec, &tm);
- n = strftime(buf, sz, "%Y-%m-%dT%H:%M:%S", &tm);
- snprintf(&buf[n], sz - n, ",%06u000", (unsigned int)tv->tv_usec);
- return buf;
-}
-
#endif /* _FRR_MGMTD_H */
diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c
index cf7d705943..9d210b8716 100644
--- a/mgmtd/mgmt_be_adapter.c
+++ b/mgmtd/mgmt_be_adapter.c
@@ -18,20 +18,10 @@
#include "mgmt_be_client.h"
#include "mgmtd/mgmt_be_adapter.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_BE_ADAPTER_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
-#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_be) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \
+ DEBUGD(&mgmt_debug_be, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_BE_ADAPTER_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
#define FOREACH_ADAPTER_IN_LIST(adapter) \
frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter))
@@ -521,7 +511,7 @@ static int mgmt_be_adapter_send_msg(struct mgmt_be_client_adapter *adapter,
&adapter->mstate, be_msg,
mgmtd__be_message__get_packed_size(be_msg),
(size_t(*)(void *, void *))mgmtd__be_message__pack,
- mgmt_debug_be);
+ MGMT_DEBUG_BE_CHECK());
mgmt_be_adapter_sched_msg_write(adapter);
return rv;
}
@@ -619,7 +609,7 @@ static void mgmt_be_adapter_proc_msgbufs(struct event *thread)
struct mgmt_be_client_adapter *adapter = EVENT_ARG(thread);
if (mgmt_msg_procbufs(&adapter->mstate, mgmt_be_adapter_process_msg,
- adapter, mgmt_debug_be))
+ adapter, MGMT_DEBUG_BE_CHECK()))
mgmt_be_adapter_register_event(adapter, MGMTD_BE_PROC_MSG);
}
@@ -630,7 +620,8 @@ static void mgmt_be_adapter_read(struct event *thread)
adapter = (struct mgmt_be_client_adapter *)EVENT_ARG(thread);
- rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, mgmt_debug_be);
+ rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd,
+ MGMT_DEBUG_BE_CHECK());
if (rv == MSR_DISCONNECT) {
mgmt_be_adapter_disconnect(adapter);
return;
@@ -645,7 +636,8 @@ static void mgmt_be_adapter_write(struct event *thread)
struct mgmt_be_client_adapter *adapter = EVENT_ARG(thread);
enum mgmt_msg_wsched rv;
- rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, mgmt_debug_be);
+ rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd,
+ MGMT_DEBUG_BE_CHECK());
if (rv == MSW_SCHED_STREAM)
mgmt_be_adapter_register_event(adapter, MGMTD_BE_CONN_WRITE);
else if (rv == MSW_DISCONNECT)
diff --git a/mgmtd/mgmt_be_server.c b/mgmtd/mgmt_be_server.c
index aa77464524..029e032feb 100644
--- a/mgmtd/mgmt_be_server.c
+++ b/mgmtd/mgmt_be_server.c
@@ -13,20 +13,10 @@
#include "mgmtd/mgmt_be_server.h"
#include "mgmtd/mgmt_be_adapter.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_BE_SRVR_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_BE_SRVR_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
#define MGMTD_BE_SRVR_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_be) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+ DEBUGD(&mgmt_debug_be, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_BE_SRVR_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
static int mgmt_be_listen_fd = -1;
static struct event_loop *mgmt_be_listen_tm;
diff --git a/mgmtd/mgmt_ds.c b/mgmtd/mgmt_ds.c
index 05a67a89cd..b5eaf7bff6 100644
--- a/mgmtd/mgmt_ds.c
+++ b/mgmtd/mgmt_ds.c
@@ -15,20 +15,10 @@
#include "mgmtd/mgmt_txn.h"
#include "libyang/libyang.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
#define MGMTD_DS_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_DS_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
-#define MGMTD_DS_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_ds) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+ DEBUGD(&mgmt_debug_ds, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_DS_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
struct mgmt_ds_ctx {
Mgmtd__DatastoreId ds_id;
diff --git a/mgmtd/mgmt_ds.h b/mgmtd/mgmt_ds.h
index 8d01f3d5b1..2a32eb641a 100644
--- a/mgmtd/mgmt_ds.h
+++ b/mgmtd/mgmt_ds.h
@@ -28,12 +28,9 @@
for ((id) = MGMTD_DS_NONE; (id) < MGMTD_DS_MAX_ID; (id)++)
#define MGMTD_MAX_COMMIT_LIST 10
-#define MGMTD_MD5_HASH_LEN 16
-#define MGMTD_MD5_HASH_STR_HEX_LEN 33
#define MGMTD_COMMIT_FILE_PATH DAEMON_DB_DIR "/commit-%s.json"
#define MGMTD_COMMIT_INDEX_FILE_NAME DAEMON_DB_DIR "/commit-index.dat"
-#define MGMTD_COMMIT_TIME_STR_LEN 100
extern struct nb_config *running_config;
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index 90e6870fd4..262741b665 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -19,20 +19,10 @@
#include "mgmtd/mgmt_memory.h"
#include "mgmtd/mgmt_fe_adapter.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
-#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_fe) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
+ DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
#define FOREACH_ADAPTER_IN_LIST(adapter) \
frr_each_safe (mgmt_fe_adapters, &mgmt_fe_adapters, (adapter))
@@ -399,7 +389,7 @@ mgmt_fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter,
&adapter->mstate, fe_msg,
mgmtd__fe_message__get_packed_size(fe_msg),
(size_t(*)(void *, void *))mgmtd__fe_message__pack,
- mgmt_debug_fe);
+ MGMT_DEBUG_FE_CHECK());
mgmt_fe_adapter_sched_msg_write(adapter);
return rv;
}
@@ -1439,7 +1429,7 @@ static void mgmt_fe_adapter_proc_msgbufs(struct event *thread)
struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
if (mgmt_msg_procbufs(&adapter->mstate, mgmt_fe_adapter_process_msg,
- adapter, mgmt_debug_fe))
+ adapter, MGMT_DEBUG_FE_CHECK()))
mgmt_fe_adapter_register_event(adapter, MGMTD_FE_PROC_MSG);
}
@@ -1448,7 +1438,8 @@ static void mgmt_fe_adapter_read(struct event *thread)
struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
enum mgmt_msg_rsched rv;
- rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, mgmt_debug_fe);
+ rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd,
+ MGMT_DEBUG_FE_CHECK());
if (rv == MSR_DISCONNECT) {
mgmt_fe_adapter_disconnect(adapter);
return;
@@ -1463,7 +1454,8 @@ static void mgmt_fe_adapter_write(struct event *thread)
struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
enum mgmt_msg_wsched rv;
- rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, mgmt_debug_fe);
+ rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd,
+ MGMT_DEBUG_FE_CHECK());
if (rv == MSW_SCHED_STREAM)
mgmt_fe_adapter_register_event(adapter, MGMTD_FE_CONN_WRITE);
else if (rv == MSW_DISCONNECT)
@@ -1722,7 +1714,7 @@ static void
mgmt_fe_adapter_cmt_stats_write(struct vty *vty,
struct mgmt_fe_client_adapter *adapter)
{
- char buf[100] = {0};
+ char buf[MGMT_LONG_TIME_MAX_LEN];
if (!mm->perf_stats_en)
return;
@@ -1803,7 +1795,7 @@ static void
mgmt_fe_adapter_setcfg_stats_write(struct vty *vty,
struct mgmt_fe_client_adapter *adapter)
{
- char buf[100] = {0};
+ char buf[MGMT_LONG_TIME_MAX_LEN];
if (!mm->perf_stats_en)
return;
diff --git a/mgmtd/mgmt_fe_server.c b/mgmtd/mgmt_fe_server.c
index e8bbe139bb..e737e00352 100644
--- a/mgmtd/mgmt_fe_server.c
+++ b/mgmtd/mgmt_fe_server.c
@@ -13,20 +13,10 @@
#include "mgmtd/mgmt_fe_server.h"
#include "mgmtd/mgmt_fe_adapter.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_FE_SRVR_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_FE_SRVR_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
#define MGMTD_FE_SRVR_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_fe) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
+ DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__)
#define MGMTD_FE_SRVR_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
static int mgmt_fe_listen_fd = -1;
static struct event_loop *mgmt_fe_listen_tm;
diff --git a/mgmtd/mgmt_history.c b/mgmtd/mgmt_history.c
index 2251c49f1c..a49718a490 100644
--- a/mgmtd/mgmt_history.c
+++ b/mgmtd/mgmt_history.c
@@ -18,8 +18,8 @@
struct mgmt_cmt_info_t {
struct mgmt_cmt_infos_item cmts;
- char cmtid_str[MGMTD_MD5_HASH_STR_HEX_LEN];
- char time_str[MGMTD_COMMIT_TIME_STR_LEN];
+ char cmtid_str[MGMT_SHORT_TIME_MAX_LEN];
+ char time_str[MGMT_LONG_TIME_MAX_LEN];
char cmt_json_file[PATH_MAX];
};
@@ -54,36 +54,30 @@ static void mgmt_history_remove_file(char *name)
zlog_err("Old commit info deletion failed");
}
-static void mgmt_history_hash(const char *input_str, char *hash)
+static struct mgmt_cmt_info_t *mgmt_history_new_cmt_info(void)
{
- int i;
- unsigned char digest[MGMTD_MD5_HASH_LEN];
- MD5_CTX ctx;
-
- memset(&ctx, 0, sizeof(ctx));
- MD5Init(&ctx);
- MD5Update(&ctx, input_str, strlen(input_str));
- MD5Final(digest, &ctx);
-
- for (i = 0; i < MGMTD_MD5_HASH_LEN; i++)
- snprintf(&hash[i * 2], MGMTD_MD5_HASH_STR_HEX_LEN, "%02x",
- (unsigned int)digest[i]);
+ struct mgmt_cmt_info_t *new;
+ struct timespec tv;
+ struct tm tm;
+
+ new = XCALLOC(MTYPE_MGMTD_CMT_INFO, sizeof(struct mgmt_cmt_info_t));
+
+ clock_gettime(CLOCK_REALTIME, &tv);
+ localtime_r(&tv.tv_sec, &tm);
+
+ mgmt_time_to_string(&tv, true, new->time_str, sizeof(new->time_str));
+ mgmt_time_to_string(&tv, false, new->cmtid_str, sizeof(new->cmtid_str));
+ snprintf(new->cmt_json_file, sizeof(new->cmt_json_file),
+ MGMTD_COMMIT_FILE_PATH, new->cmtid_str);
+
+ return new;
}
static struct mgmt_cmt_info_t *mgmt_history_create_cmt_rec(void)
{
- struct mgmt_cmt_info_t *new;
+ struct mgmt_cmt_info_t *new = mgmt_history_new_cmt_info();
struct mgmt_cmt_info_t *cmt_info;
struct mgmt_cmt_info_t *last_cmt_info = NULL;
- struct timeval cmt_recd_tv;
-
- new = XCALLOC(MTYPE_MGMTD_CMT_INFO, sizeof(struct mgmt_cmt_info_t));
- gettimeofday(&cmt_recd_tv, NULL);
- mgmt_realtime_to_string(&cmt_recd_tv, new->time_str,
- sizeof(new->time_str));
- mgmt_history_hash(new->time_str, new->cmtid_str);
- snprintf(new->cmt_json_file, sizeof(new->cmt_json_file) - 1,
- MGMTD_COMMIT_FILE_PATH, new->cmtid_str);
if (mgmt_cmt_infos_count(&mm->cmts) == MGMTD_MAX_COMMIT_LIST) {
FOREACH_CMT_REC (mm, cmt_info)
@@ -106,8 +100,7 @@ mgmt_history_find_cmt_record(const char *cmtid_str)
struct mgmt_cmt_info_t *cmt_info;
FOREACH_CMT_REC (mm, cmt_info) {
- if (strncmp(cmt_info->cmtid_str, cmtid_str,
- MGMTD_MD5_HASH_STR_HEX_LEN) == 0)
+ if (strcmp(cmt_info->cmtid_str, cmtid_str) == 0)
return cmt_info;
}
@@ -282,8 +275,7 @@ int mgmt_history_rollback_by_id(struct vty *vty, const char *cmtid_str)
}
FOREACH_CMT_REC (mm, cmt_info) {
- if (strncmp(cmt_info->cmtid_str, cmtid_str,
- MGMTD_MD5_HASH_STR_HEX_LEN) == 0) {
+ if (strcmp(cmt_info->cmtid_str, cmtid_str) == 0) {
ret = mgmt_history_rollback_to_cmt(vty, cmt_info,
false);
return ret;
@@ -349,9 +341,9 @@ void show_mgmt_cmt_history(struct vty *vty)
int slno = 0;
vty_out(vty, "Last 10 commit history:\n");
- vty_out(vty, " Sl.No\tCommit-ID(HEX)\t\t\t Commit-Record-Time\n");
+ vty_out(vty, "Slot Commit-ID Commit-Record-Time\n");
FOREACH_CMT_REC (mm, cmt_info) {
- vty_out(vty, " %d\t%s %s\n", slno, cmt_info->cmtid_str,
+ vty_out(vty, "%4d %23s %s\n", slno, cmt_info->cmtid_str,
cmt_info->time_str);
slno++;
}
diff --git a/mgmtd/mgmt_history.h b/mgmtd/mgmt_history.h
index 5f96cf90e1..d3f7958952 100644
--- a/mgmtd/mgmt_history.h
+++ b/mgmtd/mgmt_history.h
@@ -54,4 +54,42 @@ extern void mgmt_history_new_record(struct mgmt_ds_ctx *ds_ctx);
extern void mgmt_history_destroy(void);
extern void mgmt_history_init(void);
+/*
+ * 012345678901234567890123456789
+ * 2023-12-31T12:12:12,012345678
+ * 20231231121212012345678
+ */
+#define MGMT_LONG_TIME_FMT "%Y-%m-%dT%H:%M:%S"
+#define MGMT_LONG_TIME_MAX_LEN 30
+#define MGMT_SHORT_TIME_FMT "%Y%m%d%H%M%S"
+#define MGMT_SHORT_TIME_MAX_LEN 24
+
+static inline const char *
+mgmt_time_to_string(struct timespec *tv, bool long_fmt, char *buffer, size_t sz)
+{
+ struct tm tm;
+ size_t n;
+
+ localtime_r(&tv->tv_sec, &tm);
+
+ if (long_fmt) {
+ n = strftime(buffer, sz, MGMT_LONG_TIME_FMT, &tm);
+ snprintf(&buffer[n], sz - n, ",%09lu", tv->tv_nsec);
+ } else {
+ n = strftime(buffer, sz, MGMT_SHORT_TIME_FMT, &tm);
+ snprintf(&buffer[n], sz - n, "%09lu", tv->tv_nsec);
+ }
+
+ return buffer;
+}
+
+static inline const char *mgmt_realtime_to_string(struct timeval *tv, char *buf,
+ size_t sz)
+{
+ struct timespec ts = {.tv_sec = tv->tv_sec,
+ .tv_nsec = tv->tv_usec * 1000};
+
+ return mgmt_time_to_string(&ts, true, buf, sz);
+}
+
#endif /* _FRR_MGMTD_HISTORY_H_ */
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index 05844653ce..ad4a4e31f4 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -14,20 +14,10 @@
#include "mgmtd/mgmt_memory.h"
#include "mgmtd/mgmt_txn.h"
-#ifdef REDIRECT_DEBUG_TO_STDERR
-#define MGMTD_TXN_DBG(fmt, ...) \
- fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
-#define MGMTD_TXN_ERR(fmt, ...) \
- fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
-#else /* REDIRECT_DEBUG_TO_STDERR */
#define MGMTD_TXN_DBG(fmt, ...) \
- do { \
- if (mgmt_debug_txn) \
- zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
- } while (0)
-#define MGMTD_TXN_ERR(fmt, ...) \
+ DEBUGD(&mgmt_debug_txn, "%s:" fmt, __func__, ##__VA_ARGS__)
+#define MGMTD_TXN_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
-#endif /* REDIRECT_DEBUG_TO_STDERR */
#define MGMTD_TXN_LOCK(txn) mgmt_txn_lock(txn, __FILE__, __LINE__)
#define MGMTD_TXN_UNLOCK(txn) mgmt_txn_unlock(txn, __FILE__, __LINE__)
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index fa34d90c75..7d133d522f 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -380,7 +380,7 @@ DEFPY(mgmt_rollback,
return CMD_SUCCESS;
}
-static int config_write_mgmt_debug(struct vty *vty);
+int config_write_mgmt_debug(struct vty *vty);
static struct cmd_node debug_node = {
.name = "debug",
.node = DEBUG_NODE,
@@ -388,27 +388,25 @@ static struct cmd_node debug_node = {
.config_write = config_write_mgmt_debug,
};
-static int config_write_mgmt_debug_helper(struct vty *vty, bool config)
+static int write_mgmt_debug_helper(struct vty *vty, bool config)
{
- int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn;
+ uint32_t mode = config ? DEBUG_MODE_CONF : DEBUG_MODE_ALL;
+ bool be = DEBUG_MODE_CHECK(&mgmt_debug_be, mode);
+ bool ds = DEBUG_MODE_CHECK(&mgmt_debug_ds, mode);
+ bool fe = DEBUG_MODE_CHECK(&mgmt_debug_fe, mode);
+ bool txn = DEBUG_MODE_CHECK(&mgmt_debug_txn, mode);
- if (!n)
+ if (!(be || ds || fe || txn))
return 0;
- if (config && mgmt_debug_be && mgmt_debug_fe && mgmt_debug_ds &&
- mgmt_debug_txn) {
- vty_out(vty, "debug mgmt all\n");
- return 0;
- }
-
vty_out(vty, "debug mgmt");
- if (mgmt_debug_be)
+ if (be)
vty_out(vty, " backend");
- if (mgmt_debug_ds)
+ if (ds)
vty_out(vty, " datastore");
- if (mgmt_debug_fe)
+ if (fe)
vty_out(vty, " frontend");
- if (mgmt_debug_txn)
+ if (txn)
vty_out(vty, " transaction");
vty_out(vty, "\n");
@@ -416,17 +414,17 @@ static int config_write_mgmt_debug_helper(struct vty *vty, bool config)
return 0;
}
-static int config_write_mgmt_debug(struct vty *vty)
+int config_write_mgmt_debug(struct vty *vty)
{
- return config_write_mgmt_debug_helper(vty, true);
+ return write_mgmt_debug_helper(vty, true);
}
-DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
+DEFPY_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
"show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n")
{
vty_out(vty, "MGMT debugging status:\n");
- config_write_mgmt_debug_helper(vty, false);
+ write_mgmt_debug_helper(vty, false);
cmd_show_lib_debugs(vty);
@@ -434,27 +432,23 @@ DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
}
DEFPY(debug_mgmt, debug_mgmt_cmd,
- "[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>",
+ "[no$no] debug mgmt {backend$be|datastore$ds|frontend$fe|transaction$txn}",
NO_STR DEBUG_STR MGMTD_STR
- "All debug\n"
- "Back-end debug\n"
+ "Backend debug\n"
"Datastore debug\n"
- "Front-end debug\n"
+ "Frontend debug\n"
"Transaction debug\n")
{
- bool set = !no;
-
- if (all)
- be = fe = ds = txn = set ? all : NULL;
+ uint32_t mode = DEBUG_NODE2MODE(vty->node);
if (be)
- mgmt_debug_be = set;
+ DEBUG_MODE_SET(&mgmt_debug_be, mode, !no);
if (ds)
- mgmt_debug_ds = set;
+ DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no);
if (fe)
- mgmt_debug_fe = set;
+ DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no);
if (txn)
- mgmt_debug_txn = set;
+ DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no);
return CMD_SUCCESS;
}
@@ -530,6 +524,7 @@ void mgmt_vty_init(void)
install_element(ENABLE_NODE, &show_debugging_mgmt_cmd);
+ mgmt_fe_client_lib_vty_init();
/*
* TODO: Register and handlers for auto-completion here.
*/
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 09dd0081eb..1b4d26ef3d 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3996,16 +3996,15 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
/* Interface name is specified. */
ifp = if_lookup_by_name(intf_name, ospf->vrf_id);
if (ifp == NULL) {
- if (use_json)
+ if (use_json) {
json_object_boolean_true_add(json_vrf,
"noSuchIface");
- else
+ json_object_free(json_interface);
+ } else
vty_out(vty, "No such interface name\n");
} else {
- if (use_json) {
+ if (use_json)
json_interface_sub = json_object_new_object();
- json_interface = json_object_new_object();
- }
show_ip_ospf_interface_sub(
vty, ospf, ifp, json_interface_sub, use_json);
diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c
index 5eedfb7dca..aa39be63db 100644
--- a/pimd/pim6_mld.c
+++ b/pimd/pim6_mld.c
@@ -344,7 +344,8 @@ static const char *const gm_states[] = {
};
/* clang-format on */
-CPP_NOTICE("TODO: S,G entries in EXCLUDE (i.e. prune) unsupported");
+/* TODO: S,G entries in EXCLUDE (i.e. prune) unsupported" */
+
/* tib_sg_gm_prune() below is an "un-join", it doesn't prune S,G when *,G is
* joined. Whether we actually want/need to support this is a separate
* question - it is almost never used. In fact this is exactly what RFC5790
@@ -645,7 +646,7 @@ static void gm_handle_v2_pass1(struct gm_packet_state *pkt,
*/
gm_packet_sg_drop(old_grp);
gm_sg_update(grp, false);
- CPP_NOTICE("need S,G PRUNE => NO_INFO transition here");
+/* TODO "need S,G PRUNE => NO_INFO transition here" */
}
break;
@@ -793,7 +794,8 @@ static void gm_handle_v2_pass2_excl(struct gm_packet_state *pkt, size_t offs)
gm_sg_update(sg_grp, false);
}
-CPP_NOTICE("TODO: QRV/QQIC are not copied from queries to local state");
+/* TODO: QRV/QQIC are not copied from queries to local state" */
+
/* on receiving a query, we need to update our robustness/query interval to
* match, so we correctly process group/source specific queries after last
* member leaves
@@ -949,7 +951,8 @@ static void gm_handle_v1_report(struct gm_if *gm_ifp,
item = gm_packet_sg_setup(pkt, grp, true, false);
item->n_exclude = 0;
- CPP_NOTICE("set v1-seen timer on grp here");
+
+/* TODO "set v1-seen timer on grp here" */
/* } */
@@ -1012,7 +1015,9 @@ static void gm_handle_v1_leave(struct gm_if *gm_ifp,
if (old_grp) {
gm_packet_sg_drop(old_grp);
gm_sg_update(grp, false);
- CPP_NOTICE("need S,G PRUNE => NO_INFO transition here");
+
+/* TODO "need S,G PRUNE => NO_INFO transition here" */
+
}
}
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 4d5da31827..b64fcdeb87 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -46,7 +46,7 @@ int pim_mroute_set(struct pim_instance *pim, int enable)
/*
* We need to create the VRF table for the pim mroute_socket
*/
- if (pim->vrf->vrf_id != VRF_DEFAULT) {
+ if (enable && pim->vrf->vrf_id != VRF_DEFAULT) {
frr_with_privs (&pimd_privs) {
data = pim->vrf->data.l.table_id;
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 3d0ecb1bf4..1cd7cce086 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -29,6 +29,7 @@
#include "pim_jp_agg.h"
#include "pim_bfd.h"
#include "pim_register.h"
+#include "pim_oil.h"
static void dr_election_by_addr(struct interface *ifp)
{
@@ -123,9 +124,10 @@ int pim_if_dr_election(struct interface *ifp)
pim_if_update_could_assert(ifp);
pim_if_update_assert_tracking_desired(ifp);
- if (PIM_I_am_DR(pim_ifp))
+ if (PIM_I_am_DR(pim_ifp)) {
pim_ifp->am_i_dr = true;
- else {
+ pim_clear_nocache_state(pim_ifp);
+ } else {
if (pim_ifp->am_i_dr == true) {
pim_reg_del_on_couldreg_fail(ifp);
pim_ifp->am_i_dr = false;
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 63ddb85d00..e1ec9b34a1 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -149,6 +149,31 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
return c_oil;
}
+
+/*
+ * Clean up mroute and channel oil created for dropping pkts from directly
+ * connected source when the interface was non DR.
+ */
+void pim_clear_nocache_state(struct pim_interface *pim_ifp)
+{
+ struct channel_oil *c_oil;
+
+ frr_each_safe (rb_pim_oil, &pim_ifp->pim->channel_oil_head, c_oil) {
+
+ if ((!c_oil->up) ||
+ !(PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(c_oil->up->flags)))
+ continue;
+
+ if (*oil_parent(c_oil) != pim_ifp->mroute_vif_index)
+ continue;
+
+ EVENT_OFF(c_oil->up->t_ka_timer);
+ PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(c_oil->up->flags);
+ PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(c_oil->up->flags);
+ pim_upstream_del(pim_ifp->pim, c_oil->up, __func__);
+ }
+}
+
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
const char *name)
{
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 45b337cc72..dc66eaace4 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -182,6 +182,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
pim_sgaddr *sg);
struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
pim_sgaddr *sg, const char *name);
+void pim_clear_nocache_state(struct pim_interface *pim_ifp);
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
const char *name);
diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py
index c325979d24..6dd5c8866e 100644
--- a/python/xref2vtysh.py
+++ b/python/xref2vtysh.py
@@ -37,6 +37,8 @@ daemon_flags = {
"lib/filter_cli.c": "VTYSH_ACL",
"lib/if.c": "VTYSH_INTERFACE",
"lib/keychain.c": "VTYSH_RIPD|VTYSH_EIGRPD|VTYSH_OSPF6D",
+ "lib/mgmt_be_client.c": "VTYSH_STATICD",
+ "lib/mgmt_fe_client.c": "VTYSH_MGMTD",
"lib/lib_vty.c": "VTYSH_ALL",
"lib/log_vty.c": "VTYSH_ALL",
"lib/nexthop_group.c": "VTYSH_NH_GROUP",
diff --git a/ripd/rip_bfd.c b/ripd/rip_bfd.c
index ac5035f547..b59db11a30 100644
--- a/ripd/rip_bfd.c
+++ b/ripd/rip_bfd.c
@@ -13,6 +13,8 @@
#include "ripd/rip_bfd.h"
#include "ripd/rip_debug.h"
+DEFINE_MTYPE(RIPD, RIP_BFD_PROFILE, "RIP BFD profile name");
+
extern struct zclient *zclient;
static const char *rip_bfd_interface_profile(struct rip_interface *ri)
diff --git a/ripd/rip_bfd.h b/ripd/rip_bfd.h
index d49ca15153..7621498b15 100644
--- a/ripd/rip_bfd.h
+++ b/ripd/rip_bfd.h
@@ -9,6 +9,8 @@
#include "frrevent.h"
+DECLARE_MTYPE(RIP_BFD_PROFILE);
+
struct rip;
struct rip_interface;
struct rip_peer;
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index b383be042a..b58015a67d 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -25,6 +25,7 @@
#include "zebra/connected.h"
#include "ripd/ripd.h"
+#include "ripd/rip_bfd.h"
#include "ripd/rip_debug.h"
#include "ripd/rip_interface.h"
@@ -457,7 +458,7 @@ static void rip_interface_reset(struct rip_interface *ri)
ri->sent_updates = 0;
ri->passive = 0;
- XFREE(MTYPE_TMP, ri->bfd.profile);
+ XFREE(MTYPE_RIP_BFD_PROFILE, ri->bfd.profile);
rip_interface_clean(ri);
}
@@ -1110,9 +1111,10 @@ void rip_interface_sync(struct interface *ifp)
struct rip_interface *ri;
ri = ifp->info;
- ri->ifp = ifp;
- if (ri)
+ if (ri) {
ri->rip = ifp->vrf->info;
+ ri->ifp = ifp;
+ }
}
/* Called when interface structure allocated. */
diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c
index 8fe34705ca..5c7bd0fb86 100644
--- a/ripd/rip_nb_config.c
+++ b/ripd/rip_nb_config.c
@@ -25,8 +25,6 @@
#include "ripd/rip_interface.h"
#include "ripd/rip_bfd.h"
-DEFINE_MTYPE_STATIC(RIPD, RIP_BFD_PROFILE, "RIP BFD profile name");
-
/*
* XPath: /frr-ripd:ripd/instance
*/
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 48f266a94c..cb8dd4945d 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1171,6 +1171,12 @@ static void rip_response_process(struct rip_packet *packet, int size,
continue;
}
+ if (packet->version == RIPv1 && rte->tag != 0) {
+ zlog_warn("RIPv1 reserved field is nonzero: %d",
+ ntohs(rte->tag));
+ continue;
+ }
+
/* - is the destination address valid (e.g., unicast; not net 0
or 127) */
if (!rip_destination_check(rte->prefix)) {
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 386b255a85..3e58a44aa7 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -13,6 +13,7 @@
#include "nexthop.h"
#include "table.h"
#include "srcdest_table.h"
+#include "mgmt_be_client.h"
#include "mpls.h"
#include "northbound.h"
#include "libfrr.h"
@@ -1553,4 +1554,6 @@ void static_vty_init(void)
install_element(ENABLE_NODE, &debug_staticd_cmd);
install_element(CONFIG_NODE, &debug_staticd_cmd);
+
+ mgmt_be_client_lib_vty_init();
}
diff --git a/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf b/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf
index 2071c256da..e855f75c20 100644
--- a/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf
+++ b/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf
@@ -2,7 +2,9 @@ router bgp 65001
no bgp ebgp-requires-policy
neighbor 192.168.255.2 remote-as external
neighbor 192.168.255.2 timers 3 10
+ neighbor 192.168.255.2 timers connect 1
neighbor 192.168.255.2 bfd
+ neighbor 192.168.255.2 passive
address-family ipv4
redistribute connected
exit-address-family
diff --git a/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf b/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf
index 3279804e6e..faf2c6b39b 100644
--- a/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf
+++ b/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf
@@ -2,6 +2,7 @@ router bgp 65002
no bgp ebgp-requires-policy
neighbor 192.168.255.1 remote-as external
neighbor 192.168.255.1 timers 3 10
+ neighbor 192.168.255.1 timers connect 1
neighbor 192.168.255.1 bfd
address-family ipv4
redistribute connected
diff --git a/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py b/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py
index 0bc0306d7d..00142981c5 100644
--- a/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py
+++ b/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py
@@ -88,13 +88,14 @@ def test_bgp_bfd_down_notification():
expected = {
"192.168.255.1": {
"lastNotificationReason": "Cease/BFD Down",
+ "lastNotificationHardReset": True,
}
}
return topotest.json_cmp(output, expected)
step("Initial BGP converge")
test_func = functools.partial(_bgp_converge)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "Failed to see BGP convergence on R2"
step("Kill bfdd on R2")
@@ -102,7 +103,7 @@ def test_bgp_bfd_down_notification():
step("Check if we received Cease/BFD Down notification message")
test_func = functools.partial(_bgp_bfd_down_notification)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "Failed to see BGP Cease/BFD Down notification message on R2"
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf
new file mode 100644
index 0000000000..3459796629
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce1
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json
new file mode 100644
index 0000000000..d19e315772
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:1::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:1::/64": [
+ {
+ "prefix": "2001:1::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf
new file mode 100644
index 0000000000..bb5f93fe52
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf
@@ -0,0 +1,16 @@
+log file zebra.log
+!
+hostname ce1
+!
+interface eth0
+ ipv6 address 2001:1::2/64
+ ip address 192.168.1.2/24
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:1::1
+ip route 0.0.0.0/0 192.168.1.1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf
new file mode 100644
index 0000000000..8ed9978749
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce2
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json
new file mode 100644
index 0000000000..35ff14efad
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:2::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:2::/64": [
+ {
+ "prefix": "2001:2::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf
new file mode 100644
index 0000000000..a52b83f2dc
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf
@@ -0,0 +1,16 @@
+log file zebra.log
+!
+hostname ce2
+!
+interface eth0
+ ipv6 address 2001:2::2/64
+ ip address 192.168.2.2/24
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:2::1
+ip route 0.0.0.0/0 192.168.2.1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf
new file mode 100644
index 0000000000..a85d9701c7
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce3
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json
new file mode 100644
index 0000000000..2f2931f80f
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:3::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "prefix": "2001:3::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf
new file mode 100644
index 0000000000..beca0b1211
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce3
+!
+interface eth0
+ ipv6 address 2001:3::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:3::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf
new file mode 100644
index 0000000000..93fb32fd1b
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce4
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json
new file mode 100644
index 0000000000..8a98768e0d
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:4::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:4::/64": [
+ {
+ "prefix": "2001:4::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf
new file mode 100644
index 0000000000..7b21074df0
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce4
+!
+interface eth0
+ ipv6 address 2001:4::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:4::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf
new file mode 100644
index 0000000000..2ab6f2d2a7
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce5
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json
new file mode 100644
index 0000000000..80ff52ad6e
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:5::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:5::/64": [
+ {
+ "prefix": "2001:5::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf
new file mode 100644
index 0000000000..b5ad48e709
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce5
+!
+interface eth0
+ ipv6 address 2001:5::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:5::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf
new file mode 100644
index 0000000000..e0b6540514
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce6
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json
new file mode 100644
index 0000000000..ace6136f06
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:6::1",
+ "afi": "ipv6",
+ "interfaceName": "eth0",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "prefix": "2001:6::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth0",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf
new file mode 100644
index 0000000000..7d19d9880b
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce6
+!
+interface eth0
+ ipv6 address 2001:6::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:6::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf
new file mode 100644
index 0000000000..bfc9db960a
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf
@@ -0,0 +1,79 @@
+frr defaults traditional
+!
+hostname r1
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug bgp neighbor-events
+!debug bgp zebra
+!debug bgp vnc verbose
+!debug bgp update-groups
+!debug bgp updates in
+!debug bgp updates out
+!debug bgp vpn label
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!debug bgp vpn rmap-event
+!
+router bgp 1
+ bgp router-id 192.0.2.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001::2 remote-as 2
+ neighbor 2001::2 timers 3 10
+ neighbor 2001::2 timers connect 1
+ neighbor 2001::2 update-source 2001::1
+ neighbor 2001::2 capability extended-nexthop
+ !
+ address-family ipv4 vpn
+ neighbor 2001::2 activate
+ exit-address-family
+ !
+ address-family ipv6 vpn
+ neighbor 2001::2 activate
+ exit-address-family
+ !
+ segment-routing srv6
+ locator loc1
+ !
+!
+router bgp 1 vrf vrf10
+ bgp router-id 192.0.2.1
+ no bgp ebgp-requires-policy
+ !
+ address-family ipv6 unicast
+ sid vpn export auto
+ rd vpn export 1:10
+ rt vpn both 99:99
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+ address-family ipv4 unicast
+ network 192.168.1.0/24
+ sid vpn export auto
+ rd vpn export 11:10
+ rt vpn both 77:77
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+router bgp 1 vrf vrf20
+ bgp router-id 192.0.2.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export auto
+ rd vpn export 1:20
+ rt vpn both 88:88
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json
new file mode 100644
index 0000000000..6fc43e194d
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json
@@ -0,0 +1,169 @@
+{
+ "vrfName": "default",
+ "tableVersion": 2,
+ "routerId": "192.0.2.1",
+ "defaultLocPrf": 100,
+ "localAS": 1,
+ "routes": {
+ "routeDistinguishers": {
+ "1:10": {
+ "2001:1::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:1::",
+ "prefixLen": 64,
+ "network": "2001:1::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:3::",
+ "prefixLen": 64,
+ "network": "2001:3::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "1:20": {
+ "2001:5::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:5::",
+ "prefixLen": 64,
+ "network": "2001:5::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "2:10": {
+ "2001:2::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:2::",
+ "prefixLen": 64,
+ "network": "2001:2::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "2:20": {
+ "2001:4::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:4::",
+ "prefixLen": 64,
+ "network": "2001:4::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:6::",
+ "prefixLen": 64,
+ "network": "2001:6::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json
new file mode 100644
index 0000000000..9783c7e0e6
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json
@@ -0,0 +1,23 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json
new file mode 100644
index 0000000000..80c1acff8b
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json
@@ -0,0 +1,53 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "labels":[
+ 16
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:1::"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json
new file mode 100644
index 0000000000..9783c7e0e6
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json
@@ -0,0 +1,23 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json
new file mode 100644
index 0000000000..07ca64b45b
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json
@@ -0,0 +1,54 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"2001::2",
+ "afi":"ipv6",
+ "labels":[
+ 128
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:8::"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json
new file mode 100644
index 0000000000..6ac8dac25f
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json
@@ -0,0 +1,77 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json
new file mode 100644
index 0000000000..fac3d1d5f3
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json
@@ -0,0 +1,107 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "labels":[
+ 32
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:2::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json
new file mode 100644
index 0000000000..69ce312c4d
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json
@@ -0,0 +1,77 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json
new file mode 100644
index 0000000000..04e230535e
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json
@@ -0,0 +1,106 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "labels":[
+ 128
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:8::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json
new file mode 100644
index 0000000000..3cac156bb2
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json
@@ -0,0 +1,54 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"2001::2",
+ "afi":"ipv6",
+ "labels":[
+ 16
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:1::"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json
new file mode 100644
index 0000000000..163e9d626a
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json
@@ -0,0 +1,53 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"2001::2",
+ "afi":"ipv6",
+ "labels":[
+ 128
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:8::"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json
new file mode 100644
index 0000000000..1313f20c6c
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json
@@ -0,0 +1,106 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "labels":[
+ 16
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:1::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json
new file mode 100644
index 0000000000..51f249b184
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json
@@ -0,0 +1,106 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "labels":[
+ 128
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:8::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json
new file mode 100644
index 0000000000..6ac8dac25f
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json
@@ -0,0 +1,77 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json
new file mode 100644
index 0000000000..1c3dad089d
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json
@@ -0,0 +1,22 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json
new file mode 100644
index 0000000000..9579bb15de
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json
@@ -0,0 +1,112 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 32
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:2::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json
new file mode 100644
index 0000000000..25f146f4b7
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json
@@ -0,0 +1,106 @@
+{
+ "2001:4::\/64":[
+ {
+ "prefix":"2001:4::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 48
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:3::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:5::\/64":[
+ {
+ "prefix":"2001:5::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:6::\/64":[
+ {
+ "prefix":"2001:6::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 48
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:2:2:3::"
+ }
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf
new file mode 100644
index 0000000000..cf31a5c11b
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf
@@ -0,0 +1,43 @@
+log file zebra.log
+!
+hostname r1
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
+!
+interface eth0
+ ipv6 address 2001::1/64
+!
+interface eth1 vrf vrf10
+ ipv6 address 2001:1::1/64
+ ip address 192.168.1.1/24
+!
+interface eth2 vrf vrf10
+ ipv6 address 2001:3::1/64
+!
+interface eth3 vrf vrf20
+ ipv6 address 2001:5::1/64
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix 2001:db8:1:1::/64 block-len 40 node-len 24 func-bits 16
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route 2001:db8:2:1::/64 2001::2
+ipv6 route 2001:db8:2:2::/64 2001::2
+ipv6 route 2001:db8:2:3::/64 2001::2
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf
new file mode 100644
index 0000000000..892a9f73e5
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf
@@ -0,0 +1,80 @@
+frr defaults traditional
+!
+hostname r2
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug bgp neighbor-events
+!debug bgp zebra
+!debug bgp vnc verbose
+!debug bgp update-groups
+!debug bgp updates in
+!debug bgp updates out
+!debug bgp updates
+!debug bgp vpn label
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!debug bgp vpn rmap-event
+!
+router bgp 2
+ bgp router-id 192.0.2.2
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001::1 remote-as 1
+ neighbor 2001::1 update-source 2001::2
+ neighbor 2001::1 timers 3 10
+ neighbor 2001::1 timers connect 1
+ neighbor 2001::1 capability extended-nexthop
+ !
+ address-family ipv4 vpn
+ neighbor 2001::1 activate
+ exit-address-family
+ !
+ address-family ipv6 vpn
+ neighbor 2001::1 activate
+ exit-address-family
+ !
+ segment-routing srv6
+ locator loc1
+ !
+!
+router bgp 2 vrf vrf10
+ bgp router-id 192.0.2.2
+ no bgp ebgp-requires-policy
+ !
+ address-family ipv6 unicast
+ sid vpn export auto
+ rd vpn export 2:10
+ rt vpn both 99:99
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+ address-family ipv4 unicast
+ network 192.168.2.0/24
+ sid vpn export auto
+ rd vpn export 22:10
+ rt vpn both 77:77
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+router bgp 2 vrf vrf20
+ bgp router-id 192.0.2.2
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export auto
+ rd vpn export 2:20
+ rt vpn both 88:88
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json
new file mode 100644
index 0000000000..538e8955ef
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json
@@ -0,0 +1,169 @@
+{
+ "vrfName": "default",
+ "tableVersion": 2,
+ "routerId": "192.0.2.2",
+ "defaultLocPrf": 100,
+ "localAS": 2,
+ "routes": {
+ "routeDistinguishers": {
+ "1:10": {
+ "2001:1::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:1::",
+ "prefixLen": 64,
+ "network": "2001:1::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:3::",
+ "prefixLen": 64,
+ "network": "2001:3::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "1:20": {
+ "2001:5::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:5::",
+ "prefixLen": 64,
+ "network": "2001:5::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "2:10": {
+ "2001:2::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:2::",
+ "prefixLen": 64,
+ "network": "2001:2::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "2:20": {
+ "2001:4::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:4::",
+ "prefixLen": 64,
+ "network": "2001:4::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:6::",
+ "prefixLen": 64,
+ "network": "2001:6::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json
new file mode 100644
index 0000000000..446bb8eb3c
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json
@@ -0,0 +1,106 @@
+{
+ "2001:1::\/64":[
+ {
+ "prefix":"2001:1::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 32
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:1:1:2::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:2::\/64":[
+ {
+ "prefix":"2001:2::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:3::\/64":[
+ {
+ "prefix":"2001:3::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf10",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 32
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:1:1:2::"
+ }
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf10",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":10,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json
new file mode 100644
index 0000000000..8bc2fc23f1
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json
@@ -0,0 +1,112 @@
+{
+ "2001:4::\/64":[
+ {
+ "prefix":"2001:4::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:5::\/64":[
+ {
+ "prefix":"2001:5::\/64",
+ "protocol":"bgp",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "afi":"ipv6",
+ "vrf":"default",
+ "active":true,
+ "labels":[
+ 48
+ ],
+ "weight":1,
+ "seg6local":{
+ "action":"unspec"
+ },
+ "seg6":{
+ "segs":"2001:db8:1:1:3::"
+ }
+ }
+ ]
+ }
+ ],
+ "2001:6::\/64":[
+ {
+ "prefix":"2001:6::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fe80::\/64":[
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ },
+ {
+ "prefix":"fe80::\/64",
+ "protocol":"connected",
+ "vrfName":"vrf20",
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":20,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf
new file mode 100644
index 0000000000..9771ee1cd7
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf
@@ -0,0 +1,43 @@
+log file zebra.log
+!
+hostname r2
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
+!
+interface eth0
+ ipv6 address 2001::2/64
+!
+interface eth1 vrf vrf10
+ ipv6 address 2001:2::1/64
+ ip address 192.168.2.1/24
+!
+interface eth2 vrf vrf20
+ ipv6 address 2001:4::1/64
+!
+interface eth3 vrf vrf20
+ ipv6 address 2001:6::1/64
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix 2001:db8:2:2::/64 block-len 40 node-len 24 func-bits 16
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route 2001:db8:1:1::/64 2001::1
+ipv6 route 2001:db8:1:2::/64 2001::1
+ipv6 route 2001:db8:1:3::/64 2001::1
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py
new file mode 100755
index 0000000000..cddcf6a9a1
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py
@@ -0,0 +1,453 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+#
+# Copyright 2023 6WIND S.A.
+# Authored by Dmytro Shytyi <dmytro.shytyi@6wind.com>
+#
+# 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.
+#
+
+import os
+import re
+import sys
+import json
+import functools
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from lib.common_config import required_linux_kernel_version
+
+
+def build_topo(tgen):
+ """
+ CE1 CE3 CE5
+ (eth0) (eth0) (eth0)
+ :2 :2 :2
+ | | |
+ 192.168.1.0 | |
+ /24 | |
+ 2001: 2001: 2001:
+ 1::/64 3::/64 5::/64
+ | | |
+ :1 :1 :1
+ +-(eth1)--(eth2)---(eth3)-+
+ | \ / | |
+ | (vrf10) (vrf20) |
+ | R1 |
+ +----------(eth0)---------+
+ :1
+ |
+ 2001::/64
+ |
+ :2
+ (eth0)
+ +----------(eth0)--------------+
+ | R2 |
+ | (vrf10) (vrf20) |
+ | / / \ |
+ +-(eth1)-----(eth2)-----(eth3)-+
+ :1 :1 :1
+ | | |
+ +------+ +------+ +------+
+ / 2001: \ / 2001: \ / 2001: \
+ / 2::/64 \ 4::/64 / \ 6::/64 /
+ /192.168.2.0| / \ /
+ \ /24 / \ | | |
+ +------+ +------+ +------+
+ | | |
+ :2 :2 :2
+ (eth0) (eth0) (eth0)
+ CE2 CE4 CE6
+ """
+
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("ce1")
+ tgen.add_router("ce2")
+ tgen.add_router("ce3")
+ tgen.add_router("ce4")
+ tgen.add_router("ce5")
+ tgen.add_router("ce6")
+
+ tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0")
+ tgen.add_link(tgen.gears["ce1"], tgen.gears["r1"], "eth0", "eth1")
+ tgen.add_link(tgen.gears["ce2"], tgen.gears["r2"], "eth0", "eth1")
+ tgen.add_link(tgen.gears["ce3"], tgen.gears["r1"], "eth0", "eth2")
+ tgen.add_link(tgen.gears["ce4"], tgen.gears["r2"], "eth0", "eth2")
+ tgen.add_link(tgen.gears["ce5"], tgen.gears["r1"], "eth0", "eth3")
+ tgen.add_link(tgen.gears["ce6"], tgen.gears["r2"], "eth0", "eth3")
+
+
+def setup_module(mod):
+ result = required_linux_kernel_version("5.11")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+ router_list = tgen.routers()
+ for i, (rname, router) in enumerate(tgen.routers().items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.gears["r1"].run("modprobe vrf")
+ tgen.gears["r1"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r1"].run("ip link set vrf10 up")
+ tgen.gears["r1"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r1"].run("ip link set vrf20 up")
+ tgen.gears["r1"].run("ip link set eth1 master vrf10")
+ tgen.gears["r1"].run("ip link set eth2 master vrf10")
+ tgen.gears["r1"].run("ip link set eth3 master vrf20")
+ tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.default.rp_filter=0")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.all.rp_filter=0")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.lo.rp_filter=0")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.eth0.rp_filter=0")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.eth1.rp_filter=0")
+ tgen.gears["r1"].run("sysctl net.ipv4.conf.vrf10.rp_filter=0")
+
+ tgen.gears["r2"].run("modprobe vrf")
+ tgen.gears["r2"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r2"].run("ip link set vrf10 up")
+ tgen.gears["r2"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r2"].run("ip link set vrf20 up")
+ tgen.gears["r2"].run("ip link set eth1 master vrf10")
+ tgen.gears["r2"].run("ip link set eth2 master vrf20")
+ tgen.gears["r2"].run("ip link set eth3 master vrf20")
+ tgen.gears["r2"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.default.rp_filter=0")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.all.rp_filter=0")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.lo.rp_filter=0")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.eth0.rp_filter=0")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.eth1.rp_filter=0")
+ tgen.gears["r2"].run("sysctl net.ipv4.conf.vrf10.rp_filter=0")
+ tgen.start_router()
+
+ # FOR DEVELOPER:
+ # If you want to stop some specific line and start interactive shell,
+ # please use tgen.mininet_cli() to start it.
+ # Example:
+ # tgen=get_topogen()
+ # tgen.mininet_cli()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def open_json_file(filename):
+ try:
+ with open(filename, "r") as f:
+ return json.load(f)
+ except IOError:
+ assert False, "Could not read file {}".format(filename)
+
+
+def check_ping(name, dest_addr, expect_connected):
+ def _check(name, dest_addr, match):
+ tgen = get_topogen()
+ output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
+ logger.info(output)
+ if match not in output:
+ return True
+
+ match = ", {} packet loss".format("0%" if expect_connected else "100%")
+ logger.info("[+] check {} {} {}".format(name, dest_addr, match))
+ tgen = get_topogen()
+ func = functools.partial(_check, name, dest_addr, match)
+ success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+ assert result is None, "Failed"
+
+
+def check_rib(name, cmd, expected_file):
+ def _check(name, cmd, expected_file):
+ logger.info("polling")
+ tgen = get_topogen()
+ router = tgen.gears[name]
+ output = json.loads(router.vtysh_cmd(cmd))
+ expected = open_json_file("{}/{}".format(CWD, expected_file))
+ return topotest.json_cmp(output, expected)
+
+ logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file))
+ tgen = get_topogen()
+ func = functools.partial(_check, name, cmd, expected_file)
+ success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+ assert result is None, "Failed"
+
+
+def test_rib():
+ check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib.json")
+ check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib.json")
+ check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_rib.json")
+ check_rib("r1", "show ipv6 route vrf vrf20 json", "r1/vrf20_rib.json")
+ check_rib("r2", "show ipv6 route vrf vrf10 json", "r2/vrf10_rib.json")
+ check_rib("r2", "show ipv6 route vrf vrf20 json", "r2/vrf20_rib.json")
+ check_rib("ce1", "show ipv6 route json", "ce1/ipv6_rib.json")
+ check_rib("ce2", "show ipv6 route json", "ce2/ipv6_rib.json")
+ check_rib("ce3", "show ipv6 route json", "ce3/ipv6_rib.json")
+ check_rib("ce4", "show ipv6 route json", "ce4/ipv6_rib.json")
+ check_rib("ce5", "show ipv6 route json", "ce5/ipv6_rib.json")
+ check_rib("ce6", "show ipv6 route json", "ce6/ipv6_rib.json")
+
+
+def test_ping():
+ check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:3::2", True)
+ check_ping("ce1", "2001:4::2", False)
+ check_ping("ce1", "2001:5::2", False)
+ check_ping("ce1", "2001:6::2", False)
+ check_ping("ce4", "2001:1::2", False)
+ check_ping("ce4", "2001:2::2", False)
+ check_ping("ce4", "2001:3::2", False)
+ check_ping("ce4", "2001:5::2", True)
+ check_ping("ce4", "2001:6::2", True)
+
+
+def test_sid_per_afv6_auto():
+ check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json")
+ check_ping("ce1", "2001:2::2", True)
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv6 unicast
+ no sid vpn export auto
+ """
+ )
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv6 unicast
+ sid vpn export auto
+ """
+ )
+ check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json")
+ check_ping("ce1", "2001:2::2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv6 unicast
+ no sid vpn export auto
+ """
+ )
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+
+
+def test_sid_per_afv6_manual():
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv6 unicast
+ sid vpn export 8
+ """
+ )
+
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv6 unicast
+ no sid vpn export 8
+ """
+ )
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+
+
+def test_sid_per_afv4_auto():
+ check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json")
+ check_ping("ce1", "192.168.2.2", True)
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv4 unicast
+ no sid vpn export auto
+ """
+ )
+
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", False)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv4 unicast
+ sid vpn export auto
+ """
+ )
+
+ check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json")
+ check_ping("ce1", "192.168.2.2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv4 unicast
+ no sid vpn export auto
+ """
+ )
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", False)
+
+
+def test_sid_per_afv4_manual():
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", False)
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv4 unicast
+ sid vpn export 8
+ """
+ )
+
+ check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_sid_rib.json")
+ check_ping("ce1", "192.168.2.2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ address-family ipv4 unicast
+ no sid vpn export 8
+ """
+ )
+ check_ping("ce1", "192.168.2.2", False)
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json"
+ )
+
+
+def test_sid_per_vrf_auto():
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ sid vpn per-vrf export auto
+ """
+ )
+
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_auto_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", True)
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_auto_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ no sid vpn per-vrf export auto
+ """
+ )
+
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", False)
+
+
+def test_sid_per_vrf_manual():
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", False)
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ sid vpn per-vrf export 8
+ """
+ )
+
+ check_rib(
+ "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_manual_sid_rib.json"
+ )
+ check_ping("ce1", "2001:2::2", True)
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_manual_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", True)
+
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2 vrf vrf10
+ no sid vpn per-vrf export 8
+ """
+ )
+
+ check_rib(
+ "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json"
+ )
+ check_ping("ce1", "192.168.2.2", False)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
index 4ab5b98c12..8700f12d63 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
@@ -1,6 +1,6 @@
frr defaults traditional
!
-!bgp send-extra-data zebra
+bgp send-extra-data zebra
!
hostname r2
password zebra
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 3583ce17ed..2d6138990e 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -236,7 +236,6 @@ class Topogen(object):
self.add_topology_from_dict(topodef)
def add_topology_from_dict(self, topodef):
-
keylist = (
topodef.keys()
if isinstance(topodef, OrderedDict)
@@ -869,7 +868,7 @@ class TopoRouter(TopoGear):
"conf t",
"log file {}.log debug".format(daemon),
"log commands",
- "log timestamp precision 3",
+ "log timestamp precision 6",
]
),
daemon=daemon,
@@ -919,7 +918,7 @@ class TopoRouter(TopoGear):
"conf t",
"log file {}.log debug".format(daemon),
"log commands",
- "log timestamp precision 3",
+ "log timestamp precision 6",
]
),
daemon=daemon,
@@ -1204,6 +1203,7 @@ class TopoExaBGP(TopoHost):
# Diagnostic function
#
+
# Disable linter branch warning. It is expected to have these here.
# pylint: disable=R0912
def diagnose_env_linux(rundir):
diff --git a/tests/topotests/ospf_basic_functionality/ospf_lan.json b/tests/topotests/ospf_basic_functionality/ospf_lan.json
index 126934c344..54863382b2 100644
--- a/tests/topotests/ospf_basic_functionality/ospf_lan.json
+++ b/tests/topotests/ospf_basic_functionality/ospf_lan.json
@@ -18,7 +18,7 @@
"ospf": {
"area": "0.0.0.3",
"hello_interval": 1,
- "dead_interval": 4,
+ "dead_interval": 10,
"priority": 98
}
},
@@ -27,7 +27,7 @@
"ospf": {
"area": "0.0.0.3",
"hello_interval": 1,
- "dead_interval": 4,
+ "dead_interval": 10,
"priority": 99
}
},
@@ -36,7 +36,7 @@
"ospf": {
"area": "0.0.0.3",
"hello_interval": 1,
- "dead_interval": 4,
+ "dead_interval": 10,
"priority": 0
}
},
@@ -45,7 +45,7 @@
"ospf": {
"area": "0.0.0.3",
"hello_interval": 1,
- "dead_interval": 4,
+ "dead_interval": 10,
"priority": 0
}
}
@@ -135,4 +135,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index e4a032018c..1358027f21 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -196,8 +196,10 @@ def test_ospf_lan_tc1_p0(request):
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- step("Configure DR priority 100 on R0 and clear ospf neighbors "
- "on all the routers.")
+ step(
+ "Configure DR priority 100 on R0 and clear ospf neighbors "
+ "on all the routers."
+ )
input_dict = {
"r0": {
@@ -233,8 +235,10 @@ def test_ospf_lan_tc1_p0(request):
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- step("Configure DR priority 150 on R0 and clear ospf neighbors "
- "on all the routers.")
+ step(
+ "Configure DR priority 150 on R0 and clear ospf neighbors "
+ "on all the routers."
+ )
input_dict = {
"r0": {
@@ -489,7 +493,7 @@ def test_ospf_lan_tc2_p0(request):
"s1": {
"ospf": {
"priority": 98,
- "timerDeadSecs": 4,
+ "timerDeadSecs": 10,
"area": "0.0.0.3",
"mcastMemberOspfDesignatedRouters": True,
"mcastMemberOspfAllRouters": True,
diff --git a/tests/topotests/ospf_metric_propagation/r1/frr.conf b/tests/topotests/ospf_metric_propagation/r1/frr.conf
index 9f388dbd0f..85230494dd 100644
--- a/tests/topotests/ospf_metric_propagation/r1/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r1/frr.conf
@@ -8,18 +8,18 @@ interface r1-eth0
ip address 10.0.1.1/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r1-eth1 vrf blue
ip address 10.0.10.1/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
!
interface r1-eth2 vrf green
ip address 10.0.91.1/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
!
router ospf
diff --git a/tests/topotests/ospf_metric_propagation/r2/frr.conf b/tests/topotests/ospf_metric_propagation/r2/frr.conf
index 469ae5da88..e67a374ff5 100644
--- a/tests/topotests/ospf_metric_propagation/r2/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r2/frr.conf
@@ -8,18 +8,18 @@ interface r2-eth0
ip address 10.0.1.2/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r2-eth1 vrf blue
ip address 10.0.20.2/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r2-eth2 vrf green
ip address 10.0.70.2/24
ip ospf cost 1000
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.2
diff --git a/tests/topotests/ospf_metric_propagation/r3/frr.conf b/tests/topotests/ospf_metric_propagation/r3/frr.conf
index 8dbbaf0fc4..175851d427 100644
--- a/tests/topotests/ospf_metric_propagation/r3/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r3/frr.conf
@@ -8,18 +8,18 @@ interface r3-eth0
ip address 10.0.3.3/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r3-eth1 vrf blue
ip address 10.0.30.3/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r3-eth2 vrf green
ip address 10.0.80.3/24
ip ospf cost 1000
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.3
diff --git a/tests/topotests/ospf_metric_propagation/r4/frr.conf b/tests/topotests/ospf_metric_propagation/r4/frr.conf
index af1005063b..70a47e34fa 100644
--- a/tests/topotests/ospf_metric_propagation/r4/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r4/frr.conf
@@ -8,17 +8,17 @@ interface r4-eth0
ip address 10.0.3.4/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r4-eth1 vrf blue
ip address 10.0.40.4/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface r4-eth2 vrf green
ip address 10.0.94.4/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.4
diff --git a/tests/topotests/ospf_metric_propagation/ra/frr.conf b/tests/topotests/ospf_metric_propagation/ra/frr.conf
index 0bc2ec5679..7be9e5c33e 100644
--- a/tests/topotests/ospf_metric_propagation/ra/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/ra/frr.conf
@@ -7,17 +7,17 @@ ip forwarding
interface ra-eth0
ip address 10.0.50.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface ra-eth1
ip address 10.0.10.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface ra-eth2
ip address 10.0.20.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.5
diff --git a/tests/topotests/ospf_metric_propagation/rb/frr.conf b/tests/topotests/ospf_metric_propagation/rb/frr.conf
index 6f540d125e..a7dbf82278 100644
--- a/tests/topotests/ospf_metric_propagation/rb/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/rb/frr.conf
@@ -7,17 +7,17 @@ ip forwarding
interface rb-eth0
ip address 10.0.50.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface rb-eth1
ip address 10.0.30.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface rb-eth2
ip address 10.0.40.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.6
diff --git a/tests/topotests/ospf_metric_propagation/rc/frr.conf b/tests/topotests/ospf_metric_propagation/rc/frr.conf
index 9fc0ef718f..f5a2ed7c4f 100644
--- a/tests/topotests/ospf_metric_propagation/rc/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/rc/frr.conf
@@ -7,12 +7,12 @@ ip forwarding
interface rc-eth0
ip address 10.0.70.7/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
interface rc-eth1
ip address 10.0.80.7/24
ip ospf hello-interval 1
- ip ospf dead-interval 3
+ ip ospf dead-interval 30
!
router ospf
ospf router-id 10.0.255.7
diff --git a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
index 709e07649b..4d78bd2372 100644
--- a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
+++ b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
@@ -71,7 +71,6 @@ def build_topo(tgen):
tgen.add_router("h1")
tgen.add_router("h2")
-
# Interconect router 1, 2
switch = tgen.add_switch("s1-2")
switch.add_link(tgen.gears["r1"])
@@ -127,6 +126,7 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r3"])
switch.add_link(tgen.gears["rc"])
+
def setup_module(mod):
logger.info("OSPF Metric Propagation:\n {}".format(TOPOLOGY))
@@ -148,8 +148,12 @@ def setup_module(mod):
for cmd in vrf_setup_cmds:
tgen.net["r{}".format(routern)].cmd(cmd)
for routern in range(1, 5):
- tgen.net["r{}".format(routern)].cmd("ip link set dev r{}-eth1 vrf blue up".format(routern))
- tgen.net["r{}".format(routern)].cmd("ip link set dev r{}-eth2 vrf green up".format(routern))
+ tgen.net["r{}".format(routern)].cmd(
+ "ip link set dev r{}-eth1 vrf blue up".format(routern)
+ )
+ tgen.net["r{}".format(routern)].cmd(
+ "ip link set dev r{}-eth2 vrf green up".format(routern)
+ )
for rname, router in router_list.items():
logger.info("Loading router %s" % rname)
@@ -181,7 +185,7 @@ def test_all_links_up():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -202,7 +206,7 @@ def test_link_1_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -216,6 +220,10 @@ def test_link_1_2_down():
pytest.skip("skipped because of router(s) failure")
tgen.net["r2"].cmd("ip link set dev r2-eth1 down")
+ tgen.net["r2"].cmd("ip link set dev r2-eth2 down")
+ # ospf dead-interval is set to 30 seconds, wait 35 seconds to clear the neighbor
+ sleep(35)
+ tgen.net["r2"].cmd("ip link set dev r2-eth2 up")
r1 = tgen.gears["r1"]
json_file = "{}/r1/show_ip_route-3.json".format(CWD)
@@ -223,7 +231,7 @@ def test_link_1_2_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -238,8 +246,8 @@ def test_link_1_2_3_down():
tgen.net["r3"].cmd("ip link set dev r3-eth0 down")
tgen.net["r3"].cmd("ip link set dev r3-eth1 down")
- # ospf dead-interval is set to 3 seconds, wait 5 seconds to clear the neighbor
- sleep(5)
+ # ospf dead-interval is set to 30 seconds, wait 35 seconds to clear the neighbor
+ sleep(35)
tgen.net["r3"].cmd("ip link set dev r3-eth0 up")
r1 = tgen.gears["r1"]
@@ -248,11 +256,12 @@ def test_link_1_2_3_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
+
def test_link_1_2_3_4_down():
"Test path R1 -> R2 -> Rc -> R3 -> R4"
tgen = get_topogen()
@@ -268,11 +277,12 @@ def test_link_1_2_3_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
+
def test_link_1_2_4_down():
"Test path R1 -> R2 -> Rc -> R3 -> R4"
tgen = get_topogen()
@@ -289,11 +299,12 @@ def test_link_1_2_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
+
def test_link_1_4_down():
"Test path R1 -> R2 -> Ra -> Rb -> R3 -> R4"
tgen = get_topogen()
@@ -310,7 +321,7 @@ def test_link_1_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -332,7 +343,7 @@ def test_link_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -354,7 +365,7 @@ def test_link_1_2_3_4_up():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 3a325df06c..fcb692b715 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -2323,8 +2323,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zlog_debug("RTM_DELLINK for %s(%u)", name,
ifp->ifindex);
- UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
-
if (IS_ZEBRA_IF_BOND(ifp))
zebra_l2if_update_bond(ifp, false);
if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
diff --git a/zebra/interface.c b/zebra/interface.c
index 496a85e676..231ddc51db 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -800,6 +800,8 @@ void if_delete_update(struct interface **pifp)
if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
if_handle_vrf_change(ifp, VRF_DEFAULT);
+ UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
+
/* Reset some zebra interface params to default values. */
zif = ifp->info;
if (zif) {
@@ -840,6 +842,9 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
/* This is to issue an UPDATE or a DELETE, as appropriate. */
zebra_interface_vrf_update_del(ifp, vrf_id);
+ if (if_is_vrf(ifp))
+ return;
+
/* update VRF */
if_update_to_new_vrf(ifp, vrf_id);
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index bf488ca316..49120c2877 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -3157,6 +3157,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
json_array_string_add(json_flags, "local");
if (es->flags & ZEBRA_EVPNES_REMOTE)
json_array_string_add(json_flags, "remote");
+ if (es->flags & ZEBRA_EVPNES_LOCAL &&
+ !(es->flags & ZEBRA_EVPNES_NON_DF))
+ json_array_string_add(json_flags, "df");
if (es->flags & ZEBRA_EVPNES_NON_DF)
json_array_string_add(json_flags, "nonDF");
if (es->flags & ZEBRA_EVPNES_BYPASS)
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 3bbcd38d1c..28b83ce8b6 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1532,11 +1532,15 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
seg6local_context2str(buf, sizeof(buf),
&nexthop->nh_srv6->seg6local_ctx,
nexthop->nh_srv6->seg6local_action);
- vty_out(vty, ", seg6local %s %s",
- seg6local_action2str(
- nexthop->nh_srv6->seg6local_action),
- buf);
- vty_out(vty, ", seg6 %pI6", &nexthop->nh_srv6->seg6_segs);
+ if (nexthop->nh_srv6->seg6local_action !=
+ ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ vty_out(vty, ", seg6local %s %s",
+ seg6local_action2str(
+ nexthop->nh_srv6->seg6local_action),
+ buf);
+ if (IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs, &in6addr_any))
+ vty_out(vty, ", seg6 %pI6",
+ &nexthop->nh_srv6->seg6_segs);
}
if (nexthop->weight)