]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bfdd: add bfdname in bfd_key
authorwumu.zsl <wumu.zsl@alibaba-inc.com>
Mon, 20 Jan 2025 13:48:38 +0000 (13:48 +0000)
committerwumu.zsl <wumu.zsl@alibaba-inc.com>
Wed, 22 Jan 2025 15:00:24 +0000 (15:00 +0000)
sbfd will use bfdname for key hash, We introduced a bfd-name for every sbfd session, normal BFD sessions can leave it as NULL.
A unique bfd-name can be used to identify a sbfd session quickly. This is quite useful in our Srv6 deployment for path protection case.
For example, if use the sbfd session to protect the SRv6 path A-B-D, we would assign the name 'path-a-b-d' or 'a-b-d' to the session.

Signed-off-by: wumu.zsl <wumu.zsl@alibaba-inc.com>
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfdd_nb_config.c
bfdd/bfdd_nb_state.c
lib/bfd.h

index f32bc2598bdc2d82b385e26c739e877dc887e9e0..fd02156372de9a817e177ae7cd3d40cb7f402df2 100644 (file)
@@ -222,10 +222,11 @@ void bfd_profile_remove(struct bfd_session *bs)
        bfd_session_apply(bs);
 }
 
-void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
-                struct sockaddr_any *local, bool mhop, const char *ifname,
-                const char *vrfname)
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct sockaddr_any *local,
+                bool mhop, const char *ifname, const char *vrfname, const char *bfdname)
 {
+       struct vrf *vrf = NULL;
+
        memset(key, 0, sizeof(*key));
 
        switch (peer->sa_sin.sin_family) {
@@ -248,10 +249,20 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
        key->mhop = mhop;
        if (ifname && ifname[0])
                strlcpy(key->ifname, ifname, sizeof(key->ifname));
-       if (vrfname && vrfname[0])
-               strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
-       else
+       if (vrfname && vrfname[0] && strcmp(vrfname, VRF_DEFAULT_NAME) != 0) {
+               vrf = vrf_lookup_by_name(vrfname);
+               if (vrf) {
+                       strlcpy(key->vrfname, vrf->name, sizeof(key->vrfname));
+               } else {
+                       strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
+               }
+       } else {
                strlcpy(key->vrfname, VRF_DEFAULT_NAME, sizeof(key->vrfname));
+       }
+
+       if (bfdname && bfdname[0]) {
+               strlcpy(key->bfdname, bfdname, sizeof(key->bfdname));
+       }
 }
 
 struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
@@ -259,8 +270,8 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
        struct bfd_key key;
 
        /* Otherwise fallback to peer/local hash lookup. */
-       gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop,
-                   bpc->bpc_localif, bpc->bpc_vrfname);
+       gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop, bpc->bpc_localif,
+                   bpc->bpc_vrfname, bpc->bfd_name);
 
        return bfd_key_lookup(key);
 }
@@ -599,7 +610,7 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
        vrf = vrf_lookup_by_id(vrfid);
 
        gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
-                   vrf ? vrf->name : VRF_DEFAULT_NAME);
+                   vrf ? vrf->name : VRF_DEFAULT_NAME, NULL);
 
        /* XXX maybe remoteDiscr should be checked for remoteHeard cases. */
        return bfd_key_lookup(key);
@@ -1713,6 +1724,7 @@ void bfd_shutdown(void)
 struct bfd_session_iterator {
        int bsi_stop;
        bool bsi_mhop;
+       uint32_t bsi_bfdmode;
        const struct bfd_session *bsi_bs;
 };
 
@@ -1724,7 +1736,7 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)
        /* Previous entry signaled stop. */
        if (bsi->bsi_stop == 1) {
                /* Match the single/multi hop sessions. */
-               if (bs->key.mhop != bsi->bsi_mhop)
+               if ((bs->key.mhop != bsi->bsi_mhop) || (bs->bfd_mode != bsi->bsi_bfdmode))
                        return HASHWALK_CONTINUE;
 
                bsi->bsi_bs = bs;
@@ -1736,7 +1748,8 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)
                bsi->bsi_stop = 1;
                /* Set entry to NULL to signal end of list. */
                bsi->bsi_bs = NULL;
-       } else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop) {
+       } else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop &&
+                  bsi->bsi_bfdmode == bs->bfd_mode) {
                /* We want the first list item. */
                bsi->bsi_stop = 1;
                bsi->bsi_bs = hb->data;
@@ -1751,14 +1764,15 @@ static int _bfd_session_next(struct hash_bucket *hb, void *arg)
  *
  * `bs` might point to NULL to get the first item of the data structure.
  */
-const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
-                                          bool mhop)
+const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop,
+                                          uint32_t bfd_mode)
 {
        struct bfd_session_iterator bsi;
 
        bsi.bsi_stop = 0;
        bsi.bsi_bs = bs;
        bsi.bsi_mhop = mhop;
+       bsi.bsi_bfdmode = bfd_mode;
        hash_walk(bfd_key_hash, _bfd_session_next, &bsi);
        if (bsi.bsi_stop == 0)
                return NULL;
index 75204062f1ae4ef35047aa341720f8d790db1b3d..f79df1dcdd4d686b9dbd8a7008dd335703c1ad10 100644 (file)
@@ -19,6 +19,7 @@
 #include "lib/qobj.h"
 #include "lib/queue.h"
 #include "lib/vrf.h"
+#include "lib/bfd.h"
 
 #ifdef BFD_DEBUG
 #define BFDD_JSON_CONV_OPTIONS (JSON_C_TO_STRING_PRETTY)
@@ -86,6 +87,10 @@ struct bfd_peer_cfg {
 
        bool bpc_has_profile;
        char bpc_profile[64];
+
+       vrf_id_t vrf_id;
+       char bfd_name[BFD_NAME_SIZE + 1];
+       uint8_t bfd_name_len;
 };
 
 /* bfd Authentication Type. */
@@ -260,6 +265,7 @@ struct bfd_key {
        struct in6_addr local;
        char ifname[IFNAMSIZ];
        char vrfname[VRF_NAMSIZ];
+       char bfdname[BFD_NAME_SIZE + 1];
 } __attribute__((packed));
 
 struct bfd_session_stats {
@@ -381,6 +387,9 @@ struct bfd_session {
        uint8_t rtt_valid;          /* number of valid samples */
        uint8_t rtt_index;          /* last index added */
        uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */
+       char bfd_name[BFD_NAME_SIZE + 1];
+
+       uint32_t bfd_mode;
 };
 
 struct bfd_diag_str_list {
@@ -604,14 +613,13 @@ void bs_observer_del(struct bfd_session_observer *bso);
 
 void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
 
-void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
-                struct sockaddr_any *local, bool mhop, const char *ifname,
-                const char *vrfname);
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct sockaddr_any *local,
+                bool mhop, const char *ifname, const char *vrfname, const char *bfdname);
 struct bfd_session *bfd_session_new(void);
 struct bfd_session *bs_registrate(struct bfd_session *bs);
 void bfd_session_free(struct bfd_session *bs);
-const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
-                                          bool mhop);
+const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop,
+                                          uint32_t bfd_mode);
 void bfd_sessions_remove_manual(void);
 void bfd_profiles_remove(void);
 void bfd_rtt_init(struct bfd_session *bfd);
index 48fbe7139c275fdcc6d269e30a7e942819184360..c0e7bc16e7e793031211fa23e3602fbdbadebcf0 100644 (file)
 
 #include "bfd.h"
 #include "bfdd_nb.h"
+#include <ifaddrs.h>
 
 /*
  * Helpers.
  */
+static void get_ip_by_interface(const char *ifname, const char *vrfname, int family, char *ifip)
+{
+       char intfip[INET6_ADDRSTRLEN];
+       const struct interface *interface;
+       const struct connected *connected;
+       struct vrf *vrf;
+
+       vrf = vrf_lookup_by_name(vrfname ? vrfname : VRF_DEFAULT_NAME);
+       if (!vrf)
+               return;
+
+       interface = if_lookup_by_name_vrf(ifname, vrf);
+       if (interface == NULL)
+               return;
+
+       frr_each (if_connected_const, interface->connected, connected) {
+               if (!connected->address)
+                       continue;
+
+               if (family != connected->address->family)
+                       continue;
+
+               if (family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6))
+                       continue;
+
+               inet_ntop(family,
+                         family == AF_INET ? (void *)(&connected->address->u.prefix4)
+                                           : (void *)(&connected->address->u.prefix6),
+                         intfip, INET6_ADDRSTRLEN);
+               strlcpy(ifip, intfip, INET6_ADDRSTRLEN - 1);
+               break;
+       }
+}
+
 static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
                                struct bfd_key *bk)
 {
        const char *ifname = NULL, *vrfname = NULL;
+       char ifip[INET6_ADDRSTRLEN] = { 0 };
        struct sockaddr_any psa, lsa;
 
        /* Required destination parameter. */
@@ -37,10 +73,16 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
                ifname = yang_dnode_get_string(dnode, "interface");
                if (strcmp(ifname, "*") == 0)
                        ifname = NULL;
+
+               if (ifname != NULL && !yang_dnode_exists(dnode, "source-addr") &&
+                   psa.sa_sin.sin_family != 0) {
+                       get_ip_by_interface(ifname, vrfname, psa.sa_sin.sin_family, ifip);
+                       strtosa(ifip, &lsa);
+               }
        }
 
        /* Generate the corresponding key. */
-       gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
+       gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, NULL);
 }
 
 struct session_iter {
index 12acda8fd8a62683bdf97c0dd24a88179835fd8b..1fc5b9588752f03d21f7a2e8d6d9bd803c9c672a 100644 (file)
@@ -20,7 +20,7 @@
 const void *
 bfdd_bfd_sessions_single_hop_get_next(struct nb_cb_get_next_args *args)
 {
-       return bfd_session_next(args->list_entry, false);
+       return bfd_session_next(args->list_entry, false, BFD_MODE_TYPE_BFD);
 }
 
 int bfdd_bfd_sessions_single_hop_get_keys(struct nb_cb_get_keys_args *args)
@@ -50,7 +50,7 @@ bfdd_bfd_sessions_single_hop_lookup_entry(struct nb_cb_lookup_entry_args *args)
 
        strtosa(dest_addr, &psa);
        memset(&lsa, 0, sizeof(lsa));
-       gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf);
+       gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf, NULL);
 
        return bfd_key_lookup(bk);
 }
@@ -323,7 +323,7 @@ bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem(
 const void *
 bfdd_bfd_sessions_multi_hop_get_next(struct nb_cb_get_next_args *args)
 {
-       return bfd_session_next(args->list_entry, true);
+       return bfd_session_next(args->list_entry, true, BFD_MODE_TYPE_BFD);
 }
 
 int bfdd_bfd_sessions_multi_hop_get_keys(struct nb_cb_get_keys_args *args)
@@ -354,7 +354,7 @@ bfdd_bfd_sessions_multi_hop_lookup_entry(struct nb_cb_lookup_entry_args *args)
 
        strtosa(dest_addr, &psa);
        strtosa(source_addr, &lsa);
-       gen_bfd_key(&bk, &psa, &lsa, true, NULL, vrf);
+       gen_bfd_key(&bk, &psa, &lsa, true, NULL, vrf, NULL);
 
        return bfd_key_lookup(bk);
 }
index 99790f96a54b59ac06a8bfa46ca6f1b348b6d2bb..07d4c9781dbedf15841aac10e3c36c7e961b70cd 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -26,6 +26,8 @@ extern "C" {
 
 #define BFD_PROFILE_NAME_LEN 64
 
+#define BFD_NAME_SIZE 255
+
 const char *bfd_get_status_str(int status);
 
 extern void bfd_client_sendmsg(struct zclient *zclient, int command,
@@ -409,6 +411,8 @@ struct bfd_session_arg {
        uint32_t min_tx;
        /** Detection multiplier. */
        uint32_t detection_multiplier;
+       /* bfd session name*/
+       char bfd_name[BFD_NAME_SIZE + 1];
 };
 
 /**