summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bmp.c541
-rw-r--r--bgpd/bgp_bmp.h10
-rw-r--r--bgpd/bgp_route.c15
-rw-r--r--bgpd/bgp_route.h9
-rw-r--r--bgpd/bgp_trace.h3
-rw-r--r--doc/developer/bmp.rst49
-rw-r--r--doc/developer/subdir.am1
-rw-r--r--doc/user/bmp.rst8
-rw-r--r--tests/topotests/bgp_bmp/test_bgp_bmp.py11
-rw-r--r--tests/topotests/lib/bmp_collector/bmp.py3
10 files changed, 533 insertions, 117 deletions
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 7270802915..e9f912cb18 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -240,60 +240,115 @@ static void bmp_free(struct bmp *bmp)
XFREE(MTYPE_BMP_CONN, bmp);
}
+#define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
+#define BMP_PEER_TYPE_RD_INSTANCE 1
+#define BMP_PEER_TYPE_LOCAL_INSTANCE 2
+#define BMP_PEER_TYPE_LOC_RIB_INSTANCE 3
+
+static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi,
+ uint8_t peer_type,
+ uint64_t *result_ref)
+{
+
+ /* remove this check when the other peer types get correct peer dist.
+ *(RFC7854) impl.
+ * for now, always return no error and 0 peer distinguisher as before
+ */
+ if (peer_type != BMP_PEER_TYPE_LOC_RIB_INSTANCE)
+ return (*result_ref = 0);
+
+ /* sending vrf_id or rd could be turned into an option at some point */
+ struct bgp *bgp = bmp->targets->bgp;
+
+ /* vrf default => ok, distinguisher 0 */
+ if (bgp->inst_type == VRF_DEFAULT)
+ return (*result_ref = 0);
+
+ /* use RD if set in VRF config for this AFI */
+ struct prefix_rd *prd = &bgp->vpn_policy[afi].tovpn_rd;
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET)) {
+ memcpy(result_ref, prd->val, sizeof(prd->val));
+ return 0;
+ }
+
+ /* VRF has no id => error => message should be skipped */
+ if (bgp->vrf_id == VRF_UNKNOWN)
+ return 1;
+
+ /* use VRF id converted to ::vrf_id 64bits format */
+ *result_ref = ((uint64_t)htonl(bgp->vrf_id)) << 32;
+ return 0;
+}
+
static void bmp_common_hdr(struct stream *s, uint8_t ver, uint8_t type)
{
stream_putc(s, ver);
- stream_putl(s, 0); //dummy message length. will be set later.
+ stream_putl(s, 0); /* dummy message length. will be set later. */
stream_putc(s, type);
}
-static void bmp_per_peer_hdr(struct stream *s, struct peer *peer,
- uint8_t flags, const struct timeval *tv)
+static void bmp_per_peer_hdr(struct stream *s, struct bgp *bgp,
+ struct peer *peer, uint8_t flags,
+ uint8_t peer_type_flag,
+ uint64_t peer_distinguisher,
+ const struct timeval *tv)
{
- char peer_distinguisher[8];
-
-#define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
-#define BMP_PEER_TYPE_RD_INSTANCE 1
-#define BMP_PEER_TYPE_LOCAL_INSTANCE 2
-
#define BMP_PEER_FLAG_V (1 << 7)
#define BMP_PEER_FLAG_L (1 << 6)
#define BMP_PEER_FLAG_A (1 << 5)
+ bool is_locrib = peer_type_flag == BMP_PEER_TYPE_LOC_RIB_INSTANCE;
+
/* Peer Type */
- stream_putc(s, BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ stream_putc(s, peer_type_flag);
/* Peer Flags */
- if (peer->connection->su.sa.sa_family == AF_INET6)
+ if (!is_locrib && peer->connection->su.sa.sa_family == AF_INET6)
SET_FLAG(flags, BMP_PEER_FLAG_V);
else
UNSET_FLAG(flags, BMP_PEER_FLAG_V);
stream_putc(s, flags);
/* Peer Distinguisher */
- memset (&peer_distinguisher[0], 0, 8);
- stream_put(s, &peer_distinguisher[0], 8);
+ stream_put(s, (uint8_t *)&peer_distinguisher, 8);
/* Peer Address */
- if (peer->connection->su.sa.sa_family == AF_INET6)
- stream_put(s, &peer->connection->su.sin6.sin6_addr, 16);
- else if (peer->connection->su.sa.sa_family == AF_INET) {
+ /* Set to 0 if it's a LOC-RIB INSTANCE (RFC 9069) or if it's not an
+ * IPv4/6 address
+ */
+ if (is_locrib || (peer->connection->su.sa.sa_family != AF_INET6 &&
+ peer->connection->su.sa.sa_family != AF_INET)) {
stream_putl(s, 0);
stream_putl(s, 0);
stream_putl(s, 0);
- stream_put_in_addr(s, &peer->connection->su.sin.sin_addr);
- } else {
stream_putl(s, 0);
+ } else if (peer->connection->su.sa.sa_family == AF_INET6)
+ stream_put(s, &peer->connection->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
+ else if (peer->connection->su.sa.sa_family == AF_INET) {
stream_putl(s, 0);
stream_putl(s, 0);
stream_putl(s, 0);
+ stream_put_in_addr(s, &peer->connection->su.sin.sin_addr);
}
/* Peer AS */
- stream_putl(s, peer->as);
+ /* set peer ASN but for LOC-RIB INSTANCE (RFC 9069) put the local bgp
+ * ASN if available or 0
+ */
+ as_t asn = !is_locrib ? peer->as : bgp ? bgp->as : 0L;
+
+ stream_putl(s, asn);
/* Peer BGP ID */
- stream_put_in_addr(s, &peer->remote_id);
+ /* set router-id but for LOC-RIB INSTANCE (RFC 9069) put the instance
+ * router-id if available or 0
+ */
+ struct in_addr *bgp_id =
+ !is_locrib ? &peer->remote_id : bgp ? &bgp->router_id : NULL;
+
+ stream_put_in_addr(s, bgp_id);
/* Timestamp */
if (tv) {
@@ -314,11 +369,26 @@ static void bmp_put_info_tlv(struct stream *s, uint16_t type,
stream_put(s, string, len);
}
+static void __attribute__((unused))
+bmp_put_vrftablename_info_tlv(struct stream *s, struct bmp *bmp)
+{
+
+#define BMP_INFO_TYPE_VRFTABLENAME 3
+ const char *vrftablename = "global";
+ if (bmp->targets->bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+ struct vrf *vrf = vrf_lookup_by_id(bmp->targets->bgp->vrf_id);
+
+ vrftablename = vrf ? vrf->name : NULL;
+ }
+ if (vrftablename != NULL)
+ bmp_put_info_tlv(s, BMP_INFO_TYPE_VRFTABLENAME, vrftablename);
+}
+
static int bmp_send_initiation(struct bmp *bmp)
{
int len;
- struct stream *s;
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ struct stream *s = stream_new(BGP_MAX_PACKET_SIZE);
+
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_INITIATION);
#define BMP_INFO_TYPE_SYSDESCR 1
@@ -328,7 +398,7 @@ static int bmp_send_initiation(struct bmp *bmp)
bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSNAME, cmd_hostname_get());
len = stream_get_endp(s);
- stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
+ stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */
pullwr_write_stream(bmp->pullwr, s);
stream_free(s);
@@ -375,7 +445,9 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
bmp_common_hdr(s, BMP_VERSION_3,
BMP_TYPE_PEER_UP_NOTIFICATION);
- bmp_per_peer_hdr(s, peer, 0, &uptime_real);
+ bmp_per_peer_hdr(s, peer->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0,
+ &uptime_real);
/* Local Address (16 bytes) */
if (peer->su_local->sa.sa_family == AF_INET6)
@@ -428,7 +500,9 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
bmp_common_hdr(s, BMP_VERSION_3,
BMP_TYPE_PEER_DOWN_NOTIFICATION);
- bmp_per_peer_hdr(s, peer, 0, &uptime_real);
+ bmp_per_peer_hdr(s, peer->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0,
+ &uptime_real);
type_pos = stream_get_endp(s);
stream_putc(s, 0); /* placeholder for down reason */
@@ -460,7 +534,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
}
len = stream_get_endp(s);
- stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
+ stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */
return s;
}
@@ -618,7 +692,8 @@ static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
- bmp_per_peer_hdr(s, bmp->targets->bgp->peer_self, 0, &tv);
+ bmp_per_peer_hdr(s, bmp->targets->bgp, bmp->targets->bgp->peer_self, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv);
stream_putw(s, BMP_MIRROR_TLV_TYPE_INFO);
stream_putw(s, 2);
@@ -656,7 +731,8 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
- bmp_per_peer_hdr(s, peer, 0, &bmq->tv);
+ bmp_per_peer_hdr(s, bmp->targets->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &bmq->tv);
/* BMP Mirror TLV. */
stream_putw(s, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE);
@@ -763,7 +839,8 @@ static int bmp_peer_backward(struct peer *peer)
return 0;
}
-static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
+static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags,
+ uint8_t peer_type_flag)
{
struct peer *peer;
struct listnode *node;
@@ -771,7 +848,7 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
iana_afi_t pkt_afi = IANA_AFI_IPV4;
iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
- frrtrace(3, frr_bgp, bmp_eor, afi, safi, flags);
+ frrtrace(3, frr_bgp, bmp_eor, afi, safi, flags, peer_type_flag);
s = stream_new(BGP_MAX_PACKET_SIZE);
@@ -803,11 +880,22 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
if (!peer->afc_nego[afi][safi])
continue;
+ uint64_t peer_distinguisher = 0;
+ /* skip this message if peer distinguisher is not available */
+ if (bmp_get_peer_distinguisher(bmp, afi, peer_type_flag,
+ &peer_distinguisher)) {
+ zlog_warn(
+ "skipping bmp message for reason: can't get peer distinguisher");
+ continue;
+ }
+
s2 = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s2, BMP_VERSION_3,
BMP_TYPE_ROUTE_MONITORING);
- bmp_per_peer_hdr(s2, peer, flags, NULL);
+
+ bmp_per_peer_hdr(s2, bmp->targets->bgp, peer, flags,
+ peer_type_flag, peer_distinguisher, NULL);
stream_putl_at(s2, BMP_LENGTH_POS,
stream_get_endp(s) + stream_get_endp(s2));
@@ -912,14 +1000,23 @@ static struct stream *bmp_withdraw(const struct prefix *p,
}
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
- const struct prefix *p, struct prefix_rd *prd,
- struct attr *attr, afi_t afi, safi_t safi,
- time_t uptime)
+ uint8_t peer_type_flag, const struct prefix *p,
+ struct prefix_rd *prd, struct attr *attr, afi_t afi,
+ safi_t safi, time_t uptime)
{
struct stream *hdr, *msg;
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
struct timeval uptime_real;
+ uint64_t peer_distinguisher = 0;
+ /* skip this message if peer distinguisher is not available */
+ if (bmp_get_peer_distinguisher(bmp, afi, peer_type_flag,
+ &peer_distinguisher)) {
+ zlog_warn(
+ "skipping bmp message for reason: can't get peer distinguisher");
+ return;
+ }
+
monotime_to_realtime(&tv, &uptime_real);
if (attr)
msg = bmp_update(p, prd, peer, attr, afi, safi);
@@ -928,7 +1025,9 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
hdr = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
- bmp_per_peer_hdr(hdr, peer, flags, &uptime_real);
+ bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type_flag,
+ peer_distinguisher,
+ uptime == (time_t)(-1L) ? NULL : &uptime_real);
stream_putl_at(hdr, BMP_LENGTH_POS,
stream_get_endp(hdr) + stream_get_endp(msg));
@@ -1039,8 +1138,13 @@ afibreak:
zlog_info("bmp[%s] %s %s table completed (EoR)",
bmp->remote, afi2str(afi),
safi2str(safi));
- bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L);
- bmp_eor(bmp, afi, safi, 0);
+
+ bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ bmp_eor(bmp, afi, safi, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE);
+ bmp_eor(bmp, afi, safi, 0,
+ BMP_PEER_TYPE_LOC_RIB_INSTANCE);
bmp->afistate[afi][safi] = BMP_AFI_LIVE;
bmp->syncafi = AFI_MAX;
@@ -1051,10 +1155,16 @@ afibreak:
prefix_copy(&bmp->syncpos, bgp_dest_get_prefix(bn));
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_POSTPOLICY) ||
+ CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_LOC_RIB)) {
for (bpiter = bgp_dest_get_bgp_path_info(bn); bpiter;
bpiter = bpiter->next) {
- if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID))
+ if (!CHECK_FLAG(bpiter->flags,
+ BGP_PATH_VALID) &&
+ !CHECK_FLAG(bpiter->flags,
+ BGP_PATH_SELECTED))
continue;
if (bpiter->peer->qobj_node.nid
<= bmp->syncpeerid)
@@ -1065,7 +1175,8 @@ afibreak:
bpi = bpiter;
}
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi],
+ BMP_MON_PREPOLICY)) {
for (adjiter = bn->adj_in; adjiter;
adjiter = adjiter->next) {
if (adjiter->peer->qobj_node.nid
@@ -1103,12 +1214,23 @@ afibreak:
(safi == SAFI_MPLS_VPN))
prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
- if (bpi)
- bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bn_p, prd,
- bpi->attr, afi, safi, bpi->uptime);
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) &&
+ CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+ bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
+ bn_p, prd, bpi->attr, afi, safi,
+ bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
+ : (time_t)(-1L));
+ }
+
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
+ CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY))
+ bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
+ afi, safi, bpi->uptime);
+
if (adjin)
- bmp_monitor(bmp, adjin->peer, 0, bn_p, prd, adjin->attr, afi,
- safi, adjin->uptime);
+ bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
+ bn_p, prd, adjin->attr, afi, safi, adjin->uptime);
if (bn)
bgp_dest_unlock_node(bn);
@@ -1116,24 +1238,124 @@ afibreak:
return true;
}
-static struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
+static struct bmp_queue_entry *
+bmp_pull_from_queue(struct bmp_qlist_head *list, struct bmp_qhash_head *hash,
+ struct bmp_queue_entry **queuepos_ptr)
{
struct bmp_queue_entry *bqe;
- bqe = bmp->queuepos;
+ bqe = *queuepos_ptr;
if (!bqe)
return NULL;
- bmp->queuepos = bmp_qlist_next(&bmp->targets->updlist, bqe);
+ *queuepos_ptr = bmp_qlist_next(list, bqe);
bqe->refcount--;
if (!bqe->refcount) {
- bmp_qhash_del(&bmp->targets->updhash, bqe);
- bmp_qlist_del(&bmp->targets->updlist, bqe);
+ bmp_qhash_del(hash, bqe);
+ bmp_qlist_del(list, bqe);
}
return bqe;
}
+static inline struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
+{
+ return bmp_pull_from_queue(&bmp->targets->updlist,
+ &bmp->targets->updhash, &bmp->queuepos);
+}
+
+static inline struct bmp_queue_entry *bmp_pull_locrib(struct bmp *bmp)
+{
+ return bmp_pull_from_queue(&bmp->targets->locupdlist,
+ &bmp->targets->locupdhash,
+ &bmp->locrib_queuepos);
+}
+
+/* TODO BMP_MON_LOCRIB find a way to merge properly this function with
+ * bmp_wrqueue or abstract it if possible
+ */
+static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
+{
+
+ struct bmp_queue_entry *bqe;
+ struct peer *peer;
+ struct bgp_dest *bn = NULL;
+ bool written = false;
+
+ bqe = bmp_pull_locrib(bmp);
+ if (!bqe)
+ return false;
+
+ afi_t afi = bqe->afi;
+ safi_t safi = bqe->safi;
+
+ if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB))
+ goto out;
+
+ switch (bmp->afistate[afi][safi]) {
+ case BMP_AFI_INACTIVE:
+ case BMP_AFI_NEEDSYNC:
+ goto out;
+ case BMP_AFI_SYNC:
+ if (prefix_cmp(&bqe->p, &bmp->syncpos) <= 0)
+ /* currently syncing but have already passed this
+ * prefix => send it.
+ */
+ break;
+
+ /* currently syncing & haven't reached this prefix yet
+ * => it'll be sent as part of the table sync, no need here
+ */
+ goto out;
+ case BMP_AFI_LIVE:
+ break;
+ }
+
+ peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer);
+ if (!peer) {
+ /* skipping queued item for deleted peer
+ */
+ goto out;
+ }
+ if (peer != bmp->targets->bgp->peer_self && !peer_established(peer->connection)) {
+ /* peer is neither self, nor established
+ */
+ goto out;
+ }
+
+ bool is_vpn = (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN) ||
+ (bqe->safi == SAFI_MPLS_VPN);
+
+ struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL;
+
+ bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi,
+ &bqe->p, prd);
+
+ struct bgp_path_info *bpi;
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
+ if (!CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED))
+ continue;
+ if (bpi->peer == peer)
+ break;
+ }
+
+ bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
+ bpi ? bpi->attr : NULL, afi, safi,
+ bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
+ : (time_t)(-1L));
+ written = true;
+
+out:
+ if (!bqe->refcount)
+ XFREE(MTYPE_BMP_QUEUE, bqe);
+
+ if (bn)
+ bgp_dest_unlock_node(bn);
+
+ return written;
+}
+
static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
{
struct bmp_queue_entry *bqe;
@@ -1180,11 +1402,10 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi,
&bqe->p, prd);
-
- if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY)) {
struct bgp_path_info *bpi;
- for (bpi = bn ? bgp_dest_get_bgp_path_info(bn) : NULL; bpi;
+ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
if (!CHECK_FLAG(bpi->flags, BGP_PATH_VALID))
continue;
@@ -1192,13 +1413,14 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
break;
}
- bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
+ bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi ? bpi->uptime : monotime(NULL));
written = true;
}
- if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
+ if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_PREPOLICY)) {
struct bgp_adj_in *adjin;
for (adjin = bn ? bn->adj_in : NULL; adjin;
@@ -1206,8 +1428,8 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
if (adjin->peer == peer)
break;
}
- bmp_monitor(bmp, peer, 0, &bqe->p, prd,
- adjin ? adjin->attr : NULL, afi, safi,
+ bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
+ &bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
adjin ? adjin->uptime : monotime(NULL));
written = true;
}
@@ -1235,6 +1457,8 @@ static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr)
break;
if (bmp_wrqueue(bmp, pullwr))
break;
+ if (bmp_wrqueue_locrib(bmp, pullwr))
+ break;
if (bmp_wrsync(bmp, pullwr))
break;
break;
@@ -1253,16 +1477,17 @@ static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof)
bmp_free(bmp);
}
-static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp, afi_t afi,
- safi_t safi, struct bgp_dest *bn, struct peer *peer)
+static struct bmp_queue_entry *
+bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash,
+ struct bmp_qlist_head *updlist, struct bgp *bgp, afi_t afi,
+ safi_t safi, struct bgp_dest *bn, struct peer *peer)
{
- struct bmp *bmp;
struct bmp_queue_entry *bqe, bqeref;
size_t refcount;
refcount = bmp_session_count(&bt->sessions);
if (refcount == 0)
- return;
+ return NULL;
memset(&bqeref, 0, sizeof(bqeref));
prefix_copy(&bqeref.p, bgp_dest_get_prefix(bn));
@@ -1275,26 +1500,28 @@ static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp, afi_t afi,
prefix_copy(&bqeref.rd,
(struct prefix_rd *)bgp_dest_get_prefix(bn->pdest));
- bqe = bmp_qhash_find(&bt->updhash, &bqeref);
+ bqe = bmp_qhash_find(updhash, &bqeref);
if (bqe) {
if (bqe->refcount >= refcount)
/* nothing to do here */
- return;
+ return NULL;
- bmp_qlist_del(&bt->updlist, bqe);
+ bmp_qlist_del(updlist, bqe);
} else {
bqe = XMALLOC(MTYPE_BMP_QUEUE, sizeof(*bqe));
memcpy(bqe, &bqeref, sizeof(*bqe));
- bmp_qhash_add(&bt->updhash, bqe);
+ bmp_qhash_add(updhash, bqe);
}
bqe->refcount = refcount;
- bmp_qlist_add_tail(&bt->updlist, bqe);
+ bmp_qlist_add_tail(updlist, bqe);
- frr_each (bmp_session, &bt->sessions, bmp)
- if (!bmp->queuepos)
- bmp->queuepos = bqe;
+ return bqe;
+
+ /* need to update correct queue pos for all sessions of the target after
+ * a call to this function
+ */
}
static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
@@ -1316,12 +1543,26 @@ static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
return 0;
frr_each(bmp_targets, &bmpbgp->targets, bt) {
- if (!bt->afimon[afi][safi])
+ /* check if any monitoring is enabled (ignoring loc-rib since it
+ * uses another hook & queue
+ */
+ if (!CHECK_FLAG(bt->afimon[afi][safi], ~BMP_MON_LOC_RIB))
continue;
- bmp_process_one(bt, bgp, afi, safi, bn, peer);
+ struct bmp_queue_entry *last_item =
+ bmp_process_one(bt, &bt->updhash, &bt->updlist, bgp,
+ afi, safi, bn, peer);
+
+ /* if bmp_process_one returns NULL
+ * we don't have anything to do next
+ */
+ if (!last_item)
+ continue;
frr_each(bmp_session, &bt->sessions, bmp) {
+ if (!bmp->queuepos)
+ bmp->queuepos = last_item;
+
pullwr_bump(bmp->pullwr);
}
}
@@ -1360,7 +1601,8 @@ static void bmp_stats(struct event *thread)
s = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT);
- bmp_per_peer_hdr(s, peer, 0, &tv);
+ bmp_per_peer_hdr(s, bt->bgp, peer, 0,
+ BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv);
count_pos = stream_get_endp(s);
stream_putl(s, 0);
@@ -1530,6 +1772,9 @@ static void bmp_close(struct bmp *bmp)
while ((bqe = bmp_pull(bmp)))
if (!bqe->refcount)
XFREE(MTYPE_BMP_QUEUE, bqe);
+ while ((bqe = bmp_pull_locrib(bmp)))
+ if (!bqe->refcount)
+ XFREE(MTYPE_BMP_QUEUE, bqe);
EVENT_OFF(bmp->t_read);
pullwr_del(bmp->pullwr);
@@ -1633,6 +1878,8 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
bmp_session_init(&bt->sessions);
bmp_qhash_init(&bt->updhash);
bmp_qlist_init(&bt->updlist);
+ bmp_qhash_init(&bt->locupdhash);
+ bmp_qlist_init(&bt->locupdlist);
bmp_actives_init(&bt->actives);
bmp_listeners_init(&bt->listeners);
@@ -1663,6 +1910,8 @@ static void bmp_targets_put(struct bmp_targets *bt)
bmp_actives_fini(&bt->actives);
bmp_qhash_fini(&bt->updhash);
bmp_qlist_fini(&bt->updlist);
+ bmp_qhash_fini(&bt->locupdhash);
+ bmp_qlist_fini(&bt->locupdlist);
XFREE(MTYPE_BMP_ACLNAME, bt->acl_name);
XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name);
@@ -2206,21 +2455,17 @@ DEFPY(bmp_stats_cfg,
return CMD_SUCCESS;
}
-DEFPY(bmp_monitor_cfg,
- bmp_monitor_cmd,
- "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
- NO_STR
- BMP_STR
- "Send BMP route monitoring messages\n"
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
- BGP_AF_STR
+#define BMP_POLICY_IS_LOCRIB(str) ((str)[0] == 'l') /* __l__oc-rib */
+#define BMP_POLICY_IS_PRE(str) ((str)[1] == 'r') /* p__r__e-policy */
+
+DEFPY(bmp_monitor_cfg, bmp_monitor_cmd,
+ "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy|loc-rib>$policy",
+ NO_STR BMP_STR
+ "Send BMP route monitoring messages\n" BGP_AF_STR BGP_AF_STR BGP_AF_STR
+ BGP_AF_STR BGP_AF_STR BGP_AF_STR BGP_AF_STR
"Send state before policy and filter processing\n"
- "Send state with policy and filters applied\n")
+ "Send state with policy and filters applied\n"
+ "Send state after decision process is applied\n")
{
int index = 0;
uint8_t flag, prev;
@@ -2233,7 +2478,9 @@ DEFPY(bmp_monitor_cfg,
argv_find_and_parse_afi(argv, argc, &index, &afi);
argv_find_and_parse_safi(argv, argc, &index, &safi);
- if (policy[1] == 'r')
+ if (BMP_POLICY_IS_LOCRIB(policy))
+ flag = BMP_MON_LOC_RIB;
+ else if (BMP_POLICY_IS_PRE(policy))
flag = BMP_MON_PREPOLICY;
else
flag = BMP_MON_POSTPOLICY;
@@ -2364,23 +2611,31 @@ DEFPY(show_bmp,
safi_t safi;
FOREACH_AFI_SAFI (afi, safi) {
- const char *str = NULL;
-
- switch (bt->afimon[afi][safi]) {
- case BMP_MON_PREPOLICY:
- str = "pre-policy";
- break;
- case BMP_MON_POSTPOLICY:
- str = "post-policy";
- break;
- case BMP_MON_PREPOLICY | BMP_MON_POSTPOLICY:
- str = "pre-policy and post-policy";
- break;
- }
- if (!str)
+
+ uint8_t afimon_flag = bt->afimon[afi][safi];
+
+ if (!afimon_flag)
continue;
- vty_out(vty, " Route Monitoring %s %s %s\n",
- afi2str(afi), safi2str(safi), str);
+
+ const char *pre_str =
+ CHECK_FLAG(afimon_flag,
+ BMP_MON_PREPOLICY)
+ ? "pre-policy "
+ : "";
+ const char *post_str =
+ CHECK_FLAG(afimon_flag,
+ BMP_MON_POSTPOLICY)
+ ? "post-policy "
+ : "";
+ const char *locrib_str =
+ CHECK_FLAG(afimon_flag, BMP_MON_LOC_RIB)
+ ? "loc-rib"
+ : "";
+
+ vty_out(vty,
+ " Route Monitoring %s %s %s%s%s\n",
+ afi2str(afi), safi2str(safi), pre_str,
+ post_str, locrib_str);
}
vty_out(vty, " Listeners:\n");
@@ -2500,13 +2755,18 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
vty_out(vty, " bmp mirror\n");
FOREACH_AFI_SAFI (afi, safi) {
- if (bt->afimon[afi][safi] & BMP_MON_PREPOLICY)
+ if (CHECK_FLAG(bt->afimon[afi][safi],
+ BMP_MON_PREPOLICY))
vty_out(vty, " bmp monitor %s %s pre-policy\n",
afi2str_lower(afi), safi2str(safi));
- if (bt->afimon[afi][safi] & BMP_MON_POSTPOLICY)
+ if (CHECK_FLAG(bt->afimon[afi][safi],
+ BMP_MON_POSTPOLICY))
vty_out(vty,
" bmp monitor %s %s post-policy\n",
afi2str_lower(afi), safi2str(safi));
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB))
+ vty_out(vty, " bmp monitor %s %s loc-rib\n",
+ afi2str(afi), safi2str(safi));
}
frr_each (bmp_listeners, &bt->listeners, bl)
vty_out(vty, " \n bmp listener %pSU port %d\n",
@@ -2555,6 +2815,76 @@ static int bgp_bmp_init(struct event_loop *tm)
return 0;
}
+static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi,
+ struct bgp_dest *bn,
+ struct bgp_path_info *old_route,
+ struct bgp_path_info *new_route)
+{
+ bool is_locribmon_enabled = false;
+ bool is_withdraw = old_route && !new_route;
+ struct bgp_path_info *updated_route =
+ is_withdraw ? old_route : new_route;
+
+
+ /* this should never happen */
+ if (!updated_route) {
+ zlog_warn("%s: no updated route found!", __func__);
+ return 0;
+ }
+
+ struct bmp_bgp *bmpbgp = bmp_bgp_get(bgp);
+ struct peer *peer = updated_route->peer;
+ struct bmp_targets *bt;
+ struct bmp *bmp;
+
+ frr_each (bmp_targets, &bmpbgp->targets, bt) {
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+ is_locribmon_enabled = true;
+ break;
+ }
+ }
+
+ if (!is_locribmon_enabled)
+ return 0;
+
+ /* route is not installed in locrib anymore and rib uptime was saved */
+ if (old_route && old_route->extra)
+ bgp_path_info_extra_get(old_route)->bgp_rib_uptime =
+ (time_t)(-1L);
+
+ /* route is installed in locrib from now on so
+ * save rib uptime in bgp_path_info_extra
+ */
+ if (new_route)
+ bgp_path_info_extra_get(new_route)->bgp_rib_uptime =
+ monotime(NULL);
+
+ frr_each (bmp_targets, &bmpbgp->targets, bt) {
+ if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) {
+
+ struct bmp_queue_entry *last_item = bmp_process_one(
+ bt, &bt->locupdhash, &bt->locupdlist, bgp, afi,
+ safi, bn, peer);
+
+ /* if bmp_process_one returns NULL
+ * we don't have anything to do next
+ */
+ if (!last_item)
+ continue;
+
+ frr_each (bmp_session, &bt->sessions, bmp) {
+ if (!bmp->locrib_queuepos)
+ bmp->locrib_queuepos = last_item;
+
+ pullwr_bump(bmp->pullwr);
+ };
+ }
+ };
+
+ return 0;
+}
+
+
static int bgp_bmp_module_init(void)
{
hook_register(bgp_packet_dump, bmp_mirror_packet);
@@ -2565,6 +2895,7 @@ static int bgp_bmp_module_init(void)
hook_register(bgp_inst_config_write, bmp_config_write);
hook_register(bgp_inst_delete, bmp_bgp_del);
hook_register(frr_late_init, bgp_bmp_init);
+ hook_register(bgp_route_update, bmp_route_update);
return 0;
}
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index ab7463fadc..dadd99eb6d 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -124,6 +124,7 @@ struct bmp {
* ahead we need to make sure that refcount is decremented. Also, on
* disconnects we need to walk the queue and drop our reference.
*/
+ struct bmp_queue_entry *locrib_queuepos;
struct bmp_queue_entry *queuepos;
struct bmp_mirrorq *mirrorpos;
bool mirror_lost;
@@ -215,12 +216,14 @@ struct bmp_targets {
int stat_msec;
/* only supporting:
- * - IPv4 / unicast & multicast
- * - IPv6 / unicast & multicast
+ * - IPv4 / unicast & multicast & VPN
+ * - IPv6 / unicast & multicast & VPN
* - L2VPN / EVPN
*/
#define BMP_MON_PREPOLICY (1 << 0)
#define BMP_MON_POSTPOLICY (1 << 1)
+#define BMP_MON_LOC_RIB (1 << 2)
+
uint8_t afimon[AFI_MAX][SAFI_MAX];
bool mirror;
@@ -232,6 +235,9 @@ struct bmp_targets {
struct bmp_qhash_head updhash;
struct bmp_qlist_head updlist;
+ struct bmp_qhash_head locupdhash;
+ struct bmp_qlist_head locupdlist;
+
uint64_t cnt_accept, cnt_aclrefused;
QOBJ_FIELDS;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4ced565d52..b4c97eb2ea 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -87,6 +87,11 @@ DEFINE_HOOK(bgp_rpki_prefix_status,
const struct prefix *prefix),
(peer, attr, prefix));
+DEFINE_HOOK(bgp_route_update,
+ (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
+ struct bgp_path_info *old_route, struct bgp_path_info *new_route),
+ (bgp, afi, safi, bn, old_route, new_route));
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -3437,6 +3442,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&bgp->t_rmap_def_originate_eval);
}
+ /* TODO BMP insert rib update hook */
if (old_select)
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
@@ -3449,6 +3455,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
}
+ /* call bmp hook for loc-rib route update / withdraw after flags were
+ * set
+ */
+ if (old_select || new_select) {
+ hook_call(bgp_route_update, bgp, afi, safi, dest, old_select,
+ new_select);
+ }
+
+
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (old_select != new_select) {
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e9f48ea647..3057a4259a 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -211,6 +211,9 @@ struct bgp_path_info_extra {
mpls_label_t label[BGP_MAX_LABELS];
uint32_t num_labels;
+ /* timestamp of the rib installation */
+ time_t bgp_rib_uptime;
+
/*For EVPN*/
struct bgp_path_info_extra_evpn *evpn;
@@ -674,6 +677,12 @@ DECLARE_HOOK(bgp_process,
struct peer *peer, bool withdraw),
(bgp, afi, safi, bn, peer, withdraw));
+/* called when a route is updated in the rib */
+DECLARE_HOOK(bgp_route_update,
+ (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
+ struct bgp_path_info *old_route, struct bgp_path_info *new_route),
+ (bgp, afi, safi, bn, old_route, new_route));
+
/* BGP show options */
#define BGP_SHOW_OPT_JSON (1 << 0)
#define BGP_SHOW_OPT_WIDE (1 << 1)
diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h
index 964393a9f5..0980073e2b 100644
--- a/bgpd/bgp_trace.h
+++ b/bgpd/bgp_trace.h
@@ -135,11 +135,12 @@ TRACEPOINT_LOGLEVEL(frr_bgp, bmp_mirror_packet, TRACE_INFO)
TRACEPOINT_EVENT(
frr_bgp,
bmp_eor,
- TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags),
+ TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags, peer_type_flag),
TP_FIELDS(
ctf_integer(afi_t, afi, afi)
ctf_integer(safi_t, safi, safi)
ctf_integer(uint8_t, flags, flags)
+ ctf_integer(uint8_t, peer_type_flag, peer_type_flag)
)
)
diff --git a/doc/developer/bmp.rst b/doc/developer/bmp.rst
new file mode 100644
index 0000000000..1c0e4b0454
--- /dev/null
+++ b/doc/developer/bmp.rst
@@ -0,0 +1,49 @@
+.. _bmp:
+
+***
+BMP
+***
+
+RFC 7854
+========
+Missing features (non exhaustive):
+ - Per-Peer Header
+
+ - Peer Type Flag
+ - Peer Distingsher
+
+ - Peer Up
+
+ - Reason codes (according to TODO comments in code)
+
+Peer Type Flag and Peer Distinguisher can be implemented easily using RFC 9069's base code.
+
+RFC 9069
+========
+Everything that isn't listed here is implemented and should be working.
+Missing features (should be exhaustive):
+
+- Per-Peer Header
+
+ - Timestamp
+
+ - set to 0
+ - value is now saved `struct bgp_path_info -> locrib_uptime`
+ - needs testing
+
+- Peer Up/Down
+
+ - VRF/Table Name TLV
+
+ - code for TLV exists
+ - need better RFC understanding
+
+- Peer Down Only
+
+ - Reason code (bc not supported in RFC 7854 either)
+
+- Statistics Report
+
+ - Stat Type = 8: (64-bit Gauge) Number of routes in Loc-RIB.
+ - Stat Type = 10: Number of routes in per-AFI/SAFI Loc-RIB. The value is
+ structured as: 2-byte AFI, 1-byte SAFI, followed by a 64-bit Gauge.
diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am
index 0deb0f5da0..652ee4e1af 100644
--- a/doc/developer/subdir.am
+++ b/doc/developer/subdir.am
@@ -5,6 +5,7 @@
dev_RSTFILES = \
doc/developer/bgp-typecodes.rst \
doc/developer/bgpd.rst \
+ doc/developer/bmp.rst \
doc/developer/building-frr-for-alpine.rst \
doc/developer/building-frr-for-archlinux.rst \
doc/developer/building-frr-for-centos6.rst \
diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst
index 1983995c1f..0f46832059 100644
--- a/doc/user/bmp.rst
+++ b/doc/user/bmp.rst
@@ -36,8 +36,8 @@ The `BMP` implementation in FRR has the following properties:
successfully. OPEN messages for failed sessions cannot currently be
mirrored.
-- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast and
- multicast SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not
+- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast, multicast,
+ EVPN and VPN SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not
currently supported.
- monitoring peers that have BGP **add-path** enabled on the session will
@@ -146,10 +146,10 @@ associated with a particular ``bmp targets``:
Send BMP Statistics (counter) messages at the specified interval (in
milliseconds.)
-.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy>
+.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib>
Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
- IPv6 are currently valid for AFI. SAFI valid values are currently
+ IPv6 are currently valid for AFI. SAFI valid values are currently
unicast, multicast, evpn and vpn.
Other AFI/SAFI combinations may be added in the future.
diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py
index 65f191b33a..250f1cb90d 100644
--- a/tests/topotests/bgp_bmp/test_bgp_bmp.py
+++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py
@@ -49,6 +49,7 @@ SEQ = 0
PRE_POLICY = "pre-policy"
POST_POLICY = "post-policy"
+LOC_RIB = "loc-rib"
def build_topo(tgen):
@@ -120,7 +121,7 @@ def get_bmp_messages():
return messages
-def check_for_prefixes(expected_prefixes, bmp_log_type, post_policy):
+def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
"""
Check for the presence of the given prefixes in the BMP server logs with
the given message type and the set policy.
@@ -138,7 +139,7 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, post_policy):
if "ip_prefix" in m.keys()
and "bmp_log_type" in m.keys()
and m["bmp_log_type"] == bmp_log_type
- and m["post_policy"] == post_policy
+ and m["policy"] == policy
]
# check for prefixes
@@ -202,7 +203,7 @@ def unicast_prefixes(policy):
logger.info("checking for updated prefixes")
# check
- test_func = partial(check_for_prefixes, prefixes, "update", policy == POST_POLICY)
+ test_func = partial(check_for_prefixes, prefixes, "update", policy)
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
assert success, "Checking the updated prefixes has been failed !."
@@ -210,7 +211,7 @@ def unicast_prefixes(policy):
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, update=False)
logger.info("checking for withdrawed prefxies")
# check
- test_func = partial(check_for_prefixes, prefixes, "withdraw", policy == POST_POLICY)
+ test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
assert success, "Checking the withdrawed prefixes has been failed !."
@@ -239,6 +240,8 @@ def test_bmp_bgp_unicast():
unicast_prefixes(PRE_POLICY)
logger.info("*** Unicast prefixes post-policy logging ***")
unicast_prefixes(POST_POLICY)
+ logger.info("*** Unicast prefixes loc-rib logging ***")
+ unicast_prefixes(LOC_RIB)
if __name__ == "__main__":
diff --git a/tests/topotests/lib/bmp_collector/bmp.py b/tests/topotests/lib/bmp_collector/bmp.py
index b07329cd52..57f642aa0e 100644
--- a/tests/topotests/lib/bmp_collector/bmp.py
+++ b/tests/topotests/lib/bmp_collector/bmp.py
@@ -252,6 +252,7 @@ class BMPPerPeerMessage:
if peer_type == 0x03:
msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
+ msg['policy'] = 'loc-rib'
else:
# peer_flags = 0x0000 0000
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
@@ -259,7 +260,7 @@ class BMPPerPeerMessage:
is_as_path = bool(peer_flags & IS_AS_PATH)
is_post_policy = bool(peer_flags & IS_POST_POLICY)
is_ipv6 = bool(peer_flags & IS_IPV6)
- msg['post_policy'] = is_post_policy
+ msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
msg['ipv6'] = is_ipv6
msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)