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:
Rafael Zalamena 2022-08-09 15:20:24 +00:00 committed by GitHub
commit ac2f410c37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 11 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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.

View File

@ -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: