Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpctl: print absolute timestamps for mrt dumps
To:
tech@openbsd.org
Date:
Thu, 21 May 2026 15:22:24 +0200

Download raw body.

Thread
bgpctl show mrt detail currently show entries with
    Last update: Never ago

This comes from the fact that most mrt dumps come from the past and bgpctl
tries to print the Last update as a relative timeframe based on the
monotonic clock.

So for 'show mrt' switch fmt_monotime() to absolute timestamps.
Remove the 'ago' from the Last update line and print the timestamp using
monotime_to_time, gmtime and strftime("%FT%TZ") to get a ISO format
timestamp string.

While there also adjust get_rel_monotime() to be more like
monotime_to_time() and stop treating negative numbers as error.
In fmt_monotime() instead compare the time against 0 to print Never.

With this the mrt dump I have now shows this:
    Last update: 2019-05-08T20:03:06Z

-- 
:wq Claudio

Index: bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
diff -u -p -r1.321 bgpctl.c
--- bgpctl.c	18 May 2026 18:37:22 -0000	1.321
+++ bgpctl.c	21 May 2026 13:12:58 -0000
@@ -66,6 +66,7 @@ struct mrt_parser net_mrt = { network_mr
 const struct output	*output = &show_output;
 int tableid;
 int nodescr;
+int abs_time;
 
 __dead void
 usage(void)
@@ -134,6 +135,7 @@ main(int argc, char *argv[])
 		if (pledge("stdio", NULL) == -1)
 			err(1, "pledge");
 
+		abs_time = 1;
 		memset(&ribreq, 0, sizeof(ribreq));
 		if (res->as.type != AS_UNDEF)
 			ribreq.as = res->as;
@@ -588,14 +590,10 @@ show(struct imsg *imsg, struct parse_res
 }
 
 time_t
-get_rel_monotime(monotime_t t)
+get_rel_monotime(monotime_t mt)
 {
-	monotime_t now;
-
-	if (!monotime_valid(t))
-		return 0;
-	now = getmonotime();
-	return monotime_to_sec(monotime_sub(now, t));
+	mt = monotime_sub(getmonotime(), mt);
+	return monotime_to_sec(mt);
 }
 
 char *
@@ -644,7 +642,7 @@ fmt_auth_method(enum auth_method method)
 	}
 }
 
-#define TF_LEN	16
+#define TF_LEN	64
 
 static const char *
 fmt_timeframe(time_t t)
@@ -670,7 +668,7 @@ fmt_timeframe(time_t t)
 	week /= 7;
 
 	if (week >= 1000)
-		snprintf(buf, sizeof(buf), "%s%02lluw", due, week);
+		snprintf(buf, sizeof(buf), "%s%lluw", due, week);
 	else if (week > 0)
 		snprintf(buf, sizeof(buf), "%s%02lluw%01ud%02uh",
 		    due, week, day, hrs);
@@ -688,12 +686,23 @@ const char *
 fmt_monotime(monotime_t mt)
 {
 	time_t t;
+	monotime_t z = monotime_clear();
 
-	if (!monotime_valid(mt))
-		return ("Never");
-
-	t = get_rel_monotime(mt);
-	return (fmt_timeframe(t));
+	if (abs_time) {
+		struct tm *tm;
+		static char buf[TF_LEN];
+
+		t = monotime_to_time(mt);
+		if ((tm = gmtime(&t)) == NULL)
+			return "invalid";
+		strftime(buf, sizeof(buf), "%FT%TZ", tm);
+		return (buf);
+	} else {
+		if (monotime_cmp(mt, z) == 0)
+			return ("Never");
+		t = get_rel_monotime(mt);
+		return (fmt_timeframe(t));
+	}
 }
 
 const char *
Index: output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
diff -u -p -r1.76 output.c
--- output.c	18 May 2026 09:22:09 -0000	1.76
+++ output.c	21 May 2026 12:49:51 -0000
@@ -1045,7 +1045,7 @@ show_rib_detail(struct ctl_show_rib *r, 
 	printf("avs %s, %s", fmt_avs(r->aspa_validation_state, 0),
 	    fmt_flags(r->flags, 0));
 
-	printf("%c    Last update: %s ago%c", EOL0(flag0),
+	printf("%c    Last update: %s%c", EOL0(flag0),
 	    fmt_monotime(r->lastchange), EOL0(flag0));
 }