const struct bmp_queue_entry *b)
{
int ret;
+ if (a->afi == AFI_L2VPN && a->safi == SAFI_EVPN && b->afi == AFI_L2VPN
+ && b->safi == SAFI_EVPN) {
+ ret = prefix_cmp(&a->rd, &b->rd);
+ if (ret)
+ return ret;
+ } else if (a->afi == AFI_L2VPN && a->safi == SAFI_EVPN)
+ return 1;
+ else if (b->afi == AFI_L2VPN && b->safi == SAFI_EVPN)
+ return -1;
+
ret = prefix_cmp(&a->p, &b->p);
if (ret)
return ret;
key = prefix_hash_key((void *)&e->p);
key = jhash(&e->peerid,
- offsetof(struct bmp_queue_entry, refcount) -
- offsetof(struct bmp_queue_entry, peerid),
- key);
+ offsetof(struct bmp_queue_entry, refcount)
+ - offsetof(struct bmp_queue_entry, peerid),
+ key);
+ if (e->afi == AFI_L2VPN && e->safi == SAFI_EVPN)
+ key = jhash(&e->rd,
+ offsetof(struct bmp_queue_entry, rd)
+ - offsetof(struct bmp_queue_entry, refcount)
+ + PSIZE(e->rd.prefixlen),
+ key);
+
return key;
}
stream_free(s);
}
-static struct stream *bmp_update(const struct prefix *p, struct peer *peer,
- struct attr *attr, afi_t afi, safi_t safi)
+static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
+ struct peer *peer, struct attr *attr,
+ afi_t afi, safi_t safi)
{
struct bpacket_attr_vec_arr vecarr;
struct stream *s;
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
&vecarr, attr);
- bgp_packet_mpattr_prefix(s, afi, safi, p, NULL, NULL, 0,
- 0, 0, attr);
+ bgp_packet_mpattr_prefix(s, afi, safi, p, prd, NULL, 0, 0, 0,
+ attr);
bgp_packet_mpattr_end(s, mpattrlen_pos);
total_attr_len += stream_get_endp(s) - p1;
}
return s;
}
-static struct stream *bmp_withdraw(const struct prefix *p, afi_t afi,
+static struct stream *bmp_withdraw(const struct prefix *p,
+ struct prefix_rd *prd, afi_t afi,
safi_t safi)
{
struct stream *s;
mp_start = stream_get_endp(s);
mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
- bgp_packet_mpunreach_prefix(s, p, afi, safi, NULL, NULL, 0,
- 0, 0, NULL);
+ bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, 0, 0,
+ NULL);
/* Set the mp_unreach attr's length */
bgp_packet_mpunreach_end(s, mplen_pos);
}
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
- const struct prefix *p, struct attr *attr, afi_t afi,
- safi_t safi, time_t uptime)
+ 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 };
monotime_to_realtime(&tv, &uptime_real);
if (attr)
- msg = bmp_update(p, peer, attr, afi, safi);
+ msg = bmp_update(p, prd, peer, attr, afi, safi);
else
- msg = bmp_withdraw(p, afi, safi);
+ msg = bmp_withdraw(p, prd, afi, safi);
hdr = stream_new(BGP_MAX_PACKET_SIZE);
bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
bmp->syncpeerid = 0;
memset(&bmp->syncpos, 0, sizeof(bmp->syncpos));
bmp->syncpos.family = afi2family(afi);
+ bmp->syncrdpos = NULL;
zlog_info("bmp[%s] %s %s sending table",
bmp->remote,
afi2str(bmp->syncafi),
struct bgp_path_info *bpi = NULL, *bpiter;
struct bgp_adj_in *adjin = NULL, *adjiter;
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+ /* initialize syncrdpos to the first
+ * mid-layer table entry
+ */
+ if (!bmp->syncrdpos)
+ bmp->syncrdpos = bgp_table_top(table);
+
+ /* look for a valid mid-layer table */
+ do {
+ table = bgp_dest_get_bgp_table_info(bmp->syncrdpos);
+ if (table) {
+ break;
+ }
+ bmp->syncrdpos = bgp_route_next(bmp->syncrdpos);
+ } while (bmp->syncrdpos);
+
+ /* mid-layer table completed */
+ if (!bmp->syncrdpos)
+ goto eor;
+ }
+
bn = bgp_node_lookup(table, &bmp->syncpos);
do {
if (!bn) {
bn = bgp_table_get_next(table, &bmp->syncpos);
if (!bn) {
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+ /* reset bottom-layer pointer */
+ memset(&bmp->syncpos, 0,
+ sizeof(bmp->syncpos));
+ bmp->syncpos.family = afi2family(afi);
+ /* check whethere there is a valid
+ * next mid-layer table, otherwise
+ * declare table completed (eor)
+ */
+ for (bmp->syncrdpos = bgp_route_next(
+ bmp->syncrdpos);
+ bmp->syncrdpos;
+ bmp->syncrdpos = bgp_route_next(
+ bmp->syncrdpos))
+ if (bgp_dest_get_bgp_table_info(
+ bmp->syncrdpos))
+ return true;
+ }
+ eor:
zlog_info("bmp[%s] %s %s table completed (EoR)",
bmp->remote, afi2str(afi),
safi2str(safi));
}
if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
- for (bpiter = bn->info; bpiter; bpiter = bpiter->next) {
+ for (bpiter = bgp_dest_get_bgp_path_info(bn); bpiter;
+ bpiter = bpiter->next) {
if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID))
continue;
if (bpiter->peer->qobj_node.nid
}
const struct prefix *bn_p = bgp_dest_get_prefix(bn);
+ struct prefix_rd *prd = NULL;
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+ prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
if (bpi)
- bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bn_p, bpi->attr,
- afi, safi, bpi->uptime);
+ bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bn_p, prd,
+ bpi->attr, afi, safi, bpi->uptime);
if (adjin)
- bmp_monitor(bmp, adjin->peer, 0, bn_p, adjin->attr, afi, safi,
- adjin->uptime);
+ bmp_monitor(bmp, adjin->peer, 0, bn_p, prd, adjin->attr, afi,
+ safi, adjin->uptime);
return true;
}
goto out;
bn = bgp_node_lookup(bmp->targets->bgp->rib[afi][safi], &bqe->p);
+ struct prefix_rd *prd = NULL;
+ if (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN)
+ prd = &bqe->rd;
if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
struct bgp_path_info *bpi;
- for (bpi = bn ? bn->info : NULL; bpi; bpi = bpi->next) {
+ for (bpi = bn ? bgp_dest_get_bgp_path_info(bn) : NULL; bpi;
+ bpi = bpi->next) {
if (!CHECK_FLAG(bpi->flags, BGP_PATH_VALID))
continue;
if (bpi->peer == peer)
break;
}
- bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p,
+ bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi ? bpi->uptime : monotime(NULL));
written = true;
if (adjin->peer == peer)
break;
}
- bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p,
+ bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
adjin ? adjin->attr : NULL, afi, safi,
adjin ? adjin->uptime : monotime(NULL));
written = true;
bqeref.afi = afi;
bqeref.safi = safi;
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN && bn->pdest)
+ prefix_copy(&bqeref.rd,
+ (struct prefix_rd *)bgp_dest_get_prefix(bn->pdest));
+
bqe = bmp_qhash_find(&bt->updhash, &bqeref);
if (bqe) {
if (bqe->refcount >= refcount)
DEFPY(bmp_monitor_cfg,
bmp_monitor_cmd,
- "[no] bmp monitor "BGP_AFI_CMD_STR" <unicast|multicast> <pre-policy|post-policy>$policy",
+ "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
NO_STR
BMP_STR
"Send BMP route monitoring messages\n"
- BGP_AFI_HELP_STR
- "Address family modifier\n"
- "Address family modifier\n"
+ "Address Family\nAddress Family\nAddress Family\n"
+ "Address Family\nAddress Family\nAddress Family\n"
"Send state before policy and filter processing\n"
"Send state with policy and filters applied\n")
{