bgp: use monotonic clock for time of day
BGP uses time() to get system time of day; but that value
fluctuates with time adjustments from NTP. This can cause premature
flapping of peer sessions and other failures.
Use the system monotonic clock supported by Quagga thread library
to avoid issue.
See: http://bugzilla.vyatta.com/show_bug.cgi?id=4467
* bgpd/bgp_fsm.c
* bgp_uptime_reset(): dismiss function
* bgpd/bgpd.c
* bgp_clock(): new function
* bgpd/bgp_damp.c
* bgp_reuse_timer(): employ bgp_clock() instead of time(NULL)
* bgp_damp_withdraw(): idem
* bgp_damp_update(): idem
* bgp_damp_scan(): idem
* bgp_damp_info_vty(): idem
* bgp_damp_reuse_time_vty(): idem
* bgpd/bgp_fsm.c
* bgp_routeadv_timer(): idem
* bgp_stop(): idem
* bgp_establish(): idem
* bgpd/bgp_packet.c
* bgp_update_receive(): idem
* bgpd/bgp_route.c
* bgp_update_rsclient(): idem
* bgp_update_main(): idem
* bgp_static_update_rsclient(): idem
* bgp_static_update_main(): idem
* bgp_static_update_vpnv4(): idem
* bgp_aggregate_route(): idem
* bgp_aggregate_add(): idem
* bgp_redistribute_add(): idem
* bgpd/bgp_snmp.c
* bgpPeerTable(): idem
* bgpTrapEstablished(): idem
* bgpTrapBackwardTransition(): idem
* bgpd/bgpd.c
* peer_create(): idem
* peer_uptime(): idem
* bgp_master_init(): idem
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index e21131e..ba059f8 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -117,7 +117,7 @@
damp->t_reuse =
thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
- t_now = time (NULL);
+ t_now = bgp_clock ();
/* 1. save a pointer to the current zeroth queue head and zero the
list head entry. */
@@ -181,7 +181,7 @@
struct bgp_damp_info *bdi = NULL;
double last_penalty = 0;
- t_now = time (NULL);
+ t_now = bgp_clock ();
/* Processing Unreachable Messages. */
if (binfo->extra)
@@ -268,7 +268,7 @@
if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
return BGP_DAMP_USED;
- t_now = time (NULL);
+ t_now = bgp_clock ();
bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
bdi->lastrecord = BGP_RECORD_UPDATE;
@@ -306,7 +306,7 @@
assert (binfo->extra && binfo->extra->damp_info);
- t_now = time (NULL);
+ t_now = bgp_clock ();
bdi = binfo->extra->damp_info;
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
@@ -597,7 +597,7 @@
return;
/* Calculate new penalty. */
- t_now = time (NULL);
+ t_now = bgp_clock ();
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay (t_diff, bdi->penalty);
@@ -633,7 +633,7 @@
return NULL;
/* Calculate new penalty. */
- t_now = time (NULL);
+ t_now = bgp_clock ();
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay (t_diff, bdi->penalty);
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index c815f9a..487ebdd 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -305,7 +305,7 @@
"%s [FSM] Timer (routeadv timer expire)",
peer->host);
- peer->synctime = time (NULL);
+ peer->synctime = bgp_clock ();
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
@@ -315,13 +315,6 @@
return 0;
}
-/* Reset bgp update timer */
-static void
-bgp_uptime_reset (struct peer *peer)
-{
- peer->uptime = time (NULL);
-}
-
/* BGP Peer Down Cause */
const char *peer_down_str[] =
{
@@ -493,17 +486,12 @@
}
/* set last reset time */
- peer->resettime = time (NULL);
- /* Reset uptime. */
- bgp_uptime_reset (peer);
+ peer->resettime = peer->uptime = bgp_clock ();
#ifdef HAVE_SNMP
bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */
- /* Reset uptime. */
- bgp_uptime_reset (peer);
-
/* Reset peer synctime */
peer->synctime = 0;
}
@@ -857,7 +845,7 @@
#endif /* HAVE_SNMP */
/* Reset uptime, send keepalive, send current table. */
- bgp_uptime_reset (peer);
+ peer->uptime = bgp_clock ();
/* Send route-refresh when ORF is enabled */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 6153419..b29bc1f 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1805,7 +1805,7 @@
/* Increment packet counter. */
peer->update_in++;
- peer->update_time = time (NULL);
+ peer->update_time = bgp_clock ();
/* Generate BGP event. */
BGP_EVENT_ADD (peer, Receive_UPDATE_message);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f3144fe..a92ca4e 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1878,7 +1878,7 @@
/* If the update is implicit withdraw. */
if (ri)
{
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Same attribute comes in. */
if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
@@ -1946,7 +1946,7 @@
new->sub_type = sub_type;
new->peer = peer;
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
@@ -2133,7 +2133,7 @@
/* If the update is implicit withdraw. */
if (ri)
{
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Same attribute comes in. */
if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
@@ -2284,7 +2284,7 @@
new->sub_type = sub_type;
new->peer = peer;
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
@@ -3337,7 +3337,7 @@
bgp_info_restore(rn, ri);
bgp_attr_unintern (ri->attr);
ri->attr = attr_new;
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Process change. */
bgp_process (bgp, rn, afi, safi);
@@ -3355,7 +3355,7 @@
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Register new BGP information. */
bgp_info_add (rn, new);
@@ -3463,7 +3463,7 @@
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
bgp_attr_unintern (ri->attr);
ri->attr = attr_new;
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Process change. */
bgp_aggregate_increment (bgp, p, ri, afi, safi);
@@ -3482,7 +3482,7 @@
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -3533,7 +3533,7 @@
new->peer = bgp->peer_self;
new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
new->extra = bgp_info_extra_new();
memcpy (new->extra->tag, tag, 3);
@@ -4729,7 +4729,7 @@
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
@@ -4900,7 +4900,7 @@
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
@@ -5514,7 +5514,7 @@
bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
bgp_attr_unintern (bi->attr);
bi->attr = new_attr;
- bi->uptime = time (NULL);
+ bi->uptime = bgp_clock ();
/* Process change. */
bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
@@ -5532,7 +5532,7 @@
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = new_attr;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
bgp_info_add (bn, new);
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index 1e37f26..86cc087 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -546,7 +546,7 @@
if (peer->uptime == 0)
return SNMP_INTEGER (0);
else
- return SNMP_INTEGER (time (NULL) - peer->uptime);
+ return SNMP_INTEGER (bgp_clock () - peer->uptime);
break;
case BGPPEERCONNECTRETRYINTERVAL:
*write_method = write_bgpPeerTable;
@@ -584,7 +584,7 @@
if (peer->update_time == 0)
return SNMP_INTEGER (0);
else
- return SNMP_INTEGER (time (NULL) - peer->update_time);
+ return SNMP_INTEGER (bgp_clock () - peer->update_time);
break;
default:
return NULL;
@@ -859,7 +859,7 @@
smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
- bm->start_time - time (NULL), BGPESTABLISHED);
+ bm->start_time - bgp_clock (), BGPESTABLISHED);
}
void
@@ -878,7 +878,7 @@
smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
- bm->start_time - time (NULL), BGPBACKWARDTRANSITION);
+ bm->start_time - bgp_clock (), BGPBACKWARDTRANSITION);
}
void
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index cf3a6b4..882fe37 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -241,6 +241,17 @@
return 0;
}
+/* time_t value that is monotonicly increasing
+ * and uneffected by adjustments to system clock
+ */
+time_t bgp_clock (void)
+{
+ struct timeval tv;
+
+ quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
+ return tv.tv_sec;
+}
+
/* BGP timer configuration. */
int
bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
@@ -850,11 +861,8 @@
if (afi && safi)
peer->afc[afi][safi] = 1;
- /* Last read time set */
- peer->readtime = time (NULL);
-
- /* Last reset time set */
- peer->resettime = time (NULL);
+ /* Last read and reset time set */
+ peer->readtime = peer->resettime = bgp_clock ();
/* Default TTL set. */
peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
@@ -4453,7 +4461,7 @@
}
/* Get current time. */
- uptime1 = time (NULL);
+ uptime1 = bgp_clock ();
uptime1 -= uptime2;
tm = gmtime (&uptime1);
@@ -5145,7 +5153,7 @@
bm->listen_sockets = list_new ();
bm->port = BGP_PORT_DEFAULT;
bm->master = thread_master_create ();
- bm->start_time = time (NULL);
+ bm->start_time = bgp_clock ();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index f4ce898..a5afaed 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -809,6 +809,7 @@
/* Prototypes. */
extern void bgp_terminate (void);
extern void bgp_reset (void);
+extern time_t bgp_clock (void);
extern void bgp_zclient_reset (void);
extern int bgp_nexthop_set (union sockunion *, union sockunion *,
struct bgp_nexthop *, struct peer *);