forked from premiere/premiere-libtorrent
add more utp statistics and make the congestion controller less aggressive when the up-link is not saturated
This commit is contained in:
parent
84fcc0baf0
commit
1aa47fc13e
|
@ -70,11 +70,26 @@ namespace libtorrent
|
||||||
|
|
||||||
struct utp_status
|
struct utp_status
|
||||||
{
|
{
|
||||||
|
// gauges
|
||||||
int num_idle;
|
int num_idle;
|
||||||
int num_syn_sent;
|
int num_syn_sent;
|
||||||
int num_connected;
|
int num_connected;
|
||||||
int num_fin_sent;
|
int num_fin_sent;
|
||||||
int num_close_wait;
|
int num_close_wait;
|
||||||
|
|
||||||
|
// counters
|
||||||
|
boost::uint64_t packet_loss;
|
||||||
|
boost::uint64_t timeout;
|
||||||
|
boost::uint64_t packets_in;
|
||||||
|
boost::uint64_t packets_out;
|
||||||
|
boost::uint64_t fast_retransmit;
|
||||||
|
boost::uint64_t packet_resend;
|
||||||
|
boost::uint64_t samples_above_target;
|
||||||
|
boost::uint64_t samples_below_target;
|
||||||
|
boost::uint64_t payload_pkts_in;
|
||||||
|
boost::uint64_t payload_pkts_out;
|
||||||
|
boost::uint64_t invalid_pkts_in;
|
||||||
|
boost::uint64_t redundant_pkts_in;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT session_status
|
struct TORRENT_EXPORT session_status
|
||||||
|
|
|
@ -95,6 +95,27 @@ namespace libtorrent
|
||||||
void defer_ack(utp_socket_impl* s);
|
void defer_ack(utp_socket_impl* s);
|
||||||
void subscribe_drained(utp_socket_impl* s);
|
void subscribe_drained(utp_socket_impl* s);
|
||||||
|
|
||||||
|
enum counter_t
|
||||||
|
{
|
||||||
|
packet_loss = 0,
|
||||||
|
timeout,
|
||||||
|
packets_in,
|
||||||
|
packets_out,
|
||||||
|
fast_retransmit,
|
||||||
|
packet_resend,
|
||||||
|
samples_above_target,
|
||||||
|
samples_below_target,
|
||||||
|
payload_pkts_in,
|
||||||
|
payload_pkts_out,
|
||||||
|
invalid_pkts_in,
|
||||||
|
redundant_pkts_in,
|
||||||
|
|
||||||
|
num_counters,
|
||||||
|
};
|
||||||
|
|
||||||
|
// used to keep stats of uTP events
|
||||||
|
void inc_stats_counter(int counter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
udp_socket& m_sock;
|
udp_socket& m_sock;
|
||||||
incoming_utp_callback_t m_cb;
|
incoming_utp_callback_t m_cb;
|
||||||
|
@ -143,6 +164,9 @@ namespace libtorrent
|
||||||
// the buffer size of the socket. This is used
|
// the buffer size of the socket. This is used
|
||||||
// to now lower the buffer size
|
// to now lower the buffer size
|
||||||
int m_sock_buf_size;
|
int m_sock_buf_size;
|
||||||
|
|
||||||
|
// stats counters
|
||||||
|
boost::uint64_t m_counters[num_counters];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1328,6 +1328,19 @@ namespace aux {
|
||||||
|
|
||||||
":peers up send buffer"
|
":peers up send buffer"
|
||||||
|
|
||||||
|
":packet_loss"
|
||||||
|
":timeout"
|
||||||
|
":packets_in"
|
||||||
|
":packets_out"
|
||||||
|
":fast_retransmit"
|
||||||
|
":packet_resend"
|
||||||
|
":samples_above_target"
|
||||||
|
":samples_below_target"
|
||||||
|
":payload_pkts_in"
|
||||||
|
":payload_pkts_out"
|
||||||
|
":invalid_pkts_in"
|
||||||
|
":redundant_pkts_in"
|
||||||
|
|
||||||
"\n\n", m_stats_logger);
|
"\n\n", m_stats_logger);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -4100,6 +4113,19 @@ retry:
|
||||||
|
|
||||||
STAT_LOG(d, peers_up_send_buffer);
|
STAT_LOG(d, peers_up_send_buffer);
|
||||||
|
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.packet_loss);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.timeout);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.packets_in);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.packets_out);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.fast_retransmit);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.packet_resend);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.samples_above_target);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.samples_below_target);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.payload_pkts_in);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.payload_pkts_out);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.invalid_pkts_in);
|
||||||
|
STAT_LOG(PRId64, sst.utp_stats.redundant_pkts_in);
|
||||||
|
|
||||||
fprintf(m_stats_logger, "\n");
|
fprintf(m_stats_logger, "\n");
|
||||||
|
|
||||||
#undef STAT_LOG
|
#undef STAT_LOG
|
||||||
|
|
|
@ -72,6 +72,19 @@ namespace libtorrent
|
||||||
s.num_fin_sent = 0;
|
s.num_fin_sent = 0;
|
||||||
s.num_close_wait = 0;
|
s.num_close_wait = 0;
|
||||||
|
|
||||||
|
s.packet_loss = m_counters[packet_loss];
|
||||||
|
s.timeout = m_counters[timeout];
|
||||||
|
s.packets_in = m_counters[packets_in];
|
||||||
|
s.packets_out = m_counters[packets_out];
|
||||||
|
s.fast_retransmit = m_counters[fast_retransmit];
|
||||||
|
s.packet_resend = m_counters[packet_resend];
|
||||||
|
s.samples_above_target = m_counters[samples_above_target];
|
||||||
|
s.samples_below_target = m_counters[samples_below_target];
|
||||||
|
s.payload_pkts_in = m_counters[payload_pkts_in];
|
||||||
|
s.payload_pkts_out = m_counters[payload_pkts_out];
|
||||||
|
s.invalid_pkts_in = m_counters[invalid_pkts_in];
|
||||||
|
s.redundant_pkts_in = m_counters[redundant_pkts_in];
|
||||||
|
|
||||||
for (socket_map_t::const_iterator i = m_utp_sockets.begin()
|
for (socket_map_t::const_iterator i = m_utp_sockets.begin()
|
||||||
, end(m_utp_sockets.end()); i != end; ++i)
|
, end(m_utp_sockets.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
|
@ -432,6 +445,13 @@ namespace libtorrent
|
||||||
m_sock_buf_size = size;
|
m_sock_buf_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void utp_socket_manager::inc_stats_counter(int counter)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(counter >= 0);
|
||||||
|
TORRENT_ASSERT(counter < num_counters);
|
||||||
|
++m_counters[counter];
|
||||||
|
}
|
||||||
|
|
||||||
utp_socket_impl* utp_socket_manager::new_utp_socket(utp_stream* str)
|
utp_socket_impl* utp_socket_manager::new_utp_socket(utp_stream* str)
|
||||||
{
|
{
|
||||||
boost::uint16_t send_id = 0;
|
boost::uint16_t send_id = 0;
|
||||||
|
|
|
@ -229,7 +229,6 @@ struct utp_socket_impl
|
||||||
, m_connect_handler(0)
|
, m_connect_handler(0)
|
||||||
, m_remote_address()
|
, m_remote_address()
|
||||||
, m_timeout(time_now_hires() + milliseconds(m_sm->connect_timeout()))
|
, m_timeout(time_now_hires() + milliseconds(m_sm->connect_timeout()))
|
||||||
, m_last_cwnd_hit(time_now())
|
|
||||||
, m_last_history_step(time_now_hires())
|
, m_last_history_step(time_now_hires())
|
||||||
, m_cwnd(TORRENT_ETHERNET_MTU << 16)
|
, m_cwnd(TORRENT_ETHERNET_MTU << 16)
|
||||||
, m_buffered_incoming_bytes(0)
|
, m_buffered_incoming_bytes(0)
|
||||||
|
@ -421,12 +420,6 @@ struct utp_socket_impl
|
||||||
// size less than one MSS.
|
// size less than one MSS.
|
||||||
ptime m_timeout;
|
ptime m_timeout;
|
||||||
|
|
||||||
// the last time we wanted to send more data, but couldn't because
|
|
||||||
// it would bring the number of outstanding bytes above the cwnd.
|
|
||||||
// this is used to restrict increasing the cwnd size when we're
|
|
||||||
// not sending fast enough to need it bigger
|
|
||||||
ptime m_last_cwnd_hit;
|
|
||||||
|
|
||||||
// the last time we stepped the timestamp history
|
// the last time we stepped the timestamp history
|
||||||
ptime m_last_history_step;
|
ptime m_last_history_step;
|
||||||
|
|
||||||
|
@ -1524,7 +1517,7 @@ void utp_socket_impl::subscribe_drained()
|
||||||
|
|
||||||
if (m_subscribe_drained) return;
|
if (m_subscribe_drained) return;
|
||||||
|
|
||||||
UTP_LOGV("%8p: socket drained\n", this);
|
UTP_LOGV("%8p: subscribe drained\n", this);
|
||||||
m_subscribe_drained = true;
|
m_subscribe_drained = true;
|
||||||
m_sm->subscribe_drained(this);
|
m_sm->subscribe_drained(this);
|
||||||
}
|
}
|
||||||
|
@ -1578,6 +1571,7 @@ bool utp_socket_impl::send_pkt(int flags)
|
||||||
|
|
||||||
// first see if we need to resend any packets
|
// first see if we need to resend any packets
|
||||||
|
|
||||||
|
// TODO: this loop may not be very efficient
|
||||||
for (int i = (m_acked_seq_nr + 1) & ACK_MASK; i != m_seq_nr; i = (i + 1) & ACK_MASK)
|
for (int i = (m_acked_seq_nr + 1) & ACK_MASK; i != m_seq_nr; i = (i + 1) & ACK_MASK)
|
||||||
{
|
{
|
||||||
packet* p = (packet*)m_outbuf.at(i);
|
packet* p = (packet*)m_outbuf.at(i);
|
||||||
|
@ -1587,8 +1581,8 @@ bool utp_socket_impl::send_pkt(int flags)
|
||||||
{
|
{
|
||||||
// we couldn't resend the packet. It probably doesn't
|
// we couldn't resend the packet. It probably doesn't
|
||||||
// fit in our cwnd. If force is set, we need to continue
|
// fit in our cwnd. If force is set, we need to continue
|
||||||
// to send our force anyway, if we don't have to send an
|
// to send our packet anyway, if we don't have force set,
|
||||||
// force, we might as well return
|
// we might as well return
|
||||||
if (!force) return false;
|
if (!force) return false;
|
||||||
// resend_packet might have failed
|
// resend_packet might have failed
|
||||||
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return false;
|
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return false;
|
||||||
|
@ -1627,7 +1621,6 @@ bool utp_socket_impl::send_pkt(int flags)
|
||||||
if ((flags & pkt_fin) == 0) payload_size = 0;
|
if ((flags & pkt_fin) == 0) payload_size = 0;
|
||||||
|
|
||||||
// we're constrained by the window size
|
// we're constrained by the window size
|
||||||
m_last_cwnd_hit = time_now_hires();
|
|
||||||
m_cwnd_full = true;
|
m_cwnd_full = true;
|
||||||
|
|
||||||
UTP_LOGV("%8p: no space in window send_buffer_size:%d cwnd:%d "
|
UTP_LOGV("%8p: no space in window send_buffer_size:%d cwnd:%d "
|
||||||
|
@ -1686,6 +1679,8 @@ bool utp_socket_impl::send_pkt(int flags)
|
||||||
{
|
{
|
||||||
p = (packet*)malloc(sizeof(packet) + m_mtu);
|
p = (packet*)malloc(sizeof(packet) + m_mtu);
|
||||||
p->allocated = m_mtu;
|
p->allocated = m_mtu;
|
||||||
|
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::payload_pkts_out);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1852,6 +1847,7 @@ bool utp_socket_impl::send_pkt(int flags)
|
||||||
, p->mtu_probe ? utp_socket_manager::dont_fragment : 0);
|
, p->mtu_probe ? utp_socket_manager::dont_fragment : 0);
|
||||||
|
|
||||||
++m_out_packets;
|
++m_out_packets;
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::packets_out);
|
||||||
|
|
||||||
if (ec == error::message_size)
|
if (ec == error::message_size)
|
||||||
{
|
{
|
||||||
|
@ -1993,7 +1989,6 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
|
||||||
&& p->size - p->header_size > window_size_left
|
&& p->size - p->header_size > window_size_left
|
||||||
&& m_bytes_in_flight > 0)
|
&& m_bytes_in_flight > 0)
|
||||||
{
|
{
|
||||||
m_last_cwnd_hit = time_now_hires();
|
|
||||||
m_cwnd_full = true;
|
m_cwnd_full = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2005,6 +2000,9 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
|
||||||
TORRENT_ASSERT(p->size - p->header_size >= 0);
|
TORRENT_ASSERT(p->size - p->header_size >= 0);
|
||||||
if (p->need_resend) m_bytes_in_flight += p->size - p->header_size;
|
if (p->need_resend) m_bytes_in_flight += p->size - p->header_size;
|
||||||
|
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::packet_resend);
|
||||||
|
if (fast_resend) m_sm->inc_stats_counter(utp_socket_manager::fast_retransmit);
|
||||||
|
|
||||||
p->need_resend = false;
|
p->need_resend = false;
|
||||||
utp_header* h = (utp_header*)p->buf;
|
utp_header* h = (utp_header*)p->buf;
|
||||||
// update packet header
|
// update packet header
|
||||||
|
@ -2036,6 +2034,8 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
|
||||||
m_sm->send_packet(udp::endpoint(m_remote_address, m_port)
|
m_sm->send_packet(udp::endpoint(m_remote_address, m_port)
|
||||||
, (char const*)p->buf, p->size, ec);
|
, (char const*)p->buf, p->size, ec);
|
||||||
++m_out_packets;
|
++m_out_packets;
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::packets_out);
|
||||||
|
|
||||||
|
|
||||||
#if TORRENT_UTP_LOG
|
#if TORRENT_UTP_LOG
|
||||||
UTP_LOGV("%8p: re-sending packet seq_nr:%d ack_nr:%d type:%s "
|
UTP_LOGV("%8p: re-sending packet seq_nr:%d ack_nr:%d type:%s "
|
||||||
|
@ -2083,8 +2083,10 @@ void utp_socket_impl::experienced_loss(int seq_nr)
|
||||||
// window size. The first packet that's lost will
|
// window size. The first packet that's lost will
|
||||||
// update the limit to the last sequence number we sent.
|
// update the limit to the last sequence number we sent.
|
||||||
// i.e. only packet sent after this loss can cause another
|
// i.e. only packet sent after this loss can cause another
|
||||||
// window size cut
|
// window size cut. The +1 is to turn the comparison into
|
||||||
if (compare_less_wrap(seq_nr, m_loss_seq_nr, ACK_MASK)) return;
|
// less than or equal to. If we experience loss of the
|
||||||
|
// same packet again, ignore it.
|
||||||
|
if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return;
|
||||||
|
|
||||||
// cut window size in 2
|
// cut window size in 2
|
||||||
m_cwnd = (std::max)(m_cwnd * m_sm->loss_multiplier() / 100, boost::int64_t(m_mtu << 16));
|
m_cwnd = (std::max)(m_cwnd * m_sm->loss_multiplier() / 100, boost::int64_t(m_mtu << 16));
|
||||||
|
@ -2096,6 +2098,7 @@ void utp_socket_impl::experienced_loss(int 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
|
||||||
m_slow_start = false;
|
m_slow_start = false;
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::packet_loss);
|
||||||
}
|
}
|
||||||
|
|
||||||
void utp_socket_impl::maybe_inc_acked_seq_nr()
|
void utp_socket_impl::maybe_inc_acked_seq_nr()
|
||||||
|
@ -2416,10 +2419,13 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
|
|
||||||
utp_header* ph = (utp_header*)buf;
|
utp_header* ph = (utp_header*)buf;
|
||||||
|
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::packets_in);
|
||||||
|
|
||||||
if (ph->get_version() != 1)
|
if (ph->get_version() != 1)
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet version:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet version:%d (ignored)\n"
|
||||||
, this, int(ph->get_version()));
|
, this, int(ph->get_version()));
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2428,6 +2434,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet id:%d expected:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet id:%d expected:%d (ignored)\n"
|
||||||
, this, int(ph->connection_id), int(m_recv_id));
|
, this, int(ph->connection_id), int(m_recv_id));
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2435,6 +2442,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet type:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet type:%d (ignored)\n"
|
||||||
, this, int(ph->get_type()));
|
, this, int(ph->get_type()));
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2447,6 +2455,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
if (m_state != UTP_STATE_NONE && ph->get_type() == ST_SYN)
|
if (m_state != UTP_STATE_NONE && ph->get_type() == ST_SYN)
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet type:ST_SYN (ignored)\n", this);
|
UTP_LOGV("%8p: incoming packet type:ST_SYN (ignored)\n", this);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2482,6 +2491,8 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
, this, m_reply_micro, prev_base ? base_change : 0);
|
, this, m_reply_micro, prev_base ? base_change : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 2 sequence number, source IP and connection ID should be
|
||||||
|
// verified before accepting a reset packet
|
||||||
if (ph->get_type() == ST_RESET)
|
if (ph->get_type() == ST_RESET)
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet type:RESET\n", this);
|
UTP_LOGV("%8p: incoming packet type:RESET\n", this);
|
||||||
|
@ -2511,6 +2522,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet ack_nr:%d our seq_nr:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet ack_nr:%d our seq_nr:%d (ignored)\n"
|
||||||
, this, int(ph->ack_nr), m_seq_nr);
|
, this, int(ph->ack_nr), m_seq_nr);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::redundant_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2532,6 +2544,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
// we've already received this packet
|
// we've already received this packet
|
||||||
UTP_LOGV("%8p: incoming packet seq_nr:%d our ack_nr:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet seq_nr:%d our ack_nr:%d (ignored)\n"
|
||||||
, this, int(ph->seq_nr), m_ack_nr);
|
, this, int(ph->seq_nr), m_ack_nr);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::redundant_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -2545,6 +2558,9 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ph->get_type() == ST_DATA)
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::payload_pkts_in);
|
||||||
|
|
||||||
if (m_state != UTP_STATE_NONE
|
if (m_state != UTP_STATE_NONE
|
||||||
&& m_state != UTP_STATE_SYN_SENT
|
&& m_state != UTP_STATE_SYN_SENT
|
||||||
&& compare_less_wrap((m_ack_nr + max_packets_reorder) & ACK_MASK, ph->seq_nr, ACK_MASK))
|
&& compare_less_wrap((m_ack_nr + max_packets_reorder) & ACK_MASK, ph->seq_nr, ACK_MASK))
|
||||||
|
@ -2556,6 +2572,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
// to drop the timestamp information.
|
// to drop the timestamp information.
|
||||||
UTP_LOGV("%8p: incoming packet seq_nr:%d our ack_nr:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet seq_nr:%d our ack_nr:%d (ignored)\n"
|
||||||
, this, int(ph->seq_nr), m_ack_nr);
|
, this, int(ph->seq_nr), m_ack_nr);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::redundant_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2637,6 +2654,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
if (ptr - buf + 2 > size)
|
if (ptr - buf + 2 > size)
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: invalid extension header\n", this);
|
UTP_LOGV("%8p: invalid extension header\n", this);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int next_extension = *ptr++;
|
int next_extension = *ptr++;
|
||||||
|
@ -2645,12 +2663,14 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: invalid extension length:%d packet:%d\n"
|
UTP_LOGV("%8p: invalid extension length:%d packet:%d\n"
|
||||||
, this, len, int(ptr - buf));
|
, this, len, int(ptr - buf));
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ptr - buf + len > size_t(size))
|
if (ptr - buf + len > size_t(size))
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: invalid extension header size:%d packet:%d\n"
|
UTP_LOGV("%8p: invalid extension header size:%d packet:%d\n"
|
||||||
, this, len, int(ptr - buf));
|
, this, len, int(ptr - buf));
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::invalid_pkts_in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
switch(extension)
|
switch(extension)
|
||||||
|
@ -3077,6 +3097,10 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
|
||||||
|
|
||||||
int target_delay = m_sm->target_delay();
|
int target_delay = m_sm->target_delay();
|
||||||
|
|
||||||
|
// true if the upper layer is pushing enough data down the socket to be
|
||||||
|
// limited by the cwnd. If this is not the case, we should not adjust cwnd.
|
||||||
|
bool cwnd_saturated = (m_bytes_in_flight + acked_bytes + m_mtu > (m_cwnd << 16));
|
||||||
|
|
||||||
// all of these are fixed points with 16 bits fraction portion
|
// all of these are fixed points with 16 bits fraction portion
|
||||||
boost::int64_t window_factor = (boost::int64_t(acked_bytes) << 16) / in_flight;
|
boost::int64_t window_factor = (boost::int64_t(acked_bytes) << 16) / in_flight;
|
||||||
boost::int64_t delay_factor = (boost::int64_t(target_delay - delay) << 16) / target_delay;
|
boost::int64_t delay_factor = (boost::int64_t(target_delay - delay) << 16) / target_delay;
|
||||||
|
@ -3085,39 +3109,41 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
|
||||||
if (delay >= target_delay)
|
if (delay >= target_delay)
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: off_target: %d slow_start -> 0\n", this, target_delay - delay);
|
UTP_LOGV("%8p: off_target: %d slow_start -> 0\n", this, target_delay - delay);
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::samples_above_target);
|
||||||
m_slow_start = false;
|
m_slow_start = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::samples_below_target);
|
||||||
|
}
|
||||||
|
|
||||||
boost::int64_t linear_gain = (window_factor * delay_factor) >> 16;
|
boost::int64_t linear_gain = (window_factor * delay_factor) >> 16;
|
||||||
linear_gain *= boost::int64_t(m_sm->gain_factor());
|
linear_gain *= boost::int64_t(m_sm->gain_factor());
|
||||||
|
|
||||||
if (m_slow_start)
|
// if the user is not saturating the link (i.e. not filling the
|
||||||
|
// congestion window), don't adjust it at all.
|
||||||
|
if (cwnd_saturated)
|
||||||
{
|
{
|
||||||
// mimic TCP slow-start by adding the number of acked
|
if (m_slow_start)
|
||||||
// bytes to cwnd
|
{
|
||||||
scaled_gain = (std::max)(boost::int64_t(acked_bytes) << 16, linear_gain);
|
// mimic TCP slow-start by adding the number of acked
|
||||||
|
// bytes to cwnd
|
||||||
|
scaled_gain = (std::max)(boost::int64_t(acked_bytes) << 16, linear_gain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scaled_gain = linear_gain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scaled_gain = linear_gain;
|
scaled_gain = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we don't wrap the cwnd
|
// make sure we don't wrap the cwnd
|
||||||
if (scaled_gain >= INT64_MAX - m_cwnd)
|
if (scaled_gain >= INT64_MAX - m_cwnd)
|
||||||
scaled_gain = INT64_MAX - m_cwnd - 1;
|
scaled_gain = INT64_MAX - m_cwnd - 1;
|
||||||
|
|
||||||
if (scaled_gain > 0 && !m_cwnd_full
|
|
||||||
&& m_last_cwnd_hit + milliseconds(50) < now)
|
|
||||||
{
|
|
||||||
UTP_LOGV("%8p: last_cwnd_hit:%d full_cwnd:%d scaled_gain -> 0, slow_start -> 0\n", this
|
|
||||||
, total_milliseconds(now - m_last_cwnd_hit), int(m_cwnd_full));
|
|
||||||
// we haven't bumped into the cwnd limit size in the last second
|
|
||||||
// this probably means we have a send rate limit, so we shouldn't make
|
|
||||||
// the cwnd size any larger
|
|
||||||
scaled_gain = 0;
|
|
||||||
m_slow_start = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTP_LOGV("%8p: do_ledbat delay:%d off_target: %d window_factor:%f target_factor:%f "
|
UTP_LOGV("%8p: do_ledbat delay:%d off_target: %d window_factor:%f target_factor:%f "
|
||||||
"scaled_gain:%f cwnd:%d slow_start:%d\n"
|
"scaled_gain:%f cwnd:%d slow_start:%d\n"
|
||||||
, this, delay, target_delay - delay, window_factor / float(1 << 16)
|
, this, delay, target_delay - delay, window_factor / float(1 << 16)
|
||||||
|
@ -3143,7 +3169,6 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: mtu:%d in_flight:%d adv_wnd:%d cwnd:%d acked_bytes:%d cwnd_full -> 0\n"
|
UTP_LOGV("%8p: mtu:%d in_flight:%d adv_wnd:%d cwnd:%d acked_bytes:%d cwnd_full -> 0\n"
|
||||||
, this, m_mtu, in_flight, int(m_adv_wnd), int(m_cwnd >> 16), acked_bytes);
|
, this, m_mtu, in_flight, int(m_adv_wnd), int(m_cwnd >> 16), acked_bytes);
|
||||||
if (m_cwnd_full) m_last_cwnd_hit = time_now_hires();
|
|
||||||
m_cwnd_full = false;
|
m_cwnd_full = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3194,6 +3219,8 @@ void utp_socket_impl::tick(ptime const& now)
|
||||||
// TIMEOUT!
|
// TIMEOUT!
|
||||||
// set cwnd to 1 MSS
|
// set cwnd to 1 MSS
|
||||||
|
|
||||||
|
m_sm->inc_stats_counter(utp_socket_manager::timeout);
|
||||||
|
|
||||||
if (m_outbuf.size()) ++m_num_timeouts;
|
if (m_outbuf.size()) ++m_num_timeouts;
|
||||||
|
|
||||||
if (m_num_timeouts > m_sm->num_resends())
|
if (m_num_timeouts > m_sm->num_resends())
|
||||||
|
|
Loading…
Reference in New Issue