if (tcp_in_cong_recovery (tc))
{
/* Accept rtt estimates for samples that have not been retransmitted */
- if ((tc->flags & TCP_CONN_RATE_SAMPLE) && !(rs->flags & TCP_BTS_IS_RXT))
+ if ((tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
+ && !(rs->flags & TCP_BTS_IS_RXT))
{
mrtt = rs->rtt_time * THZ;
goto estimate_rtt;
tcp_update_rto (tc);
}
+always_inline u8
+tcp_recovery_no_snd_space (tcp_connection_t * tc)
+{
+ return (tcp_in_fastrecovery (tc)
+ && tcp_fastrecovery_prr_snd_space (tc) < tc->snd_mss)
+ || (tcp_in_recovery (tc)
+ && tcp_available_output_snd_space (tc) < tc->snd_mss);
+}
+
/**
* Dequeue bytes for connections that have received acks in last burst
*/
tc = tcp_connection_get (pending_deq_acked[i], thread_index);
tc->flags &= ~TCP_CONN_DEQ_PENDING;
- if (PREDICT_FALSE (!tc->burst_acked))
- continue;
+ if (tc->burst_acked)
+ {
+ /* Dequeue the newly ACKed bytes */
+ session_tx_fifo_dequeue_drop (&tc->connection, tc->burst_acked);
+ tc->burst_acked = 0;
+ tcp_validate_txf_size (tc, tc->snd_una_max - tc->snd_una);
- /* Dequeue the newly ACKed bytes */
- session_tx_fifo_dequeue_drop (&tc->connection, tc->burst_acked);
- 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 (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);
- /* If everything has been acked, stop retransmit timer
- * otherwise update. */
- tcp_retransmit_timer_update (tc);
+ /* Update pacer based on our new cwnd estimate */
+ tcp_connection_tx_pacer_update (tc);
+ }
- /* Update pacer based on our new cwnd estimate */
- tcp_connection_tx_pacer_update (tc);
+ /* Reset the pacer if we've been idle, i.e., no data sent or if
+ * 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);
+ tc->prev_dsegs_out = tc->data_segs_out;
}
_vec_len (wrk->pending_deq_acked) = 0;
}
sb->sacked_bytes = 0;
sb->last_sacked_bytes = 0;
sb->last_bytes_delivered = 0;
- sb->high_sacked = 0;
- sb->high_rxt = 0;
sb->lost_bytes = 0;
sb->last_lost_bytes = 0;
sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
tc->rtt_ts = 0;
tc->flags &= ~TCP_CONN_RXT_PENDING;
+ tcp_connection_tx_pacer_reset (tc, tc->cwnd, 0 /* start bucket */ );
+
/* Previous recovery left us congested. Continue sending as part
* of the current recovery event with an updated snd_congestion */
if (tc->sack_sb.sacked_bytes)
if (!tcp_in_recovery (tc) && !is_spurious)
tcp_cc_recovered (tc);
- tcp_connection_tx_pacer_reset (tc, tc->cwnd, 0 /* start bucket */ );
-
tcp_fastrecovery_off (tc);
tcp_fastrecovery_first_off (tc);
tcp_recovery_off (tc);
tc->snd_una = vnet_buffer (b)->tcp.ack_number;
tcp_validate_txf_size (tc, tc->bytes_acked);
- if (tc->flags & TCP_CONN_RATE_SAMPLE)
+ if (tc->cfg_flags & TCP_CFG_F_RATE_SAMPLE)
tcp_bt_sample_delivery_rate (tc, &rs);
+ tcp_program_dequeue (wrk, tc);
+
if (tc->bytes_acked)
- {
- tcp_program_dequeue (wrk, tc);
- tcp_update_rtt (tc, &rs, vnet_buffer (b)->tcp.ack_number);
- }
+ tcp_update_rtt (tc, &rs, vnet_buffer (b)->tcp.ack_number);
TCP_EVT (TCP_EVT_ACK_RCVD, tc);
sw_if_idx = dpo->dpoi_index;
hw_if = vnet_get_sup_hw_interface (vnm, sw_if_idx);
- tc->is_tso =
- ((hw_if->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0) ? 0 : 1;
+ if (hw_if->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO)
+ tc->cfg_flags |= TCP_CFG_F_TSO;
}
-
always_inline uword
tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame, int is_ip4)
goto drop;
}
- tcp_check_tx_offload (new_tc0, is_ip4);
+ if (!(new_tc0->cfg_flags & TCP_CFG_F_NO_TSO))
+ tcp_check_tx_offload (new_tc0, is_ip4);
/* Read data, if any */
if (PREDICT_FALSE (vnet_buffer (b0)->tcp.data_len))
tc0->state = TCP_STATE_ESTABLISHED;
TCP_EVT (TCP_EVT_STATE_CHANGE, tc0);
- tcp_check_tx_offload (tc0, is_ip4);
+ if (!(tc0->cfg_flags & TCP_CFG_F_NO_TSO))
+ tcp_check_tx_offload (tc0, is_ip4);
/* Initialize session variables */
tc0->snd_una = vnet_buffer (b0)->tcp.ack_number;