Define independent logical fragments and per-path transmission attempts
This commit is contained in:
1 parent
3c44c3d7bc
commit
b68e0ac3db
3 files changed
+79
-19
No files matched your search
+17
-15
@@ -9,6 +9,7 @@
|
||||
#include "etcp_connections.h"
|
||||
#include "secure_channel.h"
|
||||
#include "etcp_padding.h"
|
||||
#include "etcp_tx.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -36,6 +37,7 @@ uint16_t get_current_timestamp(void);
|
||||
#define ETCP_SECTION_MEAS_TS 0x07 // Measurement timestamp for bandwidth (burst packet)
|
||||
#define ETCP_SECTION_MEAS_RESP 0x08 // Measurement response (burst result)
|
||||
#define ETCP_SECTION_FILLER 0x09 // Filler/dummy data (discarded by receiver)
|
||||
#define ETCP_SECTION_ACK_REQUEST 0x0a // запрос актуальной логической границы, без DATA/BBR sample
|
||||
|
||||
// Burst measurement constants
|
||||
#define BURST_PACKET_COUNT 12 // число пакетов в burst
|
||||
@@ -73,17 +75,14 @@ uint16_t get_current_timestamp(void);
|
||||
struct INFLIGHT_PACKET {// выделяется из etcp->inflight_pool
|
||||
struct ll_entry ll;
|
||||
uint32_t seq; // packet seq (ID по документации)
|
||||
struct ETCP_LINK* last_link; // Последний линк попытки; занимает его окно только в WAIT_ACK
|
||||
struct ETCP_LINK* last_link; // Заимствованный курсор выбора следующего пути; очищается перед free линка
|
||||
uint64_t last_timestamp; // Last send timestamp
|
||||
uint8_t send_count; // Number of sends
|
||||
uint8_t retrans_req_count; // Number of retrans requests
|
||||
uint8_t state; // WAIT_ACK занимает окно last_link; WAIT_SEND ожидает первую/повторную отправку
|
||||
uint64_t last_attempt_id; // Последняя принятая транспортом попытка; ненулевой ID отличает retry
|
||||
uint32_t send_count; // Статистика отправок с насыщением, без wrap
|
||||
uint32_t retrans_req_count; // Число запросов повтора с насыщением
|
||||
uint32_t active_attempts; // Попытки этого seq, ещё занимающие окна каналов
|
||||
uint8_t state; // WAIT_SEND — готов к отправке; WAIT_ACK — логически ожидает доставки
|
||||
uint8_t send_hist[8]; // через какие каналы передавался пакет (NEW). send_count - head ptr
|
||||
uint64_t delivered_at_send; // link->delivered_bytes на момент отправки (для BBR prior_delivered)
|
||||
uint64_t delivered_time_at_send_tb; // время последней доставки при отправке; начало ACK-интервала BBR
|
||||
uint64_t first_tx_at_send_tb; // начало интервала отправок BBR (оба интервала — в 0.1мс)
|
||||
uint32_t inflight_at_send; // link->inflight_bytes на момент отправки (для BBR tx_in_flight)
|
||||
uint8_t is_app_limited; // данные ограничены приложением на момент отправки
|
||||
};
|
||||
|
||||
// Список пакетов для сборки. собирается в ll_queue (используем быстрый поиск с хешем)
|
||||
@@ -95,9 +94,9 @@ struct ETCP_FRAGMENT {// выделяется из пула etcp->rx_pool
|
||||
|
||||
struct ACK_PACKET {
|
||||
struct ll_entry ll;
|
||||
uint32_t seq;// sequence number
|
||||
uint16_t pkt_timestamp;// timestamp пакета (часы уладенной стороны)
|
||||
uint32_t recv_timestamp;// время приема (локальное)
|
||||
uint64_t attempt_id; // Индекс очереди конкретного линка
|
||||
uint32_t seq; // Логический фрагмент
|
||||
uint64_t received_at_us; // Полное локальное время, без modulo-wrap задержки
|
||||
};
|
||||
|
||||
#define ETCP_TX_STATE_DATA_WAIT 1
|
||||
@@ -143,11 +142,11 @@ struct ETCP_CONN {
|
||||
|
||||
// Inflight очереди (2 шт) - пока пакет в статусе inflight - к нему прикрепляется struct INFLIGHT_PACKET
|
||||
struct memory_pool* inflight_pool; // память для inflight очередей
|
||||
struct memory_pool* attempt_pool; // метаданные физических попыток; payload принадлежат inflight_pool
|
||||
struct memory_pool* io_pool; // память для rx очередей
|
||||
|
||||
struct ll_queue* input_send_q; // очередь на отправку (inflight_pool -> INFLIGHT_PACKET)
|
||||
struct ll_queue* input_wait_ack; // очередь ожидающих подтверждение (inflight_pool -> struct INFLIGHT_PACKET)
|
||||
struct ll_queue* ack_q; // неотправленные подтверждения приема пакетов (instance.ack_pool -> struct ACK_PACKET) + index [+0 SEQ]
|
||||
|
||||
struct ll_queue* recv_q; // очередь на сборку фрагментированных пакетов(rx_pool -> struct ETCP_FRAGMENT) + index [+0 SEQ]
|
||||
|
||||
@@ -163,6 +162,7 @@ struct ETCP_CONN {
|
||||
|
||||
// IDs and state
|
||||
uint32_t next_tx_id; // ID для добавления в очередь отправки (с этим id будет добавлен следующий пакет)
|
||||
uint64_t next_attempt_id; // Не переиспользуется при reset/пересоздании линков; исчерпание закрывает соединение
|
||||
uint32_t last_rx_id; // Last received ID
|
||||
uint32_t last_delivered_id; // Last delivered to output_queue
|
||||
|
||||
@@ -190,8 +190,10 @@ struct ETCP_CONN {
|
||||
uint32_t optimal_inflight; // Sum over links
|
||||
|
||||
// Timers
|
||||
void* retrans_timer; // Общий RTO: 2*(rtt_avg_10+jitter), ограничен 10мс..1с; callback проверяет FIFO
|
||||
void* ack_resp_timer; // ACK send timer
|
||||
void* ack_window_timer; // запрос потерянного till, только при заполненном приёмном окне
|
||||
uint8_t ack_till_pending; // нужно передать текущую логическую границу по рабочему пути
|
||||
uint8_t ack_request_pending; // нужно запросить границу у пира
|
||||
void* down_timer; // удаление после непрерывного DOWN, включая первоначальное ожидание
|
||||
uint64_t down_deadline_tb; // сохраняется при наличии NCD handles после истечения таймера
|
||||
|
||||
@@ -330,7 +332,7 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp);
|
||||
void etcp_conn_wake_sender(struct ETCP_CONN* conn);
|
||||
|
||||
// Process ACK receipt - remove acknowledged packet from inflight queues
|
||||
void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t dts);
|
||||
void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq);
|
||||
|
||||
// Recalculate optimal_inflight and resume input queue after link inflight_lim change
|
||||
void etcp_conn_on_inflight_lim_changed(struct ETCP_CONN* etcp);
|
||||
|
||||
@@ -37,7 +37,9 @@ extern "C" {
|
||||
// Wire-MTU кап: пакет на проводе не должен превышать 1500 (согласовано с TUN_MAX_PACKET_SIZE).
|
||||
// PACKET_DATA_SIZE (2048) — это внутренний буфер аллокации/приёма, а не wire-MTU.
|
||||
#define PACKET_DATA_MAX_MTU 1500
|
||||
#define ETCP_MAX_PAYLOAD_SIZE (PACKET_DATA_SIZE - ETCP_ACK_BASE_SIZE - 5) /* 2035 */
|
||||
#define ETCP_PAYLOAD_HEADER_SIZE 13 // type + seq:u32 + attempt_id:u64
|
||||
#define ETCP_ACK_ENTRY_SIZE 16 // seq:u32 + attempt_id:u64 + receiver_delay_us:u32
|
||||
#define ETCP_MAX_PAYLOAD_SIZE (PACKET_DATA_SIZE - ETCP_ACK_BASE_SIZE - ETCP_PAYLOAD_HEADER_SIZE)
|
||||
#define ETCP_RFC791_MIN_MTU 576
|
||||
|
||||
// Типы кодограмм протокола
|
||||
@@ -68,6 +70,8 @@ struct ETCP_DGRAM {// пакет (незашифрованный)
|
||||
uint16_t data_len;// общий размер пакета не включая timestamp
|
||||
uint16_t noencrypt_len;// число байт (с конца) которые не надо шифровать. для передачи pubkey
|
||||
uint16_t payload_len; // локальные метаданные request_pkt: DATA-байты; 0 — только ACK/control/FILLER, вне DATA-pacing
|
||||
struct ETCP_TX_ATTEMPT* attempt; // локальный резерв окна; complete снимает/фиксирует его после send
|
||||
uint8_t burst_packet; // Пакет создан измерительной серией; не зависит от последующей смены burst_active
|
||||
uint16_t timestamp;// timestamp отправляющего узла при отправке пакета
|
||||
uint8_t flag_up:1;// bit0 = up/down (recv_keepalive)
|
||||
uint8_t data[];// данные пакета (без timestamp)
|
||||
@@ -245,8 +249,13 @@ struct ETCP_LINK {
|
||||
uint64_t shaper_sub_nanotime; // sub 0-999999 для 0.1 нс - 0.1 мс
|
||||
uint8_t shaper_state;
|
||||
void* shaper_timer;
|
||||
struct ll_queue* attempts; // Физические попытки, индекс attempt_id:u64; ll.len учитывается в окне
|
||||
struct ll_queue* ack_q; // ACK только DATA этого линка, индекс attempt_id:u64
|
||||
void* retrans_timer; // Срок старейшей принятой транспортом попытки этого канала
|
||||
uint32_t data_rtt_us; // Сглаженный RTT DATA->ACK этого пути; 0 до первого измерения
|
||||
uint32_t data_jitter_us; // Сглаженное абсолютное отклонение собственного DATA RTT
|
||||
|
||||
uint32_t inflight_bytes; // байты WAIT_ACK с last_link == этому линку; WAIT_SEND окно не занимает
|
||||
uint32_t inflight_bytes; // DATA-байты физических попыток этого линка, включая синхронный резерв send
|
||||
uint32_t inflight_packets; // число таких пакетов
|
||||
uint32_t inflight_lim_bytes; // индивидуальный лимит DATA в байтах, включая целиком следующий фрагмент
|
||||
uint8_t cwnd_limited; // DATA не поместился в окно; сохраняется до передачи этого факта BBR по ACK
|
||||
@@ -326,8 +335,8 @@ struct ETCP_LINK {
|
||||
// === BBR congestion control ===
|
||||
struct bbr* bbr; // BBR state (per-link, создаётся в etcp_link_new)
|
||||
uint64_t delivered_bytes; // кумулятивно delivered bytes на линке (для round detection)
|
||||
uint64_t last_ack_time_tb; // время последней доставки/начала первого flight, 0.1мс
|
||||
uint64_t first_tx_time_tb; // начало интервала отправок, продвигается подтверждёнными попытками
|
||||
uint64_t last_ack_time_us; // время последней доставки/начала первого flight в микросекундах
|
||||
uint64_t first_tx_time_us; // начало интервала отправок, продвигается подтверждёнными попытками
|
||||
uint32_t bbr_pacing_rate; // Точный pacing B/s; менять через set_pacing_rate для пересчёта долга/таймера
|
||||
uint32_t bbr_loss_since_ack; // счётчик потерь на линке с последнего ACK (для rs->lost)
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/* etcp_tx — учёт физических попыток DATA и ACK одного канала.
|
||||
* Логический seq/очереди доставки принадлежат ETCP_CONN, попытка — ETCP_LINK.
|
||||
* prepare резервирует окно; complete фиксирует принятую транспортом отправку либо откатывает резерв.
|
||||
* ACK возвращается своим путём, обновляет только его модель и отдельно подтверждает логический seq.
|
||||
* Все вызовы выполняются в uasync-потоке; DATA/ACK этого формата требуют согласованной сессии. */
|
||||
#ifndef ETCP_TX_H
|
||||
#define ETCP_TX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../lib/ll_queue.h"
|
||||
|
||||
struct ETCP_CONN;
|
||||
struct ETCP_LINK;
|
||||
struct ETCP_DGRAM;
|
||||
struct INFLIGHT_PACKET;
|
||||
|
||||
/* Запись из attempt_pool соединения; индекс очереди линка — attempt_id, payload здесь не хранится. */
|
||||
struct ETCP_TX_ATTEMPT {
|
||||
struct ll_entry ll; // len — DATA-байты, dgram=NULL; одна очередь, владелец — линк
|
||||
uint64_t attempt_id; // уникален в пределах жизни соединения, 0 не используется
|
||||
uint32_t seq; // логический фрагмент; может быть уже освобождён после доставки
|
||||
uint64_t sent_at_us; // время принятия транспортом; 0 — пока зарезервирован
|
||||
uint64_t delivered_at_send; // доставленные DATA-байты этого канала на момент отправки
|
||||
uint64_t delivered_time_us; // начало ACK-интервала оценки скорости
|
||||
uint64_t first_tx_us; // начало интервала отправки
|
||||
uint32_t inflight_at_send; // окно после включения этой попытки
|
||||
uint8_t is_app_limited; // источник не имел ожидающих данных либо идёт PROBE_RTT
|
||||
};
|
||||
|
||||
/* Инициализировать очереди attempts/ACK линка. 0 — успех, -1 — OOM (с логом); при ошибке очереди очищены. */
|
||||
int etcp_tx_link_init(struct ETCP_LINK* link);
|
||||
/* Снять попытки/таймер/ACK линка перед reset или free. retry=1 возвращает недоставленные DATA на отправку.
|
||||
* reset не меняет физический UP; destroy дополнительно освобождает очереди. */
|
||||
void etcp_tx_link_reset(struct ETCP_LINK* link, int retry);
|
||||
void etcp_tx_link_destroy(struct ETCP_LINK* link);
|
||||
/* Расчётный RTO в микросекундах: 2*(собственный RTT+jitter), 10мс..1с; до DATA ACK использует KA RTT/1с. */
|
||||
uint32_t etcp_tx_rto_us(const struct ETCP_LINK* link);
|
||||
/* Резервировать окно для packet; NULL — ошибка с логом, packet остаётся в очереди отправки. */
|
||||
struct ETCP_TX_ATTEMPT* etcp_tx_prepare(struct ETCP_LINK* link, struct INFLIGHT_PACKET* packet);
|
||||
/* Завершить синхронный send: success=1 принят транспортом, 0 — снять резерв без сетевой потери.
|
||||
* Вызвать ровно один раз до освобождения dgram и до следующего poll; dgram->attempt обнуляется. */
|
||||
void etcp_tx_complete(struct ETCP_DGRAM* dgram, int success);
|
||||
/* Принятый ACK: seq подтверждает логическую доставку; attempt_id обновляет окно/BBR только своего линка.
|
||||
* Неизвестный старый ID не создаёт измерение и не вычитает окно. UINT32_MAX delay — RTT недостоверен. */
|
||||
void etcp_tx_ack(struct ETCP_LINK* link, uint32_t seq, uint64_t attempt_id, uint32_t receiver_delay_us);
|
||||
/* Поставить ACK уже сохранённого/доставленного DATA в очередь этого линка; 0/-1, ошибка логируется. */
|
||||
int etcp_tx_queue_ack(struct ETCP_LINK* link, uint32_t seq, uint64_t attempt_id);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user