mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 11:30:55 +00:00
Merge pull request #2856 from opensourcerouting/bfd-work
bfdd: bug fixes and improvements
This commit is contained in:
commit
018928cbaa
@ -185,10 +185,12 @@ void ptm_bfd_ses_up(struct bfd_session *bfd)
|
|||||||
|
|
||||||
control_notify(bfd);
|
control_notify(bfd);
|
||||||
|
|
||||||
if (old_state != bfd->ses_state)
|
if (old_state != bfd->ses_state) {
|
||||||
|
bfd->stats.session_up++;
|
||||||
log_info("state-change: [%s] %s -> %s", bs_to_string(bfd),
|
log_info("state-change: [%s] %s -> %s", bs_to_string(bfd),
|
||||||
state_list[old_state].str,
|
state_list[old_state].str,
|
||||||
state_list[bfd->ses_state].str);
|
state_list[bfd->ses_state].str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag)
|
void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag)
|
||||||
@ -212,11 +214,13 @@ void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag)
|
|||||||
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
|
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
|
||||||
ptm_bfd_echo_stop(bfd, 0);
|
ptm_bfd_echo_stop(bfd, 0);
|
||||||
|
|
||||||
if (old_state != bfd->ses_state)
|
if (old_state != bfd->ses_state) {
|
||||||
|
bfd->stats.session_down++;
|
||||||
log_info("state-change: [%s] %s -> %s reason:%s",
|
log_info("state-change: [%s] %s -> %s reason:%s",
|
||||||
bs_to_string(bfd), state_list[old_state].str,
|
bs_to_string(bfd), state_list[old_state].str,
|
||||||
state_list[bfd->ses_state].str,
|
state_list[bfd->ses_state].str,
|
||||||
get_diag_str(bfd->local_diag));
|
get_diag_str(bfd->local_diag));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptm_bfd_get_vrf_name(char *port_name, char *vrf_name)
|
static int ptm_bfd_get_vrf_name(char *port_name, char *vrf_name)
|
||||||
|
@ -186,6 +186,9 @@ struct bfd_session_stats {
|
|||||||
uint64_t tx_ctrl_pkt;
|
uint64_t tx_ctrl_pkt;
|
||||||
uint64_t rx_echo_pkt;
|
uint64_t rx_echo_pkt;
|
||||||
uint64_t tx_echo_pkt;
|
uint64_t tx_echo_pkt;
|
||||||
|
uint64_t session_up;
|
||||||
|
uint64_t session_down;
|
||||||
|
uint64_t znotification;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bfd_session_vxlan_info {
|
struct bfd_session_vxlan_info {
|
||||||
|
@ -718,12 +718,6 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
|
|||||||
msghdr.msg_control = cmsgbuf;
|
msghdr.msg_control = cmsgbuf;
|
||||||
msghdr.msg_controllen = sizeof(cmsgbuf);
|
msghdr.msg_controllen = sizeof(cmsgbuf);
|
||||||
|
|
||||||
/* Sanitize input/output. */
|
|
||||||
memset(port, 0, portlen);
|
|
||||||
memset(vrfname, 0, vrfnamelen);
|
|
||||||
memset(local, 0, sizeof(*local));
|
|
||||||
memset(peer, 0, sizeof(*peer));
|
|
||||||
|
|
||||||
mlen = recvmsg(sd, &msghdr, MSG_DONTWAIT);
|
mlen = recvmsg(sd, &msghdr, MSG_DONTWAIT);
|
||||||
if (mlen == -1) {
|
if (mlen == -1) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
@ -843,12 +837,6 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
|
|||||||
msghdr6.msg_control = cmsgbuf6;
|
msghdr6.msg_control = cmsgbuf6;
|
||||||
msghdr6.msg_controllen = sizeof(cmsgbuf6);
|
msghdr6.msg_controllen = sizeof(cmsgbuf6);
|
||||||
|
|
||||||
/* Sanitize input/output. */
|
|
||||||
memset(port, 0, portlen);
|
|
||||||
memset(vrfname, 0, vrfnamelen);
|
|
||||||
memset(local, 0, sizeof(*local));
|
|
||||||
memset(peer, 0, sizeof(*peer));
|
|
||||||
|
|
||||||
mlen = recvmsg(sd, &msghdr6, MSG_DONTWAIT);
|
mlen = recvmsg(sd, &msghdr6, MSG_DONTWAIT);
|
||||||
if (mlen == -1) {
|
if (mlen == -1) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
@ -983,6 +971,12 @@ int bfd_recv_cb(struct thread *t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sanitize input/output. */
|
||||||
|
memset(port, 0, sizeof(port));
|
||||||
|
memset(vrfname, 0, sizeof(vrfname));
|
||||||
|
memset(&local, 0, sizeof(local));
|
||||||
|
memset(&peer, 0, sizeof(peer));
|
||||||
|
|
||||||
/* Handle control packets. */
|
/* Handle control packets. */
|
||||||
is_mhop = is_vxlan = false;
|
is_mhop = is_vxlan = false;
|
||||||
if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
|
if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
|
||||||
|
241
bfdd/bfdd_vty.c
241
bfdd/bfdd_vty.c
@ -58,12 +58,25 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
|
|||||||
const char *ifname, const char *vrfname,
|
const char *ifname, const char *vrfname,
|
||||||
char *ebuf, size_t ebuflen);
|
char *ebuf, size_t ebuflen);
|
||||||
|
|
||||||
|
static void _display_peer_header(struct vty *vty, struct bfd_session *bs);
|
||||||
static struct json_object *__display_peer_json(struct bfd_session *bs);
|
static struct json_object *__display_peer_json(struct bfd_session *bs);
|
||||||
|
static struct json_object *_peer_json_header(struct bfd_session *bs);
|
||||||
static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
|
static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
|
||||||
static void _display_peer(struct vty *vty, struct bfd_session *bs);
|
static void _display_peer(struct vty *vty, struct bfd_session *bs);
|
||||||
static void _display_all_peers(struct vty *vty, bool use_json);
|
static void _display_all_peers(struct vty *vty, bool use_json);
|
||||||
static void _display_peer_iter(struct hash_backet *hb, void *arg);
|
static void _display_peer_iter(struct hash_backet *hb, void *arg);
|
||||||
static void _display_peer_json_iter(struct hash_backet *hb, void *arg);
|
static void _display_peer_json_iter(struct hash_backet *hb, void *arg);
|
||||||
|
static void _display_peer_counter(struct vty *vty, struct bfd_session *bs);
|
||||||
|
static struct json_object *__display_peer_counters_json(struct bfd_session *bs);
|
||||||
|
static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs);
|
||||||
|
static void _display_peer_counter_iter(struct hash_backet *hb, void *arg);
|
||||||
|
static void _display_peer_counter_json_iter(struct hash_backet *hb, void *arg);
|
||||||
|
static void _display_peers_counter(struct vty *vty, bool use_json);
|
||||||
|
static struct bfd_session *
|
||||||
|
_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
|
||||||
|
const char *label, const char *peer_str,
|
||||||
|
const char *local_str, const char *ifname,
|
||||||
|
const char *vrfname);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -353,11 +366,8 @@ DEFPY(bfd_no_peer, bfd_no_peer_cmd,
|
|||||||
/*
|
/*
|
||||||
* Show commands helper functions
|
* Show commands helper functions
|
||||||
*/
|
*/
|
||||||
static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
|
||||||
{
|
{
|
||||||
char buf[256];
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
|
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
|
||||||
vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
|
vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
|
||||||
vty_out(vty, " multihop");
|
vty_out(vty, " multihop");
|
||||||
@ -377,6 +387,14 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
|||||||
|
|
||||||
if (bs->pl)
|
if (bs->pl)
|
||||||
vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
|
vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
_display_peer_header(vty, bs);
|
||||||
|
|
||||||
vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
|
vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
|
||||||
vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
|
vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
|
||||||
@ -418,7 +436,7 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
|||||||
vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms",
|
vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms",
|
||||||
bs->timers.desired_min_tx / 1000);
|
bs->timers.desired_min_tx / 1000);
|
||||||
if (bs->up_min_tx != bs->timers.desired_min_tx)
|
if (bs->up_min_tx != bs->timers.desired_min_tx)
|
||||||
vty_out(vty, " (configured %" PRIu32 "ms)\n",
|
vty_out(vty, " (configured %" PRIu32 "ms)\n",
|
||||||
bs->up_min_tx / 1000);
|
bs->up_min_tx / 1000);
|
||||||
else
|
else
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
@ -441,7 +459,7 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
|||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct json_object *__display_peer_json(struct bfd_session *bs)
|
static struct json_object *_peer_json_header(struct bfd_session *bs)
|
||||||
{
|
{
|
||||||
struct json_object *jo = json_object_new_object();
|
struct json_object *jo = json_object_new_object();
|
||||||
|
|
||||||
@ -465,6 +483,13 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
|
|||||||
if (bs->pl)
|
if (bs->pl)
|
||||||
json_object_string_add(jo, "label", bs->pl->pl_label);
|
json_object_string_add(jo, "label", bs->pl->pl_label);
|
||||||
|
|
||||||
|
return jo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct json_object *__display_peer_json(struct bfd_session *bs)
|
||||||
|
{
|
||||||
|
struct json_object *jo = _peer_json_header(bs);
|
||||||
|
|
||||||
json_object_int_add(jo, "id", bs->discrs.my_discr);
|
json_object_int_add(jo, "id", bs->discrs.my_discr);
|
||||||
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
|
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
|
||||||
|
|
||||||
@ -550,6 +575,7 @@ static void _display_all_peers(struct vty *vty, bool use_json)
|
|||||||
struct json_object *jo;
|
struct json_object *jo;
|
||||||
|
|
||||||
if (use_json == false) {
|
if (use_json == false) {
|
||||||
|
vty_out(vty, "BFD Peers:\n");
|
||||||
bfd_id_iterate(_display_peer_iter, vty);
|
bfd_id_iterate(_display_peer_iter, vty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -561,37 +587,94 @@ static void _display_all_peers(struct vty *vty, bool use_json)
|
|||||||
json_object_free(jo);
|
json_object_free(jo);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd peers [json]",
|
static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
|
||||||
SHOW_STR
|
|
||||||
"Bidirection Forwarding Detection\n"
|
|
||||||
"BFD peers status\n"
|
|
||||||
JSON_STR)
|
|
||||||
{
|
{
|
||||||
bool json = use_json(argc, argv);
|
_display_peer_header(vty, bs);
|
||||||
|
|
||||||
if (json) {
|
vty_out(vty, "\t\tControl packet input: %" PRIu64 " packets\n",
|
||||||
_display_all_peers(vty, true);
|
bs->stats.rx_ctrl_pkt);
|
||||||
} else {
|
vty_out(vty, "\t\tControl packet output: %" PRIu64 " packets\n",
|
||||||
vty_out(vty, "BFD Peers:\n");
|
bs->stats.tx_ctrl_pkt);
|
||||||
_display_all_peers(vty, false);
|
vty_out(vty, "\t\tEcho packet input: %" PRIu64 " packets\n",
|
||||||
}
|
bs->stats.rx_echo_pkt);
|
||||||
|
vty_out(vty, "\t\tEcho packet output: %" PRIu64 " packets\n",
|
||||||
return CMD_SUCCESS;
|
bs->stats.tx_echo_pkt);
|
||||||
|
vty_out(vty, "\t\tSession up events: %" PRIu64 "\n",
|
||||||
|
bs->stats.session_up);
|
||||||
|
vty_out(vty, "\t\tSession down events: %" PRIu64 "\n",
|
||||||
|
bs->stats.session_down);
|
||||||
|
vty_out(vty, "\t\tZebra notifications: %" PRIu64 "\n",
|
||||||
|
bs->stats.znotification);
|
||||||
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
|
||||||
"show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> [json]",
|
{
|
||||||
SHOW_STR
|
struct json_object *jo = _peer_json_header(bs);
|
||||||
"Bidirection Forwarding Detection\n"
|
|
||||||
"BFD peers status\n"
|
json_object_int_add(jo, "control-packet-input", bs->stats.rx_ctrl_pkt);
|
||||||
"Peer label\n"
|
json_object_int_add(jo, "control-packet-output", bs->stats.tx_ctrl_pkt);
|
||||||
PEER_IPV4_STR PEER_IPV6_STR
|
json_object_int_add(jo, "echo-packet-input", bs->stats.rx_echo_pkt);
|
||||||
MHOP_STR
|
json_object_int_add(jo, "echo-packet-output", bs->stats.tx_echo_pkt);
|
||||||
LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
|
json_object_int_add(jo, "session-up", bs->stats.session_up);
|
||||||
INTERFACE_STR
|
json_object_int_add(jo, "session-down", bs->stats.session_down);
|
||||||
LOCAL_INTF_STR
|
json_object_int_add(jo, "zebra-notifications", bs->stats.znotification);
|
||||||
VRF_STR VRF_NAME_STR
|
|
||||||
JSON_STR)
|
return jo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
|
||||||
|
{
|
||||||
|
struct json_object *jo = __display_peer_counters_json(bs);
|
||||||
|
|
||||||
|
vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
|
||||||
|
json_object_free(jo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_peer_counter_iter(struct hash_backet *hb, void *arg)
|
||||||
|
{
|
||||||
|
struct vty *vty = arg;
|
||||||
|
struct bfd_session *bs = hb->data;
|
||||||
|
|
||||||
|
_display_peer_counter(vty, bs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_peer_counter_json_iter(struct hash_backet *hb, void *arg)
|
||||||
|
{
|
||||||
|
struct json_object *jo = arg, *jon = NULL;
|
||||||
|
struct bfd_session *bs = hb->data;
|
||||||
|
|
||||||
|
jon = __display_peer_counters_json(bs);
|
||||||
|
if (jon == NULL) {
|
||||||
|
log_warning("%s: not enough memory", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_array_add(jo, jon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _display_peers_counter(struct vty *vty, bool use_json)
|
||||||
|
{
|
||||||
|
struct json_object *jo;
|
||||||
|
|
||||||
|
if (use_json == false) {
|
||||||
|
vty_out(vty, "BFD Peers:\n");
|
||||||
|
bfd_id_iterate(_display_peer_counter_iter, vty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jo = json_object_new_array();
|
||||||
|
bfd_id_iterate(_display_peer_counter_json_iter, jo);
|
||||||
|
|
||||||
|
vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
|
||||||
|
json_object_free(jo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bfd_session *
|
||||||
|
_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
|
||||||
|
const char *label, const char *peer_str,
|
||||||
|
const char *local_str, const char *ifname,
|
||||||
|
const char *vrfname)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
bool mhop;
|
bool mhop;
|
||||||
@ -608,7 +691,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
|||||||
bs = pl->pl_bs;
|
bs = pl->pl_bs;
|
||||||
} else {
|
} else {
|
||||||
strtosa(peer_str, &psa);
|
strtosa(peer_str, &psa);
|
||||||
if (local) {
|
if (local_str) {
|
||||||
strtosa(local_str, &lsa);
|
strtosa(local_str, &lsa);
|
||||||
lsap = &lsa;
|
lsap = &lsa;
|
||||||
} else
|
} else
|
||||||
@ -622,7 +705,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
|||||||
!= 0) {
|
!= 0) {
|
||||||
vty_out(vty, "%% Invalid peer configuration: %s\n",
|
vty_out(vty, "%% Invalid peer configuration: %s\n",
|
||||||
errormsg);
|
errormsg);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bs_peer_find(&bpc);
|
bs = bs_peer_find(&bpc);
|
||||||
@ -634,15 +717,49 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
|||||||
label ? label : peer_str);
|
label ? label : peer_str);
|
||||||
if (ifname)
|
if (ifname)
|
||||||
vty_out(vty, " interface %s", ifname);
|
vty_out(vty, " interface %s", ifname);
|
||||||
if (local)
|
if (local_str)
|
||||||
vty_out(vty, " local-address %s", local_str);
|
vty_out(vty, " local-address %s", local_str);
|
||||||
if (vrfname)
|
if (vrfname)
|
||||||
vty_out(vty, " vrf %s", vrfname);
|
vty_out(vty, " vrf %s", vrfname);
|
||||||
vty_out(vty, "'\n");
|
vty_out(vty, "'\n");
|
||||||
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show commands.
|
||||||
|
*/
|
||||||
|
DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd peers [json]",
|
||||||
|
SHOW_STR
|
||||||
|
"Bidirection Forwarding Detection\n"
|
||||||
|
"BFD peers status\n" JSON_STR)
|
||||||
|
{
|
||||||
|
_display_all_peers(vty, use_json(argc, argv));
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
||||||
|
"show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> [json]",
|
||||||
|
SHOW_STR
|
||||||
|
"Bidirection Forwarding Detection\n"
|
||||||
|
"BFD peers status\n"
|
||||||
|
"Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
|
||||||
|
LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR VRF_STR
|
||||||
|
VRF_NAME_STR JSON_STR)
|
||||||
|
{
|
||||||
|
struct bfd_session *bs;
|
||||||
|
|
||||||
|
/* Look up the BFD peer. */
|
||||||
|
bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
|
||||||
|
ifname, vrfname);
|
||||||
|
if (bs == NULL)
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
|
||||||
if (use_json(argc, argv)) {
|
if (use_json(argc, argv)) {
|
||||||
_display_peer_json(vty, bs);
|
_display_peer_json(vty, bs);
|
||||||
} else {
|
} else {
|
||||||
@ -653,6 +770,54 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
|
||||||
|
"show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> counters [json]",
|
||||||
|
SHOW_STR
|
||||||
|
"Bidirection Forwarding Detection\n"
|
||||||
|
"BFD peers status\n"
|
||||||
|
"Peer label\n"
|
||||||
|
PEER_IPV4_STR
|
||||||
|
PEER_IPV6_STR
|
||||||
|
MHOP_STR
|
||||||
|
LOCAL_STR
|
||||||
|
LOCAL_IPV4_STR
|
||||||
|
LOCAL_IPV6_STR
|
||||||
|
INTERFACE_STR
|
||||||
|
LOCAL_INTF_STR
|
||||||
|
VRF_STR
|
||||||
|
VRF_NAME_STR
|
||||||
|
"Show BFD peer counters information\n"
|
||||||
|
JSON_STR)
|
||||||
|
{
|
||||||
|
struct bfd_session *bs;
|
||||||
|
|
||||||
|
/* Look up the BFD peer. */
|
||||||
|
bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
|
||||||
|
ifname, vrfname);
|
||||||
|
if (bs == NULL)
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
|
||||||
|
if (use_json(argc, argv))
|
||||||
|
_display_peer_counters_json(vty, bs);
|
||||||
|
else
|
||||||
|
_display_peer_counter(vty, bs);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
|
||||||
|
"show bfd peers counters [json]",
|
||||||
|
SHOW_STR
|
||||||
|
"Bidirection Forwarding Detection\n"
|
||||||
|
"BFD peers status\n"
|
||||||
|
"Show BFD peer counters information\n"
|
||||||
|
JSON_STR)
|
||||||
|
{
|
||||||
|
_display_peers_counter(vty, use_json(argc, argv));
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function definitions.
|
* Function definitions.
|
||||||
@ -847,6 +1012,8 @@ struct cmd_node bfd_peer_node = {
|
|||||||
|
|
||||||
void bfdd_vty_init(void)
|
void bfdd_vty_init(void)
|
||||||
{
|
{
|
||||||
|
install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd);
|
||||||
|
install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd);
|
||||||
install_element(ENABLE_NODE, &bfd_show_peers_cmd);
|
install_element(ENABLE_NODE, &bfd_show_peers_cmd);
|
||||||
install_element(ENABLE_NODE, &bfd_show_peer_cmd);
|
install_element(ENABLE_NODE, &bfd_show_peer_cmd);
|
||||||
install_element(CONFIG_NODE, &bfd_enter_cmd);
|
install_element(CONFIG_NODE, &bfd_enter_cmd);
|
||||||
|
@ -514,7 +514,7 @@ skip_header:
|
|||||||
if (bcb->bcb_left > 0)
|
if (bcb->bcb_left > 0)
|
||||||
goto schedule_next_read;
|
goto schedule_next_read;
|
||||||
|
|
||||||
switch (bcm.bcm_type) {
|
switch (bcb->bcb_bcm->bcm_type) {
|
||||||
case BMT_REQUEST_ADD:
|
case BMT_REQUEST_ADD:
|
||||||
control_handle_request_add(bcs, bcb->bcb_bcm);
|
control_handle_request_add(bcs, bcb->bcb_bcm);
|
||||||
break;
|
break;
|
||||||
@ -533,8 +533,8 @@ skip_header:
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
log_debug("%s: unhandled message type: %d", __func__,
|
log_debug("%s: unhandled message type: %d", __func__,
|
||||||
bcm.bcm_type);
|
bcb->bcb_bcm->bcm_type);
|
||||||
control_response(bcs, bcm.bcm_id, BCM_RESPONSE_ERROR,
|
control_response(bcs, bcb->bcb_bcm->bcm_id, BCM_RESPONSE_ERROR,
|
||||||
"invalid message type");
|
"invalid message type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,8 @@ int ptm_bfd_notify(struct bfd_session *bs)
|
|||||||
struct stream *msg;
|
struct stream *msg;
|
||||||
struct sockaddr_any sac;
|
struct sockaddr_any sac;
|
||||||
|
|
||||||
|
bs->stats.znotification++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Message format:
|
* Message format:
|
||||||
* - header: command, vrf
|
* - header: command, vrf
|
||||||
@ -274,7 +276,7 @@ static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_warning("%s: invalid family: %d", __func__, family);
|
log_warning("ptm-read-address: invalid family: %d", family);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +331,7 @@ static int _ptm_msg_read(struct stream *msg, int command,
|
|||||||
|
|
||||||
*pc = pc_new(pid);
|
*pc = pc_new(pid);
|
||||||
if (*pc == NULL) {
|
if (*pc == NULL) {
|
||||||
log_debug("%s: failed to allocate memory", __func__);
|
log_debug("ptm-read: failed to allocate memory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,8 +372,8 @@ static int _ptm_msg_read(struct stream *msg, int command,
|
|||||||
* structure, otherwise fail.
|
* structure, otherwise fail.
|
||||||
*/
|
*/
|
||||||
STREAM_GETC(msg, ifnamelen);
|
STREAM_GETC(msg, ifnamelen);
|
||||||
if (ifnamelen > sizeof(bpc->bpc_localif)) {
|
if (ifnamelen >= sizeof(bpc->bpc_localif)) {
|
||||||
log_error("%s: interface name is too big", __func__);
|
log_error("ptm-read: interface name is too big");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,8 +388,7 @@ static int _ptm_msg_read(struct stream *msg, int command,
|
|||||||
if (bpc->bpc_local.sa_sin.sin_family != 0
|
if (bpc->bpc_local.sa_sin.sin_family != 0
|
||||||
&& (bpc->bpc_local.sa_sin.sin_family
|
&& (bpc->bpc_local.sa_sin.sin_family
|
||||||
!= bpc->bpc_peer.sa_sin.sin_family)) {
|
!= bpc->bpc_peer.sa_sin.sin_family)) {
|
||||||
log_warning("%s: peer family doesn't match local type",
|
log_warning("ptm-read: peer family doesn't match local type");
|
||||||
__func__);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +416,7 @@ static void bfdd_dest_register(struct stream *msg)
|
|||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
bs = ptm_bfd_sess_new(&bpc);
|
bs = ptm_bfd_sess_new(&bpc);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
log_debug("%s: failed to create BFD session", __func__);
|
log_debug("ptm-add-dest: failed to create BFD session");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -428,7 +429,7 @@ static void bfdd_dest_register(struct stream *msg)
|
|||||||
/* Create client peer notification register. */
|
/* Create client peer notification register. */
|
||||||
pcn = pcn_new(pc, bs);
|
pcn = pcn_new(pc, bs);
|
||||||
if (pcn == NULL) {
|
if (pcn == NULL) {
|
||||||
log_error("%s: failed to registrate notifications", __func__);
|
log_error("ptm-add-dest: failed to registrate notifications");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +452,7 @@ static void bfdd_dest_deregister(struct stream *msg)
|
|||||||
/* Find or start new BFD session. */
|
/* Find or start new BFD session. */
|
||||||
bs = bs_peer_find(&bpc);
|
bs = bs_peer_find(&bpc);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
log_debug("%s: failed to create BFD session", __func__);
|
log_debug("ptm-del-dest: failed to find BFD session");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,14 +475,14 @@ static void bfdd_client_register(struct stream *msg)
|
|||||||
|
|
||||||
pc = pc_new(pid);
|
pc = pc_new(pid);
|
||||||
if (pc == NULL) {
|
if (pc == NULL) {
|
||||||
log_error("%s: failed to register client: %u", __func__, pid);
|
log_error("ptm-add-client: failed to register client: %u", pid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stream_failure:
|
stream_failure:
|
||||||
log_error("%s: failed to register client", __func__);
|
log_error("ptm-add-client: failed to register client");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -498,7 +499,7 @@ static void bfdd_client_deregister(struct stream *msg)
|
|||||||
|
|
||||||
pc = pc_lookup(pid);
|
pc = pc_lookup(pid);
|
||||||
if (pc == NULL) {
|
if (pc == NULL) {
|
||||||
log_debug("%s: failed to find client: %u", __func__, pid);
|
log_debug("ptm-del-client: failed to find client: %u", pid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,7 +508,7 @@ static void bfdd_client_deregister(struct stream *msg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
stream_failure:
|
stream_failure:
|
||||||
log_error("%s: failed to deregister client", __func__);
|
log_error("ptm-del-client: failed to deregister client");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bfdd_replay(int cmd, struct zclient *zc, uint16_t len, vrf_id_t vid)
|
static int bfdd_replay(int cmd, struct zclient *zc, uint16_t len, vrf_id_t vid)
|
||||||
@ -533,14 +534,14 @@ static int bfdd_replay(int cmd, struct zclient *zc, uint16_t len, vrf_id_t vid)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_debug("%s: invalid message type %u", __func__, rcmd);
|
log_debug("ptm-replay: invalid message type %u", rcmd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
stream_failure:
|
stream_failure:
|
||||||
log_error("%s: failed to find command", __func__);
|
log_error("ptm-replay: failed to find command");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
doc/user/bfd.rst
105
doc/user/bfd.rst
@ -38,7 +38,7 @@ may also be specified (:ref:`common-invocation-options`).
|
|||||||
.. option:: --bfdctl <unix-socket>
|
.. option:: --bfdctl <unix-socket>
|
||||||
|
|
||||||
Set the BFD daemon control socket location. If using a non-default
|
Set the BFD daemon control socket location. If using a non-default
|
||||||
socket location.
|
socket location::
|
||||||
|
|
||||||
/usr/lib/frr/bfdd --bfdctl /tmp/bfdd.sock
|
/usr/lib/frr/bfdd --bfdctl /tmp/bfdd.sock
|
||||||
|
|
||||||
@ -160,6 +160,8 @@ Peer Configurations
|
|||||||
BGP BFD Configuration
|
BGP BFD Configuration
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
The following commands are available inside the BGP configuration node.
|
||||||
|
|
||||||
.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
|
.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
|
||||||
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
|
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
|
||||||
|
|
||||||
@ -174,6 +176,66 @@ BGP BFD Configuration
|
|||||||
Removes any notification registration for this neighbor.
|
Removes any notification registration for this neighbor.
|
||||||
|
|
||||||
|
|
||||||
|
.. _bfd-ospf-peer-config:
|
||||||
|
|
||||||
|
OSPF BFD Configuration
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The following commands are available inside the interface configuration node.
|
||||||
|
|
||||||
|
.. index:: ip ospf bfd
|
||||||
|
.. clicmd:: ip ospf bfd
|
||||||
|
|
||||||
|
Listen for BFD events on peers created on the interface. Every time
|
||||||
|
a new neighbor is found a BFD peer is created to monitor the link
|
||||||
|
status for fast convergence.
|
||||||
|
|
||||||
|
.. index:: no ip ospf bfd
|
||||||
|
.. clicmd:: no ip ospf bfd
|
||||||
|
|
||||||
|
Removes any notification registration for this interface peers.
|
||||||
|
|
||||||
|
|
||||||
|
.. _bfd-ospf6-peer-config:
|
||||||
|
|
||||||
|
OSPF6 BFD Configuration
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The following commands are available inside the interface configuration node.
|
||||||
|
|
||||||
|
.. index:: ipv6 ospf6 bfd
|
||||||
|
.. clicmd:: ipv6 ospf6 bfd
|
||||||
|
|
||||||
|
Listen for BFD events on peers created on the interface. Every time
|
||||||
|
a new neighbor is found a BFD peer is created to monitor the link
|
||||||
|
status for fast convergence.
|
||||||
|
|
||||||
|
.. index:: no ipv6 ospf6 bfd
|
||||||
|
.. clicmd:: no ipv6 ospf6 bfd
|
||||||
|
|
||||||
|
Removes any notification registration for this interface peers.
|
||||||
|
|
||||||
|
|
||||||
|
.. _bfd-pim-peer-config:
|
||||||
|
|
||||||
|
PIM BFD Configuration
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The following commands are available inside the interface configuration node.
|
||||||
|
|
||||||
|
.. index:: ip pim bfd
|
||||||
|
.. clicmd:: ip pim bfd
|
||||||
|
|
||||||
|
Listen for BFD events on peers created on the interface. Every time
|
||||||
|
a new neighbor is found a BFD peer is created to monitor the link
|
||||||
|
status for fast convergence.
|
||||||
|
|
||||||
|
.. index:: no ip pim bfd
|
||||||
|
.. clicmd:: no ip pim bfd
|
||||||
|
|
||||||
|
Removes any notification registration for this interface peers.
|
||||||
|
|
||||||
|
|
||||||
.. _bfd-configuration:
|
.. _bfd-configuration:
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
@ -300,3 +362,44 @@ You can inspect the current BFD peer status with the following commands:
|
|||||||
Receive interval: 300ms
|
Receive interval: 300ms
|
||||||
Transmission interval: 300ms
|
Transmission interval: 300ms
|
||||||
Echo transmission interval: 50ms
|
Echo transmission interval: 50ms
|
||||||
|
|
||||||
|
frr# show bfd peer 192.168.0.1 json
|
||||||
|
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
|
||||||
|
|
||||||
|
|
||||||
|
You can also inspect peer session counters with the following commands:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
frr# show bfd peers counters
|
||||||
|
BFD Peers:
|
||||||
|
peer 192.168.2.1 interface r2-eth2
|
||||||
|
Control packet input: 28 packets
|
||||||
|
Control packet output: 28 packets
|
||||||
|
Echo packet input: 0 packets
|
||||||
|
Echo packet output: 0 packets
|
||||||
|
Session up events: 1
|
||||||
|
Session down events: 0
|
||||||
|
Zebra notifications: 2
|
||||||
|
|
||||||
|
peer 192.168.0.1
|
||||||
|
Control packet input: 54 packets
|
||||||
|
Control packet output: 103 packets
|
||||||
|
Echo packet input: 965 packets
|
||||||
|
Echo packet output: 966 packets
|
||||||
|
Session up events: 1
|
||||||
|
Session down events: 0
|
||||||
|
Zebra notifications: 4
|
||||||
|
|
||||||
|
frr# show bfd peer 192.168.0.1 counters
|
||||||
|
peer 192.168.0.1
|
||||||
|
Control packet input: 126 packets
|
||||||
|
Control packet output: 247 packets
|
||||||
|
Echo packet input: 2409 packets
|
||||||
|
Echo packet output: 2410 packets
|
||||||
|
Session up events: 1
|
||||||
|
Session down events: 0
|
||||||
|
Zebra notifications: 4
|
||||||
|
|
||||||
|
frr# show bfd peer 192.168.0.1 counters json
|
||||||
|
{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
|
||||||
|
@ -1289,6 +1289,7 @@ static void zebra_ptm_send_bfdd(struct stream *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream_free(msgc);
|
stream_free(msgc);
|
||||||
|
stream_free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zebra_ptm_send_clients(struct stream *msg)
|
static void zebra_ptm_send_clients(struct stream *msg)
|
||||||
@ -1329,6 +1330,7 @@ static void zebra_ptm_send_clients(struct stream *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream_free(msgc);
|
stream_free(msgc);
|
||||||
|
stream_free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _zebra_ptm_bfd_client_deregister(struct zserv *zs)
|
static int _zebra_ptm_bfd_client_deregister(struct zserv *zs)
|
||||||
|
Loading…
Reference in New Issue
Block a user