summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_nexthop.h2
-rw-r--r--bgpd/bgp_nht.c19
-rw-r--r--bgpd/bgp_route.c1
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c90
-rw-r--r--docker/ubuntu-ci/Dockerfile1
-rw-r--r--lib/if.h2
-rw-r--r--lib/mgmt_be_client.c42
-rw-r--r--lib/mgmt_fe_client.c40
-rw-r--r--mgmtd/mgmt_be_adapter.c13
-rw-r--r--mgmtd/mgmt_be_adapter.h3
-rw-r--r--mgmtd/mgmt_fe_adapter.c11
-rw-r--r--mgmtd/mgmt_fe_adapter.h4
-rw-r--r--mgmtd/mgmt_vty.c10
-rw-r--r--ospf6d/ospf6_top.c144
-rw-r--r--tests/topotests/all_protocol_startup/r1/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf4
-rw-r--r--tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf2
-rw-r--r--tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf2
-rw-r--r--tests/topotests/bgp_features/r1/ospf6d.conf6
-rw-r--r--tests/topotests/bgp_features/r2/ospf6d.conf6
-rw-r--r--tests/topotests/bgp_features/r3/ospf6d.conf6
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf21
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf18
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf25
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf5
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf67
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf5
-rwxr-xr-xtests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py179
-rw-r--r--tests/topotests/lib/snmptest.py186
-rw-r--r--tests/topotests/mgmt_debug_flags/r1/frr.conf11
-rw-r--r--tests/topotests/mgmt_debug_flags/test_debug.py129
-rw-r--r--tests/topotests/ospf6_topo1/r1/ospf6d.conf4
-rw-r--r--tests/topotests/ospf6_topo1/r2/ospf6d.conf4
-rw-r--r--tests/topotests/ospf6_topo1/r3/ospf6d.conf6
-rw-r--r--tests/topotests/ospf6_topo1/r4/ospf6d.conf4
-rw-r--r--tests/topotests/ospf_topo1/r1/ospf6d.conf6
-rw-r--r--tests/topotests/ospf_topo1/r2/ospf6d.conf4
-rw-r--r--tests/topotests/ospf_topo1/r3/ospf6d.conf6
-rw-r--r--tests/topotests/ospf_topo1/r4/ospf6d.conf4
-rw-r--r--tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py17
-rw-r--r--zebra/connected.c26
-rw-r--r--zebra/if_netlink.c3
-rw-r--r--zebra/interface.c9
-rw-r--r--zebra/rib.h1
-rw-r--r--zebra/zapi_msg.c25
-rw-r--r--zebra/zebra_dplane.c15
-rw-r--r--zebra/zebra_dplane.h2
-rw-r--r--zebra/zebra_rib.c84
52 files changed, 869 insertions, 425 deletions
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 49cbbaf885..90e0074e35 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -26,6 +26,8 @@ PREDECL_RBTREE_UNIQ(bgp_nexthop_cache);
/* BGP nexthop cache value structure. */
struct bgp_nexthop_cache {
+ afi_t afi;
+
/* The ifindex of the outgoing interface *if* it's a v6 LL */
ifindex_t ifindex_ipv6_ll;
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 9a2166c86b..10c0382f6f 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -386,6 +386,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
bnc = bnc_find(tree, &p, srte_color, ifindex);
if (!bnc) {
bnc = bnc_new(tree, &p, srte_color, ifindex);
+ bnc->afi = afi;
bnc->bgp = bgp_nexthop;
if (BGP_DEBUG(nht, NHT))
zlog_debug("Allocated bnc %pFX(%d)(%u)(%s) peer %p",
@@ -1162,6 +1163,11 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc)
*/
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc)
{
+ struct bgp_nexthop_cache *import;
+ struct bgp_nexthop_cache *nexthop;
+
+ struct bgp *bgp = bnc->bgp;
+
/* Check if we have already registered */
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
return;
@@ -1171,6 +1177,19 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc)
return;
}
+ import = bnc_find(&bgp->import_check_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+ nexthop = bnc_find(&bgp->nexthop_cache_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+
+ /*
+ * If this entry has both a import and a nexthop entry
+ * then let's not send the unregister quite as of yet
+ * wait until we only have 1 left
+ */
+ if (import && nexthop)
+ return;
+
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 9283055d9d..125a39d807 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -7595,7 +7595,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
*/
aggregate->count = 0;
aggregate->incomplete_origin_count = 0;
- aggregate->incomplete_origin_count = 0;
aggregate->egp_origin_count = 0;
/* ORIGIN attribute: If at least one route among routes that are
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index 3b499271c8..48db73a343 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -446,6 +446,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
size_t afi_len;
long prefix_type = 0;
long peer_addr_type = 0;
+ long nrli_index = 1;
+ long cur_index = 0;
/* Bgp4V2AddressFamilyIdentifierTC limited to IPv6 */
if (name[namelen - 1] > IANA_AFI_IPV6)
@@ -455,12 +457,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
assert(IS_VALID_AFI(afi));
#define BGP_NLRI_ENTRY_OFFSET namelen
+#define BGP4V2_NLRI_V4_V4_OFFSET IN_ADDR_SIZE + IN_ADDR_SIZE + 5
+#define BGP4V2_NLRI_V4_V6_OFFSET IN_ADDR_SIZE + IN6_ADDR_SIZE + 5
+#define BGP4V2_NLRI_V6_V6_OFFSET IN6_ADDR_SIZE + IN6_ADDR_SIZE + 5
sockunion_init(&su);
if (exact) {
- if (*length - namelen != BGP_NLRI_ENTRY_OFFSET)
+ if (*length - namelen != BGP4V2_NLRI_V4_V4_OFFSET &&
+ *length - namelen != BGP4V2_NLRI_V4_V6_OFFSET &&
+ *length - namelen != BGP4V2_NLRI_V6_V6_OFFSET)
return NULL;
/* Set OID offset for prefix type */
@@ -504,12 +511,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
su.sin.sin_family = family;
/* get bgp4V2PeerRemoteAddr*/
- if (family == AF_INET)
+ if (family == AF_INET) {
oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr);
- else
+ offset += IN_ADDR_SIZE;
+ } else {
oid2in6_addr(offset, &su.sin6.sin6_addr);
+ offset += IN6_ADDR_SIZE;
+ }
- /* bgp4V2NlriIndex currently ignored */
+ /* bgp4V2NlriIndex */
+ nrli_index = *offset;
+ offset++;
/* Lookup node */
dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
@@ -517,8 +529,11 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
for (path = bgp_dest_get_bgp_path_info(dest); path;
path = path->next)
if (sockunion_same(&path->peer->connection->su,
- &su))
- return path;
+ &su)) {
+ cur_index++;
+ if (cur_index == nrli_index)
+ return path;
+ }
bgp_dest_unlock_node(dest);
}
@@ -573,7 +588,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
offsetlen--;
/* get node */
- dest = bgp_node_get(bgp->rib[afi][safi], addr);
+ dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
}
if (!dest)
@@ -593,10 +608,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
family = AF_INET6;
offset++;
- if (family == AF_INET)
+ if (family == AF_INET) {
oid2in_addr(offset, IN_ADDR_SIZE, &paddr.ip._v4_addr);
- else
+ offset += IN_ADDR_SIZE;
+ } else {
oid2in6_addr(offset, &paddr.ip._v6_addr);
+ offset += IN6_ADDR_SIZE;
+ }
+ /* get bgp4V2NlriIndex */
+ nrli_index = *offset;
+ offset++;
+
} else {
/* default case start with ipv4*/
if (afi == AFI_IP)
@@ -604,11 +626,13 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
else
family = AF_INET6;
memset(&paddr.ip, 0, sizeof(paddr.ip));
+ nrli_index = 1;
}
do {
min = NULL;
min_family = 0;
+ cur_index = 0;
for (path = bgp_dest_get_bgp_path_info(dest); path;
path = path->next) {
@@ -618,19 +642,44 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
if (path_family < family)
continue;
- if (family == AF_INET
- && IPV4_ADDR_CMP(&paddr.ip._v4_addr,
- &path->peer->connection->su.sin.sin_addr)
- >= 0)
+ if (family == AF_INET &&
+ IPV4_ADDR_CMP(&paddr.ip._v4_addr,
+ &path->peer->connection->su.sin
+ .sin_addr) > 0)
continue;
- else if (family == AF_INET6
- && IPV6_ADDR_CMP(
- &paddr.ip._v6_addr,
- &path->peer->connection->su.sin6.sin6_addr)
- >= 0)
+ else if (family == AF_INET6 &&
+ IPV6_ADDR_CMP(&paddr.ip._v6_addr,
+ &path->peer->connection->su.sin6
+ .sin6_addr) > 0)
continue;
- /* first valid path its the min*/
+ if (family == AF_INET &&
+ IPV4_ADDR_CMP(&paddr.ip._v4_addr,
+ &path->peer->connection->su.sin
+ .sin_addr) == 0) {
+ if (cur_index == nrli_index) {
+ min = path;
+ min_family = family;
+ nrli_index++;
+ break;
+ }
+ cur_index++;
+ continue;
+ } else if (family == AF_INET6 &&
+ IPV6_ADDR_CMP(&paddr.ip._v6_addr,
+ &path->peer->connection->su
+ .sin6.sin6_addr) == 0) {
+ if (cur_index == nrli_index) {
+ min = path;
+ min_family = family;
+ nrli_index++;
+ break;
+ }
+ cur_index++;
+ continue;
+ }
+
+ /* first valid path its the min peer addr*/
if (!min) {
min = path;
min_family = path_family;
@@ -706,7 +755,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
/* Encode bgp4V2NlriIndex*/
- *offset = 1;
+ *offset = nrli_index;
offset++;
*length = offset - name;
@@ -720,6 +769,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
}
memset(&paddr.ip, 0, sizeof(paddr.ip));
+ nrli_index = 1;
} while ((dest = bgp_route_next(dest)));
diff --git a/docker/ubuntu-ci/Dockerfile b/docker/ubuntu-ci/Dockerfile
index 939a43e4ea..1b3deb2750 100644
--- a/docker/ubuntu-ci/Dockerfile
+++ b/docker/ubuntu-ci/Dockerfile
@@ -45,6 +45,7 @@ RUN apt update && apt upgrade -y && \
apt-get install -y \
curl \
gdb \
+ kmod \
iproute2 \
iputils-ping \
liblua5.3-dev \
diff --git a/lib/if.h b/lib/if.h
index 560635f7c4..fd5f6f7502 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -434,6 +434,8 @@ struct connected {
#define ZEBRA_IFA_SECONDARY (1 << 0)
#define ZEBRA_IFA_PEER (1 << 1)
#define ZEBRA_IFA_UNNUMBERED (1 << 2)
+#define ZEBRA_IFA_NOPREFIXROUTE (1 << 3)
+
/* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
a peer address has been configured. If this flag is set,
the destination field must contain the peer address.
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index ef77be1f18..51eaeb92de 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -112,7 +112,11 @@ struct mgmt_be_client {
#define FOREACH_BE_TXN_IN_LIST(client_ctx, txn) \
frr_each_safe (mgmt_be_txns, &(client_ctx)->txn_head, (txn))
-struct debug mgmt_dbg_be_client = {0, "Management backend client operations"};
+struct debug mgmt_dbg_be_client = {
+ .desc = "Management backend client operations"
+};
+
+struct mgmt_be_client *mgmt_be_client;
static int mgmt_be_client_send_msg(struct mgmt_be_client *client_ctx,
Mgmtd__BeMessage *be_msg)
@@ -820,24 +824,28 @@ static int mgmt_be_client_notify_disconenct(struct msg_conn *conn)
* Debug Flags
*/
+static void mgmt_debug_client_be_set(uint32_t flags, bool set)
+{
+ DEBUG_FLAGS_SET(&mgmt_dbg_be_client, flags, set);
+
+ if (!mgmt_be_client)
+ return;
+
+ mgmt_be_client->client.conn.debug =
+ DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL);
+}
+
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);
+ mgmt_debug_client_be_set(DEBUG_NODE2MODE(vty->node), !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))
@@ -853,7 +861,8 @@ void mgmt_debug_be_client_show_debug(struct vty *vty)
}
static struct debug_callbacks mgmt_dbg_be_client_cbs = {
- .debug_set_all = mgmt_debug_client_be_set_all};
+ .debug_set_all = mgmt_debug_client_be_set
+};
static struct cmd_node mgmt_dbg_node = {
.name = "debug mgmt client backend",
@@ -867,8 +876,13 @@ struct mgmt_be_client *mgmt_be_client_create(const char *client_name,
uintptr_t user_data,
struct event_loop *event_loop)
{
- struct mgmt_be_client *client =
- XCALLOC(MTYPE_MGMTD_BE_CLIENT, sizeof(*client));
+ struct mgmt_be_client *client;
+
+ if (mgmt_be_client)
+ return NULL;
+
+ client = XCALLOC(MTYPE_MGMTD_BE_CLIENT, sizeof(*client));
+ mgmt_be_client = client;
/* Only call after frr_init() */
assert(running_config);
@@ -902,6 +916,8 @@ void mgmt_be_client_lib_vty_init(void)
void mgmt_be_client_destroy(struct mgmt_be_client *client)
{
+ assert(client == mgmt_be_client);
+
MGMTD_BE_CLIENT_DBG("Destroying MGMTD Backend Client '%s'",
client->name);
@@ -912,4 +928,6 @@ void mgmt_be_client_destroy(struct mgmt_be_client *client)
XFREE(MTYPE_MGMTD_BE_CLIENT_NAME, client->name);
XFREE(MTYPE_MGMTD_BE_CLIENT, client);
+
+ mgmt_be_client = NULL;
}
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index aab553049d..e99826761e 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -47,8 +47,11 @@ struct mgmt_fe_client {
#define FOREACH_SESSION_IN_LIST(client, session) \
frr_each_safe (mgmt_sessions, &(client)->sessions, (session))
-struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
+struct debug mgmt_dbg_fe_client = {
+ .desc = "Management frontend client operations"
+};
+struct mgmt_fe_client *mgmt_fe_client;
static inline const char *dsid2name(Mgmtd__DatastoreId id)
{
@@ -543,6 +546,16 @@ static int mgmt_fe_client_notify_disconnect(struct msg_conn *conn)
return _notify_connect_disconnect(client, false);
}
+static void mgmt_debug_client_fe_set(uint32_t mode, bool set)
+{
+ DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, mode, set);
+
+ if (!mgmt_fe_client)
+ return;
+
+ mgmt_fe_client->client.conn.debug =
+ DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL);
+}
DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
"[no] debug mgmt client frontend",
@@ -550,18 +563,11 @@ DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
"client\n"
"frontend\n")
{
- uint32_t mode = DEBUG_NODE2MODE(vty->node);
-
- DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no);
+ mgmt_debug_client_fe_set(DEBUG_NODE2MODE(vty->node), !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))
@@ -577,7 +583,8 @@ void mgmt_debug_fe_client_show_debug(struct vty *vty)
}
static struct debug_callbacks mgmt_dbg_fe_client_cbs = {
- .debug_set_all = mgmt_debug_client_fe_set_all};
+ .debug_set_all = mgmt_debug_client_fe_set
+};
static struct cmd_node mgmt_dbg_node = {
.name = "debug mgmt client frontend",
@@ -594,8 +601,13 @@ struct mgmt_fe_client *mgmt_fe_client_create(const char *client_name,
uintptr_t user_data,
struct event_loop *event_loop)
{
- struct mgmt_fe_client *client =
- XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client));
+ struct mgmt_fe_client *client;
+
+ if (mgmt_fe_client)
+ return NULL;
+
+ client = XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client));
+ mgmt_fe_client = client;
client->name = XSTRDUP(MTYPE_MGMTD_FE_CLIENT_NAME, client_name);
client->user_data = user_data;
@@ -692,6 +704,8 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client)
{
struct mgmt_fe_client_session *session;
+ assert(client == mgmt_fe_client);
+
MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
client->name);
@@ -702,4 +716,6 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client)
XFREE(MTYPE_MGMTD_FE_CLIENT_NAME, client->name);
XFREE(MTYPE_MGMTD_FE_CLIENT, client);
+
+ mgmt_fe_client = NULL;
}
diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c
index 0043c9d8e0..ed93244b83 100644
--- a/mgmtd/mgmt_be_adapter.c
+++ b/mgmtd/mgmt_be_adapter.c
@@ -668,6 +668,8 @@ struct msg_conn *mgmt_be_create_adapter(int conn_fd, union sockunion *from)
MGMTD_BE_MAX_NUM_MSG_WRITE, MGMTD_BE_MSG_MAX_LEN, adapter,
"BE-adapter");
+ adapter->conn->debug = DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL);
+
MGMTD_BE_ADAPTER_DBG("Added new MGMTD Backend adapter '%s'",
adapter->name);
@@ -677,8 +679,7 @@ struct msg_conn *mgmt_be_create_adapter(int conn_fd, union sockunion *from)
struct mgmt_be_client_adapter *
mgmt_be_get_adapter_by_id(enum mgmt_be_client_id id)
{
- return (id < MGMTD_BE_CLIENT_ID_MAX ? mgmt_be_adapters_by_id[id]
- : NULL);
+ return (id < MGMTD_BE_CLIENT_ID_MAX ? mgmt_be_adapters_by_id[id] : NULL);
}
struct mgmt_be_client_adapter *
@@ -687,6 +688,14 @@ mgmt_be_get_adapter_by_name(const char *name)
return mgmt_be_find_adapter_by_name(name);
}
+void mgmt_be_adapter_toggle_client_debug(bool set)
+{
+ struct mgmt_be_client_adapter *adapter;
+
+ FOREACH_ADAPTER_IN_LIST (adapter)
+ adapter->conn->debug = set;
+}
+
/*
* Get a full set of changes for all the config that an adapter is subscribed to
* receive.
diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h
index a818d658a9..e06ee115f0 100644
--- a/mgmtd/mgmt_be_adapter.h
+++ b/mgmtd/mgmt_be_adapter.h
@@ -149,6 +149,9 @@ mgmt_be_get_adapter_by_name(const char *name);
extern struct mgmt_be_client_adapter *
mgmt_be_get_adapter_by_id(enum mgmt_be_client_id id);
+/* Toggle debug on or off for connected clients. */
+extern void mgmt_be_adapter_toggle_client_debug(bool set);
+
/* Fetch backend adapter config. */
extern int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
struct nb_config_cbs **cfg_chgs);
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index 2b2471c901..d613b7467a 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -246,6 +246,14 @@ mgmt_session_id2ctx(uint64_t session_id)
return session;
}
+void mgmt_fe_adapter_toggle_client_debug(bool set)
+{
+ struct mgmt_fe_client_adapter *adapter;
+
+ FOREACH_ADAPTER_IN_LIST (adapter)
+ adapter->conn->debug = set;
+}
+
static struct mgmt_fe_session_ctx *
mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter,
uint64_t client_id)
@@ -1132,6 +1140,9 @@ struct msg_conn *mgmt_fe_create_adapter(int conn_fd, union sockunion *from)
MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN,
adapter, "FE-adapter");
+ adapter->conn->debug = DEBUG_MODE_CHECK(&mgmt_debug_fe,
+ DEBUG_MODE_ALL);
+
adapter->setcfg_stats.min_tm = ULONG_MAX;
adapter->cmt_stats.min_tm = ULONG_MAX;
MGMTD_FE_ADAPTER_DBG("Added new MGMTD Frontend adapter '%s'",
diff --git a/mgmtd/mgmt_fe_adapter.h b/mgmtd/mgmt_fe_adapter.h
index 1560916c85..1172262a45 100644
--- a/mgmtd/mgmt_fe_adapter.h
+++ b/mgmtd/mgmt_fe_adapter.h
@@ -149,4 +149,8 @@ mgmt_fe_get_session_commit_stats(uint64_t session_id);
extern void mgmt_fe_adapter_status_write(struct vty *vty, bool detail);
extern void mgmt_fe_adapter_perf_measurement(struct vty *vty, bool config);
extern void mgmt_fe_adapter_reset_perf_stats(struct vty *vty);
+
+/* Toggle debug on or off for connected clients. */
+extern void mgmt_fe_adapter_toggle_client_debug(bool set);
+
#endif /* _FRR_MGMTD_FE_ADAPTER_H_ */
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index 0f6df9f129..3116ccbaf7 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -438,12 +438,18 @@ DEFPY(debug_mgmt, debug_mgmt_cmd,
{
uint32_t mode = DEBUG_NODE2MODE(vty->node);
- if (be)
+ if (be) {
DEBUG_MODE_SET(&mgmt_debug_be, mode, !no);
+ mgmt_be_adapter_toggle_client_debug(
+ DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL));
+ }
if (ds)
DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no);
- if (fe)
+ if (fe) {
DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no);
+ mgmt_fe_adapter_toggle_client_debug(
+ DEBUG_MODE_CHECK(&mgmt_debug_fe, DEBUG_MODE_ALL));
+ }
if (txn)
DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no);
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index ef312cbe3a..63672a96e7 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -1070,148 +1070,6 @@ DEFUN (no_ospf6_distance_ospf6,
return CMD_SUCCESS;
}
-DEFUN_HIDDEN (ospf6_interface_area,
- ospf6_interface_area_cmd,
- "interface IFNAME area <A.B.C.D|(0-4294967295)>",
- "Enable routing on an IPv6 interface\n"
- IFNAME_STR
- "Specify the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- "OSPF6 area ID in decimal notation\n"
- )
-{
- VTY_DECLVAR_CONTEXT(ospf6, ospf6);
- int idx_ifname = 1;
- int idx_ipv4 = 3;
- struct ospf6_area *oa;
- struct ospf6_interface *oi;
- struct interface *ifp;
- uint32_t area_id;
- int format;
-
- vty_out(vty,
- "This command is deprecated, because it is not VRF-aware.\n");
- vty_out(vty,
- "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
-
- /* find/create ospf6 interface */
- ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
- oi = (struct ospf6_interface *)ifp->info;
- if (oi == NULL)
- oi = ospf6_interface_create(ifp);
- if (oi->area) {
- vty_out(vty, "%s already attached to Area %s\n",
- oi->interface->name, oi->area->name);
- return CMD_SUCCESS;
- }
-
- if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
- vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- oi->area_id = area_id;
- oi->area_id_format = format;
-
- oa = ospf6_area_lookup(area_id, ospf6);
- if (oa == NULL)
- oa = ospf6_area_create(area_id, ospf6, format);
-
- /* attach interface to area */
- listnode_add(oa->if_list, oi); /* sort ?? */
- oi->area = oa;
-
- SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
-
- /* ospf6 process is currently disabled, not much more to do */
- if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED))
- return CMD_SUCCESS;
-
- /* start up */
- ospf6_interface_enable(oi);
-
- /* If the router is ABR, originate summary routes */
- if (ospf6_check_and_set_router_abr(ospf6)) {
- ospf6_abr_enable_area(oa);
- ospf6_schedule_abr_task(oa->ospf6);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN_HIDDEN (no_ospf6_interface_area,
- no_ospf6_interface_area_cmd,
- "no interface IFNAME area <A.B.C.D|(0-4294967295)>",
- NO_STR
- "Disable routing on an IPv6 interface\n"
- IFNAME_STR
- "Specify the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- "OSPF6 area ID in decimal notation\n"
- )
-{
- VTY_DECLVAR_CONTEXT(ospf6, ospf6);
- int idx_ifname = 2;
- int idx_ipv4 = 4;
- struct ospf6_interface *oi;
- struct ospf6_area *oa;
- struct interface *ifp;
- uint32_t area_id;
-
- vty_out(vty,
- "This command is deprecated, because it is not VRF-aware.\n");
- vty_out(vty,
- "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
-
- /* find/create ospf6 interface */
- ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
-
- if (ifp == NULL) {
- vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
- return CMD_SUCCESS;
- }
-
- oi = (struct ospf6_interface *)ifp->info;
- if (oi == NULL) {
- vty_out(vty, "Interface %s not enabled\n", ifp->name);
- return CMD_SUCCESS;
- }
-
- /* parse Area-ID */
- if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1)
- area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10));
-
- /* Verify Area */
- if (oi->area == NULL) {
- vty_out(vty, "%s not attached to area %s\n",
- oi->interface->name, argv[idx_ipv4]->arg);
- return CMD_SUCCESS;
- }
-
- if (oi->area->area_id != area_id) {
- vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n",
- oi->interface->name, oi->area->name);
- return CMD_SUCCESS;
- }
-
- ospf6_interface_disable(oi);
-
- oa = oi->area;
- listnode_delete(oi->area->if_list, oi);
- oi->area = (struct ospf6_area *)NULL;
-
- /* Withdraw inter-area routes from this area, if necessary */
- if (oa->if_list->count == 0) {
- UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
- ospf6_abr_disable_area(oa);
- }
-
- oi->area_id = 0;
- oi->area_id_format = OSPF6_AREA_FMT_UNSET;
-
- return CMD_SUCCESS;
-}
-
DEFUN (ospf6_stub_router_admin,
ospf6_stub_router_admin_cmd,
"stub-router administrative",
@@ -2360,8 +2218,6 @@ void ospf6_top_init(void)
install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd);
- install_element(OSPF6_NODE, &ospf6_interface_area_cmd);
- install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd);
install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd);
install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
diff --git a/tests/topotests/all_protocol_startup/r1/ospf6d.conf b/tests/topotests/all_protocol_startup/r1/ospf6d.conf
index 33c26501ba..31c904b415 100644
--- a/tests/topotests/all_protocol_startup/r1/ospf6d.conf
+++ b/tests/topotests/all_protocol_startup/r1/ospf6d.conf
@@ -6,12 +6,12 @@ log file ospf6d.log
! debug ospf6 neighbor
!
interface r1-eth4
- ipv6 ospf6 hello-interval 1
+ ipv6 ospf6 area 0.0.0.0
+ ipv6 ospf6 hello-interval 1
!
router ospf6
ospf6 router-id 192.168.0.1
log-adjacency-changes
- interface r1-eth4 area 0.0.0.0
!
line vty
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf
index 98da8c2619..a8ce562da2 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf
@@ -6,12 +6,14 @@ hostname rt1
password 1
!
interface eth-rt2
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
ipv6 ospf6 bfd
!
interface eth-rt3
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
@@ -19,7 +21,5 @@ interface eth-rt3
!
router ospf6
ospf6 router-id 1.1.1.1
- interface eth-rt2 area 0.0.0.0
- interface eth-rt3 area 0.0.0.0
redistribute connected
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf
index 34b0902094..f04d017681 100644
--- a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf
@@ -5,19 +5,19 @@ hostname rt2
password 1
!
interface eth-rt1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
ipv6 ospf6 bfd
!
interface eth-rt5
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
!
router ospf6
ospf6 router-id 2.2.2.2
- interface eth-rt1 area 0.0.0.0
- interface eth-rt5 area 0.0.0.0
redistribute connected
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf
index 8ab4eee1d3..faf975497d 100644
--- a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf
@@ -5,19 +5,19 @@ hostname rt3
password 1
!
interface eth-rt1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
ipv6 ospf6 bfd
!
interface eth-rt4
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
!
router ospf6
ospf6 router-id 3.3.3.3
- interface eth-rt1 area 0.0.0.0
- interface eth-rt4 area 0.0.0.0
redistribute connected
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf
index 138b688140..c96093b98a 100644
--- a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf
@@ -5,18 +5,18 @@ hostname rt4
password 1
!
interface eth-rt3
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
!
interface eth-rt5
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
ipv6 ospf6 network broadcast
!
router ospf6
ospf6 router-id 4.4.4.4
- interface eth-rt3 area 0.0.0.0
- interface eth-rt5 area 0.0.0.0
redistribute connected
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf
index 6eb4fe59a8..6d40d17d50 100644
--- a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf
@@ -5,18 +5,18 @@ hostname rt5
password 1
!
interface eth-rt2
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
!
interface eth-rt4
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 8
!
router ospf6
ospf6 router-id 5.5.5.5
- interface eth-rt2 area 0.0.0.0
- interface eth-rt4 area 0.0.0.0
redistribute connected
!
diff --git a/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf b/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf
index 4ef28c39ca..948874c0e5 100644
--- a/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf
+++ b/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf
@@ -1,4 +1,5 @@
interface r4-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 bfd profile fast-tx
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -6,5 +7,4 @@ interface r4-eth1
router ospf6
ospf6 router-id 10.254.254.4
redistribute connected
- interface r4-eth1 area 0.0.0.0
!
diff --git a/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf b/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf
index 20b53cfc55..f6e8dc3b67 100644
--- a/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf
+++ b/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf
@@ -1,4 +1,5 @@
interface r5-eth0
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 bfd
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -6,5 +7,4 @@ interface r5-eth0
router ospf6
ospf6 router-id 10.254.254.5
redistribute connected
- interface r5-eth0 area 0.0.0.0
!
diff --git a/tests/topotests/bgp_features/r1/ospf6d.conf b/tests/topotests/bgp_features/r1/ospf6d.conf
index 9afc6f4919..3e6196ecaf 100644
--- a/tests/topotests/bgp_features/r1/ospf6d.conf
+++ b/tests/topotests/bgp_features/r1/ospf6d.conf
@@ -3,19 +3,19 @@ log file ospf6d.log
! debug ospf6 neighbor
!
interface r1-lo
+ ipv6 ospf6 area 0.0.0.0
!
interface r1-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 10
!
interface r1-eth2
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 10
!
router ospf6
ospf6 router-id 192.168.0.1
log-adjacency-changes
- interface r1-lo area 0.0.0.0
- interface r1-eth1 area 0.0.0.0
- interface r1-eth2 area 0.0.0.0
!
line vty
!
diff --git a/tests/topotests/bgp_features/r2/ospf6d.conf b/tests/topotests/bgp_features/r2/ospf6d.conf
index 7fe535651e..56aecd006c 100644
--- a/tests/topotests/bgp_features/r2/ospf6d.conf
+++ b/tests/topotests/bgp_features/r2/ospf6d.conf
@@ -3,19 +3,19 @@ log file ospf6d.log
! debug ospf6 neighbor
!
interface r2-lo
+ ipv6 ospf6 area 0.0.0.0
!
interface r2-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 5
!
interface r2-eth2
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 10
!
router ospf6
ospf6 router-id 192.168.0.2
log-adjacency-changes
- interface r2-lo area 0.0.0.0
- interface r2-eth1 area 0.0.0.0
- interface r2-eth2 area 0.0.0.0
!
line vty
!
diff --git a/tests/topotests/bgp_features/r3/ospf6d.conf b/tests/topotests/bgp_features/r3/ospf6d.conf
index 07325b69b0..f15b9d9ea5 100644
--- a/tests/topotests/bgp_features/r3/ospf6d.conf
+++ b/tests/topotests/bgp_features/r3/ospf6d.conf
@@ -3,19 +3,19 @@ log file ospf6d.log
! debug ospf6 neighbor
!
interface r3-lo
+ ipv6 ospf6 area 0.0.0.0
!
interface r3-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 5
!
interface r3-eth2
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 priority 5
!
router ospf6
ospf6 router-id 192.168.0.3
log-adjacency-changes
- interface r3-lo area 0.0.0.0
- interface r3-eth1 area 0.0.0.0
- interface r3-eth2 area 0.0.0.0
!
line vty
!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf
index d82a21e1f9..144466e418 100644
--- a/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf
@@ -1,24 +1,28 @@
!
+!debug bgp updates
+!
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
no bgp default ipv4-unicast
- neighbor 192.168.12.2 remote-as external
- neighbor 192.168.12.2 timers 1 3
- neighbor 192.168.12.2 timers connect 1
- neighbor 2001:db8::12:2 remote-as external
- neighbor 2001:db8::12:2 timers 1 3
- neighbor 2001:db8::12:2 timers connect 1
+ neighbor 192.168.12.4 remote-as external
+ neighbor 192.168.12.4 timers 1 3
+ neighbor 192.168.12.4 timers connect 1
+ neighbor 2001:db8::12:4 remote-as external
+ neighbor 2001:db8::12:4 timers 1 3
+ neighbor 2001:db8::12:4 timers connect 1
!
address-family ipv4 unicast
network 10.0.0.0/31 route-map p1
network 10.0.0.2/32 route-map p2
- neighbor 192.168.12.2 activate
+ neighbor 192.168.12.4 activate
+ neighbor 192.168.12.4 addpath-tx-all-paths
+ network 10.10.10.10/32
exit-address-family
address-family ipv6 unicast
network 2001:db8::1/128 route-map p1
network 2001:db8:1::/56 route-map p2
- neighbor 2001:db8::12:2 activate
+ neighbor 2001:db8::12:4 activate
exit-address-family
!
route-map p1 permit 10
@@ -28,4 +32,3 @@ route-map p2 permit 10
set metric 2
set origin incomplete
exit
-!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
index cf0013e1b7..55686f407a 100644
--- a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
@@ -5,18 +5,20 @@ router bgp 65002
no bgp ebgp-requires-policy
no bgp network import-check
no bgp default ipv4-unicast
- neighbor 192.168.12.1 remote-as external
- neighbor 192.168.12.1 timers 1 3
- neighbor 192.168.12.1 timers connect 1
- neighbor 2001:db8::12:1 remote-as external
- neighbor 2001:db8::12:1 timers 1 3
- neighbor 2001:db8::12:1 timers connect 1
+ neighbor 192.168.12.4 remote-as external
+ neighbor 192.168.12.4 timers 1 3
+ neighbor 192.168.12.4 timers connect 1
+ neighbor 2001:db8::12:4 remote-as external
+ neighbor 2001:db8::12:4 timers 1 3
+ neighbor 2001:db8::12:4 timers connect 1
!
address-family ipv4 unicast
- neighbor 192.168.12.1 activate
+ neighbor 192.168.12.4 activate
+ neighbor 192.168.12.4 addpath-tx-all-paths
+
exit-address-family
address-family ipv6 unicast
- neighbor 2001:db8::12:1 activate
+ neighbor 2001:db8::12:4 activate
exit-address-family
!
agentx
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf
new file mode 100644
index 0000000000..71dbda0bc1
--- /dev/null
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf
@@ -0,0 +1,25 @@
+!
+!debug bgp updates
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ no bgp default ipv4-unicast
+ neighbor 192.168.12.4 remote-as external
+ neighbor 192.168.12.4 timers 1 3
+ neighbor 192.168.12.4 timers connect 1
+ neighbor 2001:db8::12:4 remote-as external
+ neighbor 2001:db8::12:4 timers 1 3
+ neighbor 2001:db8::12:4 timers connect 1
+ !
+ address-family ipv4 unicast
+ neighbor 192.168.12.4 activate
+ neighbor 192.168.12.4 addpath-tx-all-paths
+ network 10.10.10.10/32
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor 2001:db8::12:4 activate
+ exit-address-family
+!
+agentx
+!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf
new file mode 100644
index 0000000000..398af65ffe
--- /dev/null
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf
@@ -0,0 +1,5 @@
+!
+interface r3-eth0
+ ip address 192.168.12.3/24
+ ipv6 address 2001:db8::12:3/64
+!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf
new file mode 100644
index 0000000000..5ebbde6703
--- /dev/null
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf
@@ -0,0 +1,67 @@
+!
+! debug bgp updates
+!
+router bgp 65004
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ no bgp default ipv4-unicast
+ neighbor 192.168.12.1 remote-as external
+ neighbor 192.168.12.1 timers 1 3
+ neighbor 192.168.12.1 timers connect 1
+ neighbor 192.168.12.2 remote-as external
+ neighbor 192.168.12.2 timers 1 3
+ neighbor 192.168.12.2 timers connect 1
+ neighbor 192.168.12.3 remote-as external
+ neighbor 192.168.12.3 timers 1 3
+ neighbor 192.168.12.3 timers connect 1
+ neighbor 2001:db8::12:1 remote-as external
+ neighbor 2001:db8::12:1 timers 1 3
+ neighbor 2001:db8::12:1 timers connect 1
+ neighbor 2001:db8::12:2 remote-as external
+ neighbor 2001:db8::12:2 timers 1 3
+ neighbor 2001:db8::12:2 timers connect 1
+ neighbor 2001:db8::12:3 remote-as external
+ neighbor 2001:db8::12:3 timers 1 3
+ neighbor 2001:db8::12:3 timers connect 1
+ !
+ address-family ipv4 unicast
+ network 10.0.0.0/31 route-map p1
+ network 10.0.0.2/32 route-map p2
+ neighbor 192.168.12.1 activate
+ neighbor 192.168.12.2 activate
+ neighbor 192.168.12.2 addpath-tx-all-paths
+ neighbor 192.168.12.2 route-map r2-import in
+ neighbor 192.168.12.2 route-map r2-export out
+! neighbor 192.168.12.2 soft-reconfiguration inbound
+ neighbor 192.168.12.3 activate
+ exit-address-family
+ address-family ipv6 unicast
+ network 2001:db8::1/128 route-map p1
+ network 2001:db8:1::/56 route-map p2
+ neighbor 2001:db8::12:1 activate
+ neighbor 2001:db8::12:2 activate
+ neighbor 2001:db8::12:2 addpath-tx-all-paths
+ neighbor 2001:db8::12:3 activate
+ exit-address-family
+
+
+ip prefix-list r2-toto permit any
+
+route-map r2-import permit 10
+ match ip address prefix-list r2-toto
+
+route-map r2-export permit 10
+ match ip address prefix-list r2-toto
+!
+route-map p1 permit 10
+ set metric 1
+exit
+route-map p2 permit 10
+ set metric 2
+ set origin incomplete
+exit
+
+
+
+agentx
+!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf
new file mode 100644
index 0000000000..092673b8a9
--- /dev/null
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf
@@ -0,0 +1,5 @@
+!
+interface rr-eth0
+ ip address 192.168.12.4/24
+ ipv6 address 2001:db8::12:4/64
+!
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py
index 14dadd4504..8cd49e3548 100755
--- a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py
@@ -32,10 +32,14 @@ pytestmark = [pytest.mark.bgpd, pytest.mark.snmp]
def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")
+ tgen.add_router("r3")
+ tgen.add_router("rr")
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["rr"])
def setup_module(mod):
@@ -57,14 +61,15 @@ def setup_module(mod):
"-M snmp",
)
- tgen.gears["r2"].load_config(
+ r2 = tgen.gears["r2"]
+ r2.load_config(
TopoRouter.RD_SNMP,
- os.path.join(CWD, "{}/snmpd.conf".format(rname)),
+ os.path.join(CWD, "{}/snmpd.conf".format(r2.name)),
"-Le -Ivacm_conf,usmConf,iquery -V -DAgentX",
)
- tgen.gears["r2"].load_config(
+ r2.load_config(
TopoRouter.RD_TRAP,
- os.path.join(CWD, "{}/snmptrapd.conf".format(rname)),
+ os.path.join(CWD, "{}/snmptrapd.conf".format(r2.name)),
" -On -OQ ",
)
@@ -81,27 +86,29 @@ def test_bgp_snmp_bgp4v2():
r1 = tgen.gears["r1"]
r2 = tgen.gears["r2"]
+ rr = tgen.gears["rr"]
def _bgp_converge_summary():
output = json.loads(r2.vtysh_cmd("show bgp summary json"))
expected = {
"ipv4Unicast": {
"peers": {
- "192.168.12.1": {
+ "192.168.12.4": {
"state": "Established",
- "pfxRcd": 2,
+ "pfxRcd": 6,
}
}
},
"ipv6Unicast": {
"peers": {
- "2001:db8::12:1": {
+ "2001:db8::12:4": {
"state": "Established",
- "pfxRcd": 2,
+ "pfxRcd": 4,
}
}
},
}
+ # tgen.mininet_cli()
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_converge_summary)
@@ -144,6 +151,7 @@ def test_bgp_snmp_bgp4v2():
}
},
}
+ # tgen.mininet_cli()
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_converge_prefixes)
@@ -154,11 +162,12 @@ def test_bgp_snmp_bgp4v2():
def _snmpwalk_remote_addr():
expected = {
- "1.3.6.1.3.5.1.1.2.1.5.1.1.192.168.12.1": "C0 A8 0C 01",
- "1.3.6.1.3.5.1.1.2.1.5.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "20 01 0D B8 00 00 00 00 00 00 00 00 00 12 00 01",
+ "1.3.6.1.3.5.1.1.2.1.5.1.1.192.168.12.4": "C0 A8 0C 04",
+ "1.3.6.1.3.5.1.1.2.1.5.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "20 01 0D B8 00 00 00 00 00 00 00 00 00 12 00 04",
}
# bgp4V2PeerRemoteAddr
+ # tgen.mininet_cli()
output, _ = snmp.walk(".1.3.6.1.3.5.1.1.2.1.5")
return output == expected
@@ -168,8 +177,8 @@ def test_bgp_snmp_bgp4v2():
def _snmpwalk_peer_state():
expected = {
- "1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1": "6",
- "1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "6",
+ "1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.4": "6",
+ "1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "6",
}
# bgp4V2PeerState
@@ -182,8 +191,8 @@ def test_bgp_snmp_bgp4v2():
def _snmpwalk_peer_last_error_code_received():
expected = {
- "1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1": "0",
- "1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "0",
+ "1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.4": "0",
+ "1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "0",
}
# bgp4V2PeerLastErrorCodeReceived
@@ -198,14 +207,19 @@ def test_bgp_snmp_bgp4v2():
def _snmpwalk_origin():
expected = {
- "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1",
- "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "3",
- "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1",
- "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "3",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.10.10.10.32.1.192.168.12.4.1": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.10.10.10.32.1.192.168.12.4.2": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.4.1": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.4.2": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.4.1": "3",
+ "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.4.2": "3",
+ "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "1",
+ "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "3",
+ "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "3",
}
# bgp4V2NlriOrigin
- # tgen.mininet_cli()
output, _ = snmp.walk(".1.3.6.1.3.5.1.1.9.1.9")
return output == expected
@@ -215,10 +229,16 @@ def test_bgp_snmp_bgp4v2():
def _snmpwalk_med():
expected = {
- "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1",
- "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "2",
- "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1",
- "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "2",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.10.10.10.32.1.192.168.12.4.1": "0",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.10.10.10.32.1.192.168.12.4.2": "0",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.4.1": "1",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.4.2": "0",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.4.1": "2",
+ "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.4.2": "0",
+ "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "1",
+ "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "0",
+ "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "2",
+ "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "0",
}
# bgp4V2NlriMed
@@ -230,96 +250,65 @@ def test_bgp_snmp_bgp4v2():
assertmsg = "Can't fetch SNMP for bgp4V2NlriMed"
assert result, assertmsg
+ #
+ # traps
+ #
+
+ #
+ # bgp4 traps
+ #
def _snmptrap_ipv4():
- expected = [
- ("1.3.6.1.2.1.15.3.1.7.192.168.12.1", "192.168.12.1"),
- ("1.3.6.1.2.1.15.3.1.14.192.168.12.1", '"06 04 "'),
- ("1.3.6.1.2.1.15.3.1.2.192.168.12.1", "7"),
- ("1.3.6.1.2.1.15.3.1.7.192.168.12.1", "192.168.12.1"),
- ("1.3.6.1.2.1.15.3.1.14.192.168.12.1", '"06 04 "'),
- ("1.3.6.1.2.1.15.3.1.2.192.168.12.1", "6"),
- ]
-
- # load trapd resulting file
- # tgen.mininet_cli()
+ def __get_notif_bgp4_in_trap_file(router):
+ snmptrapfile = "{}/{}/snmptrapd.log".format(router.logdir, router.name)
+ outputfile = open(snmptrapfile).read()
+ output = snmp.get_notif_bgp4(outputfile)
- snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name)
- outputfile = open(snmptrapfile).read()
- output = snmp.trap(outputfile)
- return output == expected
+ return output
+
+ output = __get_notif_bgp4_in_trap_file(r2)
+ logger.info("output bgp4")
+ logger.info(output)
+ return snmp.is_notif_bgp4_valid(output, "192.168.12.4")
# skip tests is SNMP not installed
if not os.path.isfile("/usr/sbin/snmptrapd"):
error_msg = "SNMP not installed - skipping"
pytest.skip(error_msg)
- snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name)
- trap_file = open(snmptrapfile, "w")
- trap_file.truncate(0)
- trap_file.close()
- r1.vtysh_cmd("clear bgp *")
+ rr.vtysh_cmd("clear bgp *")
_, result = topotest.run_and_expect(_snmptrap_ipv4, True, count=2, wait=10)
assertmsg = "Can't fetch SNMP trap for ipv4"
assert result, assertmsg
+ #
+ # bgp4v2 traps
+ #
def _snmptrap_ipv6():
- expected = [
- ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "7"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"),
- ("1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1", "6"),
- ("1.3.6.1.3.5.1.1.3.1.2.1.1.192.168.12.1", "4"),
- ("1.3.6.1.3.5.1.1.3.1.4.1.1.192.168.12.1", '"00 "'),
- ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "7"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"),
- ("1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"),
- ("1.3.6.1.3.5.1.1.3.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "4"),
- (
- "1.3.6.1.3.5.1.1.3.1.4.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1",
- '"00 "',
- ),
- ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "6"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"),
- ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"),
- ]
-
- expected2 = [
- ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "7"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"),
- ("1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"),
- ("1.3.6.1.3.5.1.1.3.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "4"),
- (
- "1.3.6.1.3.5.1.1.3.1.4.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1",
- '"00 "',
- ),
- ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "7"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"),
- ("1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1", "6"),
- ("1.3.6.1.3.5.1.1.3.1.2.1.1.192.168.12.1", "4"),
- ("1.3.6.1.3.5.1.1.3.1.4.1.1.192.168.12.1", '"00 "'),
- ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "6"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"),
- ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"),
- ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"),
- ]
-
- # load trapd resulting file
- # tgen.mininet_cli()
+ def __get_notif_bgp4v2_in_trap_file(router):
+ snmptrapfile = "{}/{}/snmptrapd.log".format(router.logdir, router.name)
+ outputfile = open(snmptrapfile).read()
+ output = snmp.get_notif_bgp4v2(outputfile)
- snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name)
- outputfile = open(snmptrapfile).read()
- output = snmp.trap(outputfile)
+ return output
+
+ # tgen.mininet_cli()
+ output = __get_notif_bgp4v2_in_trap_file(r2)
+ logger.info("output bgp4v2")
logger.info(output)
- output_cut = output[:14]
- return output_cut == expected or output_cut == expected2
+ p_ipv4_addr = "1.192.168.12.4"
+ p_ipv6_addr = "2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4"
+ return (
+ snmp.is_notif_bgp4v2_valid(output, p_ipv4_addr, "Estab")
+ and snmp.is_notif_bgp4v2_valid(output, p_ipv6_addr, "Estab")
+ and snmp.is_notif_bgp4v2_valid(output, p_ipv4_addr, "Backward")
+ and snmp.is_notif_bgp4v2_valid(output, p_ipv6_addr, "Backward")
+ )
- snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name)
- trap_file = open(snmptrapfile, "w")
- trap_file.truncate(0)
- trap_file.close()
+ sleep(10)
r2.vtysh_cmd("conf\nbgp snmp traps bgp4-mibv2")
r2.vtysh_cmd("conf\nno bgp snmp traps rfc4273")
- r1.vtysh_cmd("clear bgp *")
+ rr.vtysh_cmd("clear bgp *")
+ sleep(30)
_, result = topotest.run_and_expect(_snmptrap_ipv6, True, count=2, wait=10)
assertmsg = "Can't fetch SNMP trap for ipv6"
assert result, assertmsg
diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py
index 598ad05f58..5c4e97a5d2 100644
--- a/tests/topotests/lib/snmptest.py
+++ b/tests/topotests/lib/snmptest.py
@@ -73,39 +73,6 @@ class SnmpTester(object):
# third token onwards is the value of the object
return tokens[0].split(".", 1)[1]
- def _parse_notification_trap(self, snmp_out):
- # we use the "=" as separator thus we will have
- # element of list formated "value oid"
- # value for index i is corresponding to index i-1
- results = snmp_out.strip().split("=")
-
- # remove the notification part date, notification OID
- del results[0:2]
-
- index = 0
- oid_list = []
- next_oid = ""
- oid = ""
- while index < len(results):
- result = results[index].strip().split()
- if index < len(results) - 1:
- raw_oid = result[-1]
- # remove initial "." of oid
- next_oid = raw_oid.split(".", 1)[1]
- # remove oid from result to have only value
- del result[-1]
- if index > 0:
- value = " ".join(result)
- # ignore remote port oid 1.3.6.1.3.5.1.1.2.1.9 since
- # it's value is variable
- local_port = re.search("1.3.6.1.3.5.1.1.2.1.9", oid)
- if not local_port:
- oid_list.append((oid, value))
-
- oid = next_oid
- index += 1
- return oid_list
-
def _parse_multiline(self, snmp_output):
results = snmp_output.strip().split("\n")
@@ -117,15 +84,6 @@ class SnmpTester(object):
return out_dict, out_list
- def _parse_multiline_trap(self, results):
- out_list = []
- results = [elem for index, elem in enumerate(results) if index % 2 != 0]
-
- for response in results:
- oid_list = self._parse_notification_trap(response)
- out_list += oid_list
- return out_list
-
def get(self, oid):
cmd = "snmpget {0} {1}".format(self._snmp_config(), oid)
@@ -149,10 +107,148 @@ class SnmpTester(object):
result = self.router.cmd(cmd)
return self._parse_multiline(result)
- def trap(self, outputfile):
- whitecleanfile = re.sub("\t", " ", outputfile)
+ def parse_notif_ipv4(self, notif):
+ # normalise values
+ notif = re.sub(":", "", notif)
+ notif = re.sub('"([0-9]{2}) ([0-9]{2}) "', r"\1\2", notif)
+ notif = re.sub('"([0-9]{2}) "', r"\1", notif)
+ elems = re.findall("([0-9,\.]+) = ([0-9,\.]+)", notif)
+
+ # remove common part
+ elems = elems[1:]
+ return elems
+
+ def is_notif_bgp4_valid(self, output_list, address):
+ oid_notif_type = ".1.3.6.1.6.3.1.1.4.1.0"
+ peer_notif_established = ".1.3.6.1.2.1.15.0.1"
+ peer_notif_backward = ".1.3.6.1.2.1.15.0.2"
+ oid_peer_last_error = ".1.3.6.1.2.1.15.3.1.14"
+ oid_peer_remote_addr = ".1.3.6.1.2.1.15.3.1.7"
+ oid_peer_state = ".1.3.6.1.2.1.15.3.1.2"
+
+ nb_notif = len(output_list)
+ for nb in range(0, nb_notif - 1):
+ # identify type of notification
+ # established or BackwardTransition
+
+ if output_list[nb][0][0] != "{}".format(oid_notif_type):
+ return False
+
+ if output_list[nb][0][1] == "{}".format(peer_notif_established):
+ logger.info("Established notification")
+ elif output_list[nb][0][1] == "{}".format(peer_notif_backward):
+ logger.info("Backward transition notification")
+ else:
+ return False
+
+ # same behavior for 2 notification type in bgp4
+ if output_list[nb][1][0] != "{}.{}".format(oid_peer_remote_addr, address):
+ return False
+
+ if output_list[nb][2][0] != "{}.{}".format(oid_peer_last_error, address):
+ return False
+ if output_list[nb][3][0] != "{}.{}".format(oid_peer_state, address):
+ return False
+
+ return True
+
+ def is_notif_bgp4v2_valid(self, output_list, address, type_requested):
+ oid_notif_type = ".1.3.6.1.6.3.1.1.4.1.0"
+ peer_notif_established = ".1.3.6.1.3.5.1.0.1"
+ peer_notif_backward = ".1.3.6.1.3.5.1.0.2"
+ oid_peer_state = ".1.3.6.1.3.5.1.1.2.1.13"
+ oid_peer_local_port = ".1.3.6.1.3.5.1.1.2.1.6"
+ oid_peer_remote_port = ".1.3.6.1.3.5.1.1.2.1.9"
+ oid_peer_err_code_recv = ".1.3.6.1.3.5.1.1.3.1.1"
+ oid_peer_err_sub_code_recv = ".1.3.6.1.3.5.1.1.3.1.2"
+ oid_peer_err_recv_text = ".1.3.6.1.3.5.1.1.3.1.4"
+
+ nb_notif = len(output_list)
+ for nb in range(nb_notif):
+ if output_list[nb][0][0] != "{}".format(oid_notif_type):
+ return False
+
+ if output_list[nb][0][1] == "{}".format(peer_notif_established):
+ logger.info("Established notification")
+ notif_type = "Estab"
+
+ elif output_list[nb][0][1] == "{}".format(peer_notif_backward):
+ logger.info("Backward transition notification")
+ notif_type = "Backward"
+ else:
+ return False
+
+ if notif_type != type_requested:
+ continue
+
+ if output_list[nb][1][0] != "{}.1.{}".format(oid_peer_state, address):
+ continue
+
+ if output_list[nb][2][0] != "{}.1.{}".format(oid_peer_local_port, address):
+ return False
+
+ if output_list[nb][3][0] != "{}.1.{}".format(oid_peer_remote_port, address):
+ return False
+
+ if notif_type == "Estab":
+ return True
+
+ if output_list[nb][4][0] != "{}.1.{}".format(
+ oid_peer_err_code_recv, address
+ ):
+ return False
+
+ if output_list[nb][5][0] != "{}.1.{}".format(
+ oid_peer_err_sub_code_recv, address
+ ):
+ return False
+
+ if output_list[nb][6][0] != "{}.1.{}".format(
+ oid_peer_err_recv_text, address
+ ):
+ return False
+
+ return True
+
+ return False
+
+ def get_notif_bgp4(self, output_file):
+ notif_list = []
+ whitecleanfile = re.sub("\t", " ", output_file)
results = whitecleanfile.strip().split("\n")
- return self._parse_multiline_trap(results)
+
+ # don't consider SNMP additional messages
+ notifs_first = [elem for elem in results if not ("SNMP" in elem)]
+ # don't consider additional application messages
+ notifs = [elem for index, elem in enumerate(notifs_first) if index % 2 != 0]
+
+ oid_v4 = "1\.3\.6\.1\.2\.1\.15"
+ for one_notif in notifs:
+ is_ipv4_notif = re.search(oid_v4, one_notif)
+ if is_ipv4_notif != None:
+ formated_notif = self.parse_notif_ipv4(one_notif)
+ notif_list.append(formated_notif)
+
+ return notif_list
+
+ def get_notif_bgp4v2(self, output_file):
+ notif_list = []
+ whitecleanfile = re.sub("\t", " ", output_file)
+ results = whitecleanfile.strip().split("\n")
+
+ # don't consider SNMP additional messages
+ notifs_first = [elem for elem in results if not ("SNMP" in elem)]
+ # don't consider additional application messages
+ notifs = [elem for index, elem in enumerate(results) if index % 2 != 0]
+
+ oid_v6 = "1\.3\.6\.1\.3\.5\.1"
+ for one_notif in notifs:
+ is_ipv6_notif = re.search(oid_v6, one_notif)
+ if is_ipv6_notif != None:
+ formated_notif = self.parse_notif_ipv4(one_notif)
+ notif_list.append(formated_notif)
+
+ return notif_list
def test_oid(self, oid, value):
print("oid: {}".format(self.get_next(oid)))
diff --git a/tests/topotests/mgmt_debug_flags/r1/frr.conf b/tests/topotests/mgmt_debug_flags/r1/frr.conf
new file mode 100644
index 0000000000..ba95b8d493
--- /dev/null
+++ b/tests/topotests/mgmt_debug_flags/r1/frr.conf
@@ -0,0 +1,11 @@
+log timestamp precision 6
+log file frr.log
+
+! debug mgmt backend datastore frontend transaction
+! debug mgmt client frontend
+! debug mgmt client backend
+
+interface r1-eth0
+ ip address 1.1.1.1/24
+exit
+ip route 11.11.11.11/32 1.1.1.2 \ No newline at end of file
diff --git a/tests/topotests/mgmt_debug_flags/test_debug.py b/tests/topotests/mgmt_debug_flags/test_debug.py
new file mode 100644
index 0000000000..b0ab71e9bd
--- /dev/null
+++ b/tests/topotests/mgmt_debug_flags/test_debug.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2021, LabN Consulting, L.L.C.
+# Copyright (c) 2019-2020 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# noqa: E501
+#
+"""
+Test static route functionality
+"""
+import pytest
+from lib.common_config import step
+from lib.topogen import Topogen
+from munet.watchlog import WatchLog
+
+pytestmark = [pytest.mark.staticd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {"s1": ("r1",)}
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ for rname, router in tgen.routers().items():
+ router.load_frr_config("frr.conf")
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_client_debug_enable(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ # Start watching log files
+ watch_mgmtd_log = WatchLog(r1.net.rundir / "mgmtd.log")
+ watch_staticd_log = WatchLog(r1.net.rundir / "staticd.log")
+
+ def __test_debug(r1, on):
+ watch_mgmtd_log.snapshot()
+ watch_staticd_log.snapshot()
+
+ # Add ip route and remove look for debug.
+ r1.vtysh_cmd("conf t\nip route 11.11.11.11/32 1.1.1.2")
+ r1.vtysh_cmd("conf t\nno ip route 11.11.11.11/32 1.1.1.2")
+
+ new_mgmt_logs = watch_mgmtd_log.snapshot()
+ new_be_logs = watch_staticd_log.snapshot()
+
+ fe_cl_msg = "Sending SET_CONFIG_REQ"
+ fe_ad_msg = "Got SETCFG_REQ"
+ be_ad_msg = "Sending CFGDATA_CREATE_REQ"
+ be_cl_msg = "Got CFG_APPLY_REQ"
+
+ if on:
+ assert fe_cl_msg in new_mgmt_logs
+ assert fe_ad_msg in new_mgmt_logs
+ assert be_ad_msg in new_mgmt_logs
+ assert be_cl_msg in new_be_logs
+ else:
+ assert fe_cl_msg not in new_mgmt_logs
+ assert fe_ad_msg not in new_mgmt_logs
+ assert be_ad_msg not in new_mgmt_logs
+ assert be_cl_msg not in new_be_logs
+
+ step("test debug off")
+ __test_debug(r1, False)
+
+ # Turn it on
+ step("tests debug on")
+ r1.vtysh_cmd("debug mgmt client frontend")
+ r1.vtysh_cmd("debug mgmt client backend")
+ r1.vtysh_cmd("debug mgmt backend frontend")
+ __test_debug(r1, True)
+
+ # Turn it off
+ step("tests debug off")
+ r1.vtysh_cmd("no debug mgmt client frontend")
+ r1.vtysh_cmd("no debug mgmt client backend")
+ r1.vtysh_cmd("no debug mgmt backend frontend")
+ __test_debug(r1, False)
+
+ # Configure it on
+ step("tests debug on")
+ r1.vtysh_cmd("conf t\ndebug mgmt client frontend")
+ r1.vtysh_cmd("conf t\ndebug mgmt client backend")
+ r1.vtysh_cmd("conf t\ndebug mgmt backend frontend")
+ __test_debug(r1, True)
+
+ # Configure it off
+ step("tests debug off")
+ r1.vtysh_cmd("conf t\nno debug mgmt client frontend")
+ r1.vtysh_cmd("conf t\nno debug mgmt client backend")
+ r1.vtysh_cmd("conf t\nno debug mgmt backend frontend")
+ __test_debug(r1, False)
+
+ # Turn it on
+ step("tests debug on")
+ r1.vtysh_cmd("debug mgmt client frontend")
+ r1.vtysh_cmd("debug mgmt client backend")
+ r1.vtysh_cmd("debug mgmt backend frontend")
+ __test_debug(r1, True)
+ # Configure it on
+ step("tests debug on")
+ r1.vtysh_cmd("conf t\ndebug mgmt client frontend")
+ r1.vtysh_cmd("conf t\ndebug mgmt client backend")
+ r1.vtysh_cmd("conf t\ndebug mgmt backend frontend")
+ __test_debug(r1, True)
+ # Turn it off
+ step("tests debug on")
+ r1.vtysh_cmd("no debug mgmt client frontend")
+ r1.vtysh_cmd("no debug mgmt client backend")
+ r1.vtysh_cmd("no debug mgmt backend frontend")
+ __test_debug(r1, True)
+ # Configure it off
+ step("tests debug off")
+ r1.vtysh_cmd("conf t\nno debug mgmt client frontend")
+ r1.vtysh_cmd("conf t\nno debug mgmt client backend")
+ r1.vtysh_cmd("conf t\nno debug mgmt backend frontend")
+ __test_debug(r1, False)
diff --git a/tests/topotests/ospf6_topo1/r1/ospf6d.conf b/tests/topotests/ospf6_topo1/r1/ospf6d.conf
index 5f1ceee964..d2693ec07d 100644
--- a/tests/topotests/ospf6_topo1/r1/ospf6d.conf
+++ b/tests/topotests/ospf6_topo1/r1/ospf6d.conf
@@ -10,11 +10,13 @@ log file ospf6d.log
! debug ospf6 flooding
!
interface r1-stubnet
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r1-sw5
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -23,8 +25,6 @@ router ospf6
ospf6 router-id 10.0.0.1
log-adjacency-changes detail
redistribute static
- interface r1-stubnet area 0.0.0.0
- interface r1-sw5 area 0.0.0.0
!
line vty
exec-timeout 0 0
diff --git a/tests/topotests/ospf6_topo1/r2/ospf6d.conf b/tests/topotests/ospf6_topo1/r2/ospf6d.conf
index d51b41e1e5..c9e88f1545 100644
--- a/tests/topotests/ospf6_topo1/r2/ospf6d.conf
+++ b/tests/topotests/ospf6_topo1/r2/ospf6d.conf
@@ -10,11 +10,13 @@ log file ospf6d.log
! debug ospf6 flooding
!
interface r2-stubnet
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r2-sw5
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -23,8 +25,6 @@ router ospf6
ospf6 router-id 10.0.0.2
log-adjacency-changes detail
redistribute static
- interface r2-stubnet area 0.0.0.0
- interface r2-sw5 area 0.0.0.0
!
line vty
exec-timeout 0 0
diff --git a/tests/topotests/ospf6_topo1/r3/ospf6d.conf b/tests/topotests/ospf6_topo1/r3/ospf6d.conf
index cad71ac067..e1c3e44d0e 100644
--- a/tests/topotests/ospf6_topo1/r3/ospf6d.conf
+++ b/tests/topotests/ospf6_topo1/r3/ospf6d.conf
@@ -10,16 +10,19 @@ log file ospf6d.log
! debug ospf6 flooding
!
interface r3-stubnet
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r3-sw5
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r3-sw6
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -28,9 +31,6 @@ router ospf6
ospf6 router-id 10.0.0.3
log-adjacency-changes detail
redistribute static
- interface r3-stubnet area 0.0.0.0
- interface r3-sw5 area 0.0.0.0
- interface r3-sw6 area 0.0.0.1
!
line vty
exec-timeout 0 0
diff --git a/tests/topotests/ospf6_topo1/r4/ospf6d.conf b/tests/topotests/ospf6_topo1/r4/ospf6d.conf
index f0b166bc4b..230ec7aad4 100644
--- a/tests/topotests/ospf6_topo1/r4/ospf6d.conf
+++ b/tests/topotests/ospf6_topo1/r4/ospf6d.conf
@@ -10,11 +10,13 @@ log file ospf6d.log
! debug ospf6 flooding
!
interface r4-stubnet
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r4-sw6
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 network broadcast
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
@@ -23,8 +25,6 @@ router ospf6
ospf6 router-id 10.0.0.4
log-adjacency-changes detail
redistribute static
- interface r4-stubnet area 0.0.0.1
- interface r4-sw6 area 0.0.0.1
!
line vty
exec-timeout 0 0
diff --git a/tests/topotests/ospf_topo1/r1/ospf6d.conf b/tests/topotests/ospf_topo1/r1/ospf6d.conf
index ca3497b4a5..0e6c7dadfb 100644
--- a/tests/topotests/ospf_topo1/r1/ospf6d.conf
+++ b/tests/topotests/ospf_topo1/r1/ospf6d.conf
@@ -4,10 +4,12 @@ router ospf6
redistribute kernel
redistribute connected
redistribute static
- interface r1-eth0 area 0.0.0.0
- interface r1-eth1 area 0.0.0.0
+!
+interface r1-eth0
+ ipv6 ospf6 area 0.0.0.0
!
int r1-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 dead-interval 10
ipv6 ospf6 hello-interval 2
!
diff --git a/tests/topotests/ospf_topo1/r2/ospf6d.conf b/tests/topotests/ospf_topo1/r2/ospf6d.conf
index 44047e1a4e..f6a1f50530 100644
--- a/tests/topotests/ospf_topo1/r2/ospf6d.conf
+++ b/tests/topotests/ospf_topo1/r2/ospf6d.conf
@@ -4,14 +4,14 @@ router ospf6
redistribute kernel
redistribute connected
redistribute static
- interface r2-eth0 area 0.0.0.0
- interface r2-eth1 area 0.0.0.0
!
int r2-eth0
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
int r2-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
diff --git a/tests/topotests/ospf_topo1/r3/ospf6d.conf b/tests/topotests/ospf_topo1/r3/ospf6d.conf
index 13ad9a7356..278a016968 100644
--- a/tests/topotests/ospf_topo1/r3/ospf6d.conf
+++ b/tests/topotests/ospf_topo1/r3/ospf6d.conf
@@ -4,19 +4,19 @@ router ospf6
redistribute kernel
redistribute connected
redistribute static
- interface r3-eth0 area 0.0.0.0
- interface r3-eth1 area 0.0.0.0
- interface r3-eth2 area 0.0.0.1
!
int r3-eth0
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
int r3-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
int r3-eth2
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
diff --git a/tests/topotests/ospf_topo1/r4/ospf6d.conf b/tests/topotests/ospf_topo1/r4/ospf6d.conf
index f9bde0e83c..777dd0b7b7 100644
--- a/tests/topotests/ospf_topo1/r4/ospf6d.conf
+++ b/tests/topotests/ospf_topo1/r4/ospf6d.conf
@@ -4,14 +4,14 @@ router ospf6
redistribute kernel
redistribute connected
redistribute static
- interface r4-eth0 area 0.0.0.1
- interface r4-eth1 area 0.0.0.1
!
int r4-eth0
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
int r4-eth1
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
diff --git a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py
index 529520cd9e..0b2937c12a 100644
--- a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py
+++ b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py
@@ -144,6 +144,23 @@ def test_zebra_system_recursion():
assert result is None, "Kernel route is missing from zebra"
+def test_zebra_noprefix_connected():
+ "Test that a noprefixroute created does not create a connected route"
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+ router.run("ip addr add 192.168.44.1/24 dev r1-eth1 noprefixroute")
+ expected = "% Network not in table"
+ test_func = partial(
+ topotest.router_output_cmp, router, "show ip route 192.168.44.0/24", expected
+ )
+ result, diff = topotest.run_and_expect(test_func, "", count=20, wait=1)
+ assert result, "Connected Route should not have been added"
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/zebra/connected.c b/zebra/connected.c
index 297234b6af..404f892f6e 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -282,13 +282,15 @@ void connected_up(struct interface *ifp, struct connected *ifc)
return;
}
- rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
- false);
+ if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) {
+ rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
+ zvrf->table_id, metric, 0, 0, 0, false);
- rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
- false);
+ rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
+ zvrf->table_id, metric, 0, 0, 0, false);
+ }
if (install_local) {
rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_LOCAL,
@@ -481,11 +483,15 @@ void connected_down(struct interface *ifp, struct connected *ifc)
* Same logic as for connected_up(): push the changes into the
* head.
*/
- rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
+ if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) {
+ rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
- rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
+ rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
+ }
if (remove_local) {
rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 2cedb29960..551ef6533e 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1423,6 +1423,9 @@ int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id,
if (kernel_flags & IFA_F_SECONDARY)
dplane_ctx_intf_set_secondary(ctx);
+ if (kernel_flags & IFA_F_NOPREFIXROUTE)
+ dplane_ctx_intf_set_noprefixroute(ctx);
+
/* Label */
if (tb[IFA_LABEL]) {
label = (char *)RTA_DATA(tb[IFA_LABEL]);
diff --git a/zebra/interface.c b/zebra/interface.c
index c4a952e1a7..39d24f1883 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1317,6 +1317,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx,
if (dplane_ctx_intf_is_secondary(ctx))
SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
+ if (dplane_ctx_intf_is_noprefixroute(ctx))
+ SET_FLAG(flags, ZEBRA_IFA_NOPREFIXROUTE);
+
/* Label? */
if (dplane_ctx_intf_has_label(ctx))
label = dplane_ctx_get_intf_label(ctx);
@@ -2335,6 +2338,12 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
vty_out(vty, " secondary");
if (json)
+ json_object_boolean_add(json_addr, "noPrefixRoute",
+ CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE));
+ else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE))
+ vty_out(vty, " noprefixroute");
+
+ if (json)
json_object_boolean_add(
json_addr, "unnumbered",
CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED));
diff --git a/zebra/rib.h b/zebra/rib.h
index 7ce6fbe609..61d9953d81 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -430,6 +430,7 @@ extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx);
/* Enqueue incoming nhg from proto daemon for processing */
extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe);
+extern int rib_queue_nhe_del(struct nhg_hash_entry *nhe);
/* Enqueue evpn route for processing */
int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2d1614ca54..761eafeb13 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1959,20 +1959,19 @@ static void zread_nhg_del(ZAPI_HANDLER_ARGS)
return;
}
- /*
- * Delete the received nhg id
- */
- nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto);
+ /* Create a temporary nhe */
+ nhe = zebra_nhg_alloc();
+ nhe->id = api_nhg.id;
+ nhe->type = api_nhg.proto;
+ nhe->zapi_instance = client->instance;
+ nhe->zapi_session = client->session_id;
+
+ /* Sanity check - Empty nexthop and group */
+ nhe->nhg.nexthop = NULL;
+
+ /* Enqueue to workqueue for processing */
+ rib_queue_nhe_del(nhe);
- if (nhe) {
- zebra_nhg_decrement_ref(nhe);
- zsend_nhg_notify(api_nhg.proto, client->instance,
- client->session_id, api_nhg.id,
- ZAPI_NHG_REMOVED);
- } else
- zsend_nhg_notify(api_nhg.proto, client->instance,
- client->session_id, api_nhg.id,
- ZAPI_NHG_REMOVE_FAIL);
/* Stats */
client->nhg_del_cnt++;
}
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 28319c5bdf..369394e845 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -230,6 +230,7 @@ struct dplane_intf_info {
#define DPLANE_INTF_BROADCAST (1 << 2)
#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED
#define DPLANE_INTF_HAS_LABEL (1 << 4)
+#define DPLANE_INTF_NOPREFIXROUTE (1 << 5)
/* Interface address/prefix */
struct prefix prefix;
@@ -2541,6 +2542,13 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx)
return (ctx->u.intf.flags & DPLANE_INTF_CONNECTED);
}
+bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return (ctx->u.intf.flags & DPLANE_INTF_NOPREFIXROUTE);
+}
+
bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2569,6 +2577,13 @@ void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx)
ctx->u.intf.flags |= DPLANE_INTF_SECONDARY;
}
+void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags |= DPLANE_INTF_NOPREFIXROUTE;
+}
+
void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 87c2e03656..6dc52ead14 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -658,6 +658,8 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_connected(struct zebra_dplane_ctx *ctx);
bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx);
bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx);
const struct prefix *dplane_ctx_get_intf_addr(
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index af94adf05a..980fced8a7 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -186,6 +186,7 @@ struct wq_nhg_wrapper {
struct nhg_ctx *ctx;
struct nhg_hash_entry *nhe;
} u;
+ bool deletion;
};
#define WQ_NHG_WRAPPER_TYPE_CTX 0x01
@@ -339,7 +340,7 @@ static char *_dump_re_status(const struct route_entry *re, char *buf,
: "",
CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "",
CHECK_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING)
- ? "Replacing"
+ ? "Replacing "
: "",
CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed "
: "",
@@ -1233,6 +1234,7 @@ static void rib_process(struct route_node *rn)
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
struct vrf *vrf;
+ struct route_entry *proto_re_changed = NULL;
vrf_id_t vrf_id = VRF_UNKNOWN;
@@ -1302,6 +1304,7 @@ static void rib_process(struct route_node *rn)
* skip it.
*/
if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
+ proto_re_changed = re;
if (!nexthop_active_update(rn, re)) {
const struct prefix *p;
struct rib_table_info *info;
@@ -1387,6 +1390,8 @@ static void rib_process(struct route_node *rn)
* new_selected --- RE entry that is newly SELECTED
* old_fib --- RE entry currently in kernel FIB
* new_fib --- RE entry that is newly to be in kernel FIB
+ * proto_re_changed -- RE that is the last changed entry in the
+ * list of RE's.
*
* new_selected will get SELECTED flag, and is going to be redistributed
* the zclients. new_fib (which can be new_selected) will be installed
@@ -1441,6 +1446,22 @@ static void rib_process(struct route_node *rn)
}
}
+ /*
+ * If zebra has a new_selected and a proto_re_changed
+ * entry that was not the old selected and the protocol
+ * is different, zebra should notify the upper level
+ * protocol that the sent down entry was not selected
+ */
+ if (new_selected && proto_re_changed &&
+ proto_re_changed != old_selected &&
+ new_selected->type != proto_re_changed->type) {
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
+
+ zsend_route_notify_owner(rn, proto_re_changed,
+ ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi,
+ info->safi);
+ }
+
/* Update fib according to selection results */
if (new_fib && old_fib)
rib_process_update_fib(zvrf, rn, old_fib, new_fib);
@@ -2511,7 +2532,7 @@ static void process_subq_evpn(struct listnode *lnode)
static void process_subq_nhg(struct listnode *lnode)
{
struct nhg_ctx *ctx;
- struct nhg_hash_entry *nhe, *newnhe;
+ struct nhg_hash_entry *nhe, *newnhe, *oldnhe;
struct wq_nhg_wrapper *w;
uint8_t qindex = META_QUEUE_NHG;
@@ -2543,15 +2564,33 @@ static void process_subq_nhg(struct listnode *lnode)
subqueue2str(qindex));
/* Process incoming nhg update, probably from a proto daemon */
- newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
- nhe->zapi_instance,
- nhe->zapi_session, &nhe->nhg, 0);
+ if (w->deletion) {
+ /*
+ * Delete the received nhg id
+ */
+ oldnhe = zebra_nhg_proto_del(nhe->id, nhe->type);
+ if (oldnhe) {
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_REMOVED);
+ zebra_nhg_decrement_ref(oldnhe);
+ } else
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_REMOVE_FAIL);
- /* Report error to daemon via ZAPI */
- if (newnhe == NULL)
- zsend_nhg_notify(nhe->type, nhe->zapi_instance,
- nhe->zapi_session, nhe->id,
- ZAPI_NHG_FAIL_INSTALL);
+ } else {
+ newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
+ nhe->zapi_instance,
+ nhe->zapi_session,
+ &nhe->nhg, 0);
+
+ /* Report error to daemon via ZAPI */
+ if (newnhe == NULL)
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_FAIL_INSTALL);
+ }
/* Free temp nhe - we own that memory. */
zebra_nhg_free(nhe);
@@ -3319,7 +3358,8 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
return 0;
}
-static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+static int rib_meta_queue_nhg_process(struct meta_queue *mq, void *data,
+ bool deletion)
{
struct nhg_hash_entry *nhe = NULL;
uint8_t qindex = META_QUEUE_NHG;
@@ -3334,6 +3374,7 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
w->type = WQ_NHG_WRAPPER_TYPE_NHG;
w->u.nhe = nhe;
+ w->deletion = deletion;
listnode_add(mq->subq[qindex], w);
mq->size++;
@@ -3345,6 +3386,16 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
return 0;
}
+static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+{
+ return rib_meta_queue_nhg_process(mq, data, false);
+}
+
+static int rib_meta_queue_nhg_del(struct meta_queue *mq, void *data)
+{
+ return rib_meta_queue_nhg_process(mq, data, true);
+}
+
static int rib_meta_queue_evpn_add(struct meta_queue *mq, void *data)
{
listnode_add(mq->subq[META_QUEUE_EVPN], data);
@@ -3453,6 +3504,17 @@ int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
}
/*
+ * Enqueue incoming nhg from proto daemon for processing
+ */
+int rib_queue_nhe_del(struct nhg_hash_entry *nhe)
+{
+ if (nhe == NULL)
+ return -1;
+
+ return mq_add_handler(nhe, rib_meta_queue_nhg_del);
+}
+
+/*
* Enqueue evpn route for processing
*/
int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,