only allow cwnd to be reduced so often

This commit is contained in:
arvidn 2019-01-07 01:27:02 +01:00 committed by Arvid Norberg
parent 33fa7454d0
commit 786d78b6c9
4 changed files with 24 additions and 5 deletions

View File

@ -1608,6 +1608,11 @@ namespace libtorrent
// systems. // systems.
close_file_interval, close_file_interval,
// When uTP experiences packet loss, it will reduce the congestion
// window, and not reduce it again for this many milliseconds, even if
// experiencing another lost packet.
utp_cwnd_reduce_timer,
max_int_setting_internal max_int_setting_internal
}; };

View File

@ -87,6 +87,7 @@ namespace libtorrent
int connect_timeout() const { return m_sett.get_int(settings_pack::utp_connect_timeout); } int connect_timeout() const { return m_sett.get_int(settings_pack::utp_connect_timeout); }
int min_timeout() const { return m_sett.get_int(settings_pack::utp_min_timeout); } int min_timeout() const { return m_sett.get_int(settings_pack::utp_min_timeout); }
int loss_multiplier() const { return m_sett.get_int(settings_pack::utp_loss_multiplier); } int loss_multiplier() const { return m_sett.get_int(settings_pack::utp_loss_multiplier); }
int cwnd_reduce_timer() const { return m_sett.get_int(settings_pack::utp_cwnd_reduce_timer); }
void mtu_for_dest(address const& addr, int& link_mtu, int& utp_mtu); void mtu_for_dest(address const& addr, int& link_mtu, int& utp_mtu);
void set_sock_buf(int size); void set_sock_buf(int size);

View File

@ -366,6 +366,7 @@ namespace libtorrent
SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 0), SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 0),
SET_NOPREV(web_seed_name_lookup_retry, 1800, 0), SET_NOPREV(web_seed_name_lookup_retry, 1800, 0),
SET_NOPREV(close_file_interval, CLOSE_FILE_INTERVAL, &session_impl::update_close_file_interval), SET_NOPREV(close_file_interval, CLOSE_FILE_INTERVAL, &session_impl::update_close_file_interval),
SET_NOPREV(utp_cwnd_reduce_timer, 100, 0),
}; };
#undef SET #undef SET

View File

@ -359,7 +359,7 @@ struct utp_socket_impl
bool consume_incoming_data( bool consume_incoming_data(
utp_header const* ph, boost::uint8_t const* ptr, int payload_size, time_point now); utp_header const* ph, boost::uint8_t const* ptr, int payload_size, time_point now);
void update_mtu_limits(); void update_mtu_limits();
void experienced_loss(int seq_nr); void experienced_loss(int seq_nr, time_point now);
void set_state(int s); void set_state(int s);
@ -467,6 +467,10 @@ public:
// the last time we stepped the timestamp history // the last time we stepped the timestamp history
time_point m_last_history_step; time_point m_last_history_step;
// the next time we allow a lost packet to halve cwnd. We only do this once every
// 100 ms
time_point m_next_loss;
// the max number of bytes in-flight. This is a fixed point // the max number of bytes in-flight. This is a fixed point
// value, to get the true number of bytes, shift right 16 bits // value, to get the true number of bytes, shift right 16 bits
// the value is always >= 0, but the calculations performed on // the value is always >= 0, but the calculations performed on
@ -1648,7 +1652,7 @@ void utp_socket_impl::parse_sack(boost::uint16_t const packet_ack, boost::uint8_
// the logic to handle a lost MTU probe is in resend_packet() // the logic to handle a lost MTU probe is in resend_packet()
if (cut_cwnd && (pkt_seq != m_mtu_seq || m_mtu_seq == 0)) if (cut_cwnd && (pkt_seq != m_mtu_seq || m_mtu_seq == 0))
{ {
experienced_loss(pkt_seq); experienced_loss(pkt_seq, now);
cut_cwnd = false; cut_cwnd = false;
} }
@ -2360,7 +2364,7 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
return !m_stalled; return !m_stalled;
} }
void utp_socket_impl::experienced_loss(int const seq_nr) void utp_socket_impl::experienced_loss(int const seq_nr, time_point const now)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -2380,11 +2384,17 @@ void utp_socket_impl::experienced_loss(int const seq_nr)
// same packet again, ignore it. // same packet again, ignore it.
if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return; if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return;
// don't reduce cwnd more than once every 100ms
if (m_next_loss >= now) return;
m_next_loss = now + milliseconds(m_sm->cwnd_reduce_timer());
// cut window size in 2 // cut window size in 2
m_cwnd = std::max(m_cwnd * m_sm->loss_multiplier() / 100 m_cwnd = std::max(m_cwnd * m_sm->loss_multiplier() / 100
, boost::int64_t(m_mtu) * (1 << 16)); , boost::int64_t(m_mtu) * (1 << 16));
m_loss_seq_nr = m_seq_nr; m_loss_seq_nr = m_seq_nr;
UTP_LOGV("%8p: Lost packet %d caused cwnd cut\n", static_cast<void*>(this), seq_nr); UTP_LOGV("%8p: Lost packet %d caused cwnd cut. m_loss_seq_nr:%d\n"
, static_cast<void*>(this), seq_nr, m_seq_nr);
// if we happen to be in slow-start mode, we need to leave it // if we happen to be in slow-start mode, we need to leave it
// note that we set ssthres to the window size _after_ reducing it. Next slow // note that we set ssthres to the window size _after_ reducing it. Next slow
@ -3071,7 +3081,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
{ {
// don't consider a lost probe as proper loss, it doesn't necessarily // don't consider a lost probe as proper loss, it doesn't necessarily
// signal congestion // signal congestion
if (!p->mtu_probe) experienced_loss(m_fast_resend_seq_nr); if (!p->mtu_probe) experienced_loss(m_fast_resend_seq_nr, receive_time);
resend_packet(p, true); resend_packet(p, true);
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true; if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true;
} }
@ -3281,6 +3291,8 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true; if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true;
} }
TORRENT_ASSERT(!compare_less_wrap(m_seq_nr, m_acked_seq_nr, ACK_MASK));
#if TORRENT_UTP_LOG #if TORRENT_UTP_LOG
if (sample && acked_bytes && prev_bytes_in_flight) if (sample && acked_bytes && prev_bytes_in_flight)
{ {