From 786d78b6c955486faaddd63cfcc7fecb6299282b Mon Sep 17 00:00:00 2001 From: arvidn Date: Mon, 7 Jan 2019 01:27:02 +0100 Subject: [PATCH] only allow cwnd to be reduced so often --- include/libtorrent/settings_pack.hpp | 5 +++++ include/libtorrent/utp_socket_manager.hpp | 1 + src/settings_pack.cpp | 1 + src/utp_stream.cpp | 22 +++++++++++++++++----- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index b14947fd8..9ff65a2c0 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -1608,6 +1608,11 @@ namespace libtorrent // systems. 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 }; diff --git a/include/libtorrent/utp_socket_manager.hpp b/include/libtorrent/utp_socket_manager.hpp index 8865fbd2f..4181d191c 100644 --- a/include/libtorrent/utp_socket_manager.hpp +++ b/include/libtorrent/utp_socket_manager.hpp @@ -87,6 +87,7 @@ namespace libtorrent 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 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 set_sock_buf(int size); diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 4e1ab9590..a8018e6f1 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -366,6 +366,7 @@ namespace libtorrent SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 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(utp_cwnd_reduce_timer, 100, 0), }; #undef SET diff --git a/src/utp_stream.cpp b/src/utp_stream.cpp index a3301565a..991a19def 100644 --- a/src/utp_stream.cpp +++ b/src/utp_stream.cpp @@ -359,7 +359,7 @@ struct utp_socket_impl bool consume_incoming_data( utp_header const* ph, boost::uint8_t const* ptr, int payload_size, time_point now); void update_mtu_limits(); - void experienced_loss(int seq_nr); + void experienced_loss(int seq_nr, time_point now); void set_state(int s); @@ -467,6 +467,10 @@ public: // the last time we stepped the timestamp history 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 // value, to get the true number of bytes, shift right 16 bits // 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() if (cut_cwnd && (pkt_seq != m_mtu_seq || m_mtu_seq == 0)) { - experienced_loss(pkt_seq); + experienced_loss(pkt_seq, now); cut_cwnd = false; } @@ -2360,7 +2364,7 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend) 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; @@ -2380,11 +2384,17 @@ void utp_socket_impl::experienced_loss(int const seq_nr) // same packet again, ignore it. 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 m_cwnd = std::max(m_cwnd * m_sm->loss_multiplier() / 100 , boost::int64_t(m_mtu) * (1 << 16)); m_loss_seq_nr = m_seq_nr; - UTP_LOGV("%8p: Lost packet %d caused cwnd cut\n", static_cast(this), seq_nr); + UTP_LOGV("%8p: Lost packet %d caused cwnd cut. m_loss_seq_nr:%d\n" + , static_cast(this), seq_nr, m_seq_nr); // 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 @@ -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 // 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); 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; } + TORRENT_ASSERT(!compare_less_wrap(m_seq_nr, m_acked_seq_nr, ACK_MASK)); + #if TORRENT_UTP_LOG if (sample && acked_bytes && prev_bytes_in_flight) {