tcp: fix retransmit with no sacks
[vpp.git] / src / vnet / tcp / tcp_input.c
index 744c5bc..08cea1e 100755 (executable)
@@ -629,9 +629,7 @@ tcp_handle_postponed_dequeues (tcp_worker_ctx_t * wrk)
        * we're in recovery and snd space constrained */
       if (tc->data_segs_out == tc->prev_dsegs_out
          || tcp_recovery_no_snd_space (tc))
-       transport_connection_tx_pacer_reset_bucket (&tc->connection,
-                                                   wrk->vm->clib_time.
-                                                   last_cpu_time);
+       transport_connection_tx_pacer_reset_bucket (&tc->connection);
       tc->prev_dsegs_out = tc->data_segs_out;
     }
   _vec_len (wrk->pending_deq_acked) = 0;
@@ -1485,9 +1483,12 @@ tcp_cc_handle_event (tcp_connection_t * tc, tcp_rate_sample_t * rs,
       tc->rxt_delivered = clib_max (tc->rxt_delivered + tc->bytes_acked,
                                    tc->snd_rxt_bytes);
       if (is_dack)
-       tc->prr_delivered += 1;
+       tc->prr_delivered += clib_min (tc->snd_mss,
+                                      tc->snd_nxt - tc->snd_una);
       else
-       tc->prr_delivered += tc->bytes_acked - tc->snd_mss * tc->rcv_dupacks;
+       tc->prr_delivered += tc->bytes_acked - clib_min (tc->bytes_acked,
+                                                        tc->snd_mss *
+                                                        tc->rcv_dupacks);
 
       /* If partial ack, assume that the first un-acked segment was lost */
       if (tc->bytes_acked || tc->rcv_dupacks == TCP_DUPACK_THRESHOLD)
@@ -2263,7 +2264,8 @@ VLIB_REGISTER_NODE (tcp6_established_node) =
 
 
 static u8
-tcp_lookup_is_valid (tcp_connection_t * tc, tcp_header_t * hdr)
+tcp_lookup_is_valid (tcp_connection_t * tc, vlib_buffer_t * b,
+                    tcp_header_t * hdr)
 {
   transport_connection_t *tmp = 0;
   u64 handle;
@@ -2275,9 +2277,30 @@ tcp_lookup_is_valid (tcp_connection_t * tc, tcp_header_t * hdr)
   if (tc->c_lcl_port == 0 && tc->state == TCP_STATE_LISTEN)
     return 1;
 
+
+  u8 is_ip_valid = 0;
+  if (tc->connection.is_ip4)
+    {
+      ip4_header_t *ip4_hdr = (ip4_header_t *) vlib_buffer_get_current (b);
+      is_ip_valid =
+       (!(ip4_address_compare
+          (&ip4_hdr->src_address, &tc->connection.rmt_ip.ip4)
+          && ip4_address_compare (&ip4_hdr->dst_address,
+                                  &tc->connection.lcl_ip.ip4)));
+    }
+  else
+    {
+      ip6_header_t *ip6_hdr = (ip6_header_t *) vlib_buffer_get_current (b);
+      is_ip_valid =
+       (!(ip6_address_compare
+          (&ip6_hdr->src_address, &tc->connection.rmt_ip.ip6)
+          && ip6_address_compare (&ip6_hdr->dst_address,
+                                  &tc->connection.lcl_ip.ip6)));
+    }
+
   u8 is_valid = (tc->c_lcl_port == hdr->dst_port
                 && (tc->state == TCP_STATE_LISTEN
-                    || tc->c_rmt_port == hdr->src_port));
+                    || tc->c_rmt_port == hdr->src_port) && is_ip_valid);
 
   if (!is_valid)
     {
@@ -2291,6 +2314,7 @@ tcp_lookup_is_valid (tcp_connection_t * tc, tcp_header_t * hdr)
              && tmp->rmt_port == hdr->src_port)
            {
              TCP_DBG ("half-open is valid!");
+             is_valid = 1;
            }
        }
     }
@@ -2321,7 +2345,7 @@ tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index,
                                             TRANSPORT_PROTO_TCP,
                                             thread_index, &is_filtered);
       tc = tcp_get_connection_from_transport (tconn);
-      ASSERT (tcp_lookup_is_valid (tc, tcp));
+      ASSERT (tcp_lookup_is_valid (tc, b, tcp));
     }
   else
     {
@@ -2336,7 +2360,7 @@ tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index,
                                             TRANSPORT_PROTO_TCP,
                                             thread_index, &is_filtered);
       tc = tcp_get_connection_from_transport (tconn);
-      ASSERT (tcp_lookup_is_valid (tc, tcp));
+      ASSERT (tcp_lookup_is_valid (tc, b, tcp));
     }
   return tc;
 }
@@ -2718,14 +2742,17 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
       if (CLIB_DEBUG)
        {
-         tcp_connection_t *tmp;
-         tmp = tcp_lookup_connection (tc0->c_fib_index, b0, thread_index,
-                                      is_ip4);
-         if (tmp->state != tc0->state)
+         if (!(tc0->connection.flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
            {
-             if (tc0->state != TCP_STATE_CLOSED)
-               clib_warning ("state changed");
-             goto drop;
+             tcp_connection_t *tmp;
+             tmp = tcp_lookup_connection (tc0->c_fib_index, b0, thread_index,
+                                          is_ip4);
+             if (tmp->state != tc0->state)
+               {
+                 if (tc0->state != TCP_STATE_CLOSED)
+                   clib_warning ("state changed");
+                 goto drop;
+               }
            }
        }
 
@@ -3546,8 +3573,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
       if (PREDICT_TRUE (!tc0 + !tc1 == 0))
        {
-         ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
-         ASSERT (tcp_lookup_is_valid (tc1, tcp_buffer_hdr (b[1])));
+         ASSERT (tcp_lookup_is_valid (tc0, b[0], tcp_buffer_hdr (b[0])));
+         ASSERT (tcp_lookup_is_valid (tc1, b[1], tcp_buffer_hdr (b[1])));
 
          vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
          vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
@@ -3559,7 +3586,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          if (PREDICT_TRUE (tc0 != 0))
            {
-             ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
+             ASSERT (tcp_lookup_is_valid (tc0, b[0], tcp_buffer_hdr (b[0])));
              vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
              tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], &error0);
            }
@@ -3568,7 +3595,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
          if (PREDICT_TRUE (tc1 != 0))
            {
-             ASSERT (tcp_lookup_is_valid (tc1, tcp_buffer_hdr (b[1])));
+             ASSERT (tcp_lookup_is_valid (tc1, b[1], tcp_buffer_hdr (b[1])));
              vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
              tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], &error1);
            }
@@ -3596,7 +3623,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
                                     is_nolookup);
       if (PREDICT_TRUE (tc0 != 0))
        {
-         ASSERT (tcp_lookup_is_valid (tc0, tcp_buffer_hdr (b[0])));
+         ASSERT (tcp_lookup_is_valid (tc0, b[0], tcp_buffer_hdr (b[0])));
          vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
          tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], &error0);
        }