summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2018-12-12 10:56:01 -0800
committerDave Barach <openvpp@barachs.net>2018-12-13 13:40:32 +0000
commit42ceddb7cd836a89a12b0b8e623b06bc4c0cc0cb (patch)
tree9731e8708e3ad9d96d418068d59743dbd8e69658 /src/vnet/tcp
parent413f4a5b2123c1625d615315db293a080078482b (diff)
session/tcp: support tx flush mark
For tcp this means that the last enqueued data goes out with a psh bit set. Change-Id: I29d357ecae6f02e748b59a7b799150ec73d14ba2 Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/tcp')
-rw-r--r--src/vnet/tcp/tcp.c11
-rw-r--r--src/vnet/tcp/tcp.h3
-rw-r--r--src/vnet/tcp/tcp_input.c6
-rw-r--r--src/vnet/tcp/tcp_output.c7
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);
is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __DVR_DPO_H__ #define __DVR_DPO_H__ #include <vnet/dpo/dpo.h> /** * @brief * The DVR DPO. Used as the resolving object for a DVR route. * This is used, in place of the usual L3 Adjacency, to retransmit * the packet with the original L2 header intact but also to run L3 features. * After running L3 features the packet is re-injected back into the L2 path * so it can pick up the necessary VLAN tags of the egress interface. * This re-injection is done with an output feature. */ typedef struct dvr_dpo_t_ { /** * The Software interface index that the packets will output on */ u32 dd_sw_if_index; /** * The protocol of packets using this DPO */ dpo_proto_t dd_proto; /** * number of locks. */ u16 dd_locks; } dvr_dpo_t; extern void dvr_dpo_add_or_lock (u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo); extern void dvr_dpo_module_init(void); /** * @brief pool of all interface DPOs */ extern dvr_dpo_t *dvr_dpo_pool; static inline dvr_dpo_t * dvr_dpo_get (index_t index) { return (pool_elt_at_index(dvr_dpo_pool, index)); } #endif