On Tue, Dec 31, 2019 at 04:32:24PM +0100, Claudio Jeker wrote:
> This changes bgpd to only use CLOCK_MONOTONIC via the getmonotime()
> function. Additionally it changes the export of RIB entries to report the
> last modified time relative to now. Other places also needed some fixup,
> like the mrt dump code since the Originated Time field in those messages
> is epoch based.
>
> It would be nice to also send the last_read, last_write, and last_updown in
> a relative form to bgpctl but that is more complex.
>
> In bgpctl fmt_timeframe is now for relative timestamps and fmt_monotime
> for those using CLOCK_MONOTONIC. The goal is to remove the latter once
> last_read and friends got changed.
>
> OK?
OK denis@
> --
> :wq Claudio
>
> Index: bgpctl/bgpctl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
> retrieving revision 1.255
> diff -u -p -r1.255 bgpctl.c
> --- bgpctl/bgpctl.c 31 Dec 2019 14:09:27 -0000 1.255
> +++ bgpctl/bgpctl.c 31 Dec 2019 15:31:39 -0000
> @@ -595,8 +595,8 @@ print_neighbor_msgstats(struct peer *p)
> #define TF_BUFS 8
> #define TF_LEN 9
>
> -static const char *
> -fmt_timeframe_core(time_t t)
> +const char *
> +fmt_timeframe(time_t t)
> {
> char *buf;
> static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
> @@ -630,17 +630,18 @@ fmt_timeframe_core(time_t t)
> }
>
> const char *
> -fmt_timeframe(time_t t)
> +fmt_monotime(time_t t)
> {
> - time_t now;
> + struct timespec ts;
>
> if (t == 0)
> return ("Never");
>
> - now = time(NULL);
> - if (t > now) /* time in the future is not possible */
> - t = now;
> - return (fmt_timeframe_core(now - t));
> + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
> + err(1, "clock_gettime");
> + if (t > ts.tv_sec) /* time in the future is not possible */
> + t = ts.tv_sec;
> + return (fmt_timeframe(ts.tv_sec - t));
> }
>
> void
> @@ -1414,17 +1415,20 @@ show_mrt_dump(struct mrt_rib *mr, struct
> struct parse_result res;
> struct ctl_show_rib_request *req = arg;
> struct mrt_rib_entry *mre;
> + time_t now;
> u_int16_t i, j;
>
> memset(&res, 0, sizeof(res));
> res.flags = req->flags;
> + now = time(NULL);
>
> for (i = 0; i < mr->nentries; i++) {
> mre = &mr->entries[i];
> bzero(&ctl, sizeof(ctl));
> ctl.prefix = mr->prefix;
> ctl.prefixlen = mr->prefixlen;
> - ctl.lastchange = mre->originated;
> + if (mre->originated <= now)
> + ctl.age = now - mre->originated;
> ctl.true_nexthop = mre->nexthop;
> ctl.exit_nexthop = mre->nexthop;
> ctl.origin = mre->origin;
> @@ -1490,14 +1494,17 @@ network_mrt_dump(struct mrt_rib *mr, str
> struct ctl_show_rib_request *req = arg;
> struct mrt_rib_entry *mre;
> struct ibuf *msg;
> + time_t now;
> u_int16_t i, j;
>
> + now = time(NULL);
> for (i = 0; i < mr->nentries; i++) {
> mre = &mr->entries[i];
> bzero(&ctl, sizeof(ctl));
> ctl.prefix = mr->prefix;
> ctl.prefixlen = mr->prefixlen;
> - ctl.lastchange = mre->originated;
> + if (mre->originated <= now)
> + ctl.age = now - mre->originated;
> ctl.true_nexthop = mre->nexthop;
> ctl.exit_nexthop = mre->nexthop;
> ctl.origin = mre->origin;
> Index: bgpctl/bgpctl.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
> retrieving revision 1.2
> diff -u -p -r1.2 bgpctl.h
> --- bgpctl/bgpctl.h 31 Dec 2019 14:09:27 -0000 1.2
> +++ bgpctl/bgpctl.h 31 Dec 2019 15:31:39 -0000
> @@ -44,6 +44,7 @@ const char *print_auth_method(enum auth_
> const char *fmt_mem(long long);
>
> const char *fmt_timeframe(time_t);
> +const char *fmt_monotime(time_t);
> char *fmt_peer(const char *, const struct bgpd_addr *, int);
> const char *get_errstr(u_int8_t, u_int8_t);
>
> Index: bgpctl/output.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 output.c
> --- bgpctl/output.c 31 Dec 2019 14:09:27 -0000 1.2
> +++ bgpctl/output.c 31 Dec 2019 15:31:39 -0000
> @@ -111,7 +111,7 @@ show_summary(struct peer *p)
> p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
> p->stats.msg_sent_rrefresh,
> p->wbuf.queued,
> - fmt_timeframe(p->stats.last_updown));
> + fmt_monotime(p->stats.last_updown));
> if (p->state == STATE_ESTABLISHED) {
> printf("%6u", p->stats.prefix_cnt);
> if (p->conf.max_prefix != 0)
> @@ -182,11 +182,12 @@ show_neighbor_full(struct peer *p, struc
> if (p->stats.last_updown != 0)
> printf(", %s for %s",
> p->state == STATE_ESTABLISHED ? "up" : "down",
> - fmt_timeframe(p->stats.last_updown));
> + fmt_monotime(p->stats.last_updown));
> printf("\n");
> printf(" Last read %s, holdtime %us, keepalive interval %us\n",
> - fmt_timeframe(p->stats.last_read),
> + fmt_monotime(p->stats.last_read),
> p->holdtime, p->holdtime/3);
> + printf(" Last write %s\n", fmt_monotime(p->stats.last_write));
> for (i = 0; i < AID_MAX; i++)
> if (p->capa.peer.mp[i])
> hascapamp = 1;
> @@ -288,7 +289,7 @@ show_timer(struct ctl_timer *t)
> if (t->val <= 0)
> printf("%-20s\n", "due");
> else
> - printf("due in %-13s\n", fmt_timeframe(time(NULL) - t->val));
> + printf("due in %-13s\n", fmt_timeframe(t->val));
> }
>
> void
> @@ -432,7 +433,7 @@ show_rib_detail(struct ctl_show_rib *r,
> print_flags(r->flags, 0);
>
> printf("%c Last update: %s ago%c", EOL0(flag0),
> - fmt_timeframe(r->lastchange), EOL0(flag0));
> + fmt_timeframe(r->age), EOL0(flag0));
> }
>
> void
> Index: bgpd/bgpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
> retrieving revision 1.395
> diff -u -p -r1.395 bgpd.h
> --- bgpd/bgpd.h 27 Nov 2019 01:21:54 -0000 1.395
> +++ bgpd/bgpd.h 31 Dec 2019 15:31:40 -0000
> @@ -711,7 +711,7 @@ struct ctl_show_rib {
> struct bgpd_addr prefix;
> struct bgpd_addr remote_addr;
> char descr[PEER_DESCR_LEN];
> - time_t lastchange;
> + time_t age;
> u_int32_t remote_id;
> u_int32_t local_pref;
> u_int32_t med;
> @@ -1290,6 +1290,9 @@ int trie_roa_check(struct trie_head *, s
> u_int32_t);
> void trie_dump(struct trie_head *);
> int trie_equal(struct trie_head *, struct trie_head *);
> +
> +/* timer.c */
> +time_t getmonotime(void);
>
> /* util.c */
> const char *log_addr(const struct bgpd_addr *);
> Index: bgpd/mrt.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/mrt.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 mrt.c
> --- bgpd/mrt.c 31 Dec 2019 12:02:47 -0000 1.101
> +++ bgpd/mrt.c 31 Dec 2019 15:31:40 -0000
> @@ -323,7 +323,8 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
>
> DUMP_SHORT(h2buf, 0); /* view */
> DUMP_SHORT(h2buf, 1); /* status */
> - DUMP_LONG(h2buf, p->lastchange); /* originated */
> + /* originated timestamp */
> + DUMP_LONG(h2buf, time(NULL) - (getmonotime() - p->lastchange));
>
> pt_getaddr(p->pt, &addr);
>
> @@ -459,7 +460,8 @@ mrt_dump_entry(struct mrt *mrt, struct p
> DUMP_BYTE(hbuf, p->pt->prefixlen);
>
> DUMP_BYTE(hbuf, 1); /* state */
> - DUMP_LONG(hbuf, p->lastchange); /* originated */
> + /* originated timestamp */
> + DUMP_LONG(hbuf, time(NULL) - (getmonotime() - p->lastchange));
> switch (p->pt->aid) {
> case AID_INET:
> DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr);
> @@ -547,7 +549,8 @@ mrt_dump_entry_v2(struct mrt *mrt, struc
> nh = &nexthop->exit_nexthop;
>
> DUMP_SHORT(buf, prefix_peer(p)->mrt_idx);
> - DUMP_LONG(buf, p->lastchange); /* originated */
> + /* originated timestamp */
> + DUMP_LONG(buf, time(NULL) - (getmonotime() - p->lastchange));
>
> if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
> log_warn("%s: ibuf_dynamic", __func__);
> Index: bgpd/rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> retrieving revision 1.494
> diff -u -p -r1.494 rde.c
> --- bgpd/rde.c 31 Dec 2019 11:53:46 -0000 1.494
> +++ bgpd/rde.c 31 Dec 2019 15:31:41 -0000
> @@ -2222,7 +2222,7 @@ rde_dump_rib_as(struct prefix *p, struct
>
> nexthop = prefix_nexthop(p);
> bzero(&rib, sizeof(rib));
> - rib.lastchange = p->lastchange;
> + rib.age = getmonotime() - p->lastchange;
> rib.local_pref = asp->lpref;
> rib.med = asp->med;
> rib.weight = asp->weight;
> @@ -3875,7 +3875,7 @@ peer_stale(struct rde_peer *peer, u_int8
> if (peer->staletime[aid])
> peer_flush(peer, aid, peer->staletime[aid]);
>
> - peer->staletime[aid] = now = time(NULL);
> + peer->staletime[aid] = now = getmonotime();
> peer->state = PEER_DOWN;
>
> /* mark Adj-RIB-Out stale for this peer */
> @@ -3884,7 +3884,7 @@ peer_stale(struct rde_peer *peer, u_int8
> fatal("%s: prefix_dump_new", __func__);
>
> /* make sure new prefixes start on a higher timestamp */
> - while (now >= time(NULL))
> + while (now >= getmonotime())
> sleep(1);
> }
>
> Index: bgpd/rde_rib.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
> retrieving revision 1.210
> diff -u -p -r1.210 rde_rib.c
> --- bgpd/rde_rib.c 30 Oct 2019 05:27:50 -0000 1.210
> +++ bgpd/rde_rib.c 31 Dec 2019 15:31:41 -0000
> @@ -983,7 +983,7 @@ prefix_update(struct rib *rib, struct rd
> communities_equal(ncomm, prefix_communities(p)) &&
> path_compare(nasp, prefix_aspath(p)) == 0) {
> /* no change, update last change */
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
> p->validation_state = vstate;
> return (0);
> }
> @@ -1058,7 +1058,7 @@ prefix_move(struct prefix *p, struct rde
> np->nhflags = nhflags;
> np->nexthop = nexthop_ref(nexthop);
> nexthop_link(np);
> - np->lastchange = time(NULL);
> + np->lastchange = getmonotime();
>
> /*
> * no need to update the peer prefix count because we are only moving
> @@ -1168,7 +1168,7 @@ prefix_adjout_update(struct rde_peer *pe
> 0) {
> /* nothing changed */
> p->validation_state = vstate;
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
> p->flags &= ~PREFIX_FLAG_STALE;
> return 0;
> }
> @@ -1217,7 +1217,7 @@ prefix_adjout_update(struct rde_peer *pe
> p->nhflags = state->nhflags;
>
> p->validation_state = vstate;
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
>
> if (p->flags & PREFIX_FLAG_MASK)
> fatalx("%s: bad flags %x", __func__, p->flags);
> @@ -1244,7 +1244,7 @@ prefix_adjout_withdraw(struct rde_peer *
>
> /* already a withdraw, shortcut */
> if (p->flags & PREFIX_FLAG_WITHDRAW) {
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
> p->flags &= ~PREFIX_FLAG_STALE;
> return (0);
> }
> @@ -1271,7 +1271,7 @@ prefix_adjout_withdraw(struct rde_peer *
> p->aspath = NULL;
> /* re already NULL */
>
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
>
> p->flags |= PREFIX_FLAG_WITHDRAW;
> if (RB_INSERT(prefix_tree, &peer->withdraws[prefix->aid], p) != NULL)
> @@ -1599,7 +1599,7 @@ prefix_link(struct prefix *p, struct rib
> p->nhflags = nhflags;
> p->nexthop = nexthop_ref(nexthop);
> nexthop_link(p);
> - p->lastchange = time(NULL);
> + p->lastchange = getmonotime();
>
> /* make route decision */
> prefix_evaluate(p, re);
> Index: bgpd/session.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
> retrieving revision 1.395
> diff -u -p -r1.395 session.c
> --- bgpd/session.c 2 Oct 2019 08:57:00 -0000 1.395
> +++ bgpd/session.c 31 Dec 2019 15:31:42 -0000
> @@ -252,7 +252,7 @@ session_main(int debug, int verbose)
> /* cloned peer that idled out? */
> if (p->template && (p->state == STATE_IDLE ||
> p->state == STATE_ACTIVE) &&
> - time(NULL) - p->stats.last_updown >=
> + getmonotime() - p->stats.last_updown >=
> INTERVAL_HOLD_CLONED)
> p->reconf_action = RECONF_DELETE;
>
> @@ -1701,6 +1701,7 @@ session_dispatch_msg(struct pollfd *pfd,
> bgp_fsm(p, EVNT_CON_FATAL);
> return (1);
> }
> + p->stats.last_write = getmonotime();
> if (p->throttled && p->wbuf.queued < SESS_MSG_LOW_MARK) {
> if (imsg_rde(IMSG_XON, p->conf.id, NULL, 0) == -1)
> log_peer_warn(&p->conf, "imsg_compose XON");
> @@ -1726,7 +1727,7 @@ session_dispatch_msg(struct pollfd *pfd,
> }
>
> p->rbuf->wpos += n;
> - p->stats.last_read = time(NULL);
> + p->stats.last_read = getmonotime();
> return (1);
> }
> return (0);
> @@ -3048,7 +3049,7 @@ void
> session_down(struct peer *peer)
> {
> bzero(&peer->capa.neg, sizeof(peer->capa.neg));
> - peer->stats.last_updown = time(NULL);
> + peer->stats.last_updown = getmonotime();
> /*
> * session_down is called in the exit code path so check
> * if the RDE is still around, if not there is no need to
> @@ -3075,7 +3076,7 @@ session_up(struct peer *p)
> sup.remote_bgpid = p->remote_bgpid;
> sup.short_as = p->short_as;
> memcpy(&sup.capa, &p->capa.neg, sizeof(sup.capa));
> - p->stats.last_updown = time(NULL);
> + p->stats.last_updown = getmonotime();
> if (imsg_rde(IMSG_SESSION_UP, p->conf.id, &sup, sizeof(sup)) == -1)
> fatalx("imsg_compose error");
> }
> Index: bgpd/session.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/session.h,v
> retrieving revision 1.141
> diff -u -p -r1.141 session.h
> --- bgpd/session.h 1 Oct 2019 11:05:30 -0000 1.141
> +++ bgpd/session.h 31 Dec 2019 15:31:42 -0000
> @@ -167,6 +167,7 @@ struct peer_stats {
> unsigned long long prefix_sent_eor;
> time_t last_updown;
> time_t last_read;
> + time_t last_write;
> u_int32_t prefix_cnt;
> u_int8_t last_sent_errcode;
> u_int8_t last_sent_suberr;
> @@ -310,7 +311,6 @@ int imsg_ctl_rde(int, pid_t, void *, u
> void session_stop(struct peer *, u_int8_t);
>
> /* timer.c */
> -time_t getmonotime(void);
> struct peer_timer *timer_get(struct peer *, enum Timer);
> struct peer_timer *timer_nextisdue(struct peer *, time_t);
> time_t timer_nextduein(struct peer *, time_t);
>