]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bfdd: support sbfd session create and destroy
authorwumu.zsl <wumu.zsl@alibaba-inc.com>
Tue, 21 Jan 2025 03:11:03 +0000 (03:11 +0000)
committerwumu.zsl <wumu.zsl@alibaba-inc.com>
Thu, 23 Jan 2025 02:29:09 +0000 (02:29 +0000)
refactor bfd_session_create and bfd_session_destroy to support SBFD

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

index fd02156372de9a817e177ae7cd3d40cb7f402df2..a0094fd85fe61370fc240582d159cfbeeb6de31f 100644 (file)
@@ -657,11 +657,13 @@ void bfd_echo_recvtimer_cb(struct event *t)
        }
 }
 
-struct bfd_session *bfd_session_new(void)
+struct bfd_session *bfd_session_new(enum bfd_mode_type mode)
 {
        struct bfd_session *bs;
 
-       bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs));
+       bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(struct bfd_session));
+       bs->segnum = 0;
+       bs->bfd_mode = mode;
 
        /* Set peer session defaults. */
        bfd_profile_set_default(&bs->peer_profile);
@@ -799,7 +801,7 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
        }
 
        /* Get BFD session storage with its defaults. */
-       bfd = bfd_session_new();
+       bfd = bfd_session_new(BFD_MODE_TYPE_BFD);
 
        /*
         * Store interface/VRF name in case we need to delay session
index f79df1dcdd4d686b9dbd8a7008dd335703c1ad10..6b3df63e3d3709f07397d9e7efee3fe7ea59aa3b 100644 (file)
@@ -615,7 +615,7 @@ 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, const char *bfdname);
-struct bfd_session *bfd_session_new(void);
+struct bfd_session *bfd_session_new(enum bfd_mode_type mode);
 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,
index c0e7bc16e7e793031211fa23e3602fbdbadebcf0..91084ba02ea495eed56d2753c4271bc2a5db9020 100644 (file)
@@ -85,6 +85,26 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
        gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, NULL);
 }
 
+static void sbfd_session_get_key(bool mhop, const struct lyd_node *dnode, struct bfd_key *bk)
+{
+       const char *ifname = NULL, *vrfname = NULL, *bfdname = NULL;
+       struct sockaddr_any psa, lsa;
+
+       /* Required source parameter. */
+       strtosa(yang_dnode_get_string(dnode, "source-addr"), &lsa);
+
+       strtosa(yang_dnode_get_string(dnode, "dest-addr"), &psa);
+
+       if (yang_dnode_exists(dnode, "bfd-name"))
+               bfdname = yang_dnode_get_string(dnode, "bfd-name");
+
+       if (yang_dnode_exists(dnode, "vrf"))
+               vrfname = yang_dnode_get_string(dnode, "vrf");
+
+       /* Generate the corresponding key. */
+       gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname, bfdname);
+}
+
 struct session_iter {
        int count;
        bool wildcard;
@@ -105,7 +125,25 @@ static int session_iter_cb(const struct lyd_node *dnode, void *arg)
        return YANG_ITER_CONTINUE;
 }
 
-static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
+static int segment_list_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+       struct bfd_session *bs = arg;
+       uint8_t segnum = bs->segnum;
+       const char *addr;
+       struct sockaddr_any sa;
+
+       addr = yang_dnode_get_string(dnode, NULL);
+
+       if (strtosa(addr, &sa) < 0 || sa.sa_sin6.sin6_family != AF_INET6)
+               return YANG_ITER_STOP;
+
+       memcpy(&bs->seg_list[segnum], &sa.sa_sin6.sin6_addr, sizeof(struct in6_addr));
+       bs->segnum = segnum + 1;
+
+       return YANG_ITER_CONTINUE;
+}
+
+static int bfd_session_create(struct nb_cb_create_args *args, bool mhop, uint32_t bfd_mode)
 {
        const struct lyd_node *sess_dnode;
        struct session_iter iter;
@@ -115,10 +153,20 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
        const char *vrfname;
        struct bfd_key bk;
        struct prefix p;
+       const char *bfd_name = NULL;
+       struct sockaddr_any out_sip6;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               yang_dnode_get_prefix(&p, args->dnode, "dest-addr");
+               if ((bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) || (bfd_mode == BFD_MODE_TYPE_SBFD_INIT)) {
+                       if (bfd_session_get_by_name(yang_dnode_get_string(args->dnode, "bfd-name"))) {
+                               snprintf(args->errmsg, args->errmsg_len, "bfd name already exist.");
+                               return NB_ERR_VALIDATION;
+                       }
+                       return NB_OK;
+               }
+
+               yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
 
                if (mhop) {
                        /*
@@ -170,34 +218,123 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
                break;
 
        case NB_EV_PREPARE:
-               bfd_session_get_key(mhop, args->dnode, &bk);
-               bs = bfd_key_lookup(bk);
+               if (bfd_mode == BFD_MODE_TYPE_BFD) {
+                       bfd_session_get_key(mhop, args->dnode, &bk);
+                       bs = bfd_key_lookup(bk);
+
+                       /* This session was already configured by another daemon. */
+                       if (bs != NULL) {
+                               /* Now it is configured also by CLI. */
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
+                               bs->refcount++;
+
+                               args->resource->ptr = bs;
+                               break;
+                       }
+
+                       bs = bfd_session_new(BFD_MODE_TYPE_BFD);
 
-               /* This session was already configured by another daemon. */
-               if (bs != NULL) {
-                       /* Now it is configured also by CLI. */
+                       /* Fill the session key. */
+                       bfd_session_get_key(mhop, args->dnode, &bs->key);
+                       /* Set configuration flags. */
+                       bs->refcount = 1;
                        SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
-                       bs->refcount++;
+                       if (mhop)
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
+                       if (bs->key.family == AF_INET6)
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
 
                        args->resource->ptr = bs;
                        break;
-               }
+               } else if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO ||
+                          bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+                       sbfd_session_get_key(mhop, args->dnode, &bk);
+                       bs = bfd_key_lookup(bk);
+
+                       /* This session was already configured by another daemon. */
+                       if (bs != NULL) {
+                               /* Now it is configured also by CLI. */
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
+                               bs->refcount++;
+
+                               args->resource->ptr = bs;
+                               break;
+                       }
 
-               bs = bfd_session_new();
+                       if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO &&
+                           !yang_dnode_exists(args->dnode, "srv6-encap-data")) {
+                               //srv6-encap-data should not be null for sbfd echo
+                               snprintf(args->errmsg, args->errmsg_len,
+                                        "srv6-encap-data should not be null");
+                               return NB_ERR_RESOURCE;
+                       }
 
-               /* Fill the session key. */
-               bfd_session_get_key(mhop, args->dnode, &bs->key);
+                       if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO &&
+                           !yang_dnode_exists(args->dnode, "srv6-source-ipv6")) {
+                               snprintf(args->errmsg, args->errmsg_len,
+                                        "source_ipv6 should not be null");
+                               return NB_ERR_RESOURCE;
+                       }
 
-               /* Set configuration flags. */
-               bs->refcount = 1;
-               SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
-               if (mhop)
-                       SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
-               if (bs->key.family == AF_INET6)
-                       SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
+                       if (bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+                               if (!yang_dnode_exists(args->dnode, "remote-discr")) {
+                                       snprintf(args->errmsg, args->errmsg_len,
+                                                "remote-discr should not be null");
+                                       return NB_ERR_RESOURCE;
+                               }
+                       }
 
-               args->resource->ptr = bs;
-               break;
+                       bfd_name = yang_dnode_get_string(args->dnode, "bfd-name");
+
+                       bs = bfd_session_new(bfd_mode);
+                       if (bs == NULL) {
+                               snprintf(args->errmsg, args->errmsg_len,
+                                        "session-new: allocation failed");
+                               return NB_ERR_RESOURCE;
+                       }
+                       /* Fill the session key. */
+                       sbfd_session_get_key(mhop, args->dnode, &bs->key);
+                       strlcpy(bs->bfd_name, bfd_name, BFD_NAME_SIZE);
+
+                       if (yang_dnode_exists(args->dnode, "srv6-encap-data")) {
+                               yang_dnode_iterate(segment_list_iter_cb, bs, args->dnode,
+                                                  "./srv6-encap-data");
+
+
+                               strtosa(yang_dnode_get_string(args->dnode, "./srv6-source-ipv6"),
+                                       &out_sip6);
+                               memcpy(&bs->out_sip6, &out_sip6.sa_sin6.sin6_addr,
+                                      sizeof(struct in6_addr));
+                       }
+
+                       if (bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+                               bs->discrs.remote_discr = yang_dnode_get_uint32(args->dnode,
+                                                                               "./remote-discr");
+                       }
+
+                       /* Set configuration flags. */
+                       bs->refcount = 1;
+                       SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
+                       if (mhop)
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_MH);
+
+                       if (bs->key.family == AF_INET6)
+                               SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
+
+                       if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) {
+                               memcpy(&bs->key.peer, &bs->key.local, sizeof(struct in6_addr));
+                       } else {
+                               bs->xmt_TO = bs->timers.desired_min_tx;
+                               bs->detect_TO = bs->detect_mult * bs->xmt_TO;
+                       }
+
+                       args->resource->ptr = bs;
+                       break;
+
+               } else {
+                       snprintf(args->errmsg, args->errmsg_len, "bfd mode must be bfd or sbfd.");
+                       return NB_ERR_VALIDATION;
+               }
 
        case NB_EV_APPLY:
                bs = args->resource->ptr;
@@ -219,15 +356,19 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
        return NB_OK;
 }
 
-static int bfd_session_destroy(enum nb_event event,
-                              const struct lyd_node *dnode, bool mhop)
+static int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, bool mhop,
+                              uint32_t bfd_mode)
 {
        struct bfd_session *bs;
        struct bfd_key bk;
 
        switch (event) {
        case NB_EV_VALIDATE:
-               bfd_session_get_key(mhop, dnode, &bk);
+               if (bfd_mode == BFD_MODE_TYPE_BFD)
+                       bfd_session_get_key(mhop, dnode, &bk);
+               else
+                       sbfd_session_get_key(mhop, dnode, &bk);
+
                if (bfd_key_lookup(bk) == NULL)
                        return NB_ERR_INCONSISTENCY;
                break;
@@ -248,6 +389,12 @@ static int bfd_session_destroy(enum nb_event event,
                if (bs->refcount > 0)
                        break;
 
+               if (bglobal.debug_peer_event)
+                       zlog_info("session destroy: %s", bs_to_string(bs));
+
+               if (bfd_mode == BFD_MODE_TYPE_SBFD_ECHO || bfd_mode == BFD_MODE_TYPE_SBFD_INIT)
+                       ptm_bfd_notify(bs, PTM_BFD_DOWN);
+
                bfd_session_free(bs);
                break;
 
@@ -552,12 +699,12 @@ int bfdd_bfd_profile_required_echo_receive_interval_modify(
  */
 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
 {
-       return bfd_session_create(args, false);
+       return bfd_session_create(args, false, BFD_MODE_TYPE_BFD);
 }
 
 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
 {
-       return bfd_session_destroy(args->event, args->dnode, false);
+       return bfd_session_destroy(args->event, args->dnode, false, BFD_MODE_TYPE_BFD);
 }
 
 /*
@@ -853,12 +1000,12 @@ int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
  */
 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
 {
-       return bfd_session_create(args, true);
+       return bfd_session_create(args, true, BFD_MODE_TYPE_BFD);
 }
 
 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
 {
-       return bfd_session_destroy(args->event, args->dnode, true);
+       return bfd_session_destroy(args->event, args->dnode, true, BFD_MODE_TYPE_BFD);
 }
 
 /*