bgpd: bmp, add peer distinguisher support for peer up/down

All BMP peer up/down messages send a 0:0 peer distinguisher.
This will not be ok when adding RD instance type.

Add code to get the peer distinguisher value.
- modify the API to pass the BGP instance instead of BMP.
- implement error cases with an unknown vrf identifier or a
peer type with local type value.
- handle the error return of the API; consequently, handle
the bmp_peerstate() error return in the calling functions.

There is no functional change, as the peer type value is
either loc-rib or global, both cases are already handled.

The next commit will handle the RD instance case.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2024-10-30 21:57:35 +01:00
parent b7059a8fd9
commit 3c68228a05

View File

@ -275,13 +275,16 @@ static inline int bmp_get_peer_type(struct peer *peer)
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,
static inline int bmp_get_peer_distinguisher(struct bgp *bgp, afi_t afi, uint8_t peer_type,
uint64_t *result_ref)
{
/* use RD if set in VRF config */
struct prefix_rd *prd;
/* sending vrf_id or rd could be turned into an option at some point */
if (peer_type == BMP_PEER_TYPE_LOCAL_INSTANCE || bgp->vrf_id == VRF_UNKNOWN)
return 1;
/* 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
@ -289,9 +292,6 @@ static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi,
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);
@ -310,10 +310,6 @@ static inline int bmp_get_peer_distinguisher(struct bmp *bmp, afi_t afi,
return 0;
}
/* VRF has no id => error => message should be skipped */
if (bgp->vrf_id == VRF_UNKNOWN)
return 1;
/* use VRF id converted to ::vrf_id 64bits format */
*result_ref = ((uint64_t)htonl(bgp->vrf_id)) << 32;
return 0;
@ -476,6 +472,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
struct timeval uptime, uptime_real;
uint8_t peer_type;
bool is_locrib = false;
uint64_t peer_distinguisher = 0;
uptime.tv_sec = peer->uptime;
uptime.tv_usec = 0;
@ -491,6 +488,12 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
if (is_locrib == false)
peer_type = BMP_PEER_TYPE_GLOBAL_INSTANCE;
if (bmp_get_peer_distinguisher(peer->bgp, AFI_UNSPEC, peer_type, &peer_distinguisher)) {
zlog_warn("skipping bmp message for peer %s: can't get peer distinguisher",
peer->host);
return NULL;
}
#define BGP_BMP_MAX_PACKET_SIZE 1024
#define BMP_PEERUP_INFO_TYPE_STRING 0
s = stream_new(BGP_MAX_PACKET_SIZE);
@ -616,8 +619,10 @@ 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);
pullwr_write_stream(bmp->pullwr, s);
stream_free(s);
if (s) {
pullwr_write_stream(bmp->pullwr, s);
stream_free(s);
}
}
return 0;
@ -634,10 +639,10 @@ static int bmp_send_peerup_vrf(struct bmp *bmp)
bmp_bgp_update_vrf_status(bmpbgp, vrf_state_unknown);
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;
}
@ -648,6 +653,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);
@ -656,6 +664,9 @@ static void bmp_send_all(struct bmp_bgp *bmpbgp, struct stream *s)
static void bmp_send_all_safe(struct bmp_bgp *bmpbgp, struct stream *s)
{
if (!s)
return;
if (!bmpbgp) {
stream_free(s);
return;
@ -979,8 +990,7 @@ 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)) {
if (bmp_get_peer_distinguisher(peer->bgp, afi, peer_type_flag, &peer_distinguisher)) {
zlog_warn(
"skipping bmp message for reason: can't get peer distinguisher");
continue;
@ -1108,8 +1118,7 @@ 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)) {
if (bmp_get_peer_distinguisher(peer->bgp, afi, peer_type_flag, &peer_distinguisher)) {
zlog_warn(
"skipping bmp message for reason: can't get peer distinguisher");
return;