96 lines
6.5 KiB
C
96 lines
6.5 KiB
C
/* multicast — адресная рассылка по маршрутам topo-группы, с разделением по next hop.
|
||
* send копирует данные; descriptor задаёт приложение источника, это не номер пакета.
|
||
* Одна FIFO на ETCP-соединение обслуживает все группы/источники/дескрипторы.
|
||
* При переполнении теряется новая ветка; источник получает OVERLOAD через router.
|
||
* Все вызовы и callbacks — uasync-поток. В callbacks допустима отправка, но нельзя
|
||
* уничтожать ядро/группу/модуль. Данные callbacks заимствованы только на время вызова.
|
||
*
|
||
* Wire DATA, все числа little-endian:
|
||
* cmd:1 | group:8 | descriptor:2 | count:2 | source:8 | recipients:8*count |
|
||
* payload | visited:8*hops | hops:1.
|
||
* Получатели строго возрастают. Источник начинает visited собой, каждый транзит
|
||
* добавляет себя ровно один раз. Первый visited=source, последний=ETCP peer.
|
||
* Полный резерв visited учитывается до отправки, payload на транзите не меняется.
|
||
*
|
||
* Wire OVERLOAD — payload отдельного router-сервиса:
|
||
* descriptor:2 | src:8 | dst:8 | packets:4 | count:2 | prefix_len:1 |
|
||
* prefix:16 | recipients:8*count.
|
||
* src/dst — концы перегруженного участка; router dst — источник DATA.
|
||
* packets относится к КАЖДОМУ указанному получателю. Части длинного отчёта имеют
|
||
* непересекающиеся списки: складывать их packets как число исходных пакетов нельзя.
|
||
* Отчёт сохраняет префикс первого пакета; разные наборы получателей не смешиваются.
|
||
*/
|
||
#ifndef UTUN_MULTICAST_H
|
||
#define UTUN_MULTICAST_H
|
||
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
struct UTUN_INSTANCE;
|
||
struct TOPO_GROUP;
|
||
struct multicast_ctx;
|
||
|
||
#define MULTICAST_QUEUE_BYTES (256u * 1024u)
|
||
#define MULTICAST_REPORT_BYTES (16u * 1024u)
|
||
#define MULTICAST_REPORT_INTERVAL_TB 3000
|
||
#define MULTICAST_MAX_VISITED 64
|
||
#define MULTICAST_HEADER_SIZE 21
|
||
#define MULTICAST_PATH_RESERVE (8 * MULTICAST_MAX_VISITED + 1)
|
||
#define MULTICAST_REPORT_HEADER_SIZE 41
|
||
|
||
enum multicast_loss_reason {
|
||
MULTICAST_OVERLOAD = 1, /* очередь выбранного исходящего соединения заполнена */
|
||
MULTICAST_NO_ROUTE, /* только локальное уведомление источнику */
|
||
MULTICAST_PATH_LOOP, /* локальное уведомление; транзит логирует потерю */
|
||
MULTICAST_INTERNAL_ERROR /* выделение памяти / отказ транспорта */
|
||
};
|
||
|
||
struct multicast_loss {
|
||
uint64_t group_id; /* группа исходной рассылки */
|
||
uint64_t source_node_id; /* источник исходного DATA */
|
||
uint64_t src, dst; /* узел потери и выбранный next hop; dst=0 без маршрута */
|
||
uint16_t descriptor; /* идентификатор приложения источника */
|
||
uint16_t recipient_count; /* число ID в recipients */
|
||
const uint64_t* recipients; /* заимствованный массив в host byte order */
|
||
uint32_t packets; /* потери для каждого получателя этого списка */
|
||
enum multicast_loss_reason reason;
|
||
uint8_t prefix_len; /* 0..16 значимых байт */
|
||
uint8_t prefix[16]; /* начало payload первого потерянного пакета */
|
||
};
|
||
|
||
typedef void (*multicast_recv_fn)(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t source,
|
||
uint16_t descriptor, const uint8_t* payload, size_t len, void* arg);
|
||
typedef void (*multicast_loss_fn)(struct UTUN_INSTANCE* inst, const struct multicast_loss* loss, void* arg);
|
||
|
||
struct multicast_stats {
|
||
uint64_t sent, delivered, overload_packets, no_route_packets, loop_packets, invalid_packets, internal_errors;
|
||
uint64_t reports_sent, reports_received, reports_evicted; /* отправленные части / принятые / вытесненные записи */
|
||
size_t queued_bytes, report_bytes; /* данные в FIFO / память отчётов и окон, без уже переданного транспорту */
|
||
unsigned queues; /* лениво созданные FIFO, в том числе временно опустевшие */
|
||
};
|
||
|
||
/* Инициализация после etcp_router_init; destroy до router/ETCP. 0/-1; повторный init — ошибка. */
|
||
int multicast_init(struct UTUN_INSTANCE* inst);
|
||
void multicast_destroy(struct UTUN_INSTANCE* inst);
|
||
/* Один приёмник и обработчик потерь на ядро; NULL отключает соответствующий callback. */
|
||
void multicast_set_callbacks(struct UTUN_INSTANCE* inst, multicast_recv_fn recv, multicast_loss_fn loss, void* arg);
|
||
/* count>0, ID ненулевые; повторы удаляются. len может быть 0. 0=принято к обработке,
|
||
* -1=неверный аргумент/размер или отказ начального выделения. Частичные потери — через loss.
|
||
* Доставка best effort: повторов/сквозных ACK нет; порядок при смене маршрутов не гарантируется. */
|
||
int multicast_send(struct TOPO_GROUP* group, uint16_t descriptor, const uint64_t* recipients,
|
||
uint16_t count, const void* payload, size_t len);
|
||
/* Снимок диагностики; 0/-1, не создаёт состояния. */
|
||
int multicast_get_stats(struct UTUN_INSTANCE* inst, struct multicast_stats* out);
|
||
/* Внутренние hooks топологии: отложенный пересмотр маршрутов / отмена данных удаляемой группы. */
|
||
void multicast_routes_changed(struct UTUN_INSTANCE* inst);
|
||
void multicast_close_group(struct UTUN_INSTANCE* inst, uint64_t group_id);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif
|