diff options
Diffstat (limited to 'src/vnet/tcp')
-rw-r--r-- | src/vnet/tcp/tcp.c | 11 | ||||
-rw-r--r-- | src/vnet/tcp/tcp.h | 3 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_input.c | 6 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_output.c | 7 |
4 files changed, 26 insertions, 1 deletions
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index f703d634b54..6d6a880eda8 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -1123,6 +1123,16 @@ tcp_session_push_header (transport_connection_t * tconn, vlib_buffer_t * b) return tcp_push_header (tc, b); } +static void +tcp_session_flush_data (transport_connection_t * tconn) +{ + tcp_connection_t *tc = (tcp_connection_t *) tconn; + if (tc->flags & TCP_CONN_PSH_PENDING) + return; + tc->flags |= TCP_CONN_PSH_PENDING; + tc->psh_seq = tc->snd_una_max + transport_max_tx_dequeue (tconn) - 1; +} + /* *INDENT-OFF* */ const static transport_proto_vft_t tcp_proto = { .enable = vnet_tcp_enable_disable, @@ -1139,6 +1149,7 @@ const static transport_proto_vft_t tcp_proto = { .send_space = tcp_session_send_space, .update_time = tcp_update_time, .tx_fifo_offset = tcp_session_tx_fifo_offset, + .flush_data = tcp_session_flush_data, .format_connection = format_tcp_session, .format_listener = format_tcp_listener_session, .format_half_open = format_tcp_half_open_session, diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 5b235b65d74..46b03ac14b4 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -124,6 +124,7 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler; _(FRXT_PENDING, "Fast-retransmit pending") \ _(FRXT_FIRST, "Fast-retransmit first again") \ _(DEQ_PENDING, "Pending dequeue acked") \ + _(PSH_PENDING, "Pending psh packet") \ typedef enum _tcp_connection_flag_bits { @@ -334,6 +335,8 @@ typedef struct _tcp_connection u32 last_fib_check; /**< Last time we checked fib route for peer */ u32 sw_if_index; /**< Interface for the connection */ u32 tx_fifo_size; /**< Tx fifo size. Used to constrain cwnd */ + + u32 psh_seq; /**< Add psh header for seg that includes this */ } tcp_connection_t; /* *INDENT-OFF* */ diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index dff18029155..f04fa5d8901 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -543,6 +543,12 @@ tcp_handle_postponed_dequeues (tcp_worker_ctx_t * wrk) tc->burst_acked = 0; tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una); + if (PREDICT_FALSE (tc->flags & TCP_CONN_PSH_PENDING)) + { + if (seq_leq (tc->psh_seq, tc->snd_una)) + tc->flags &= ~TCP_CONN_PSH_PENDING; + } + /* If everything has been acked, stop retransmit timer * otherwise update. */ tcp_retransmit_timer_update (tc); diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 74fc15fe6cc..7cee34995e3 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1169,7 +1169,12 @@ tcp_push_hdr_i (tcp_connection_t * tc, vlib_buffer_t * b, advertise_wnd = tcp_window_to_advertise (tc, next_state); flags = tcp_make_state_flags (tc, next_state); - + if (PREDICT_FALSE (tc->flags & TCP_CONN_PSH_PENDING)) + { + if (seq_geq (tc->psh_seq, tc->snd_nxt) + && seq_lt (tc->psh_seq, tc->snd_nxt + data_len)) + flags |= TCP_FLAG_PSH; + } th = vlib_buffer_push_tcp (b, tc->c_lcl_port, tc->c_rmt_port, tc->snd_nxt, tc->rcv_nxt, tcp_hdr_opts_len, flags, advertise_wnd); |