Clarify address profiles and route statistics contracts

This commit is contained in:
evgeny committed 2026-10-24 12:18:30 +02:00
1 parent 30a69712fc
commit 0445c38c31
3 files changed
+24 -10

No files matched your search

+5 -2
View File
@@ -22,11 +22,12 @@ enum address_inbound {
enum address_profile_source { ADDRESS_SOURCE_NONE, ADDRESS_SOURCE_ETCP, ADDRESS_SOURCE_STUN };
struct address_profile {
uint8_t mapping;
uint8_t inbound;
uint8_t mapping; /* enum address_mapping: UNKNOWN, без трансляции, EIM или зависимый mapping. */
uint8_t inbound; /* enum address_inbound: UNKNOWN, OPEN либо нужен исходящий контакт. */
uint8_t source; /* ETCP — измерение рабочего endpoint; STUN — предварительный EIM? с неизвестным входом. */
};
/* Постоянные строки для диагностики; неизвестное значение возвращает INVALID. */
static inline const char *address_mapping_name(uint8_t value) {
static const char *const names[] = {"UNKNOWN", "UNCHANGED", "EIM", "DEPENDENT"};
return value <= ADDRESS_MAP_DEPENDENT ? names[value] : "INVALID";
@@ -42,6 +43,8 @@ static inline const char *address_profile_source_name(uint8_t value) {
return value <= ADDRESS_SOURCE_STUN ? names[value] : "INVALID";
}
/* 1 — поля входят в enum и при source=NONE оба свойства UNKNOWN; 0 — иначе/NULL.
* Проверяет представление, а не достоверность измерения или сочетания свойств. */
static inline int address_profile_valid(const struct address_profile *profile) {
return profile && profile->mapping <= ADDRESS_MAP_DEPENDENT && profile->inbound <= ADDRESS_IN_CONTACT &&
profile->source <= ADDRESS_SOURCE_STUN &&
+9 -3
View File
@@ -1,6 +1,7 @@
/* Учёт первой доставки payload логического канала. Один uasync-поток.
* Десять завершённых интервалов по 50мс и текущий интервал; reset начинает новую историю.
* Повторы учитывает вызывающий: add вызывается только при снятии подтверждённого inflight. */
* Повторы учитывает вызывающий: ack вызывается только при снятии подтверждённого inflight.
* Время — монотонные микросекунды; память всех структур принадлежит вызывающему. */
#ifndef ROUTE_TX_STATS_H
#define ROUTE_TX_STATS_H
@@ -14,16 +15,21 @@ extern "C" {
#define ROUTE_TX_WINDOW_US 500000u
#define ROUTE_TX_BUCKETS 11
/* tick_plus_one=0 означает пустую ячейку; иначе это номер 50-мс интервала + 1. */
struct route_tx_bucket { uint64_t tick_plus_one, bytes, packets; };
struct route_tx_meter {
struct route_tx_bucket buckets[ROUTE_TX_BUCKETS];
uint64_t started_us, last_us, bytes, packets;
uint64_t started_us, last_us, bytes, packets; /* reset/последний ACK и накопленные итоги эпохи */
};
/* end_us — правая граница окна; valid=1 после накопления полных 500 мс с момента reset. */
struct route_tx_window { uint64_t end_us, bytes, packets; int valid; };
/* Обнулить историю и начать эпоху в now_us; meter обязателен. */
void route_tx_meter_reset(struct route_tx_meter *meter, uint64_t now_us);
/* Учесть один впервые подтверждённый payload (bytes>0); 0/-1, при ошибке история не меняется. */
int route_tx_meter_ack(struct route_tx_meter *meter, uint64_t now_us, uint64_t bytes);
/* Неполное окно после reset возвращает valid=0; текущая незавершённая ячейка исключается. */
/* Заполнить out суммой завершённых ячеек; 0/-1 (при ошибке out не меняется).
* Неполное окно после reset возвращает valid=0; текущая незавершённая ячейка исключается. */
int route_tx_meter_window(const struct route_tx_meter *meter, uint64_t now_us, struct route_tx_window *out);
#ifdef __cplusplus
+10 -5
View File
@@ -21,17 +21,22 @@ struct ETCP_SOCKET;
#define SOCK_TC_PROBE 4
struct sock_view {
struct ETCP_SOCKET *sock;
uint8_t role, has_inet, has_priv, family, is_tcp;
uint32_t local_ip4, public_ip4;
struct address_profile address_profile;
struct ETCP_SOCKET *sock; /* заимствован; не переживает удаление сокета */
uint8_t role, has_inet, has_priv, family, is_tcp; /* SOCK_ROLE_*, доступ к Internet/LAN, AF_INET, TCP-флаг */
uint32_t local_ip4, public_ip4; /* network order; public_ip4=0, если публичный адрес неизвестен */
struct address_profile address_profile; /* копия текущего профиля */
};
/* public_address — классификация IP в соответствующем семействе, не доказательство входа. */
/* Возвращает SOCK_TC_*; address_type=TOPO_ADDR_*, config_type=CFG_SERVER_TYPE_*.
* public_address — классификация IP в соответствующем семействе, не доказательство входа. */
uint8_t sock_target_class(uint8_t address_type, uint8_t config_type, const struct address_profile *profile,
int public_address);
/* 1 — разрешена попытка по target_ip4 (network order), 0 — нет; проверяет has_priv/has_inet.
* Семейство/протокол и выбор маршрута проверяет вызывающий; profile может быть NULL. */
int sock_match(const struct sock_view *view, uint8_t address_type, uint8_t config_type,
const struct address_profile *profile, uint32_t target_ip4);
/* В потоке ядра заполнить до max views обычных IPv4-сокетов, включая TCP; probe_only исключены.
* Возвращает число заполненных (0 также при неверных аргументах); специальной сортировки нет. */
int sock_collect_views(struct UTUN_INSTANCE *instance, struct sock_view *out, int max);
#endif