X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ftcp%2Ftcp_input.c;h=21e5f3cdabaeb1d9ba4256473368acf86633870e;hb=776f3d85ebd4edfb70b0f748890f1efd98d8474c;hp=ac0e996567ee8ab26adbc1567cc5e35fce95ffec;hpb=d67f112063e6c57160a3d0260537b9dcfe23d217;p=vpp.git diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index ac0e996567e..21e5f3cdaba 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -258,7 +258,7 @@ tcp_update_timestamp (tcp_connection_t * tc, u32 seq, u32 seq_end) { ASSERT (timestamp_leq (tc->tsval_recent, tc->rcv_opts.tsval)); tc->tsval_recent = tc->rcv_opts.tsval; - tc->tsval_recent_age = tcp_time_now (); + tc->tsval_recent_age = tcp_time_now_w_thread (tc->c_thread_index); } } @@ -308,7 +308,7 @@ tcp_segment_validate (vlib_main_t * vm, tcp_connection_t * tc0, /* If it just so happens that a segment updates tsval_recent for a * segment over 24 days old, invalidate tsval_recent. */ if (timestamp_lt (tc0->tsval_recent_age + TCP_PAWS_IDLE, - tcp_time_now ())) + tcp_time_now_w_thread (tc0->c_thread_index))) { /* Age isn't reset until we get a valid tsval (bsd inspired) */ tc0->tsval_recent = 0; @@ -470,7 +470,8 @@ tcp_update_rtt (tcp_connection_t * tc, u32 ack) * seq_lt (tc->snd_una, ack). This is a condition for calling update_rtt */ else if (tcp_opts_tstamp (&tc->rcv_opts) && tc->rcv_opts.tsecr) { - mrtt = clib_max (tcp_time_now () - tc->rcv_opts.tsecr, 1); + u32 now = tcp_time_now_w_thread (tc->c_thread_index); + mrtt = clib_max (now - tc->rcv_opts.tsecr, 1); } /* Ignore dubious measurements */ @@ -1084,10 +1085,6 @@ tcp_cc_fastrecovery_exit (tcp_connection_t * tc) tcp_fastrecovery_1_smss_off (tc); tcp_fastrecovery_first_off (tc); - /* Update pacer because our cwnd changed. Also makes sure - * that we recompute the max burst size */ - tcp_update_pacer (tc); - TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 3); } @@ -1185,9 +1182,8 @@ tcp_should_fastrecover (tcp_connection_t * tc) } void -tcp_program_fastretransmit (tcp_connection_t * tc) +tcp_program_fastretransmit (tcp_worker_ctx_t * wrk, tcp_connection_t * tc) { - tcp_worker_ctx_t *wrk = &tcp_main.wrk_ctx[tc->c_thread_index]; if (!(tc->flags & TCP_CONN_FRXT_PENDING)) { vec_add1 (wrk->pending_fast_rxt, tc->c_c_index); @@ -1196,70 +1192,62 @@ tcp_program_fastretransmit (tcp_connection_t * tc) } void -tcp_do_fastretransmits (u32 thread_index) +tcp_do_fastretransmits (tcp_worker_ctx_t * wrk) { - tcp_worker_ctx_t *wrk = &tcp_main.wrk_ctx[thread_index]; - u32 max_burst_size, burst_size, n_segs = 0; + u32 *ongoing_fast_rxt, burst_bytes, sent_bytes, thread_index; + u32 max_burst_size, burst_size, n_segs = 0, n_segs_now; tcp_connection_t *tc; + u64 last_cpu_time; int i; - if (vec_len (wrk->pending_fast_rxt) == 0) + if (vec_len (wrk->pending_fast_rxt) == 0 + && vec_len (wrk->postponed_fast_rxt) == 0) return; - vec_append (wrk->ongoing_fast_rxt, wrk->pending_fast_rxt); - vec_reset_length (wrk->pending_fast_rxt); + thread_index = wrk->vm->thread_index; + last_cpu_time = wrk->vm->clib_time.last_cpu_time; + ongoing_fast_rxt = wrk->ongoing_fast_rxt; + vec_append (ongoing_fast_rxt, wrk->postponed_fast_rxt); + vec_append (ongoing_fast_rxt, wrk->pending_fast_rxt); + + _vec_len (wrk->postponed_fast_rxt) = 0; + _vec_len (wrk->pending_fast_rxt) = 0; - max_burst_size = VLIB_FRAME_SIZE / vec_len (wrk->ongoing_fast_rxt); + max_burst_size = VLIB_FRAME_SIZE / vec_len (ongoing_fast_rxt); max_burst_size = clib_max (max_burst_size, 1); - for (i = 0; i < vec_len (wrk->ongoing_fast_rxt); i++) + for (i = 0; i < vec_len (ongoing_fast_rxt); i++) { - tc = tcp_connection_get (wrk->ongoing_fast_rxt[i], thread_index); + if (n_segs >= VLIB_FRAME_SIZE) + { + vec_add1 (wrk->postponed_fast_rxt, ongoing_fast_rxt[i]); + continue; + } + + tc = tcp_connection_get (ongoing_fast_rxt[i], thread_index); tc->flags &= ~TCP_CONN_FRXT_PENDING; if (!tcp_in_fastrecovery (tc)) continue; - /* TODO tx pacer instead of this */ - if (n_segs >= VLIB_FRAME_SIZE) + burst_size = clib_min (max_burst_size, VLIB_FRAME_SIZE - n_segs); + burst_bytes = transport_connection_tx_pacer_burst (&tc->connection, + last_cpu_time); + burst_size = clib_min (burst_size, burst_bytes / tc->snd_mss); + if (!burst_size) { - tcp_program_fastretransmit (tc); + tcp_program_fastretransmit (wrk, tc); continue; } - burst_size = clib_min (max_burst_size, VLIB_FRAME_SIZE - n_segs); - - if (tc->cwnd > tc->ssthresh + 3 * tc->snd_mss) - { - /* The first segment MUST be retransmitted */ - if (tcp_retransmit_first_unacked (tc)) - { - tcp_program_fastretransmit (tc); - continue; - } - - /* Post retransmit update cwnd to ssthresh and account for the - * three segments that have left the network and should've been - * buffered at the receiver XXX */ - tc->cwnd = tc->ssthresh + 3 * tc->snd_mss; - - /* If cwnd allows, send more data */ - if (tcp_opts_sack_permitted (&tc->rcv_opts)) - { - scoreboard_init_high_rxt (&tc->sack_sb, - tc->snd_una + tc->snd_mss); - tc->sack_sb.rescue_rxt = tc->snd_una - 1; - n_segs += tcp_fast_retransmit_sack (tc, burst_size); - } - else - { - n_segs += tcp_fast_retransmit_no_sack (tc, burst_size); - } - } - else - n_segs += tcp_fast_retransmit (tc, burst_size); + n_segs_now = tcp_fast_retransmit (wrk, tc, burst_size); + sent_bytes = clib_min (n_segs_now * tc->snd_mss, burst_bytes); + transport_connection_tx_pacer_update_bytes (&tc->connection, + sent_bytes); + n_segs += n_segs_now; } - vec_reset_length (wrk->ongoing_fast_rxt); + _vec_len (ongoing_fast_rxt) = 0; + wrk->ongoing_fast_rxt = ongoing_fast_rxt; } /** @@ -1274,7 +1262,7 @@ tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack) { if (tc->bytes_acked) goto partial_ack; - tcp_program_fastretransmit (tc); + tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index), tc); return; } /* @@ -1298,6 +1286,8 @@ tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack) } else if (tcp_should_fastrecover (tc)) { + u32 pacer_wnd; + ASSERT (!tcp_in_fastrecovery (tc)); /* Heuristic to catch potential late dupacks @@ -1313,9 +1303,24 @@ tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack) tc->cc_algo->rcv_cong_ack (tc, TCP_CC_DUPACK); if (tcp_opts_sack_permitted (&tc->rcv_opts)) - tc->sack_sb.high_rxt = tc->snd_una; + { + tc->cwnd = tc->ssthresh; + scoreboard_init_high_rxt (&tc->sack_sb, tc->snd_una); + tc->sack_sb.rescue_rxt = tc->snd_una - 1; + } + else + { + /* Post retransmit update cwnd to ssthresh and account for the + * three segments that have left the network and should've been + * buffered at the receiver XXX */ + tc->cwnd = tc->ssthresh + 3 * tc->snd_mss; + } - tcp_program_fastretransmit (tc); + pacer_wnd = clib_max (0.1 * tc->cwnd, 2 * tc->snd_mss); + tcp_connection_tx_pacer_reset (tc, pacer_wnd, + 0 /* start bucket */ ); + tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index), + tc); return; } else if (!tc->bytes_acked @@ -1432,7 +1437,7 @@ partial_ack: /* * Since this was a partial ack, try to retransmit some more data */ - tcp_program_fastretransmit (tc); + tcp_program_fastretransmit (tcp_get_worker (tc->c_thread_index), tc); } /** @@ -2095,7 +2100,7 @@ tcp46_established_inline (vlib_main_t * vm, vlib_node_runtime_t * node, thread_index); err_counters[TCP_ERROR_EVENT_FIFO_FULL] = errors; tcp_store_err_counters (established, err_counters); - tcp_flush_frame_to_output (vm, thread_index, is_ip4); + tcp_flush_frame_to_output (tcp_get_worker (thread_index), is_ip4); return frame->n_vectors; } @@ -3386,7 +3391,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; u16 nexts[VLIB_FRAME_SIZE], *next; - tcp_set_time_now (thread_index); + tcp_set_time_now (tcp_get_worker (thread_index)); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors;