+ BFD_DBG ("\nSession auth modified: %U", format_bfd_session, bs);
+ vlib_log_info (bm->log_class, "session auth modified: %U",
+ format_bfd_session_brief, bs);
+ return 0;
+#else
+ vlib_log_err (bm->log_class,
+ "SSL missing, cannot deactivate BFD authentication");
+ return VNET_API_ERROR_BFD_NOTSUPP;
+#endif
+}
+
+vnet_api_error_t
+bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs,
+ u32 desired_min_tx_usec,
+ u32 required_min_rx_usec, u8 detect_mult)
+{
+ if (bs->local_detect_mult != detect_mult ||
+ bs->config_desired_min_tx_usec != desired_min_tx_usec ||
+ bs->config_required_min_rx_usec != required_min_rx_usec)
+ {
+ BFD_DBG ("\nChanging session params: %U", format_bfd_session, bs);
+ switch (bs->poll_state)
+ {
+ case BFD_POLL_NOT_NEEDED:
+ if (BFD_STATE_up == bs->local_state ||
+ BFD_STATE_init == bs->local_state)
+ {
+ /* poll sequence is not needed for detect multiplier change */
+ if (bs->config_desired_min_tx_usec != desired_min_tx_usec ||
+ bs->config_required_min_rx_usec != required_min_rx_usec)
+ {
+ bfd_set_poll_state (bs, BFD_POLL_NEEDED);
+ }
+ }
+ break;
+ case BFD_POLL_NEEDED:
+ case BFD_POLL_IN_PROGRESS_AND_QUEUED:
+ /*
+ * nothing to do - will be handled in the future poll which is
+ * already scheduled for execution
+ */
+ break;
+ case BFD_POLL_IN_PROGRESS:
+ /* poll sequence is not needed for detect multiplier change */
+ if (bs->config_desired_min_tx_usec != desired_min_tx_usec ||
+ bs->config_required_min_rx_usec != required_min_rx_usec)
+ {
+ BFD_DBG ("Poll in progress, queueing extra poll, bs_idx=%u",
+ bs->bs_idx);
+ bfd_set_poll_state (bs, BFD_POLL_IN_PROGRESS_AND_QUEUED);
+ }
+ }
+
+ bs->local_detect_mult = detect_mult;
+ bs->config_desired_min_tx_usec = desired_min_tx_usec;
+ bs->config_desired_min_tx_clocks =
+ bfd_usec_to_clocks (bm, desired_min_tx_usec);
+ bs->config_required_min_rx_usec = required_min_rx_usec;
+ bs->config_required_min_rx_clocks =
+ bfd_usec_to_clocks (bm, required_min_rx_usec);
+ BFD_DBG ("\nChanged session params: %U", format_bfd_session, bs);
+
+ vlib_log_info (bm->log_class, "changed session params: %U",
+ format_bfd_session_brief, bs);
+ vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index,
+ BFD_EVENT_CONFIG_CHANGED, bs->bs_idx);
+ }
+ else
+ {
+ BFD_DBG ("Ignore parameter change - no change, bs_idx=%u", bs->bs_idx);
+ }
+ return 0;
+}
+
+vnet_api_error_t
+bfd_auth_set_key (u32 conf_key_id, u8 auth_type, u8 key_len,
+ const u8 * key_data)
+{
+ bfd_main_t *bm = &bfd_main;
+#if WITH_LIBSSL > 0
+ bfd_auth_key_t *auth_key = NULL;
+ if (!key_len || key_len > bfd_max_key_len_for_auth_type (auth_type))
+ {
+ vlib_log_err (bm->log_class,
+ "invalid authentication key length for auth_type=%d:%s "
+ "(key_len=%u, must be non-zero, expected max=%u)",
+ auth_type, bfd_auth_type_str (auth_type), key_len,
+ (u32) bfd_max_key_len_for_auth_type (auth_type));
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+ if (!bfd_auth_type_supported (auth_type))
+ {
+ vlib_log_err (bm->log_class, "unsupported auth type=%d:%s", auth_type,
+ bfd_auth_type_str (auth_type));
+ return VNET_API_ERROR_BFD_NOTSUPP;
+ }
+ uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
+ if (key_idx_p)
+ {
+ /* modifying existing key - must not be used */
+ const uword key_idx = *key_idx_p;
+ auth_key = pool_elt_at_index (bm->auth_keys, key_idx);
+ if (auth_key->use_count > 0)
+ {
+ vlib_log_err (bm->log_class,
+ "authentication key with conf ID %u in use by %u BFD "
+ "session(s) - cannot modify", conf_key_id,
+ auth_key->use_count);
+ return VNET_API_ERROR_BFD_EINUSE;
+ }
+ }
+ else
+ {
+ /* adding new key */
+ pool_get (bm->auth_keys, auth_key);
+ auth_key->conf_key_id = conf_key_id;
+ hash_set (bm->auth_key_by_conf_key_id, conf_key_id,
+ auth_key - bm->auth_keys);
+ }
+ auth_key->auth_type = auth_type;
+ clib_memset (auth_key->key, 0, sizeof (auth_key->key));
+ clib_memcpy (auth_key->key, key_data, key_len);
+ return 0;
+#else
+ vlib_log_err (bm->log_class,
+ "SSL missing, cannot manipulate authentication keys");
+ return VNET_API_ERROR_BFD_NOTSUPP;
+#endif
+}
+
+vnet_api_error_t
+bfd_auth_del_key (u32 conf_key_id)
+{
+#if WITH_LIBSSL > 0
+ bfd_auth_key_t *auth_key = NULL;
+ bfd_main_t *bm = &bfd_main;
+ uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
+ if (key_idx_p)
+ {
+ /* deleting existing key - must not be used */
+ const uword key_idx = *key_idx_p;
+ auth_key = pool_elt_at_index (bm->auth_keys, key_idx);
+ if (auth_key->use_count > 0)
+ {
+ vlib_log_err (bm->log_class,
+ "authentication key with conf ID %u in use by %u BFD "
+ "session(s) - cannot delete", conf_key_id,
+ auth_key->use_count);
+ return VNET_API_ERROR_BFD_EINUSE;
+ }
+ hash_unset (bm->auth_key_by_conf_key_id, conf_key_id);
+ clib_memset (auth_key, 0, sizeof (*auth_key));
+ pool_put (bm->auth_keys, auth_key);
+ }
+ else
+ {
+ /* no such key */
+ vlib_log_err (bm->log_class,
+ "authentication key with conf ID %u does not exist",
+ conf_key_id);
+ return VNET_API_ERROR_BFD_ENOENT;
+ }