tcp: allow fins in syns in syn-rcvd 81/39681/2
authorFlorin Coras <fcoras@cisco.com>
Sat, 14 Oct 2023 22:16:18 +0000 (15:16 -0700)
committerDave Barach <vpp@barachs.net>
Mon, 16 Oct 2023 20:00:49 +0000 (20:00 +0000)
Also make sure connection is properly cleaned up.

Type: fix

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I02f83e9a1e17cbbbd2ee74044d02049b2fd2f21c

src/vnet/tcp/tcp_input.c

index 1602b49..1494fd8 100644 (file)
@@ -2123,7 +2123,7 @@ tcp46_rcv_process_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
        case TCP_STATE_SYN_RCVD:
 
          /* Make sure the segment is exactly right */
-         if (tc->rcv_nxt != vnet_buffer (b[0])->tcp.seq_number || is_fin)
+         if (tc->rcv_nxt != vnet_buffer (b[0])->tcp.seq_number)
            {
              tcp_send_reset_w_pkt (tc, b[0], thread_index, is_ip4);
              error = TCP_ERROR_SEGMENT_INVALID;
@@ -2143,6 +2143,10 @@ tcp46_rcv_process_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
              goto drop;
            }
 
+         /* Avoid notifying app if connection is about to be closed */
+         if (PREDICT_FALSE (is_fin))
+           break;
+
          /* Update rtt and rto */
          tcp_estimate_initial_rtt (tc);
          tcp_connection_tx_pacer_update (tc);
@@ -2363,15 +2367,15 @@ tcp46_rcv_process_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
                            tcp_cfg.closewait_time);
          break;
        case TCP_STATE_SYN_RCVD:
-         /* Send FIN-ACK, enter LAST-ACK and because the app was not
-          * notified yet, set a cleanup timer instead of relying on
-          * disconnect notify and the implicit close call. */
+         /* Send FIN-ACK and enter TIME-WAIT, as opposed to LAST-ACK,
+          * because the app was not notified yet and we want to avoid
+          * session state transitions to ensure cleanup does not
+          * propagate to app. */
          tcp_connection_timers_reset (tc);
          tc->rcv_nxt += 1;
          tcp_send_fin (tc);
-         tcp_connection_set_state (tc, TCP_STATE_LAST_ACK);
-         tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
-                        tcp_cfg.lastack_time);
+         tcp_connection_set_state (tc, TCP_STATE_TIME_WAIT);
+         tcp_program_cleanup (wrk, tc);
          break;
        case TCP_STATE_CLOSE_WAIT:
        case TCP_STATE_CLOSING: