From e9d3797e2df639939695242978cbbd8f6807acf8 Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Mon, 13 Feb 2023 13:13:39 +0100 Subject: [PATCH 01/11] bgpd, lib, doc: bmp adj-rib-out monitoring, bmp multipath support bgpd: changed bmp config to include bmp monitor rib-out bgpd: added rib-out pre-policy & post-policy monitoring bgpd: bmp sync for rib-out pre and post bgpd: added missing out-pre hook bump bmp sessions on bmp reconfigure to run sync immediately lib, bgpd: added pullwr_timeout, added bmp startup-delay command bgpd: bmp added bmp session state to bmp show doc: bmp updated documentation with new commands bgpd: bmp add rib-out post-policy stats bgpd: bmp add adj-rib-in stats bgpd: bmp add loc-rib stats bgpd: bmp multipath support for adj-rib-in pre-policy bgpd: bmp multipath support for adj-rib-out post-policy bgpd: bmp multipath support for adj-rib-in post-policy bgpd: bmp multipath support for loc-rib bgpd: bmp multipath support for rib-out-pre bgpd: bmp add multipath syncing, fix startup-delay cmd bgpd: bmp simplify bpi locking system, add show bmp locked bgpd: remove locked path in bqe, fix withdraw flag, fix lbpi hash & cmp bgpd: no addpath id in mpls vpn case bgpd: peer types and peer distinguisher in all bmp messages Signed-off-by: Maxence Younsi --- bgpd/bgp_advertise.c | 18 +- bgpd/bgp_advertise.h | 12 +- bgpd/bgp_bmp.c | 1768 +++++++++++++++++++++++++++++------- bgpd/bgp_bmp.h | 128 ++- bgpd/bgp_conditional_adv.c | 25 +- bgpd/bgp_evpn.c | 2 +- bgpd/bgp_evpn_mh.c | 2 +- bgpd/bgp_main.c | 7 + bgpd/bgp_mpath.c | 44 +- bgpd/bgp_mpath.h | 19 +- bgpd/bgp_route.c | 165 +++- bgpd/bgp_route.h | 30 +- bgpd/bgp_updgrp.h | 14 + bgpd/bgp_updgrp_adv.c | 42 +- bgpd/bgpd.c | 3 + bgpd/bgpd.h | 5 +- doc/user/bmp.rst | 84 +- lib/pullwr.c | 13 + lib/pullwr.h | 1 + tests/bgpd/test_mpath.c | 0 20 files changed, 1971 insertions(+), 411 deletions(-) create mode 100644 tests/bgpd/test_mpath.c diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index d5c7e1887b60..7179c5835d3e 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -162,8 +162,8 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, } -void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr, - uint32_t addpath_id, struct bgp_labels *labels) +void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels) { struct bgp_adj_in *adj; @@ -182,29 +182,29 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr, } adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); adj->peer = peer_lock(peer); /* adj_in peer reference */ + adj->peer->stat_adj_in_count[afi][safi]++; adj->attr = bgp_attr_intern(attr); adj->uptime = monotime(NULL); adj->addpath_rx_id = addpath_id; adj->labels = bgp_labels_intern(labels); BGP_ADJ_IN_ADD(dest, adj); - peer->stat_pfx_adj_rib_in++; bgp_dest_lock_node(dest); } -void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai) +void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, + struct bgp_adj_in *bai) { bgp_attr_unintern(&bai->attr); bgp_labels_unintern(&bai->labels); - if (bai->peer) - bai->peer->stat_pfx_adj_rib_in--; BGP_ADJ_IN_DEL(*dest, bai); + bai->peer->stat_adj_in_count[afi][safi]--; *dest = bgp_dest_unlock_node(*dest); peer_unlock(bai->peer); /* adj_in peer reference */ XFREE(MTYPE_BGP_ADJ_IN, bai); } -bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer, - uint32_t addpath_id) +bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, + struct peer *peer, uint32_t addpath_id) { struct bgp_adj_in *adj; struct bgp_adj_in *adj_next; @@ -218,7 +218,7 @@ bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer, adj_next = adj->next; if (adj->peer == peer && adj->addpath_rx_id == addpath_id) - bgp_adj_in_remove(dest, adj); + bgp_adj_in_remove(dest, afi, safi, adj); adj = adj_next; diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index 8c831892b33d..ae71418bfb8d 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -140,12 +140,14 @@ struct bgp_synchronize { /* Prototypes. */ extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, uint32_t addpath_tx_id); -extern void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, - struct attr *attr, uint32_t addpath_id, +extern void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr, + uint32_t addpath_id, struct bgp_labels *labels); -extern bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer, - uint32_t addpath_id); -extern void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai); +extern bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, + struct peer *peer, uint32_t addpath_id); +extern void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, + struct bgp_adj_in *bai); extern unsigned int bgp_advertise_attr_hash_key(const void *p); extern bool bgp_advertise_attr_hash_cmp(const void *p1, const void *p2); diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 2e3a0388d0ed..95dde58f1aa0 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -2,6 +2,7 @@ /* BMP support. * Copyright (C) 2018 Yasuhiro Ohara * Copyright (C) 2019 David Lamparter for NetDEF, Inc. + * Copyright (C) 2023 Maxence Younsi */ #include @@ -24,6 +25,7 @@ #include "lib/version.h" #include "jhash.h" #include "termtable.h" +#include "time.h" #include "bgpd/bgp_table.h" #include "bgpd/bgpd.h" @@ -38,6 +40,10 @@ #include "bgpd/bgp_vty.h" #include "bgpd/bgp_trace.h" #include "bgpd/bgp_network.h" +#include "bgp_addpath.h" +#include "bgp_rd.h" +#include "bgpd/bgp_open.h" +#include "bgpd/bgp_aspath.h" #include "bgpd/bgp_label.h" #include "bgpd/bgp_open.h" #include "bgpd/bgp_aspath.h" @@ -63,9 +69,46 @@ DEFINE_MTYPE_STATIC(BMP, BMP, "BMP instance state"); DEFINE_MTYPE_STATIC(BMP, BMP_MIRRORQ, "BMP route mirroring buffer"); DEFINE_MTYPE_STATIC(BMP, BMP_PEER, "BMP per BGP peer data"); DEFINE_MTYPE_STATIC(BMP, BMP_OPEN, "BMP stored BGP OPEN message"); +DEFINE_MTYPE_STATIC(BMP, BMP_LBPI, "BMP locked BPI"); DEFINE_QOBJ_TYPE(bmp_targets); +/* module startup time for the startup-delay */ +static struct timeval bmp_startup_time = {0}; + +/* compute the time in millis since the bmp_startup_time recorded */ +static uint32_t bmp_time_since_startup(struct timeval *delay) +{ + + if (bmp_startup_time.tv_sec == 0 && bmp_startup_time.tv_usec == 0) { + zlog_info("bmp [%s]: Startup time not recorded", __func__); + return 0; + } + + uint32_t micros = (uint32_t)(monotime_since(&bmp_startup_time, delay)); + + return micros / 1000; +} + +/* convert the enum BMP_State to a human-friendly display string */ +static const char *bmp_state_str(enum BMP_State state) +{ + switch (state) { + + case BMP_StartupIdle: + return "Startup-Wait"; + case BMP_PeerUp: + return "Peer-Up"; + case BMP_Run: + return "Running"; + default: + return "Unknown"; + } +} + +/* comparison function for struct bmp_bgp used in bmp_bgph hashtable + * compares the pointer values of the bgp instance + */ static int bmp_bgp_cmp(const struct bmp_bgp *a, const struct bmp_bgp *b) { if (a->bgp < b->bgp) @@ -75,6 +118,9 @@ static int bmp_bgp_cmp(const struct bmp_bgp *a, const struct bmp_bgp *b) return 0; } +/* hash function for struct bmp_bgp used in bmp_bgph hashtable + * hashes based on the pointer value of the bgp instance + */ static uint32_t bmp_bgp_hash(const struct bmp_bgp *e) { return jhash(&e->bgp, sizeof(e->bgp), 0x55aa5a5a); @@ -82,8 +128,14 @@ static uint32_t bmp_bgp_hash(const struct bmp_bgp *e) DECLARE_HASH(bmp_bgph, struct bmp_bgp, bbi, bmp_bgp_cmp, bmp_bgp_hash); +/* hashtable to store the bmp state for a bgp instance + * lookup by struct bgp pointer value + */ struct bmp_bgph_head bmp_bgph; +/* comparison function for struct bmp_bgp_peer used in bmp_peerh hashtable + * compares the peer id of each peer (qobj ids) + */ static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer *a, const struct bmp_bgp_peer *b) { @@ -94,6 +146,9 @@ static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer *a, return 0; } +/* hash function for struct bmp_bgp_peer used in bmp_peerh hashtable + * hashes based on the peer id (qobj id) + */ static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer *e) { return e->peerid; @@ -102,8 +157,153 @@ static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer *e) DECLARE_HASH(bmp_peerh, struct bmp_bgp_peer, bpi, bmp_bgp_peer_cmp, bmp_bgp_peer_hash); +/* hashtable to store the bmp state for bgp peers state (open messages store) + * lookup by peer id (qobj id) + * this hashtable holds the head of head of a linked list of bgp path info + * for a specific bgp + destination prefix tuple then match on bpi pointer value + */ struct bmp_peerh_head bmp_peerh; +/* comparison function for struct bmp_bpi_lock used in bmp_lbpi_h hashtable + * compares the prefixes and bgp instance pointer values + */ +static int bmp_bpi_lock_cmp(const struct bmp_bpi_lock *a, + const struct bmp_bpi_lock *b) +{ + int cmp = prefix_cmp(bgp_dest_get_prefix(a->dest), bgp_dest_get_prefix(b->dest)); + if (cmp) + return cmp; + + if (a->bgp < b->bgp) + return -1; + if (a->bgp > b->bgp) + return 1; + + return 0; +} + +/* hash function for struct bmp_bpi_lock used in bmp_lbpi_h hashtable + * hashes based on the dest prefix and bgp instance pointer value + */ +static uint32_t bmp_bpi_lock_hash(const struct bmp_bpi_lock *e) +{ + uint32_t key = prefix_hash_key(bgp_dest_get_prefix(e->dest)); + + key = jhash(&e->bgp, sizeof(e->bgp), key); + return key; +} + +DECLARE_HASH(bmp_lbpi_h, struct bmp_bpi_lock, lbpi_h, bmp_bpi_lock_cmp, + bmp_bpi_lock_hash); + +/* hashtable to store the bgp path state when withdrawn + * allows rib-out pre-policy to run the pre-policy check on the path after + * it has been withdrawn + * lookup by destination prefix and bgp instance pointer value (vrf safe) + */ +struct bmp_lbpi_h_head bmp_lbpi; + +/* lock a bgp path info for a bgp instance and store it in bmp_lbpi + * allocate and store in hashtable if not exist + * lock bgp_path_info, dest and bgp to keep them in memory + * increment the lock + * returns the lock structure if successful + */ +static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, + struct bgp_path_info *bpi) +{ + if (!bpi && !bpi) + return NULL; + + BMP_LBPI_LOOKUP_BPI(head, prev, hash_lookup, bpi, bgp); + + if (!hash_lookup) { + hash_lookup = + XCALLOC(MTYPE_BMP_LBPI, sizeof(struct bmp_bpi_lock)); + SET_FLAG(bpi->flags, BGP_PATH_BMP_LOCKED); + hash_lookup->bgp = bgp; + hash_lookup->locked = bpi; + hash_lookup->dest = bpi->net; + hash_lookup->next = NULL; + hash_lookup->lock = 0; + bgp_lock(hash_lookup->bgp); + bgp_path_info_lock(hash_lookup->locked); + bgp_dest_lock_node(hash_lookup->dest); + + /* here prev is tail bc hash_lookup == tail->next == NULL */ + if (!prev) + bmp_lbpi_h_add(&bmp_lbpi, hash_lookup); + else + prev->next = hash_lookup; + } + + hash_lookup->lock++; + + return hash_lookup; +} + + +/* lock a bgp path info for a bgp instance and store it in bmp_lbpi + * look up locks for this bgp_path_info and bgp instance + * decrement the lock + * if lock is <= 0 we need to free the lock and unlock held structures + * returns the lock structure if it is not freed + */ +static struct bmp_bpi_lock *bmp_unlock_bpi(struct bgp *bgp, + struct bgp_path_info *bpi) +{ + + if (!bpi) + return NULL; + + BMP_LBPI_LOOKUP_BPI(head, prev, hash_lookup, bpi, bgp); + + /* nothing found, bpi is not locked, cannot unlock */ + if (!hash_lookup) + return NULL; + + /* unlock once */ + hash_lookup->lock--; + + /* if bpi is not used by bmp anymore */ + if (hash_lookup->lock <= 0) { + + struct bgp_path_info *tmp_bpi = hash_lookup->locked; + struct bgp_dest *tmp_dest = hash_lookup->dest; + struct bgp *tmp_bgp = hash_lookup->bgp; + + /* swap hash list head */ + if (head == hash_lookup) { + bmp_lbpi_h_del(&bmp_lbpi, hash_lookup); + if (head->next) + bmp_lbpi_h_add(&bmp_lbpi, head->next); + } + + /* relink list */ + if (prev) + prev->next = hash_lookup->next; + + UNSET_FLAG(bpi->flags, BGP_PATH_BMP_LOCKED); + XFREE(MTYPE_BMP_LBPI, hash_lookup); + bgp_unlock(tmp_bgp); + bgp_dest_unlock_node(tmp_dest); + bgp_path_info_unlock(tmp_bpi); + + return NULL; + } + + return hash_lookup; +} + +/* free a bqe */ +static inline void bmp_bqe_free(struct bmp_queue_entry *bqe) +{ + if (!bqe) + return; + + XFREE(MTYPE_BMP_QUEUE, bqe); +} + DECLARE_LIST(bmp_mirrorq, struct bmp_mirrorq, bmi); /* listener management */ @@ -148,6 +348,7 @@ static int bmp_qhash_cmp(const struct bmp_queue_entry *a, 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); @@ -193,6 +394,7 @@ static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry *e) - offsetof(struct bmp_queue_entry, refcount) + PSIZE(e->rd.prefixlen), key); + key = jhash(&e->addpath_id, sizeof(uint32_t), key); return key; } @@ -253,6 +455,7 @@ static void bmp_free(struct bmp *bmp) */ static inline int bmp_get_peer_type_vrf(vrf_id_t vrf_id) { + switch (vrf_id) { case VRF_DEFAULT: return BMP_PEER_TYPE_GLOBAL_INSTANCE; @@ -265,34 +468,61 @@ static inline int bmp_get_peer_type_vrf(vrf_id_t vrf_id) } /* determine the peer type for per-peer headers from a struct peer - * provide a bgp->peer_self for loc-rib + * bgp->peer_self will NOT give loc-rib peer type */ static inline int bmp_get_peer_type(struct peer *peer) { - if (peer->bgp->peer_self == peer) - return BMP_PEER_TYPE_LOC_RIB_INSTANCE; - return bmp_get_peer_type_vrf(peer->bgp->vrf_id); } -static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi, - uint8_t peer_type, +/* compute peer distinguisher from bmp session, afi and peer_type + * store it in result_ref + * + * providing AFI_UNSPEC as afi value will use any RD configured in the VRF + * + * returns 1 on error that needs message discarding + * 0 if successful + */ +static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, 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); + return (int)(*result_ref = 0); + + /* if requested afi has no rd configured find any other */ + if (afi >= AFI_MAX || !CHECK_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_RD_SET)) + afi = AFI_UNSPEC; + + /* afi not known, use any afi configured in this vrf */ + if (afi == AFI_UNSPEC) { + { /* scope lock iter variables */ + afi_t afi_rd_lookup; + safi_t _; + + FOREACH_AFI_SAFI (afi_rd_lookup, _) { + + if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup] + .flags, + BGP_VPN_POLICY_TOVPN_RD_SET)) { + afi = afi_rd_lookup; + /* stop FOREACH_AFI_SAFI macro */ + afi_rd_lookup = AFI_MAX; + } + + /* break safi sub-loop to go over next afi */ + break; + } + } + + /* no RD found for any AFI => error => skip message */ + if (afi == AFI_UNSPEC) { + zlog_warn( + "skipping bmp message for reason: can't get peer distinguisher (no RD configured)"); + return 1; + } + } /* use RD if set in VRF config for this AFI */ struct prefix_rd *prd = &bgp->vpn_policy[afi].tovpn_rd; @@ -304,14 +534,18 @@ static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi, } /* VRF has no id => error => message should be skipped */ - if (bgp->vrf_id == VRF_UNKNOWN) + if (bgp->vrf_id == VRF_UNKNOWN) { + zlog_warn( + "skipping bmp message for reason: can't get peer distinguisher (VRF badly configured)"); return 1; + } /* use VRF id converted to ::vrf_id 64bits format */ *result_ref = ((uint64_t)htonl(bgp->vrf_id)) << 32; return 0; } +/* add common header to the stream */ static void bmp_common_hdr(struct stream *s, uint8_t ver, uint8_t type) { stream_putc(s, ver); @@ -319,6 +553,7 @@ static void bmp_common_hdr(struct stream *s, uint8_t ver, uint8_t type) stream_putc(s, type); } +/* add per-peer header to the stream */ static void bmp_per_peer_hdr(struct stream *s, struct bgp *bgp, struct peer *peer, uint8_t flags, uint8_t peer_type_flag, @@ -328,6 +563,7 @@ static void bmp_per_peer_hdr(struct stream *s, struct bgp *bgp, #define BMP_PEER_FLAG_V (1 << 7) #define BMP_PEER_FLAG_L (1 << 6) #define BMP_PEER_FLAG_A (1 << 5) +#define BMP_PEER_FLAG_O (1 << 4) bool is_locrib = peer_type_flag == BMP_PEER_TYPE_LOC_RIB_INSTANCE; @@ -390,10 +626,11 @@ static void bmp_per_peer_hdr(struct stream *s, struct bgp *bgp, } } +/* put a string tlv with type 'type' to the stream */ static void bmp_put_info_tlv(struct stream *s, uint16_t type, const char *string) { - int len = strlen (string); + uint16_t len = (uint16_t)strlen(string); stream_putw(s, type); stream_putw(s, len); stream_put(s, string, len); @@ -415,6 +652,7 @@ static void bmp_put_vrftablename_info_tlv(struct stream *s, struct bgp *bgp) bmp_put_info_tlv(s, BMP_INFO_TYPE_VRFTABLENAME, vrftablename); } +/* send initiation message */ static int bmp_send_initiation(struct bmp *bmp) { int len; @@ -459,6 +697,7 @@ static void bmp_notify_put(struct stream *s, struct bgp_notify *nfy) } /* send peer up/down for peer based on down boolean value + * pass a bgp->peer_self for a vrf/loc-rib peer state message * returns the message to send or NULL if the peer_distinguisher is not * available */ @@ -472,8 +711,15 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) uptime.tv_usec = 0; monotime_to_realtime(&uptime, &uptime_real); - uint8_t peer_type = bmp_get_peer_type(peer); - bool is_locrib = peer_type == BMP_PEER_TYPE_LOC_RIB_INSTANCE; + bool is_locrib = peer->bgp->peer_self == peer; + uint8_t peer_type = is_locrib ? BMP_PEER_TYPE_LOC_RIB_INSTANCE + : bmp_get_peer_type(peer); + + uint64_t peer_distinguisher = 0; + /* skip this message if peer distinguisher is not available */ + if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, + &peer_distinguisher)) + return NULL; #define BGP_BMP_MAX_PACKET_SIZE 1024 #define BMP_PEERUP_INFO_TYPE_STRING 0 @@ -484,12 +730,11 @@ 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->bgp, peer, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, - &uptime_real); + bmp_per_peer_hdr(s, peer->bgp, peer, 0, peer_type, + peer_distinguisher, &uptime_real); /* Local Address (16 bytes) */ - if (is_locrib) + if (!peer->su_local || is_locrib) stream_put(s, 0, 16); else if (peer->su_local->sa.sa_family == AF_INET6) stream_put(s, &peer->su_local->sin6.sin6_addr, 16); @@ -548,9 +793,8 @@ 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->bgp, peer, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, - &uptime_real); + bmp_per_peer_hdr(s, peer->bgp, peer, 0, peer_type, + peer_distinguisher, &uptime_real); type_pos = stream_get_endp(s); stream_putc(s, 0); /* placeholder for down reason */ @@ -594,7 +838,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) return s; } - +/* send a peer up for each bgp peer of the bgp instance bmp is bound to */ static int bmp_send_peerup(struct bmp *bmp) { struct peer *peer; @@ -604,6 +848,9 @@ static int bmp_send_peerup(struct bmp *bmp) /* Walk down all peers */ for (ALL_LIST_ELEMENTS_RO(bmp->targets->bgp->peer, node, peer)) { s = bmp_peerstate(peer, false); + if (!s) + continue; + pullwr_write_stream(bmp->pullwr, s); stream_free(s); } @@ -611,6 +858,7 @@ static int bmp_send_peerup(struct bmp *bmp) return 0; } +/* send a peer up mesasge for a vrf */ static int bmp_send_peerup_vrf(struct bmp *bmp) { struct bmp_bgp *bmpbgp = bmp->targets->bmpbgp; @@ -636,6 +884,9 @@ static void bmp_send_all(struct bmp_bgp *bmpbgp, struct stream *s) struct bmp_targets *bt; struct bmp *bmp; + if (!s) + return; + frr_each(bmp_targets, &bmpbgp->targets, bt) frr_each(bmp_session, &bt->sessions, bmp) pullwr_write_stream(bmp->pullwr, s); @@ -662,6 +913,7 @@ static void bmp_send_all_safe(struct bmp_bgp *bmpbgp, struct stream *s) #define BMP_MIRROR_INFO_CODE_ERRORPDU 0 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1 +/* pull a queue item from the bmp mirroring queue */ static struct bmp_mirrorq *bmp_pull_mirror(struct bmp *bmp) { struct bmp_mirrorq *bmq; @@ -711,6 +963,7 @@ static void bmp_mirror_cull(struct bmp_bgp *bmpbgp) } } +/* queue a bmp mirror queue item for a peer */ static int bmp_mirror_packet(struct peer *peer, uint8_t type, bgp_size_t size, struct stream *packet) { @@ -767,6 +1020,7 @@ static int bmp_mirror_packet(struct peer *peer, uint8_t type, bgp_size_t size, return 0; } +/* send a bmp mirror lost message */ static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr) { struct stream *s; @@ -774,11 +1028,23 @@ static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr) gettimeofday(&tv, NULL); + struct bgp *bgp = bmp->targets->bgp; + + /* use the vrf based peer type to not get a loc-rib peer-type + * (undefined for mirror lost RFC7854) + */ + uint8_t peer_type = bmp_get_peer_type_vrf(bgp->vrf_id); + + uint64_t peer_distinguisher = 0; + /* skip this message if peer distinguisher is not available */ + if (bmp_get_peer_distinguisher(bgp, AFI_UNSPEC, &peer_distinguisher)) + return; + 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, bmp->targets->bgp->peer_self, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv); + bmp_per_peer_hdr(s, bgp, bgp->peer_self, 0, peer_type, + peer_distinguisher, &tv); stream_putw(s, BMP_MIRROR_TLV_TYPE_INFO); stream_putw(s, 2); @@ -790,6 +1056,9 @@ static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr) stream_free(s); } + +/* pulls a bmq and sends a bmp mirror message on the session + */ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr) { struct bmp_mirrorq *bmq; @@ -812,12 +1081,21 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr) goto out; } + uint8_t peer_type = bmp_get_peer_type(peer); + + uint64_t peer_distinguisher = 0; + /* skip this message if peer distinguisher is not available */ + if (bmp_get_peer_distinguisher(bmp->targets->bgp, AFI_UNSPEC, + &peer_distinguisher)) + goto out; + struct stream *s; 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, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &bmq->tv); + + bmp_per_peer_hdr(s, bmp->targets->bgp, peer, 0, peer_type, + peer_distinguisher, &bmq->tv); /* BMP Mirror TLV. */ stream_putw(s, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE); @@ -837,6 +1115,10 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr) return written; } + +/* triggered when a bgp packet is sent + * saves the packet if the packet was a bgp open + */ static int bmp_outgoing_packet(struct peer *peer, uint8_t type, bgp_size_t size, struct stream *packet) { @@ -854,6 +1136,10 @@ static int bmp_outgoing_packet(struct peer *peer, uint8_t type, bgp_size_t size, return 0; } + +/* triggered when a bgp peer goes up + * sends a bmp peer up to all bmp peers and saves the bgp open packet + */ static int bmp_peer_status_changed(struct peer *peer) { struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); @@ -902,6 +1188,9 @@ static int bmp_peer_status_changed(struct peer *peer) return 0; } +/* triggered when a bgp peer goes down + * sends a bmp peer down to all bmp peers and free the saved bgp open packet + */ static int bmp_peer_backward(struct peer *peer) { struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); @@ -924,6 +1213,10 @@ static int bmp_peer_backward(struct peer *peer) return 0; } + +/* sends a bmp end-of-rib on the bmp session for the given afi/safi + * for each peer + */ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags, uint8_t peer_type_flag) { @@ -967,18 +1260,17 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags, 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"); + if (bmp_get_peer_distinguisher(peer->bgp, afi, &peer_distinguisher)) continue; - } s2 = stream_new(BGP_MAX_PACKET_SIZE); bmp_common_hdr(s2, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING); + if (peer_type_flag != BMP_PEER_TYPE_LOC_RIB_INSTANCE) + peer_type_flag = bmp_get_peer_type(peer); + bmp_per_peer_hdr(s2, bmp->targets->bgp, peer, flags, peer_type_flag, peer_distinguisher, NULL); @@ -993,10 +1285,12 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags, stream_free(s); } +/* makes a bgp update to be embedded in a bmp monitoring message + */ 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, mpls_label_t *label, - uint32_t num_labels) + uint32_t addpath_id, struct peer *peer, + struct attr *attr, afi_t afi, safi_t safi, + mpls_label_t *label, uint32_t num_labels) { struct bpacket_attr_vec_arr vecarr; struct stream *s; @@ -1016,14 +1310,16 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, stream_putw(s, 0); /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */ - total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, safi, peer, - NULL, NULL, 0, 0, 0); + total_attr_len = + bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, + safi, peer, NULL, NULL, 0, + safi != SAFI_MPLS_VPN, addpath_id); /* space check? */ /* peer_cap_enhe & add-path removed */ if (afi == AFI_IP && safi == SAFI_UNICAST) - stream_put_prefix(s, p); + stream_put_prefix_addpath(s, p, 1, addpath_id); else { size_t p1 = stream_get_endp(s); @@ -1032,7 +1328,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, &vecarr, attr); bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, - num_labels, 0, 0, attr); + num_labels, safi != SAFI_MPLS_VPN, + addpath_id, attr); bgp_packet_mpattr_end(s, mpattrlen_pos); total_attr_len += stream_get_endp(s) - p1; } @@ -1043,9 +1340,11 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, return s; } +/* makes a bgp withdraw to be embedded in a bmp monitoring message + */ static struct stream *bmp_withdraw(const struct prefix *p, - struct prefix_rd *prd, afi_t afi, - safi_t safi) + struct prefix_rd *prd, uint32_t addpath_id, + afi_t afi, safi_t safi) { struct stream *s; size_t attrlen_pos = 0, mp_start, mplen_pos; @@ -1058,7 +1357,7 @@ static struct stream *bmp_withdraw(const struct prefix *p, stream_putw(s, 0); if (afi == AFI_IP && safi == SAFI_UNICAST) { - stream_put_prefix(s, p); + stream_put_prefix_addpath(s, p, 1, addpath_id); unfeasible_len = stream_get_endp(s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN; stream_putw_at(s, BGP_HEADER_SIZE, unfeasible_len); @@ -1070,7 +1369,8 @@ static struct stream *bmp_withdraw(const struct prefix *p, mp_start = stream_get_endp(s); mplen_pos = bgp_packet_mpunreach_start(s, afi, safi); - bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, 0, 0, + bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, + safi != SAFI_MPLS_VPN, addpath_id, NULL); /* Set the mp_unreach attr's length */ bgp_packet_mpunreach_end(s, mplen_pos); @@ -1084,11 +1384,15 @@ static struct stream *bmp_withdraw(const struct prefix *p, return s; } +/* sends a bmp monitoring message using the given information on the bmp session + * + * if uptime is (time_t)(-1L) then do not include the timestamp in the message + */ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, - uint8_t peer_type_flag, const struct prefix *p, + uint8_t peer_type, const struct prefix *p, struct prefix_rd *prd, struct attr *attr, afi_t afi, - safi_t safi, time_t uptime, mpls_label_t *label, - uint32_t num_labels) + safi_t safi, uint32_t addpath_id, time_t uptime, + mpls_label_t *label, uint32_t num_labels) { struct stream *hdr, *msg; struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 }; @@ -1096,23 +1400,20 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, 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"); + if (bmp_get_peer_distinguisher(bmp->targets->bgp, afi, + &peer_distinguisher)) return; - } monotime_to_realtime(&tv, &uptime_real); if (attr) - msg = bmp_update(p, prd, peer, attr, afi, safi, label, - num_labels); + msg = bmp_update(p, prd, addpath_id, peer, attr, afi, safi, + label, num_labels); else - msg = bmp_withdraw(p, prd, afi, safi); + msg = bmp_withdraw(p, prd, addpath_id, afi, safi); hdr = stream_new(BGP_MAX_PACKET_SIZE); bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING); - bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type_flag, + bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type, peer_distinguisher, uptime == (time_t)(-1L) ? NULL : &uptime_real); @@ -1126,6 +1427,176 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, stream_free(msg); } + +struct rib_out_pre_updgrp_walkctx { + struct bmp *bmp; + const struct prefix *pfx; + struct bgp_dest *dest; + struct bgp_path_info *bpi; + struct prefix_rd *prd; + struct attr *attr; + bool *written_ref; +}; + +/* bmp sync for rib-out pre-policy callback for each update group */ +static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, + void *hidden_ctx) +{ + struct rib_out_pre_updgrp_walkctx *ctx = + (struct rib_out_pre_updgrp_walkctx *)hidden_ctx; + + struct update_subgroup *subgrp; + struct peer_af *paf; + uint32_t addpath_tx_id; + struct bgp_path_info *bpi = ctx->bpi; + + UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { + + struct attr dummy_attr = {0}; + + if (!subgroup_announce_check(ctx->dest, bpi, subgrp, + ctx->pfx, &dummy_attr, NULL, + BGP_ANNCHK_SPECIAL_PREPOLICY)) + continue; + + SUBGRP_FOREACH_PEER (subgrp, paf) { + + addpath_tx_id = + !bpi ? 0 + : bgp_addpath_id_for_peer( + SUBGRP_PEER(subgrp), + SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), + &bpi->tx_addpath); + + bmp_monitor(ctx->bmp, PAF_PEER(paf), BMP_PEER_FLAG_O, + bmp_get_peer_type(PAF_PEER(paf)), bgp_dest_get_prefix(ctx->dest), + ctx->prd, ctx->attr, SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), addpath_tx_id, + (time_t)(-1L), + bpi->extra ? bpi->extra->labels->label : NULL, + bpi->extra ? bpi->extra->labels->num_labels : 0); + + *ctx->written_ref = true; + } + } + + return HASHWALK_CONTINUE; +}; + +/* bmp sync for rib-out pre-policy + * calls bmp_monitor_rib_out_pre_updgrp_walkcb foreach update group + */ +static inline bool bmp_monitor_rib_out_pre_walk(struct bmp *bmp, afi_t afi, + safi_t safi, const struct prefix *pfx, + struct bgp_dest *dest, + struct bgp_path_info *bpi, + struct attr *attr, + struct prefix_rd *prd) +{ + bool written = false; + struct rib_out_pre_updgrp_walkctx walkctx = {.bmp = bmp, + .pfx = pfx, + .dest = dest ? dest + : bpi->net, + .bpi = bpi, + .attr = attr, + .prd = prd, + .written_ref = &written}; + + update_group_af_walk(bmp->targets->bgp, afi, safi, + bmp_monitor_rib_out_pre_updgrp_walkcb, + (void *)&walkctx); + + return written; +} + +struct rib_out_post_updgrp_walkctx { + struct bmp *bmp; + const struct prefix *pfx; + struct bgp_dest *dest; + struct bgp_path_info *bpi; + struct prefix_rd *prd; + bool *written_ref; +}; + +/* bmp sync for rib-out post-policy callback for each update group */ +static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, + void *hidden_ctx) +{ + + + struct rib_out_post_updgrp_walkctx *ctx = + (struct rib_out_post_updgrp_walkctx *)hidden_ctx; + + struct update_subgroup *subgrp; + struct peer_af *paf; + struct bgp_adj_out *adj; + struct attr *advertised_attr; + uint32_t addpath_tx_id; + struct bgp_path_info *bpi = ctx->bpi; + + UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { + + addpath_tx_id = !bpi ? 0 + : bgp_addpath_id_for_peer( + SUBGRP_PEER(subgrp), + SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), + &bpi->tx_addpath); + + adj = adj_lookup(ctx->dest, subgrp, addpath_tx_id); + + if (!adj) + continue; + + advertised_attr = !adj->adv ? adj->attr + : adj->adv->baa ? adj->adv->baa->attr + : NULL; + + SUBGRP_FOREACH_PEER (subgrp, paf) { + bmp_monitor(ctx->bmp, PAF_PEER(paf), + BMP_PEER_FLAG_O | BMP_PEER_FLAG_L, + bmp_get_peer_type(PAF_PEER(paf)), ctx->pfx, ctx->prd, + advertised_attr, SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), addpath_tx_id, + (time_t)(-1L), + bpi->extra ? bpi->extra->labels->label : NULL, + bpi->extra ? bpi->extra->labels->num_labels : 0); + + *ctx->written_ref = true; + } + } + + return HASHWALK_CONTINUE; +}; + +/* bmp sync for rib-out post-policy + * calls bmp_monitor_rib_out_post_updgrp_walkcb for each update group + */ +static inline bool bmp_monitor_rib_out_post_walk( + struct bmp *bmp, afi_t afi, safi_t safi, + const struct prefix *pfx, struct bgp_dest *dest, + struct bgp_path_info *bpi, struct prefix_rd *prd) +{ + bool written = false; + struct rib_out_post_updgrp_walkctx walkctx = {.bmp = bmp, + .pfx = pfx, + .dest = dest, + .bpi = bpi, + .prd = prd, + .written_ref = &written}; + + update_group_af_walk(bmp->targets->bgp, afi, safi, + bmp_monitor_rib_out_post_updgrp_walkcb, + (void *)&walkctx); + + + return written; +} + +/* does the bmp initial rib synchronization + */ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) { uint8_t bpi_num_labels, adjin_num_labels; @@ -1227,12 +1698,32 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) bmp->remote, afi2str(afi), safi2str(safi)); - 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); + /* TODO refactor bmp_eor function to include + * loc-rib bgp->peer_self and new peer type + * function + */ + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_IN_PREPOLICY)) + bmp_eor(bmp, afi, safi, 0, + BMP_PEER_TYPE_GLOBAL_INSTANCE); + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_IN_POSTPOLICY)) + bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L, + BMP_PEER_TYPE_GLOBAL_INSTANCE); + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_LOC_RIB)) + bmp_eor(bmp, afi, safi, 0, + BMP_PEER_TYPE_LOC_RIB_INSTANCE); + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_OUT_PREPOLICY)) + bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_O, + BMP_PEER_TYPE_GLOBAL_INSTANCE); + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_OUT_POSTPOLICY)) + bmp_eor(bmp, afi, safi, + BMP_PEER_FLAG_O | + BMP_PEER_FLAG_L, + BMP_PEER_TYPE_GLOBAL_INSTANCE); bmp->afistate[afi][safi] = BMP_AFI_LIVE; bmp->syncafi = AFI_MAX; @@ -1244,15 +1735,16 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) } if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_POSTPOLICY) || - CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_LOC_RIB)) { + BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB | + BMP_MON_OUT_PREPOLICY | + BMP_MON_OUT_POSTPOLICY)) { for (bpiter = bgp_dest_get_bgp_path_info(bn); bpiter; bpiter = bpiter->next) { if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID) && !CHECK_FLAG(bpiter->flags, - BGP_PATH_SELECTED)) + BGP_PATH_SELECTED | + BGP_PATH_MULTIPATH)) continue; if (bpiter->peer->qobj_node.nid <= bmp->syncpeerid) @@ -1264,7 +1756,7 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) } } if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_PREPOLICY)) { + BMP_MON_IN_PREPOLICY)) { for (adjiter = bn->adj_in; adjiter; adjiter = adjiter->next) { if (adjiter->peer->qobj_node.nid @@ -1302,46 +1794,77 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) (safi == SAFI_MPLS_VPN)) prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos); + bool written = false; + + if (adjin) { + adjin_num_labels = adjin->labels ? adjin->labels->num_labels : 0; + bmp_monitor(bmp, adjin->peer, 0, bmp_get_peer_type(adjin->peer), bn_p, prd, + adjin->attr, afi, safi, adjin->addpath_rx_id, adjin->uptime, + adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); + written = true; + } + + uint8_t mon_flags = bmp->targets->afimon[afi][safi]; bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); - 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(mon_flags, BMP_MON_IN_POSTPOLICY)) { + bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, + bmp_get_peer_type(bpi->peer), bn_p, prd, bpi->attr, afi, + safi, bpi->addpath_rx_id, bpi->uptime, bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); + + UNSET_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG); + written = true; } - 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, + bool bpi_selected = + bpi && + CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH); + + if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_LOC_RIB)) { + bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, bn_p, + prd, bpi->attr, afi, safi, bpi->addpath_rx_id, + bpi && bpi->extra ? bpi->extra->bgp_rib_uptime + : (time_t)(-1L), bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); + written = true; + } - if (adjin) { - adjin_num_labels = adjin->labels ? adjin->labels->num_labels : 0; - bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, - adjin->attr, afi, safi, adjin->uptime, - adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); + if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_OUT_PREPOLICY)) { + written |= bmp_monitor_rib_out_pre_walk( + bmp, afi, safi, bgp_dest_get_prefix(bn), bn, bpi, bpi->attr, prd); + } + + if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_OUT_POSTPOLICY)) { + written |= bmp_monitor_rib_out_post_walk(bmp, afi, safi, bgp_dest_get_prefix(bn), + bn, bpi, prd); } if (bn) bgp_dest_unlock_node(bn); - return true; + /* if we got here and nothing is written it means this specific + * destination had no monitoring configured or configured monitoring + * had nothing to send. we need to bump for wrsync to be called for the + * following destinations in the table + */ + if (!written) + pullwr_bump(bmp->pullwr); + + return written; } +/* pulls a bqe from a given list + */ 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; + struct bmp_queue_entry *bqe = *queuepos_ptr; - bqe = *queuepos_ptr; if (!bqe) return NULL; @@ -1355,30 +1878,79 @@ bmp_pull_from_queue(struct bmp_qlist_head *list, struct bmp_qhash_head *hash, return bqe; } -static inline struct bmp_queue_entry *bmp_pull(struct bmp *bmp) +/* shortcut to pull a bqe from the rib-in pre-policy queue + */ +static inline struct bmp_queue_entry *bmp_pull_ribin(struct bmp *bmp) { - return bmp_pull_from_queue(&bmp->targets->updlist, - &bmp->targets->updhash, &bmp->queuepos); + return bmp_pull_from_queue(&bmp->targets->mon_in_updlist, + &bmp->targets->mon_in_updhash, + &bmp->mon_in_queuepos); } +/* shortcut to pull a bqe from the loc-rib + rib-in post-policy queue + */ 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); + return bmp_pull_from_queue(&bmp->targets->mon_loc_updlist, + &bmp->targets->mon_loc_updhash, + &bmp->mon_loc_queuepos); } -/* TODO BMP_MON_LOCRIB find a way to merge properly this function with - * bmp_wrqueue or abstract it if possible +/* shortcut to pull a bqe from the rib-out pre/post queue */ -static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) +static inline struct bmp_queue_entry *bmp_pull_ribout(struct bmp *bmp) +{ + return bmp_pull_from_queue(&bmp->targets->mon_out_updlist, + &bmp->targets->mon_out_updhash, + &bmp->mon_out_queuepos); +} + +/* returns 1 if the prefix will be synced later + * it means that we do not need to send an update about this prefix + */ +static inline int bmp_prefix_will_sync(struct bmp *bmp, afi_t afi, safi_t safi, + struct prefix *prefix) { + switch (bmp->afistate[afi][safi]) { + case BMP_AFI_INACTIVE: + case BMP_AFI_NEEDSYNC: + /* this afi will be synced later, wait for sync + */ + return 1; + case BMP_AFI_SYNC: + if (prefix_cmp(prefix, &bmp->syncpos) <= 0) + /* currently syncing but have already passed this + * prefix => send it. */ + return 0; + + /* currently syncing & haven't reached this prefix yet + * => it'll be sent as part of the table sync, no update here + */ + + return 1; + case BMP_AFI_LIVE: + /* this afi has already been synced, send an update + */ + return 0; + } + + return 0; +} + +/* gets a bqe from the loc-rib queue and sends a bmp monitoring message for + * loc-rib (if configured) and rib-out post-policy (if configured) + * the messages use the first selected path found in rib matching the prefix + * + * TODO BMP_MON_LOCRIB find a way to merge properly this function with + * bmp_wrqueue_in 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; - uint8_t bpi_num_labels; bqe = bmp_pull_locrib(bmp); if (!bqe) @@ -1386,71 +1958,175 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) afi_t afi = bqe->afi; safi_t safi = bqe->safi; + uint8_t flags = bmp->targets->afimon[afi][safi] & bqe->flags; - if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) + uint32_t addpath_rx_id = bqe->addpath_id; + + if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB)) goto out; - switch (bmp->afistate[afi][safi]) { - case BMP_AFI_INACTIVE: - case BMP_AFI_NEEDSYNC: + if (bmp_prefix_will_sync(bmp, afi, safi, &bqe->p)) 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 - */ + + 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; + } + + /* retrieve info about the selected path + */ + 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 *locrib = NULL, *ribin = NULL; + + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); + bpi; bpi = bpi->next) { + + /* match the right path */ + if (bpi->peer != peer || bpi->addpath_rx_id != addpath_rx_id) + continue; + + /* rib-in post-policy configured and path is valid */ + if (CHECK_FLAG(flags, BMP_MON_IN_POSTPOLICY) && + CHECK_FLAG(bpi->flags, BGP_PATH_VALID)) { + + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, + bmp_get_peer_type(peer), &bqe->p, prd, + bpi->attr, afi, safi, addpath_rx_id, + bpi->uptime, + bpi && bpi->extra ? bpi->extra->labels->label : NULL, + bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); + ribin = bpi; + written = true; + } + + /* loc-rib configured and path is selected */ + if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && + CHECK_FLAG(bpi->flags, + BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) { + uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); + + bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, + &bqe->p, prd, bpi->attr, afi, safi, + addpath_rx_id, + bpi->extra ? bpi->extra->bgp_rib_uptime + : (time_t)(-1L), + bpi_num_labels ? bpi->extra->labels->label : NULL, + bpi_num_labels); + locrib = bpi; + written = true; + } + + if (locrib && + ribin) /* early out when we've sent both messages */ + goto out; + } + + /* rib-in post-policy path not found, send withdraw */ + if (CHECK_FLAG(flags, BMP_MON_IN_POSTPOLICY) && !ribin) { + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, bmp_get_peer_type(peer), + &bqe->p, prd, NULL, afi, safi, addpath_rx_id, + (time_t)(-1), NULL, 0); + written = true; + } + + /* loc-rib path not found, send withdraw */ + if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && !locrib) { + bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, + NULL, afi, safi, addpath_rx_id, (time_t)(-1L), + NULL, 0); + written = true; + } + +out: + if (!bqe->refcount) + bmp_bqe_free(bqe); + + if (bn) + bgp_dest_unlock_node(bn); + + return written; +} + +/* gets a bqe from the rib-in pre-policy queue and sends a bmp monitoring + * message to the peer if configured about the + * first valid path found in adj-rib-in for this prefix + */ +static bool bmp_wrqueue_ribin(struct bmp *bmp, struct pullwr *pullwr) +{ + struct bmp_queue_entry *bqe; + struct peer *peer; + struct bgp_dest *bn = NULL; + bool written = false; + uint8_t adjin_num_labels; + + bqe = bmp_pull_ribin(bmp); + if (!bqe) + return false; + + afi_t afi = bqe->afi; + safi_t safi = bqe->safi; + uint32_t addpath_rx_id = bqe->addpath_id; + + if (bmp_prefix_will_sync(bmp, afi, safi, &bqe->p)) goto out; - case BMP_AFI_LIVE: - break; - } peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer); if (!peer) { - /* skipping queued item for deleted peer - */ + zlog_info("bmp: 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 - */ + if (!peer_established(peer->connection)) + goto out; + + if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_IN_PREPOLICY) || + !CHECK_FLAG(bqe->flags, BMP_MON_IN_PREPOLICY)) 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; + struct bgp_adj_in *adjin; - 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) + /* lookup adjin of this destination */ + for (adjin = bn ? bn->adj_in : NULL; adjin; adjin = adjin->next) { + /* match right path */ + if (adjin->peer == peer && + adjin->addpath_rx_id == addpath_rx_id) break; } - bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); + adjin_num_labels = adjin && adjin->labels ? adjin->labels->num_labels : 0; + bmp_monitor(bmp, peer, 0, bmp_get_peer_type(peer), &bqe->p, prd, + adjin ? adjin->attr : NULL, afi, safi, addpath_rx_id, + adjin ? adjin->uptime : monotime(NULL), + adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); - 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), - bpi_num_labels ? bpi->extra->labels->label : NULL, - bpi_num_labels); written = true; out: if (!bqe->refcount) - XFREE(MTYPE_BMP_QUEUE, bqe); + bmp_bqe_free(bqe); if (bn) bgp_dest_unlock_node(bn); @@ -1458,94 +2134,104 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) return written; } -static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr) +/* gets a bqe from the rib-out pre/post-policy queue and sends a bmp + * rib-out + * pre/post-policy monitoring message to the peer + */ +static bool bmp_wrqueue_ribout(struct bmp *bmp, struct pullwr *pullwr) { struct bmp_queue_entry *bqe; struct peer *peer; struct bgp_dest *bn = NULL; bool written = false; - uint8_t bpi_num_labels, adjin_num_labels; - bqe = bmp_pull(bmp); + bqe = bmp_pull_ribout(bmp); if (!bqe) return false; afi_t afi = bqe->afi; safi_t safi = bqe->safi; + uint32_t addpath_tx_id = bqe->addpath_id; - switch (bmp->afistate[afi][safi]) { - case BMP_AFI_INACTIVE: - case BMP_AFI_NEEDSYNC: + if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_OUT_POSTPOLICY | BMP_MON_OUT_PREPOLICY)) { 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 */ + if (bmp_prefix_will_sync(bmp, afi, safi, &bqe->p)) goto out; - case BMP_AFI_LIVE: - break; - } peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer); if (!peer) { zlog_info("bmp: skipping queued item for deleted peer"); goto out; } - if (!peer_established(peer->connection)) - 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); - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY)) { + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_OUT_PREPOLICY) && + CHECK_FLAG(bqe->flags, BMP_MON_OUT_PREPOLICY)) { + + /* lookup path in rib */ 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_VALID)) + if (addpath_tx_id != + bgp_addpath_id_for_peer(peer, afi, safi, + &bpi->tx_addpath)) continue; - if (bpi->peer == peer) + + if (CHECK_FLAG(bpi->flags, + BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) break; } - bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); + uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); - 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), + bmp_monitor(bmp, peer, BMP_PEER_FLAG_O, bmp_get_peer_type(peer), + &bqe->p, prd, bpi ? bpi->attr : NULL, afi, safi, + addpath_tx_id, (time_t)(-1L), bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); written = true; } - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_PREPOLICY)) { - struct bgp_adj_in *adjin; + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], + BMP_MON_OUT_POSTPOLICY) && + CHECK_FLAG(bqe->flags, BMP_MON_OUT_POSTPOLICY)) { + struct bgp_adj_out *adj; + struct attr *advertised_attr; + + /* lookup path in adj-rib-out */ + adj = adj_lookup(bn, peer_subgroup(peer, afi, safi), + addpath_tx_id); + + /* advertised attributes (NULL if withdrawn) */ + advertised_attr = adj ? !adj->adv ? adj->attr + : adj->adv->baa ? adj->adv->baa->attr + : NULL + : NULL; + + /* TODO: set label here when adjout supports labels */ + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L | BMP_PEER_FLAG_O, + bmp_get_peer_type(peer), &bqe->p, prd, + advertised_attr, afi, safi, addpath_tx_id, + (time_t)(-1L), NULL, 0); - for (adjin = bn ? bn->adj_in : NULL; adjin; - adjin = adjin->next) { - if (adjin->peer == peer) - break; - } - adjin_num_labels = adjin && adjin->labels ? adjin->labels->num_labels : 0; - bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd, - adjin ? adjin->attr : NULL, afi, safi, - adjin ? adjin->uptime : monotime(NULL), - adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); written = true; } out: if (!bqe->refcount) - XFREE(MTYPE_BMP_QUEUE, bqe); + bmp_bqe_free(bqe); if (bn) bgp_dest_unlock_node(bn); @@ -1553,9 +2239,28 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr) return written; } +/* called, when the socket is available, to retrieve data to send + */ static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr) { switch(bmp->state) { + case BMP_StartupIdle: { + uint32_t startup_delay = bmp->targets->bmpbgp->startup_delay_ms; + uint32_t timeout_ms = bmp_time_since_startup(NULL); + + if (timeout_ms < startup_delay) { + pullwr_timeout(pullwr, startup_delay - timeout_ms); + return; + } + + zlog_info("bmp: Startup timeout expired, time since startup is %" PRIu32 + "ms", timeout_ms); + bmp->state = BMP_PeerUp; + + /* start BMP_PeerUp mode now */ + bmp_wrfill(bmp, pullwr); + break; + } case BMP_PeerUp: bmp_send_peerup_vrf(bmp); bmp_send_peerup(bmp); @@ -1565,10 +2270,12 @@ static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr) case BMP_Run: if (bmp_wrmirror(bmp, pullwr)) break; - if (bmp_wrqueue(bmp, pullwr)) + if (bmp_wrqueue_ribin(bmp, pullwr)) break; if (bmp_wrqueue_locrib(bmp, pullwr)) break; + if (bmp_wrqueue_ribout(bmp, pullwr)) + break; if (bmp_wrsync(bmp, pullwr)) break; break; @@ -1587,10 +2294,19 @@ static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof) bmp_free(bmp); } +/* inserts a bmp_queue_entry in the updlist. overwrites any similar + * bmp_queue_entry in the list. + * + * returns the bqe inserted or NULL if updated an already existing bqe + * + * need to update correct queue pos for all sessions of the target after + * a call to this function + */ 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_qlist_head *updlist, afi_t afi, safi_t safi, + struct bgp_dest *bn, uint32_t addpath_id, struct peer *peer, + uint8_t mon_flag) { struct bmp_queue_entry *bqe, bqeref; size_t refcount; @@ -1604,6 +2320,8 @@ bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash, bqeref.peerid = peer->qobj_node.nid; bqeref.afi = afi; bqeref.safi = safi; + bqeref.flags = mon_flag; + bqeref.addpath_id = addpath_id; if ((afi == AFI_L2VPN && safi == SAFI_EVPN && bn->pdest) || (safi == SAFI_MPLS_VPN)) @@ -1612,9 +2330,14 @@ bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash, bqe = bmp_qhash_find(updhash, &bqeref); if (bqe) { - if (bqe->refcount >= refcount) - /* nothing to do here */ + SET_FLAG(bqe->flags, mon_flag); + + if (bqe->refcount >= refcount) { + /* same update, not sent to anyone yet, + * nothing to do here + */ return NULL; + } bmp_qlist_del(updlist, bqe); } else { @@ -1628,57 +2351,136 @@ bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash, bmp_qlist_add_tail(updlist, 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, - struct bgp_dest *bn, struct peer *peer, bool withdraw) + +/* triggered when a change in adj-rib-in is detected. + * if enabled in config, inserts a bqe to the adj-rib-in pre monitoring queue + * which will trigger a bmp monitoring message to be sent for adj-rib-in pre + */ +static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, + struct bgp_dest *bn, uint32_t addpath_id, + struct peer *peer, bool post) { struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); struct bmp_targets *bt; struct bmp *bmp; - if (frrtrace_enabled(frr_bgp, bmp_process)) { + if (frrtrace_enabled(frr_bgp, bmp_process_ribinpre)) { char pfxprint[PREFIX2STR_BUFFER]; prefix2str(&bn->rn->p, pfxprint, sizeof(pfxprint)); - frrtrace(5, frr_bgp, bmp_process, peer, pfxprint, afi, safi, - withdraw); + frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, + safi, withdraw); } if (!bmpbgp) return 0; + /* mark paths that changed in adj-rib-in pre-policy + * allows rib-in post to know which path has changed in adj-in and needs + * a bmp update + * + * (trigger is called later for VALID state to be evaluated) + * this is needed because where the trigger is called (bgp_process) + * we don't know because of which adj-in update we recompute the + * best-path + */ + if (post) { + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); + bpi; bpi = bpi->next) + if (bpi->peer == peer && + bpi->addpath_rx_id == addpath_id) + SET_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG); + } + frr_each(bmp_targets, &bmpbgp->targets, bt) { - /* 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)) + if (!CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_IN_PREPOLICY)) continue; - struct bmp_queue_entry *last_item = - bmp_process_one(bt, &bt->updhash, &bt->updlist, bgp, - afi, safi, bn, peer); + struct bmp_queue_entry *new_item = bmp_process_one( + bt, &bt->mon_in_updhash, &bt->mon_in_updlist, afi, safi, + bn, addpath_id, peer, BMP_MON_IN_PREPOLICY); /* if bmp_process_one returns NULL * we don't have anything to do next */ - if (!last_item) + if (!new_item) continue; frr_each(bmp_session, &bt->sessions, bmp) { - if (!bmp->queuepos) - bmp->queuepos = last_item; + if (!bmp->mon_in_queuepos) + bmp->mon_in_queuepos = new_item; + + pullwr_bump(bmp->pullwr); + } + } + return 0; +} + +/* triggered when a change in adj-rib-in post-policy is detected. + * if enabled in config, inserts a bqe to the loc-rib / rib-in-post + * monitoring queue which will trigger a bmp monitoring message to be sent + * for adj-rib-in post-policy + */ +static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, + struct bgp_dest *bn) +{ + struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp); + struct bmp_targets *bt; + struct bmp *bmp; + + if (frrtrace_enabled(frr_bgp, bmp_process_ribinpre)) { + char pfxprint[PREFIX2STR_BUFFER]; + + prefix2str(bgp_dest_get_prefix(bn), pfxprint, sizeof(pfxprint)); + frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, + safi, withdraw); + } + + if (!bmpbgp) + return 0; + + + frr_each (bmp_targets, &bmpbgp->targets, bt) { + if (!CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_IN_POSTPOLICY)) + continue; + + struct bmp_queue_entry *new_head = NULL, *new_item = NULL; + + /* find paths that changed in pre-policy and need update */ + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); + bpi; bpi = bpi->next) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG)) { + new_item = bmp_process_one( + bt, &bt->mon_loc_updhash, + &bt->mon_loc_updlist, afi, safi, bn, + bpi->addpath_rx_id, bpi->peer, + BMP_MON_IN_POSTPOLICY); + + new_head = !new_head ? new_item : new_head; + + UNSET_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG); + } + } + + // if bmp_process_one returns NULL + // we don't have anything to do next + if (!new_head) + continue; + + frr_each (bmp_session, &bt->sessions, bmp) { + if (!bmp->mon_loc_queuepos) + bmp->mon_loc_queuepos = new_head; pullwr_bump(bmp->pullwr); } } + return 0; } +/* put a u32 stat to the stream */ static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type, uint32_t value) { @@ -1688,6 +2490,7 @@ static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type, (*cnt)++; } +/* put a u64 stat to the stream */ static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type, uint64_t value) { @@ -1697,6 +2500,36 @@ static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type, (*cnt)++; } +/* put a per-AFI/SAFI u64 stat to the stream */ +static void bmp_stat_put_af_u64(struct stream *s, size_t *cnt, uint16_t type, + afi_t afi, safi_t safi, uint64_t value) +{ + stream_putw(s, type); + stream_putw(s, 2 + 1 + 8); + stream_put3(s, (afi_int2iana(afi) << 8) + safi_int2iana(safi)); + stream_putq(s, value); + (*cnt)++; +} + + +/* macro that sends a stat per AFI/SAFI and the total sum of sub-stats. + * per AFI/SAFI is not sent if 0 and force_zero == false + */ +#define BMP_PER_AF_STAT(afi_var, safi_var, af_stat_arr, sum_var, safi_stat, \ + safi_stat_call, sum_stat_call, force_zero) \ + do { \ + (sum_var) = 0; \ + FOREACH_AFI_SAFI ((afi_var), (safi_var)) { \ + (sum_var) += ((af_stat_arr)[(afi_var)][(safi_var)] = \ + (safi_stat)); \ + if ((force_zero) || \ + (af_stat_arr)[(afi_var)][(safi_var)]) \ + (safi_stat_call); \ + }; \ + (sum_stat_call); \ + } while (0) + +/* send stats and reschedule event */ static void bmp_stats(struct event *thread) { struct bmp_targets *bt = EVENT_ARG(thread); @@ -1704,6 +2537,12 @@ static void bmp_stats(struct event *thread) struct peer *peer; struct listnode *node; struct timeval tv; + afi_t afi; + safi_t safi; + + uint64_t af_stat[AFI_MAX][SAFI_MAX]; + struct update_subgroup *subgrp; + if (bt->stat_msec) event_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec, @@ -1714,37 +2553,82 @@ static void bmp_stats(struct event *thread) /* Walk down all peers */ for (ALL_LIST_ELEMENTS_RO(bt->bgp->peer, node, peer)) { size_t count = 0, count_pos, len; + uint64_t per_af_sum = 0; if (!peer_established(peer->connection)) continue; + uint8_t peer_type = bmp_get_peer_type(peer); + + uint64_t peer_distinguisher = 0; + /* skip this message if peer distinguisher is not available */ + if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, + &peer_distinguisher)) + continue; + + s = stream_new(BGP_MAX_PACKET_SIZE); bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT); bmp_per_peer_hdr(s, bt->bgp, peer, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE, 0, &tv); + peer_type, peer_distinguisher, &tv); count_pos = stream_get_endp(s); stream_putl(s, 0); bmp_stat_put_u32(s, &count, BMP_STATS_PFX_REJECTED, peer->stat_pfx_filter); + bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW, + peer->stat_pfx_dup_withdraw); + bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER, + peer->stat_pfx_cluster_loop); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ASPATH, peer->stat_pfx_aspath_loop); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ORIGINATOR, - peer->stat_pfx_originator_loop); - bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER, - peer->stat_pfx_cluster_loop); - bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW, - peer->stat_pfx_dup_withdraw); + peer->stat_pfx_originator_loop); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW, peer->stat_upd_7606); + + BMP_PER_AF_STAT( + afi, safi, af_stat, per_af_sum, + peer->stat_adj_in_count[afi][safi], + bmp_stat_put_af_u64( + s, &count, + BMP_STATS_SIZE_ADJ_RIB_IN_SAFI, afi, + safi, af_stat[afi][safi]), + bmp_stat_put_u64(s, &count, + BMP_STATS_SIZE_ADJ_RIB_IN, + per_af_sum), + false); + + BMP_PER_AF_STAT(afi, safi, af_stat, per_af_sum, + peer->stat_loc_rib_count[afi][safi], + bmp_stat_put_af_u64( + s, &count, + BMP_STATS_SIZE_LOC_RIB_SAFI, + afi, safi, af_stat[afi][safi]), + bmp_stat_put_u64(s, &count, + BMP_STATS_SIZE_LOC_RIB, + per_af_sum), + false); + + BMP_PER_AF_STAT( + afi, safi, af_stat, per_af_sum, + ((subgrp = peer_subgroup(peer, afi, safi)) + ? subgrp->pscount + : 0), + bmp_stat_put_af_u64( + s, &count, + BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI, + afi, safi, af_stat[afi][safi]), + bmp_stat_put_u64( + s, &count, + BMP_STATS_SIZE_ADJ_RIB_OUT_POST, + per_af_sum), + false); + if (bt->stats_send_experimental) bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID, - peer->stat_pfx_nh_invalid); - bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN, - peer->stat_pfx_adj_rib_in); - bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_LOC_RIB, - peer->stat_pfx_loc_rib); + peer->stat_pfx_nh_invalid); stream_putl_at(s, count_pos, count); @@ -1825,9 +2709,9 @@ static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock) sockunion2str(&su, buf, SU_ADDRSTRLEN); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":%u", - su.sa.sa_family == AF_INET - ? ntohs(su.sin.sin_port) - : ntohs(su.sin6.sin6_port)); + su.sa.sa_family == AF_INET + ? ntohs(su.sin.sin_port) + : ntohs(su.sin6.sin6_port)); if (ret == FILTER_DENY) { bt->cnt_aclrefused++; @@ -1850,9 +2734,9 @@ static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock) bmp = bmp_new(bt, bmp_sock); strlcpy(bmp->remote, buf, sizeof(bmp->remote)); - bmp->state = BMP_PeerUp; + bmp->state = BMP_StartupIdle; bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill, - bmp_wrerr); + bmp_wrerr); event_add_read(bm->master, bmp_read, bmp, bmp_sock, &bmp->t_read); bmp_send_initiation(bmp); @@ -1893,12 +2777,15 @@ static void bmp_close(struct bmp *bmp) while ((bmq = bmp_pull_mirror(bmp))) if (!bmq->refcount) XFREE(MTYPE_BMP_MIRRORQ, bmq); - while ((bqe = bmp_pull(bmp))) + while ((bqe = bmp_pull_ribin(bmp))) if (!bqe->refcount) - XFREE(MTYPE_BMP_QUEUE, bqe); + bmp_bqe_free(bqe); while ((bqe = bmp_pull_locrib(bmp))) if (!bqe->refcount) - XFREE(MTYPE_BMP_QUEUE, bqe); + bmp_bqe_free(bqe); + while ((bqe = bmp_pull_ribout(bmp))) + if (!bqe->refcount) + bmp_bqe_free(bqe); EVENT_OFF(bmp->t_read); pullwr_del(bmp->pullwr); @@ -1923,6 +2810,7 @@ static struct bmp_bgp *bmp_bgp_get(struct bgp *bgp) bmpbgp->bgp = bgp; bmpbgp->vrf_state = vrf_state_unknown; bmpbgp->mirror_qsizelimit = ~0UL; + bmpbgp->startup_delay_ms = 0; bmp_mirrorq_init(&bmpbgp->mirrorq); bmp_bgph_add(&bmp_bgph, bmpbgp); @@ -2034,6 +2922,7 @@ bool bmp_bgp_update_vrf_status(struct bmp_bgp *bmpbgp, enum bmp_vrf_state force) static struct bmp_bgp_peer *bmp_bgp_peer_find(uint64_t peerid) { struct bmp_bgp_peer dummy = { .peerid = peerid }; + return bmp_peerh_find(&bmp_peerh, &dummy); } @@ -2077,10 +2966,12 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name) bt->bmpbgp = bmp_bgp_get(bgp); bt->stats_send_experimental = true; 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_qhash_init(&bt->mon_in_updhash); + bmp_qlist_init(&bt->mon_in_updlist); + bmp_qhash_init(&bt->mon_loc_updhash); + bmp_qlist_init(&bt->mon_loc_updlist); + bmp_qhash_init(&bt->mon_out_updhash); + bmp_qlist_init(&bt->mon_out_updlist); bmp_actives_init(&bt->actives); bmp_listeners_init(&bt->listeners); @@ -2109,10 +3000,12 @@ static void bmp_targets_put(struct bmp_targets *bt) bmp_listeners_fini(&bt->listeners); 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); + bmp_qhash_fini(&bt->mon_in_updhash); + bmp_qlist_fini(&bt->mon_in_updlist); + bmp_qhash_fini(&bt->mon_loc_updhash); + bmp_qlist_fini(&bt->mon_loc_updlist); + bmp_qhash_fini(&bt->mon_out_updhash); + bmp_qlist_fini(&bt->mon_out_updlist); XFREE(MTYPE_BMP_ACLNAME, bt->acl_name); XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name); @@ -2297,7 +3190,7 @@ static void bmp_active_connect(struct bmp_active *ba) res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos], - htons(ba->port), 0); + htons(ba->port), 0); switch (res) { case connect_error: zlog_warn("bmp[%s]: failed to connect to %pSU:%d", @@ -2671,17 +3564,36 @@ DEFPY(bmp_stats_send_experimental, return CMD_SUCCESS; } -#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 */ +/* |l|oc-rib */ +#define BMP_POLICY_IS_LOCRIB(rib) ((rib)[0] == 'l') +/* rib-|i|n p|r|e-policy */ +#define BMP_POLICY_IS_IN_PRE(rib, policy) ((rib)[4] == 'i' \ + && (policy) \ + && (policy)[1] == 'r') \ + /* rib-|i|n p|o|st-policy */ +#define BMP_POLICY_IS_IN_POST(rib, policy) ((rib)[4] == 'i' \ + && (policy) \ + && (policy)[1] == 'o') \ + /* rib-|o|ut p|r|e-policy */ +#define BMP_POLICY_IS_OUT_PRE(rib, policy) ((rib)[4] == 'o' \ + && (policy) \ + && (policy)[1] == 'r') \ + /* rib-|o|ut p|o|st-policy */ +#define BMP_POLICY_IS_OUT_POST(rib, policy) ((rib)[4] == 'o' \ + && (policy) \ + && (policy)[1] == 'o') DEFPY(bmp_monitor_cfg, bmp_monitor_cmd, - "[no] bmp monitor $policy", + "[no] bmp monitor $rib [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 - "Send state before policy and filter processing\n" - "Send state with policy and filters applied\n" - "Send state after decision process is applied\n") + BGP_AF_MODIFIER_STR BGP_AF_MODIFIER_STR BGP_AF_MODIFIER_STR + BGP_AF_MODIFIER_STR + "Monitor BGP Adj-RIB-In\n" + "Monitor BGP Local-RIB\n" + "Monitor BGP Adj-RIB-Out\n" + "Send state of Adj-RIB-In/out before in/outbound policy is applied\n" + "Send state of Adj-RIB-In/out after in/outbound policy is applied\n") { int index = 0; uint8_t flag, prev; @@ -2694,12 +3606,20 @@ DEFPY(bmp_monitor_cfg, bmp_monitor_cmd, argv_find_and_parse_afi(argv, argc, &index, &afi); argv_find_and_parse_safi(argv, argc, &index, &safi); - if (BMP_POLICY_IS_LOCRIB(policy)) + if (BMP_POLICY_IS_LOCRIB(rib)) { flag = BMP_MON_LOC_RIB; - else if (BMP_POLICY_IS_PRE(policy)) - flag = BMP_MON_PREPOLICY; - else - flag = BMP_MON_POSTPOLICY; + } else if (BMP_POLICY_IS_IN_PRE(rib, policy)) { + flag = BMP_MON_IN_PREPOLICY; + } else if (BMP_POLICY_IS_IN_POST(rib, policy)) { + flag = BMP_MON_IN_POSTPOLICY; + } else if (BMP_POLICY_IS_OUT_PRE(rib, policy)) { + flag = BMP_MON_OUT_PREPOLICY; + } else if (BMP_POLICY_IS_OUT_POST(rib, policy)) { + flag = BMP_MON_OUT_POSTPOLICY; + } else { + vty_out(vty, "%% Target RIB doesn't exist\n"); + return CMD_WARNING; + } prev = bt->afimon[afi][safi]; if (no) @@ -2722,6 +3642,8 @@ DEFPY(bmp_monitor_cfg, bmp_monitor_cmd, } bmp->afistate[afi][safi] = BMP_AFI_NEEDSYNC; + + pullwr_bump(bmp->pullwr); } return CMD_SUCCESS; @@ -2789,12 +3711,28 @@ DEFPY(no_bmp_mirror_limit_cfg, return CMD_SUCCESS; } +DEFPY(bmp_startup_delay_cfg, bmp_startup_delay_cmd, + "[no] bmp startup-delay [(0-4294967294)]$startup_delay", + NO_STR BMP_STR + "Configure delay before BMP starts sending monitoring and mirroring messages\n" + "Time in milliseconds\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct bmp_bgp *bmpbgp; + + if (!no && startup_delay < 0) { + vty_out(vty, "Missing startup delay parameter\n"); + return CMD_ERR_INCOMPLETE; + } + + bmpbgp = bmp_bgp_get(bgp); + bmpbgp->startup_delay_ms = !no ? startup_delay : 0; + + return CMD_SUCCESS; +} -DEFPY(show_bmp, - show_bmp_cmd, - "show bmp", - SHOW_STR - BMP_STR) +/* show the classic 'show bmp' information */ +static void bmp_show_bmp(struct vty *vty) { struct bmp_bgp *bmpbgp; struct bmp_targets *bt; @@ -2805,19 +3743,29 @@ DEFPY(show_bmp, char uptime[BGP_UPTIME_LEN]; char *out; + vty_out(vty, "BMP Module started at %pTVM\n\n", &bmp_startup_time); frr_each(bmp_bgph, &bmp_bgph, bmpbgp) { vty_out(vty, "BMP state for BGP %s:\n\n", - bmpbgp->bgp->name_pretty); - vty_out(vty, " Route Mirroring %9zu bytes (%zu messages) pending\n", - bmpbgp->mirror_qsize, - bmp_mirrorq_count(&bmpbgp->mirrorq)); - vty_out(vty, " %9zu bytes maximum buffer used\n", - bmpbgp->mirror_qsizemax); + bmpbgp->bgp->name_pretty); + vty_out(vty, + " Route Mirroring %9zu bytes (%zu messages) pending\n", + bmpbgp->mirror_qsize, + bmp_mirrorq_count(&bmpbgp->mirrorq)); + vty_out(vty, + " %9zu bytes maximum buffer used\n", + bmpbgp->mirror_qsizemax); if (bmpbgp->mirror_qsizelimit != ~0UL) - vty_out(vty, " %9zu bytes buffer size limit\n", - bmpbgp->mirror_qsizelimit); + vty_out(vty, + " %9zu bytes buffer size limit\n", + bmpbgp->mirror_qsizelimit); vty_out(vty, "\n"); + vty_out(vty, " Startup delay : %s", + bmpbgp->startup_delay_ms == 0 ? "Immediate\n\n" : ""); + if (bmpbgp->startup_delay_ms != 0) + vty_out(vty, "%" PRIu32 "ms\n\n", + bmpbgp->startup_delay_ms); + frr_each(bmp_targets, &bmpbgp->targets, bt) { vty_out(vty, " Targets \"%s\":\n", bt->name); vty_out(vty, " Route Mirroring %sabled\n", @@ -2833,25 +3781,36 @@ DEFPY(show_bmp, if (!afimon_flag) continue; - const char *pre_str = + const char *in_pre_str = CHECK_FLAG(afimon_flag, - BMP_MON_PREPOLICY) - ? "pre-policy " + BMP_MON_IN_PREPOLICY) + ? "rib-in pre-policy " : ""; - const char *post_str = + const char *in_post_str = CHECK_FLAG(afimon_flag, - BMP_MON_POSTPOLICY) - ? "post-policy " + BMP_MON_IN_POSTPOLICY) + ? "rib-in post-policy " : ""; const char *locrib_str = CHECK_FLAG(afimon_flag, BMP_MON_LOC_RIB) - ? "loc-rib" + ? "loc-rib " + : ""; + const char *out_pre_str = + CHECK_FLAG(afimon_flag, + BMP_MON_OUT_PREPOLICY) + ? "rib-out pre-policy " + : ""; + const char *out_post_str = + CHECK_FLAG(afimon_flag, + BMP_MON_OUT_POSTPOLICY) + ? "rib-out post-policy " : ""; vty_out(vty, - " Route Monitoring %s %s %s%s%s\n", - afi2str(afi), safi2str(safi), pre_str, - post_str, locrib_str); + " Route Monitoring %s %s %s%s%s%s%s\n", + afi2str(afi), safi2str(safi), + in_pre_str, in_post_str, locrib_str, + out_pre_str, out_post_str); } vty_out(vty, " Listeners:\n"); @@ -2899,7 +3858,6 @@ DEFPY(show_bmp, state_str, ba->last_err ? ba->last_err : "", uptime, &ba->addrsrc); - continue; } out = ttable_dump(tt, "\n"); vty_out(vty, "%s", out); @@ -2909,7 +3867,9 @@ DEFPY(show_bmp, vty_out(vty, "\n %zu connected clients:\n", bmp_session_count(&bt->sessions)); tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); - ttable_add_row(tt, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel"); + ttable_add_row( + tt, + "remote|uptime|state|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel"); ttable_rowseps(tt, 0, BOTTOM, true, '-'); frr_each (bmp_session, &bt->sessions, bmp) { @@ -2921,12 +3881,12 @@ DEFPY(show_bmp, peer_uptime(bmp->t_up.tv_sec, uptime, sizeof(uptime), false, NULL); - ttable_add_row(tt, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu", - bmp->remote, uptime, - bmp->cnt_update, - bmp->cnt_mirror, - bmp->cnt_mirror_overruns, - total, q, kq); + ttable_add_row( + tt, "%s|%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu", + bmp->remote, uptime, + bmp_state_str(bmp->state), + bmp->cnt_update, bmp->cnt_mirror, + bmp->cnt_mirror_overruns, total, q, kq); } out = ttable_dump(tt, "\n"); vty_out(vty, "%s", out); @@ -2935,6 +3895,52 @@ DEFPY(show_bmp, vty_out(vty, "\n"); } } +} + +/* show the bpi locked by bmp with 'show bmp locked' */ +static void bmp_show_locked(struct vty *vty) +{ + + vty_out(vty, "BMP: BGP Paths locked for use in the Monitoring\n"); + struct bmp_bpi_lock *lbpi_iter; + + frr_each (bmp_lbpi_h, &bmp_lbpi, lbpi_iter) { + if (!lbpi_iter) + continue; + + vty_out(vty, "Bucket:\n"); + + int n = 0; + struct bmp_bpi_lock *lbpi_curr = lbpi_iter; + + do { + if (!lbpi_curr->locked) { + vty_out(vty, " [%d] Empty node\n", n); + continue; + } + + vty_out(vty, + " [#%d][lock=%d] %s: bgp id=%" PRId64 + " dest=%pBD rx_id=%" PRIu32 " from peer=%pBP\n", + n, lbpi_curr->lock, n == 0 ? "head" : "node", + lbpi_curr->bgp ? (int64_t)lbpi_curr->bgp->vrf_id + : -1, + lbpi_curr->locked->net, + lbpi_curr->locked->addpath_rx_id, + lbpi_curr->locked->peer); + n++; + } while ((lbpi_curr = lbpi_curr->next)); + } +} + +/* command router for 'show bmp' command */ +DEFPY(show_bmp, show_bmp_cmd, "show bmp [locked]$locked", + SHOW_STR BMP_STR "Display information specific to paths locked by BMP\n") +{ + if (locked) + bmp_show_locked(vty); + else + bmp_show_bmp(vty); return CMD_SUCCESS; } @@ -2955,6 +3961,10 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) vty_out(vty, " !\n bmp mirror buffer-limit %zu\n", bmpbgp->mirror_qsizelimit); + if (bmpbgp->startup_delay_ms != 0) + vty_out(vty, " !\n bmp startup-delay %" PRIu32 "\n", + bmpbgp->startup_delay_ms); + frr_each(bmp_targets, &bmpbgp->targets, bt) { vty_out(vty, " !\n bmp targets %s\n", bt->name); @@ -2975,17 +3985,28 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) FOREACH_AFI_SAFI (afi, safi) { if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_PREPOLICY)) - vty_out(vty, " bmp monitor %s %s pre-policy\n", + BMP_MON_IN_PREPOLICY)) + vty_out(vty, + " bmp monitor %s %s rib-in pre-policy\n", afi2str_lower(afi), safi2str(safi)); if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_POSTPOLICY)) + BMP_MON_IN_POSTPOLICY)) vty_out(vty, - " bmp monitor %s %s post-policy\n", + " bmp monitor %s %s rib-in 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_lower(afi), safi2str(safi)); + if (CHECK_FLAG(bt->afimon[afi][safi], + BMP_MON_OUT_PREPOLICY)) + vty_out(vty, + " bmp monitor %s %s rib-out pre-policy\n", + afi2str_lower(afi), safi2str(safi)); + if (CHECK_FLAG(bt->afimon[afi][safi], + BMP_MON_OUT_POSTPOLICY)) + vty_out(vty, + " bmp monitor %s %s rib-out post-policy\n", + afi2str_lower(afi), safi2str(safi)); } frr_each (bmp_listeners, &bt->listeners, bl) vty_out(vty, " bmp listener %pSU port %d\n", &bl->addr, bl->port); @@ -3027,23 +4048,38 @@ static int bgp_bmp_init(struct event_loop *tm) install_element(BGP_NODE, &bmp_mirror_limit_cmd); install_element(BGP_NODE, &no_bmp_mirror_limit_cmd); + install_element(BGP_NODE, &bmp_startup_delay_cmd); install_element(VIEW_NODE, &show_bmp_cmd); resolver_init(tm); + + monotime(&bmp_startup_time); + return 0; } +/* this function is triggered when a route is updated is the BGP RIB + * it puts a bmp_queue_entry in the loc-rib queue which will trigger a bmp + * monitoring message for loc-rib based on config + */ 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; + /* lock the bpi in case of withdraw for rib-out pre-policy + * do this unconditionally because bmp_path_unlock hook will always be + * called whether rib-out mon is configured or not and this avoids + * problems in case of configuration changes between lock and unlock + * calls + */ + if (old_route) + bmp_lock_bpi(bgp, old_route); /* this should never happen */ if (!updated_route) { @@ -3052,26 +4088,17 @@ static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi, } 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 */ + /* route is not installed in loc-rib 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 + /* route is installed in loc-rib from now on so * save rib uptime in bgp_path_info_extra */ if (new_route) @@ -3079,22 +4106,144 @@ static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi, monotime(NULL); frr_each (bmp_targets, &bmpbgp->targets, bt) { - if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) { + if (!CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_LOC_RIB)) + continue; + + struct bmp_queue_entry *new_head = NULL; + + /* send withdraw for previously selected best-path in case of + * best path change + */ + if (old_route && new_route && old_route != new_route) { + new_head = bmp_process_one( + bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, + afi, safi, bn, old_route->addpath_rx_id, + old_route->peer, BMP_MON_LOC_RIB); + } + + struct bmp_queue_entry *new_item = bmp_process_one( + bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, afi, + safi, bn, updated_route->addpath_rx_id, + updated_route->peer, BMP_MON_LOC_RIB); + new_head = !new_head ? new_item : new_head; + + /* if bmp_process_one returns NULL + * we don't have anything to do next + */ + if (!new_head) + continue; + + frr_each (bmp_session, &bt->sessions, bmp) { + if (!bmp->mon_loc_queuepos) + bmp->mon_loc_queuepos = new_head; + + pullwr_bump(bmp->pullwr); + }; + }; + + return 0; +} + +/* this function is triggered when a change has been registered in the + * adj-rib-out. it puts a bmp_queue_entry in the rib-out queue + * and which will trigger a bmp monitoring message for rib-out pre/post-policy + * if either is configured. + */ +static int bmp_adj_out_changed(struct update_subgroup *subgrp, + struct bgp_dest *dest, + struct bgp_path_info *locked_path, + uint32_t addpath_id, struct attr *attr, + bool post_policy, bool withdraw) +{ + + if (!subgrp) + return 0; + + /* for rib-out pre-policy we need to run bgp conditions check to know + * if a path is in adj-rib-out pre or not + */ + if (!post_policy) { + + /* because of withdraw we don't have the path right away, + * look it up in bmp locked paths + */ + if (withdraw && !locked_path) { + { /* scope lock the vars declared by lookup */ + BMP_LBPI_LOOKUP_DEST( + head, prev, lbpi, dest, + SUBGRP_INST(subgrp), + bgp_addpath_id_for_peer( + SUBGRP_PEER(subgrp), + SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), + &lbpi->locked->tx_addpath) == + addpath_id); + + if (!lbpi) { + zlog_warn( + "no locked path found for %pBD tx %" PRIu32" in bgp %s", + dest, addpath_id, SUBGRP_INST(subgrp)->name); + return 0; + } + + locked_path = lbpi->locked; + } + } + + struct attr dummy_attr = {0}; + + /* run bgp rib-out-pre check + * withdraw | pre_check | result + * true | true | withdraw + * true | false | nothing to do + * false | true | update + * false | false | nothing to do + * so if pre-policy check is false we + * return early. + */ + if (locked_path && + !subgroup_announce_check(dest, locked_path, subgrp, + bgp_dest_get_prefix(dest), &dummy_attr, NULL, + BGP_ANNCHK_SPECIAL_PREPOLICY)) { + return 0; + } + } + + struct bmp_targets *bt; + struct bgp *bgp = SUBGRP_INST(subgrp); + struct bmp_bgp *bmpbgp = bmp_bgp_get(bgp); + afi_t afi = SUBGRP_AFI(subgrp); + safi_t safi = SUBGRP_SAFI(subgrp); + + uint8_t mon_flag = + post_policy ? BMP_MON_OUT_POSTPOLICY : BMP_MON_OUT_PREPOLICY; + + struct peer_af *paf; + struct peer *peer; + struct bmp *bmp; + + frr_each (bmp_targets, &bmpbgp->targets, bt) { + if (!CHECK_FLAG(bt->afimon[afi][safi], mon_flag)) + continue; + + SUBGRP_FOREACH_PEER (subgrp, paf) { + peer = PAF_PEER(paf); - struct bmp_queue_entry *last_item = bmp_process_one( - bt, &bt->locupdhash, &bt->locupdlist, bgp, afi, - safi, bn, peer); + struct bmp_queue_entry *new_item = bmp_process_one( + bt, &bt->mon_out_updhash, &bt->mon_out_updlist, + afi, safi, dest, addpath_id, peer, mon_flag); /* if bmp_process_one returns NULL * we don't have anything to do next */ - if (!last_item) + if (!new_item) continue; frr_each (bmp_session, &bt->sessions, bmp) { - if (!bmp->locrib_queuepos) - bmp->locrib_queuepos = last_item; + if (!bmp->mon_out_queuepos) + bmp->mon_out_queuepos = new_item; + // TODO avoid bumping for each update ? pullwr_bump(bmp->pullwr); }; } @@ -3103,11 +4252,10 @@ static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi, return 0; } -static int bgp_bmp_early_fini(void) +/* called at the end of the bgp_process when we need to unlock the path */ +static int bmp_path_unlock(struct bgp *bgp, struct bgp_path_info *path) { - resolver_terminate(); - - return 0; + return bmp_unlock_bpi(bgp, path) == NULL; } /* called when a bgp instance goes up/down, implying that the underlying VRF @@ -3115,13 +4263,13 @@ static int bgp_bmp_early_fini(void) */ static int bmp_vrf_state_changed(struct bgp *bgp) { + struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp); if (!bmp_bgp_update_vrf_status(bmpbgp, vrf_state_unknown)) return 1; - bmp_send_all_safe(bmpbgp, - bmp_peerstate(bgp->peer_self, bmpbgp->vrf_state == vrf_state_down)); + bmp_send_all_safe(bmpbgp, bmp_peerstate(bgp->peer_self, bmpbgp->vrf_state == vrf_state_down)); return 0; } @@ -3148,17 +4296,29 @@ static int bmp_vrf_itf_state_changed(struct bgp *bgp, struct interface *itf) return 0; } +static int bgp_bmp_early_fini(void) +{ + resolver_terminate(); + + return 0; +} + static int bgp_bmp_module_init(void) { hook_register(bgp_packet_dump, bmp_mirror_packet); hook_register(bgp_packet_send, bmp_outgoing_packet); hook_register(peer_status_changed, bmp_peer_status_changed); hook_register(peer_backward_transition, bmp_peer_backward); - hook_register(bgp_process, bmp_process); + hook_register(bgp_process, bmp_process_ribinpre); 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_process_main_one, bmp_process_ribinpost); hook_register(bgp_route_update, bmp_route_update); + hook_register(bgp_adj_out_updated, bmp_adj_out_changed); + hook_register(bgp_process_main_one_end, bmp_path_unlock); + hook_register(bgp_instance_state, bmp_vrf_state_changed); + hook_register(bgp_vrf_status_changed, bmp_vrf_itf_state_changed); hook_register(frr_early_fini, bgp_bmp_early_fini); hook_register(bgp_instance_state, bmp_vrf_state_changed); hook_register(bgp_vrf_status_changed, bmp_vrf_itf_state_changed); diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h index d45a4278f69e..fdd5d70d8afe 100644 --- a/bgpd/bgp_bmp.h +++ b/bgpd/bgp_bmp.h @@ -12,6 +12,7 @@ #include "pullwr.h" #include "qobj.h" #include "resolver.h" +#include "bgp_updgrp.h" #define BMP_VERSION_3 3 @@ -29,9 +30,11 @@ #define BMP_READ_BUFSIZ 1024 /* bmp->state */ -#define BMP_None 0 -#define BMP_PeerUp 2 -#define BMP_Run 3 +enum BMP_State { + BMP_StartupIdle, + BMP_PeerUp, + BMP_Run, +}; /* This one is for BMP Route Monitoring messages, i.e. delivering updates * in somewhat processed (as opposed to fully raw, see mirroring below) form. @@ -60,6 +63,10 @@ struct bmp_queue_entry { struct bmp_qlist_item bli; struct bmp_qhash_item bhi; + uint32_t addpath_id; + +#define BMP_QUEUE_FLAGS_NONE (0) + uint8_t flags; struct prefix p; uint64_t peerid; afi_t afi; @@ -116,7 +123,7 @@ struct bmp { struct pullwr *pullwr; - int state; + enum BMP_State state; /* queue positions must remain synced with refcounts in the items. * Whenever appending a queue item, we need to know the correct number @@ -124,8 +131,10 @@ 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_queue_entry *mon_in_queuepos; + struct bmp_queue_entry *mon_loc_queuepos; + struct bmp_queue_entry *mon_out_queuepos; + struct bmp_mirrorq *mirrorpos; bool mirror_lost; @@ -220,9 +229,12 @@ struct bmp_targets { * - 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) +#define BMP_MON_IN_PREPOLICY (1 << 0) +#define BMP_MON_IN_POSTPOLICY (1 << 1) +#define BMP_MON_LOC_RIB (1 << 2) +#define BMP_MON_OUT_PREPOLICY (1 << 3) +#define BMP_MON_OUT_POSTPOLICY (1 << 4) + uint8_t afimon[AFI_MAX][SAFI_MAX]; bool mirror; @@ -232,11 +244,14 @@ struct bmp_targets { struct event *t_stats; struct bmp_session_head sessions; - struct bmp_qhash_head updhash; - struct bmp_qlist_head updlist; + struct bmp_qhash_head mon_in_updhash; + struct bmp_qlist_head mon_in_updlist; - struct bmp_qhash_head locupdhash; - struct bmp_qlist_head locupdlist; + struct bmp_qhash_head mon_loc_updhash; + struct bmp_qlist_head mon_loc_updlist; + + struct bmp_qhash_head mon_out_updhash; + struct bmp_qlist_head mon_out_updlist; uint64_t cnt_accept, cnt_aclrefused; @@ -263,6 +278,56 @@ struct bmp_bgp_peer { size_t open_tx_len; }; +/* every bgp_path_info that bmp currently has locked for rib-out-prepolicy + * when this is allocated the bgp_path_info is locked using bgp_path_info_lock + * when freed unlocked using bpg_path_info_unlock + */ +PREDECL_HASH(bmp_lbpi_h); + +struct bmp_bpi_lock { + /* hashset field */ + struct bmp_lbpi_h_item lbpi_h; + struct bmp_bpi_lock *next; + + /* bgp instance associated with bpi and dest + * needed for differentiation between vrfs/views + */ + struct bgp *bgp; + /* locked bgp_path_info */ + struct bgp_path_info *locked; + /* dest of locked bgp_path_info for lookup */ + struct bgp_dest *dest; + + /* lock, one for each bqe in the rib-out queue + * when each bqe is allocated we increment this lock + * when freed we decrement it + * after all bqe are processed, it should be 0 + * so the bpi can be unlocked (and maybe freed) + */ + int lock; +}; + + +#define BMP_LBPI_LOOKUP_DEST(head, prev, lookup, target_dest, target_bgp, \ + condition) \ + struct bmp_bpi_lock _dummy_lbpi = { \ + .dest = (target_dest), \ + .bgp = (target_bgp), \ + }; \ + \ + struct bmp_bpi_lock *(head) = NULL, *(prev) = NULL, *(lookup) = NULL; \ + \ + (head) = bmp_lbpi_h_find(&bmp_lbpi, &_dummy_lbpi); \ + \ + for ((lookup) = (head); (lookup); \ + (lookup) = ((prev) = (lookup))->next) { \ + if ((condition)) \ + break; \ + } + +#define BMP_LBPI_LOOKUP_BPI(head, prev, lookup, target_bpi, target_bgp) \ + BMP_LBPI_LOOKUP_DEST((head), (prev), (lookup), (target_bpi)->net, \ + (target_bgp), ((lookup)->locked == (target_bpi))) /* per struct bgp * data */ PREDECL_HASH(bmp_bgph); @@ -287,6 +352,8 @@ struct bmp_bgp { size_t mirror_qsize, mirror_qsizemax; size_t mirror_qsizelimit; + + uint32_t startup_delay_ms; }; extern bool bmp_bgp_update_vrf_status(struct bmp_bgp *bmpbgp, enum bmp_vrf_state force); @@ -298,26 +365,31 @@ enum { BMP_PEERDOWN_REMOTE_NOTIFY = 3, BMP_PEERDOWN_REMOTE_CLOSE = 4, BMP_PEERDOWN_ENDMONITOR = 5, + /* RFC9069 - 8.4 */ BMP_PEERDOWN_LOCAL_TLV = 6, }; enum { - BMP_STATS_PFX_REJECTED = 0, - BMP_STATS_PFX_DUP_ADV = 1, - BMP_STATS_PFX_DUP_WITHDRAW = 2, - BMP_STATS_UPD_LOOP_CLUSTER = 3, - BMP_STATS_UPD_LOOP_ASPATH = 4, - BMP_STATS_UPD_LOOP_ORIGINATOR = 5, - BMP_STATS_UPD_LOOP_CONFED = 6, - BMP_STATS_SIZE_ADJ_RIB_IN = 7, - BMP_STATS_SIZE_LOC_RIB = 8, - BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, - BMP_STATS_SIZE_LOC_RIB_IN_SAFI = 10, - BMP_STATS_UPD_7606_WITHDRAW = 11, - BMP_STATS_PFX_7606_WITHDRAW = 12, - BMP_STATS_UPD_DUP = 13, - BMP_STATS_FRR_NH_INVALID = 65531, + BMP_STATS_PFX_REJECTED = 0, + BMP_STATS_PFX_DUP_ADV = 1, + BMP_STATS_PFX_DUP_WITHDRAW = 2, + BMP_STATS_UPD_LOOP_CLUSTER = 3, + BMP_STATS_UPD_LOOP_ASPATH = 4, + BMP_STATS_UPD_LOOP_ORIGINATOR = 5, + BMP_STATS_UPD_LOOP_CONFED = 6, + BMP_STATS_SIZE_ADJ_RIB_IN = 7, + BMP_STATS_SIZE_LOC_RIB = 8, + BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, + BMP_STATS_SIZE_LOC_RIB_SAFI = 10, + BMP_STATS_UPD_7606_WITHDRAW = 11, + BMP_STATS_PFX_7606_WITHDRAW = 12, + BMP_STATS_UPD_DUP = 13, + BMP_STATS_SIZE_ADJ_RIB_OUT_PRE = 14, + BMP_STATS_SIZE_ADJ_RIB_OUT_POST = 15, + BMP_STATS_SIZE_ADJ_RIB_OUT_PRE_SAFI = 16, + BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI = 17, + BMP_STATS_FRR_NH_INVALID = 65531, }; DECLARE_MGROUP(BMP); diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index a99d0201e7e0..1977bbf0b43f 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -98,6 +98,25 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { advmap_attr = *pi->attr; + bool selected = bgp_check_selected( + pi, peer, addpath_capable, afi, safi); + + if (selected) { + bgp_adj_out_updated( + subgrp, dest, pi, + !addpath_capable + ? 0 + : bgp_addpath_id_for_peer( + peer, afi, safi, + &pi->tx_addpath), + &attr, false, + update_type == UPDATE_TYPE_ADVERTISE + ? false + : true, + __func__); + } + + /* Fill temp path_info */ prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL, &advmap_attr); @@ -105,9 +124,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, RESET_FLAG(advmap_attr.rmap_change_flags); ret = route_map_apply(rmap, dest_p, &path); - if (ret != RMAP_PERMITMATCH || - !bgp_check_selected(pi, peer, addpath_capable, afi, - safi)) { + if (ret != RMAP_PERMITMATCH || !selected) { bgp_attr_flush(&advmap_attr); continue; } @@ -121,7 +138,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, */ if (update_type == UPDATE_TYPE_ADVERTISE && subgroup_announce_check(dest, pi, subgrp, dest_p, - &attr, &advmap_attr)) { + &attr, &advmap_attr, 0)) { if (!bgp_adj_out_set_subgroup(dest, subgrp, &attr, pi)) bgp_attr_flush(&attr); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ad29828adecb..0d797fdf9ec7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1470,7 +1470,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, /* Compute the best path. */ bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi); + afi, safi, NULL); old_select = old_and_new.old; new_select = old_and_new.new; diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index ad3625242ee1..96bfb5ee2111 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -107,7 +107,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, /* Compute the best path. */ bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi); + afi, safi, NULL); old_select = old_and_new.old; new_select = old_and_new.new; diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 535d2fc5f434..03f4886d3b29 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -267,6 +267,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) static int bgp_vrf_new(struct vrf *vrf) { + zlog_info("BGP VRF CREATE %s", vrf->name); + if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id); @@ -275,6 +277,7 @@ static int bgp_vrf_new(struct vrf *vrf) static int bgp_vrf_delete(struct vrf *vrf) { + zlog_info("BGP VRF DELETE %s", vrf->name); if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id); @@ -286,6 +289,8 @@ static int bgp_vrf_enable(struct vrf *vrf) struct bgp *bgp; vrf_id_t old_vrf_id; + zlog_info("BGP VRF ENABLE %s", vrf->name); + if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id); @@ -319,6 +324,8 @@ static int bgp_vrf_disable(struct vrf *vrf) { struct bgp *bgp; + zlog_info("BGP VRF DISABLE %s", vrf->name); + if (vrf->vrf_id == VRF_DEFAULT) return 0; diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 609afa4245e6..8002b1dad5c7 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -410,6 +410,42 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, mpath->mp_attr = attr; } +void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, + struct bgp_path_info *bpi, bool update) +{ + if (!diff) + return; + if (!bpi) { + zlog_warn("%s: path info given is null", __func__); + return; + } + + struct bgp_path_info_mpath_diff *item = XCALLOC( + MTYPE_BGP_MPATH_DIFF, sizeof(struct bgp_path_info_mpath_diff)); + item->path = bpi; + item->update = update; + + bgp_path_info_lock(bpi); + bgp_dest_lock_node(bpi->net); + bgp_mpath_diff_add_tail(diff, item); +} + +void bgp_mpath_diff_clear(struct bgp_mpath_diff_head *diff) +{ + struct bgp_path_info_mpath_diff *mp_diff; + + if (!diff) + return; + + while ((mp_diff = bgp_mpath_diff_pop(diff))) { + if (mp_diff->path && mp_diff->path->net) + bgp_dest_unlock_node(mp_diff->path->net); + if (mp_diff->path) + bgp_path_info_unlock(mp_diff->path); + XFREE(MTYPE_BGP_MPATH_DIFF, mp_diff); + } +} + /* * bgp_path_info_mpath_update * @@ -418,7 +454,8 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, */ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *new_best, struct bgp_path_info *old_best, - uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg) + uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_mpath_diff_head *mpath_diff_list) { uint16_t maxpaths, mpath_count, old_mpath_count; uint64_t bwval; @@ -518,8 +555,10 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, if (cur_iterator != new_best) SET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); - if (!old_mpath) + if (!old_mpath) { mpath_changed = true; + bgp_mpath_diff_insert(mpath_diff_list, cur_iterator, true); + } if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(cur_iterator->attr), &bwval) || @@ -544,6 +583,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, */ mpath_changed = true; UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); + bgp_mpath_diff_insert(mpath_diff_list, cur_iterator, false); } cur_iterator = cur_iterator->next; diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index c5a009a4c8bb..f4f9f7b05e64 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -35,6 +35,22 @@ struct bgp_path_info_mpath { uint64_t cum_bw; }; +DEFINE_MTYPE_STATIC(BGPD, BGP_MPATH_DIFF, "multipath diff in decision process"); +PREDECL_LIST(bgp_mpath_diff); + +struct bgp_path_info_mpath_diff { + struct bgp_mpath_diff_item next; + struct bgp_path_info *path; + bool update; +}; + +DECLARE_LIST(bgp_mpath_diff, struct bgp_path_info_mpath_diff, next); + +extern void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, + struct bgp_path_info *bpi, bool update); + +extern void bgp_mpath_diff_clear(struct bgp_mpath_diff_head *diff); + /* Functions to support maximum-paths configuration */ extern int bgp_maximum_paths_set(struct bgp *bgp, afi_t afi, safi_t safi, int peertype, uint16_t maxpaths, @@ -49,7 +65,8 @@ extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, struct bgp_path extern void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *new_best, struct bgp_path_info *old_best, uint32_t num_candidates, - struct bgp_maxpaths_cfg *mpath_cfg); + struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_mpath_diff_head *mpath_diff_list); extern void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, struct bgp_path_info *old_best); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7a8773947923..585c4c08a005 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -92,6 +92,9 @@ DEFINE_HOOK(bgp_route_update, struct bgp_path_info *old_route, struct bgp_path_info *new_route), (bgp, afi, safi, bn, old_route, new_route)); +DEFINE_HOOK(bgp_process_main_one_end, + (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); + /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; extern const char *bgp_origin_long_str[]; @@ -155,9 +158,13 @@ static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi, } DEFINE_HOOK(bgp_process, - (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, - struct peer *peer, bool withdraw), - (bgp, afi, safi, bn, peer, withdraw)); + (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, + uint32_t addpath_id, struct peer *peer, bool post), + (bgp, afi, safi, bn, addpath_id, peer, post)); + +DEFINE_HOOK(bgp_process_main_one, + (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), + (bgp, afi, safi, dest)); /** Test if path is suppressed. */ bool bgp_path_suppressed(struct bgp_path_info *pi) @@ -508,8 +515,6 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest, bgp_dest_lock_node(dest); peer_lock(pi->peer); /* bgp_path_info peer reference */ bgp_dest_set_defer_flag(dest, false); - if (pi->peer) - pi->peer->stat_pfx_loc_rib++; hook_call(bgp_snmp_update_stats, dest, pi, true); } @@ -528,8 +533,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest, pi->next = NULL; pi->prev = NULL; - if (pi->peer) - pi->peer->stat_pfx_loc_rib--; hook_call(bgp_snmp_update_stats, dest, pi, false); bgp_path_info_unlock(pi); @@ -542,8 +545,6 @@ static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest, pi->next = NULL; pi->prev = NULL; - if (pi->peer) - pi->peer->stat_pfx_loc_rib--; hook_call(bgp_snmp_update_stats, dest, pi, false); bgp_path_info_unlock(pi); @@ -2136,7 +2137,7 @@ void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr) bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, struct update_subgroup *subgrp, const struct prefix *p, struct attr *attr, - struct attr *post_attr) + struct attr *post_attr, uint8_t special_cond) { struct bgp_filter *filter; struct peer *from; @@ -2170,6 +2171,13 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, bgp = SUBGRP_INST(subgrp); piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr; + /* special conditions for bmp rib-out pre-policy check */ + bool ignore_policy = + CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY); + bool ignore_path_status = + CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS); + + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) && peer->pmax_out[afi][safi] != 0 && subgrp->pscount >= peer->pmax_out[afi][safi]) { @@ -2209,21 +2217,22 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, /* With addpath we may be asked to TX all kinds of paths so make sure * pi is valid */ - if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) - || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) - || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { + if (!ignore_path_status && (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || + CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) || + CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))) { return false; } /* If this is not the bestpath then check to see if there is an enabled * addpath * feature that requires us to advertise it */ - if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) + if (!ignore_path_status && !CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) if (!bgp_addpath_capable(pi, peer, afi, safi)) return false; /* Aggregate-address suppress check. */ - if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter)) + if (!ignore_policy && bgp_path_suppressed(pi) && + !UNSUPPRESS_MAP_NAME(filter)) return false; /* @@ -2312,7 +2321,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* ORF prefix-list filter check */ - if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && + if (!ignore_policy && + CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)) if (peer->orf_plist[afi][safi]) { if (prefix_list_apply(peer->orf_plist[afi][safi], p) @@ -2327,7 +2337,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* Output filter check. */ - if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) { + if (!ignore_policy && + bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer, p); @@ -2501,7 +2512,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, bgp_otc_egress(peer, attr)) return false; - if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW && + bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); + bgp_peer_as_override(bgp, afi, safi, peer, attr); + + if (!ignore_policy && + filter->advmap.update_type == UPDATE_TYPE_WITHDRAW && filter->advmap.aname && route_map_lookup_by_name(filter->advmap.aname)) { struct bgp_path_info rmap_path = {0}; @@ -2528,7 +2543,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* Route map & unsuppress-map apply. */ - if (!post_attr && + if (!ignore_policy && !post_attr && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) { struct bgp_path_info rmap_path = {0}; struct bgp_path_info_extra dummy_rmap_path_extra = {0}; @@ -2903,7 +2918,8 @@ static void bgp_route_select_timer_expire(struct event *thread) void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg, struct bgp_path_info_pair *result, afi_t afi, - safi_t safi) + safi_t safi, + struct bgp_mpath_diff_head *mpath_diff_list) { struct bgp_path_info *new_select, *look_thru; struct bgp_path_info *old_select, *worse, *first; @@ -3081,6 +3097,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, if (old_select != first && CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) { + bgp_mpath_diff_insert(mpath_diff_list, first, false); dest = bgp_path_info_reap_unsorted(dest, first); assert(dest); } else { @@ -3330,7 +3347,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, } } - bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg); + bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg, mpath_diff_list); bgp_path_info_mpath_aggregate_update(new_select, old_select); bgp_addpath_update_ids(bgp, dest, afi, safi); @@ -3379,9 +3396,12 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, */ advertise = bgp_check_advertise(bgp, dest, safi); + bgp_adj_out_updated(subgrp, dest, selected, addpath_tx_id, &attr, false, + selected && advertise ? false : true, __func__); + if (selected) { if (subgroup_announce_check(dest, selected, subgrp, p, pattr, - NULL)) { + NULL, 0)) { /* Route is selected, if the route is already installed * in FIB, then it is advertised */ @@ -3739,9 +3759,14 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, return; } + hook_call(bgp_process_main_one, bgp, afi, safi, dest); + struct bgp_mpath_diff_head mpath_diff; + + bgp_mpath_diff_init(&mpath_diff); + /* Best path selection. */ bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi); + afi, safi, &mpath_diff); old_select = old_and_new.old; new_select = old_and_new.new; @@ -3764,6 +3789,37 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, __func__, dest, bgp->name_pretty, afi2str(afi), safi2str(safi), old_select, new_select); + + struct bgp_path_info_mpath_diff *diff; + + /* 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); + } + + if (debug) + zlog_debug("%s: multipath diff %p computed, mpath_changed=%d", + __func__, &mpath_diff, + (int)bgp_mpath_diff_count(&mpath_diff)); + frr_each (bgp_mpath_diff, &mpath_diff, diff) { + if (diff->path) { + if (debug) + zlog_debug( + "[%s] bpi: %p, dest=%pBD peer=%pBP, rx_id=%" PRIu32, + diff->update ? "+" : "-", diff->path, + diff->path->net, diff->path->peer, + diff->path->addpath_rx_id); + + hook_call(bgp_route_update, bgp, afi, safi, dest, + diff->path, diff->update ? diff->path : NULL); + } else if (debug) + zlog_debug("[%s] diff: %p no path", + diff->update ? "+" : "-", diff); + } + /* If best route remains the same and this is not due to user-initiated * clear, see exactly what needs to be done. */ @@ -3817,7 +3873,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG); bgp_zebra_clear_route_change_flags(dest); UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED); - return; + + goto out; } /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set @@ -3844,6 +3901,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, /* TODO BMP insert rib update hook */ if (old_select) bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED); + if (new_select) { if (debug) zlog_debug("%s: %pBD setting SELECTED flag", __func__, @@ -3855,15 +3913,6 @@ 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) { @@ -3933,6 +3982,32 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED)) bgp_path_info_reap(dest, old_select); +out: + if (old_select) { + if (old_select->peer) + old_select->peer->stat_loc_rib_count[afi][safi]--; + + hook_call(bgp_process_main_one_end, bgp, old_select); + } + + if (new_select && new_select->peer) + new_select->peer->stat_loc_rib_count[afi][safi]++; + + struct bgp_path_info *mpath; + + frr_each (bgp_mpath_diff, &mpath_diff, diff) { + mpath = diff->path; + + if (!mpath) + continue; + + if (mpath->peer) + mpath->peer->stat_loc_rib_count[afi][safi] += diff->update ? 1 : -1; + + hook_call(bgp_process_main_one_end, bgp, mpath); + } + bgp_mpath_diff_clear(&mpath_diff); + bgp_mpath_diff_fini(&mpath_diff); return; } @@ -4384,7 +4459,8 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi, } } - hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true); + hook_call(bgp_process, peer->bgp, afi, safi, dest, + pi ? pi->addpath_rx_id : 0, peer, true); bgp_process(peer->bgp, dest, pi, afi, safi); } @@ -4742,7 +4818,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, else evpn_overlay_free(evpn); } - bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels); + bgp_adj_in_set(dest, afi, safi, peer, attr, addpath_id, &bgp_labels); } /* Check previously received route. */ @@ -5028,7 +5104,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, pi->uptime = monotime(NULL); same_attr = attrhash_cmp(pi->attr, attr_new); - hook_call(bgp_process, bgp, afi, safi, dest, peer, true); + hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, + true); /* Same attribute comes in. */ if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr && @@ -5404,7 +5481,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, new); - hook_call(bgp_process, bgp, afi, safi, dest, peer, false); + hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, true); /* Process change. */ bgp_process(bgp, dest, new, afi, safi); @@ -5443,7 +5520,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, XFREE(MTYPE_BGP_ROUTE, new); } - hook_call(bgp_process, bgp, afi, safi, dest, peer, true); + hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, false); if (bgp_debug_update(peer, p, NULL, 1)) { if (!peer->rcvd_attr_printed) { @@ -5531,8 +5608,8 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, * if there was no entry, we don't need to do anything more. */ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) - && peer != bgp->peer_self) - if (!bgp_adj_in_unset(&dest, peer, addpath_id)) { + && peer != bgp->peer_self) { + if (!bgp_adj_in_unset(&dest, afi, safi, peer, addpath_id)) { assert(dest); peer->stat_pfx_dup_withdraw++; @@ -5549,6 +5626,10 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, return; } + hook_call(bgp_process, peer->bgp, afi, safi, dest, addpath_id, + peer, false); + } + /* Lookup withdrawn route. */ assert(dest); for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) @@ -6121,7 +6202,7 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, ain_next = ain->next; if (ain->peer == peer) - bgp_adj_in_remove(&dest, ain); + bgp_adj_in_remove(&dest, afi, safi, ain); ain = ain_next; @@ -6231,7 +6312,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi) ain_next = ain->next; if (ain->peer == peer) - bgp_adj_in_remove(&dest, ain); + bgp_adj_in_remove(&dest, afi, safi, ain); ain = ain_next; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 1df0ffd300e1..f976a00e0437 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -14,6 +14,7 @@ #include "bgp_table.h" #include "bgp_addpath_types.h" #include "bgp_rpki.h" +#include "bgp_mpath.h" struct bgp_nexthop_cache; struct bgp_route_evpn; @@ -330,6 +331,8 @@ struct bgp_path_info { #define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17) #define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18) #define BGP_PATH_UNSORTED (1 << 19) +#define BGP_PATH_BMP_LOCKED (1 << 20) +#define BGP_PATH_BMP_ADJIN_CHG (1 << 21) /* * BGP_PATH_MULTIPATH_NEW is set on those bgp_path_info * nodes that we have decided should possibly be in the @@ -338,7 +341,7 @@ struct bgp_path_info { * decide on whether or not a bgp_path_info is on * the actual ecmp path. */ -#define BGP_PATH_MULTIPATH_NEW (1 << 20) +#define BGP_PATH_MULTIPATH_NEW (1 << 22) /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ uint8_t type; @@ -700,8 +703,13 @@ static inline bool bgp_check_withdrawal(struct bgp *bgp, struct bgp_dest *dest, /* called before bgp_process() */ DECLARE_HOOK(bgp_process, (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, - struct peer *peer, bool withdraw), - (bgp, afi, safi, bn, peer, withdraw)); + uint32_t addpath_id, struct peer *peer, bool post), + (bgp, afi, safi, bn, addpath_id, peer, post)); + +/* called before bgp_process() */ +DECLARE_HOOK(bgp_process_main_one, + (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), + (bgp, afi, safi, dest)); /* called when a route is updated in the rib */ DECLARE_HOOK(bgp_route_update, @@ -709,6 +717,10 @@ DECLARE_HOOK(bgp_route_update, struct bgp_path_info *old_route, struct bgp_path_info *new_route), (bgp, afi, safi, bn, old_route, new_route)); + +DECLARE_HOOK(bgp_process_main_one_end, + (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); + /* BGP show options */ #define BGP_SHOW_OPT_JSON (1 << 0) #define BGP_SHOW_OPT_WIDE (1 << 1) @@ -893,11 +905,18 @@ extern void subgroup_process_announce_selected(struct update_subgroup *subgrp, safi_t safi, uint32_t addpath_tx_id); +/* used by bmp to ignore certain conditions in rib-out pre-policy check */ +#define BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY (1 << 0) +#define BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS (1 << 1) +#define BGP_ANNCHK_SPECIAL_PREPOLICY \ + (BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY | \ + BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS) extern bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, struct update_subgroup *subgrp, const struct prefix *p, struct attr *attr, - struct attr *post_attr); + struct attr *post_attr, + uint8_t special_cond); extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer); extern void bgp_process_queues_drain_immediate(void); @@ -921,7 +940,8 @@ extern void bgp_attr_add_gshut_community(struct attr *attr); extern void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg, struct bgp_path_info_pair *result, afi_t afi, - safi_t safi); + safi_t safi, + struct bgp_mpath_diff_head *mpath_diff_list); extern void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest); extern bool bgp_zebra_has_route_changed(struct bgp_path_info *selected); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index d0fd226d9988..5ade05c3653f 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -57,6 +57,12 @@ (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ADDPATH_AF_TX_ADV | \ PEER_CAP_ADDPATH_AF_RX_RCV | PEER_CAP_ENHE_AF_NEGO) +DECLARE_HOOK(bgp_adj_out_updated, + (struct update_subgroup *subgrp, struct bgp_dest *dest, + struct bgp_path_info *path, uint32_t addpath_id, + struct attr *attr, bool post_policy, bool withdraw), + (subgrp, dest, path, addpath_id, attr, post_policy, withdraw)); + enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX }; typedef struct { @@ -444,9 +450,17 @@ extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, struct attr *attr, struct bgp_path_info *path); +extern void bgp_adj_out_updated(struct update_subgroup *subgrp, + struct bgp_dest *dest, + struct bgp_path_info *path, uint32_t addpath_tx, + struct attr *attr, bool post_policy, + bool withdraw, const char *caller); extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, char withdraw, uint32_t addpath_tx_id); +extern struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, + struct update_subgroup *subgrp, + uint32_t addpath_tx_id); void subgroup_announce_table(struct update_subgroup *subgrp, struct bgp_table *table); extern void subgroup_trigger_write(struct update_subgroup *subgrp); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 1a66df59fc20..aadd0c67d8aa 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -36,6 +36,11 @@ #include "bgpd/bgp_advertise.h" #include "bgpd/bgp_addpath.h" +DEFINE_HOOK(bgp_adj_out_updated, + (struct update_subgroup *subgrp, struct bgp_dest *dest, + struct bgp_path_info *path, uint32_t addpath_id, struct attr *attr, + bool post_policy, bool withdraw), + (subgrp, dest, path, addpath_id, attr, post_policy, withdraw)); /******************** * PRIVATE FUNCTIONS @@ -59,9 +64,9 @@ static int bgp_adj_out_compare(const struct bgp_adj_out *o1, } RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare); -static inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, - struct update_subgroup *subgrp, - uint32_t addpath_tx_id) +inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, + struct update_subgroup *subgrp, + uint32_t addpath_tx_id) { struct bgp_adj_out lookup; @@ -278,6 +283,12 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) adj->addpath_tx_id); } } + + if (!adj) + bgp_adj_out_updated( + subgrp, ctx->dest, NULL, + 0, NULL, false, true, + __func__); } } } @@ -523,6 +534,21 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, return next; } +/* call the bgp_adj_out_updated hook for bmp rib-out monitoring */ +void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest, + struct bgp_path_info *path, uint32_t addpath_tx, + struct attr *attr, bool post_policy, bool withdraw, + const char *caller) +{ + if (path && !withdraw && CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) { + /* path is removed, enforcing withdraw state */ + withdraw = true; + } + + hook_call(bgp_adj_out_updated, subgrp, dest, path, addpath_tx, attr, + post_policy, withdraw); +} + bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, struct attr *attr, struct bgp_path_info *path) @@ -655,6 +681,8 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, subgrp->version = MAX(subgrp->version, dest->version); + bgp_adj_out_updated(subgrp, dest, path, adj->addpath_tx_id, attr, true, + false, __func__); return true; } @@ -705,6 +733,10 @@ void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, if (trigger_write) subgroup_trigger_write(subgrp); + + bgp_adj_out_updated(subgrp, dest, NULL, + adj->addpath_tx_id, NULL, true, + withdraw, __func__); } else { /* Free allocated information. */ adj_free(adj); @@ -992,6 +1024,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw) dest = bgp_safi_node_lookup(bgp->rib[afi][safi_rib], safi_rib, &p, NULL); + // TODO BMP hook call for rib-out pre-policy + if (withdraw) { /* Withdraw the default route advertised using default * originate @@ -1012,7 +1046,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw) if (subgroup_announce_check(dest, pi, subgrp, bgp_dest_get_prefix( dest), - &attr, NULL)) { + &attr, NULL, 0)) { if (!bgp_adj_out_set_subgroup(dest, subgrp, &attr, pi)) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 22f1cf841426..e32af95c226b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3960,6 +3960,9 @@ void bgp_instance_down(struct bgp *bgp) struct listnode *node; struct listnode *next; + /* notify BMP of instance state changed */ + hook_call(bgp_instance_state, bgp); + /* Cleanup evpn instance state */ bgp_evpn_instance_down(bgp); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index f7f74c670f08..22cb9b3b7bff 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1710,8 +1710,9 @@ struct peer { uint32_t stat_pfx_nh_invalid; uint32_t stat_pfx_dup_withdraw; uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */ - uint64_t stat_pfx_loc_rib; /* RFC7854 : Number of routes in Loc-RIB */ - uint64_t stat_pfx_adj_rib_in; /* RFC7854 : Number of routes in Adj-RIBs-In */ + uint32_t stat_adj_in_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Adj-RIBs-In */ + uint32_t stat_loc_rib_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Loc-RIB */ + // no need for stat_adj_out_count here, it is in struct update_subgroup /* BGP state count */ uint32_t established; /* Established */ diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst index 14d0849b3410..e4cffcb2e460 100644 --- a/doc/user/bmp.rst +++ b/doc/user/bmp.rst @@ -73,7 +73,7 @@ All of FRR's BMP configuration options are located inside the :clicmd:`router bgp ASN` block. Configure BGP first before proceeding to BMP setup. -There is one option that applies to the BGP instance as a whole: +There are two options that apply to the BGP instance as a whole: .. clicmd:: bmp mirror buffer-limit(0-4294967294) @@ -93,6 +93,33 @@ There is one option that applies to the BGP instance as a whole: BMP Route Monitoring is not affected by this option. +.. clicmd:: bmp startup-delay delay(0-4294967294) + + This sets the delay (in milliseconds) after module startup + for BMP sessions to become active. + + This setting is useful for BMP Monitoring because it allows BMP + to wait a bit for BGP to converge and the whole BGP state. It avoids + sending empty RIB content during synchronization on startup followed + by multiple incremental updates. It also avoids RIB-Out Pre-Policy Monitoring + to send duplicated messages on startup triggered by the reconfiguration of peer + policies. + + This setting applies to all sessions defined in the same BGP Instance. + On module initialization (at BGP Startup), the time is recorded. Then, + established sessions will wait "delay" after this recorded time to start + sending BMP Mirroring, the initial BMP Monitoring synchronization and + following BMP Monitoring Messages containing incremental updates. + + BMP Peer Up Messages are sent if the peer becomes available during this + period of time. + + The startup delay is applied for BMP startup only. BMP Sessions configured + while the daemon is running will only wait if this initial timer has not expired + yet. + + BMP Session Establishment is not affected by this option. + All other configuration is managed per targets: .. clicmd:: bmp targets NAME @@ -153,9 +180,9 @@ associated with a particular ``bmp targets``: Send BMP Statistics (counter) messages whose code is defined as experimental (in the [65531-65534] range). -.. clicmd:: bmp monitor AFI SAFI +.. clicmd:: bmp monitor AFI SAFI - Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and + Perform Route Monitoring for the specified AFI, SAFI and RIB. Only IPv4 and 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. @@ -163,6 +190,11 @@ associated with a particular ``bmp targets``: All BGP neighbors are included in Route Monitoring. Options to select a subset of BGP sessions may be added in the future. + Pre-Policy and Post-Policy flags do not apply to Local-RIB monitoring. + + BMP Local-RIB Monitoring is defined in :rfc:`9069` + BMP RIB-Out Monitoring is defined in :rfc:`8671` + .. clicmd:: bmp mirror Perform Route Mirroring for all BGP neighbors. Since this provides a @@ -171,3 +203,49 @@ associated with a particular ``bmp targets``: All BGP neighbors are included in Route Mirroring. Options to select a subset of BGP sessions may be added in the future. + +BMP Troubleshooting +------------- + + +When encountering problems with BMP, it may be interesting to know the current +state of the latter. + +.. clicmd:: show bmp + + Displays information about the current state of BMP including targets, sessions, + configured modes, global settings, ... + +.. code-block:: frr +BMP Module started at Fri Feb 24 13:05:50 2023 + +BMP state for BGP VRF default: + + Route Mirroring 0 bytes (0 messages) pending + 0 bytes maximum buffer used + + Startup delay : 10000ms + + Targets "my_targets": + Route Mirroring disabled + Route Monitoring IPv4 unicast rib-out pre-policy rib-out post-policy + Listeners: + + Outbound connections: + remote state timer local + ---------------------------------------------------------------------- + 99.99.99.99:12345 Up 99.99.99.99:12345 00:00:04 (unspec) + + 1 connected clients: + remote uptime state MonSent MirrSent MirrLost ByteSent ByteQ ByteQKernel + --------------------------------------------------------------------------------------------------------------- + 99.99.99.99:12345 00:00:04 Startup-Wait 0 0 0 61 0 0 +:: + + Here we have a single BGP instance running on VRF default. No specific mirroring settings but a + startup delay of 10000ms. + This instance has a single target with rib-out pre-policy and post-policy monitoring, no mirroring. + This target has a single session open with client 99.99.99.99 on port 12345 which is in state Startup-Wait. + This session will start sending monitoring messages as soon as the current time is + "Fri Feb 24 13:05:50 2023" + 10000ms = "Fri Feb 24 13:06:00 2023" which explains why it is in + Startup-Wait mode and has not sent Monitoring Messages yet. diff --git a/lib/pullwr.c b/lib/pullwr.c index 919a663db536..76c57a34f5de 100644 --- a/lib/pullwr.c +++ b/lib/pullwr.c @@ -84,6 +84,19 @@ void pullwr_bump(struct pullwr *pullwr) event_add_timer(pullwr->tm, pullwr_run, pullwr, 0, &pullwr->writer); } +/* call this function to schedule a pullwr_bump after a certain timeout + * + * uint32_t timeout is the wait time before pullwr_bump, in milliseconds + */ +void pullwr_timeout(struct pullwr *pullwr, uint32_t timeout) +{ + if (pullwr->writer) + return; + + event_add_timer_msec(pullwr->tm, pullwr_run, pullwr, timeout, + &pullwr->writer); +} + static size_t pullwr_iov(struct pullwr *pullwr, struct iovec *iov) { size_t len1; diff --git a/lib/pullwr.h b/lib/pullwr.h index ef2e01c04ede..9a58fdaf5671 100644 --- a/lib/pullwr.h +++ b/lib/pullwr.h @@ -86,6 +86,7 @@ extern void pullwr_cfg(struct pullwr *pullwr, int64_t max_spin_usec, size_t write_threshold); extern void pullwr_bump(struct pullwr *pullwr); +extern void pullwr_timeout(struct pullwr *pullwr, uint32_t timeout); extern void pullwr_write(struct pullwr *pullwr, const void *data, size_t len); diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c new file mode 100644 index 000000000000..e69de29bb2d1 From bb5cc3e9fd8159a16fca6399ca95f851b9faa2c0 Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Fri, 24 Nov 2023 14:03:02 +0100 Subject: [PATCH 02/11] tests: bmp tests for adj-rib-out and ecmp add multipath test and rename ribs add rd statement to vrf configuration now bmp cannot export information about a VRF without the RD being set (it is required for RD Instance Peer to have a Peer Distinguisher) change expected output for bgp_bmp tests also add dashes in ADJ_[IN|OUT]_[PRE|POST]_POLICY constants to have spaceless file names add add-path to nlri parsing add bmpserver exception printing add 3rd peer in topotest for ecmp Signed-off-by: Maxence Younsi --- .../bmp1/bmp-update-loc-rib-step1.json | 6 +- .../bmp1/bmp-update-loc-rib-step3.json | 34 ++++ ... bmp-update-rib-in-post-policy-step1.json} | 10 +- ... bmp-update-rib-in-post-policy-step2.json} | 6 +- ...> bmp-update-rib-in-pre-policy-step1.json} | 10 +- ...> bmp-update-rib-in-pre-policy-step2.json} | 6 +- .../bmp-update-rib-out-post-policy-step1.json | 38 ++++ .../bmp-update-rib-out-pre-policy-step1.json | 38 ++++ .../bmp1/bmp-withdraw-loc-rib-step1.json | 6 +- .../bmp1/bmp-withdraw-loc-rib-step3.json | 28 +++ ...mp-withdraw-rib-in-post-policy-step1.json} | 10 +- ...mp-withdraw-rib-in-post-policy-step2.json} | 6 +- ...bmp-withdraw-rib-in-pre-policy-step1.json} | 10 +- ...bmp-withdraw-rib-in-pre-policy-step2.json} | 6 +- ...mp-withdraw-rib-out-post-policy-step1.json | 32 ++++ ...bmp-withdraw-rib-out-pre-policy-step1.json | 32 ++++ tests/topotests/bgp_bmp/r1/bgpd.conf | 36 +++- .../r1/show-bgp-ipv4-update-step3.json | 48 +++++ .../r1/show-bgp-ipv4-withdraw-step3.json | 48 +++++ .../r1/show-bgp-ipv6-update-step3.json | 46 +++++ .../r1/show-bgp-ipv6-withdraw-step3.json | 5 + tests/topotests/bgp_bmp/r2/bgpd.conf | 2 + tests/topotests/bgp_bmp/r3/bgpd.conf | 21 +++ tests/topotests/bgp_bmp/r3/zebra.conf | 8 + tests/topotests/bgp_bmp/test_bgp_bmp.py | 166 ++++++++++++------ .../bmp1/bmp-update-loc-rib-step1.json | 8 +- ... bmp-update-rib-in-post-policy-step1.json} | 18 +- ...> bmp-update-rib-in-pre-policy-step1.json} | 18 +- .../bmp-update-rib-out-post-policy-step1.json | 38 ++++ .../bmp-update-rib-out-pre-policy-step1.json | 38 ++++ .../bmp1/bmp-withdraw-loc-rib-step1.json | 8 +- ...mp-withdraw-rib-in-post-policy-step1.json} | 18 +- ...bmp-withdraw-rib-in-pre-policy-step1.json} | 18 +- ...mp-withdraw-rib-out-post-policy-step1.json | 32 ++++ ...bmp-withdraw-rib-out-pre-policy-step1.json | 32 ++++ tests/topotests/bgp_bmp_vrf/r1/bgpd.conf | 14 +- .../topotests/bgp_bmp_vrf/test_bgp_bmp_vrf.py | 39 ++-- .../lib/bmp_collector/bgp/update/nlri.py | 103 ++++++++++- tests/topotests/lib/bmp_collector/bmp.py | 6 +- 39 files changed, 892 insertions(+), 156 deletions(-) create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json rename tests/topotests/bgp_bmp/bmp1/{bmp-update-pre-policy-step1.json => bmp-update-rib-in-post-policy-step1.json} (83%) rename tests/topotests/bgp_bmp/bmp1/{bmp-update-pre-policy-step2.json => bmp-update-rib-in-post-policy-step2.json} (91%) rename tests/topotests/bgp_bmp/bmp1/{bmp-update-post-policy-step1.json => bmp-update-rib-in-pre-policy-step1.json} (83%) rename tests/topotests/bgp_bmp/bmp1/{bmp-update-post-policy-step2.json => bmp-update-rib-in-pre-policy-step2.json} (91%) create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-post-policy-step1.json create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-pre-policy-step1.json create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json rename tests/topotests/bgp_bmp/bmp1/{bmp-withdraw-post-policy-step1.json => bmp-withdraw-rib-in-post-policy-step1.json} (79%) rename tests/topotests/bgp_bmp/bmp1/{bmp-withdraw-post-policy-step2.json => bmp-withdraw-rib-in-post-policy-step2.json} (89%) rename tests/topotests/bgp_bmp/bmp1/{bmp-withdraw-pre-policy-step1.json => bmp-withdraw-rib-in-pre-policy-step1.json} (80%) rename tests/topotests/bgp_bmp/bmp1/{bmp-withdraw-pre-policy-step2.json => bmp-withdraw-rib-in-pre-policy-step2.json} (89%) create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-post-policy-step1.json create mode 100644 tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json create mode 100644 tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json create mode 100644 tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json create mode 100644 tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json create mode 100644 tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step3.json create mode 100644 tests/topotests/bgp_bmp/r3/bgpd.conf create mode 100644 tests/topotests/bgp_bmp/r3/zebra.conf rename tests/topotests/bgp_bmp_vrf/bmp1/{bmp-update-pre-policy-step1.json => bmp-update-rib-in-post-policy-step1.json} (67%) rename tests/topotests/bgp_bmp_vrf/bmp1/{bmp-update-post-policy-step1.json => bmp-update-rib-in-pre-policy-step1.json} (67%) create mode 100644 tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-post-policy-step1.json create mode 100644 tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-pre-policy-step1.json rename tests/topotests/bgp_bmp_vrf/bmp1/{bmp-withdraw-post-policy-step1.json => bmp-withdraw-rib-in-post-policy-step1.json} (60%) rename tests/topotests/bgp_bmp_vrf/bmp1/{bmp-withdraw-pre-policy-step1.json => bmp-withdraw-rib-in-pre-policy-step1.json} (60%) create mode 100644 tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-post-policy-step1.json create mode 100644 tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json index 27f1fe6e27b6..0cc20fb54039 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json @@ -12,7 +12,8 @@ "peer_bgp_id": "192.168.0.1", "peer_distinguisher": "0:0", "peer_type": "loc-rib instance", - "policy": "loc-rib" + "policy": "loc-rib", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -27,7 +28,8 @@ "peer_distinguisher": "0:0", "peer_type": "loc-rib instance", "policy": "loc-rib", - "safi": 1 + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json new file mode 100644 index 000000000000..784c8b63bcc1 --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step3.json @@ -0,0 +1,34 @@ +{ + "loc-rib": { + "update": { + "1.1.1.0/31": { + "as_path": "65501 65502", + "bgp_nexthop": "192.168.0.3", + "bmp_log_type": "update", + "ip_prefix": "1.1.1.0/31", + "is_filtered": false, + "origin": "IGP", + "path_id": 0, + "peer_asn": 65501, + "peer_bgp_id": "192.168.0.1", + "peer_distinguisher": "0:0", + "peer_type": "loc-rib instance", + "policy": "loc-rib" + }, + "3.3.3.0/31": { + "as_path": "65501 65502", + "bgp_nexthop": "192.168.0.3", + "bmp_log_type": "update", + "ip_prefix": "3.3.3.0/31", + "is_filtered": false, + "origin": "IGP", + "path_id": 0, + "peer_asn": 65501, + "peer_bgp_id": "192.168.0.1", + "peer_distinguisher": "0:0", + "peer_type": "loc-rib instance", + "policy": "loc-rib" + } + } + } +} \ No newline at end of file diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step1.json similarity index 83% rename from tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step1.json rename to tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step1.json index fafe6f7c21e3..c8113ca24f00 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step1.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-post-policy": { "update": { "172.31.0.15/32": { "as_path": "65501 65502", @@ -13,7 +13,8 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "pre-policy" + "policy": "rib-in-post-policy", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -28,8 +29,9 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "pre-policy", - "safi": 1 + "policy": "rib-in-post-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step2.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step2.json similarity index 91% rename from tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step2.json rename to tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step2.json index 95acb5903a5d..4036f76b312c 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-update-pre-policy-step2.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-post-policy-step2.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-post-policy": { "update": { "172.31.0.15/32": { "afi": 1, @@ -16,7 +16,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "pre-policy", + "policy": "rib-in-post-policy", "rd": "444:2", "safi": 128 }, @@ -36,7 +36,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "pre-policy", + "policy": "rib-in-post-policy", "rd": "555:2", "safi": 128 } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step1.json similarity index 83% rename from tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step1.json rename to tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step1.json index d30ef9fd3217..653c78f2527b 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step1.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-pre-policy": { "update": { "172.31.0.15/32": { "as_path": "65501 65502", @@ -13,7 +13,8 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "post-policy" + "policy": "rib-in-pre-policy", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -28,8 +29,9 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "post-policy", - "safi": 1 + "policy": "rib-in-pre-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step2.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step2.json similarity index 91% rename from tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step2.json rename to tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step2.json index 9bf2d577693f..1c30fec90838 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-update-post-policy-step2.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-in-pre-policy-step2.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-pre-policy": { "update": { "172.31.0.15/32": { "afi": 1, @@ -16,7 +16,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "post-policy", + "policy": "rib-in-pre-policy", "rd": "444:2", "safi": 128 }, @@ -36,7 +36,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "post-policy", + "policy": "rib-in-pre-policy", "rd": "555:2", "safi": 128 } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-post-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-post-policy-step1.json new file mode 100644 index 000000000000..30af5cbc40ee --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-post-policy-step1.json @@ -0,0 +1,38 @@ +{ + "rib-out-post-policy": { + "update": { + "172.31.0.15/32": { + "as_path": "65501 65502", + "bgp_nexthop": "192.168.0.2", + "bmp_log_type": "update", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192.168.0.3", + "peer_type": "global instance", + "policy": "rib-out-post-policy", + "path_id": 0 + }, + "2001::1111/128": { + "afi": 2, + "as_path": "65501 65502", + "bmp_log_type": "update", + "ip_prefix": "2001::1111/128", + "ipv6": true, + "nxhp_ip": "192:168::2", + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192:168::3", + "peer_type": "global instance", + "policy": "rib-out-post-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-pre-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-pre-policy-step1.json new file mode 100644 index 000000000000..e7f8b17eee64 --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-update-rib-out-pre-policy-step1.json @@ -0,0 +1,38 @@ +{ + "rib-out-pre-policy": { + "update": { + "172.31.0.15/32": { + "as_path": "65501 65502", + "bgp_nexthop": "192.168.0.2", + "bmp_log_type": "update", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192.168.0.3", + "peer_type": "global instance", + "policy": "rib-out-pre-policy", + "path_id": 0 + }, + "2001::1111/128": { + "afi": 2, + "as_path": "65501 65502", + "bmp_log_type": "update", + "ip_prefix": "2001::1111/128", + "ipv6": true, + "nxhp_ip": "192:168::2", + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192:168::3", + "peer_type": "global instance", + "policy": "rib-out-pre-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json index 3891fbb15e47..9b74e62bdaf5 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json @@ -9,7 +9,8 @@ "peer_bgp_id": "192.168.0.1", "peer_distinguisher": "0:0", "peer_type": "loc-rib instance", - "policy": "loc-rib" + "policy": "loc-rib", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -21,7 +22,8 @@ "peer_distinguisher": "0:0", "peer_type": "loc-rib instance", "policy": "loc-rib", - "safi": 1 + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json new file mode 100644 index 000000000000..1eee3cfd6c01 --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step3.json @@ -0,0 +1,28 @@ +{ + "loc-rib": { + "withdraw": { + "1.1.1.0/31": { + "bmp_log_type": "withdraw", + "ip_prefix": "1.1.1.0/31", + "is_filtered": false, + "peer_asn": 65501, + "peer_bgp_id": "192.168.0.1", + "peer_distinguisher": "0:0", + "peer_type": "loc-rib instance", + "policy": "loc-rib", + "path_id": 0 + }, + "3.3.3.0/31": { + "bmp_log_type": "withdraw", + "ip_prefix": "3.3.3.0/31", + "is_filtered": false, + "peer_asn": 65501, + "peer_bgp_id": "192.168.0.1", + "peer_distinguisher": "0:0", + "peer_type": "loc-rib instance", + "policy": "loc-rib", + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step1.json similarity index 79% rename from tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step1.json rename to tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step1.json index 3224b525e217..0738509db6fb 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step1.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-post-policy": { "withdraw": { "172.31.0.15/32": { "bmp_log_type": "withdraw", @@ -10,7 +10,8 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "post-policy" + "policy": "rib-in-post-policy", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -22,8 +23,9 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "post-policy", - "safi": 1 + "policy": "rib-in-post-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step2.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step2.json similarity index 89% rename from tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step2.json rename to tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step2.json index 9eb221d4d0a2..43317fb2931f 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-post-policy-step2.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-post-policy-step2.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-post-policy": { "withdraw": { "2001::1111/128": { "afi": 2, @@ -12,7 +12,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "post-policy", + "policy": "rib-in-post-policy", "rd": "555:2", "safi": 128 }, @@ -27,7 +27,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "post-policy", + "policy": "rib-in-post-policy", "rd": "444:2", "safi": 128 } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json similarity index 80% rename from tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step1.json rename to tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json index 8add68c022d4..e9e5775e9b3c 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step1.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-pre-policy": { "withdraw": { "172.31.0.15/32": { "bmp_log_type": "withdraw", @@ -10,7 +10,8 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "pre-policy" + "policy": "rib-in-pre-policy", + "path_id": 0 }, "2001::1111/128": { "afi": 2, @@ -22,8 +23,9 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "pre-policy", - "safi": 1 + "policy": "rib-in-pre-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step2.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step2.json similarity index 89% rename from tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step2.json rename to tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step2.json index eea7501b2287..0cbfabe056dd 100644 --- a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-pre-policy-step2.json +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-in-pre-policy-step2.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-pre-policy": { "withdraw": { "2001::1111/128": { "afi": 2, @@ -12,7 +12,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192:168::2", "peer_type": "global instance", - "policy": "pre-policy", + "policy": "rib-in-pre-policy", "rd": "555:2", "safi": 128 }, @@ -27,7 +27,7 @@ "peer_distinguisher": "0:0", "peer_ip": "192.168.0.2", "peer_type": "global instance", - "policy": "pre-policy", + "policy": "rib-in-pre-policy", "rd": "444:2", "safi": 128 } diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-post-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-post-policy-step1.json new file mode 100644 index 000000000000..20f3b3cc9c04 --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-post-policy-step1.json @@ -0,0 +1,32 @@ +{ + "rib-out-post-policy": { + "withdraw": { + "172.31.0.15/32": { + "bmp_log_type": "withdraw", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192.168.0.3", + "peer_type": "global instance", + "policy": "rib-out-post-policy", + "path_id": 0 + }, + "2001::1111/128": { + "afi": 2, + "bmp_log_type": "withdraw", + "ip_prefix": "2001::1111/128", + "ipv6": true, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192:168::3", + "peer_type": "global instance", + "policy": "rib-out-post-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json new file mode 100644 index 000000000000..e9e7611b52d1 --- /dev/null +++ b/tests/topotests/bgp_bmp/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json @@ -0,0 +1,32 @@ +{ + "rib-out-pre-policy": { + "withdraw": { + "172.31.0.15/32": { + "bmp_log_type": "withdraw", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192.168.0.3", + "peer_type": "global instance", + "policy": "rib-out-pre-policy", + "path_id": 0 + }, + "2001::1111/128": { + "afi": 2, + "bmp_log_type": "withdraw", + "ip_prefix": "2001::1111/128", + "ipv6": true, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.3", + "peer_distinguisher": "0:0", + "peer_ip": "192:168::3", + "peer_type": "global instance", + "policy": "rib-out-pre-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp/r1/bgpd.conf b/tests/topotests/bgp_bmp/r1/bgpd.conf index 485c2170967c..e551adcd8a34 100644 --- a/tests/topotests/bgp_bmp/r1/bgpd.conf +++ b/tests/topotests/bgp_bmp/r1/bgpd.conf @@ -4,21 +4,34 @@ router bgp 65501 no bgp ebgp-requires-policy neighbor 192.168.0.2 remote-as 65502 neighbor 192:168::2 remote-as 65502 + neighbor 192.168.0.3 remote-as 65502 + neighbor 192:168::3 remote-as 65502 + neighbor 192.168.0.2 solo + neighbor 192:168::2 solo + neighbor 192.168.0.3 solo + neighbor 192:168::3 solo ! bmp targets bmp1 bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000 - bmp monitor ipv4 unicast pre-policy - bmp monitor ipv6 unicast pre-policy - bmp monitor ipv4 vpn pre-policy - bmp monitor ipv6 vpn pre-policy - bmp monitor ipv4 unicast post-policy - bmp monitor ipv6 unicast post-policy - bmp monitor ipv4 vpn post-policy - bmp monitor ipv6 vpn post-policy + bmp monitor ipv4 unicast rib-in pre-policy + bmp monitor ipv6 unicast rib-in pre-policy + bmp monitor ipv4 vpn rib-in pre-policy + bmp monitor ipv6 vpn rib-in pre-policy + bmp monitor ipv4 unicast rib-in post-policy + bmp monitor ipv6 unicast rib-in post-policy + bmp monitor ipv4 vpn rib-in post-policy + bmp monitor ipv6 vpn rib-in post-policy + ! bmp monitor ipv4 unicast loc-rib bmp monitor ipv6 unicast loc-rib bmp monitor ipv4 vpn loc-rib bmp monitor ipv6 vpn loc-rib + ! + bmp monitor ipv4 unicast rib-out pre-policy + bmp monitor ipv6 unicast rib-out pre-policy + bmp monitor ipv4 unicast rib-out post-policy + bmp monitor ipv6 unicast rib-out post-policy + ! exit ! address-family ipv4 vpn @@ -33,11 +46,16 @@ router bgp 65501 neighbor 192.168.0.2 activate neighbor 192.168.0.2 soft-reconfiguration inbound no neighbor 192:168::2 activate + neighbor 192.168.0.3 activate + neighbor 192.168.0.3 soft-reconfiguration inbound + no neighbor 192:168::3 activate exit-address-family ! address-family ipv6 unicast neighbor 192:168::2 activate neighbor 192:168::2 soft-reconfiguration inbound + neighbor 192:168::3 activate + neighbor 192:168::3 soft-reconfiguration inbound exit-address-family ! router bgp 65501 vrf vrf1 @@ -56,5 +74,5 @@ router bgp 65501 vrf vrf1 rt vpn both 54:200 export vpn import vpn - exit-address-family + exit-address-family exit diff --git a/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json b/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json new file mode 100644 index 000000000000..782de9b7e967 --- /dev/null +++ b/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step3.json @@ -0,0 +1,48 @@ +{ + "routes": { + "1.1.1.0/31": [ + { + "valid": true, + "pathFrom": "external", + "prefix": "1.1.1.0", + "prefixLen": 31, + "network": "1.1.1.0/31", + "metric": 0, + "weight": 0, + "peerId": "192.168.0.3", + "path": "65502", + "origin": "IGP", + "nexthops": [ + { + "ip": "192.168.0.3", + "hostname": "r3", + "afi": "ipv4", + "used": true + } + ] + } + ], + "3.3.3.0/31": [ + { + "valid": true, + "pathFrom": "external", + "prefix": "3.3.3.0", + "prefixLen": 31, + "network": "3.3.3.0/31", + "metric": 0, + "weight": 0, + "peerId": "192.168.0.3", + "path": "65502", + "origin": "IGP", + "nexthops": [ + { + "ip": "192.168.0.3", + "hostname": "r3", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} \ No newline at end of file diff --git a/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json b/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json new file mode 100644 index 000000000000..782de9b7e967 --- /dev/null +++ b/tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step3.json @@ -0,0 +1,48 @@ +{ + "routes": { + "1.1.1.0/31": [ + { + "valid": true, + "pathFrom": "external", + "prefix": "1.1.1.0", + "prefixLen": 31, + "network": "1.1.1.0/31", + "metric": 0, + "weight": 0, + "peerId": "192.168.0.3", + "path": "65502", + "origin": "IGP", + "nexthops": [ + { + "ip": "192.168.0.3", + "hostname": "r3", + "afi": "ipv4", + "used": true + } + ] + } + ], + "3.3.3.0/31": [ + { + "valid": true, + "pathFrom": "external", + "prefix": "3.3.3.0", + "prefixLen": 31, + "network": "3.3.3.0/31", + "metric": 0, + "weight": 0, + "peerId": "192.168.0.3", + "path": "65502", + "origin": "IGP", + "nexthops": [ + { + "ip": "192.168.0.3", + "hostname": "r3", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} \ No newline at end of file diff --git a/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json b/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json new file mode 100644 index 000000000000..6e65a9408c5f --- /dev/null +++ b/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step3.json @@ -0,0 +1,46 @@ +{ + "routes": { + "192:168::/64": [ + { + "valid": true, + "pathFrom": "external", + "prefix": "192:168::", + "prefixLen": 64, + "network": "192:168::/64", + "metric": 0, + "weight": 0, + "peerId": "192:168::2", + "path": "65502", + "origin": "incomplete", + "nexthops": [ + { + "ip": "192:168::2", + "hostname": "r2", + "afi": "ipv6", + "scope": "global" + } + ] + }, + { + "valid": true, + "pathFrom": "external", + "prefix": "192:168::", + "prefixLen": 64, + "network": "192:168::/64", + "metric": 0, + "weight": 0, + "peerId": "192:168::3", + "path": "65502", + "origin": "incomplete", + "nexthops": [ + { + "ip": "192:168::3", + "hostname": "r3", + "afi": "ipv6", + "scope": "global" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step3.json b/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step3.json new file mode 100644 index 000000000000..616558a9c47d --- /dev/null +++ b/tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step3.json @@ -0,0 +1,5 @@ +{ + "routes": { + "2001::1111/128": null + } +} \ No newline at end of file diff --git a/tests/topotests/bgp_bmp/r2/bgpd.conf b/tests/topotests/bgp_bmp/r2/bgpd.conf index 40e2cd5bbcb9..842cbc163755 100644 --- a/tests/topotests/bgp_bmp/r2/bgpd.conf +++ b/tests/topotests/bgp_bmp/r2/bgpd.conf @@ -5,6 +5,8 @@ router bgp 65502 no bgp network import-check neighbor 192.168.0.1 remote-as 65501 neighbor 192:168::1 remote-as 65501 + neighbor 192.168.0.1 solo + neighbor 192:168::1 solo ! address-family ipv4 unicast neighbor 192.168.0.1 activate diff --git a/tests/topotests/bgp_bmp/r3/bgpd.conf b/tests/topotests/bgp_bmp/r3/bgpd.conf new file mode 100644 index 000000000000..9cb7c401f7df --- /dev/null +++ b/tests/topotests/bgp_bmp/r3/bgpd.conf @@ -0,0 +1,21 @@ +router bgp 65502 + bgp router-id 192.168.0.3 + bgp log-neighbor-changes + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.0.1 remote-as 65501 + neighbor 192:168::1 remote-as 65501 + neighbor 192.168.0.1 solo + neighbor 192:168::1 solo +! + address-family ipv4 unicast + neighbor 192.168.0.1 activate + no neighbor 192:168::1 activate + redistribute connected + exit-address-family +! + address-family ipv6 unicast + neighbor 192:168::1 activate + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_bmp/r3/zebra.conf b/tests/topotests/bgp_bmp/r3/zebra.conf new file mode 100644 index 000000000000..752a212411ca --- /dev/null +++ b/tests/topotests/bgp_bmp/r3/zebra.conf @@ -0,0 +1,8 @@ +interface r3-eth0 + ip address 192.168.0.3/24 + ipv6 address 192:168::3/64 +! +interface r3-eth1 + ip address 172.31.0.3/24 + ipv6 address 172:31::3/64 +! diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py index 658ad2b99a2c..8fb45a274d56 100644 --- a/tests/topotests/bgp_bmp/test_bgp_bmp.py +++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py @@ -9,15 +9,22 @@ test_bgp_bmp.py: Test BGP BMP functionalities +------+ +------+ +------+ - | | | | | | - | BMP1 |------------| R1 |---------------| R2 | - | | | | | | - +------+ +------+ +------+ - -Setup two routers R1 and R2 with one link configured with IPv4 and + | | | | eth1 eth0 | | + | BMP1 |------------| R1 |-------+-------| R2 | + | | | | | | | + +------+ +------+ | +------+ + | + | +------+ + | eth0 | | + +--------| R3 | + | | + +------+ + +Setup three routers R1 and R3 with one link configured with IPv4 and IPv6 addresses. -Configure BGP in R1 and R2 to exchange prefixes from -the latter to the first router. +Configure BGP to exchange prefixes from R2 and R3 to R1. +R3 is only used in the multi-path test. +It announces the same as R2 to R1 to have the R2 prefixes be ECMP paths in R1. Setup a link between R1 and the BMP server, activate the BMP feature in R1 and ensure the monitored BGP sessions logs are well present on the BMP server. """ @@ -46,10 +53,17 @@ # remember the last sequence number of the logging messages SEQ = 0 -PRE_POLICY = "pre-policy" -POST_POLICY = "post-policy" +ADJ_IN_PRE_POLICY = "rib-in-pre-policy" +ADJ_IN_POST_POLICY = "rib-in-post-policy" +ADJ_OUT_PRE_POLICY = "rib-out-pre-policy" +ADJ_OUT_POST_POLICY = "rib-out-post-policy" LOC_RIB = "loc-rib" +BMP_UPDATE = "update" +BMP_WITHDRAW = "withdraw" + +TEST_PREFIXES = ["172.31.0.15/32", "2001::1111/128"] + UPDATE_EXPECTED_JSON = False DEBUG_PCAP = False @@ -57,13 +71,17 @@ def build_topo(tgen): tgen.add_router("r1") tgen.add_router("r2") + tgen.add_router("r3") tgen.add_bmp_server("bmp1", ip="192.0.2.10", defaultRoute="via 192.0.2.1") switch = tgen.add_switch("s1") switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["bmp1"]) - tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "r1-eth1", "r2-eth0") + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"], nodeif="r1-eth1") + switch.add_link(tgen.gears["r2"], nodeif="r2-eth0") + switch.add_link(tgen.gears["r3"], nodeif="r3-eth0") def setup_module(mod): @@ -163,7 +181,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s } } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" in pfx: continue @@ -171,7 +189,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s # ls /tmp/show*json | while read file; do egrep -v 'prefix|network|metric|ocPrf|version|weight|peerId|vrf|Version|valid|Reason|fe80' $file >$(basename $file); echo >> $(basename $file); done with open( - f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w" + f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w" ) as json_file: json.dump(filtered_out, json_file, indent=4) @@ -191,13 +209,13 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s } } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" not in pfx: continue filtered_out["routes"]["routeDistinguishers"][rd][pfx] = None with open( - f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w" + f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w" ) as json_file: json.dump(filtered_out, json_file, indent=4) @@ -211,7 +229,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s if prefix in expected_prefixes } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" in pfx: continue @@ -229,7 +247,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s if prefix in expected_prefixes } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" not in pfx: continue @@ -267,11 +285,11 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): actual = {} for m in messages: if ( - "bmp_log_type" in m.keys() - and "ip_prefix" in m.keys() - and m["ip_prefix"] in expected_prefixes - and m["bmp_log_type"] == bmp_log_type - and m["policy"] == policy + "bmp_log_type" in m.keys() + and "ip_prefix" in m.keys() + and m["ip_prefix"] in expected_prefixes + and m["bmp_log_type"] == bmp_log_type + and m["policy"] == policy ): policy_dict = actual.setdefault(m["policy"], {}) bmp_log_type_dict = policy_dict.setdefault(m["bmp_log_type"], {}) @@ -282,30 +300,34 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): for k, v in sorted(m.items()) # filter out variable keys if k not in ["timestamp", "seq", "nxhp_link-local"] - and ( - # When policy is loc-rib, the peer-distinguisher is 0:0 - # for the default VRF or the RD if any or the 0:. - # 0: is used to distinguished. RFC7854 says: "If the - # peer is a "Local Instance Peer", it is set to a unique, - # locally defined value." The value is not tested because it - # is variable. - k != "peer_distinguisher" - or policy != LOC_RIB - or v == "0:0" - or not v.startswith("0:") - ) + and ( + # When policy is loc-rib, the peer-distinguisher is 0:0 + # for the default VRF or the RD if any or the 0:. + # 0: is used to distinguished. RFC7854 says: "If the + # peer is a "Local Instance Peer", it is set to a unique, + # locally defined value." The value is not tested because it + # is variable. + k != "peer_distinguisher" + or policy != LOC_RIB + or v == "0:0" + or not v.startswith("0:") + ) } + logger.debug(f"messages = {messages}") + logger.debug(f"actual = {actual}") + # build expected JSON files if ( - UPDATE_EXPECTED_JSON - and actual - and set(actual.get(policy, {}).get(bmp_log_type, {}).keys()) - == set(expected_prefixes) + UPDATE_EXPECTED_JSON + and actual + and set(actual.get(policy, {}).get(bmp_log_type, {}).keys()) + == set(expected_prefixes) ): update_expected_files(actual, expected_prefixes, bmp_log_type, policy, step) - return topotest.json_cmp(actual, expected, exact=True) + should_be_exact = policy not in [ADJ_OUT_PRE_POLICY, ADJ_OUT_POST_POLICY] + return topotest.json_cmp(actual, expected, should_be_exact) def check_for_peer_message(expected_peers, bmp_log_type): @@ -351,11 +373,11 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True): "{}network {}\n".format(withdraw, ip), "exit-address-family\n", ] - logger.debug("setting prefix: ipv{} {} {}".format(ip.version, safi, ip)) + logger.debug("[{}] setting prefix: ipv{} {} {}".format(node, ip.version, safi, ip)) tgen.gears[node].vtysh_cmd("".join(cmd)) -def _test_prefixes(policy, vrf=None, step=0): +def _test_prefixes(policy, vrf=None, step=0, prefixes=TEST_PREFIXES): """ Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes. Check if the previous actions are logged in the BMP server with the right @@ -365,13 +387,11 @@ def _test_prefixes(policy, vrf=None, step=0): safi = "vpn" if vrf else "unicast" - prefixes = ["172.31.0.15/32", "2001::1111/128"] - - for type in ("update", "withdraw"): + for type in (BMP_UPDATE, BMP_WITHDRAW): update_seq() configure_prefixes( - tgen, "r2", 65502, "unicast", prefixes, vrf=vrf, update=(type == "update") + tgen, "r2", 65502, "unicast", prefixes, vrf=vrf, update=(type == BMP_UPDATE) ) logger.info(f"checking for prefixes {type}") @@ -384,6 +404,8 @@ def _test_prefixes(policy, vrf=None, step=0): ) expected = json.loads(open(ref_file).read()) + logger.debug(f"checking ipv{ipver} {policy} {type}s for step={step}") + test_func = partial( topotest.router_json_cmp, tgen.gears["r1"], @@ -436,24 +458,62 @@ def test_bmp_bgp_unicast(): """ Add/withdraw bgp unicast prefixes and check the bmp logs. """ - logger.info("*** Unicast prefixes pre-policy logging ***") - _test_prefixes(PRE_POLICY, step=1) - logger.info("*** Unicast prefixes post-policy logging ***") - _test_prefixes(POST_POLICY, step=1) + logger.info("*** Unicast prefixes adj-rib-in pre-policy logging ***") + _test_prefixes(ADJ_IN_PRE_POLICY, step=1) + logger.info("*** Unicast prefixes adj-rib-in post-policy logging ***") + _test_prefixes(ADJ_IN_POST_POLICY, step=1) logger.info("*** Unicast prefixes loc-rib logging ***") _test_prefixes(LOC_RIB, step=1) + logger.info("*** Unicast prefixes adj-rib-out pre-policy logging ***") + _test_prefixes(ADJ_OUT_PRE_POLICY, step=1) + logger.info("*** Unicast prefixes adj-rib-out post-policy logging ***") + _test_prefixes(ADJ_OUT_POST_POLICY, step=1) def test_bmp_bgp_vpn(): # check for the prefixes in the BMP server logging file - logger.info("***** VPN prefixes pre-policy logging *****") - _test_prefixes(PRE_POLICY, vrf="vrf1", step=2) - logger.info("***** VPN prefixes post-policy logging *****") - _test_prefixes(POST_POLICY, vrf="vrf1", step=2) + logger.info("***** VPN prefixes rib-in-pre-policy logging *****") + _test_prefixes(ADJ_IN_PRE_POLICY, vrf="vrf1", step=2) + logger.info("***** VPN prefixes rib-in-post-policy logging *****") + _test_prefixes(ADJ_IN_POST_POLICY, vrf="vrf1", step=2) logger.info("***** VPN prefixes loc-rib logging *****") _test_prefixes(LOC_RIB, vrf="vrf1", step=2) + +def multipath_unicast_prefixes(policy, step, vrf=None): + """ + Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes. + Check if the previous actions are logged in the BMP server with the right + message type and the right policy. + + Make R3 announce the prefixes, then R2 so its paths are ECMP + Finally, withdraw on R3 to clean up + """ + tgen = get_topogen() + + MULTIPATH_TEST_PREFIXES = ["1.1.1.0/31", "3.3.3.0/31"] + + configure_prefixes( + tgen, "r3", 65502, "unicast", MULTIPATH_TEST_PREFIXES, vrf=vrf, update=True + ) + + _test_prefixes(policy, step=step, prefixes=MULTIPATH_TEST_PREFIXES) + + configure_prefixes( + tgen, "r3", 65502, "unicast", MULTIPATH_TEST_PREFIXES, vrf=vrf, update=False + ) + + +def test_bmp_bgp_multipath(): + """ + Test the ECMP feature of BMP i.e. when the loc-rib installs multiple paths + """ + + logger.info("*** Multipath unicast prefixes loc-rib logging ***") + multipath_unicast_prefixes(LOC_RIB, step=3) + + def test_peer_down(): """ Checking for BMP peers down messages diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-loc-rib-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-loc-rib-step1.json index ba31bf1d5df7..57d4a8ace507 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-loc-rib-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-loc-rib-step1.json @@ -6,18 +6,21 @@ "bgp_nexthop": "192.168.0.2", "bmp_log_type": "update", "ip_prefix": "172.31.0.15/32", + "peer_distinguisher": "65501:2", "is_filtered": false, "origin": "IGP", "peer_asn": 65501, "peer_bgp_id": "192.168.0.1", "peer_type": "loc-rib instance", - "policy": "loc-rib" + "policy": "loc-rib", + "path_id": 0 }, "2111::1111/128": { "afi": 2, "as_path": "65501 65502", "bmp_log_type": "update", "ip_prefix": "2111::1111/128", + "peer_distinguisher": "65501:2", "is_filtered": false, "nxhp_ip": "192:168::2", "origin": "IGP", @@ -25,7 +28,8 @@ "peer_bgp_id": "192.168.0.1", "peer_type": "loc-rib instance", "policy": "loc-rib", - "safi": 1 + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-pre-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-post-policy-step1.json similarity index 67% rename from tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-pre-policy-step1.json rename to tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-post-policy-step1.json index e11badc040a9..76b8c5d1f2d8 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-pre-policy-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-post-policy-step1.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-post-policy": { "update": { "172.31.0.15/32": { "as_path": "65501 65502", @@ -10,10 +10,11 @@ "origin": "IGP", "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192.168.0.2", - "peer_type": "global instance", - "policy": "pre-policy" + "peer_type": "route distinguisher instance", + "policy": "rib-in-post-policy", + "path_id": 0 }, "2111::1111/128": { "afi": 2, @@ -25,11 +26,12 @@ "origin": "IGP", "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192:168::2", - "peer_type": "global instance", - "policy": "pre-policy", - "safi": 1 + "peer_type": "route distinguisher instance", + "policy": "rib-in-post-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-post-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-pre-policy-step1.json similarity index 67% rename from tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-post-policy-step1.json rename to tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-pre-policy-step1.json index d5d9d6518265..94a773506905 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-post-policy-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-in-pre-policy-step1.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-pre-policy": { "update": { "172.31.0.15/32": { "as_path": "65501 65502", @@ -10,10 +10,11 @@ "origin": "IGP", "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192.168.0.2", - "peer_type": "global instance", - "policy": "post-policy" + "peer_type": "route distinguisher instance", + "policy": "rib-in-pre-policy", + "path_id": 0 }, "2111::1111/128": { "afi": 2, @@ -25,11 +26,12 @@ "origin": "IGP", "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192:168::2", - "peer_type": "global instance", - "policy": "post-policy", - "safi": 1 + "peer_type": "route distinguisher instance", + "policy": "rib-in-pre-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-post-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-post-policy-step1.json new file mode 100644 index 000000000000..26232702a654 --- /dev/null +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-post-policy-step1.json @@ -0,0 +1,38 @@ +{ + "rib-out-post-policy": { + "update": { + "172.31.0.15/32": { + "as_path": "65501 65502", + "bgp_nexthop": "0.0.0.0", + "bmp_log_type": "update", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192.168.0.2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-post-policy", + "path_id": 0 + }, + "2111::1111/128": { + "afi": 2, + "as_path": "65501 65502", + "bmp_log_type": "update", + "ip_prefix": "2111::1111/128", + "ipv6": true, + "nxhp_ip": "::", + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192:168::2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-post-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-pre-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-pre-policy-step1.json new file mode 100644 index 000000000000..eef374abd86d --- /dev/null +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-update-rib-out-pre-policy-step1.json @@ -0,0 +1,38 @@ +{ + "rib-out-pre-policy": { + "update": { + "172.31.0.15/32": { + "as_path": "65501 65502", + "bgp_nexthop": "192.168.0.2", + "bmp_log_type": "update", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192.168.0.2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-pre-policy", + "path_id": 0 + }, + "2111::1111/128": { + "afi": 2, + "as_path": "65501 65502", + "bmp_log_type": "update", + "ip_prefix": "2111::1111/128", + "ipv6": true, + "nxhp_ip": "192:168::2", + "origin": "IGP", + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192:168::2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-pre-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-loc-rib-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-loc-rib-step1.json index 37ddc09ff85b..202cec10dd7f 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-loc-rib-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-loc-rib-step1.json @@ -4,22 +4,26 @@ "172.31.0.15/32": { "bmp_log_type": "withdraw", "ip_prefix": "172.31.0.15/32", + "peer_distinguisher": "65501:2", "is_filtered": false, "peer_asn": 65501, "peer_bgp_id": "192.168.0.1", "peer_type": "loc-rib instance", - "policy": "loc-rib" + "policy": "loc-rib", + "path_id": 0 }, "2111::1111/128": { "afi": 2, "bmp_log_type": "withdraw", "ip_prefix": "2111::1111/128", + "peer_distinguisher": "65501:2", "is_filtered": false, "peer_asn": 65501, "peer_bgp_id": "192.168.0.1", "peer_type": "loc-rib instance", "policy": "loc-rib", - "safi": 1 + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-post-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-post-policy-step1.json similarity index 60% rename from tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-post-policy-step1.json rename to tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-post-policy-step1.json index de84307a4e6b..cda5a0441681 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-post-policy-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-post-policy-step1.json @@ -1,5 +1,5 @@ { - "post-policy": { + "rib-in-post-policy": { "withdraw": { "172.31.0.15/32": { "bmp_log_type": "withdraw", @@ -7,10 +7,11 @@ "ipv6": false, "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192.168.0.2", - "peer_type": "global instance", - "policy": "post-policy" + "peer_type": "route distinguisher instance", + "policy": "rib-in-post-policy", + "path_id": 0 }, "2111::1111/128": { "afi": 2, @@ -19,11 +20,12 @@ "ipv6": true, "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192:168::2", - "peer_type": "global instance", - "policy": "post-policy", - "safi": 1 + "peer_type": "route distinguisher instance", + "policy": "rib-in-post-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-pre-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json similarity index 60% rename from tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-pre-policy-step1.json rename to tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json index 1c34498b7a38..ff69965535f7 100644 --- a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-pre-policy-step1.json +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-in-pre-policy-step1.json @@ -1,5 +1,5 @@ { - "pre-policy": { + "rib-in-pre-policy": { "withdraw": { "172.31.0.15/32": { "bmp_log_type": "withdraw", @@ -7,10 +7,11 @@ "ipv6": false, "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192.168.0.2", - "peer_type": "global instance", - "policy": "pre-policy" + "peer_type": "route distinguisher instance", + "policy": "rib-in-pre-policy", + "path_id": 0 }, "2111::1111/128": { "afi": 2, @@ -19,11 +20,12 @@ "ipv6": true, "peer_asn": 65502, "peer_bgp_id": "192.168.0.2", - "peer_distinguisher": "0:0", + "peer_distinguisher": "65501:2", "peer_ip": "192:168::2", - "peer_type": "global instance", - "policy": "pre-policy", - "safi": 1 + "peer_type": "route distinguisher instance", + "policy": "rib-in-pre-policy", + "safi": 1, + "path_id": 0 } } } diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-post-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-post-policy-step1.json new file mode 100644 index 000000000000..f52212a9a680 --- /dev/null +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-post-policy-step1.json @@ -0,0 +1,32 @@ +{ + "rib-out-post-policy": { + "withdraw": { + "172.31.0.15/32": { + "bmp_log_type": "withdraw", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192.168.0.2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-post-policy", + "path_id": 0 + }, + "2111::1111/128": { + "afi": 2, + "bmp_log_type": "withdraw", + "ip_prefix": "2111::1111/128", + "ipv6": true, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192:168::2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-post-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json new file mode 100644 index 000000000000..ea628a2e0c59 --- /dev/null +++ b/tests/topotests/bgp_bmp_vrf/bmp1/bmp-withdraw-rib-out-pre-policy-step1.json @@ -0,0 +1,32 @@ +{ + "rib-out-pre-policy": { + "withdraw": { + "172.31.0.15/32": { + "bmp_log_type": "withdraw", + "ip_prefix": "172.31.0.15/32", + "ipv6": false, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192.168.0.2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-pre-policy", + "path_id": 0 + }, + "2111::1111/128": { + "afi": 2, + "bmp_log_type": "withdraw", + "ip_prefix": "2111::1111/128", + "ipv6": true, + "peer_asn": 65502, + "peer_bgp_id": "192.168.0.2", + "peer_distinguisher": "65501:2", + "peer_ip": "192:168::2", + "peer_type": "route distinguisher instance", + "policy": "rib-out-pre-policy", + "safi": 1, + "path_id": 0 + } + } + } +} diff --git a/tests/topotests/bgp_bmp_vrf/r1/bgpd.conf b/tests/topotests/bgp_bmp_vrf/r1/bgpd.conf index 961e20498b2e..eb62221a6c7f 100644 --- a/tests/topotests/bgp_bmp_vrf/r1/bgpd.conf +++ b/tests/topotests/bgp_bmp_vrf/r1/bgpd.conf @@ -7,22 +7,28 @@ router bgp 65501 vrf vrf1 ! bmp targets bmp1 bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000 - bmp monitor ipv4 unicast pre-policy - bmp monitor ipv6 unicast pre-policy - bmp monitor ipv4 unicast post-policy - bmp monitor ipv6 unicast post-policy + bmp monitor ipv4 unicast rib-in pre-policy + bmp monitor ipv6 unicast rib-in pre-policy + bmp monitor ipv4 unicast rib-in post-policy + bmp monitor ipv6 unicast rib-in post-policy bmp monitor ipv4 unicast loc-rib bmp monitor ipv6 unicast loc-rib + bmp monitor ipv4 unicast rib-out pre-policy + bmp monitor ipv6 unicast rib-out pre-policy + bmp monitor ipv4 unicast rib-out post-policy + bmp monitor ipv6 unicast rib-out post-policy exit ! address-family ipv4 unicast + rd vpn export 65501:2 neighbor 192.168.0.2 activate neighbor 192.168.0.2 soft-reconfiguration inbound no neighbor 192:168::2 activate exit-address-family ! address-family ipv6 unicast + rd vpn export 65501:2 neighbor 192:168::2 activate neighbor 192:168::2 soft-reconfiguration inbound exit-address-family diff --git a/tests/topotests/bgp_bmp_vrf/test_bgp_bmp_vrf.py b/tests/topotests/bgp_bmp_vrf/test_bgp_bmp_vrf.py index d31328bdb659..fbcf1c098b50 100644 --- a/tests/topotests/bgp_bmp_vrf/test_bgp_bmp_vrf.py +++ b/tests/topotests/bgp_bmp_vrf/test_bgp_bmp_vrf.py @@ -47,10 +47,17 @@ # remember the last sequence number of the logging messages SEQ = 0 -PRE_POLICY = "pre-policy" -POST_POLICY = "post-policy" +ADJ_IN_PRE_POLICY = "rib-in-pre-policy" +ADJ_IN_POST_POLICY = "rib-in-post-policy" +ADJ_OUT_PRE_POLICY = "rib-out-pre-policy" +ADJ_OUT_POST_POLICY = "rib-out-post-policy" LOC_RIB = "loc-rib" +BMP_UPDATE = "update" +BMP_WITHDRAW = "withdraw" + +TEST_PREFIXES = ["172.31.0.15/32", "2111::1111/128"] + UPDATE_EXPECTED_JSON = False DEBUG_PCAP = False @@ -163,7 +170,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s if prefix in expected_prefixes } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" in pfx: continue @@ -181,7 +188,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s if prefix in expected_prefixes } } - if bmp_log_type == "withdraw": + if bmp_log_type == BMP_WITHDRAW: for pfx in expected_prefixes: if "::" not in pfx: continue @@ -206,7 +213,7 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): # create empty initial files # for step in $(seq 1); do - # for i in "update" "withdraw"; do + # for i in BMP_UPDATE BMP_WITHDRAW; do # for j in "pre-policy" "post-policy" "loc-rib"; do # echo '{"null": {}}'> bmp-$i-$j-step$step.json # done @@ -316,14 +323,12 @@ def _test_prefixes(policy, step=1): """ tgen = get_topogen() - prefixes = ["172.31.0.15/32", "2111::1111/128"] - - for type in ("update", "withdraw"): + for type in (BMP_UPDATE, BMP_WITHDRAW): update_seq() # add prefixes configure_prefixes( - tgen, "r2", 65502, "unicast", prefixes, update=(type == "update") + tgen, "r2", 65502, "unicast", TEST_PREFIXES, update=(type == BMP_UPDATE) ) logger.info(f"checking for prefixes {type}") @@ -347,7 +352,7 @@ def _test_prefixes(policy, step=1): assert res is None, assertmsg # check - test_func = partial(check_for_prefixes, prefixes, type, policy, step) + test_func = partial(check_for_prefixes, TEST_PREFIXES, type, policy, step) success, res = topotest.run_and_expect(test_func, None, count=30, wait=1) assert success, "Checking the updated prefixes has been failed ! %s" % res @@ -388,12 +393,16 @@ def test_bmp_bgp_unicast(): """ Add/withdraw bgp unicast prefixes and check the bmp logs. """ - logger.info("*** Unicast prefixes pre-policy logging ***") - _test_prefixes(PRE_POLICY) - logger.info("*** Unicast prefixes post-policy logging ***") - _test_prefixes(POST_POLICY) + logger.info("*** Unicast prefixes adj-rib-in pre-policy logging ***") + _test_prefixes(ADJ_IN_PRE_POLICY, step=1) + logger.info("*** Unicast prefixes adj-rib-in post-policy logging ***") + _test_prefixes(ADJ_IN_POST_POLICY, step=1) logger.info("*** Unicast prefixes loc-rib logging ***") - _test_prefixes(LOC_RIB) + _test_prefixes(LOC_RIB, step=1) + logger.info("*** Unicast prefixes adj-rib-out pre-policy logging ***") + _test_prefixes(ADJ_OUT_PRE_POLICY, step=1) + logger.info("*** Unicast prefixes adj-rib-out post-policy logging ***") + _test_prefixes(ADJ_OUT_POST_POLICY, step=1) def test_peer_down(): diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py index b3625201f4d9..618173c9093b 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py @@ -47,21 +47,112 @@ class NlriIPv4Unicast: @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from("!B", data) - prefix = padding(data[1:], 4) - return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"} + # we have an add-path id, this check is simpler than the unnecessary (i think?) + # detect_addpath_prefix_ipv46(data, max_bit_length=32) procedure + if len(data) > 5: + (addpath_id, prefix_len) = struct.unpack_from("!IB", data) + addpath_id = {"path_id": addpath_id} + prefix = padding(data[5:], 4) + else: + (prefix_len,) = struct.unpack_from("!B", data) + addpath_id = {} + prefix = padding(data[1:], 4) + + return { + "ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}", + **addpath_id, + } # ------------------------------------------------------------------------------ + +""" +this is the addpath detection from wireshark, not perfect but works in our use cases + +static int detect_add_path_prefix46(tvbuff_t *tvb, gint offset, gint end, gint max_bit_length) +in packet-bgp.c BGP dissector from Wireshark +""" + + +def detect_addpath_prefix_ipv46(data, max_bit_length): + end = len(data) + + # proof by contradiction + # assuming this a well-formatted add-path prefix + # if we find an error it means there was no path-id, or a badly formatted one + # prefix length would be right after path id + # (i don't understand why they loop this check in range(4, end, 4) in Wireshark) + offset = 4 + prefix_len = data[offset] + + # the prefix length is bigger than the maximum allowed size + if prefix_len > max_bit_length: + return False + + addr_len = (prefix_len + 7) // 8 + offset += 1 + addr_len + + # the prefix length announces a prefix bigger than what we have + if offset > end: + return False + + # the prefix length tells us that the last byte will have more some 0 padding bits + # and those bits are not set to 0 + if prefix_len % 8 > 0 and data[offset - 1] & (0xFF >> (prefix_len % 8)) > 0: + return False + + # proof by contradiction + # assuming there is not an add-path prefix, and this is well formatted + # if we find an error it may mean there was a path-id + # assuming there is no add-path path-id + offset = 0 + while offset < end: + # prefix length would be first + prefix_len = data[offset] + + # prefix length is zero and we have more than one byte of address so maybe this was a path-id + if prefix_len == 0 and end - offset > 1: + return True + + # invalid prefix length so maybe this was a path-id + if prefix_len > max_bit_length: + return True + + addr_len = (prefix_len + 7) // 8 + offset += 1 + addr_len + + # the prefix length announces a prefix bigger than what we have + if offset > end: + return True # maybe this was a path-id + + # the prefix length tells us that the last byte will have more some 0 padding bits + # and those bits are not set to 0 + if prefix_len % 8 > 0 and data[offset - 1] & (0xFF >> (prefix_len % 8)) > 0: + return True # maybe it was a path-id + + # we don't know if it's add-path so let's say no + return False + class NlriIPv6Unicast: @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from("!B", data) - prefix = padding(data[1:], 16) - return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"} + # we have an add-path id + if detect_addpath_prefix_ipv46(data, max_bit_length=128): + (addpath_id, prefix_len) = struct.unpack_from("!IB", data) + addpath_id = {"path_id": addpath_id} + prefix = padding(data[5:], 16) + else: + (prefix_len,) = struct.unpack_from("!B", data) + addpath_id = {} + prefix = padding(data[1:], 16) + + return { + "ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}", + **addpath_id, + } # ------------------------------------------------------------------------------ diff --git a/tests/topotests/lib/bmp_collector/bmp.py b/tests/topotests/lib/bmp_collector/bmp.py index ac8af0284499..b5f34748577a 100644 --- a/tests/topotests/lib/bmp_collector/bmp.py +++ b/tests/topotests/lib/bmp_collector/bmp.py @@ -281,7 +281,11 @@ def dissect(cls, data): 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["policy"] = "post-policy" if is_post_policy else "pre-policy" + msg["policy"] = ( + ("rib-out" if is_adj_rib_out else "rib-in") + + "-" + + ("post-policy" if is_post_policy else "pre-policy") + ) msg["ipv6"] = is_ipv6 msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6) From 5566d75a0f3ae3492082f1aa87acf084f88410ef Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Tue, 28 Nov 2023 13:32:55 +0100 Subject: [PATCH 03/11] doc: update bmp doc for adj-rib-out, ecmp, and loc-rib Signed-off-by: Maxence Younsi --- doc/developer/bmp.rst | 55 +++++++++++-------------- doc/user/bmp.rst | 94 +++++++++++++++++++++---------------------- 2 files changed, 69 insertions(+), 80 deletions(-) diff --git a/doc/developer/bmp.rst b/doc/developer/bmp.rst index 1c0e4b045426..269cbafd29a5 100644 --- a/doc/developer/bmp.rst +++ b/doc/developer/bmp.rst @@ -4,46 +4,37 @@ BMP *** -RFC 7854 -======== +RFC 7854: BMP Adj-RIB-In +======================== Missing features (non exhaustive): - - Per-Peer Header - - - Peer Type Flag - - Peer Distingsher - - - Peer Up - + - Peer Down - 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 -======== +RFC 9069: BMP Local-RIB +======================= 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 +- Peer Down Only + - Reason code (bc not supported in RFC 7854 either) - - code for TLV exists - - need better RFC understanding +RFC8671: BMP Adj-RIB-Out +======================== +Adj-RIB-Out pre-policy uses tricks to work because we soft-reconfiguration outbound does not exist. +So what we do is we call the BGP function (subgroup_announce_check) which decides whether to announce or not to peers, +while ignoring the outbound policy + some conditions specific to Adj-RIB-Out Post-policy. +This allows us to guess whether the route would've been in Adj-RIB-Out Pre-policy or not. However, we cannot compute +all pre-policy stats as a consequence. -- Peer Down Only +Everything that isn't listed here is implemented and should be working. - - Reason code (bc not supported in RFC 7854 either) +- Per-Peer Header + - Timestamp: not recorded, set to 0 -- Statistics Report +- Stats + - adj-rib-out pre-policy counters (cannot be done since adj-rib-out pre-policy is not saved) - - 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. +ECMP Support +============ +The RX Add-Path ID is exported for Adj-RIB-In Pre/Post-policy and Local-RIB. +The TX Add-Path ID is exported for Adj-RIB-Out Pre/Post-policy. diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst index e4cffcb2e460..078bca61663c 100644 --- a/doc/user/bmp.rst +++ b/doc/user/bmp.rst @@ -12,8 +12,8 @@ Implementation characteristics The `BMP` implementation in FRR has the following properties: -- only the :rfc:`7854` features are currently implemented. This means protocol - version 3 without any extensions. It is not possible to use an older draft +- :rfc:`7854`, :rfc:`9069`, :rfc:`8671` features are currently implemented. This means protocol + version 3 without Local-RIB and Adj-RIB-Out Monitoring support. It is not possible to use an older draft protocol version of BMP. - the following statistics codes are implemented: @@ -23,10 +23,16 @@ The `BMP` implementation in FRR has the following properties: - 3: count of **prefixes** with loop in cluster id - 4: count of **prefixes** with loop in AS-path - 5: count of **prefixes** with loop in originator + - 7: count of **routes** in adj-rib-in (pre-policy) + - 8: count of **routes** in local-rib + - 9: count of **routes** per afi/safi in adj-rib-in (pre-policy) + - 10: count of **routes** per afi/safi in local-rib - 7: count of **routes** in adj-rib-in - 8: count of **routes** in Loc-RIB - 11: count of updates subjected to :rfc:`7607` "treat as withdrawal" handling due to errors + - 15: count of routes in adj-rib-out post-policy + - 17: count of routes per afi/safi in adj-rib-out post-policy - 65531: *experimental* count of prefixes rejected due to invalid next-hop Note that stat items 3, 4 and 5 are specified to count updates, but FRR @@ -42,20 +48,11 @@ The `BMP` implementation in FRR has the following properties: 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 - result in somewhat unpredictable behaviour. Currently, the outcome is: - +- monitoring peers that have BGP **add-path** enabled on will have the following behaviour: - route mirroring functions as intended, messages are copied verbatim - - the add-path ID is never included in route monitoring messages - - if multiple paths were received from a peer, an unpredictable path is - picked and sent on the BMP session. The selection will differ for - pre-policy and post-policy monitoring sessions. - - as long as any path is present, something will be advertised on BMP - sessions. Only after the last path is gone a withdrawal will be sent on - BMP sessions. - - updates to additional paths will trigger BMP route monitoring messages. - There is no guarantee on consistency regarding which path is sent in these - messages. + - the add-path ID is always included in route monitoring messages + - routes from peers without add-path have the "default" 0 path-id included + - the received path-id will be included for Adj-RIB-In and Local-RIB - monitoring peers with :rfc:`5549` extended next-hops has not been tested. @@ -205,7 +202,7 @@ associated with a particular ``bmp targets``: a subset of BGP sessions may be added in the future. BMP Troubleshooting -------------- +------------------- When encountering problems with BMP, it may be interesting to know the current @@ -217,35 +214,36 @@ state of the latter. configured modes, global settings, ... .. code-block:: frr -BMP Module started at Fri Feb 24 13:05:50 2023 - -BMP state for BGP VRF default: - - Route Mirroring 0 bytes (0 messages) pending - 0 bytes maximum buffer used - - Startup delay : 10000ms - - Targets "my_targets": - Route Mirroring disabled - Route Monitoring IPv4 unicast rib-out pre-policy rib-out post-policy - Listeners: - - Outbound connections: - remote state timer local - ---------------------------------------------------------------------- - 99.99.99.99:12345 Up 99.99.99.99:12345 00:00:04 (unspec) - - 1 connected clients: - remote uptime state MonSent MirrSent MirrLost ByteSent ByteQ ByteQKernel - --------------------------------------------------------------------------------------------------------------- - 99.99.99.99:12345 00:00:04 Startup-Wait 0 0 0 61 0 0 -:: - - Here we have a single BGP instance running on VRF default. No specific mirroring settings but a - startup delay of 10000ms. - This instance has a single target with rib-out pre-policy and post-policy monitoring, no mirroring. - This target has a single session open with client 99.99.99.99 on port 12345 which is in state Startup-Wait. - This session will start sending monitoring messages as soon as the current time is - "Fri Feb 24 13:05:50 2023" + 10000ms = "Fri Feb 24 13:06:00 2023" which explains why it is in - Startup-Wait mode and has not sent Monitoring Messages yet. + + BMP Module started at Fri Feb 24 13:05:50 2023 + + BMP state for BGP VRF default: + + Route Mirroring 0 bytes (0 messages) pending + 0 bytes maximum buffer used + + Startup delay : 10000ms + + Targets "my_targets": + Route Mirroring disabled + Route Monitoring IPv4 unicast rib-out pre-policy rib-out post-policy + Listeners: + + Outbound connections: + remote state timer local + ---------------------------------------------------------------------- + 99.99.99.99:12345 Up 99.99.99.99:12345 00:00:04 (unspec) + + 1 connected clients: + remote uptime state MonSent MirrSent MirrLost ByteSent ByteQ ByteQKernel + --------------------------------------------------------------------------------------------------------------- + 99.99.99.99:12345 00:00:04 Startup-Wait 0 0 0 61 0 0 + + +Here we have a single BGP instance running on VRF default. No specific mirroring settings but a +startup delay of 10000ms. +This instance has a single target with rib-out pre-policy and post-policy monitoring, no mirroring. +This target has a single session open with client 99.99.99.99 on port 12345 which is in state Startup-Wait. +This session will start sending monitoring messages as soon as the current time is +"Fri Feb 24 13:05:50 2023" + 10000ms = "Fri Feb 24 13:06:00 2023" which explains why it is in +Startup-Wait mode and has not sent Monitoring Messages yet. From 5fa7c46b2c57c2ae60e43a49dea5ab8bc6147ab6 Mon Sep 17 00:00:00 2001 From: Maxou <5208681+mxyns@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:34:34 +0100 Subject: [PATCH 04/11] bgpd: supplementary lock for when the bmp module is not loaded Signed-off-by: Maxence Younsi --- bgpd/bgp_route.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 585c4c08a005..ada41d82b8c5 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3796,6 +3796,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, * set */ if (old_select || new_select) { + if (old_select) + bgp_path_info_lock(old_select); + hook_call(bgp_route_update, bgp, afi, safi, dest, old_select, new_select); } @@ -3988,6 +3991,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, old_select->peer->stat_loc_rib_count[afi][safi]--; hook_call(bgp_process_main_one_end, bgp, old_select); + bgp_path_info_unlock(old_select); } if (new_select && new_select->peer) @@ -4008,7 +4012,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, } bgp_mpath_diff_clear(&mpath_diff); bgp_mpath_diff_fini(&mpath_diff); - return; } /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */ From 1e7e0c14f633e4c9165beeb0a676f40c619c73be Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Mon, 8 Jan 2024 11:06:48 +0100 Subject: [PATCH 05/11] doc, tests, bgpd: address PR#14847 review fixed nits & styling issues fixed bad conditions in bmp_bpi_(un)lock added bgp_peer_get_send_holdtime added bgp_peer_get_local_as Signed-off-by: Maxence Younsi --- bgpd/bgp_bmp.c | 49 +++++++++----------------------------- bgpd/bgp_conditional_adv.c | 10 ++++---- bgpd/bgp_main.c | 7 ------ bgpd/bgp_packet.c | 36 ++++++++++++++++------------ bgpd/bgp_packet.h | 4 +++- bgpd/bgp_route.c | 2 +- bgpd/bgp_updgrp.h | 2 +- bgpd/bgp_updgrp_adv.c | 18 +++++++------- bgpd/bgpd.h | 4 ++-- doc/developer/bmp.rst | 2 +- doc/user/bmp.rst | 2 +- 11 files changed, 55 insertions(+), 81 deletions(-) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 95dde58f1aa0..24fb0ab04edb 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -79,7 +79,6 @@ static struct timeval bmp_startup_time = {0}; /* compute the time in millis since the bmp_startup_time recorded */ static uint32_t bmp_time_since_startup(struct timeval *delay) { - if (bmp_startup_time.tv_sec == 0 && bmp_startup_time.tv_usec == 0) { zlog_info("bmp [%s]: Startup time not recorded", __func__); return 0; @@ -94,7 +93,6 @@ static uint32_t bmp_time_since_startup(struct timeval *delay) static const char *bmp_state_str(enum BMP_State state) { switch (state) { - case BMP_StartupIdle: return "Startup-Wait"; case BMP_PeerUp: @@ -212,7 +210,7 @@ struct bmp_lbpi_h_head bmp_lbpi; static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, struct bgp_path_info *bpi) { - if (!bpi && !bpi) + if (!bgp || !bpi) return NULL; BMP_LBPI_LOOKUP_BPI(head, prev, hash_lookup, bpi, bgp); @@ -252,8 +250,7 @@ static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, static struct bmp_bpi_lock *bmp_unlock_bpi(struct bgp *bgp, struct bgp_path_info *bpi) { - - if (!bpi) + if (!bgp || !bpi) return NULL; BMP_LBPI_LOOKUP_BPI(head, prev, hash_lookup, bpi, bgp); @@ -267,7 +264,6 @@ static struct bmp_bpi_lock *bmp_unlock_bpi(struct bgp *bgp, /* if bpi is not used by bmp anymore */ if (hash_lookup->lock <= 0) { - struct bgp_path_info *tmp_bpi = hash_lookup->locked; struct bgp_dest *tmp_dest = hash_lookup->dest; struct bgp *tmp_bgp = hash_lookup->bgp; @@ -499,20 +495,15 @@ static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, if (afi == AFI_UNSPEC) { { /* scope lock iter variables */ afi_t afi_rd_lookup; - safi_t _; - - FOREACH_AFI_SAFI (afi_rd_lookup, _) { + for (afi_rd_lookup = AFI_IP; afi_rd_lookup < AFI_MAX; afi_rd_lookup++) { if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup] .flags, BGP_VPN_POLICY_TOVPN_RD_SET)) { afi = afi_rd_lookup; - /* stop FOREACH_AFI_SAFI macro */ - afi_rd_lookup = AFI_MAX; + /* we found an AFI with a RD set */ + break; } - - /* break safi sub-loop to go over next afi */ - break; } } @@ -735,9 +726,9 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) /* Local Address (16 bytes) */ if (!peer->su_local || is_locrib) - stream_put(s, 0, 16); + stream_put(s, 0, IPV6_MAX_BYTELEN); else if (peer->su_local->sa.sa_family == AF_INET6) - stream_put(s, &peer->su_local->sin6.sin6_addr, 16); + stream_put(s, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); else if (peer->su_local->sa.sa_family == AF_INET) { stream_putl(s, 0); stream_putl(s, 0); @@ -1460,7 +1451,6 @@ static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, continue; SUBGRP_FOREACH_PEER (subgrp, paf) { - addpath_tx_id = !bpi ? 0 : bgp_addpath_id_for_peer( @@ -1524,8 +1514,6 @@ struct rib_out_post_updgrp_walkctx { static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, void *hidden_ctx) { - - struct rib_out_post_updgrp_walkctx *ctx = (struct rib_out_post_updgrp_walkctx *)hidden_ctx; @@ -1537,7 +1525,6 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, struct bgp_path_info *bpi = ctx->bpi; UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { - addpath_tx_id = !bpi ? 0 : bgp_addpath_id_for_peer( SUBGRP_PEER(subgrp), @@ -1591,7 +1578,6 @@ static inline bool bmp_monitor_rib_out_post_walk( bmp_monitor_rib_out_post_updgrp_walkcb, (void *)&walkctx); - return written; } @@ -2464,8 +2450,9 @@ static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, } } - // if bmp_process_one returns NULL - // we don't have anything to do next + /* if bmp_process_one returns NULL + * we don't have anything to do next + */ if (!new_head) continue; @@ -2847,21 +2834,7 @@ static int bmp_bgp_del(struct bgp *bgp) static void bmp_bgp_peer_vrf(struct bmp_bgp_peer *bbpeer, struct bgp *bgp) { struct peer *peer = bgp->peer_self; - uint16_t send_holdtime; - as_t local_as; - - if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) - send_holdtime = peer->holdtime; - else - send_holdtime = peer->bgp->default_holdtime; - - /* local-as Change */ - if (peer->change_local_as) - local_as = peer->change_local_as; - else - local_as = peer->local_as; - - struct stream *s = bgp_open_make(peer, send_holdtime, local_as); + struct stream *s = bgp_open_make(peer); size_t open_len = stream_get_endp(s); bbpeer->open_rx_len = open_len; diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index 1977bbf0b43f..cd23ba7ddc1b 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -106,14 +106,14 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, subgrp, dest, pi, !addpath_capable ? 0 - : bgp_addpath_id_for_peer( - peer, afi, safi, - &pi->tx_addpath), + : bgp_addpath_id_for_peer(peer, + afi, + safi, + &pi->tx_addpath), &attr, false, update_type == UPDATE_TYPE_ADVERTISE ? false - : true, - __func__); + : true); } diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 03f4886d3b29..535d2fc5f434 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -267,8 +267,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) static int bgp_vrf_new(struct vrf *vrf) { - zlog_info("BGP VRF CREATE %s", vrf->name); - if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id); @@ -277,7 +275,6 @@ static int bgp_vrf_new(struct vrf *vrf) static int bgp_vrf_delete(struct vrf *vrf) { - zlog_info("BGP VRF DELETE %s", vrf->name); if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id); @@ -289,8 +286,6 @@ static int bgp_vrf_enable(struct vrf *vrf) struct bgp *bgp; vrf_id_t old_vrf_id; - zlog_info("BGP VRF ENABLE %s", vrf->name); - if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id); @@ -324,8 +319,6 @@ static int bgp_vrf_disable(struct vrf *vrf) { struct bgp *bgp; - zlog_info("BGP VRF DISABLE %s", vrf->name); - if (vrf->vrf_id == VRF_DEFAULT) return 0; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index a76a300c11bc..2f2138592ec2 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -637,11 +637,30 @@ void bgp_keepalive_send(struct peer *peer) bgp_writes_on(peer->connection); } -struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t local_as) +uint16_t bgp_peer_get_send_holdtime(struct peer *peer) +{ + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) + return peer->holdtime; + else + return peer->bgp->default_holdtime; +} + +as_t bgp_peer_get_local_as(struct peer *peer) +{ + if (peer->change_local_as) + return peer->change_local_as; + else + return peer->local_as; +} + +struct stream *bgp_open_make(struct peer *peer) { struct stream *s = stream_new(BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE); bool ext_opt_params = false; + uint16_t send_holdtime = bgp_peer_get_send_holdtime(peer); + as_t local_as = bgp_peer_get_local_as(peer); + /* Make open packet. */ bgp_packet_set_marker(s, BGP_MSG_OPEN); @@ -690,22 +709,9 @@ struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t loc void bgp_open_send(struct peer_connection *connection) { struct stream *s; - uint16_t send_holdtime; - as_t local_as; struct peer *peer = connection->peer; - if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) - send_holdtime = peer->holdtime; - else - send_holdtime = peer->bgp->default_holdtime; - - /* local-as Change */ - if (peer->change_local_as) - local_as = peer->change_local_as; - else - local_as = peer->local_as; - - s = bgp_open_make(peer, send_holdtime, local_as); + s = bgp_open_make(peer); /* Dump packet if debug option is set. */ /* bgp_packet_dump (s); */ diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index c266b17266ec..fe1be95ad8ce 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -43,7 +43,9 @@ DECLARE_HOOK(bgp_packet_send, /* Packet send and receive function prototypes. */ extern void bgp_keepalive_send(struct peer *peer); -extern struct stream *bgp_open_make(struct peer *peer, uint16_t send_holdtime, as_t local_as); +extern as_t bgp_peer_get_local_as(struct peer *peer); +extern uint16_t bgp_peer_get_send_holdtime(struct peer *peer); +extern struct stream *bgp_open_make(struct peer *peer); extern void bgp_open_send(struct peer_connection *connection); extern void bgp_notify_send(struct peer_connection *connection, uint8_t code, uint8_t sub_code); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ada41d82b8c5..254560dfebed 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3397,7 +3397,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, advertise = bgp_check_advertise(bgp, dest, safi); bgp_adj_out_updated(subgrp, dest, selected, addpath_tx_id, &attr, false, - selected && advertise ? false : true, __func__); + selected && advertise ? false : true); if (selected) { if (subgroup_announce_check(dest, selected, subgrp, p, pattr, diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index 5ade05c3653f..537fe87d1ed5 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -454,7 +454,7 @@ extern void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest, struct bgp_path_info *path, uint32_t addpath_tx, struct attr *attr, bool post_policy, - bool withdraw, const char *caller); + bool withdraw); extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, char withdraw, uint32_t addpath_tx_id); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index aadd0c67d8aa..587fa06f8fd0 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -285,10 +285,11 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) } if (!adj) - bgp_adj_out_updated( - subgrp, ctx->dest, NULL, - 0, NULL, false, true, - __func__); + bgp_adj_out_updated(subgrp, + ctx->dest, + NULL, 0, + NULL, false, + true); } } } @@ -537,8 +538,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, /* call the bgp_adj_out_updated hook for bmp rib-out monitoring */ void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest, struct bgp_path_info *path, uint32_t addpath_tx, - struct attr *attr, bool post_policy, bool withdraw, - const char *caller) + struct attr *attr, bool post_policy, bool withdraw) { if (path && !withdraw && CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) { /* path is removed, enforcing withdraw state */ @@ -682,7 +682,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, subgrp->version = MAX(subgrp->version, dest->version); bgp_adj_out_updated(subgrp, dest, path, adj->addpath_tx_id, attr, true, - false, __func__); + false); return true; } @@ -736,7 +736,7 @@ void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, bgp_adj_out_updated(subgrp, dest, NULL, adj->addpath_tx_id, NULL, true, - withdraw, __func__); + withdraw); } else { /* Free allocated information. */ adj_free(adj); @@ -1024,7 +1024,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw) dest = bgp_safi_node_lookup(bgp->rib[afi][safi_rib], safi_rib, &p, NULL); - // TODO BMP hook call for rib-out pre-policy + // TODO add missing BMP hook call for default-originate in rib-out pre-policy if (withdraw) { /* Withdraw the default route advertised using default diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 22cb9b3b7bff..36f80153c3b7 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1710,9 +1710,9 @@ struct peer { uint32_t stat_pfx_nh_invalid; uint32_t stat_pfx_dup_withdraw; uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */ - uint32_t stat_adj_in_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Adj-RIBs-In */ + uint32_t stat_adj_in_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Adj-RIB-In */ uint32_t stat_loc_rib_count[AFI_MAX][SAFI_MAX]; /* RFC7854 : Number of routes in Loc-RIB */ - // no need for stat_adj_out_count here, it is in struct update_subgroup + /* no need for stat_adj_out_count here, it is in struct update_subgroup */ /* BGP state count */ uint32_t established; /* Established */ diff --git a/doc/developer/bmp.rst b/doc/developer/bmp.rst index 269cbafd29a5..1ba198497d7b 100644 --- a/doc/developer/bmp.rst +++ b/doc/developer/bmp.rst @@ -20,7 +20,7 @@ Missing features (should be exhaustive): RFC8671: BMP Adj-RIB-Out ======================== -Adj-RIB-Out pre-policy uses tricks to work because we soft-reconfiguration outbound does not exist. +Adj-RIB-Out pre-policy monitoring uses tricks to work because soft-reconfiguration outbound does not exist. So what we do is we call the BGP function (subgroup_announce_check) which decides whether to announce or not to peers, while ignoring the outbound policy + some conditions specific to Adj-RIB-Out Post-policy. This allows us to guess whether the route would've been in Adj-RIB-Out Pre-policy or not. However, we cannot compute diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst index 078bca61663c..fa567f448961 100644 --- a/doc/user/bmp.rst +++ b/doc/user/bmp.rst @@ -90,7 +90,7 @@ There are two options that apply to the BGP instance as a whole: BMP Route Monitoring is not affected by this option. -.. clicmd:: bmp startup-delay delay(0-4294967294) +.. clicmd:: bmp startup-delay delay (0-4294967294) This sets the delay (in milliseconds) after module startup for BMP sessions to become active. From e92854975d36006bb140d041adee1b8ceda5a6d5 Mon Sep 17 00:00:00 2001 From: Maxou Date: Tue, 26 Mar 2024 10:52:12 +0100 Subject: [PATCH 06/11] bgp: apply frrbot patch Signed-off-by: Maxence Younsi --- bgpd/bgp_advertise.c | 11 +- bgpd/bgp_advertise.h | 10 +- bgpd/bgp_bmp.c | 709 +++++++----------- bgpd/bgp_bmp.h | 70 +- bgpd/bgp_conditional_adv.c | 28 +- bgpd/bgp_evpn.c | 3 +- bgpd/bgp_evpn_mh.c | 3 +- bgpd/bgp_mpath.c | 7 +- bgpd/bgp_mpath.h | 4 +- bgpd/bgp_packet.c | 4 +- bgpd/bgp_route.c | 97 +-- bgpd/bgp_route.h | 36 +- bgpd/bgp_updgrp.h | 16 +- bgpd/bgp_updgrp_adv.c | 33 +- lib/pullwr.c | 3 +- tests/topotests/bgp_bmp/test_bgp_bmp.py | 8 +- .../lib/bmp_collector/bgp/update/nlri.py | 1 + 17 files changed, 412 insertions(+), 631 deletions(-) diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 7179c5835d3e..0dad5324f45a 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -162,8 +162,8 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, } -void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, - struct peer *peer, struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels) +void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, struct peer *peer, + struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels) { struct bgp_adj_in *adj; @@ -191,8 +191,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, bgp_dest_lock_node(dest); } -void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, - struct bgp_adj_in *bai) +void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, struct bgp_adj_in *bai) { bgp_attr_unintern(&bai->attr); bgp_labels_unintern(&bai->labels); @@ -203,8 +202,8 @@ void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, XFREE(MTYPE_BGP_ADJ_IN, bai); } -bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, - struct peer *peer, uint32_t addpath_id) +bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, struct peer *peer, + uint32_t addpath_id) { struct bgp_adj_in *adj; struct bgp_adj_in *adj_next; diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index ae71418bfb8d..071d1fec4b6d 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -140,12 +140,10 @@ struct bgp_synchronize { /* Prototypes. */ extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, uint32_t addpath_tx_id); -extern void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, - struct peer *peer, struct attr *attr, - uint32_t addpath_id, - struct bgp_labels *labels); -extern bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, - struct peer *peer, uint32_t addpath_id); +extern void bgp_adj_in_set(struct bgp_dest *dest, afi_t afi, safi_t safi, struct peer *peer, + struct attr *attr, uint32_t addpath_id, struct bgp_labels *labels); +extern bool bgp_adj_in_unset(struct bgp_dest **dest, afi_t afi, safi_t safi, struct peer *peer, + uint32_t addpath_id); extern void bgp_adj_in_remove(struct bgp_dest **dest, afi_t afi, safi_t safi, struct bgp_adj_in *bai); diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 24fb0ab04edb..2a33e2392df1 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -74,7 +74,7 @@ DEFINE_MTYPE_STATIC(BMP, BMP_LBPI, "BMP locked BPI"); DEFINE_QOBJ_TYPE(bmp_targets); /* module startup time for the startup-delay */ -static struct timeval bmp_startup_time = {0}; +static struct timeval bmp_startup_time = { 0 }; /* compute the time in millis since the bmp_startup_time recorded */ static uint32_t bmp_time_since_startup(struct timeval *delay) @@ -165,8 +165,7 @@ struct bmp_peerh_head bmp_peerh; /* comparison function for struct bmp_bpi_lock used in bmp_lbpi_h hashtable * compares the prefixes and bgp instance pointer values */ -static int bmp_bpi_lock_cmp(const struct bmp_bpi_lock *a, - const struct bmp_bpi_lock *b) +static int bmp_bpi_lock_cmp(const struct bmp_bpi_lock *a, const struct bmp_bpi_lock *b) { int cmp = prefix_cmp(bgp_dest_get_prefix(a->dest), bgp_dest_get_prefix(b->dest)); if (cmp) @@ -191,8 +190,7 @@ static uint32_t bmp_bpi_lock_hash(const struct bmp_bpi_lock *e) return key; } -DECLARE_HASH(bmp_lbpi_h, struct bmp_bpi_lock, lbpi_h, bmp_bpi_lock_cmp, - bmp_bpi_lock_hash); +DECLARE_HASH(bmp_lbpi_h, struct bmp_bpi_lock, lbpi_h, bmp_bpi_lock_cmp, bmp_bpi_lock_hash); /* hashtable to store the bgp path state when withdrawn * allows rib-out pre-policy to run the pre-policy check on the path after @@ -207,8 +205,7 @@ struct bmp_lbpi_h_head bmp_lbpi; * increment the lock * returns the lock structure if successful */ -static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, - struct bgp_path_info *bpi) +static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, struct bgp_path_info *bpi) { if (!bgp || !bpi) return NULL; @@ -216,8 +213,7 @@ static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, BMP_LBPI_LOOKUP_BPI(head, prev, hash_lookup, bpi, bgp); if (!hash_lookup) { - hash_lookup = - XCALLOC(MTYPE_BMP_LBPI, sizeof(struct bmp_bpi_lock)); + hash_lookup = XCALLOC(MTYPE_BMP_LBPI, sizeof(struct bmp_bpi_lock)); SET_FLAG(bpi->flags, BGP_PATH_BMP_LOCKED); hash_lookup->bgp = bgp; hash_lookup->locked = bpi; @@ -247,8 +243,7 @@ static struct bmp_bpi_lock *bmp_lock_bpi(struct bgp *bgp, * if lock is <= 0 we need to free the lock and unlock held structures * returns the lock structure if it is not freed */ -static struct bmp_bpi_lock *bmp_unlock_bpi(struct bgp *bgp, - struct bgp_path_info *bpi) +static struct bmp_bpi_lock *bmp_unlock_bpi(struct bgp *bgp, struct bgp_path_info *bpi) { if (!bgp || !bpi) return NULL; @@ -451,7 +446,6 @@ static void bmp_free(struct bmp *bmp) */ static inline int bmp_get_peer_type_vrf(vrf_id_t vrf_id) { - switch (vrf_id) { case VRF_DEFAULT: return BMP_PEER_TYPE_GLOBAL_INSTANCE; @@ -479,16 +473,14 @@ static inline int bmp_get_peer_type(struct peer *peer) * returns 1 on error that needs message discarding * 0 if successful */ -static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, - uint64_t *result_ref) +static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, uint64_t *result_ref) { /* vrf default => ok, distinguisher 0 */ if (bgp->inst_type == VRF_DEFAULT) return (int)(*result_ref = 0); /* if requested afi has no rd configured find any other */ - if (afi >= AFI_MAX || !CHECK_FLAG(bgp->vpn_policy[afi].flags, - BGP_VPN_POLICY_TOVPN_RD_SET)) + if (afi >= AFI_MAX || !CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) afi = AFI_UNSPEC; /* afi not known, use any afi configured in this vrf */ @@ -497,8 +489,7 @@ static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, afi_t afi_rd_lookup; for (afi_rd_lookup = AFI_IP; afi_rd_lookup < AFI_MAX; afi_rd_lookup++) { - if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup] - .flags, + if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) { afi = afi_rd_lookup; /* we found an AFI with a RD set */ @@ -703,13 +694,11 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) monotime_to_realtime(&uptime, &uptime_real); bool is_locrib = peer->bgp->peer_self == peer; - uint8_t peer_type = is_locrib ? BMP_PEER_TYPE_LOC_RIB_INSTANCE - : bmp_get_peer_type(peer); + uint8_t peer_type = is_locrib ? BMP_PEER_TYPE_LOC_RIB_INSTANCE : bmp_get_peer_type(peer); uint64_t peer_distinguisher = 0; /* skip this message if peer distinguisher is not available */ - if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, - &peer_distinguisher)) + if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, &peer_distinguisher)) return NULL; #define BGP_BMP_MAX_PACKET_SIZE 1024 @@ -721,8 +710,7 @@ 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->bgp, peer, 0, peer_type, - peer_distinguisher, &uptime_real); + bmp_per_peer_hdr(s, peer->bgp, peer, 0, peer_type, peer_distinguisher, &uptime_real); /* Local Address (16 bytes) */ if (!peer->su_local || is_locrib) @@ -784,8 +772,7 @@ 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->bgp, peer, 0, peer_type, - peer_distinguisher, &uptime_real); + bmp_per_peer_hdr(s, peer->bgp, peer, 0, peer_type, peer_distinguisher, &uptime_real); type_pos = stream_get_endp(s); stream_putc(s, 0); /* placeholder for down reason */ @@ -1034,8 +1021,7 @@ 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, bgp, bgp->peer_self, 0, peer_type, - peer_distinguisher, &tv); + bmp_per_peer_hdr(s, bgp, bgp->peer_self, 0, peer_type, peer_distinguisher, &tv); stream_putw(s, BMP_MIRROR_TLV_TYPE_INFO); stream_putw(s, 2); @@ -1076,8 +1062,7 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr) uint64_t peer_distinguisher = 0; /* skip this message if peer distinguisher is not available */ - if (bmp_get_peer_distinguisher(bmp->targets->bgp, AFI_UNSPEC, - &peer_distinguisher)) + if (bmp_get_peer_distinguisher(bmp->targets->bgp, AFI_UNSPEC, &peer_distinguisher)) goto out; struct stream *s; @@ -1085,8 +1070,7 @@ static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr) bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING); - bmp_per_peer_hdr(s, bmp->targets->bgp, peer, 0, peer_type, - peer_distinguisher, &bmq->tv); + bmp_per_peer_hdr(s, bmp->targets->bgp, peer, 0, peer_type, peer_distinguisher, &bmq->tv); /* BMP Mirror TLV. */ stream_putw(s, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE); @@ -1278,9 +1262,8 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags, /* makes a bgp update to be embedded in a bmp monitoring message */ -static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, - uint32_t addpath_id, 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, uint32_t addpath_id, + struct peer *peer, struct attr *attr, afi_t afi, safi_t safi, mpls_label_t *label, uint32_t num_labels) { struct bpacket_attr_vec_arr vecarr; @@ -1301,10 +1284,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, stream_putw(s, 0); /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */ - total_attr_len = - bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, - safi, peer, NULL, NULL, 0, - safi != SAFI_MPLS_VPN, addpath_id); + total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, safi, peer, + NULL, NULL, 0, safi != SAFI_MPLS_VPN, addpath_id); /* space check? */ @@ -1318,9 +1299,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, &vecarr, attr); - bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, - num_labels, safi != SAFI_MPLS_VPN, - addpath_id, attr); + bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels, + safi != SAFI_MPLS_VPN, addpath_id, attr); bgp_packet_mpattr_end(s, mpattrlen_pos); total_attr_len += stream_get_endp(s) - p1; } @@ -1333,9 +1313,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd, /* makes a bgp withdraw to be embedded in a bmp monitoring message */ -static struct stream *bmp_withdraw(const struct prefix *p, - struct prefix_rd *prd, uint32_t addpath_id, - afi_t afi, safi_t safi) +static struct stream *bmp_withdraw(const struct prefix *p, struct prefix_rd *prd, + uint32_t addpath_id, afi_t afi, safi_t safi) { struct stream *s; size_t attrlen_pos = 0, mp_start, mplen_pos; @@ -1360,9 +1339,8 @@ static struct stream *bmp_withdraw(const struct prefix *p, mp_start = stream_get_endp(s); mplen_pos = bgp_packet_mpunreach_start(s, afi, safi); - bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, - safi != SAFI_MPLS_VPN, addpath_id, - NULL); + bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, safi != SAFI_MPLS_VPN, + addpath_id, NULL); /* Set the mp_unreach attr's length */ bgp_packet_mpunreach_end(s, mplen_pos); @@ -1379,11 +1357,10 @@ static struct stream *bmp_withdraw(const struct prefix *p, * * if uptime is (time_t)(-1L) then do not include the timestamp in the message */ -static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, - uint8_t peer_type, const struct prefix *p, - struct prefix_rd *prd, struct attr *attr, afi_t afi, - safi_t safi, uint32_t addpath_id, time_t uptime, - mpls_label_t *label, uint32_t num_labels) +static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, uint8_t peer_type, + const struct prefix *p, struct prefix_rd *prd, struct attr *attr, afi_t afi, + safi_t safi, uint32_t addpath_id, time_t uptime, mpls_label_t *label, + uint32_t num_labels) { struct stream *hdr, *msg; struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 }; @@ -1391,21 +1368,18 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, uint64_t peer_distinguisher = 0; /* skip this message if peer distinguisher is not available */ - if (bmp_get_peer_distinguisher(bmp->targets->bgp, afi, - &peer_distinguisher)) + if (bmp_get_peer_distinguisher(bmp->targets->bgp, afi, &peer_distinguisher)) return; monotime_to_realtime(&tv, &uptime_real); if (attr) - msg = bmp_update(p, prd, addpath_id, peer, attr, afi, safi, - label, num_labels); + msg = bmp_update(p, prd, addpath_id, peer, attr, afi, safi, label, num_labels); else msg = bmp_withdraw(p, prd, addpath_id, afi, safi); hdr = stream_new(BGP_MAX_PACKET_SIZE); bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING); - bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type, - peer_distinguisher, + bmp_per_peer_hdr(hdr, bmp->targets->bgp, peer, flags, peer_type, peer_distinguisher, uptime == (time_t)(-1L) ? NULL : &uptime_real); stream_putl_at(hdr, BMP_LENGTH_POS, @@ -1430,11 +1404,9 @@ struct rib_out_pre_updgrp_walkctx { }; /* bmp sync for rib-out pre-policy callback for each update group */ -static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, - void *hidden_ctx) +static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, void *hidden_ctx) { - struct rib_out_pre_updgrp_walkctx *ctx = - (struct rib_out_pre_updgrp_walkctx *)hidden_ctx; + struct rib_out_pre_updgrp_walkctx *ctx = (struct rib_out_pre_updgrp_walkctx *)hidden_ctx; struct update_subgroup *subgrp; struct peer_af *paf; @@ -1442,30 +1414,25 @@ static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, struct bgp_path_info *bpi = ctx->bpi; UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { + struct attr dummy_attr = { 0 }; - struct attr dummy_attr = {0}; - - if (!subgroup_announce_check(ctx->dest, bpi, subgrp, - ctx->pfx, &dummy_attr, NULL, + if (!subgroup_announce_check(ctx->dest, bpi, subgrp, ctx->pfx, &dummy_attr, NULL, BGP_ANNCHK_SPECIAL_PREPOLICY)) continue; SUBGRP_FOREACH_PEER (subgrp, paf) { - addpath_tx_id = - !bpi ? 0 - : bgp_addpath_id_for_peer( - SUBGRP_PEER(subgrp), - SUBGRP_AFI(subgrp), - SUBGRP_SAFI(subgrp), - &bpi->tx_addpath); + addpath_tx_id = !bpi ? 0 + : bgp_addpath_id_for_peer(SUBGRP_PEER(subgrp), + SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), + &bpi->tx_addpath); bmp_monitor(ctx->bmp, PAF_PEER(paf), BMP_PEER_FLAG_O, - bmp_get_peer_type(PAF_PEER(paf)), bgp_dest_get_prefix(ctx->dest), - ctx->prd, ctx->attr, SUBGRP_AFI(subgrp), - SUBGRP_SAFI(subgrp), addpath_tx_id, - (time_t)(-1L), - bpi->extra ? bpi->extra->labels->label : NULL, - bpi->extra ? bpi->extra->labels->num_labels : 0); + bmp_get_peer_type(PAF_PEER(paf)), + bgp_dest_get_prefix(ctx->dest), ctx->prd, ctx->attr, + SUBGRP_AFI(subgrp), SUBGRP_SAFI(subgrp), addpath_tx_id, + (time_t)(-1L), bpi && bpi->extra ? bpi->extra->labels->label : NULL, + bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); *ctx->written_ref = true; } @@ -1477,25 +1444,21 @@ static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, /* bmp sync for rib-out pre-policy * calls bmp_monitor_rib_out_pre_updgrp_walkcb foreach update group */ -static inline bool bmp_monitor_rib_out_pre_walk(struct bmp *bmp, afi_t afi, - safi_t safi, const struct prefix *pfx, - struct bgp_dest *dest, - struct bgp_path_info *bpi, - struct attr *attr, +static inline bool bmp_monitor_rib_out_pre_walk(struct bmp *bmp, afi_t afi, safi_t safi, + const struct prefix *pfx, struct bgp_dest *dest, + struct bgp_path_info *bpi, struct attr *attr, struct prefix_rd *prd) { bool written = false; - struct rib_out_pre_updgrp_walkctx walkctx = {.bmp = bmp, - .pfx = pfx, - .dest = dest ? dest - : bpi->net, - .bpi = bpi, - .attr = attr, - .prd = prd, - .written_ref = &written}; - - update_group_af_walk(bmp->targets->bgp, afi, safi, - bmp_monitor_rib_out_pre_updgrp_walkcb, + struct rib_out_pre_updgrp_walkctx walkctx = { .bmp = bmp, + .pfx = pfx, + .dest = dest ? dest : bpi->net, + .bpi = bpi, + .attr = attr, + .prd = prd, + .written_ref = &written }; + + update_group_af_walk(bmp->targets->bgp, afi, safi, bmp_monitor_rib_out_pre_updgrp_walkcb, (void *)&walkctx); return written; @@ -1511,11 +1474,9 @@ struct rib_out_post_updgrp_walkctx { }; /* bmp sync for rib-out post-policy callback for each update group */ -static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, - void *hidden_ctx) +static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, void *hidden_ctx) { - struct rib_out_post_updgrp_walkctx *ctx = - (struct rib_out_post_updgrp_walkctx *)hidden_ctx; + struct rib_out_post_updgrp_walkctx *ctx = (struct rib_out_post_updgrp_walkctx *)hidden_ctx; struct update_subgroup *subgrp; struct peer_af *paf; @@ -1525,12 +1486,10 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, struct bgp_path_info *bpi = ctx->bpi; UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { - addpath_tx_id = !bpi ? 0 - : bgp_addpath_id_for_peer( - SUBGRP_PEER(subgrp), - SUBGRP_AFI(subgrp), - SUBGRP_SAFI(subgrp), - &bpi->tx_addpath); + addpath_tx_id = + !bpi ? 0 + : bgp_addpath_id_for_peer(SUBGRP_PEER(subgrp), SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), &bpi->tx_addpath); adj = adj_lookup(ctx->dest, subgrp, addpath_tx_id); @@ -1542,14 +1501,12 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, : NULL; SUBGRP_FOREACH_PEER (subgrp, paf) { - bmp_monitor(ctx->bmp, PAF_PEER(paf), - BMP_PEER_FLAG_O | BMP_PEER_FLAG_L, + bmp_monitor(ctx->bmp, PAF_PEER(paf), BMP_PEER_FLAG_O | BMP_PEER_FLAG_L, bmp_get_peer_type(PAF_PEER(paf)), ctx->pfx, ctx->prd, - advertised_attr, SUBGRP_AFI(subgrp), - SUBGRP_SAFI(subgrp), addpath_tx_id, - (time_t)(-1L), - bpi->extra ? bpi->extra->labels->label : NULL, - bpi->extra ? bpi->extra->labels->num_labels : 0); + advertised_attr, SUBGRP_AFI(subgrp), SUBGRP_SAFI(subgrp), + addpath_tx_id, (time_t)(-1L), + bpi && bpi->extra ? bpi->extra->labels->label : NULL, + bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); *ctx->written_ref = true; } @@ -1561,21 +1518,16 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, /* bmp sync for rib-out post-policy * calls bmp_monitor_rib_out_post_updgrp_walkcb for each update group */ -static inline bool bmp_monitor_rib_out_post_walk( - struct bmp *bmp, afi_t afi, safi_t safi, - const struct prefix *pfx, struct bgp_dest *dest, - struct bgp_path_info *bpi, struct prefix_rd *prd) +static inline bool bmp_monitor_rib_out_post_walk(struct bmp *bmp, afi_t afi, safi_t safi, + const struct prefix *pfx, struct bgp_dest *dest, + struct bgp_path_info *bpi, struct prefix_rd *prd) { bool written = false; - struct rib_out_post_updgrp_walkctx walkctx = {.bmp = bmp, - .pfx = pfx, - .dest = dest, - .bpi = bpi, - .prd = prd, - .written_ref = &written}; + struct rib_out_post_updgrp_walkctx walkctx = { + .bmp = bmp, .pfx = pfx, .dest = dest, .bpi = bpi, .prd = prd, .written_ref = &written + }; - update_group_af_walk(bmp->targets->bgp, afi, safi, - bmp_monitor_rib_out_post_updgrp_walkcb, + update_group_af_walk(bmp->targets->bgp, afi, safi, bmp_monitor_rib_out_post_updgrp_walkcb, (void *)&walkctx); return written; @@ -1690,25 +1642,20 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) */ if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_IN_PREPOLICY)) - bmp_eor(bmp, afi, safi, 0, - BMP_PEER_TYPE_GLOBAL_INSTANCE); + bmp_eor(bmp, afi, safi, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE); if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_IN_POSTPOLICY)) bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L, BMP_PEER_TYPE_GLOBAL_INSTANCE); - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_LOC_RIB)) - bmp_eor(bmp, afi, safi, 0, - BMP_PEER_TYPE_LOC_RIB_INSTANCE); + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) + bmp_eor(bmp, afi, safi, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE); if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_OUT_PREPOLICY)) bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_O, BMP_PEER_TYPE_GLOBAL_INSTANCE); if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_OUT_POSTPOLICY)) - bmp_eor(bmp, afi, safi, - BMP_PEER_FLAG_O | - BMP_PEER_FLAG_L, + bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_O | BMP_PEER_FLAG_L, BMP_PEER_TYPE_GLOBAL_INSTANCE); bmp->afistate[afi][safi] = BMP_AFI_LIVE; @@ -1721,16 +1668,13 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) } if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB | - BMP_MON_OUT_PREPOLICY | + BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB | BMP_MON_OUT_PREPOLICY | BMP_MON_OUT_POSTPOLICY)) { 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 | - BGP_PATH_MULTIPATH)) + BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) continue; if (bpiter->peer->qobj_node.nid <= bmp->syncpeerid) @@ -1741,8 +1685,7 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) bpi = bpiter; } } - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_IN_PREPOLICY)) { + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_IN_PREPOLICY)) { for (adjiter = bn->adj_in; adjiter; adjiter = adjiter->next) { if (adjiter->peer->qobj_node.nid @@ -1791,37 +1734,32 @@ static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) } uint8_t mon_flags = bmp->targets->afimon[afi][safi]; + bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) && CHECK_FLAG(mon_flags, BMP_MON_IN_POSTPOLICY)) { - bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, - bmp_get_peer_type(bpi->peer), bn_p, prd, bpi->attr, afi, - safi, bpi->addpath_rx_id, bpi->uptime, - bpi_num_labels ? bpi->extra->labels->label : NULL, - bpi_num_labels); + bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bmp_get_peer_type(bpi->peer), bn_p, + prd, bpi->attr, afi, safi, bpi->addpath_rx_id, bpi->uptime, + bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); UNSET_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG); written = true; } - bool bpi_selected = - bpi && - CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH); + bool bpi_selected = bpi && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH); if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_LOC_RIB)) { - bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, bn_p, - prd, bpi->attr, afi, safi, bpi->addpath_rx_id, - bpi && bpi->extra ? bpi->extra->bgp_rib_uptime - : (time_t)(-1L), - bpi_num_labels ? bpi->extra->labels->label : NULL, - bpi_num_labels); + bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, bn_p, prd, bpi->attr, + afi, safi, bpi->addpath_rx_id, + bpi && bpi->extra ? bpi->extra->bgp_rib_uptime : (time_t)(-1L), + bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); written = true; } if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_OUT_PREPOLICY)) { - written |= bmp_monitor_rib_out_pre_walk( - bmp, afi, safi, bgp_dest_get_prefix(bn), bn, bpi, bpi->attr, prd); + written |= bmp_monitor_rib_out_pre_walk(bmp, afi, safi, bgp_dest_get_prefix(bn), bn, + bpi, bpi->attr, prd); } if (bpi_selected && CHECK_FLAG(mon_flags, BMP_MON_OUT_POSTPOLICY)) { @@ -1868,8 +1806,7 @@ bmp_pull_from_queue(struct bmp_qlist_head *list, struct bmp_qhash_head *hash, */ static inline struct bmp_queue_entry *bmp_pull_ribin(struct bmp *bmp) { - return bmp_pull_from_queue(&bmp->targets->mon_in_updlist, - &bmp->targets->mon_in_updhash, + return bmp_pull_from_queue(&bmp->targets->mon_in_updlist, &bmp->targets->mon_in_updhash, &bmp->mon_in_queuepos); } @@ -1877,8 +1814,7 @@ static inline struct bmp_queue_entry *bmp_pull_ribin(struct bmp *bmp) */ static inline struct bmp_queue_entry *bmp_pull_locrib(struct bmp *bmp) { - return bmp_pull_from_queue(&bmp->targets->mon_loc_updlist, - &bmp->targets->mon_loc_updhash, + return bmp_pull_from_queue(&bmp->targets->mon_loc_updlist, &bmp->targets->mon_loc_updhash, &bmp->mon_loc_queuepos); } @@ -1886,8 +1822,7 @@ static inline struct bmp_queue_entry *bmp_pull_locrib(struct bmp *bmp) */ static inline struct bmp_queue_entry *bmp_pull_ribout(struct bmp *bmp) { - return bmp_pull_from_queue(&bmp->targets->mon_out_updlist, - &bmp->targets->mon_out_updhash, + return bmp_pull_from_queue(&bmp->targets->mon_out_updlist, &bmp->targets->mon_out_updhash, &bmp->mon_out_queuepos); } @@ -1897,7 +1832,6 @@ static inline struct bmp_queue_entry *bmp_pull_ribout(struct bmp *bmp) static inline int bmp_prefix_will_sync(struct bmp *bmp, afi_t afi, safi_t safi, struct prefix *prefix) { - switch (bmp->afistate[afi][safi]) { case BMP_AFI_INACTIVE: case BMP_AFI_NEEDSYNC: @@ -1948,8 +1882,7 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) uint32_t addpath_rx_id = bqe->addpath_id; - if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB)) + if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_IN_POSTPOLICY | BMP_MON_LOC_RIB)) goto out; if (bmp_prefix_will_sync(bmp, afi, safi, &bqe->p)) @@ -1975,14 +1908,11 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL; - bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi, - &bqe->p, prd); + bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi, &bqe->p, prd); struct bgp_path_info *locrib = NULL, *ribin = NULL; - for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); - bpi; bpi = bpi->next) { - + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { /* match the right path */ if (bpi->peer != peer || bpi->addpath_rx_id != addpath_rx_id) continue; @@ -1990,11 +1920,8 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* rib-in post-policy configured and path is valid */ if (CHECK_FLAG(flags, BMP_MON_IN_POSTPOLICY) && CHECK_FLAG(bpi->flags, BGP_PATH_VALID)) { - - bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, - bmp_get_peer_type(peer), &bqe->p, prd, - bpi->attr, afi, safi, addpath_rx_id, - bpi->uptime, + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, bmp_get_peer_type(peer), &bqe->p, + prd, bpi->attr, afi, safi, addpath_rx_id, bpi->uptime, bpi && bpi->extra ? bpi->extra->labels->label : NULL, bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); ribin = bpi; @@ -2003,39 +1930,33 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* loc-rib configured and path is selected */ if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && - CHECK_FLAG(bpi->flags, - BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) { + CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) { uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); - bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, - &bqe->p, prd, bpi->attr, afi, safi, - addpath_rx_id, - bpi->extra ? bpi->extra->bgp_rib_uptime - : (time_t)(-1L), + bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, + bpi->attr, afi, safi, addpath_rx_id, + bpi->extra ? bpi->extra->bgp_rib_uptime : (time_t)(-1L), bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); locrib = bpi; written = true; } - if (locrib && - ribin) /* early out when we've sent both messages */ + if (locrib && ribin) /* early out when we've sent both messages */ goto out; } /* rib-in post-policy path not found, send withdraw */ if (CHECK_FLAG(flags, BMP_MON_IN_POSTPOLICY) && !ribin) { - bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, bmp_get_peer_type(peer), - &bqe->p, prd, NULL, afi, safi, addpath_rx_id, - (time_t)(-1), NULL, 0); + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, bmp_get_peer_type(peer), &bqe->p, prd, NULL, + afi, safi, addpath_rx_id, (time_t)(-1), NULL, 0); written = true; } /* loc-rib path not found, send withdraw */ if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && !locrib) { - bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, - NULL, afi, safi, addpath_rx_id, (time_t)(-1L), - NULL, 0); + bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, NULL, afi, + safi, addpath_rx_id, (time_t)(-1L), NULL, 0); written = true; } @@ -2080,8 +2001,7 @@ static bool bmp_wrqueue_ribin(struct bmp *bmp, struct pullwr *pullwr) if (!peer_established(peer->connection)) goto out; - if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_IN_PREPOLICY) || + if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_IN_PREPOLICY) || !CHECK_FLAG(bqe->flags, BMP_MON_IN_PREPOLICY)) goto out; @@ -2097,15 +2017,13 @@ static bool bmp_wrqueue_ribin(struct bmp *bmp, struct pullwr *pullwr) /* lookup adjin of this destination */ for (adjin = bn ? bn->adj_in : NULL; adjin; adjin = adjin->next) { /* match right path */ - if (adjin->peer == peer && - adjin->addpath_rx_id == addpath_rx_id) + if (adjin->peer == peer && adjin->addpath_rx_id == addpath_rx_id) break; } adjin_num_labels = adjin && adjin->labels ? adjin->labels->num_labels : 0; - bmp_monitor(bmp, peer, 0, bmp_get_peer_type(peer), &bqe->p, prd, - adjin ? adjin->attr : NULL, afi, safi, addpath_rx_id, - adjin ? adjin->uptime : monotime(NULL), + bmp_monitor(bmp, peer, 0, bmp_get_peer_type(peer), &bqe->p, prd, adjin ? adjin->attr : NULL, + afi, safi, addpath_rx_id, adjin ? adjin->uptime : monotime(NULL), adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); written = true; @@ -2140,7 +2058,7 @@ static bool bmp_wrqueue_ribout(struct bmp *bmp, struct pullwr *pullwr) uint32_t addpath_tx_id = bqe->addpath_id; if (!CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_OUT_POSTPOLICY | BMP_MON_OUT_PREPOLICY)) { + BMP_MON_OUT_POSTPOLICY | BMP_MON_OUT_PREPOLICY)) { goto out; } @@ -2161,44 +2079,36 @@ static bool bmp_wrqueue_ribout(struct bmp *bmp, struct pullwr *pullwr) bn = bgp_safi_node_lookup(bmp->targets->bgp->rib[afi][safi], safi, &bqe->p, prd); - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_OUT_PREPOLICY) && + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_OUT_PREPOLICY) && CHECK_FLAG(bqe->flags, BMP_MON_OUT_PREPOLICY)) { - /* lookup path in rib */ struct bgp_path_info *bpi; for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { if (addpath_tx_id != - bgp_addpath_id_for_peer(peer, afi, safi, - &bpi->tx_addpath)) + bgp_addpath_id_for_peer(peer, afi, safi, &bpi->tx_addpath)) continue; - if (CHECK_FLAG(bpi->flags, - BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) break; } uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); - bmp_monitor(bmp, peer, BMP_PEER_FLAG_O, bmp_get_peer_type(peer), - &bqe->p, prd, bpi ? bpi->attr : NULL, afi, safi, - addpath_tx_id, (time_t)(-1L), - bpi_num_labels ? bpi->extra->labels->label : NULL, - bpi_num_labels); + bmp_monitor(bmp, peer, BMP_PEER_FLAG_O, bmp_get_peer_type(peer), &bqe->p, prd, + bpi ? bpi->attr : NULL, afi, safi, addpath_tx_id, (time_t)(-1L), + bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); written = true; } - if (CHECK_FLAG(bmp->targets->afimon[afi][safi], - BMP_MON_OUT_POSTPOLICY) && + if (CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_OUT_POSTPOLICY) && CHECK_FLAG(bqe->flags, BMP_MON_OUT_POSTPOLICY)) { struct bgp_adj_out *adj; struct attr *advertised_attr; /* lookup path in adj-rib-out */ - adj = adj_lookup(bn, peer_subgroup(peer, afi, safi), - addpath_tx_id); + adj = adj_lookup(bn, peer_subgroup(peer, afi, safi), addpath_tx_id); /* advertised attributes (NULL if withdrawn) */ advertised_attr = adj ? !adj->adv ? adj->attr @@ -2207,10 +2117,9 @@ static bool bmp_wrqueue_ribout(struct bmp *bmp, struct pullwr *pullwr) : NULL; /* TODO: set label here when adjout supports labels */ - bmp_monitor(bmp, peer, BMP_PEER_FLAG_L | BMP_PEER_FLAG_O, - bmp_get_peer_type(peer), &bqe->p, prd, - advertised_attr, afi, safi, addpath_tx_id, - (time_t)(-1L), NULL, 0); + bmp_monitor(bmp, peer, BMP_PEER_FLAG_L | BMP_PEER_FLAG_O, bmp_get_peer_type(peer), + &bqe->p, prd, advertised_attr, afi, safi, addpath_tx_id, (time_t)(-1L), + NULL, 0); written = true; } @@ -2239,8 +2148,8 @@ static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr) return; } - zlog_info("bmp: Startup timeout expired, time since startup is %" PRIu32 - "ms", timeout_ms); + zlog_info("bmp: Startup timeout expired, time since startup is %" PRIu32 "ms", + timeout_ms); bmp->state = BMP_PeerUp; /* start BMP_PeerUp mode now */ @@ -2290,9 +2199,8 @@ static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof) */ static struct bmp_queue_entry * bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash, - struct bmp_qlist_head *updlist, afi_t afi, safi_t safi, - struct bgp_dest *bn, uint32_t addpath_id, struct peer *peer, - uint8_t mon_flag) + struct bmp_qlist_head *updlist, afi_t afi, safi_t safi, struct bgp_dest *bn, + uint32_t addpath_id, struct peer *peer, uint8_t mon_flag) { struct bmp_queue_entry *bqe, bqeref; size_t refcount; @@ -2344,9 +2252,8 @@ bmp_process_one(struct bmp_targets *bt, struct bmp_qhash_head *updhash, * if enabled in config, inserts a bqe to the adj-rib-in pre monitoring queue * which will trigger a bmp monitoring message to be sent for adj-rib-in pre */ -static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_dest *bn, uint32_t addpath_id, - struct peer *peer, bool post) +static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, + uint32_t addpath_id, struct peer *peer, bool post) { struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); struct bmp_targets *bt; @@ -2356,8 +2263,7 @@ static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, char pfxprint[PREFIX2STR_BUFFER]; prefix2str(&bn->rn->p, pfxprint, sizeof(pfxprint)); - frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, - safi, withdraw); + frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, safi, withdraw); } if (!bmpbgp) @@ -2373,10 +2279,9 @@ static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, * best-path */ if (post) { - for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); - bpi; bpi = bpi->next) - if (bpi->peer == peer && - bpi->addpath_rx_id == addpath_id) + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); bpi; + bpi = bpi->next) + if (bpi->peer == peer && bpi->addpath_rx_id == addpath_id) SET_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG); } @@ -2384,9 +2289,9 @@ static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, if (!CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_IN_PREPOLICY)) continue; - struct bmp_queue_entry *new_item = bmp_process_one( - bt, &bt->mon_in_updhash, &bt->mon_in_updlist, afi, safi, - bn, addpath_id, peer, BMP_MON_IN_PREPOLICY); + struct bmp_queue_entry *new_item = + bmp_process_one(bt, &bt->mon_in_updhash, &bt->mon_in_updlist, afi, safi, bn, + addpath_id, peer, BMP_MON_IN_PREPOLICY); /* if bmp_process_one returns NULL * we don't have anything to do next @@ -2409,8 +2314,7 @@ static int bmp_process_ribinpre(struct bgp *bgp, afi_t afi, safi_t safi, * monitoring queue which will trigger a bmp monitoring message to be sent * for adj-rib-in post-policy */ -static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_dest *bn) +static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn) { struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp); struct bmp_targets *bt; @@ -2420,8 +2324,7 @@ static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, char pfxprint[PREFIX2STR_BUFFER]; prefix2str(bgp_dest_get_prefix(bn), pfxprint, sizeof(pfxprint)); - frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, - safi, withdraw); + frrtrace(5, frr_bgp, bmp_process_ribinpre, peer, pfxprint, afi, safi, withdraw); } if (!bmpbgp) @@ -2435,14 +2338,13 @@ static int bmp_process_ribinpost(struct bgp *bgp, afi_t afi, safi_t safi, struct bmp_queue_entry *new_head = NULL, *new_item = NULL; /* find paths that changed in pre-policy and need update */ - for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); - bpi; bpi = bpi->next) { + for (struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(bn); bpi; + bpi = bpi->next) { if (CHECK_FLAG(bpi->flags, BGP_PATH_BMP_ADJIN_CHG)) { - new_item = bmp_process_one( - bt, &bt->mon_loc_updhash, - &bt->mon_loc_updlist, afi, safi, bn, - bpi->addpath_rx_id, bpi->peer, - BMP_MON_IN_POSTPOLICY); + new_item = bmp_process_one(bt, &bt->mon_loc_updhash, + &bt->mon_loc_updlist, afi, safi, bn, + bpi->addpath_rx_id, bpi->peer, + BMP_MON_IN_POSTPOLICY); new_head = !new_head ? new_item : new_head; @@ -2488,8 +2390,8 @@ static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type, } /* put a per-AFI/SAFI u64 stat to the stream */ -static void bmp_stat_put_af_u64(struct stream *s, size_t *cnt, uint16_t type, - afi_t afi, safi_t safi, uint64_t value) +static void bmp_stat_put_af_u64(struct stream *s, size_t *cnt, uint16_t type, afi_t afi, + safi_t safi, uint64_t value) { stream_putw(s, type); stream_putw(s, 2 + 1 + 8); @@ -2502,18 +2404,16 @@ static void bmp_stat_put_af_u64(struct stream *s, size_t *cnt, uint16_t type, /* macro that sends a stat per AFI/SAFI and the total sum of sub-stats. * per AFI/SAFI is not sent if 0 and force_zero == false */ -#define BMP_PER_AF_STAT(afi_var, safi_var, af_stat_arr, sum_var, safi_stat, \ - safi_stat_call, sum_stat_call, force_zero) \ - do { \ - (sum_var) = 0; \ - FOREACH_AFI_SAFI ((afi_var), (safi_var)) { \ - (sum_var) += ((af_stat_arr)[(afi_var)][(safi_var)] = \ - (safi_stat)); \ - if ((force_zero) || \ - (af_stat_arr)[(afi_var)][(safi_var)]) \ - (safi_stat_call); \ - }; \ - (sum_stat_call); \ +#define BMP_PER_AF_STAT(afi_var, safi_var, af_stat_arr, sum_var, safi_stat, safi_stat_call, \ + sum_stat_call, force_zero) \ + do { \ + (sum_var) = 0; \ + FOREACH_AFI_SAFI ((afi_var), (safi_var)) { \ + (sum_var) += ((af_stat_arr)[(afi_var)][(safi_var)] = (safi_stat)); \ + if ((force_zero) || (af_stat_arr)[(afi_var)][(safi_var)]) \ + (safi_stat_call); \ + }; \ + (sum_stat_call); \ } while (0) /* send stats and reschedule event */ @@ -2549,25 +2449,21 @@ static void bmp_stats(struct event *thread) uint64_t peer_distinguisher = 0; /* skip this message if peer distinguisher is not available */ - if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, - &peer_distinguisher)) + if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, &peer_distinguisher)) continue; s = stream_new(BGP_MAX_PACKET_SIZE); bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT); - bmp_per_peer_hdr(s, bt->bgp, peer, 0, - peer_type, peer_distinguisher, &tv); + bmp_per_peer_hdr(s, bt->bgp, peer, 0, peer_type, peer_distinguisher, &tv); count_pos = stream_get_endp(s); stream_putl(s, 0); bmp_stat_put_u32(s, &count, BMP_STATS_PFX_REJECTED, peer->stat_pfx_filter); - bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW, - peer->stat_pfx_dup_withdraw); - bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER, - peer->stat_pfx_cluster_loop); + bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW, peer->stat_pfx_dup_withdraw); + bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER, peer->stat_pfx_cluster_loop); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ASPATH, peer->stat_pfx_aspath_loop); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ORIGINATOR, @@ -2575,47 +2471,29 @@ static void bmp_stats(struct event *thread) bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW, peer->stat_upd_7606); - BMP_PER_AF_STAT( - afi, safi, af_stat, per_af_sum, - peer->stat_adj_in_count[afi][safi], - bmp_stat_put_af_u64( - s, &count, - BMP_STATS_SIZE_ADJ_RIB_IN_SAFI, afi, - safi, af_stat[afi][safi]), - bmp_stat_put_u64(s, &count, - BMP_STATS_SIZE_ADJ_RIB_IN, - per_af_sum), - false); + BMP_PER_AF_STAT(afi, safi, af_stat, per_af_sum, peer->stat_adj_in_count[afi][safi], + bmp_stat_put_af_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN_SAFI, afi, + safi, af_stat[afi][safi]), + bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN, per_af_sum), + false); + + BMP_PER_AF_STAT(afi, safi, af_stat, per_af_sum, peer->stat_loc_rib_count[afi][safi], + bmp_stat_put_af_u64(s, &count, BMP_STATS_SIZE_LOC_RIB_SAFI, afi, + safi, af_stat[afi][safi]), + bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_LOC_RIB, per_af_sum), + false); BMP_PER_AF_STAT(afi, safi, af_stat, per_af_sum, - peer->stat_loc_rib_count[afi][safi], - bmp_stat_put_af_u64( - s, &count, - BMP_STATS_SIZE_LOC_RIB_SAFI, - afi, safi, af_stat[afi][safi]), - bmp_stat_put_u64(s, &count, - BMP_STATS_SIZE_LOC_RIB, + ((subgrp = peer_subgroup(peer, afi, safi)) ? subgrp->pscount : 0), + bmp_stat_put_af_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI, + afi, safi, af_stat[afi][safi]), + bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_OUT_POST, per_af_sum), false); - BMP_PER_AF_STAT( - afi, safi, af_stat, per_af_sum, - ((subgrp = peer_subgroup(peer, afi, safi)) - ? subgrp->pscount - : 0), - bmp_stat_put_af_u64( - s, &count, - BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI, - afi, safi, af_stat[afi][safi]), - bmp_stat_put_u64( - s, &count, - BMP_STATS_SIZE_ADJ_RIB_OUT_POST, - per_af_sum), - false); - if (bt->stats_send_experimental) bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID, - peer->stat_pfx_nh_invalid); + peer->stat_pfx_nh_invalid); stream_putl_at(s, count_pos, count); @@ -2696,9 +2574,7 @@ static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock) sockunion2str(&su, buf, SU_ADDRSTRLEN); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":%u", - su.sa.sa_family == AF_INET - ? ntohs(su.sin.sin_port) - : ntohs(su.sin6.sin6_port)); + su.sa.sa_family == AF_INET ? ntohs(su.sin.sin_port) : ntohs(su.sin6.sin6_port)); if (ret == FILTER_DENY) { bt->cnt_aclrefused++; @@ -2722,8 +2598,7 @@ static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock) strlcpy(bmp->remote, buf, sizeof(bmp->remote)); bmp->state = BMP_StartupIdle; - bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill, - bmp_wrerr); + bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill, bmp_wrerr); event_add_read(bm->master, bmp_read, bmp, bmp_sock, &bmp->t_read); bmp_send_initiation(bmp); @@ -3162,8 +3037,7 @@ static void bmp_active_connect(struct bmp_active *ba) } - res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos], - htons(ba->port), 0); + res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos], htons(ba->port), 0); switch (res) { case connect_error: zlog_warn("bmp[%s]: failed to connect to %pSU:%d", @@ -3540,21 +3414,13 @@ DEFPY(bmp_stats_send_experimental, /* |l|oc-rib */ #define BMP_POLICY_IS_LOCRIB(rib) ((rib)[0] == 'l') /* rib-|i|n p|r|e-policy */ -#define BMP_POLICY_IS_IN_PRE(rib, policy) ((rib)[4] == 'i' \ - && (policy) \ - && (policy)[1] == 'r') \ - /* rib-|i|n p|o|st-policy */ -#define BMP_POLICY_IS_IN_POST(rib, policy) ((rib)[4] == 'i' \ - && (policy) \ - && (policy)[1] == 'o') \ - /* rib-|o|ut p|r|e-policy */ -#define BMP_POLICY_IS_OUT_PRE(rib, policy) ((rib)[4] == 'o' \ - && (policy) \ - && (policy)[1] == 'r') \ - /* rib-|o|ut p|o|st-policy */ -#define BMP_POLICY_IS_OUT_POST(rib, policy) ((rib)[4] == 'o' \ - && (policy) \ - && (policy)[1] == 'o') +#define BMP_POLICY_IS_IN_PRE(rib, policy) \ + ((rib)[4] == 'i' && (policy) && (policy)[1] == 'r') /* rib-|i|n p|o|st-policy */ +#define BMP_POLICY_IS_IN_POST(rib, policy) \ + ((rib)[4] == 'i' && (policy) && (policy)[1] == 'o') /* rib-|o|ut p|r|e-policy */ +#define BMP_POLICY_IS_OUT_PRE(rib, policy) \ + ((rib)[4] == 'o' && (policy) && (policy)[1] == 'r') /* rib-|o|ut p|o|st-policy */ +#define BMP_POLICY_IS_OUT_POST(rib, policy) ((rib)[4] == 'o' && (policy) && (policy)[1] == 'o') DEFPY(bmp_monitor_cfg, bmp_monitor_cmd, "[no] bmp monitor $rib [pre-policy|post-policy]$policy", @@ -3718,26 +3584,20 @@ static void bmp_show_bmp(struct vty *vty) vty_out(vty, "BMP Module started at %pTVM\n\n", &bmp_startup_time); frr_each(bmp_bgph, &bmp_bgph, bmpbgp) { - vty_out(vty, "BMP state for BGP %s:\n\n", - bmpbgp->bgp->name_pretty); - vty_out(vty, - " Route Mirroring %9zu bytes (%zu messages) pending\n", - bmpbgp->mirror_qsize, - bmp_mirrorq_count(&bmpbgp->mirrorq)); - vty_out(vty, - " %9zu bytes maximum buffer used\n", + vty_out(vty, "BMP state for BGP %s:\n\n", bmpbgp->bgp->name_pretty); + vty_out(vty, " Route Mirroring %9zu bytes (%zu messages) pending\n", + bmpbgp->mirror_qsize, bmp_mirrorq_count(&bmpbgp->mirrorq)); + vty_out(vty, " %9zu bytes maximum buffer used\n", bmpbgp->mirror_qsizemax); if (bmpbgp->mirror_qsizelimit != ~0UL) - vty_out(vty, - " %9zu bytes buffer size limit\n", + vty_out(vty, " %9zu bytes buffer size limit\n", bmpbgp->mirror_qsizelimit); vty_out(vty, "\n"); vty_out(vty, " Startup delay : %s", bmpbgp->startup_delay_ms == 0 ? "Immediate\n\n" : ""); if (bmpbgp->startup_delay_ms != 0) - vty_out(vty, "%" PRIu32 "ms\n\n", - bmpbgp->startup_delay_ms); + vty_out(vty, "%" PRIu32 "ms\n\n", bmpbgp->startup_delay_ms); frr_each(bmp_targets, &bmpbgp->targets, bt) { vty_out(vty, " Targets \"%s\":\n", bt->name); @@ -3754,36 +3614,29 @@ static void bmp_show_bmp(struct vty *vty) if (!afimon_flag) continue; - const char *in_pre_str = - CHECK_FLAG(afimon_flag, - BMP_MON_IN_PREPOLICY) - ? "rib-in pre-policy " - : ""; - const char *in_post_str = - CHECK_FLAG(afimon_flag, - BMP_MON_IN_POSTPOLICY) - ? "rib-in post-policy " - : ""; - const char *locrib_str = - CHECK_FLAG(afimon_flag, BMP_MON_LOC_RIB) - ? "loc-rib " - : ""; - const char *out_pre_str = - CHECK_FLAG(afimon_flag, - BMP_MON_OUT_PREPOLICY) - ? "rib-out pre-policy " - : ""; - const char *out_post_str = - CHECK_FLAG(afimon_flag, - BMP_MON_OUT_POSTPOLICY) - ? "rib-out post-policy " - : ""; - - vty_out(vty, - " Route Monitoring %s %s %s%s%s%s%s\n", - afi2str(afi), safi2str(safi), - in_pre_str, in_post_str, locrib_str, - out_pre_str, out_post_str); + const char *in_pre_str = CHECK_FLAG(afimon_flag, + BMP_MON_IN_PREPOLICY) + ? "rib-in pre-policy " + : ""; + const char *in_post_str = CHECK_FLAG(afimon_flag, + BMP_MON_IN_POSTPOLICY) + ? "rib-in post-policy " + : ""; + const char *locrib_str = CHECK_FLAG(afimon_flag, BMP_MON_LOC_RIB) + ? "loc-rib " + : ""; + const char *out_pre_str = CHECK_FLAG(afimon_flag, + BMP_MON_OUT_PREPOLICY) + ? "rib-out pre-policy " + : ""; + const char *out_post_str = CHECK_FLAG(afimon_flag, + BMP_MON_OUT_POSTPOLICY) + ? "rib-out post-policy " + : ""; + + vty_out(vty, " Route Monitoring %s %s %s%s%s%s%s\n", + afi2str(afi), safi2str(safi), in_pre_str, in_post_str, + locrib_str, out_pre_str, out_post_str); } vty_out(vty, " Listeners:\n"); @@ -3840,9 +3693,8 @@ static void bmp_show_bmp(struct vty *vty) vty_out(vty, "\n %zu connected clients:\n", bmp_session_count(&bt->sessions)); tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); - ttable_add_row( - tt, - "remote|uptime|state|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel"); + ttable_add_row(tt, + "remote|uptime|state|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel"); ttable_rowseps(tt, 0, BOTTOM, true, '-'); frr_each (bmp_session, &bt->sessions, bmp) { @@ -3854,12 +3706,10 @@ static void bmp_show_bmp(struct vty *vty) peer_uptime(bmp->t_up.tv_sec, uptime, sizeof(uptime), false, NULL); - ttable_add_row( - tt, "%s|%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu", - bmp->remote, uptime, - bmp_state_str(bmp->state), - bmp->cnt_update, bmp->cnt_mirror, - bmp->cnt_mirror_overruns, total, q, kq); + ttable_add_row(tt, "%s|%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu", bmp->remote, + uptime, bmp_state_str(bmp->state), bmp->cnt_update, + bmp->cnt_mirror, bmp->cnt_mirror_overruns, total, q, + kq); } out = ttable_dump(tt, "\n"); vty_out(vty, "%s", out); @@ -3873,7 +3723,6 @@ static void bmp_show_bmp(struct vty *vty) /* show the bpi locked by bmp with 'show bmp locked' */ static void bmp_show_locked(struct vty *vty) { - vty_out(vty, "BMP: BGP Paths locked for use in the Monitoring\n"); struct bmp_bpi_lock *lbpi_iter; @@ -3893,13 +3742,11 @@ static void bmp_show_locked(struct vty *vty) } vty_out(vty, - " [#%d][lock=%d] %s: bgp id=%" PRId64 - " dest=%pBD rx_id=%" PRIu32 " from peer=%pBP\n", + " [#%d][lock=%d] %s: bgp id=%" PRId64 " dest=%pBD rx_id=%" PRIu32 + " from peer=%pBP\n", n, lbpi_curr->lock, n == 0 ? "head" : "node", - lbpi_curr->bgp ? (int64_t)lbpi_curr->bgp->vrf_id - : -1, - lbpi_curr->locked->net, - lbpi_curr->locked->addpath_rx_id, + lbpi_curr->bgp ? (int64_t)lbpi_curr->bgp->vrf_id : -1, + lbpi_curr->locked->net, lbpi_curr->locked->addpath_rx_id, lbpi_curr->locked->peer); n++; } while ((lbpi_curr = lbpi_curr->next)); @@ -3935,8 +3782,7 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) bmpbgp->mirror_qsizelimit); if (bmpbgp->startup_delay_ms != 0) - vty_out(vty, " !\n bmp startup-delay %" PRIu32 "\n", - bmpbgp->startup_delay_ms); + vty_out(vty, " !\n bmp startup-delay %" PRIu32 "\n", bmpbgp->startup_delay_ms); frr_each(bmp_targets, &bmpbgp->targets, bt) { vty_out(vty, " !\n bmp targets %s\n", bt->name); @@ -3957,28 +3803,20 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) vty_out(vty, " bmp mirror\n"); FOREACH_AFI_SAFI (afi, safi) { - if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_IN_PREPOLICY)) - vty_out(vty, - " bmp monitor %s %s rib-in pre-policy\n", + if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_IN_PREPOLICY)) + vty_out(vty, " bmp monitor %s %s rib-in pre-policy\n", afi2str_lower(afi), safi2str(safi)); - if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_IN_POSTPOLICY)) - vty_out(vty, - " bmp monitor %s %s rib-in post-policy\n", + if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_IN_POSTPOLICY)) + vty_out(vty, " bmp monitor %s %s rib-in 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_lower(afi), safi2str(safi)); - if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_OUT_PREPOLICY)) - vty_out(vty, - " bmp monitor %s %s rib-out pre-policy\n", + if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_OUT_PREPOLICY)) + vty_out(vty, " bmp monitor %s %s rib-out pre-policy\n", afi2str_lower(afi), safi2str(safi)); - if (CHECK_FLAG(bt->afimon[afi][safi], - BMP_MON_OUT_POSTPOLICY)) - vty_out(vty, - " bmp monitor %s %s rib-out post-policy\n", + if (CHECK_FLAG(bt->afimon[afi][safi], BMP_MON_OUT_POSTPOLICY)) + vty_out(vty, " bmp monitor %s %s rib-out post-policy\n", afi2str_lower(afi), safi2str(safi)); } frr_each (bmp_listeners, &bt->listeners, bl) @@ -4088,16 +3926,15 @@ static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi, * best path change */ if (old_route && new_route && old_route != new_route) { - new_head = bmp_process_one( - bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, - afi, safi, bn, old_route->addpath_rx_id, - old_route->peer, BMP_MON_LOC_RIB); + new_head = bmp_process_one(bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, + afi, safi, bn, old_route->addpath_rx_id, + old_route->peer, BMP_MON_LOC_RIB); } - struct bmp_queue_entry *new_item = bmp_process_one( - bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, afi, - safi, bn, updated_route->addpath_rx_id, - updated_route->peer, BMP_MON_LOC_RIB); + struct bmp_queue_entry *new_item = + bmp_process_one(bt, &bt->mon_loc_updhash, &bt->mon_loc_updlist, afi, safi, + bn, updated_route->addpath_rx_id, updated_route->peer, + BMP_MON_LOC_RIB); new_head = !new_head ? new_item : new_head; /* if bmp_process_one returns NULL @@ -4122,13 +3959,10 @@ static int bmp_route_update(struct bgp *bgp, afi_t afi, safi_t safi, * and which will trigger a bmp monitoring message for rib-out pre/post-policy * if either is configured. */ -static int bmp_adj_out_changed(struct update_subgroup *subgrp, - struct bgp_dest *dest, - struct bgp_path_info *locked_path, - uint32_t addpath_id, struct attr *attr, - bool post_policy, bool withdraw) +static int bmp_adj_out_changed(struct update_subgroup *subgrp, struct bgp_dest *dest, + struct bgp_path_info *locked_path, uint32_t addpath_id, + struct attr *attr, bool post_policy, bool withdraw) { - if (!subgrp) return 0; @@ -4136,26 +3970,23 @@ static int bmp_adj_out_changed(struct update_subgroup *subgrp, * if a path is in adj-rib-out pre or not */ if (!post_policy) { - /* because of withdraw we don't have the path right away, * look it up in bmp locked paths */ if (withdraw && !locked_path) { { /* scope lock the vars declared by lookup */ - BMP_LBPI_LOOKUP_DEST( - head, prev, lbpi, dest, - SUBGRP_INST(subgrp), - bgp_addpath_id_for_peer( - SUBGRP_PEER(subgrp), - SUBGRP_AFI(subgrp), - SUBGRP_SAFI(subgrp), - &lbpi->locked->tx_addpath) == - addpath_id); + BMP_LBPI_LOOKUP_DEST(head, prev, lbpi, dest, SUBGRP_INST(subgrp), + bgp_addpath_id_for_peer(SUBGRP_PEER(subgrp), + SUBGRP_AFI(subgrp), + SUBGRP_SAFI(subgrp), + &lbpi->locked + ->tx_addpath) == + addpath_id); if (!lbpi) { - zlog_warn( - "no locked path found for %pBD tx %" PRIu32" in bgp %s", - dest, addpath_id, SUBGRP_INST(subgrp)->name); + zlog_warn("no locked path found for %pBD tx %" PRIu32 + " in bgp %s", + dest, addpath_id, SUBGRP_INST(subgrp)->name); return 0; } @@ -4163,7 +3994,7 @@ static int bmp_adj_out_changed(struct update_subgroup *subgrp, } } - struct attr dummy_attr = {0}; + struct attr dummy_attr = { 0 }; /* run bgp rib-out-pre check * withdraw | pre_check | result @@ -4175,9 +4006,8 @@ static int bmp_adj_out_changed(struct update_subgroup *subgrp, * return early. */ if (locked_path && - !subgroup_announce_check(dest, locked_path, subgrp, - bgp_dest_get_prefix(dest), &dummy_attr, NULL, - BGP_ANNCHK_SPECIAL_PREPOLICY)) { + !subgroup_announce_check(dest, locked_path, subgrp, bgp_dest_get_prefix(dest), + &dummy_attr, NULL, BGP_ANNCHK_SPECIAL_PREPOLICY)) { return 0; } } @@ -4188,8 +4018,7 @@ static int bmp_adj_out_changed(struct update_subgroup *subgrp, afi_t afi = SUBGRP_AFI(subgrp); safi_t safi = SUBGRP_SAFI(subgrp); - uint8_t mon_flag = - post_policy ? BMP_MON_OUT_POSTPOLICY : BMP_MON_OUT_PREPOLICY; + uint8_t mon_flag = post_policy ? BMP_MON_OUT_POSTPOLICY : BMP_MON_OUT_PREPOLICY; struct peer_af *paf; struct peer *peer; @@ -4202,9 +4031,9 @@ static int bmp_adj_out_changed(struct update_subgroup *subgrp, SUBGRP_FOREACH_PEER (subgrp, paf) { peer = PAF_PEER(paf); - struct bmp_queue_entry *new_item = bmp_process_one( - bt, &bt->mon_out_updhash, &bt->mon_out_updlist, - afi, safi, dest, addpath_id, peer, mon_flag); + struct bmp_queue_entry *new_item = + bmp_process_one(bt, &bt->mon_out_updhash, &bt->mon_out_updlist, afi, + safi, dest, addpath_id, peer, mon_flag); /* if bmp_process_one returns NULL * we don't have anything to do next @@ -4236,13 +4065,13 @@ static int bmp_path_unlock(struct bgp *bgp, struct bgp_path_info *path) */ static int bmp_vrf_state_changed(struct bgp *bgp) { - struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp); if (!bmp_bgp_update_vrf_status(bmpbgp, vrf_state_unknown)) return 1; - bmp_send_all_safe(bmpbgp, bmp_peerstate(bgp->peer_self, bmpbgp->vrf_state == vrf_state_down)); + bmp_send_all_safe(bmpbgp, + bmp_peerstate(bgp->peer_self, bmpbgp->vrf_state == vrf_state_down)); return 0; } diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h index fdd5d70d8afe..90f27ea4b19b 100644 --- a/bgpd/bgp_bmp.h +++ b/bgpd/bgp_bmp.h @@ -308,26 +308,24 @@ struct bmp_bpi_lock { }; -#define BMP_LBPI_LOOKUP_DEST(head, prev, lookup, target_dest, target_bgp, \ - condition) \ - struct bmp_bpi_lock _dummy_lbpi = { \ - .dest = (target_dest), \ - .bgp = (target_bgp), \ - }; \ - \ - struct bmp_bpi_lock *(head) = NULL, *(prev) = NULL, *(lookup) = NULL; \ - \ - (head) = bmp_lbpi_h_find(&bmp_lbpi, &_dummy_lbpi); \ - \ - for ((lookup) = (head); (lookup); \ - (lookup) = ((prev) = (lookup))->next) { \ - if ((condition)) \ - break; \ +#define BMP_LBPI_LOOKUP_DEST(head, prev, lookup, target_dest, target_bgp, condition) \ + struct bmp_bpi_lock _dummy_lbpi = { \ + .dest = (target_dest), \ + .bgp = (target_bgp), \ + }; \ +\ + struct bmp_bpi_lock *(head) = NULL, *(prev) = NULL, *(lookup) = NULL; \ +\ + (head) = bmp_lbpi_h_find(&bmp_lbpi, &_dummy_lbpi); \ +\ + for ((lookup) = (head); (lookup); (lookup) = ((prev) = (lookup))->next) { \ + if ((condition)) \ + break; \ } -#define BMP_LBPI_LOOKUP_BPI(head, prev, lookup, target_bpi, target_bgp) \ - BMP_LBPI_LOOKUP_DEST((head), (prev), (lookup), (target_bpi)->net, \ - (target_bgp), ((lookup)->locked == (target_bpi))) +#define BMP_LBPI_LOOKUP_BPI(head, prev, lookup, target_bpi, target_bgp) \ + BMP_LBPI_LOOKUP_DEST((head), (prev), (lookup), (target_bpi)->net, (target_bgp), \ + ((lookup)->locked == (target_bpi))) /* per struct bgp * data */ PREDECL_HASH(bmp_bgph); @@ -371,25 +369,25 @@ enum { }; enum { - BMP_STATS_PFX_REJECTED = 0, - BMP_STATS_PFX_DUP_ADV = 1, - BMP_STATS_PFX_DUP_WITHDRAW = 2, - BMP_STATS_UPD_LOOP_CLUSTER = 3, - BMP_STATS_UPD_LOOP_ASPATH = 4, - BMP_STATS_UPD_LOOP_ORIGINATOR = 5, - BMP_STATS_UPD_LOOP_CONFED = 6, - BMP_STATS_SIZE_ADJ_RIB_IN = 7, - BMP_STATS_SIZE_LOC_RIB = 8, - BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, - BMP_STATS_SIZE_LOC_RIB_SAFI = 10, - BMP_STATS_UPD_7606_WITHDRAW = 11, - BMP_STATS_PFX_7606_WITHDRAW = 12, - BMP_STATS_UPD_DUP = 13, - BMP_STATS_SIZE_ADJ_RIB_OUT_PRE = 14, - BMP_STATS_SIZE_ADJ_RIB_OUT_POST = 15, - BMP_STATS_SIZE_ADJ_RIB_OUT_PRE_SAFI = 16, + BMP_STATS_PFX_REJECTED = 0, + BMP_STATS_PFX_DUP_ADV = 1, + BMP_STATS_PFX_DUP_WITHDRAW = 2, + BMP_STATS_UPD_LOOP_CLUSTER = 3, + BMP_STATS_UPD_LOOP_ASPATH = 4, + BMP_STATS_UPD_LOOP_ORIGINATOR = 5, + BMP_STATS_UPD_LOOP_CONFED = 6, + BMP_STATS_SIZE_ADJ_RIB_IN = 7, + BMP_STATS_SIZE_LOC_RIB = 8, + BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, + BMP_STATS_SIZE_LOC_RIB_SAFI = 10, + BMP_STATS_UPD_7606_WITHDRAW = 11, + BMP_STATS_PFX_7606_WITHDRAW = 12, + BMP_STATS_UPD_DUP = 13, + BMP_STATS_SIZE_ADJ_RIB_OUT_PRE = 14, + BMP_STATS_SIZE_ADJ_RIB_OUT_POST = 15, + BMP_STATS_SIZE_ADJ_RIB_OUT_PRE_SAFI = 16, BMP_STATS_SIZE_ADJ_RIB_OUT_POST_SAFI = 17, - BMP_STATS_FRR_NH_INVALID = 65531, + BMP_STATS_FRR_NH_INVALID = 65531, }; DECLARE_MGROUP(BMP); diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index cd23ba7ddc1b..45be9a115ec5 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -98,22 +98,18 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { advmap_attr = *pi->attr; - bool selected = bgp_check_selected( - pi, peer, addpath_capable, afi, safi); + bool selected = bgp_check_selected(pi, peer, addpath_capable, afi, safi); if (selected) { - bgp_adj_out_updated( - subgrp, dest, pi, - !addpath_capable - ? 0 - : bgp_addpath_id_for_peer(peer, - afi, - safi, - &pi->tx_addpath), - &attr, false, - update_type == UPDATE_TYPE_ADVERTISE - ? false - : true); + bgp_adj_out_updated(subgrp, dest, pi, + !addpath_capable + ? 0 + : bgp_addpath_id_for_peer(peer, afi, + safi, + &pi->tx_addpath), + &attr, false, + update_type == UPDATE_TYPE_ADVERTISE ? false + : true); } @@ -137,8 +133,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, * be advertised as expected. */ if (update_type == UPDATE_TYPE_ADVERTISE && - subgroup_announce_check(dest, pi, subgrp, dest_p, - &attr, &advmap_attr, 0)) { + subgroup_announce_check(dest, pi, subgrp, dest_p, &attr, &advmap_attr, + 0)) { if (!bgp_adj_out_set_subgroup(dest, subgrp, &attr, pi)) bgp_attr_flush(&attr); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 0d797fdf9ec7..47518af9fee6 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1469,8 +1469,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, } /* Compute the best path. */ - bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi, NULL); + bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi, NULL); old_select = old_and_new.old; new_select = old_and_new.new; diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 96bfb5ee2111..b2921f9b29d7 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -106,8 +106,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, SET_FLAG(pi->flags, BGP_PATH_UNSORTED); /* Compute the best path. */ - bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi, NULL); + bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi, NULL); old_select = old_and_new.old; new_select = old_and_new.new; diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 8002b1dad5c7..87c139269131 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -410,8 +410,7 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, mpath->mp_attr = attr; } -void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, - struct bgp_path_info *bpi, bool update) +void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, struct bgp_path_info *bpi, bool update) { if (!diff) return; @@ -420,8 +419,8 @@ void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, return; } - struct bgp_path_info_mpath_diff *item = XCALLOC( - MTYPE_BGP_MPATH_DIFF, sizeof(struct bgp_path_info_mpath_diff)); + struct bgp_path_info_mpath_diff *item = XCALLOC(MTYPE_BGP_MPATH_DIFF, + sizeof(struct bgp_path_info_mpath_diff)); item->path = bpi; item->update = update; diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index f4f9f7b05e64..6750a8b9e692 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -46,8 +46,8 @@ struct bgp_path_info_mpath_diff { DECLARE_LIST(bgp_mpath_diff, struct bgp_path_info_mpath_diff, next); -extern void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, - struct bgp_path_info *bpi, bool update); +extern void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, struct bgp_path_info *bpi, + bool update); extern void bgp_mpath_diff_clear(struct bgp_mpath_diff_head *diff); diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 2f2138592ec2..939b40951be8 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1791,14 +1791,14 @@ static int bgp_open_receive(struct peer_connection *connection, uint16_t optlen; uint16_t holdtime; uint16_t send_holdtime; - as_t remote_as; - as_t as4 = 0, as4_be; struct in_addr remote_id; int mp_capability; uint8_t notify_data_remote_as[2]; uint8_t notify_data_remote_as4[4]; uint8_t notify_data_remote_id[4]; uint16_t *holdtime_ptr; + as_t remote_as; + as_t as4 = 0, as4_be; /* Parse open packet. */ version = stream_getc(peer->curr); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 254560dfebed..cf53d661cc0d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -92,8 +92,7 @@ DEFINE_HOOK(bgp_route_update, struct bgp_path_info *old_route, struct bgp_path_info *new_route), (bgp, afi, safi, bn, old_route, new_route)); -DEFINE_HOOK(bgp_process_main_one_end, - (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); +DEFINE_HOOK(bgp_process_main_one_end, (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -158,12 +157,11 @@ static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi, } DEFINE_HOOK(bgp_process, - (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, - uint32_t addpath_id, struct peer *peer, bool post), + (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, uint32_t addpath_id, + struct peer *peer, bool post), (bgp, afi, safi, bn, addpath_id, peer, post)); -DEFINE_HOOK(bgp_process_main_one, - (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), +DEFINE_HOOK(bgp_process_main_one, (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), (bgp, afi, safi, dest)); /** Test if path is suppressed. */ @@ -2135,9 +2133,8 @@ void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr) } bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, - struct update_subgroup *subgrp, - const struct prefix *p, struct attr *attr, - struct attr *post_attr, uint8_t special_cond) + struct update_subgroup *subgrp, const struct prefix *p, + struct attr *attr, struct attr *post_attr, uint8_t special_cond) { struct bgp_filter *filter; struct peer *from; @@ -2172,10 +2169,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr; /* special conditions for bmp rib-out pre-policy check */ - bool ignore_policy = - CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY); - bool ignore_path_status = - CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS); + bool ignore_policy = CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY); + bool ignore_path_status = CHECK_FLAG(special_cond, BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS); if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) && @@ -2217,9 +2212,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, /* With addpath we may be asked to TX all kinds of paths so make sure * pi is valid */ - if (!ignore_path_status && (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || - CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) || - CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))) { + if (!ignore_path_status && + (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) || + CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))) { return false; } @@ -2231,8 +2226,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, return false; /* Aggregate-address suppress check. */ - if (!ignore_policy && bgp_path_suppressed(pi) && - !UNSUPPRESS_MAP_NAME(filter)) + if (!ignore_policy && bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter)) return false; /* @@ -2321,8 +2315,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* ORF prefix-list filter check */ - if (!ignore_policy && - CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && + if (!ignore_policy && CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)) if (peer->orf_plist[afi][safi]) { if (prefix_list_apply(peer->orf_plist[afi][safi], p) @@ -2337,8 +2330,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* Output filter check. */ - if (!ignore_policy && - bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) { + if (!ignore_policy && bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer, p); @@ -2515,10 +2507,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); bgp_peer_as_override(bgp, afi, safi, peer, attr); - if (!ignore_policy && - filter->advmap.update_type == UPDATE_TYPE_WITHDRAW && - filter->advmap.aname && - route_map_lookup_by_name(filter->advmap.aname)) { + if (!ignore_policy && filter->advmap.update_type == UPDATE_TYPE_WITHDRAW && + filter->advmap.aname && route_map_lookup_by_name(filter->advmap.aname)) { struct bgp_path_info rmap_path = {0}; struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct attr dummy_attr = *attr; @@ -2543,8 +2533,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, } /* Route map & unsuppress-map apply. */ - if (!ignore_policy && !post_attr && - (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) { + if (!ignore_policy && !post_attr && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) { struct bgp_path_info rmap_path = {0}; struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct attr dummy_attr = {0}; @@ -2915,10 +2904,8 @@ static void bgp_route_select_timer_expire(struct event *thread) bgp_best_path_select_defer(bgp, afi, safi); } -void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, - struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_path_info_pair *result, afi_t afi, - safi_t safi, +void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_path_info_pair *result, afi_t afi, safi_t safi, struct bgp_mpath_diff_head *mpath_diff_list) { struct bgp_path_info *new_select, *look_thru; @@ -3347,7 +3334,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, } } - bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg, mpath_diff_list); + bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg, + mpath_diff_list); bgp_path_info_mpath_aggregate_update(new_select, old_select); bgp_addpath_update_ids(bgp, dest, afi, safi); @@ -3400,8 +3388,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, selected && advertise ? false : true); if (selected) { - if (subgroup_announce_check(dest, selected, subgrp, p, pattr, - NULL, 0)) { + if (subgroup_announce_check(dest, selected, subgrp, p, pattr, NULL, 0)) { /* Route is selected, if the route is already installed * in FIB, then it is advertised */ @@ -3765,8 +3752,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, bgp_mpath_diff_init(&mpath_diff); /* Best path selection. */ - bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, - afi, safi, &mpath_diff); + bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi, + &mpath_diff); old_select = old_and_new.old; new_select = old_and_new.new; @@ -3799,28 +3786,23 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, if (old_select) bgp_path_info_lock(old_select); - hook_call(bgp_route_update, bgp, afi, safi, dest, old_select, - new_select); + hook_call(bgp_route_update, bgp, afi, safi, dest, old_select, new_select); } if (debug) - zlog_debug("%s: multipath diff %p computed, mpath_changed=%d", - __func__, &mpath_diff, - (int)bgp_mpath_diff_count(&mpath_diff)); + zlog_debug("%s: multipath diff %p computed, mpath_changed=%d", __func__, + &mpath_diff, (int)bgp_mpath_diff_count(&mpath_diff)); frr_each (bgp_mpath_diff, &mpath_diff, diff) { if (diff->path) { if (debug) - zlog_debug( - "[%s] bpi: %p, dest=%pBD peer=%pBP, rx_id=%" PRIu32, - diff->update ? "+" : "-", diff->path, - diff->path->net, diff->path->peer, - diff->path->addpath_rx_id); + zlog_debug("[%s] bpi: %p, dest=%pBD peer=%pBP, rx_id=%" PRIu32, + diff->update ? "+" : "-", diff->path, diff->path->net, + diff->path->peer, diff->path->addpath_rx_id); - hook_call(bgp_route_update, bgp, afi, safi, dest, - diff->path, diff->update ? diff->path : NULL); + hook_call(bgp_route_update, bgp, afi, safi, dest, diff->path, + diff->update ? diff->path : NULL); } else if (debug) - zlog_debug("[%s] diff: %p no path", - diff->update ? "+" : "-", diff); + zlog_debug("[%s] diff: %p no path", diff->update ? "+" : "-", diff); } /* If best route remains the same and this is not due to user-initiated @@ -4462,8 +4444,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi, } } - hook_call(bgp_process, peer->bgp, afi, safi, dest, - pi ? pi->addpath_rx_id : 0, peer, true); + hook_call(bgp_process, peer->bgp, afi, safi, dest, pi ? pi->addpath_rx_id : 0, peer, true); bgp_process(peer->bgp, dest, pi, afi, safi); } @@ -5107,8 +5088,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, pi->uptime = monotime(NULL); same_attr = attrhash_cmp(pi->attr, attr_new); - hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, - true); + hook_call(bgp_process, bgp, afi, safi, dest, addpath_id, peer, true); /* Same attribute comes in. */ if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr && @@ -5610,8 +5590,8 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, * and * if there was no entry, we don't need to do anything more. */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) - && peer != bgp->peer_self) { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) && + peer != bgp->peer_self) { if (!bgp_adj_in_unset(&dest, afi, safi, peer, addpath_id)) { assert(dest); peer->stat_pfx_dup_withdraw++; @@ -5629,8 +5609,7 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, return; } - hook_call(bgp_process, peer->bgp, afi, safi, dest, addpath_id, - peer, false); + hook_call(bgp_process, peer->bgp, afi, safi, dest, addpath_id, peer, false); } /* Lookup withdrawn route. */ diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index f976a00e0437..80bf6adc3f06 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -331,8 +331,8 @@ struct bgp_path_info { #define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17) #define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18) #define BGP_PATH_UNSORTED (1 << 19) -#define BGP_PATH_BMP_LOCKED (1 << 20) -#define BGP_PATH_BMP_ADJIN_CHG (1 << 21) +#define BGP_PATH_BMP_LOCKED (1 << 20) +#define BGP_PATH_BMP_ADJIN_CHG (1 << 21) /* * BGP_PATH_MULTIPATH_NEW is set on those bgp_path_info * nodes that we have decided should possibly be in the @@ -702,13 +702,12 @@ static inline bool bgp_check_withdrawal(struct bgp *bgp, struct bgp_dest *dest, /* called before bgp_process() */ DECLARE_HOOK(bgp_process, - (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, - uint32_t addpath_id, struct peer *peer, bool post), + (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, uint32_t addpath_id, + struct peer *peer, bool post), (bgp, afi, safi, bn, addpath_id, peer, post)); /* called before bgp_process() */ -DECLARE_HOOK(bgp_process_main_one, - (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), +DECLARE_HOOK(bgp_process_main_one, (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *dest), (bgp, afi, safi, dest)); /* called when a route is updated in the rib */ @@ -718,8 +717,7 @@ DECLARE_HOOK(bgp_route_update, (bgp, afi, safi, bn, old_route, new_route)); -DECLARE_HOOK(bgp_process_main_one_end, - (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); +DECLARE_HOOK(bgp_process_main_one_end, (struct bgp *bgp, struct bgp_path_info *path), (bgp, path)); /* BGP show options */ #define BGP_SHOW_OPT_JSON (1 << 0) @@ -906,17 +904,13 @@ extern void subgroup_process_announce_selected(struct update_subgroup *subgrp, uint32_t addpath_tx_id); /* used by bmp to ignore certain conditions in rib-out pre-policy check */ -#define BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY (1 << 0) +#define BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY (1 << 0) #define BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS (1 << 1) -#define BGP_ANNCHK_SPECIAL_PREPOLICY \ - (BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY | \ - BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS) -extern bool subgroup_announce_check(struct bgp_dest *dest, - struct bgp_path_info *pi, - struct update_subgroup *subgrp, - const struct prefix *p, struct attr *attr, - struct attr *post_attr, - uint8_t special_cond); +#define BGP_ANNCHK_SPECIAL_PREPOLICY \ + (BGP_ANNCHK_SPECIAL_IGNORE_OUT_POLICY | BGP_ANNCHK_SPECIAL_IGNORE_PATH_STATUS) +extern bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, + struct update_subgroup *subgrp, const struct prefix *p, + struct attr *attr, struct attr *post_attr, uint8_t special_cond); extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer); extern void bgp_process_queues_drain_immediate(void); @@ -938,10 +932,8 @@ extern void bgp_attr_add_llgr_community(struct attr *attr); extern void bgp_attr_add_gshut_community(struct attr *attr); extern void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, - struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_path_info_pair *result, afi_t afi, - safi_t safi, - struct bgp_mpath_diff_head *mpath_diff_list); + struct bgp_maxpaths_cfg *mpath_cfg, struct bgp_path_info_pair *result, + afi_t afi, safi_t safi, struct bgp_mpath_diff_head *mpath_diff_list); extern void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest); extern bool bgp_zebra_has_route_changed(struct bgp_path_info *selected); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index 537fe87d1ed5..ca4ed8a39c85 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -58,9 +58,8 @@ PEER_CAP_ADDPATH_AF_RX_RCV | PEER_CAP_ENHE_AF_NEGO) DECLARE_HOOK(bgp_adj_out_updated, - (struct update_subgroup *subgrp, struct bgp_dest *dest, - struct bgp_path_info *path, uint32_t addpath_id, - struct attr *attr, bool post_policy, bool withdraw), + (struct update_subgroup *subgrp, struct bgp_dest *dest, struct bgp_path_info *path, + uint32_t addpath_id, struct attr *attr, bool post_policy, bool withdraw), (subgrp, dest, path, addpath_id, attr, post_policy, withdraw)); enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX }; @@ -450,16 +449,13 @@ extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, struct attr *attr, struct bgp_path_info *path); -extern void bgp_adj_out_updated(struct update_subgroup *subgrp, - struct bgp_dest *dest, - struct bgp_path_info *path, uint32_t addpath_tx, - struct attr *attr, bool post_policy, - bool withdraw); +extern void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest, + struct bgp_path_info *path, uint32_t addpath_tx, struct attr *attr, + bool post_policy, bool withdraw); extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, struct update_subgroup *subgrp, char withdraw, uint32_t addpath_tx_id); -extern struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, - struct update_subgroup *subgrp, +extern struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, struct update_subgroup *subgrp, uint32_t addpath_tx_id); void subgroup_announce_table(struct update_subgroup *subgrp, struct bgp_table *table); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 587fa06f8fd0..62ea026043b8 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -37,9 +37,8 @@ #include "bgpd/bgp_addpath.h" DEFINE_HOOK(bgp_adj_out_updated, - (struct update_subgroup *subgrp, struct bgp_dest *dest, - struct bgp_path_info *path, uint32_t addpath_id, struct attr *attr, - bool post_policy, bool withdraw), + (struct update_subgroup *subgrp, struct bgp_dest *dest, struct bgp_path_info *path, + uint32_t addpath_id, struct attr *attr, bool post_policy, bool withdraw), (subgrp, dest, path, addpath_id, attr, post_policy, withdraw)); /******************** @@ -64,8 +63,7 @@ static int bgp_adj_out_compare(const struct bgp_adj_out *o1, } RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare); -inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, - struct update_subgroup *subgrp, +inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest, struct update_subgroup *subgrp, uint32_t addpath_tx_id) { struct bgp_adj_out lookup; @@ -285,11 +283,8 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) } if (!adj) - bgp_adj_out_updated(subgrp, - ctx->dest, - NULL, 0, - NULL, false, - true); + bgp_adj_out_updated(subgrp, ctx->dest, NULL, 0, + NULL, false, true); } } } @@ -537,16 +532,15 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, /* call the bgp_adj_out_updated hook for bmp rib-out monitoring */ void bgp_adj_out_updated(struct update_subgroup *subgrp, struct bgp_dest *dest, - struct bgp_path_info *path, uint32_t addpath_tx, - struct attr *attr, bool post_policy, bool withdraw) + struct bgp_path_info *path, uint32_t addpath_tx, struct attr *attr, + bool post_policy, bool withdraw) { if (path && !withdraw && CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) { /* path is removed, enforcing withdraw state */ withdraw = true; } - hook_call(bgp_adj_out_updated, subgrp, dest, path, addpath_tx, attr, - post_policy, withdraw); + hook_call(bgp_adj_out_updated, subgrp, dest, path, addpath_tx, attr, post_policy, withdraw); } bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, @@ -681,8 +675,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, subgrp->version = MAX(subgrp->version, dest->version); - bgp_adj_out_updated(subgrp, dest, path, adj->addpath_tx_id, attr, true, - false); + bgp_adj_out_updated(subgrp, dest, path, adj->addpath_tx_id, attr, true, false); return true; } @@ -734,8 +727,7 @@ void bgp_adj_out_unset_subgroup(struct bgp_dest *dest, if (trigger_write) subgroup_trigger_write(subgrp); - bgp_adj_out_updated(subgrp, dest, NULL, - adj->addpath_tx_id, NULL, true, + bgp_adj_out_updated(subgrp, dest, NULL, adj->addpath_tx_id, NULL, true, withdraw); } else { /* Free allocated information. */ @@ -1044,9 +1036,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw) continue; if (subgroup_announce_check(dest, pi, subgrp, - bgp_dest_get_prefix( - dest), - &attr, NULL, 0)) { + bgp_dest_get_prefix(dest), &attr, NULL, + 0)) { if (!bgp_adj_out_set_subgroup(dest, subgrp, &attr, pi)) diff --git a/lib/pullwr.c b/lib/pullwr.c index 76c57a34f5de..73afe7290553 100644 --- a/lib/pullwr.c +++ b/lib/pullwr.c @@ -93,8 +93,7 @@ void pullwr_timeout(struct pullwr *pullwr, uint32_t timeout) if (pullwr->writer) return; - event_add_timer_msec(pullwr->tm, pullwr_run, pullwr, timeout, - &pullwr->writer); + event_add_timer_msec(pullwr->tm, pullwr_run, pullwr, timeout, &pullwr->writer); } static size_t pullwr_iov(struct pullwr *pullwr, struct iovec *iov) diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py index 8fb45a274d56..e94d505f217f 100644 --- a/tests/topotests/bgp_bmp/test_bgp_bmp.py +++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py @@ -391,7 +391,13 @@ def _test_prefixes(policy, vrf=None, step=0, prefixes=TEST_PREFIXES): update_seq() configure_prefixes( - tgen, "r2", 65502, "unicast", prefixes, vrf=vrf, update=(type == BMP_UPDATE) + tgen, + "r2", + 65502, + "unicast", + prefixes, + vrf=vrf, + update=(type == BMP_UPDATE), ) logger.info(f"checking for prefixes {type}") diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py index 618173c9093b..00da0c922a2f 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py @@ -134,6 +134,7 @@ def detect_addpath_prefix_ipv46(data, max_bit_length): # we don't know if it's add-path so let's say no return False + class NlriIPv6Unicast: @staticmethod def parse(data): From 9d795cb32abaf876b1a428e53ad8f509068d97a0 Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Sun, 3 Nov 2024 11:42:30 +0100 Subject: [PATCH 07/11] bgpd: fix NPE in bgp_mpath_diff_insert Signed-off-by: Maxence Younsi --- bgpd/bgp_mpath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 87c139269131..0c8473325c8b 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -425,7 +425,8 @@ void bgp_mpath_diff_insert(struct bgp_mpath_diff_head *diff, struct bgp_path_inf item->update = update; bgp_path_info_lock(bpi); - bgp_dest_lock_node(bpi->net); + if (bpi->net) + bgp_dest_lock_node(bpi->net); bgp_mpath_diff_add_tail(diff, item); } From 72bc8d1203fb8d3bdbc113c81cb3a8859fa6233a Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Sun, 3 Nov 2024 15:29:56 +0100 Subject: [PATCH 08/11] bgpd: safer bmp_send_peerup_vrf and bmp_vrf_itf_state_changed check for null stream in bmp_send_peerup_vrf (which can happen when RD is not found) use bmp_send_all_safe instead of bmp_send_all in bmp_vrf_itf_state_changed Signed-off-by: Maxence Younsi --- bgpd/bgp_bmp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 2a33e2392df1..ed9e1fc21241 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -849,8 +849,10 @@ static int bmp_send_peerup_vrf(struct bmp *bmp) s = bmp_peerstate(bmpbgp->bgp->peer_self, bmpbgp->vrf_state == vrf_state_down); - pullwr_write_stream(bmp->pullwr, s); - stream_free(s); + if (s) { + pullwr_write_stream(bmp->pullwr, s); + stream_free(s); + } return 0; } @@ -4093,7 +4095,7 @@ static int bmp_vrf_itf_state_changed(struct bgp *bgp, struct interface *itf) bmpbgp = bmp_bgp_find(bgp); new_state = if_is_up(itf) ? vrf_state_up : vrf_state_down; if (bmp_bgp_update_vrf_status(bmpbgp, new_state)) - bmp_send_all(bmpbgp, bmp_peerstate(bgp->peer_self, new_state == vrf_state_down)); + bmp_send_all_safe(bmpbgp, bmp_peerstate(bgp->peer_self, new_state == vrf_state_down)); return 0; } From f45cb25d09b7c6bec5ebe2994a90d50aa843b1fe Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Sun, 3 Nov 2024 16:02:29 +0100 Subject: [PATCH 09/11] bgpd: cleanup bmp rd lookup Signed-off-by: Maxence Younsi --- bgpd/bgp_bmp.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index ed9e1fc21241..d2e6816e61eb 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -485,16 +485,12 @@ static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, uint64_ /* afi not known, use any afi configured in this vrf */ if (afi == AFI_UNSPEC) { - { /* scope lock iter variables */ - afi_t afi_rd_lookup; - - for (afi_rd_lookup = AFI_IP; afi_rd_lookup < AFI_MAX; afi_rd_lookup++) { - if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup].flags, - BGP_VPN_POLICY_TOVPN_RD_SET)) { - afi = afi_rd_lookup; - /* we found an AFI with a RD set */ - break; - } + for (afi_t afi_rd_lookup = AFI_IP; afi_rd_lookup < AFI_MAX; afi_rd_lookup++) { + if (CHECK_FLAG(bgp->vpn_policy[afi_rd_lookup].flags, + BGP_VPN_POLICY_TOVPN_RD_SET)) { + afi = afi_rd_lookup; + /* we found an AFI with a RD set */ + break; } } From 706e774fc7feec7ff903b904b324a94ae92db2ea Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Tue, 5 Nov 2024 10:49:39 +0100 Subject: [PATCH 10/11] bgpd: update bmp bgp labels Signed-off-by: Maxence Younsi --- bgpd/bgp_bmp.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index d2e6816e61eb..9357518471c3 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -1410,6 +1410,7 @@ static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, vo struct peer_af *paf; uint32_t addpath_tx_id; struct bgp_path_info *bpi = ctx->bpi; + uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { struct attr dummy_attr = { 0 }; @@ -1429,8 +1430,8 @@ static int bmp_monitor_rib_out_pre_updgrp_walkcb(struct update_group *updgrp, vo bmp_get_peer_type(PAF_PEER(paf)), bgp_dest_get_prefix(ctx->dest), ctx->prd, ctx->attr, SUBGRP_AFI(subgrp), SUBGRP_SAFI(subgrp), addpath_tx_id, - (time_t)(-1L), bpi && bpi->extra ? bpi->extra->labels->label : NULL, - bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); + (time_t)(-1L), bpi_num_labels ? bpi->extra->labels->label : NULL, + bpi_num_labels); *ctx->written_ref = true; } @@ -1482,6 +1483,7 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, v struct attr *advertised_attr; uint32_t addpath_tx_id; struct bgp_path_info *bpi = ctx->bpi; + uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) { addpath_tx_id = @@ -1503,8 +1505,8 @@ static int bmp_monitor_rib_out_post_updgrp_walkcb(struct update_group *updgrp, v bmp_get_peer_type(PAF_PEER(paf)), ctx->pfx, ctx->prd, advertised_attr, SUBGRP_AFI(subgrp), SUBGRP_SAFI(subgrp), addpath_tx_id, (time_t)(-1L), - bpi && bpi->extra ? bpi->extra->labels->label : NULL, - bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); + bpi_num_labels ? bpi->extra->labels->label : NULL, + bpi_num_labels); *ctx->written_ref = true; } @@ -1901,8 +1903,8 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* retrieve info about the selected path */ - bool is_vpn = (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN) || - (bqe->safi == SAFI_MPLS_VPN); + bool is_vpn = (afi == AFI_L2VPN && safi == SAFI_EVPN) || + (safi == SAFI_MPLS_VPN); struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL; @@ -1915,13 +1917,15 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) if (bpi->peer != peer || bpi->addpath_rx_id != addpath_rx_id) continue; + uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); + /* rib-in post-policy configured and path is valid */ if (CHECK_FLAG(flags, BMP_MON_IN_POSTPOLICY) && CHECK_FLAG(bpi->flags, BGP_PATH_VALID)) { bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, bmp_get_peer_type(peer), &bqe->p, prd, bpi->attr, afi, safi, addpath_rx_id, bpi->uptime, - bpi && bpi->extra ? bpi->extra->labels->label : NULL, - bpi && bpi->extra ? bpi->extra->labels->num_labels : 0); + bpi_num_labels ? bpi->extra->labels->label : NULL, + bpi_num_labels); ribin = bpi; written = true; } @@ -1929,7 +1933,6 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* loc-rib configured and path is selected */ if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) { - uint8_t bpi_num_labels = BGP_PATH_INFO_NUM_LABELS(bpi); bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, bpi->attr, afi, safi, addpath_rx_id, From f49f7cfe217ab163ace2c64b3e0374ee6c5da516 Mon Sep 17 00:00:00 2001 From: Maxence Younsi Date: Tue, 5 Nov 2024 11:57:15 +0100 Subject: [PATCH 11/11] bgpd: apply frrbot Signed-off-by: Maxence Younsi --- bgpd/bgp_bmp.c | 7 ++-- tests/topotests/bgp_bmp/test_bgp_bmp.py | 51 +++++++++++++------------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 9357518471c3..883de2592452 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -1903,8 +1903,7 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* retrieve info about the selected path */ - bool is_vpn = (afi == AFI_L2VPN && safi == SAFI_EVPN) || - (safi == SAFI_MPLS_VPN); + bool is_vpn = (afi == AFI_L2VPN && safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN); struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL; @@ -1933,7 +1932,6 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr) /* loc-rib configured and path is selected */ if (CHECK_FLAG(flags, BMP_MON_LOC_RIB) && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED | BGP_PATH_MULTIPATH)) { - bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd, bpi->attr, afi, safi, addpath_rx_id, bpi->extra ? bpi->extra->bgp_rib_uptime : (time_t)(-1L), @@ -4094,7 +4092,8 @@ static int bmp_vrf_itf_state_changed(struct bgp *bgp, struct interface *itf) bmpbgp = bmp_bgp_find(bgp); new_state = if_is_up(itf) ? vrf_state_up : vrf_state_down; if (bmp_bgp_update_vrf_status(bmpbgp, new_state)) - bmp_send_all_safe(bmpbgp, bmp_peerstate(bgp->peer_self, new_state == vrf_state_down)); + bmp_send_all_safe(bmpbgp, + bmp_peerstate(bgp->peer_self, new_state == vrf_state_down)); return 0; } diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py index e94d505f217f..fc45d6b62f2b 100644 --- a/tests/topotests/bgp_bmp/test_bgp_bmp.py +++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py @@ -189,7 +189,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s # ls /tmp/show*json | while read file; do egrep -v 'prefix|network|metric|ocPrf|version|weight|peerId|vrf|Version|valid|Reason|fe80' $file >$(basename $file); echo >> $(basename $file); done with open( - f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w" + f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w" ) as json_file: json.dump(filtered_out, json_file, indent=4) @@ -215,7 +215,7 @@ def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, s continue filtered_out["routes"]["routeDistinguishers"][rd][pfx] = None with open( - f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w" + f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w" ) as json_file: json.dump(filtered_out, json_file, indent=4) @@ -285,11 +285,11 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): actual = {} for m in messages: if ( - "bmp_log_type" in m.keys() - and "ip_prefix" in m.keys() - and m["ip_prefix"] in expected_prefixes - and m["bmp_log_type"] == bmp_log_type - and m["policy"] == policy + "bmp_log_type" in m.keys() + and "ip_prefix" in m.keys() + and m["ip_prefix"] in expected_prefixes + and m["bmp_log_type"] == bmp_log_type + and m["policy"] == policy ): policy_dict = actual.setdefault(m["policy"], {}) bmp_log_type_dict = policy_dict.setdefault(m["bmp_log_type"], {}) @@ -300,18 +300,18 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): for k, v in sorted(m.items()) # filter out variable keys if k not in ["timestamp", "seq", "nxhp_link-local"] - and ( - # When policy is loc-rib, the peer-distinguisher is 0:0 - # for the default VRF or the RD if any or the 0:. - # 0: is used to distinguished. RFC7854 says: "If the - # peer is a "Local Instance Peer", it is set to a unique, - # locally defined value." The value is not tested because it - # is variable. - k != "peer_distinguisher" - or policy != LOC_RIB - or v == "0:0" - or not v.startswith("0:") - ) + and ( + # When policy is loc-rib, the peer-distinguisher is 0:0 + # for the default VRF or the RD if any or the 0:. + # 0: is used to distinguished. RFC7854 says: "If the + # peer is a "Local Instance Peer", it is set to a unique, + # locally defined value." The value is not tested because it + # is variable. + k != "peer_distinguisher" + or policy != LOC_RIB + or v == "0:0" + or not v.startswith("0:") + ) } logger.debug(f"messages = {messages}") @@ -319,10 +319,10 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step): # build expected JSON files if ( - UPDATE_EXPECTED_JSON - and actual - and set(actual.get(policy, {}).get(bmp_log_type, {}).keys()) - == set(expected_prefixes) + UPDATE_EXPECTED_JSON + and actual + and set(actual.get(policy, {}).get(bmp_log_type, {}).keys()) + == set(expected_prefixes) ): update_expected_files(actual, expected_prefixes, bmp_log_type, policy, step) @@ -373,7 +373,9 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True): "{}network {}\n".format(withdraw, ip), "exit-address-family\n", ] - logger.debug("[{}] setting prefix: ipv{} {} {}".format(node, ip.version, safi, ip)) + logger.debug( + "[{}] setting prefix: ipv{} {} {}".format(node, ip.version, safi, ip) + ) tgen.gears[node].vtysh_cmd("".join(cmd)) @@ -486,7 +488,6 @@ def test_bmp_bgp_vpn(): _test_prefixes(LOC_RIB, vrf="vrf1", step=2) - def multipath_unicast_prefixes(policy, step, vrf=None): """ Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.