bfdd: implement minimum TTL

Initial BFD protocol implementation had a hard coded value of maximum 5
hops, now we have a configurable hop amount with a safe default of 1
hop.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2020-08-11 14:43:56 -03:00
parent abd1529680
commit 262e1d2528
10 changed files with 200 additions and 6 deletions

View File

@ -89,6 +89,7 @@ static void bfd_profile_set_default(struct bfd_profile *bp)
bp->detection_multiplier = BFD_DEFDETECTMULT;
bp->echo_mode = false;
bp->passive = false;
bp->minimum_ttl = BFD_DEF_MHOP_TTL;
bp->min_echo_rx = BFD_DEF_REQ_MIN_ECHO;
bp->min_rx = BFD_DEFREQUIREDMINRX;
bp->min_tx = BFD_DEFDESIREDMINTX;
@ -190,6 +191,12 @@ void bfd_session_apply(struct bfd_session *bs)
bfd_set_echo(bs, bp->echo_mode);
else
bfd_set_echo(bs, bs->peer_profile.echo_mode);
} else {
/* Configure the TTL packet filter. */
if (bs->peer_profile.minimum_ttl == BFD_DEF_MHOP_TTL)
bs->mh_ttl = bp->minimum_ttl;
else
bs->mh_ttl = bs->peer_profile.minimum_ttl;
}
/* Toggle 'passive-mode' if default value. */
@ -752,6 +759,11 @@ static void _bfd_session_update(struct bfd_session *bs,
else
UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT);
if (bpc->bpc_has_minimum_ttl) {
bs->mh_ttl = bpc->bpc_minimum_ttl;
bs->peer_profile.minimum_ttl = bpc->bpc_minimum_ttl;
}
bs->peer_profile.echo_mode = bpc->bpc_echo;
bfd_set_echo(bs, bpc->bpc_echo);

View File

@ -210,6 +210,8 @@ struct bfd_profile {
bool admin_shutdown;
/** Passive mode. */
bool passive;
/** Minimum expected TTL value. */
uint8_t minimum_ttl;
/** Echo mode (only applies to single hop). */
bool echo_mode;
@ -331,7 +333,8 @@ TAILQ_HEAD(obslist, bfd_session_observer);
#define BFD_DEFREQUIREDMINRX (300 * 1000) /* microseconds. */
#define BFD_DEF_REQ_MIN_ECHO (50 * 1000) /* microseconds. */
#define BFD_DEF_SLOWTX (1000 * 1000) /* microseconds. */
#define BFD_DEF_MHOP_TTL 5
/** Minimum multi hop TTL. */
#define BFD_DEF_MHOP_TTL 254
#define BFD_PKT_LEN 24 /* Length of control packet */
#define BFD_TTL_VAL 255
#define BFD_RCV_TTL_VAL 1

View File

@ -577,7 +577,7 @@ int bfd_recv_cb(struct thread *t)
return 0;
}
/* Validate packet TTL. */
/* Validate single hop packet TTL. */
if ((!is_mhop) && (ttl != BFD_TTL_VAL)) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
@ -630,10 +630,10 @@ int bfd_recv_cb(struct thread *t)
* Single hop: set local address that received the packet.
*/
if (is_mhop) {
if ((BFD_TTL_VAL - bfd->mh_ttl) > BFD_TTL_VAL) {
if (ttl < bfd->mh_ttl) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"exceeded max hop count (expected %d, got %d)",
bfd->mh_ttl, BFD_TTL_VAL);
bfd->mh_ttl, ttl);
return 0;
}
} else if (bfd->local_address.sa_sin.sin_family == AF_UNSPEC) {

View File

@ -84,6 +84,9 @@ struct bfd_peer_cfg {
bool bpc_has_echointerval;
uint64_t bpc_echointerval;
bool bpc_has_minimum_ttl;
uint8_t bpc_minimum_ttl;
bool bpc_echo;
bool bpc_createonly;
bool bpc_shutdown;

View File

@ -286,6 +286,42 @@ void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
}
DEFPY_YANG(
bfd_peer_minimum_ttl, bfd_peer_minimum_ttl_cmd,
"[no] minimum-ttl (1-254)$ttl",
NO_STR
"Expect packets with at least this TTL\n"
"Minimum TTL expected\n")
{
if (no)
nb_cli_enqueue_change(vty, "./minimum-ttl", NB_OP_DESTROY,
NULL);
else
nb_cli_enqueue_change(vty, "./minimum-ttl", NB_OP_MODIFY,
ttl_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_bfd_peer_minimum_ttl, no_bfd_peer_minimum_ttl_cmd,
"no minimum-ttl",
NO_STR
"Expect packets with at least this TTL\n")
{
nb_cli_enqueue_change(vty, "./minimum-ttl", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void bfd_cli_show_minimum_ttl(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
if (show_defaults)
vty_out(vty, " minimum-ttl 254\n");
else
vty_out(vty, " minimum-ttl %s\n",
yang_dnode_get_string(dnode, NULL));
}
DEFPY_YANG(
bfd_peer_mult, bfd_peer_mult_cmd,
"detect-multiplier (2-255)$multiplier",
@ -488,6 +524,17 @@ ALIAS_YANG(bfd_peer_passive, bfd_profile_passive_cmd,
NO_STR
"Don't attempt to start sessions\n")
ALIAS_YANG(bfd_peer_minimum_ttl, bfd_profile_minimum_ttl_cmd,
"[no] minimum-ttl (1-254)$ttl",
NO_STR
"Expect packets with at least this TTL\n"
"Minimum TTL expected\n")
ALIAS_YANG(no_bfd_peer_minimum_ttl, no_bfd_profile_minimum_ttl_cmd,
"no minimum-ttl",
NO_STR
"Expect packets with at least this TTL\n")
ALIAS_YANG(bfd_peer_echo, bfd_profile_echo_cmd,
"[no] echo-mode",
NO_STR
@ -557,6 +604,8 @@ bfdd_cli_init(void)
install_element(BFD_PEER_NODE, &bfd_peer_echo_interval_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_profile_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_passive_cmd);
install_element(BFD_PEER_NODE, &bfd_peer_minimum_ttl_cmd);
install_element(BFD_PEER_NODE, &no_bfd_peer_minimum_ttl_cmd);
/* Profile commands. */
cmd_variable_handler_register(bfd_vars);
@ -574,4 +623,6 @@ bfdd_cli_init(void)
install_element(BFD_PROFILE_NODE, &bfd_profile_echo_cmd);
install_element(BFD_PROFILE_NODE, &bfd_profile_echo_interval_cmd);
install_element(BFD_PROFILE_NODE, &bfd_profile_passive_cmd);
install_element(BFD_PROFILE_NODE, &bfd_profile_minimum_ttl_cmd);
install_element(BFD_PROFILE_NODE, &no_bfd_profile_minimum_ttl_cmd);
}

View File

@ -84,6 +84,14 @@ const struct frr_yang_module_info frr_bfdd_info = {
.cli_show = bfd_cli_show_passive,
}
},
{
.xpath = "/frr-bfdd:bfdd/bfd/profile/minimum-ttl",
.cbs = {
.modify = bfdd_bfd_profile_minimum_ttl_modify,
.destroy = bfdd_bfd_profile_minimum_ttl_destroy,
.cli_show = bfd_cli_show_minimum_ttl,
}
},
{
.xpath = "/frr-bfdd:bfdd/bfd/profile/echo-mode",
.cbs = {
@ -349,6 +357,14 @@ const struct frr_yang_module_info frr_bfdd_info = {
.cli_show = bfd_cli_show_passive,
}
},
{
.xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl",
.cbs = {
.modify = bfdd_bfd_sessions_multi_hop_minimum_ttl_modify,
.destroy = bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy,
.cli_show = bfd_cli_show_minimum_ttl,
}
},
{
.xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator",
.cbs = {

View File

@ -38,6 +38,8 @@ int bfdd_bfd_profile_required_receive_interval_modify(
struct nb_cb_modify_args *args);
int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args);
int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args);
int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args);
int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args *args);
int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args);
int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
struct nb_cb_modify_args *args);
@ -134,6 +136,10 @@ int bfdd_bfd_sessions_multi_hop_required_receive_interval_modify(
struct nb_cb_modify_args *args);
int bfdd_bfd_sessions_multi_hop_administrative_down_modify(
struct nb_cb_modify_args *args);
int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
struct nb_cb_modify_args *args);
int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
struct nb_cb_destroy_args *args);
struct yang_data *
bfdd_bfd_sessions_multi_hop_stats_local_discriminator_get_elem(
struct nb_cb_get_elem_args *args);
@ -211,5 +217,7 @@ void bfd_cli_peer_profile_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void bfd_cli_show_minimum_ttl(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
#endif /* _FRR_BFDD_NB_H_ */

View File

@ -381,6 +381,42 @@ int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
return NB_OK;
}
/*
* XPath: /frr-bfdd:bfdd/bfd/profile/minimum-ttl
*/
int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
{
struct bfd_profile *bp;
uint8_t minimum_ttl;
if (args->event != NB_EV_APPLY)
return NB_OK;
minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bp = nb_running_get_entry(args->dnode, NULL, true);
if (bp->minimum_ttl == minimum_ttl)
return NB_OK;
bp->minimum_ttl = minimum_ttl;
bfd_profile_update(bp);
return NB_OK;
}
int bfdd_bfd_profile_minimum_ttl_destroy(struct nb_cb_destroy_args *args)
{
struct bfd_profile *bp;
if (args->event != NB_EV_APPLY)
return NB_OK;
bp = nb_running_get_entry(args->dnode, NULL, true);
bp->minimum_ttl = BFD_DEF_MHOP_TTL;
bfd_profile_update(bp);
return NB_OK;
}
/*
* XPath: /frr-bfdd:bfdd/bfd/profile/echo-mode
*/
@ -739,3 +775,54 @@ int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
{
return bfd_session_destroy(args->event, args->dnode, true);
}
/*
* XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop/minimum-ttl
*/
int bfdd_bfd_sessions_multi_hop_minimum_ttl_modify(
struct nb_cb_modify_args *args)
{
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
return NB_OK;
case NB_EV_APPLY:
break;
case NB_EV_ABORT:
return NB_OK;
}
bs = nb_running_get_entry(args->dnode, NULL, true);
bs->peer_profile.minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
bfd_session_apply(bs);
return NB_OK;
}
int bfdd_bfd_sessions_multi_hop_minimum_ttl_destroy(
struct nb_cb_destroy_args *args)
{
struct bfd_session *bs;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
return NB_OK;
case NB_EV_APPLY:
break;
case NB_EV_ABORT:
return NB_OK;
}
bs = nb_running_get_entry(args->dnode, NULL, true);
bs->peer_profile.minimum_ttl = BFD_DEF_MHOP_TTL;
bfd_session_apply(bs);
return NB_OK;
}

View File

@ -115,6 +115,8 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
vty_out(vty, "\t\tPassive mode\n");
else
vty_out(vty, "\t\tActive mode\n");
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
vty_out(vty, "\t\tMinimum TTL: %d\n", bs->mh_ttl);
vty_out(vty, "\t\tStatus: ");
switch (bs->ses_state) {
@ -209,6 +211,8 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
json_object_boolean_add(jo, "passive-mode",
CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE));
if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
json_object_int_add(jo, "minimum-ttl", bs->mh_ttl);
switch (bs->ses_state) {
case PTM_BFD_ADM_DOWN:

View File

@ -303,7 +303,6 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
struct bfd_peer_cfg *bpc, struct ptm_client **pc)
{
uint32_t pid;
uint8_t ttl __attribute__((unused));
size_t ifnamelen;
/*
@ -375,7 +374,18 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
if (bpc->bpc_mhop) {
/* Read multihop source address and TTL. */
_ptm_msg_read_address(msg, &bpc->bpc_local);
STREAM_GETC(msg, ttl);
STREAM_GETC(msg, bpc->bpc_minimum_ttl);
if (bpc->bpc_minimum_ttl >= BFD_TTL_VAL
|| bpc->bpc_minimum_ttl == 0) {
zlog_warn("%s: received invalid TTL configuration %d",
__func__, bpc->bpc_has_minimum_ttl);
bpc->bpc_minimum_ttl = BFD_DEF_MHOP_TTL;
bpc->bpc_has_minimum_ttl = false;
} else {
bpc->bpc_minimum_ttl =
(BFD_TTL_VAL + 1) - bpc->bpc_minimum_ttl;
bpc->bpc_has_minimum_ttl = true;
}
} else {
/* If target is IPv6, then we must obtain local address. */
if (bpc->bpc_ipv4 == false)