@ -21,8 +21,8 @@
// Constants from spec (adjusted for completeness)
# define MAX_INFLIGHT_BYTES 65536 // Initial window
# define RETRANS_K1 2.0f // RTT multiplier for retrans timeout
# define RETRANS_K2 1.5f // Jitter multiplier
# define RETRANS_K1 32 // RTT multiplier for retrans timeout
# define RETRANS_K2 32 // Jitter multiplier
# define ACK_DELAY_TB 20 // ACK timer delay (2ms in 0.1ms units)
# define BURST_DELAY_FACTOR 4 // Delay before burst
# define BURST_SIZE 5 // Packets in burst (1 delayed + 4 burst)
@ -555,7 +555,9 @@ static void ack_timeout_check(struct ETCP_CONN* etcp) {
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " " ) ;
uint64_t now = get_time_tb ( ) ;
int64_t timeout = 1000 ; //(uint64_t)(etcp->rtt_avg_10 * RETRANS_K1) + (uint64_t)(etcp->jitter * RETRANS_K2);
int32_t timeout = ( etcp - > rtt_avg_10 * RETRANS_K1 + etcp - > jitter * RETRANS_K2 ) / 16 ;
if ( timeout < 50 ) timeout = 50 ;
if ( timeout > 10000 ) timeout = 10000 ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP , " starting check, now=%llu, timeout=%llu, rtt_avg_10=%u, jitter=%u " ,
( unsigned long long ) now , ( unsigned long long ) timeout , etcp - > rtt_avg_10 , etcp - > jitter ) ;
@ -898,37 +900,6 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d
return ;
}
// Calculate RTT if timestamps are valid
/* if (ts != (uint16_t)-1 && dts != (uint16_t)-1) {
uint16_t rtt = timestamp_diff ( ts , dts ) ;
etcp - > rtt_last = rtt ;
// Update RTT averages (exponential smoothing)
if ( etcp - > rtt_avg_10 = = 0 ) {
etcp - > rtt_avg_10 = rtt ;
etcp - > rtt_avg_100 = rtt ;
} else {
// RTT average over 10 packets
etcp - > rtt_avg_10 = ( etcp - > rtt_avg_10 * 9 + rtt ) / 10 ;
// RTT average over 100 packets
etcp - > rtt_avg_100 = ( etcp - > rtt_avg_100 * 99 + rtt ) / 100 ;
}
// Update jitter calculation (max - min of last 10 RTT samples)
etcp - > rtt_history [ etcp - > rtt_history_idx ] = rtt ;
etcp - > rtt_history_idx = ( etcp - > rtt_history_idx + 1 ) % 10 ;
uint16_t rtt_min = UINT16_MAX , rtt_max = 0 ;
for ( int i = 0 ; i < 10 ; i + + ) {
if ( etcp - > rtt_history [ i ] < rtt_min ) rtt_min = etcp - > rtt_history [ i ] ;
if ( etcp - > rtt_history [ i ] > rtt_max ) rtt_max = etcp - > rtt_history [ i ] ;
}
etcp - > jitter = rtt_max - rtt_min ;
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTT updated - last=%u, avg_10=%u, avg_100=%u, jitter=%u",
// etcp->log_name, rtt, etcp->rtt_avg_10, etcp->rtt_avg_100, etcp->jitter);
}
*/
// Update connection statistics
etcp - > unacked_bytes - = acked_pkt - > ll . len ;
etcp - > bytes_sent_total + = acked_pkt - > ll . len ;
@ -960,10 +931,6 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
uint16_t len = pkt - > data_len ;
uint16_t ts = pkt - > timestamp ; // Received timestamp
// Note: Assume packet starts with sections after timestamp (but timestamp is already extracted in connections?).
// Protocol.txt: timestamp is first 2B, then sections.
// But in conn_input, pkt->data is after timestamp? Assume data starts with first section.
while ( len > = 1 ) {
uint8_t type = data [ 0 ] ;
@ -987,32 +954,83 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
case ETCP_SECTION_TIMESTAMP : {
uint16_t cur_ts = get_current_timestamp ( ) ;
uint16_t ret_ts = data [ 1 ] | ( data [ 2 ] < < 8 ) ; // cur_ts=ret_ts = RTT
pkt - > link - > rtt_last = cur_ts - ret_ts ;
uint16_t new_rtt = cur_ts - ret_ts ;
pkt - > link - > rtt_last = new_rtt ;
uint8_t old_idx = pkt - > link - > rtt_history_index ;
uint16_t old_val = pkt - > link - > rtt_history [ old_idx ] ;
pkt - > link - > rtt_history [ old_idx ] = new_rtt ;
pkt - > link - > rtt_history_index = ( old_idx + 1 ) % 10 ;
if ( pkt - > link - > rtt_history_count < 10 ) pkt - > link - > rtt_history_count + + ;
if ( new_rtt > = pkt - > link - > rtt_max_val ) {
pkt - > link - > rtt_max_val = new_rtt ;
pkt - > link - > rtt_max_idx = old_idx ;
} else if ( old_val = = pkt - > link - > rtt_max_val ) {
pkt - > link - > rtt_max_idx = 255 ;
}
uint8_t rtt_cnt = pkt - > link - > rtt_history_count ;
if ( rtt_cnt = = 1 ) {
pkt - > link - > rtt_avg10 = new_rtt ;
} else {
uint32_t sum = 0 ;
if ( pkt - > link - > rtt_max_idx = = 255 ) {
uint16_t max_val = 0 ;
uint8_t max_pos = 0 ;
for ( uint8_t i = 0 ; i < rtt_cnt ; i + + ) {
uint16_t v = pkt - > link - > rtt_history [ i ] ;
sum + = v ;
if ( v > max_val ) {
max_val = v ;
max_pos = i ;
}
}
pkt - > link - > rtt_max_val = max_val ;
pkt - > link - > rtt_max_idx = max_pos ;
} else {
for ( uint8_t i = 0 ; i < rtt_cnt ; i + + ) {
sum + = pkt - > link - > rtt_history [ i ] ;
}
}
pkt - > link - > rtt_avg10 = ( sum - pkt - > link - > rtt_max_val ) / ( rtt_cnt - 1 ) ;
}
int recv_dt_tx1 = data [ 3 ] | ( data [ 4 ] < < 8 ) ; // localtime удаленной стороны момента принятия пакета - timestamp этого пакета (на стороне отправителя, т.е. у нас)
int recv_dt_tx = recv_dt_tx1 - pkt - > link - > rtt_last / 2 ;
int recv_dt_rx = cur_ts - pkt - > link - > rtt_last / 2 - ts ;
if ( pkt - > link - > recv_dt_avg_rx = = 0 ) pkt - > link - > recv_dt_avg_rx = recv_dt_rx * 256 ;
if ( pkt - > link - > recv_dt_avg_tx = = 0 ) pkt - > link - > recv_dt_avg_tx = recv_dt_tx * 256 ;
pkt - > link - > recv_dt_avg_rx + = ( recv_dt_rx * 256 - pkt - > link - > recv_dt_avg_rx ) / 256 ;
pkt - > link - > recv_dt_avg_tx + = ( recv_dt_tx * 256 - pkt - > link - > recv_dt_avg_tx ) / 256 ;
pkt - > link - > tt_last = recv_dt_tx1 ; // - pkt->link->recv_dt_avg_tx/256;
pkt - > link - > rt_last = cur_ts - ts - pkt - > link - > recv_dt_avg_tx / 256 ;
int recv_dt_rx = cur_ts - pkt - > link - > rtt_last / 2 - 1000 - ts ;
int recv_dt_tx = recv_dt_tx1 - pkt - > link - > rtt_last / 2 - 1000 ;
if ( pkt - > link - > recv_dt_avg_rx = = 0 ) pkt - > link - > recv_dt_avg_rx = recv_dt_rx * 6553 6;
if ( pkt - > link - > recv_dt_avg_tx = = 0 ) pkt - > link - > recv_dt_avg_tx = recv_dt_tx * 6553 6;
pkt - > link - > recv_dt_avg_rx + = ( ( int32_t ) ( recv_dt_rx * 6553 6 - pkt - > link - > recv_dt_avg_rx ) ) / 3 2;
pkt - > link - > recv_dt_avg_tx + = ( ( int32_t ) ( recv_dt_tx * 6553 6 - pkt - > link - > recv_dt_avg_tx ) ) / 3 2;
pkt - > link - > rt_last = cur_ts - ts - pkt - > link - > recv_dt_avg_rx / 65536 ;
pkt - > link - > tt_last = recv_dt_tx1 - pkt - > link - > recv_dt_avg_tx / 6553 6;
//tts_correction += ((NOW - RTT/2 - TTS) - tts_correction)/16 (инициализируем сразу по 1 пакету)
data + = 5 ; len - = 5 ;
int d_rtt = pkt - > link - > rtt_avg10 - pkt - > link - > rtt_last ;
if ( d_rtt < 0 ) d_rtt = - d_rtt ;
pkt - > link - > jitter + = ( ( int32_t ) ( d_rtt * 65536 - pkt - > link - > jitter ) ) / 32 ;
struct ETCP_LINK * c = etcp - > links ;
int rtt_sum = 0 ;
int rtt_a10_max = 0 ;
int tt_sum = 0 ;
int j_sum = 0 ;
int cnt = 0 ;
while ( c ) {
rtt_sum + = c - > rtt_last ;
if ( rtt_a10_max < c - > rtt_avg10 ) rtt_a10_max = c - > rtt_avg10 ;
tt_sum + = c - > tt_last ;
j_sum + = c - > jitter / 32768 ;
cnt + + ;
c = c - > next ;
}
etcp - > rtt_last = rtt_sum / cnt ;
etcp - > rtt_avg_10 = rtt_a10_max ;
etcp - > tt_last = tt_sum / cnt ;
etcp - > jitter = j_sum / cnt ;
break ;
}
case ETCP_SECTION_PAYLOAD : {