|
|
|
@ -605,7 +605,11 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn |
|
|
|
link->link_status = 0; // down initially
|
|
|
|
link->link_status = 0; // down initially
|
|
|
|
link->handshake_minsize = 100; |
|
|
|
link->handshake_minsize = 100; |
|
|
|
link->handshake_maxsize = mtu;// 28 = udp header size
|
|
|
|
link->handshake_maxsize = mtu;// 28 = udp header size
|
|
|
|
|
|
|
|
link->rtt_swm=swm_create(1024); |
|
|
|
|
|
|
|
if (!link->rtt_swm) { |
|
|
|
|
|
|
|
u_free(link); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Initialize keepalive timeout from global config
|
|
|
|
// Initialize keepalive timeout from global config
|
|
|
|
if (etcp->instance && etcp->instance->config) { |
|
|
|
if (etcp->instance && etcp->instance->config) { |
|
|
|
@ -721,6 +725,7 @@ void etcp_link_close(struct ETCP_LINK* link) { |
|
|
|
|
|
|
|
|
|
|
|
remove_link(link->conn, link->ip_port_hash); |
|
|
|
remove_link(link->conn, link->ip_port_hash); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
swm_destroy(link->rtt_swm); |
|
|
|
u_free(link); |
|
|
|
u_free(link); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -750,6 +755,35 @@ static void link_stats_timer_cb(void* arg) { |
|
|
|
link->stat_win[link->win_ptr].pkt_loss = (uint16_t)link->window_retransmissions; |
|
|
|
link->stat_win[link->win_ptr].pkt_loss = (uint16_t)link->window_retransmissions; |
|
|
|
link->stat_win[link->win_ptr].pkt_transmitted = link->window_pkt_transmitted; |
|
|
|
link->stat_win[link->win_ptr].pkt_transmitted = link->window_pkt_transmitted; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
swm_add(link->rtt_avg10, link->rtt_avg10); |
|
|
|
|
|
|
|
link->rtt_min=swm_get_min(link->rtt_swm); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// пересчитываем BW
|
|
|
|
|
|
|
|
float rtt=(float)link->rtt_min/10000.f;// переводим в секунды
|
|
|
|
|
|
|
|
if (rtt<0.005f) rtt=0.005f;// 5 ms
|
|
|
|
|
|
|
|
if (rtt>1.f) rtt=1.f;// 1 sec
|
|
|
|
|
|
|
|
float win_size=link->inflight_lim_bytes*8.f;// переводим в биты
|
|
|
|
|
|
|
|
if (win_size<100000.f) win_size=100000.f;// 10kb min
|
|
|
|
|
|
|
|
if (win_size>10000000.f) win_size=10000000.f;// 1Mb max
|
|
|
|
|
|
|
|
link->bandwidth=(int)(win_size/rtt/1024.f*1.3f);// результат в кБит/сек
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (link->inflight_lim_bytes<10000 || link->inflight_bytes > link->inflight_lim_bytes - 2000) {// очередь загружена
|
|
|
|
|
|
|
|
int new_lim=link->inflight_lim_bytes; |
|
|
|
|
|
|
|
if (link->rtt_avg10*10 < link->rtt_min*16) {// подъема rtt нет, плавно увеличиваем win
|
|
|
|
|
|
|
|
new_lim+=new_lim/64+1; |
|
|
|
|
|
|
|
if (new_lim>1000000) new_lim=1000000; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
new_lim-=new_lim/64+1; |
|
|
|
|
|
|
|
if (new_lim<10000) new_lim=10000; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
etcp_link_update_inflight_lim(link, new_lim); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// если окно забито - пробуем его расширить
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] stats window updated (win_timebase=%u us, rtt=%u, retrans=%u, transmitted=%u)",
|
|
|
|
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] stats window updated (win_timebase=%u us, rtt=%u, retrans=%u, transmitted=%u)",
|
|
|
|
// link->etcp->log_name, link->win_timebase, link->rtt_avg10, link->window_retransmissions, link->window_pkt_transmitted);
|
|
|
|
// link->etcp->log_name, link->win_timebase, link->rtt_avg10, link->window_retransmissions, link->window_pkt_transmitted);
|
|
|
|
|
|
|
|
|
|
|
|
@ -761,11 +795,11 @@ static void link_stats_timer_cb(void* arg) { |
|
|
|
link->window_retransmissions = 0; |
|
|
|
link->window_retransmissions = 0; |
|
|
|
|
|
|
|
|
|
|
|
// 4. Плавная подстройка win_timebase под rtt/2 (в микросекундах)
|
|
|
|
// 4. Плавная подстройка win_timebase под rtt/2 (в микросекундах)
|
|
|
|
uint32_t target_us = (uint32_t)link->rtt_avg10 * 50ULL; // rtt_avg10 (0.1 ms) → rtt/2 в us
|
|
|
|
// uint32_t target_us = (uint32_t)link->rtt_avg10 * 50ULL; // rtt_avg10 (0.1 ms) → rtt/2 в us
|
|
|
|
if (target_us < 10000) target_us = 10000; // минимум 10 ms
|
|
|
|
// if (target_us < 10000) target_us = 10000; // минимум 10 ms
|
|
|
|
if (target_us > 500000) target_us = 500000; // максимум 0.5 s
|
|
|
|
// if (target_us > 500000) target_us = 500000; // максимум 0.5 s
|
|
|
|
|
|
|
|
|
|
|
|
link->win_timebase = (link->win_timebase * 7 + target_us) / 8; |
|
|
|
link->win_timebase = 10000;// (link->win_timebase * 7 + target_us) / 8;
|
|
|
|
|
|
|
|
|
|
|
|
// 5. Перезапускаем таймер с новым интервалом
|
|
|
|
// 5. Перезапускаем таймер с новым интервалом
|
|
|
|
start_stats_timer(link); |
|
|
|
start_stats_timer(link); |
|
|
|
|