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