]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/bfd.c
Merge pull request #6483 from sylane/router-id-v6
[mirror_frr.git] / lib / bfd.c
index 5f2d2f0edab7db4ae1f655f8b44a8a45a4920570..d1a0ec671e505c3e7fbf0616774fb16e1320a337 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -94,7 +94,8 @@ int bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str,
  * bfd_set_param - Set the configured BFD paramter values
  */
 void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx,
-                  uint8_t detect_mult, int defaults, int *command)
+                  uint8_t detect_mult, const char *profile, int defaults,
+                  int *command)
 {
        if (!*bfd_info) {
                *bfd_info = bfd_info_create();
@@ -102,7 +103,8 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx,
        } else {
                if (((*bfd_info)->required_min_rx != min_rx)
                    || ((*bfd_info)->desired_min_tx != min_tx)
-                   || ((*bfd_info)->detect_mult != detect_mult))
+                   || ((*bfd_info)->detect_mult != detect_mult)
+                   || (profile && strcmp((*bfd_info)->profile, profile)))
                        *command = ZEBRA_BFD_DEST_UPDATE;
        }
 
@@ -110,6 +112,11 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx,
                (*bfd_info)->required_min_rx = min_rx;
                (*bfd_info)->desired_min_tx = min_tx;
                (*bfd_info)->detect_mult = detect_mult;
+               if (profile)
+                       strlcpy((*bfd_info)->profile, profile,
+                               BFD_PROFILE_NAME_LEN);
+               else
+                       (*bfd_info)->profile[0] = '\0';
        }
 
        if (!defaults)
@@ -121,15 +128,16 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx,
 /*
  * bfd_peer_sendmsg - Format and send a peer register/Unregister
  *                    command to Zebra to be forwarded to BFD
+ *
+ * DEPRECATED: use zclient_bfd_command instead
  */
 void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
                      int family, void *dst_ip, void *src_ip, char *if_name,
                      int ttl, int multihop, int cbit, int command,
                      int set_flag, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       int ret;
-       int len;
+       struct bfd_session_arg args = {};
+       size_t addrlen;
 
        /* Individual reg/dereg messages are suppressed during shutdown. */
        if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) {
@@ -144,92 +152,42 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
        if (!zclient || zclient->sock < 0) {
                if (bfd_debug)
                        zlog_debug(
-                               "%s: Can't send BFD peer register, Zebra client not "
-                               "established",
+                               "%s: Can't send BFD peer register, Zebra client not established",
                                __func__);
                return;
        }
 
-       s = zclient->obuf;
-       stream_reset(s);
-       zclient_create_header(s, command, vrf_id);
-
-       stream_putl(s, getpid());
-
-       stream_putw(s, family);
-       switch (family) {
-       case AF_INET:
-               stream_put_in_addr(s, (struct in_addr *)dst_ip);
-               break;
-       case AF_INET6:
-               stream_put(s, dst_ip, 16);
-               break;
-       default:
-               break;
-       }
-
-       if (command != ZEBRA_BFD_DEST_DEREGISTER) {
-               stream_putl(s, bfd_info->required_min_rx);
-               stream_putl(s, bfd_info->desired_min_tx);
-               stream_putc(s, bfd_info->detect_mult);
-       }
-
-       if (multihop) {
-               stream_putc(s, 1);
-               /* Multi-hop destination send the source IP address to BFD */
-               if (src_ip) {
-                       stream_putw(s, family);
-                       switch (family) {
-                       case AF_INET:
-                               stream_put_in_addr(s, (struct in_addr *)src_ip);
-                               break;
-                       case AF_INET6:
-                               stream_put(s, src_ip, 16);
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               stream_putc(s, ttl);
-       } else {
-               stream_putc(s, 0);
-               if ((family == AF_INET6) && (src_ip)) {
-                       stream_putw(s, family);
-                       stream_put(s, src_ip, 16);
-               }
-               if (if_name) {
-                       len = strlen(if_name);
-                       stream_putc(s, len);
-                       stream_put(s, if_name, len);
-               } else {
-                       stream_putc(s, 0);
+       /* Fill in all arguments. */
+       args.ttl = ttl;
+       args.cbit = cbit;
+       args.family = family;
+       args.mhop = multihop;
+       args.vrf_id = vrf_id;
+       args.command = command;
+       args.set_flag = set_flag;
+       args.bfd_info = bfd_info;
+       if (args.bfd_info) {
+               args.min_rx = bfd_info->required_min_rx;
+               args.min_tx = bfd_info->desired_min_tx;
+               args.detection_multiplier = bfd_info->detect_mult;
+               if (bfd_info->profile[0]) {
+                       args.profilelen = strlen(bfd_info->profile);
+                       strlcpy(args.profile, bfd_info->profile,
+                               sizeof(args.profile));
                }
        }
-       /* cbit */
-       if (cbit)
-               stream_putc(s, 1);
-       else
-               stream_putc(s, 0);
 
-       stream_putw_at(s, 0, stream_get_endp(s));
+       addrlen = family == AF_INET ? sizeof(struct in_addr)
+                                   : sizeof(struct in6_addr);
+       memcpy(&args.dst, dst_ip, addrlen);
+       if (src_ip)
+               memcpy(&args.src, src_ip, addrlen);
 
-       ret = zclient_send_message(zclient);
+       if (if_name)
+               args.ifnamelen =
+                       strlcpy(args.ifname, if_name, sizeof(args.ifname));
 
-       if (ret < 0) {
-               if (bfd_debug)
-                       zlog_debug(
-                               "bfd_peer_sendmsg: zclient_send_message() failed");
-               return;
-       }
-
-       if (set_flag) {
-               if (command == ZEBRA_BFD_DEST_REGISTER)
-                       SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
-               else if (command == ZEBRA_BFD_DEST_DEREGISTER)
-                       UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
-       }
-
-       return;
+       zclient_bfd_command(zclient, &args);
 }
 
 /*
@@ -272,8 +230,7 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
                if (ifp == NULL) {
                        if (bfd_debug)
                                zlog_debug(
-                                       "zebra_interface_bfd_read: "
-                                       "Can't find interface by ifindex: %d ",
+                                       "zebra_interface_bfd_read: Can't find interface by ifindex: %d ",
                                        ifindex);
                        return NULL;
                }
@@ -375,8 +332,7 @@ void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
                                               json_bfd);
        } else {
                vty_out(vty,
-                       "  %s%sDetect Multiplier: %d, Min Rx interval: %d,"
-                       " Min Tx interval: %d\n",
+                       "  %s%sDetect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
                        (extra_space) ? "  " : "", (bfd_tag) ? "BFD: " : "  ",
                        bfd_info->detect_mult, bfd_info->required_min_rx,
                        bfd_info->desired_min_tx);
@@ -452,8 +408,7 @@ void bfd_client_sendmsg(struct zclient *zclient, int command,
        if (!zclient || zclient->sock < 0) {
                if (bfd_debug)
                        zlog_debug(
-                               "%s: Can't send BFD client register, Zebra client not "
-                               "established",
+                               "%s: Can't send BFD client register, Zebra client not established",
                                __func__);
                return;
        }
@@ -478,3 +433,102 @@ void bfd_client_sendmsg(struct zclient *zclient, int command,
 
        return;
 }
+
+int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args)
+{
+       struct stream *s;
+       size_t addrlen;
+
+       /* Individual reg/dereg messages are suppressed during shutdown. */
+       if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) {
+               if (bfd_debug)
+                       zlog_debug(
+                               "%s: Suppressing BFD peer reg/dereg messages",
+                               __func__);
+               return -1;
+       }
+
+       /* Check socket. */
+       if (!zc || zc->sock < 0) {
+               if (bfd_debug)
+                       zlog_debug("%s: zclient unavailable", __func__);
+               return -1;
+       }
+
+       s = zc->obuf;
+       stream_reset(s);
+
+       /* Create new message. */
+       zclient_create_header(s, args->command, args->vrf_id);
+       stream_putl(s, getpid());
+
+       /* Encode destination address. */
+       stream_putw(s, args->family);
+       addrlen = (args->family == AF_INET) ? sizeof(struct in_addr)
+                                           : sizeof(struct in6_addr);
+       stream_put(s, &args->dst, addrlen);
+
+       /* Encode timers if this is a registration message. */
+       if (args->command != ZEBRA_BFD_DEST_DEREGISTER) {
+               stream_putl(s, args->min_rx);
+               stream_putl(s, args->min_tx);
+               stream_putc(s, args->detection_multiplier);
+       }
+
+       if (args->mhop) {
+               /* Multi hop indicator. */
+               stream_putc(s, 1);
+
+               /* Multi hop always sends the source address. */
+               stream_putw(s, args->family);
+               stream_put(s, &args->src, addrlen);
+
+               /* Send the expected TTL. */
+               stream_putc(s, args->ttl);
+       } else {
+               /* Multi hop indicator. */
+               stream_putc(s, 0);
+
+               /* Single hop only sends the source address when IPv6. */
+               if (args->family == AF_INET6) {
+                       stream_putw(s, args->family);
+                       stream_put(s, &args->src, addrlen);
+               }
+
+               /* Send interface name if any. */
+               stream_putc(s, args->ifnamelen);
+               if (args->ifnamelen)
+                       stream_put(s, args->ifname, args->ifnamelen);
+       }
+
+       /* Send the C bit indicator. */
+       stream_putc(s, args->cbit);
+
+       /* `ptm-bfd` doesn't support profiles yet. */
+#if HAVE_BFDD > 0
+       /* Send profile name if any. */
+       stream_putc(s, args->profilelen);
+       if (args->profilelen)
+               stream_put(s, args->profile, args->profilelen);
+#endif /* HAVE_BFDD */
+
+       /* Finish the message by writing the size. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       /* Send message to zebra. */
+       if (zclient_send_message(zc) == -1) {
+               if (bfd_debug)
+                       zlog_debug("%s: zclient_send_message failed", __func__);
+               return -1;
+       }
+
+       /* Write registration indicator into data structure. */
+       if (args->bfd_info && args->set_flag) {
+               if (args->command == ZEBRA_BFD_DEST_REGISTER)
+                       SET_FLAG(args->bfd_info->flags, BFD_FLAG_BFD_REG);
+               else if (args->command == ZEBRA_BFD_DEST_DEREGISTER)
+                       UNSET_FLAG(args->bfd_info->flags, BFD_FLAG_BFD_REG);
+       }
+
+       return 0;
+}