Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
Re: bgpctl: print absolute timestamps for mrt dumps
To:
tech@openbsd.org
Date:
Thu, 21 May 2026 16:11:22 +0200

Download raw body.

Thread
On Thu, May 21, 2026 at 03:22:24PM +0200, Claudio Jeker wrote:
> 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

ok tb

> 
> -- 
> :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));
>  }
>  
>