summaryrefslogtreecommitdiffstats
path: root/bfdd
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@users.noreply.github.com>2022-08-09 17:20:24 +0200
committerGitHub <noreply@github.com>2022-08-09 17:20:24 +0200
commitac2f410c379a8cef0abade46a2d2ef351b8f38a7 (patch)
tree6150e660037020a62132b39c877687a55e82e0b9 /bfdd
parentMerge pull request #11752 from opensourcerouting/fix/update_policy_on_filters (diff)
parentDoc: Update documentation for BFD Echo. (diff)
downloadfrr-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.c17
-rw-r--r--bfdd/bfd.h10
-rw-r--r--bfdd/bfd_packet.c46
-rw-r--r--bfdd/bfdd_vty.c41
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.