mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 13:21:22 +00:00
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:
parent
abd1529680
commit
262e1d2528
12
bfdd/bfd.c
12
bfdd/bfd.c
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user