Этап 3a — EOF-хендшейк END/COMPLETE (§10 п.7, техдолг #6 наполовину)

Раньше A после EOF молча закрывал буфер и рапортовал успех независимо от
того, что доехало. Теперь передача завершается подтверждением от B.

- common.h: HDR_SIG_END_1 0xE7 — третий тип кадра (данные F0 AA, END F0 E7,
  STATUS F0 55). Тип задаёт сигнатура, в payload не кодируется.
- feedback.{h,c}: fb_end_t{total_seq,total_bytes} + pack/unpack, 12 Б BE.
  Чистая логика без liquid/iio, как и STATUS.
- transmitter.c: fb_callback публикует STATUS снимком под мьютексом
  (latest-wins — STATUS кумулятивен, очередь не нужна); TX-буфером владеет
  только main. end_phase(): END каждые 100 мс + опрос снимка, до 10 с;
  COMPLETE → exit 0, таймаут → exit 2. Симплекс идёт прежним путём.
- receiver.c: process_end() ветвится по сигнатуре ДО seq-детектора (у END
  свой счётчик seq) и делает backfill хвостовых дыр в NACK — иначе потеря
  последних кадров молчалива: нет следующего seq, по которому видна дыра.
  arq_check_complete() поднимает FB_FLAG_COMPLETE, держит 600 мс (≥6 STATUS
  в тихом эфире END-фазы) и завершает приём штатным stop.
- scripts/test_arq.sh: проверяет протокол, а не только md5 — сторожевой kill
  приёмника = провал (B обязан выйти сам), код возврата A штатный отчёт,
  режим NEGATIVE=1.

Прогон 1 МБ GROUPFEC=0 PAUSE=4000, кабель:
  END 98 отправлено → 98 принято (100%); backfill «не хватает 3» точно равен
  «Потери seq: 3»; A честно exit 2 (ретрансмитов ещё нет — 3b).
  Негатив FBGAIN=-89: доставка STATUS 0%, A exit 2 за 10.0 с — OK.
  Регрессия симплекса: Кадров 1024 ровно, END не просочился; потери 5/7/10/6
  на 4 прогонах — уровень базы §12.8 (3/5/14).
This commit is contained in:
Maxim
2026-07-16 14:14:20 +03:00
parent 4ee9274f09
commit b9846fcbdc

View File

@@ -390,4 +390,4 @@ int main(int argc, char *argv[]) {
if (g_fbrx_buf) iio_buffer_destroy(g_fbrx_buf);
iio_context_destroy(ctx);
return rc;
}
}