bfd: add support for multihop

Type: feature

Change-Id: If23f9cc9317e7528f3c8d66303457206843a12c5
Signed-off-by: Abdel Baig <abdbaig@cisco.com>
This commit is contained in:
Abdel Baig 2024-09-03 11:52:20 -04:00 committed by Mirza Baig
parent 514098ee82
commit 17a918133b
11 changed files with 1734 additions and 519 deletions

View File

@ -359,6 +359,16 @@ autoreply define bfd_udp_auth_deactivate
bool is_delayed;
};
/** \brief BFD UDP - enable multihop support
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
autoreply define bfd_udp_enable_multihop
{
u32 client_index;
u32 context;
};
/* must be compatible with bfd_error_t */
counters bfd_udp {
none {

View File

@ -46,8 +46,24 @@ pub_sub_handler (bfd_events, BFD_EVENTS);
ip_address_decode(&mp->local_addr, &local_addr); \
ip_address_decode(&mp->peer_addr, &peer_addr);
#define BFD_UDP_API_PARAM_FROM_MP(mp) \
clib_net_to_host_u32 (mp->sw_if_index), &local_addr, &peer_addr
#define BFD_UDP_API_PARAM_IS_MH(mp) \
bfd_main.multihop_enabled && (mp->sw_if_index == ~0)
#define BFD_UDP_API_PARAM_FROM_MP(mp) \
BFD_UDP_API_PARAM_IS_MH (mp) ? true : false, \
BFD_UDP_API_PARAM_IS_MH (mp) ? ~0 : \
clib_net_to_host_u32 (mp->sw_if_index), \
&local_addr, &peer_addr
#define COND_VALIDATE_SW_IF_INDEX(mp) \
do \
{ \
if (!(bfd_main.multihop_enabled && mp->sw_if_index == ~0)) \
{ \
VALIDATE_SW_IF_INDEX (mp) \
} \
} \
while (0);
static void
vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp)
@ -55,7 +71,7 @@ vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp)
vl_api_bfd_udp_add_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -76,7 +92,7 @@ vl_api_bfd_udp_upd_t_handler (vl_api_bfd_udp_add_t *mp)
vl_api_bfd_udp_upd_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -97,7 +113,7 @@ vl_api_bfd_udp_mod_t_handler (vl_api_bfd_udp_mod_t * mp)
vl_api_bfd_udp_mod_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -116,7 +132,7 @@ vl_api_bfd_udp_del_t_handler (vl_api_bfd_udp_del_t * mp)
vl_api_bfd_udp_del_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -143,7 +159,14 @@ send_bfd_udp_session_details (vl_api_registration_t * reg, u32 context,
mp->state = clib_host_to_net_u32 (bs->local_state);
bfd_udp_session_t *bus = &bs->udp;
bfd_udp_key_t *key = &bus->key;
mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
if (bs->hop_type == BFD_HOP_TYPE_MULTI)
{
mp->sw_if_index = ~0;
}
else
{
mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
}
if ((!bs->auth.is_delayed && bs->auth.curr_key) ||
(bs->auth.is_delayed && bs->auth.next_key))
{
@ -186,7 +209,14 @@ send_bfd_udp_session_event (vl_api_registration_t *reg, u32 pid,
mp->state = clib_host_to_net_u32 (bs->local_state);
bfd_udp_session_t *bus = &bs->udp;
bfd_udp_key_t *key = &bus->key;
mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
if (bs->hop_type == BFD_HOP_TYPE_MULTI)
{
mp->sw_if_index = ~0;
}
else
{
mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
}
if ((!bs->auth.is_delayed && bs->auth.curr_key) ||
(bs->auth.is_delayed && bs->auth.next_key))
{
@ -315,7 +345,7 @@ vl_api_bfd_udp_auth_activate_t_handler (vl_api_bfd_udp_auth_activate_t * mp)
vl_api_bfd_udp_auth_activate_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -334,7 +364,7 @@ vl_api_bfd_udp_auth_deactivate_t_handler (vl_api_bfd_udp_auth_deactivate_t *
vl_api_bfd_udp_auth_deactivate_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
COND_VALIDATE_SW_IF_INDEX (mp);
BFD_UDP_API_PARAM_COMMON_CODE;
@ -423,6 +453,17 @@ vl_api_bfd_udp_get_echo_source_t_handler (vl_api_bfd_udp_get_echo_source_t *
}))
}
static void
vl_api_bfd_udp_enable_multihop_t_handler (vl_api_bfd_udp_enable_multihop_t *mp)
{
vl_api_bfd_udp_enable_multihop_reply_t *rmp;
int rv = 0;
bfd_main.multihop_enabled = true;
REPLY_MACRO (VL_API_BFD_UDP_ENABLE_MULTIHOP_REPLY);
}
#include <vnet/bfd/bfd.api.c>
static clib_error_t *
bfd_api_hookup (vlib_main_t * vm)

View File

@ -37,44 +37,49 @@ typedef enum
/**
* @brief create a new bfd session
*/
vnet_api_error_t
bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
u32 desired_min_tx_usec, u32 required_min_rx_usec,
u8 detect_mult, u8 is_authenticated, u32 conf_key_id,
u8 bfd_key_id);
vnet_api_error_t bfd_udp_add_session (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u32 desired_min_tx_usec,
u32 required_min_rx_usec, u8 detect_mult,
u8 is_authenticated, u32 conf_key_id,
u8 bfd_key_id);
/**
* @brief create a new or modify and existing bfd session
* @brief create a new or modify an existing bfd session
*/
vnet_api_error_t
bfd_udp_upd_session (u32 sw_if_index, const ip46_address_t *local_addr,
const ip46_address_t *peer_addr, u32 desired_min_tx_usec,
u32 required_min_rx_usec, u8 detect_mult,
u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id);
vnet_api_error_t bfd_udp_upd_session (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u32 desired_min_tx_usec,
u32 required_min_rx_usec, u8 detect_mult,
u8 is_authenticated, u32 conf_key_id,
u8 bfd_key_id);
/**
* @brief modify existing session
*/
vnet_api_error_t
bfd_udp_mod_session (u32 sw_if_index, const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
u32 desired_min_tx_usec, u32 required_min_rx_usec,
u8 detect_mult);
vnet_api_error_t bfd_udp_mod_session (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u32 desired_min_tx_usec,
u32 required_min_rx_usec,
u8 detect_mult);
/**
* @brief delete existing session
*/
vnet_api_error_t bfd_udp_del_session (u32 sw_if_index,
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr);
vnet_api_error_t bfd_udp_del_session (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr);
/**
* @brief set session admin down/up
*/
vnet_api_error_t bfd_udp_session_set_flags (vlib_main_t * vm, u32 sw_if_index,
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
vnet_api_error_t bfd_udp_session_set_flags (vlib_main_t *vm, bool multihop,
u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u8 admin_up_down);
/**
@ -91,18 +96,18 @@ vnet_api_error_t bfd_auth_del_key (u32 conf_key_id);
/**
* @brief activate authentication for existing session
*/
vnet_api_error_t bfd_udp_auth_activate (u32 sw_if_index,
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
vnet_api_error_t bfd_udp_auth_activate (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u32 conf_key_id, u8 bfd_key_id,
u8 is_delayed);
/**
* @brief deactivate authentication for existing session
*/
vnet_api_error_t bfd_udp_auth_deactivate (u32 sw_if_index,
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
vnet_api_error_t bfd_udp_auth_deactivate (bool multihop, u32 sw_if_index,
const ip46_address_t *local_addr,
const ip46_address_t *peer_addr,
u8 is_delayed);
/**

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,20 @@
#include <vlib/log.h>
#include <vnet/crypto/crypto.h>
const char *
bfd_hop_type_string (bfd_hop_type_e hoptype)
{
switch (hoptype)
{
#define F(x) \
case BFD_HOP_TYPE_##x: \
return "BFD_HOP_TYPE_" #x;
foreach_bfd_hop (F)
#undef F
}
return "UNKNOWN";
}
static void
bfd_validate_counters (bfd_main_t *bm)
{
@ -1353,6 +1367,8 @@ VLIB_REGISTER_NODE (bfd_process_node, static) =
[BFD_TX_IP6_REWRITE] = "ip6-rewrite",
[BFD_TX_IP4_MIDCHAIN] = "ip4-midchain",
[BFD_TX_IP6_MIDCHAIN] = "ip6-midchain",
[BFD_TX_IP4_LOOKUP] = "ip4-lookup",
[BFD_TX_IP6_LOOKUP] = "ip6-lookup",
}
};
// clang-format on
@ -2049,29 +2065,29 @@ u8 *
format_bfd_session (u8 * s, va_list * args)
{
const bfd_session_t *bs = va_arg (*args, bfd_session_t *);
s = format (s, "bs_idx=%u local-state=%s remote-state=%s\n"
"local-discriminator=%u remote-discriminator=%u\n"
"local-diag=%s echo-active=%s\n"
"desired-min-tx=%u required-min-rx=%u\n"
"required-min-echo-rx=%u detect-mult=%u\n"
"remote-min-rx=%u remote-min-echo-rx=%u\n"
"remote-demand=%s poll-state=%s\n"
"auth: local-seq-num=%u remote-seq-num=%u\n"
" is-delayed=%s\n"
" curr-key=%U\n"
" next-key=%U",
bs->bs_idx, bfd_state_string (bs->local_state),
bfd_state_string (bs->remote_state), bs->local_discr,
bs->remote_discr, bfd_diag_code_string (bs->local_diag),
(bs->echo ? "yes" : "no"), bs->config_desired_min_tx_usec,
bs->config_required_min_rx_usec, 1, bs->local_detect_mult,
bs->remote_min_rx_usec, bs->remote_min_echo_rx_usec,
(bs->remote_demand ? "yes" : "no"),
bfd_poll_state_string (bs->poll_state),
bs->auth.local_seq_number, bs->auth.remote_seq_number,
(bs->auth.is_delayed ? "yes" : "no"),
format_bfd_auth_key, bs->auth.curr_key, format_bfd_auth_key,
bs->auth.next_key);
s = format (
s,
"bs_idx=%u hop-type=%s local-state=%s remote-state=%s\n"
"local-discriminator=%u remote-discriminator=%u\n"
"local-diag=%s echo-active=%s\n"
"desired-min-tx=%u required-min-rx=%u\n"
"required-min-echo-rx=%u detect-mult=%u\n"
"remote-min-rx=%u remote-min-echo-rx=%u\n"
"remote-demand=%s poll-state=%s\n"
"auth: local-seq-num=%u remote-seq-num=%u\n"
" is-delayed=%s\n"
" curr-key=%U\n"
" next-key=%U",
bs->bs_idx, bfd_hop_type_string (bs->hop_type),
bfd_state_string (bs->local_state), bfd_state_string (bs->remote_state),
bs->local_discr, bs->remote_discr, bfd_diag_code_string (bs->local_diag),
(bs->echo ? "yes" : "no"), bs->config_desired_min_tx_usec,
bs->config_required_min_rx_usec, 1, bs->local_detect_mult,
bs->remote_min_rx_usec, bs->remote_min_echo_rx_usec,
(bs->remote_demand ? "yes" : "no"), bfd_poll_state_string (bs->poll_state),
bs->auth.local_seq_number, bs->auth.remote_seq_number,
(bs->auth.is_delayed ? "yes" : "no"), format_bfd_auth_key,
bs->auth.curr_key, format_bfd_auth_key, bs->auth.next_key);
return s;
}

View File

@ -71,13 +71,13 @@ typedef enum
/**
* hop types
*/
#define foreach_bfd_hop(F) \
F (SINGLE, "single") \
F (MULTI, "multi") \
#define foreach_bfd_hop(F) \
F (SINGLE) \
F (MULTI)
typedef enum
{
#define F(sym, str) BFD_HOP_TYPE_##sym,
#define F(sym) BFD_HOP_TYPE_##sym,
foreach_bfd_hop (F)
#undef F
} bfd_hop_type_e;
@ -318,6 +318,12 @@ typedef struct
/** vector of callback notification functions */
bfd_notify_fn_t *listeners;
/**
* true if multihop support is enabled so sw_if_index of ~0
* represents a multihop session
*/
bool multihop_enabled;
/** log class */
vlib_log_class_t log_class;
@ -449,6 +455,7 @@ vnet_api_error_t bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs,
u32 bfd_nsec_to_usec (u64 nsec);
const char *bfd_poll_state_string (bfd_poll_state_e state);
const char *bfd_hop_type_string (bfd_hop_type_e state);
#define USEC_PER_MS (1000LL)
#define MSEC_PER_SEC (1000LL)
@ -482,6 +489,8 @@ typedef enum
BFD_TX_IP6_REWRITE,
BFD_TX_IP4_MIDCHAIN,
BFD_TX_IP6_MIDCHAIN,
BFD_TX_IP4_LOOKUP,
BFD_TX_IP6_LOOKUP,
BFD_TX_N_NEXT,
} bfd_tx_next_t;

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,10 @@
/** identifier of BFD session based on UDP transport only */
typedef CLIB_PACKED (struct {
union {
/** interface to which the session is tied - single-hop */
u32 sw_if_index;
/** the FIB index the peer is in - multi-hop*/
u32 fib_index;
};
/** interface to which the session is tied - single-hop */
u16 sw_if_index;
/** the FIB index the peer is in - multi-hop*/
u16 fib_index;
/** local address */
ip46_address_t local_addr;
/** peer address */

View File

@ -18,42 +18,43 @@
#include <vnet/vnet.h>
#define foreach_udp4_dst_port \
_ (53, dns) \
_ (67, dhcp_to_server) \
_ (68, dhcp_to_client) \
_ (500, ikev2) \
_ (2152, GTPU) \
_ (3784, bfd4) \
_ (3785, bfd_echo4) \
_ (4341, lisp_gpe) \
_ (4342, lisp_cp) \
_ (4500, ipsec) \
_ (4739, ipfix) \
_ (4789, vxlan) \
_ (4789, vxlan6) \
_ (48879, vxlan_gbp) \
_ (4790, VXLAN_GPE) \
_ (6633, vpath_3) \
_ (6081, geneve) \
_ (53053, dns_reply)
#define foreach_udp4_dst_port \
_ (53, dns) \
_ (67, dhcp_to_server) \
_ (68, dhcp_to_client) \
_ (500, ikev2) \
_ (2152, GTPU) \
_ (3784, bfd4) \
_ (3785, bfd_echo4) \
_ (4341, lisp_gpe) \
_ (4342, lisp_cp) \
_ (4500, ipsec) \
_ (4739, ipfix) \
_ (4784, bfd4_mh) \
_ (4789, vxlan) \
_ (4789, vxlan6) \
_ (48879, vxlan_gbp) \
_ (4790, VXLAN_GPE) \
_ (6633, vpath_3) \
_ (6081, geneve) \
_ (53053, dns_reply)
#define foreach_udp6_dst_port \
_ (53, dns6) \
_ (547, dhcpv6_to_server) \
_ (546, dhcpv6_to_client) \
_ (2152, GTPU6) \
_ (3784, bfd6) \
_ (3785, bfd_echo6) \
_ (4341, lisp_gpe6) \
_ (4342, lisp_cp6) \
_ (48879, vxlan6_gbp) \
_ (4790, VXLAN6_GPE) \
_ (6633, vpath6_3) \
_ (6081, geneve6) \
_ (8138, BIER) \
_ (53053, dns_reply6)
#define foreach_udp6_dst_port \
_ (53, dns6) \
_ (547, dhcpv6_to_server) \
_ (546, dhcpv6_to_client) \
_ (2152, GTPU6) \
_ (3784, bfd6) \
_ (3785, bfd_echo6) \
_ (4341, lisp_gpe6) \
_ (4342, lisp_cp6) \
_ (48879, vxlan6_gbp) \
_ (4784, bfd6_mh) \
_ (4790, VXLAN6_GPE) \
_ (6633, vpath6_3) \
_ (6081, geneve6) \
_ (8138, BIER) \
_ (53053, dns_reply6)
typedef enum
{

View File

@ -17,6 +17,9 @@ from vpp_object import VppObject
from util import NumericConstant
from vpp_papi import VppEnum
BFD_UDP_SH_PORT = 3784
BFD_UDP_MH_PORT = 4784
class BFDDiagCode(NumericConstant):
"""BFD Diagnostic Code"""
@ -153,7 +156,8 @@ class BFD(Packet):
# glue the BFD packet class to scapy parser
bind_layers(UDP, BFD, dport=BFD.udp_dport)
bind_layers(UDP, BFD, dport=BFD_UDP_SH_PORT)
bind_layers(UDP, BFD, dport=BFD_UDP_MH_PORT)
class BFD_vpp_echo(Packet):
@ -248,6 +252,7 @@ class VppBFDUDPSession(VppObject):
test,
interface,
peer_addr,
multihop=False,
local_addr=None,
af=AF_INET,
desired_min_tx=300000,
@ -258,12 +263,24 @@ class VppBFDUDPSession(VppObject):
is_tunnel=False,
):
self._test = test
self._multihop = multihop
self._interface = interface
self._af = af
if multihop:
self._sw_if_index = 0xFFFFFFFF
self.test.vapi.bfd_udp_enable_multihop()
else:
self._sw_if_index = self._interface.sw_if_index
if local_addr:
self._local_addr = local_addr
else:
self._local_addr = None
if self.af == AF_INET:
self._local_addr = self.interface.local_ip4
else:
self._local_addr = self.interface.local_ip6
self._peer_addr = peer_addr
self._desired_min_tx = desired_min_tx
self._required_min_rx = required_min_rx
@ -312,17 +329,10 @@ class VppBFDUDPSession(VppObject):
result = self.test.vapi.bfd_udp_session_dump()
for s in result:
self.test.logger.debug("session entry: %s" % str(s))
if s.sw_if_index == self.interface.sw_if_index:
if (
self.af == AF_INET
and self.interface.local_ip4 == str(s.local_addr)
and self.interface.remote_ip4 == str(s.peer_addr)
):
return s
if (
self.af == AF_INET6
and self.interface.local_ip6 == str(s.local_addr)
and self.interface.remote_ip6 == str(s.peer_addr)
multihop = s.sw_if_index == ~0
if multihop or s.sw_if_index == self._sw_if_index:
if self._local_addr == str(s.local_addr) and self._peer_addr == str(
s.peer_addr
):
return s
return None
@ -371,7 +381,7 @@ class VppBFDUDPSession(VppObject):
conf_key_id = self._sha1_key.conf_key_id
is_delayed = 1 if delayed else 0
self.test.vapi.bfd_udp_auth_activate(
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
local_addr=self.local_addr,
peer_addr=self.peer_addr,
bfd_key_id=self._bfd_key_id,
@ -385,7 +395,7 @@ class VppBFDUDPSession(VppObject):
self._sha1_key = None
is_delayed = 1 if delayed else 0
self.test.vapi.bfd_udp_auth_deactivate(
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
local_addr=self.local_addr,
peer_addr=self.peer_addr,
is_delayed=is_delayed,
@ -402,7 +412,7 @@ class VppBFDUDPSession(VppObject):
if required_min_rx:
self._required_min_rx = required_min_rx
self.test.vapi.bfd_udp_mod(
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
desired_min_tx=self.desired_min_tx,
required_min_rx=self.required_min_rx,
detect_mult=self.detect_mult,
@ -415,7 +425,7 @@ class VppBFDUDPSession(VppObject):
conf_key_id = self._sha1_key.conf_key_id if self._sha1_key else None
is_authenticated = True if self._sha1_key else False
self.test.vapi.bfd_udp_add(
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
desired_min_tx=self.desired_min_tx,
required_min_rx=self.required_min_rx,
detect_mult=self.detect_mult,
@ -440,7 +450,7 @@ class VppBFDUDPSession(VppObject):
conf_key_id = self._sha1_key.conf_key_id if self._sha1_key else None
is_authenticated = True if self._sha1_key else False
self.test.vapi.bfd_udp_upd(
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
desired_min_tx=self.desired_min_tx,
required_min_rx=self.required_min_rx,
detect_mult=self.detect_mult,
@ -458,14 +468,15 @@ class VppBFDUDPSession(VppObject):
def remove_vpp_config(self):
self.test.vapi.bfd_udp_del(
self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
local_addr=self.local_addr,
peer_addr=self.peer_addr,
)
def object_id(self):
return "bfd-udp-%s-%s-%s-%s" % (
self._interface.sw_if_index,
return "bfd-udp-%s-%s-%s-%s-%s" % (
self._multihop,
self._sw_if_index,
self.local_addr,
self.peer_addr,
self.af,
@ -475,7 +486,7 @@ class VppBFDUDPSession(VppObject):
"""set bfd session admin-up"""
self.test.vapi.bfd_udp_session_set_flags(
flags=VppEnum.vl_api_if_status_flags_t.IF_STATUS_API_FLAG_ADMIN_UP,
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
local_addr=self.local_addr,
peer_addr=self.peer_addr,
)
@ -484,7 +495,7 @@ class VppBFDUDPSession(VppObject):
"""set bfd session admin-down"""
self.test.vapi.bfd_udp_session_set_flags(
flags=0,
sw_if_index=self._interface.sw_if_index,
sw_if_index=self._sw_if_index,
local_addr=self.local_addr,
peer_addr=self.peer_addr,
)

File diff suppressed because it is too large Load Diff