diff options
author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-08-11 19:43:56 +0200 |
---|---|---|
committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-08-12 02:22:39 +0200 |
commit | 262e1d2528e866d5608a3cf337c7761e35160926 (patch) | |
tree | ba8a99ce918626978c4c99d7ffe8ecaf7f58dd0b /bfdd | |
parent | doc: add BFD passive mode documentation (diff) | |
download | frr-262e1d2528e866d5608a3cf337c7761e35160926.tar.xz frr-262e1d2528e866d5608a3cf337c7761e35160926.zip |
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>
Diffstat (limited to 'bfdd')
-rw-r--r-- | bfdd/bfd.c | 12 | ||||
-rw-r--r-- | bfdd/bfd.h | 5 | ||||
-rw-r--r-- | bfdd/bfd_packet.c | 6 | ||||
-rw-r--r-- | bfdd/bfdctl.h | 3 | ||||
-rw-r--r-- | bfdd/bfdd_cli.c | 51 | ||||
-rw-r--r-- | bfdd/bfdd_nb.c | 16 | ||||
-rw-r--r-- | bfdd/bfdd_nb.h | 8 | ||||
-rw-r--r-- | bfdd/bfdd_nb_config.c | 87 | ||||
-rw-r--r-- | bfdd/bfdd_vty.c | 4 | ||||
-rw-r--r-- | bfdd/ptm_adapter.c | 14 |
10 files changed, 200 insertions, 6 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 1fc922475..2b3caa6fe 100644 --- a/bfdd/bfd.c +++ b/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); diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 4f88e6b2e..af3f92d6a 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -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 diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 68bdd89bb..38855acff 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -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) { diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h index 3cb2fba49..e1cff9a31 100644 --- a/bfdd/bfdctl.h +++ b/bfdd/bfdctl.h @@ -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; diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index e70354de0..058ce7d1f 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -287,6 +287,42 @@ void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode, } 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", "Configure peer detection multiplier\n" @@ -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); } diff --git a/bfdd/bfdd_nb.c b/bfdd/bfdd_nb.c index cf063f82f..64ba3cf81 100644 --- a/bfdd/bfdd_nb.c +++ b/bfdd/bfdd_nb.c @@ -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 = { @@ -350,6 +358,14 @@ const struct frr_yang_module_info frr_bfdd_info = { } }, { + .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 = { .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, diff --git a/bfdd/bfdd_nb.h b/bfdd/bfdd_nb.h index ec467f357..fbd557b6b 100644 --- a/bfdd/bfdd_nb.h +++ b/bfdd/bfdd_nb.h @@ -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_ */ diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index 527c6d83a..0046bc625 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -382,6 +382,42 @@ int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args) } /* + * 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 */ int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args) @@ -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; +} diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index a532b76f0..a3f1638e5 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -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: diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 8134807a1..48e55bce3 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -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) |