From 65957886bfd0dd9d95360d8b015781fc82cc09be Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 15 Jan 2010 16:22:10 +0300 Subject: 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 --- bgpd/bgp_damp.c | 12 ++++++------ bgpd/bgp_fsm.c | 18 +++--------------- bgpd/bgp_packet.c | 2 +- bgpd/bgp_route.c | 26 +++++++++++++------------- bgpd/bgp_snmp.c | 8 ++++---- bgpd/bgpd.c | 22 +++++++++++++++------- bgpd/bgpd.h | 1 + 7 files changed, 43 insertions(+), 46 deletions(-) diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index e21131ef..ba059f8c 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -117,7 +117,7 @@ bgp_reuse_timer (struct thread *t) 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 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn, 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 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, 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 @@ bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi) 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 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo) 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 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo, 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 c815f9a1..487ebddb 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -305,7 +305,7 @@ bgp_routeadv_timer (struct thread *thread) "%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 @@ bgp_routeadv_timer (struct thread *thread) 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 @@ bgp_stop (struct peer *peer) } /* 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 @@ bgp_establish (struct peer *peer) #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 61534191..b29bc1f0 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1805,7 +1805,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) /* 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 f3144fea..a92ca4e2 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1878,7 +1878,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* 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 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, 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 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* 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 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, 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_static_update_rsclient (struct peer *rsclient, struct prefix *p, 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 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, 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_static_update_main (struct bgp *bgp, struct prefix *p, 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 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, 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 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi, 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 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, 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 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, 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_redistribute_add (struct prefix *p, struct in_addr *nexthop, 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 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, 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 1e37f266..86cc0879 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -546,7 +546,7 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length, 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 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length, 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 @@ bgpTrapEstablished (struct peer *peer) 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 @@ bgpTrapBackwardTransition (struct peer *peer) 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 cf3a6b42..882fe37c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -241,6 +241,17 @@ bgp_cluster_id_unset (struct bgp *bgp) 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 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as, 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 @@ peer_uptime (time_t uptime2, char *buf, size_t len) } /* Get current time. */ - uptime1 = time (NULL); + uptime1 = bgp_clock (); uptime1 -= uptime2; tm = gmtime (&uptime1); @@ -5145,7 +5153,7 @@ bgp_master_init (void) 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 f4ce8985..a5afaedc 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -809,6 +809,7 @@ extern struct thread_master *master; /* 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 *); -- cgit v1.2.1