]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Allow extending peer timeout in rare case
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 15 Jun 2020 14:35:50 +0000 (10:35 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 15 Jun 2020 14:35:50 +0000 (10:35 -0400)
Currently the I/O pthread handles incoming/outgoing data
communication with all peers.  There is no attempt at modifying
the hold timers.  It's sole goal is to read/write data to appropriate
channels.  All this data is handled as *events* on the master pthread
in BGP.   The problem is that if the master pthread is extremely busy
then any packet read that would be treated as a keepalive event may
happen after the hold timer pops, due to the way thread events are handled
in lib/thread.c.

In a last gap attempt, if we notice that we have incoming data
to proceses on the input Queue, slightly delay the hold timer.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
bgpd/bgp_fsm.c

index ce5747dc2bae9d5cdaea11f9214add9db9453634..e78682a3bb48b906e7ad5231556efa9b5f38cc60 100644 (file)
@@ -512,6 +512,7 @@ static int bgp_connect_timer(struct thread *thread)
 /* BGP holdtime timer. */
 static int bgp_holdtime_timer(struct thread *thread)
 {
+       atomic_size_t inq_count;
        struct peer *peer;
 
        peer = THREAD_ARG(thread);
@@ -521,6 +522,25 @@ static int bgp_holdtime_timer(struct thread *thread)
                zlog_debug("%s [FSM] Timer (holdtime timer expire)",
                           peer->host);
 
+       /*
+        * Given that we do not have any expectation of ordering
+        * for handling packets from a peer -vs- handling
+        * the hold timer for a peer as that they are both
+        * events on the peer.  If we have incoming
+        * data on the peers inq, let's give the system a chance
+        * to handle that data.  This can be especially true
+        * for systems where we are heavily loaded for one
+        * reason or another.
+        */
+       inq_count = atomic_load_explicit(&peer->ibuf->count,
+                                        memory_order_relaxed);
+       if (inq_count) {
+               BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
+                            peer->v_holdtime);
+
+               return 0;
+       }
+
        THREAD_VAL(thread) = Hold_Timer_expired;
        bgp_event(thread); /* bgp_event unlocks peer */