mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 06:50:17 +00:00
Merge pull request #11668 from rampxxxx/bfd_rtt_in_echo_pkt
BFDD: Add RTT to BFD IPV4 Echo packet processing
This commit is contained in:
commit
ac2f410c37
17
bfdd/bfd.c
17
bfdd/bfd.c
@ -381,6 +381,9 @@ int bfd_session_enable(struct bfd_session *bs)
|
||||
ptm_bfd_start_xmt_timer(bs, false);
|
||||
}
|
||||
|
||||
/* initialize RTT */
|
||||
bfd_rtt_init(bs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -574,6 +577,9 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
|
||||
memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
|
||||
/* reset local address ,it might has been be changed after bfd is up*/
|
||||
memset(&bfd->local_address, 0, sizeof(bfd->local_address));
|
||||
|
||||
/* reset RTT */
|
||||
bfd_rtt_init(bfd);
|
||||
}
|
||||
|
||||
static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
|
||||
@ -2063,3 +2069,14 @@ unsigned long bfd_get_session_count(void)
|
||||
{
|
||||
return bfd_key_hash->count;
|
||||
}
|
||||
|
||||
void bfd_rtt_init(struct bfd_session *bfd)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* initialize RTT */
|
||||
bfd->rtt_valid = 0;
|
||||
bfd->rtt_index = 0;
|
||||
for (i = 0; i < BFD_RTT_SAMPLE; i++)
|
||||
bfd->rtt[i] = 0;
|
||||
}
|
||||
|
10
bfdd/bfd.h
10
bfdd/bfd.h
@ -86,7 +86,8 @@ struct bfd_echo_pkt {
|
||||
};
|
||||
};
|
||||
uint32_t my_discr;
|
||||
uint8_t pad[16];
|
||||
uint64_t time_sent_sec;
|
||||
uint64_t time_sent_usec;
|
||||
};
|
||||
|
||||
|
||||
@ -249,6 +250,8 @@ struct bfd_config_timers {
|
||||
uint32_t required_min_echo_rx;
|
||||
};
|
||||
|
||||
#define BFD_RTT_SAMPLE 8
|
||||
|
||||
/*
|
||||
* Session state information
|
||||
*/
|
||||
@ -311,6 +314,10 @@ struct bfd_session {
|
||||
struct bfd_timers remote_timers;
|
||||
|
||||
uint64_t refcount; /* number of pointers referencing this. */
|
||||
|
||||
uint8_t rtt_valid; /* number of valid samples */
|
||||
uint8_t rtt_index; /* last index added */
|
||||
uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */
|
||||
};
|
||||
|
||||
struct peer_label {
|
||||
@ -635,6 +642,7 @@ const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
|
||||
bool mhop);
|
||||
void bfd_sessions_remove_manual(void);
|
||||
void bfd_profiles_remove(void);
|
||||
void bfd_rtt_init(struct bfd_session *bfd);
|
||||
|
||||
/**
|
||||
* Set the BFD session echo state.
|
||||
|
@ -55,8 +55,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
|
||||
struct sockaddr_any *peer);
|
||||
int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
|
||||
struct sockaddr *to, socklen_t tolen);
|
||||
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
|
||||
uint8_t *ttl, uint32_t *my_discr);
|
||||
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd, uint8_t *ttl,
|
||||
uint32_t *my_discr, uint64_t *my_rtt);
|
||||
#ifdef BFD_LINUX
|
||||
ssize_t bfd_recv_ipv4_fp(int sd, uint8_t *msgbuf, size_t msgbuflen,
|
||||
uint8_t *ttl, ifindex_t *ifindex,
|
||||
@ -207,6 +207,7 @@ void ptm_bfd_echo_fp_snd(struct bfd_session *bfd)
|
||||
struct iphdr *iph;
|
||||
struct bfd_echo_pkt *beph;
|
||||
static char sendbuff[100];
|
||||
struct timeval time_sent;
|
||||
|
||||
if (!bvrf)
|
||||
return;
|
||||
@ -259,6 +260,11 @@ void ptm_bfd_echo_fp_snd(struct bfd_session *bfd)
|
||||
beph->len = BFD_ECHO_PKT_LEN;
|
||||
beph->my_discr = htonl(bfd->discrs.my_discr);
|
||||
|
||||
/* RTT calculation: add starting time in packet */
|
||||
monotime(&time_sent);
|
||||
beph->time_sent_sec = htobe64(time_sent.tv_sec);
|
||||
beph->time_sent_usec = htobe64(time_sent.tv_usec);
|
||||
|
||||
total_len += sizeof(struct bfd_echo_pkt);
|
||||
uh->len =
|
||||
htons(total_len - sizeof(struct iphdr) - sizeof(struct ethhdr));
|
||||
@ -338,10 +344,11 @@ static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
|
||||
{
|
||||
struct bfd_session *bfd;
|
||||
uint32_t my_discr = 0;
|
||||
uint64_t my_rtt = 0;
|
||||
uint8_t ttl = 0;
|
||||
|
||||
/* Receive and parse echo packet. */
|
||||
if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr) == -1)
|
||||
if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr, &my_rtt) == -1)
|
||||
return 0;
|
||||
|
||||
/* Your discriminator not zero - use it to find session */
|
||||
@ -360,6 +367,16 @@ static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* RTT Calculation: add current RTT to samples */
|
||||
if (my_rtt != 0) {
|
||||
bfd->rtt[bfd->rtt_index] = my_rtt;
|
||||
bfd->rtt_index++;
|
||||
if (bfd->rtt_index >= BFD_RTT_SAMPLE)
|
||||
bfd->rtt_index = 0;
|
||||
if (bfd->rtt_valid < BFD_RTT_SAMPLE)
|
||||
bfd->rtt_valid++;
|
||||
}
|
||||
|
||||
bfd->stats.rx_echo_pkt++;
|
||||
|
||||
/* Compute detect time */
|
||||
@ -1003,8 +1020,8 @@ void bfd_recv_cb(struct thread *t)
|
||||
*
|
||||
* Returns -1 on error or loopback or 0 on success.
|
||||
*/
|
||||
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
|
||||
uint8_t *ttl, uint32_t *my_discr)
|
||||
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd, uint8_t *ttl,
|
||||
uint32_t *my_discr, uint64_t *my_rtt)
|
||||
{
|
||||
struct bfd_echo_pkt *bep;
|
||||
ssize_t rlen;
|
||||
@ -1062,6 +1079,17 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef BFD_LINUX
|
||||
/* RTT Calculation: determine RTT time of IPv4 echo pkt */
|
||||
if (sd == bvrf->bg_echo) {
|
||||
struct timeval time_sent = {0, 0};
|
||||
|
||||
time_sent.tv_sec = be64toh(bep->time_sent_sec);
|
||||
time_sent.tv_usec = be64toh(bep->time_sent_usec);
|
||||
*my_rtt = monotime_since(&time_sent, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1074,11 +1102,10 @@ int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
|
||||
struct bfd_session *bfd)
|
||||
{
|
||||
ssize_t wlen;
|
||||
struct msghdr msg;
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
uint8_t msgctl[255];
|
||||
struct sockaddr_ll sadr_ll;
|
||||
|
||||
struct sockaddr_ll sadr_ll = {0};
|
||||
|
||||
sadr_ll.sll_ifindex = bfd->ifp->ifindex;
|
||||
sadr_ll.sll_halen = ETH_ALEN;
|
||||
@ -1089,7 +1116,6 @@ int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
|
||||
iov[0].iov_base = data;
|
||||
iov[0].iov_len = datalen;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
memset(msgctl, 0, sizeof(msgctl));
|
||||
msg.msg_name = &sadr_ll;
|
||||
msg.msg_namelen = sizeof(sadr_ll);
|
||||
@ -1605,7 +1631,7 @@ int bp_echo_socket(const struct vrf *vrf)
|
||||
zlog_fatal("echo-socket: socket: %s", strerror(errno));
|
||||
|
||||
struct sock_fprog pf;
|
||||
struct sockaddr_ll sll;
|
||||
struct sockaddr_ll sll = {0};
|
||||
|
||||
/* adjust filter for socket to only receive ECHO packets */
|
||||
pf.filter = my_filterudp;
|
||||
|
@ -66,6 +66,9 @@ static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
|
||||
static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg);
|
||||
static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg);
|
||||
static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json);
|
||||
static void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
|
||||
struct bfd_session *bs);
|
||||
|
||||
static struct bfd_session *
|
||||
_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
|
||||
const char *label, const char *peer_str,
|
||||
@ -106,6 +109,9 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
||||
{
|
||||
char buf[256];
|
||||
time_t now;
|
||||
uint32_t min = 0;
|
||||
uint32_t avg = 0;
|
||||
uint32_t max = 0;
|
||||
|
||||
_display_peer_header(vty, bs);
|
||||
|
||||
@ -150,6 +156,8 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
|
||||
vty_out(vty, "\t\tRemote diagnostics: %s\n", diag2str(bs->remote_diag));
|
||||
vty_out(vty, "\t\tPeer Type: %s\n",
|
||||
CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) ? "configured" : "dynamic");
|
||||
_display_rtt(&min, &avg, &max, bs);
|
||||
vty_out(vty, "\t\tRTT min/avg/max: %u/%u/%u usec\n", min, avg, max);
|
||||
|
||||
vty_out(vty, "\t\tLocal timers:\n");
|
||||
vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
|
||||
@ -217,6 +225,9 @@ static struct json_object *_peer_json_header(struct bfd_session *bs)
|
||||
static struct json_object *__display_peer_json(struct bfd_session *bs)
|
||||
{
|
||||
struct json_object *jo = _peer_json_header(bs);
|
||||
uint32_t min = 0;
|
||||
uint32_t avg = 0;
|
||||
uint32_t max = 0;
|
||||
|
||||
json_object_int_add(jo, "id", bs->discrs.my_discr);
|
||||
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
|
||||
@ -275,6 +286,11 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
|
||||
json_object_int_add(jo, "remote-detect-multiplier",
|
||||
bs->remote_detect_mult);
|
||||
|
||||
_display_rtt(&min, &avg, &max, bs);
|
||||
json_object_int_add(jo, "rtt-min", min);
|
||||
json_object_int_add(jo, "rtt-avg", avg);
|
||||
json_object_int_add(jo, "rtt-max", max);
|
||||
|
||||
return jo;
|
||||
}
|
||||
|
||||
@ -608,6 +624,31 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
|
||||
return bs;
|
||||
}
|
||||
|
||||
void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
|
||||
struct bfd_session *bs)
|
||||
{
|
||||
#ifdef BFD_LINUX
|
||||
uint8_t i;
|
||||
uint32_t average = 0;
|
||||
|
||||
if (bs->rtt_valid == 0)
|
||||
return;
|
||||
|
||||
*max = bs->rtt[0];
|
||||
*min = 1000;
|
||||
*avg = 0;
|
||||
|
||||
for (i = 0; i < bs->rtt_valid; i++) {
|
||||
if (bs->rtt[i] < *min)
|
||||
*min = bs->rtt[i];
|
||||
if (bs->rtt[i] > *max)
|
||||
*max = bs->rtt[i];
|
||||
average += bs->rtt[i];
|
||||
}
|
||||
*avg = average / bs->rtt_valid;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Show commands.
|
||||
|
@ -518,6 +518,10 @@ You can inspect the current BFD peer status with the following commands:
|
||||
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-receive-interval":50,"echo-transmit-interval":0,"detect-multiplier":3,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-receive-interval":50,"remote-detect-multiplier":3,"peer-type":"dynamic"}
|
||||
|
||||
If you are running IPV4 BFD Echo, on a Linux platform, we also
|
||||
calculate round trip time for the packets. We display minimum,
|
||||
average and maximum time it took to receive the looped Echo packets
|
||||
in the RTT fields.
|
||||
|
||||
You can inspect the current BFD peer status in brief with the following commands:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user