This diffs adds timestamps similar to kdump to bgpctl show mrt output when messages or states are shown.
Currently it looks like this: 1531425344.000000 153.5.146.105[23456] -> 62.48.0.253[0]: size 63 0.000000 153.5.146.105[23456] -> 62.48.0.253[0]: Connect -> OpenSent 0.000000 153.5.146.105[23456] -> 62.48.0.252[0]: size 63 0.000000 153.5.146.105[23456] -> 62.48.0.252[0]: Connect -> OpenSent 0.000000 153.5.146.105[196618] -> 62.48.0.253[8271]: size 19 0.000000 153.5.146.105[196618] -> 62.48.0.253[8271]: OpenSent -> OpenConfirm 0.000000 153.5.146.105[196618] -> 62.48.0.252[8271]: size 19 0.000000 153.5.146.105[196618] -> 62.48.0.252[8271]: OpenSent -> OpenConfirm 0.000000 153.5.146.105[196618] -> 62.48.0.253[8271]: OpenConfirm -> Established 0.000000 153.5.146.105[196618] -> 62.48.0.252[8271]: OpenConfirm -> Established 0.000000 153.5.146.105[196618] -> 62.48.0.253[8271]: size 23 0.000000 153.5.146.105[196618] -> 62.48.0.252[8271]: size 23 My dump did not include microseconds yet so they are all 0. OK? -- :wq Claudio Index: bgpctl.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v retrieving revision 1.205 diff -u -p -r1.205 bgpctl.c --- bgpctl.c 12 Jul 2018 21:45:37 -0000 1.205 +++ bgpctl.c 17 Jul 2018 16:29:48 -0000 @@ -2010,6 +2010,20 @@ network_mrt_dump(struct mrt_rib *mr, str } } +static const char * +print_time(struct timespec *t) +{ + static char timebuf[32]; + static struct timespec prevtime; + struct timespec temp; + + timespecsub(t, &prevtime, &temp); + snprintf(timebuf, sizeof(timebuf), "%lld.%06ld", + (long long)temp.tv_sec, temp.tv_nsec / 1000); + prevtime = *t; + return (timebuf); +} + void show_mrt_state(struct mrt_bgp_state *ms, void *arg) { @@ -2017,7 +2031,8 @@ show_mrt_state(struct mrt_bgp_state *ms, mrt_to_bgpd_addr(&ms->src, &src); mrt_to_bgpd_addr(&ms->dst, &dst); - printf("%s[%u] -> ", log_addr(&src), ms->src_as); + printf("%s %s[%u] -> ", print_time(&ms->time), + log_addr(&src), ms->src_as); printf("%s[%u]: %s -> %s\n", log_addr(&dst), ms->dst_as, statenames[ms->old_state], statenames[ms->new_state]); } @@ -2029,7 +2044,8 @@ show_mrt_msg(struct mrt_bgp_msg *mm, voi mrt_to_bgpd_addr(&mm->src, &src); mrt_to_bgpd_addr(&mm->dst, &dst); - printf("%s[%u] -> ", log_addr(&src), mm->src_as); + printf("%s %s[%u] -> ", print_time(&mm->time), + log_addr(&src), mm->src_as); printf("%s[%u]: size %u\n", log_addr(&dst), mm->dst_as, mm->msg_len); } Index: mrtparser.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.c,v retrieving revision 1.8 diff -u -p -r1.8 mrtparser.c --- mrtparser.c 23 Dec 2015 20:42:20 -0000 1.8 +++ mrtparser.c 17 Jul 2018 16:26:09 -0000 @@ -23,6 +23,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <time.h> #include <unistd.h> #include "mrt.h" @@ -990,14 +991,26 @@ mrt_extract_addr(void *msg, u_int len, u struct mrt_bgp_state * mrt_parse_state(struct mrt_hdr *hdr, void *msg) { + struct timespec t; struct mrt_bgp_state *s; u_int8_t *b = msg; u_int len = ntohl(hdr->length); - u_int32_t sas, das; + u_int32_t sas, das, usec; u_int16_t tmp16, afi; int r; sa_family_t af; + t.tv_sec = ntohl(hdr->timestamp); + t.tv_nsec = 0; + + /* handle the microsec field for _ET header */ + if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { + memcpy(&usec, b, sizeof(usec)); + b += sizeof(usec); + len -= sizeof(usec); + t.tv_nsec = ntohl(usec) * 1000; + } + switch (ntohs(hdr->subtype)) { case BGP4MP_STATE_CHANGE: if (len < 8) @@ -1061,6 +1074,7 @@ mrt_parse_state(struct mrt_hdr *hdr, voi if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL) err(1, "calloc"); + s->time = t; s->src_as = sas; s->dst_as = das; @@ -1093,14 +1107,26 @@ fail: struct mrt_bgp_msg * mrt_parse_msg(struct mrt_hdr *hdr, void *msg) { + struct timespec t; struct mrt_bgp_msg *m; u_int8_t *b = msg; u_int len = ntohl(hdr->length); - u_int32_t sas, das; + u_int32_t sas, das, usec; u_int16_t tmp16, afi; int r; sa_family_t af; + t.tv_sec = ntohl(hdr->timestamp); + t.tv_nsec = 0; + + /* handle the microsec field for _ET header */ + if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { + memcpy(&usec, b, sizeof(usec)); + b += sizeof(usec); + len -= sizeof(usec); + t.tv_nsec = ntohl(usec) * 1000; + } + switch (ntohs(hdr->subtype)) { case BGP4MP_MESSAGE: if (len < 8) @@ -1164,6 +1190,7 @@ mrt_parse_msg(struct mrt_hdr *hdr, void if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL) err(1, "calloc"); + m->time = t; m->src_as = sas; m->dst_as = das; Index: mrtparser.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.h,v retrieving revision 1.1 diff -u -p -r1.1 mrtparser.h --- mrtparser.h 21 Sep 2011 10:37:51 -0000 1.1 +++ mrtparser.h 17 Jul 2018 16:26:09 -0000 @@ -77,6 +77,7 @@ struct mrt_rib { /* data structures for the BGP4MP MESSAGE and STATE types */ struct mrt_bgp_state { + struct timespec time; union mrt_addr src; union mrt_addr dst; u_int32_t src_as; @@ -86,6 +87,7 @@ struct mrt_bgp_state { }; struct mrt_bgp_msg { + struct timespec time; union mrt_addr src; union mrt_addr dst; u_int32_t src_as;