]> git.puffer.fish Git - mirror/frr.git/commitdiff
bfdd: enable sbfd session
authorwumu.zsl <wumu.zsl@alibaba-inc.com>
Tue, 21 Jan 2025 06:56:32 +0000 (06:56 +0000)
committerwumu.zsl <wumu.zsl@alibaba-inc.com>
Thu, 23 Jan 2025 02:59:09 +0000 (02:59 +0000)
1) create socket to send sbfd packets
2) integrate sbfd logic with existing BFD

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

index 754f6aa7827bd3e5f5a95393707c7d6c108a32c9..164910556bb168e944ed5a44e87d7b55cf8acf9a 100644 (file)
@@ -197,10 +197,12 @@ void bfd_session_apply(struct bfd_session *bs)
        }
 
        /* Toggle 'passive-mode' if default value. */
-       if (bs->peer_profile.passive == false)
-               bfd_set_passive_mode(bs, bp->passive);
-       else
-               bfd_set_passive_mode(bs, bs->peer_profile.passive);
+       if (bs->bfd_mode == BFD_MODE_TYPE_BFD) {
+               if (bs->peer_profile.passive == false)
+                       bfd_set_passive_mode(bs, bp->passive);
+               else
+                       bfd_set_passive_mode(bs, bs->peer_profile.passive);
+       }
 
        /* Toggle 'no shutdown' if default value. */
        if (bs->peer_profile.admin_shutdown == false)
@@ -349,14 +351,24 @@ int bfd_session_enable(struct bfd_session *bs)
         * could use the destination port (3784) for the source
         * port we wouldn't need a socket per session.
         */
-       if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6) == 0) {
+       if (bs->bfd_mode == BFD_MODE_TYPE_SBFD_ECHO || bs->bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+               psock = bp_peer_srh_socketv6(bs);
+               if (psock <= 0) {
+                       zlog_err("bp_peer_srh_socketv6 error");
+                       return 0;
+               }
+       } else if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6) == 0) {
                psock = bp_peer_socket(bs);
-               if (psock == -1)
+               if (psock == -1) {
+                       zlog_err("bp_peer_socket error");
                        return 0;
+               }
        } else {
                psock = bp_peer_socketv6(bs);
-               if (psock == -1)
+               if (psock == -1) {
+                       zlog_err("bp_peer_socketv6 error");
                        return 0;
+               }
        }
 
        /*
@@ -367,10 +379,18 @@ int bfd_session_enable(struct bfd_session *bs)
 
        /* Only start timers if we are using active mode. */
        if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE) == 0) {
-               bfd_recvtimer_update(bs);
-               ptm_bfd_start_xmt_timer(bs, false);
-       }
+               if (bs->bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) {
+                       /*enable receive echo response*/
+                       bfd_set_echo(bs, true);
 
+                       bs->echo_detect_TO = (bs->remote_detect_mult * bs->echo_xmt_TO);
+                       sbfd_echo_recvtimer_update(bs);
+                       ptm_bfd_start_xmt_timer(bs, true);
+               } else {
+                       bfd_recvtimer_update(bs);
+                       ptm_bfd_start_xmt_timer(bs, false);
+               }
+       }
        /* initialize RTT */
        bfd_rtt_init(bs);
 
@@ -399,6 +419,8 @@ void bfd_session_disable(struct bfd_session *bs)
        bfd_recvtimer_delete(bs);
        bfd_xmttimer_delete(bs);
        ptm_bfd_echo_stop(bs);
+       bs->vrf = NULL;
+       bs->ifp = NULL;
 
        /* Set session down so it doesn't report UP and disabled. */
        ptm_bfd_sess_dn(bs, BD_PATH_DOWN);
@@ -438,10 +460,18 @@ void ptm_bfd_start_xmt_timer(struct bfd_session *bfd, bool is_echo)
        jitter = (xmt_TO * (75 + (frr_weak_random() % maxpercent))) / 100;
        /* XXX remove that division above */
 
-       if (is_echo)
-               bfd_echo_xmttimer_update(bfd, jitter);
-       else
-               bfd_xmttimer_update(bfd, jitter);
+       if (bfd->bfd_mode == BFD_MODE_TYPE_SBFD_ECHO || bfd->bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+               if (is_echo)
+                       sbfd_echo_xmttimer_update(bfd, jitter);
+               else
+                       sbfd_init_xmttimer_update(bfd, jitter);
+
+       } else {
+               if (is_echo)
+                       bfd_echo_xmttimer_update(bfd, jitter);
+               else
+                       bfd_xmttimer_update(bfd, jitter);
+       }
 }
 
 static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd)
@@ -597,7 +627,8 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
        UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
        memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
        /* reset local address ,it might has been be changed after bfd is up*/
-       memset(&bfd->local_address, 0, sizeof(bfd->local_address));
+       if (bfd->bfd_mode == BFD_MODE_TYPE_BFD)
+               memset(&bfd->local_address, 0, sizeof(bfd->local_address));
 
        /* reset RTT */
        bfd_rtt_init(bfd);
@@ -790,6 +821,11 @@ void bfd_echo_recvtimer_cb(struct event *t)
 {
        struct bfd_session *bs = EVENT_ARG(t);
 
+       if (bglobal.debug_peer_event) {
+               zlog_debug("%s:  time-out bfd: [%s]  bfd'state is %s", __func__, bs_to_string(bs),
+                          state_list[bs->ses_state].str);
+       }
+
        switch (bs->ses_state) {
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
@@ -1436,6 +1472,15 @@ void bs_set_slow_timers(struct bfd_session *bs)
        /* Set the appropriated timeouts for slow connection. */
        bs->detect_TO = (BFD_DEFDETECTMULT * BFD_DEF_SLOWTX);
        bs->xmt_TO = BFD_DEF_SLOWTX;
+
+       /* add for sbfd-echo slow connection  */
+       if (BFD_MODE_TYPE_SBFD_ECHO == bs->bfd_mode) {
+               bs->echo_xmt_TO = SBFD_ECHO_DEF_SLOWTX;
+               bs->timers.desired_min_echo_tx = BFD_DEFDESIREDMINTX;
+               bs->timers.required_min_echo_rx = BFD_DEFDESIREDMINTX;
+               bs->peer_profile.min_echo_rx = BFD_DEFDESIREDMINTX;
+               bs->peer_profile.min_echo_tx = BFD_DEFDESIREDMINTX;
+       }
 }
 
 void bfd_set_echo(struct bfd_session *bs, bool echo)
@@ -1727,6 +1772,8 @@ const char *bs_to_string(const struct bfd_session *bs)
        if (bs->key.ifname[0])
                pos += snprintf(buf + pos, sizeof(buf) - pos, " ifname:%s",
                                bs->key.ifname);
+       if (bs->bfd_name[0])
+               pos += snprintf(buf + pos, sizeof(buf) - pos, " bfd_name:%s", bs->bfd_name);
 
        (void)pos;
 
@@ -1860,6 +1907,8 @@ static bool bfd_key_hash_cmp(const void *n1, const void *n2)
        if (memcmp(bs1->key.vrfname, bs2->key.vrfname,
                   sizeof(bs1->key.vrfname)))
                return false;
+       if (memcmp(bs1->key.bfdname, bs2->key.bfdname, sizeof(bs1->key.bfdname)))
+               return false;
 
        /*
         * Local address is optional and can be empty.
@@ -2281,6 +2330,7 @@ static int bfd_vrf_new(struct vrf *vrf)
        bvrf->bg_mhop6 = -1;
        bvrf->bg_echo = -1;
        bvrf->bg_echov6 = -1;
+       bvrf->bg_initv6 = -1;
 
        return 0;
 }
@@ -2314,6 +2364,8 @@ static int bfd_vrf_enable(struct vrf *vrf)
                bvrf->bg_shop6 = bp_udp6_shop(vrf);
        if (bvrf->bg_mhop6 == -1)
                bvrf->bg_mhop6 = bp_udp6_mhop(vrf);
+       if (bvrf->bg_initv6 == -1)
+               bvrf->bg_initv6 = bp_initv6_socket(vrf);
 
        if (bvrf->bg_ev[0] == NULL && bvrf->bg_shop != -1)
                event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
@@ -2327,6 +2379,8 @@ static int bfd_vrf_enable(struct vrf *vrf)
        if (bvrf->bg_ev[3] == NULL && bvrf->bg_mhop6 != -1)
                event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
                               &bvrf->bg_ev[3]);
+       if (bvrf->bg_ev[6] == NULL && bvrf->bg_initv6 != -1)
+               event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_initv6, &bvrf->bg_ev[6]);
 
        /* Toggle echo if VRF was disabled. */
        bfd_vrf_toggle_echo(bvrf);
@@ -2363,6 +2417,7 @@ static int bfd_vrf_disable(struct vrf *vrf)
        EVENT_OFF(bvrf->bg_ev[3]);
        EVENT_OFF(bvrf->bg_ev[4]);
        EVENT_OFF(bvrf->bg_ev[5]);
+       EVENT_OFF(bvrf->bg_ev[6]);
 
        /* Close all descriptors. */
        socket_close(&bvrf->bg_echo);
@@ -2371,6 +2426,7 @@ static int bfd_vrf_disable(struct vrf *vrf)
        socket_close(&bvrf->bg_shop6);
        socket_close(&bvrf->bg_mhop6);
        socket_close(&bvrf->bg_echov6);
+       socket_close(&bvrf->bg_initv6);
 
        return 0;
 }
index e4421a358f853b85aca28dafb5a264935529704f..d9119d16c218f66925c3bc6391093f9d1688c1da 100644 (file)
@@ -152,7 +152,6 @@ struct bfd_echo_pkt {
        uint64_t time_sent_usec;
 };
 
-
 /* Macros for manipulating control packets */
 #define BFD_VERMASK 0x07
 #define BFD_DIAGMASK 0x1F
@@ -470,9 +469,10 @@ struct bfd_vrf_global {
        int bg_mhop6;
        int bg_echo;
        int bg_echov6;
+       int bg_initv6;
        struct vrf *vrf;
 
-       struct event *bg_ev[6];
+       struct event *bg_ev[7];
 };
 
 /* Forward declaration of data plane context struct. */
index 84f2e6ba75d7094d268a2f11e107d1a944c5704d..f43759ab8bbe602651b5e72d3f08e224efd160b4 100644 (file)
@@ -22,6 +22,8 @@
 
 #ifdef BFD_LINUX
 #include <linux/if_packet.h>
+#include <linux/seg6.h>
+#include <linux/ipv6.h>
 #endif /* BFD_LINUX */
 
 #include <netinet/if_ether.h>
@@ -387,7 +389,24 @@ static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
        /* Compute detect time */
        bfd->echo_detect_TO = bfd->remote_detect_mult * bfd->echo_xmt_TO;
 
-       /* Update echo receive timeout. */
+       /* Update sbfd-echo session state */
+       if (bfd->bfd_mode == BFD_MODE_TYPE_SBFD_ECHO) {
+               sbfd_echo_state_handler(bfd, PTM_BFD_UP);
+
+               if (bfd->echo_xmt_TO != bfd->timers.desired_min_echo_tx) {
+                       bfd->echo_xmt_TO = bfd->timers.desired_min_echo_tx;
+                       //reset xmt timer TO after UP
+                       ptm_bfd_start_xmt_timer(bfd, true);
+               }
+
+               bfd->echo_detect_TO = bfd->detect_mult * bfd->echo_xmt_TO;
+               /* Update sbfd echo receive timeout. */
+               if (bfd->echo_detect_TO > 0)
+                       sbfd_echo_recvtimer_update(bfd);
+               return 0;
+       }
+
+       /* Update bfd-echo receive timeout. */
        if (bfd->echo_detect_TO > 0)
                bfd_echo_recvtimer_update(bfd);
 
@@ -742,6 +761,9 @@ static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd)
                EVENT_OFF(bvrf->bg_ev[5]);
                event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
                               &bvrf->bg_ev[5]);
+       } else if (sd == bvrf->bg_initv6) {
+               EVENT_OFF(bvrf->bg_ev[6]);
+               event_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_initv6, &bvrf->bg_ev[6]);
        }
 }
 
@@ -835,6 +857,11 @@ void bfd_recv_cb(struct event *t)
        /* Schedule next read. */
        bfd_sd_reschedule(bvrf, sd);
 
+       /* The reflector handle SBFD init packets. */
+       if (sd == bvrf->bg_initv6) {
+               ptm_bfd_reflector_process_init_packet(bvrf, sd);
+               return;
+       }
        /* Handle echo packets. */
        if (sd == bvrf->bg_echo || sd == bvrf->bg_echov6) {
                ptm_bfd_process_echo_pkt(bvrf, sd);
@@ -1009,6 +1036,29 @@ void bfd_recv_cb(struct event *t)
        else
                bfd->remote_cbit = 0;
 
+       /* The initiator handle SBFD reflect packet. */
+       if (bfd->bfd_mode == BFD_MODE_TYPE_SBFD_INIT) {
+               sbfd_initiator_state_handler(bfd, PTM_BFD_UP);
+               if (bfd->xmt_TO != bfd->timers.desired_min_tx) {
+                       bfd->xmt_TO = bfd->timers.desired_min_tx;
+                       //reset xmt timer TO after UP
+                       ptm_bfd_start_xmt_timer(bfd, false);
+               }
+
+               bfd->detect_TO = bfd->detect_mult * bfd->xmt_TO;
+               sbfd_init_recvtimer_update(bfd);
+
+               if (bfd->polling && BFD_GETFBIT(cp->flags)) {
+                       /* Disable polling. */
+                       bfd->polling = 0;
+                       /* Start using our new timers. */
+                       bfd->cur_timers.desired_min_tx = bfd->timers.desired_min_tx;
+                       bfd->cur_timers.required_min_rx = bfd->timers.required_min_rx;
+               }
+
+               return;
+       }
+
        /* State switch from section 6.2. */
        bs_state_handler(bfd, BFD_GETSTATE(cp->flags));