BFD: echo function

Change-Id: Ib1e301d62b687d4e42434239e7cd412065c28da0
Signed-off-by: Klement Sekera <ksekera@cisco.com>
This commit is contained in:
Klement Sekera
2017-02-16 10:53:53 +01:00
committed by Damjan Marion
parent 263440e789
commit 239790fd91
12 changed files with 1322 additions and 370 deletions

View File

@ -13,29 +13,43 @@
* limitations under the License.
*/
/** \brief Configure BFD feature
/** \brief Set BFD echo source
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param slow_timer - slow timer (seconds)
@param min_tx - desired min tx interval
@param min_rx - desired min rx interval
@param detect_mult - desired detection multiplier
@param sw_if_index - interface to use as echo source
*/
define bfd_set_config
define bfd_udp_set_echo_source
{
u32 client_index;
u32 context;
u32 slow_timer;
u32 min_tx;
u32 min_rx;
u8 detect_mult;
u32 sw_if_index;
};
/** \brief Configure BFD feature response
/** \brief Set BFD feature response
@param context - sender context, to match reply w/ request
@param retval - return code for the request
*/
define bfd_set_config_reply
define bfd_udp_set_echo_source_reply
{
u32 context;
i32 retval;
};
/** \brief Delete BFD echo source
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
define bfd_udp_del_echo_source
{
u32 client_index;
u32 context;
};
/** \brief Delete BFD feature response
@param context - sender context, to match reply w/ request
@param retval - return code for the request
*/
define bfd_udp_del_echo_source_reply
{
u32 context;
i32 retval;

View File

@ -54,7 +54,9 @@
_ (BFD_AUTH_DEL_KEY, bfd_auth_del_key) \
_ (BFD_AUTH_KEYS_DUMP, bfd_auth_keys_dump) \
_ (BFD_UDP_AUTH_ACTIVATE, bfd_udp_auth_activate) \
_ (BFD_UDP_AUTH_DEACTIVATE, bfd_udp_auth_deactivate)
_ (BFD_UDP_AUTH_DEACTIVATE, bfd_udp_auth_deactivate) \
_ (BFD_UDP_SET_ECHO_SOURCE, bfd_udp_set_echo_source) \
_ (BFD_UDP_DEL_ECHO_SOURCE, bfd_udp_del_echo_source)
pub_sub_handler (bfd_events, BFD_EVENTS);
@ -314,6 +316,33 @@ vl_api_bfd_udp_auth_deactivate_t_handler (vl_api_bfd_udp_auth_deactivate_t *
REPLY_MACRO (VL_API_BFD_UDP_AUTH_DEACTIVATE_REPLY);
}
static void
vl_api_bfd_udp_set_echo_source_t_handler (vl_api_bfd_udp_set_echo_source_t *
mp)
{
vl_api_bfd_udp_set_echo_source_reply_t *rmp;
int rv;
VALIDATE_SW_IF_INDEX (mp);
rv = bfd_udp_set_echo_source (clib_net_to_host_u32 (mp->sw_if_index));
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_BFD_UDP_SET_ECHO_SOURCE_REPLY);
}
static void
vl_api_bfd_udp_del_echo_source_t_handler (vl_api_bfd_udp_del_echo_source_t *
mp)
{
vl_api_bfd_udp_del_echo_source_reply_t *rmp;
int rv;
rv = bfd_udp_del_echo_source ();
REPLY_MACRO (VL_API_BFD_UDP_DEL_ECHO_SOURCE_REPLY);
}
/*
* bfd_api_hookup
* Add vpe's API message handlers to the table.

View File

@ -24,6 +24,17 @@
#include <vnet/ip/ip6_packet.h>
#include <vnet/bfd/bfd_udp.h>
#define foreach_bfd_transport(F) \
F (UDP4, "ip4-rewrite") \
F (UDP6, "ip6-rewrite")
typedef enum
{
#define F(t, n) BFD_TRANSPORT_##t,
foreach_bfd_transport (F)
#undef F
} bfd_transport_e;
vnet_api_error_t
bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr,
const ip46_address_t * peer_addr,
@ -31,12 +42,11 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr,
u8 detect_mult, u8 is_authenticated, u32 conf_key_id,
u8 bfd_key_id);
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 (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_del_session (u32 sw_if_index,
const ip46_address_t * local_addr,
@ -63,6 +73,10 @@ vnet_api_error_t bfd_udp_auth_deactivate (u32 sw_if_index,
const ip46_address_t * peer_addr,
u8 is_delayed);
vnet_api_error_t bfd_udp_set_echo_source (u32 loopback_sw_if_index);
vnet_api_error_t bfd_udp_del_echo_source ();
#endif /* __included_bfd_api_h__ */
/*

View File

@ -20,7 +20,7 @@
#define __included_bfd_debug_h__
/* controls debug prints */
#define BFD_DEBUG (0)
#define BFD_DEBUG (1)
#if BFD_DEBUG
#define BFD_DEBUG_FILE_DEF \

File diff suppressed because it is too large Load Diff

View File

@ -24,17 +24,6 @@
#include <vnet/bfd/bfd_protocol.h>
#include <vnet/bfd/bfd_udp.h>
#define foreach_bfd_transport(F) \
F (UDP4, "ip4-rewrite") \
F (UDP6, "ip6-rewrite")
typedef enum
{
#define F(t, n) BFD_TRANSPORT_##t,
foreach_bfd_transport (F)
#undef F
} bfd_transport_t;
#define foreach_bfd_mode(F) \
F (asynchronous) \
F (demand)
@ -64,14 +53,15 @@ typedef struct
bfd_auth_type_e auth_type;
} bfd_auth_key_t;
#define foreach_bfd_poll_state(F)\
F(NOT_NEEDED)\
F(NEEDED)\
F(IN_PROGRESS)
#define foreach_bfd_poll_state(F) \
F (NOT_NEEDED) \
F (NEEDED) \
F (IN_PROGRESS) \
F (IN_PROGRESS_AND_QUEUED)
typedef enum
{
#define F(x) POLL_##x,
#define F(x) BFD_POLL_##x,
foreach_bfd_poll_state (F)
#undef F
} bfd_poll_state_e;
@ -120,21 +110,27 @@ typedef struct bfd_session_s
/* remote min rx interval (clocks) */
u64 remote_min_rx_clocks;
/* remote min echo rx interval (microseconds) */
u64 remote_min_echo_rx_usec;
/* remote min echo rx interval (clocks) */
u64 remote_min_echo_rx_clocks;
/* remote desired min tx interval (clocks) */
u64 remote_desired_min_tx_clocks;
/* configured detect multiplier */
u8 local_detect_mult;
/* 1 if in demand mode, 0 otherwise */
u8 local_demand;
/* 1 if remote system sets demand mode, 0 otherwise */
u8 remote_demand;
/* remote detect multiplier */
u8 remote_detect_mult;
/* 1 is echo function is active, 0 otherwise */
u8 echo;
/* set to value of timer in timing wheel, 0 if never set */
u64 wheel_time_clocks;
@ -150,12 +146,33 @@ typedef struct bfd_session_s
/* timestamp of last packet received */
u64 last_rx_clocks;
/* transmit interval for echo packets */
u64 echo_transmit_interval_clocks;
/* next time at which to transmit echo packet */
u64 echo_tx_timeout_clocks;
/* timestamp of last echo packet transmitted */
u64 echo_last_tx_clocks;
/* timestamp of last echo packet received */
u64 echo_last_rx_clocks;
/* secret used for calculating/checking checksum of echo packets */
u32 echo_secret;
/* detection time */
u64 detection_time_clocks;
/* state info regarding poll sequence */
bfd_poll_state_e poll_state;
/*
* helper for delayed poll sequence - marks either start of running poll
* sequence or timeout, after which we can start the next poll sequnce
*/
u64 poll_state_start_or_timeout_clocks;
/* authentication information */
struct
{
@ -191,7 +208,7 @@ typedef struct bfd_session_s
} auth;
/* transport type for this session */
bfd_transport_t transport;
bfd_transport_e transport;
/* union of transport-specific data */
union
@ -227,6 +244,9 @@ typedef struct
/* default desired min tx in clocks */
u64 default_desired_min_tx_clocks;
/* minimum required min rx while echo function is active - clocks */
u64 min_required_min_rx_while_echo_clocks;
/* for generating random numbers */
u32 random_seed;
@ -268,36 +288,54 @@ enum
BFD_EVENT_CONFIG_CHANGED,
} bfd_process_event_e;
u8 *bfd_input_format_trace (u8 * s, va_list * args);
/* echo packet structure */
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
/* local discriminator */
u32 discriminator;
/* expire time of this packet - clocks */
u64 expire_time_clocks;
/* checksum - based on discriminator, local secret and expire time */
u64 checksum;
}) bfd_echo_pkt_t;
/* *INDENT-ON* */
bfd_session_t *bfd_get_session (bfd_main_t * bm, bfd_transport_t t);
u8 *bfd_input_format_trace (u8 * s, va_list * args);
bfd_session_t *bfd_get_session (bfd_main_t * bm, bfd_transport_e t);
void bfd_put_session (bfd_main_t * bm, bfd_session_t * bs);
bfd_session_t *bfd_find_session_by_idx (bfd_main_t * bm, uword bs_idx);
bfd_session_t *bfd_find_session_by_disc (bfd_main_t * bm, u32 disc);
void bfd_session_start (bfd_main_t * bm, bfd_session_t * bs);
void bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * bfd, u32 bs_idx);
int bfd_consume_echo_pkt (bfd_main_t * bm, vlib_buffer_t * b);
int bfd_verify_pkt_common (const bfd_pkt_t * pkt);
int bfd_verify_pkt_auth (const bfd_pkt_t * pkt, u16 pkt_size,
bfd_session_t * bs);
void bfd_event (bfd_main_t * bm, bfd_session_t * bs);
void bfd_init_final_control_frame (vlib_main_t * vm, vlib_buffer_t * b,
bfd_session_t * bs);
bfd_main_t * bm, bfd_session_t * bs);
u8 *format_bfd_session (u8 * s, va_list * args);
void bfd_session_set_flags (bfd_session_t * bs, u8 admin_up_down);
unsigned bfd_auth_type_supported (bfd_auth_type_e auth_type);
vnet_api_error_t bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id,
u8 bfd_key_id, u8 is_delayed);
vnet_api_error_t bfd_auth_deactivate (bfd_session_t * bs, u8 is_delayed);
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);
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);
#define USEC_PER_MS 1000LL
#define USEC_PER_SECOND (1000 * USEC_PER_MS)
/* default, slow transmission interval for BFD packets, per spec at least 1s */
#define BFD_DEFAULT_DESIRED_MIN_TX_US USEC_PER_SECOND
#define BFD_DEFAULT_DESIRED_MIN_TX_USEC USEC_PER_SECOND
/*
* minimum required min rx set locally when echo function is used, per spec
* should be set to at least 1s
*/
#define BFD_REQUIRED_MIN_RX_USEC_WHILE_ECHO USEC_PER_SECOND
#endif /* __included_bfd_main_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,7 @@
#include <vppinfra/clib.h>
#include <vnet/adj/adj_types.h>
#include <vnet/ip/ip6_packet.h>
#include <vnet/bfd/bfd_api.h>
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
@ -49,10 +50,17 @@ typedef struct
struct bfd_session_s;
void bfd_add_udp4_transport (vlib_main_t * vm, vlib_buffer_t * b,
const struct bfd_session_s *bs);
void bfd_add_udp6_transport (vlib_main_t * vm, vlib_buffer_t * b,
const struct bfd_session_s *bs);
int bfd_add_udp4_transport (vlib_main_t * vm, vlib_buffer_t * b,
const struct bfd_session_s *bs, int is_echo);
int bfd_add_udp6_transport (vlib_main_t * vm, vlib_buffer_t * b,
const struct bfd_session_s *bs, int is_echo);
/**
* @brief check if the bfd udp layer is echo-capable at this time
*
* @return 1 if available, 0 otherwise
*/
int bfd_udp_is_echo_available (bfd_transport_e transport);
#endif /* __included_bfd_udp_h__ */

View File

@ -152,6 +152,27 @@ class BFD(Packet):
bind_layers(UDP, BFD, dport=BFD.udp_dport)
class BFD_vpp_echo(Packet):
""" BFD echo packet as used by VPP (non-rfc, as rfc doesn't define one) """
udp_dport = 3785 #: BFD echo destination port per RFC 5881
name = "BFD_VPP_ECHO"
fields_desc = [
BitField("discriminator", 0, 32),
BitField("expire_time_clocks", 0, 64),
BitField("checksum", 0, 64)
]
def mysummary(self):
return self.sprintf(
"BFD_VPP_ECHO(disc=%BFD_VPP_ECHO.discriminator%,"
"expire_time_clocks=%BFD_VPP_ECHO.expire_time_clocks%)")
# glue the BFD echo packet class to scapy parser
bind_layers(UDP, BFD_vpp_echo, dport=BFD_vpp_echo.udp_dport)
class VppBFDAuthKey(VppObject):
""" Represents BFD authentication key in VPP """

View File

@ -574,7 +574,7 @@ class VppTestCase(unittest.TestCase):
def assert_equal(self, real_value, expected_value, name_or_class=None):
if name_or_class is None:
self.assertEqual(real_value, expected_value, msg)
self.assertEqual(real_value, expected_value)
return
try:
msg = "Invalid %s: %d('%s') does not match expected value %d('%s')"

File diff suppressed because it is too large Load Diff

View File

@ -1117,6 +1117,10 @@ class VppPapiProvider(object):
def bfd_auth_keys_dump(self):
return self.api(self.papi.bfd_auth_keys_dump, {})
def bfd_udp_set_echo_source(self, sw_if_index):
return self.api(self.papi.bfd_udp_set_echo_source,
{'sw_if_index': sw_if_index})
def classify_add_del_table(
self,
is_add,