tcp: dynamic max timers per loop
[vpp.git] / src / vnet / tcp / tcp.c
index f24ddb3..e243f5a 100644 (file)
@@ -599,6 +599,10 @@ tcp_init_rcv_mss (tcp_connection_t * tc)
 {
   u8 ip_hdr_len;
 
+  /* Already provided at connection init time */
+  if (tc->mss)
+    return;
+
   ip_hdr_len = tc->c_is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t);
   tc->mss = tcp_cfg.default_mtu - sizeof (tcp_header_t) - ip_hdr_len;
 }
@@ -763,6 +767,7 @@ tcp_session_open (transport_endpoint_cfg_t * rmt)
   tc->cc_algo = tcp_cc_algo_get (tcp_cfg.cc_algo);
   /* The other connection vars will be initialized after SYN ACK */
   tcp_connection_timers_init (tc);
+  tc->mss = rmt->mss;
 
   TCP_EVT (TCP_EVT_OPEN, tc);
   tc->state = TCP_STATE_SYN_SENT;
@@ -964,8 +969,8 @@ format_tcp_vars (u8 * s, va_list * args)
              tc->rto, tc->rto_boff, tc->srtt, tc->mrtt_us * 1000, tc->rttvar,
              tc->rtt_ts);
   s = format (s, " rtt_seq %u\n", tc->rtt_seq - tc->iss);
-  s = format (s, " next_node %u opaque 0x%x\n", tc->next_node_index,
-             tc->next_node_opaque);
+  s = format (s, " next_node %u opaque 0x%x fib_index %u\n",
+             tc->next_node_index, tc->next_node_opaque, tc->c_fib_index);
   s = format (s, " cong:   %U", format_tcp_congestion, tc);
 
   if (tc->state >= TCP_STATE_ESTABLISHED)
@@ -1387,7 +1392,7 @@ tcp_dispatch_pending_timers (tcp_worker_ctx_t * wrk)
     return;
 
   thread_index = wrk->vm->thread_index;
-  for (i = 0; i < clib_min (n_timers, 32); i++)
+  for (i = 0; i < clib_min (n_timers, wrk->max_timers_per_loop); i++)
     {
       clib_fifo_sub1 (wrk->pending_timers, timer_handle);
       connection_index = timer_handle & 0x0FFFFFFF;
@@ -1407,6 +1412,10 @@ tcp_dispatch_pending_timers (tcp_worker_ctx_t * wrk)
 
       (*timer_expiration_handlers[timer_id]) (tc);
     }
+
+  if (thread_index == 0 && clib_fifo_elts (wrk->pending_timers))
+    vlib_process_signal_event_mt (wrk->vm, session_queue_process_node.index,
+                                 SESSION_Q_PROCESS_FLUSH_FRAMES, 0);
 }
 
 /**
@@ -1506,8 +1515,8 @@ tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
 static void
 tcp_expired_timers_dispatch (u32 * expired_timers)
 {
-  u32 thread_index = vlib_get_thread_index ();
-  u32 connection_index, timer_id, n_expired;
+  u32 thread_index = vlib_get_thread_index (), n_left, max_per_loop;
+  u32 connection_index, timer_id, n_expired, max_loops;
   tcp_worker_ctx_t *wrk;
   tcp_connection_t *tc;
   int i;
@@ -1515,6 +1524,7 @@ tcp_expired_timers_dispatch (u32 * expired_timers)
   wrk = tcp_get_worker (thread_index);
   n_expired = vec_len (expired_timers);
   tcp_workerp_stats_inc (wrk, timer_expirations, n_expired);
+  n_left = clib_fifo_elts (wrk->pending_timers);
 
   /*
    * Invalidate all timer handles before dispatching. This avoids dangling
@@ -1536,6 +1546,16 @@ tcp_expired_timers_dispatch (u32 * expired_timers)
     }
 
   clib_fifo_add (wrk->pending_timers, expired_timers, n_expired);
+
+  max_loops = clib_max (1, 0.5 * TCP_TIMER_TICK * wrk->vm->loops_per_second);
+  max_per_loop = clib_max ((n_left + n_expired) / max_loops, 10);
+  max_per_loop = clib_min (max_per_loop, VLIB_FRAME_SIZE);
+  wrk->max_timers_per_loop = clib_max (n_left ? wrk->max_timers_per_loop : 0,
+                                      max_per_loop);
+
+  if (thread_index == 0)
+    vlib_process_signal_event_mt (wrk->vm, session_queue_process_node.index,
+                                 SESSION_Q_PROCESS_FLUSH_FRAMES, 0);
 }
 
 static void
@@ -1607,6 +1627,7 @@ tcp_main_enable (vlib_main_t * vm)
       vec_reset_length (wrk->pending_disconnects);
       vec_reset_length (wrk->pending_resets);
       wrk->vm = vlib_mains[thread];
+      wrk->max_timers_per_loop = 10;
 
       /*
        * Preallocate connections. Assume that thread 0 won't