]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgp: use monotonic clock for time of day
authorStephen Hemminger <shemminger@vyatta.com>
Fri, 15 Jan 2010 13:22:10 +0000 (16:22 +0300)
committerDenis Ovsienko <infrastation@yandex.ru>
Fri, 15 Jan 2010 13:22:10 +0000 (16:22 +0300)
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
bgpd/bgp_fsm.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_snmp.c
bgpd/bgpd.c
bgpd/bgpd.h

index e21131ef92e8c483aee7c816c66b9414809d8051..ba059f8c1b6934b7d9155328a1eb0002beeb2a64 100644 (file)
@@ -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);
 
index c815f9a17cad6a95a7c0dffdf471c262c6021ea9..487ebddbbec1ab0b5106124c14f2889503ed746b 100644 (file)
@@ -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++)
index 6153419181b6bfc7b053b0ddcb1b3d2b5eff0ff0..b29bc1f036ef1aa36800ed44339e56bc9e8edc83 100644 (file)
@@ -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);
index f3144fea301f8473350e503909ec5bbdb32cc6a3..a92ca4e2bca99781d549c70d75eb6f47349c1ea4 100644 (file)
@@ -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);
index 1e37f266abda48dc55bbf541971f3385b12bb539..86cc0879492511c9f818f2be78b74700a97f3fd5 100644 (file)
@@ -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
index cf3a6b424094f878a9b6b998104caf859bed1090..882fe37cad66b858e1155cbf1ebbf0b48bb435a5 100644 (file)
@@ -241,6 +241,17 @@ bgp_cluster_id_unset (struct bgp *bgp)
   return 0;
 }
 \f
+/* 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 ();
 }
 
 \f
index f4ce89859a2f3ad0877d4f784b623131f00c36fa..a5afaedcc3f16f242b4ee1cf89403f2b28403e10 100644 (file)
@@ -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 *);