]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: bmp, add peer distinguisher support for peer up/down
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 30 Oct 2024 20:57:35 +0000 (21:57 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 11 Dec 2024 10:29:37 +0000 (11:29 +0100)
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>
bgpd/bgp_bmp.c

index 56d4c55246bf6aa1d7d98b1f02768f6ae5f7dfbe..fbd6e8a1d14499646b62a4a4c08d59a39fb6c491 100644 (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;