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