extern struct zclient *zclient;
-/*
- * ospf6_bfd_info_free - Free BFD info structure
- */
-void ospf6_bfd_info_free(void **bfd_info)
-{
- bfd_info_free((struct bfd_info **)bfd_info);
-}
-
-/*
- * ospf6_bfd_show_info - Show BFD info structure
- */
-void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only,
- json_object *json_obj, bool use_json)
-{
- if (param_only)
- bfd_show_param(vty, bfd_info, 1, 0, use_json, json_obj);
- else
- bfd_show_info(vty, bfd_info, 0, 1, use_json, json_obj);
-}
-
-/*
- * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
- * zebra for starting/stopping the monitoring of
- * the neighbor rechahability.
- */
-void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command)
-{
- struct ospf6_interface *oi = on->ospf6_if;
- struct interface *ifp = oi->interface;
- struct bfd_info *bfd_info;
- char src[64];
- int cbit;
-
- if (!oi->bfd_info || !on->bfd_info)
- return;
- bfd_info = (struct bfd_info *)oi->bfd_info;
-
- if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
- inet_ntop(AF_INET6, &on->linklocal_addr, src, sizeof(src));
- zlog_debug("%s nbr (%s) with BFD",
- bfd_get_command_dbg_str(command), src);
- }
-
- cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
-
- bfd_peer_sendmsg(zclient, bfd_info, AF_INET6, &on->linklocal_addr,
- on->ospf6_if->linklocal_addr, ifp->name, 0, 0, cbit,
- command, 0, ifp->vrf_id);
-
- if (command == ZEBRA_BFD_DEST_DEREGISTER)
- bfd_info_free((struct bfd_info **)&on->bfd_info);
-}
-
/*
* ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
* neighbor state is changed to/from 2way.
void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state,
int state)
{
- if ((old_state < OSPF6_NEIGHBOR_TWOWAY)
- && (state >= OSPF6_NEIGHBOR_TWOWAY))
- ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER);
- else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY)
- && (state < OSPF6_NEIGHBOR_TWOWAY))
- ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER);
+ int family;
+ struct in6_addr src, dst;
+
+ /* Skip sessions without BFD. */
+ if (on->bfd_session == NULL)
+ return;
+
+ if (old_state < OSPF6_NEIGHBOR_TWOWAY
+ && state >= OSPF6_NEIGHBOR_TWOWAY) {
+ /*
+ * Check if neighbor address changed.
+ *
+ * When the neighbor is configured BFD before having an existing
+ * connection, then the destination address will be set to `::`
+ * which will cause session installation failure. This piece of
+ * code updates the address in that case.
+ */
+ bfd_sess_addresses(on->bfd_session, &family, &src, &dst);
+ if (memcmp(&on->linklocal_addr, &dst, sizeof(dst))) {
+ bfd_sess_set_ipv6_addrs(on->bfd_session, &src,
+ &on->linklocal_addr);
+ }
+
+ bfd_sess_install(on->bfd_session);
+ } else if (old_state >= OSPF6_NEIGHBOR_TWOWAY
+ && state < OSPF6_NEIGHBOR_TWOWAY)
+ bfd_sess_uninstall(on->bfd_session);
}
/*
* zebra for starting/stopping the monitoring of
* the neighbor rechahability.
*/
-static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi, int command)
+static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi,
+ bool install)
{
struct ospf6_neighbor *on;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
- if (command == ZEBRA_BFD_DEST_REGISTER)
- ospf6_bfd_info_nbr_create(oi, on);
-
- if (on->state < OSPF6_NEIGHBOR_TWOWAY) {
- if (command == ZEBRA_BFD_DEST_DEREGISTER)
- bfd_info_free(
- (struct bfd_info **)&on->bfd_info);
+ /* Remove all sessions. */
+ if (!install) {
+ bfd_sess_free(&on->bfd_session);
continue;
}
- ospf6_bfd_reg_dereg_nbr(on, command);
- }
-}
-
-/*
- * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
- * to zebra
- */
-static int ospf6_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
-{
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
- struct listnode *node;
- struct interface *ifp;
- struct ospf6_interface *oi;
- struct ospf6_neighbor *on;
- char dst[64];
-
- if (IS_OSPF6_DEBUG_ZEBRA(RECV))
- zlog_debug("Zebra: BFD Dest replay request");
-
- /* Send the client registration */
- bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
-
- /* Replay the neighbor, if BFD is enabled on the interface*/
- FOR_ALL_INTERFACES (vrf, ifp) {
- oi = (struct ospf6_interface *)ifp->info;
+ /* Always allocate session data even if not enabled. */
+ ospf6_bfd_info_nbr_create(oi, on);
- if (!oi || !oi->bfd_info)
+ /*
+ * If not connected yet, don't create any session but defer it
+ * for later. See function `ospf6_bfd_trigger_event`.
+ */
+ if (on->state < OSPF6_NEIGHBOR_TWOWAY)
continue;
- for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
- if (on->state < OSPF6_NEIGHBOR_TWOWAY)
- continue;
-
- if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
- inet_ntop(AF_INET6, &on->linklocal_addr, dst,
- sizeof(dst));
- zlog_debug("Replaying nbr (%s) to BFD", dst);
- }
-
- ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE);
- }
+ bfd_sess_install(on->bfd_session);
}
- return 0;
}
-/*
- * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
- * has changed and bring down the neighbor
- * connectivity if BFD down is received.
- */
-static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
+static void ospf6_bfd_callback(struct bfd_session_params *bsp,
+ const struct bfd_session_status *bss, void *arg)
{
- struct interface *ifp;
- struct ospf6_interface *oi;
- struct ospf6_neighbor *on;
- struct prefix dp;
- struct prefix sp;
- struct listnode *node, *nnode;
- char dst[64];
- int status;
- int old_status;
- struct bfd_info *bfd_info;
- struct timeval tv;
-
- ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status,
- NULL, vrf_id);
-
- if ((ifp == NULL) || (dp.family != AF_INET6))
- return 0;
-
- if (IS_OSPF6_DEBUG_ZEBRA(RECV))
- zlog_debug("Zebra: interface %s bfd destination %pFX %s",
- ifp->name, &dp, bfd_get_status_str(status));
-
-
- oi = (struct ospf6_interface *)ifp->info;
- if (!oi || !oi->bfd_info)
- return 0;
-
- for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
- if (memcmp(&(on->linklocal_addr), &dp.u.prefix6,
- sizeof(struct in6_addr)))
- continue;
-
- if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) {
- inet_ntop(AF_INET6, &on->linklocal_addr, dst,
- sizeof(dst));
- zlog_debug("[%s:%s]: BFD %s", ifp->name, dst,
- bfd_get_status_str(status));
- }
-
- if (!on->bfd_info)
- continue;
-
- bfd_info = (struct bfd_info *)on->bfd_info;
- if (bfd_info->status == status)
- continue;
-
- old_status = bfd_info->status;
- BFD_SET_CLIENT_STATUS(bfd_info->status, status);
- monotime(&tv);
- bfd_info->last_update = tv.tv_sec;
+ struct ospf6_neighbor *on = arg;
- if ((status == BFD_STATUS_DOWN)
- && (old_status == BFD_STATUS_UP)) {
- THREAD_OFF(on->inactivity_timer);
- thread_add_event(master, inactivity_timer, on, 0, NULL);
- }
+ if (bss->state == BFD_STATUS_DOWN
+ && bss->previous_state == BFD_STATUS_UP) {
+ THREAD_OFF(on->inactivity_timer);
+ thread_add_event(master, inactivity_timer, on, 0, NULL);
}
-
- return 0;
}
/*
void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
struct ospf6_neighbor *on)
{
- struct bfd_info *oi_bfd_info;
- struct bfd_info *on_bfd_info;
-
- if (!oi->bfd_info)
+ if (!oi->bfd_config.enabled)
return;
- oi_bfd_info = (struct bfd_info *)oi->bfd_info;
+ if (on->bfd_session == NULL)
+ on->bfd_session = bfd_sess_new(ospf6_bfd_callback, on);
- if (!on->bfd_info)
- on->bfd_info = bfd_info_create();
-
- on_bfd_info = (struct bfd_info *)on->bfd_info;
- on_bfd_info->detect_mult = oi_bfd_info->detect_mult;
- on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
- on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
+ bfd_sess_set_timers(on->bfd_session,
+ oi->bfd_config.detection_multiplier,
+ oi->bfd_config.min_rx, oi->bfd_config.min_tx);
+ bfd_sess_set_ipv6_addrs(on->bfd_session, on->ospf6_if->linklocal_addr,
+ &on->linklocal_addr);
+ bfd_sess_set_interface(on->bfd_session, oi->interface->name);
+ bfd_sess_set_profile(on->bfd_session, oi->bfd_config.profile);
}
/*
*/
void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi)
{
-#if HAVE_BFDD == 0
- struct bfd_info *bfd_info;
-#endif /* ! HAVE_BFDD */
-
- if (!oi->bfd_info)
+ if (!oi->bfd_config.enabled)
return;
#if HAVE_BFDD == 0
- bfd_info = (struct bfd_info *)oi->bfd_info;
-
- if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
+ if (oi->bfd_config.detection_multiplier != BFD_DEF_DETECT_MULT
+ || oi->bfd_config.min_rx != BFD_DEF_MIN_RX
+ || oi->bfd_config.min_tx != BFD_DEF_MIN_TX)
vty_out(vty, " ipv6 ospf6 bfd %d %d %d\n",
- bfd_info->detect_mult, bfd_info->required_min_rx,
- bfd_info->desired_min_tx);
+ oi->bfd_config.detection_multiplier,
+ oi->bfd_config.min_rx, oi->bfd_config.min_tx);
else
#endif /* ! HAVE_BFDD */
vty_out(vty, " ipv6 ospf6 bfd\n");
}
-/*
- * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
- * interface.
- */
-static void ospf6_bfd_if_param_set(struct ospf6_interface *oi, uint32_t min_rx,
- uint32_t min_tx, uint8_t detect_mult,
- int defaults)
-{
- int command = 0;
-
- bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx,
- detect_mult, NULL, defaults, &command);
- if (command)
- ospf6_bfd_reg_dereg_all_nbr(oi, command);
-}
-
DEFUN (ipv6_ospf6_bfd,
ipv6_ospf6_bfd_cmd,
"ipv6 ospf6 bfd",
oi = ospf6_interface_create(ifp);
assert(oi);
- ospf6_bfd_if_param_set(oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
- BFD_DEF_DETECT_MULT, 1);
+ oi->bfd_config.detection_multiplier = BFD_DEF_DETECT_MULT;
+ oi->bfd_config.min_rx = BFD_DEF_MIN_RX;
+ oi->bfd_config.min_tx = BFD_DEF_MIN_TX;
+ oi->bfd_config.enabled = true;
+
+ ospf6_bfd_reg_dereg_all_nbr(oi, true);
+
return CMD_SUCCESS;
}
int idx_number_2 = 4;
int idx_number_3 = 5;
struct ospf6_interface *oi;
- uint32_t rx_val;
- uint32_t tx_val;
- uint8_t dm_val;
- int ret;
assert(ifp);
oi = ospf6_interface_create(ifp);
assert(oi);
- if ((ret = bfd_validate_param(
- vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
- != CMD_SUCCESS)
- return ret;
+ oi->bfd_config.detection_multiplier =
+ strtoul(argv[idx_number]->arg, NULL, 10);
+ oi->bfd_config.min_rx = strtoul(argv[idx_number_2]->arg, NULL, 10);
+ oi->bfd_config.min_tx = strtoul(argv[idx_number_3]->arg, NULL, 10);
+ oi->bfd_config.enabled = true;
- ospf6_bfd_if_param_set(oi, rx_val, tx_val, dm_val, 0);
+ ospf6_bfd_reg_dereg_all_nbr(oi, true);
return CMD_SUCCESS;
}
oi = ospf6_interface_create(ifp);
assert(oi);
- if (oi->bfd_info) {
- ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
- bfd_info_free((struct bfd_info **)&(oi->bfd_info));
- }
+ oi->bfd_config.enabled = false;
+ ospf6_bfd_reg_dereg_all_nbr(oi, false);
return CMD_SUCCESS;
}
void ospf6_bfd_init(void)
{
- bfd_gbl_init();
-
- /* Initialize BFD client functions */
- zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
- zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
+ bfd_protocol_integration_init(zclient, master);
/* Install BFD command */
install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);