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

Reply via email to