diff options
author | Rafael Zalamena <rzalamena@users.noreply.github.com> | 2022-08-09 17:20:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-09 17:20:24 +0200 |
commit | ac2f410c379a8cef0abade46a2d2ef351b8f38a7 (patch) | |
tree | 6150e660037020a62132b39c877687a55e82e0b9 /bfdd | |
parent | Merge pull request #11752 from opensourcerouting/fix/update_policy_on_filters (diff) | |
parent | Doc: Update documentation for BFD Echo. (diff) | |
download | frr-ac2f410c379a8cef0abade46a2d2ef351b8f38a7.tar.xz frr-ac2f410c379a8cef0abade46a2d2ef351b8f38a7.zip |
Merge pull request #11668 from rampxxxx/bfd_rtt_in_echo_pkt
BFDD: Add RTT to BFD IPV4 Echo packet processing
Diffstat (limited to 'bfdd')
-rw-r--r-- | bfdd/bfd.c | 17 | ||||
-rw-r--r-- | bfdd/bfd.h | 10 | ||||
-rw-r--r-- | bfdd/bfd_packet.c | 46 | ||||
-rw-r--r-- | bfdd/bfdd_vty.c | 41 |
4 files changed, 103 insertions, 11 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index a16192635..a1fb67d35 100644 --- a/bfdd/bfd.c +++ b/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; +} diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 48a1e0bc3..a5881cddb 100644 --- a/bfdd/bfd.h +++ b/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. diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index e2a44bce7..98411a873 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -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; diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index a9fc71617..21429f06c 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -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. |