summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2020-05-19 20:15:20 -0300
committerRafael Zalamena <rzalamena@opensourcerouting.org>2020-05-29 17:48:14 -0300
commit02012befe8cf5589ba4190c832b6b2488d0ab79b (patch)
tree445815ec8739da5427734766fa7ddfa5ab9f55a3
parent18322efd130a7ce60a2c8b731494d12edb1c937e (diff)
bgpd: support BFD profiles configuration
Allow BGP to use the new API to configure BFD session profiles. Now it is possible to preconfigure BFD sessions without needing to create the peers. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
-rw-r--r--bgpd/bgp_bfd.c182
1 files changed, 164 insertions, 18 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index a200589bd3..4e237120a1 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -95,9 +95,11 @@ bool bgp_bfd_is_peer_multihop(struct peer *peer)
*/
static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
{
+ struct bfd_session_arg arg = {};
struct bfd_info *bfd_info;
- int multihop, cbit = 0;
+ int multihop;
vrf_id_t vrf_id;
+ size_t addrlen;
bfd_info = (struct bfd_info *)peer->bfd_info;
@@ -121,21 +123,49 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
&& !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
- cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
-
- if (peer->su.sa.sa_family == AF_INET)
- bfd_peer_sendmsg(
- zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr,
- (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
- (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
- peer->ttl, multihop, cbit, command, 1, vrf_id);
- else if (peer->su.sa.sa_family == AF_INET6)
- bfd_peer_sendmsg(
- zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr,
- (peer->su_local) ? &peer->su_local->sin6.sin6_addr
- : NULL,
- (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
- peer->ttl, multihop, cbit, command, 1, vrf_id);
+ /* Set all message arguments. */
+ arg.family = peer->su.sa.sa_family;
+ addrlen = arg.family == AF_INET ? sizeof(struct in_addr)
+ : sizeof(struct in6_addr);
+
+ if (arg.family == AF_INET)
+ memcpy(&arg.dst, &peer->su.sin.sin_addr, addrlen);
+ else
+ memcpy(&arg.dst, &peer->su.sin6.sin6_addr, addrlen);
+
+ if (peer->su_local) {
+ if (arg.family == AF_INET)
+ memcpy(&arg.src, &peer->su_local->sin.sin_addr,
+ addrlen);
+ else
+ memcpy(&arg.src, &peer->su_local->sin6.sin6_addr,
+ addrlen);
+ }
+
+ if (peer->nexthop.ifp) {
+ arg.ifnamelen = strlen(peer->nexthop.ifp->name);
+ strlcpy(arg.ifname, peer->nexthop.ifp->name,
+ sizeof(arg.ifname));
+ }
+
+ if (bfd_info->profile[0]) {
+ arg.profilelen = strlen(bfd_info->profile);
+ strlcpy(arg.profile, bfd_info->profile, sizeof(arg.profile));
+ }
+
+ arg.set_flag = 1;
+ arg.mhop = multihop;
+ arg.ttl = peer->ttl;
+ arg.vrf_id = vrf_id;
+ arg.command = command;
+ arg.bfd_info = bfd_info;
+ arg.min_tx = bfd_info->desired_min_tx;
+ arg.min_rx = bfd_info->required_min_rx;
+ arg.detection_multiplier = bfd_info->detect_mult;
+ arg.cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
+
+ /* Send message. */
+ zclient_bfd_command(zclient, &arg);
}
/*
@@ -553,6 +583,61 @@ static int bgp_bfd_peer_param_type_set(struct peer *peer,
return 0;
}
+/**
+ * Set peer BFD profile configuration.
+ */
+static int bgp_bfd_peer_set_profile(struct peer *peer, const char *profile)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+ int command = 0;
+ struct bfd_info *bfd_info;
+
+ bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX,
+ BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command);
+
+ bfd_info = (struct bfd_info *)peer->bfd_info;
+
+ /* If profile was specified, then copy string. */
+ if (profile)
+ strlcpy(bfd_info->profile, profile, sizeof(bfd_info->profile));
+ else /* Otherwise just initialize it empty. */
+ bfd_info->profile[0] = 0;
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
+ command = 0;
+ bfd_set_param((struct bfd_info **)&(peer->bfd_info),
+ BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
+ BFD_DEF_DETECT_MULT, 1, &command);
+
+ bfd_info = (struct bfd_info *)peer->bfd_info;
+
+ /* If profile was specified, then copy string. */
+ if (profile)
+ strlcpy(bfd_info->profile, profile,
+ sizeof(bfd_info->profile));
+ else /* Otherwise just initialize it empty. */
+ bfd_info->profile[0] = 0;
+
+ if (peer->status == Established
+ && command == ZEBRA_BFD_DEST_REGISTER)
+ bgp_bfd_register_peer(peer);
+ else if (command == ZEBRA_BFD_DEST_UPDATE)
+ bgp_bfd_update_peer(peer);
+ }
+ } else {
+ if (peer->status == Established
+ && command == ZEBRA_BFD_DEST_REGISTER)
+ bgp_bfd_register_peer(peer);
+ else if (command == ZEBRA_BFD_DEST_UPDATE)
+ bgp_bfd_update_peer(peer);
+ }
+
+ return 0;
+}
+
/*
* bgp_bfd_peer_config_write - Write the peer BFD configuration.
*/
@@ -580,8 +665,12 @@ void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
: "singlehop");
if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)
- && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
- vty_out(vty, " neighbor %s bfd\n", addr);
+ && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) {
+ vty_out(vty, " neighbor %s bfd", addr);
+ if (bfd_info->profile[0])
+ vty_out(vty, " profile %s", bfd_info->profile);
+ vty_out(vty, "\n");
+ }
if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
vty_out(vty, " neighbor %s bfd check-control-plane-failure\n", addr);
@@ -824,6 +913,58 @@ DEFUN_HIDDEN (no_neighbor_bfd_type,
return CMD_SUCCESS;
}
+#if HAVE_BFDD > 0
+DEFUN(neighbor_bfd_profile, neighbor_bfd_profile_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BFD integration\n"
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
+{
+ int idx_peer = 1, idx_prof = 4;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = bgp_bfd_peer_set_profile(peer, argv[idx_prof]->arg);
+ if (ret != 0)
+ return bgp_vty_return(vty, ret);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BFD integration\n"
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
+{
+ int idx_peer = 2;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!peer->bfd_info)
+ return 0;
+
+ ret = bgp_bfd_peer_set_profile(peer, NULL);
+ if (ret != 0)
+ return bgp_vty_return(vty, ret);
+
+ return CMD_SUCCESS;
+}
+#endif /* HAVE_BFDD */
+
void bgp_bfd_init(void)
{
bfd_gbl_init();
@@ -839,4 +980,9 @@ void bgp_bfd_init(void)
install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
install_element(BGP_NODE, &no_neighbor_bfd_cmd);
install_element(BGP_NODE, &no_neighbor_bfd_type_cmd);
+
+#if HAVE_BFDD > 0
+ install_element(BGP_NODE, &neighbor_bfd_profile_cmd);
+ install_element(BGP_NODE, &no_neighbor_bfd_profile_cmd);
+#endif /* HAVE_BFDD */
}