tcp: avoid sending acks when data available
[vpp.git] / src / vnet / tcp / tcp_output.c
index 047247e..6ba0ee2 100644 (file)
@@ -405,7 +405,7 @@ tcp_update_burst_snd_vars (tcp_connection_t * tc)
 
   tcp_update_rcv_wnd (tc);
 
-  if (tc->flags & TCP_CONN_RATE_SAMPLE)
+  if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
     tc->flags |= TCP_CONN_TRACK_BURST;
 
   if (tc->snd_una == tc->snd_nxt)
@@ -499,7 +499,7 @@ static inline u16
 tcp_compute_checksum (tcp_connection_t * tc, vlib_buffer_t * b)
 {
   u16 checksum = 0;
-  if (PREDICT_FALSE (tc->flags & TCP_CONN_NO_CSUM_OFFLOAD))
+  if (PREDICT_FALSE (tc->cfg_flags & TCP_CFG_F_NO_CSUM_OFFLOAD))
     {
       tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
       vlib_main_t *vm = wrk->vm;
@@ -518,7 +518,6 @@ tcp_compute_checksum (tcp_connection_t * tc, vlib_buffer_t * b)
   return checksum;
 }
 
-
 /**
  * Prepare ACK
  */
@@ -867,7 +866,7 @@ tcp_send_reset_w_pkt (tcp_connection_t * tc, vlib_buffer_t * pkt,
       ASSERT ((pkt_ih4->ip_version_and_header_length & 0xF0) == 0x40);
       ih4 = vlib_buffer_push_ip4 (vm, b, &pkt_ih4->dst_address,
                                  &pkt_ih4->src_address, IP_PROTOCOL_TCP,
-                                 (!(tc->flags & TCP_CONN_NO_CSUM_OFFLOAD)));
+                                 tcp_csum_offload (tc));
       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
     }
   else
@@ -934,7 +933,7 @@ tcp_push_ip_hdr (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
       ip4_header_t *ih;
       ih = vlib_buffer_push_ip4 (vm, b, &tc->c_lcl_ip4,
                                 &tc->c_rmt_ip4, IP_PROTOCOL_TCP,
-                                (!(tc->flags & TCP_CONN_NO_CSUM_OFFLOAD)));
+                                tcp_csum_offload (tc));
       th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih);
     }
   else
@@ -1086,6 +1085,10 @@ tcp_send_fin (tcp_connection_t * tc)
       return;
     }
 
+  /* If we have non-dupacks programmed, no need to send them */
+  if ((tc->flags & TCP_CONN_SNDACK) && !tc->pending_dupacks)
+    tc->flags &= ~TCP_CONN_SNDACK;
+
   tcp_retransmit_timer_force_update (tc);
   b = vlib_get_buffer (vm, bi);
   tcp_init_buffer (vm, b);
@@ -1165,7 +1168,6 @@ tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b, u32 snd_nxt,
   tc->bytes_out += data_len;
   tc->data_segs_out += 1;
 
-
   th->checksum = tcp_compute_checksum (tc, b);
 
   TCP_EVT (TCP_EVT_PKTIZE, tc);
@@ -1445,7 +1447,7 @@ tcp_prepare_retransmit_segment (tcp_worker_ctx_t * wrk,
 
   tc->snd_rxt_bytes += n_bytes;
 
-  if (tc->flags & TCP_CONN_RATE_SAMPLE)
+  if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
     tcp_bt_track_rxt (tc, start, start + n_bytes);
 
   tc->bytes_retrans += n_bytes;
@@ -1777,7 +1779,7 @@ tcp_timer_persist_handler (u32 index)
                           || tc->snd_nxt == tc->snd_una_max
                           || tc->rto_boff > 1));
 
-  if (tc->flags & TCP_CONN_RATE_SAMPLE)
+  if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
     {
       tcp_bt_check_app_limited (tc);
       tcp_bt_track_tx (tc);
@@ -1883,6 +1885,13 @@ tcp_retransmit_should_retry_head (tcp_connection_t * tc,
   return (tx_adv_sack > (tc->snd_una - tc->prr_start) * rr);
 }
 
+static inline u8
+tcp_max_tx_deq (tcp_connection_t * tc)
+{
+  return (transport_max_tx_dequeue (&tc->connection)
+         - (tc->snd_nxt - tc->snd_una));
+}
+
 #define scoreboard_rescue_rxt_valid(_sb, _tc)                  \
     (seq_geq (_sb->rescue_rxt, _tc->snd_una)                   \
        && seq_leq (_sb->rescue_rxt, _tc->snd_congestion))
@@ -1932,7 +1941,8 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
   sb = &tc->sack_sb;
 
   /* Check if snd_una is a lost retransmit */
-  if (seq_gt (sb->high_sacked, tc->snd_congestion)
+  if (pool_elts (sb->holes)
+      && seq_gt (sb->high_sacked, tc->snd_congestion)
       && tc->rxt_head != tc->snd_una
       && tcp_retransmit_should_retry_head (tc, sb))
     {
@@ -2144,8 +2154,13 @@ tcp_send_acks (tcp_connection_t * tc, u32 max_burst_size)
 
   if (!tc->pending_dupacks)
     {
-      tcp_send_ack (tc);
-      return 1;
+      if (tcp_in_cong_recovery (tc) || !tcp_max_tx_deq (tc)
+         || tc->state != TCP_STATE_ESTABLISHED)
+       {
+         tcp_send_ack (tc);
+         return 1;
+       }
+      return 0;
     }
 
   /* If we're supposed to send dupacks but have no ooo data
@@ -2153,6 +2168,7 @@ tcp_send_acks (tcp_connection_t * tc, u32 max_burst_size)
   if (!vec_len (tc->snd_sacks))
     {
       tcp_send_ack (tc);
+      tc->pending_dupacks = 0;
       return 1;
     }
 
@@ -2301,8 +2317,7 @@ tcp_output_push_ip (vlib_main_t * vm, vlib_buffer_t * b0,
 
   if (is_ip4)
     ih0 = vlib_buffer_push_ip4 (vm, b0, &tc0->c_lcl_ip4, &tc0->c_rmt_ip4,
-                               IP_PROTOCOL_TCP,
-                               (!(tc0->flags & TCP_CONN_NO_CSUM_OFFLOAD)));
+                               IP_PROTOCOL_TCP, tcp_csum_offload (tc0));
   else
     ih0 = vlib_buffer_push_ip6 (vm, b0, &tc0->c_lcl_ip6, &tc0->c_rmt_ip6,
                                IP_PROTOCOL_TCP);
@@ -2312,8 +2327,9 @@ tcp_output_push_ip (vlib_main_t * vm, vlib_buffer_t * b0,
 always_inline void
 tcp_check_if_gso (tcp_connection_t * tc, vlib_buffer_t * b)
 {
-  if (!tc->is_tso)
+  if (PREDICT_TRUE (!(tc->cfg_flags & TCP_CFG_F_TSO)))
     return;
+
   u16 data_len = b->current_length - sizeof (tcp_header_t) - tc->snd_opts_len;
 
   if (PREDICT_FALSE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))