Browse Source

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
Stephen Hemminger 11 years ago
parent
commit
65957886bf
7 changed files with 43 additions and 46 deletions
  1. 6 6
      bgpd/bgp_damp.c
  2. 3 15
      bgpd/bgp_fsm.c
  3. 1 1
      bgpd/bgp_packet.c
  4. 13 13
      bgpd/bgp_route.c
  5. 4 4
      bgpd/bgp_snmp.c
  6. 15 7
      bgpd/bgpd.c
  7. 1 0
      bgpd/bgpd.h

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

+ 3 - 15
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++)

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

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

+ 4 - 4
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

+ 15 - 7
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 ();
 }
 
 

+ 1 - 0
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 *);