Adapt sender ACK receive window based on observed timing
This commit is contained in:
51
src/main.cpp
51
src/main.cpp
@@ -105,6 +105,7 @@ static uint32_t g_sender_ack_timeout_total = 0;
|
||||
static uint32_t g_sender_ack_retry_total = 0;
|
||||
static uint32_t g_sender_ack_rtt_last_ms = 0;
|
||||
static uint32_t g_sender_ack_rtt_ewma_ms = 0;
|
||||
static uint32_t g_sender_ack_miss_streak = 0;
|
||||
static RxRejectReason g_sender_rx_reject_reason = RxRejectReason::None;
|
||||
static uint32_t g_sender_rx_reject_log_ms = 0;
|
||||
static RxRejectReason g_receiver_rx_reject_reason = RxRejectReason::None;
|
||||
@@ -203,7 +204,7 @@ static void sender_log_diagnostics(uint32_t now_ms) {
|
||||
}
|
||||
|
||||
serial_debug_printf(
|
||||
"diag: q_depth=%lu q_hi=%lu q_drop=%lu batch_q=%u build=%u ack_pending=%u ack_retry_cur=%u ack_retry_total=%lu ack_timeout_total=%lu ack_rtt_last_ms=%lu ack_rtt_ewma_ms=%lu meter_ok=%lu meter_fail=%lu meter_ovf=%lu meter_timeout=%lu meter_age_ms=%lu rx_win_ms=%lu sleep_ms=%lu",
|
||||
"diag: q_depth=%lu q_hi=%lu q_drop=%lu batch_q=%u build=%u ack_pending=%u ack_retry_cur=%u ack_retry_total=%lu ack_timeout_total=%lu ack_rtt_last_ms=%lu ack_rtt_ewma_ms=%lu ack_miss_streak=%lu meter_ok=%lu meter_fail=%lu meter_ovf=%lu meter_timeout=%lu meter_age_ms=%lu rx_win_ms=%lu sleep_ms=%lu",
|
||||
static_cast<unsigned long>(queue_depth),
|
||||
static_cast<unsigned long>(g_meter_queue_high_water),
|
||||
static_cast<unsigned long>(g_meter_queue_drop_count),
|
||||
@@ -215,6 +216,7 @@ static void sender_log_diagnostics(uint32_t now_ms) {
|
||||
static_cast<unsigned long>(g_sender_ack_timeout_total),
|
||||
static_cast<unsigned long>(g_sender_ack_rtt_last_ms),
|
||||
static_cast<unsigned long>(g_sender_ack_rtt_ewma_ms),
|
||||
static_cast<unsigned long>(g_sender_ack_miss_streak),
|
||||
static_cast<unsigned long>(meter_stats.frames_ok),
|
||||
static_cast<unsigned long>(meter_stats.frames_parse_fail),
|
||||
static_cast<unsigned long>(meter_stats.rx_overflow),
|
||||
@@ -1384,26 +1386,49 @@ static void sender_loop() {
|
||||
LoraPacket ack_pkt = {};
|
||||
constexpr size_t ack_len = lora_frame_size(LORA_ACK_DOWN_PAYLOAD_LEN);
|
||||
uint32_t ack_air_ms = lora_airtime_ms(ack_len);
|
||||
uint32_t ack_window_ms = ack_air_ms + 300;
|
||||
if (ack_window_ms < 1200) {
|
||||
ack_window_ms = 1200;
|
||||
uint32_t ack_window_first_ms = ack_air_ms + 200;
|
||||
if (g_sender_ack_rtt_ewma_ms > 0) {
|
||||
uint32_t rtt_based_ms = g_sender_ack_rtt_ewma_ms + 150;
|
||||
if (rtt_based_ms > ack_window_first_ms) {
|
||||
ack_window_first_ms = rtt_based_ms;
|
||||
}
|
||||
if (ack_window_ms > 4000) {
|
||||
ack_window_ms = 4000;
|
||||
}
|
||||
uint32_t miss_boost_ms = g_sender_ack_miss_streak * 150;
|
||||
if (miss_boost_ms > 1200) {
|
||||
miss_boost_ms = 1200;
|
||||
}
|
||||
ack_window_first_ms += miss_boost_ms;
|
||||
if (ack_window_first_ms < 600) {
|
||||
ack_window_first_ms = 600;
|
||||
}
|
||||
if (ack_window_first_ms > 2500) {
|
||||
ack_window_first_ms = 2500;
|
||||
}
|
||||
uint32_t ack_window_second_ms = ack_window_first_ms + (ack_window_first_ms / 2);
|
||||
uint32_t min_second_ms = ack_air_ms + 400;
|
||||
if (ack_window_second_ms < min_second_ms) {
|
||||
ack_window_second_ms = min_second_ms;
|
||||
}
|
||||
if (ack_window_second_ms > 5000) {
|
||||
ack_window_second_ms = 5000;
|
||||
}
|
||||
if (SERIAL_DEBUG_MODE) {
|
||||
serial_debug_printf("ack: rx window=%lu airtime=%lu", static_cast<unsigned long>(ack_window_ms),
|
||||
static_cast<unsigned long>(ack_air_ms));
|
||||
serial_debug_printf("ack: rx windows=%lu/%lu airtime=%lu miss_streak=%lu",
|
||||
static_cast<unsigned long>(ack_window_first_ms),
|
||||
static_cast<unsigned long>(ack_window_second_ms),
|
||||
static_cast<unsigned long>(ack_air_ms),
|
||||
static_cast<unsigned long>(g_sender_ack_miss_streak));
|
||||
}
|
||||
uint32_t rx_start = millis();
|
||||
bool got_ack = lora_receive_window(ack_pkt, ack_window_ms);
|
||||
bool got_ack = lora_receive_window(ack_pkt, ack_window_first_ms);
|
||||
if (!got_ack) {
|
||||
got_ack = lora_receive_window(ack_pkt, ack_window_ms / 2);
|
||||
got_ack = lora_receive_window(ack_pkt, ack_window_second_ms);
|
||||
}
|
||||
uint32_t rx_elapsed = millis() - rx_start;
|
||||
if (SERIAL_DEBUG_MODE) {
|
||||
g_sender_rx_window_ms += rx_elapsed;
|
||||
}
|
||||
bool ack_accepted = false;
|
||||
if (!got_ack) {
|
||||
RxRejectReason reason = lora_get_last_rx_reject_reason();
|
||||
sender_note_rx_reject(reason, "ack");
|
||||
@@ -1445,6 +1470,7 @@ static void sender_loop() {
|
||||
uint32_t ack_epoch = read_u32_be(&ack_pkt.payload[3]);
|
||||
bool set_time = false;
|
||||
if (g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
||||
ack_accepted = true;
|
||||
g_sender_ack_rtt_last_ms = rx_elapsed;
|
||||
if (g_sender_ack_rtt_ewma_ms == 0) {
|
||||
g_sender_ack_rtt_ewma_ms = rx_elapsed;
|
||||
@@ -1475,6 +1501,11 @@ static void sender_loop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ack_accepted) {
|
||||
g_sender_ack_miss_streak = 0;
|
||||
} else if (g_sender_ack_miss_streak < UINT32_MAX) {
|
||||
g_sender_ack_miss_streak++;
|
||||
}
|
||||
}
|
||||
if (!g_batch_ack_pending) {
|
||||
lora_sleep();
|
||||
|
||||
Reference in New Issue
Block a user