Record BLE throughput results and harden the hardware probe

This commit is contained in:
evgeny committed 2026-10-29 18:38:11 +01:00
1 parent 3def3f5af2
commit 33b4f0acc8
3 files changed
+85 -8

No files matched your search

+34
View File
@@ -99,6 +99,11 @@ Instrumentation восстанавливает Bluetooth-политику в fin
THROUGHPUT считает verified_bytes_each_direction и aggregate_bytes_per_second
за время от первого send до последнего проверенного echo, без GATT/ETCP handshake.
Это двунаправленный echo goodput, не скорость PHY. Неполный прогон имеет ненулевой exit.
При неполном прогоне THROUGHPUT complete=0 учитывает всё окно до остановки,
включая простой после последнего echo; RESULT failed=1 и ERROR содержат target/sent/verified.
До первого send разрыв/смена адреса возвращает пробу к discovery; разрыв во время
передачи завершает её с ошибкой. UTUN_TEST_DEBUG=1 включает ETCP trace/connection debug
на desktop для подробного разбора ACK/RTO без изменения штатных фильтров приложения.
Перед пробой выключить BLE обычного desktop GUI: два сервиса с одинаковыми UUID
на одном адаптере делают GATT discovery неоднозначным.
@@ -165,3 +170,32 @@ LAN-приглашения или исходящую отправку. Ново
Это не полный нагрузочный проход обратной роли.
- Windows backend проверен кросс-компиляцией MinGW/C++WinRT, без физического Win BT.
- Общие тесты: 230/230; отдельные BLE/BlueZ/UI и ASAN/UBSAN пройдены.
Write Without Response / Notification: проверка 2026-10-29
--------------------------------------------------------
Android, BlueZ и WinRT используют быстрый DATA, INVITE сохраняет Request/Indication.
Android HIGH/MTU517/2M сохранены; WinRT запрашивает ThroughputOptimized при наличии
API Windows 11. BlueZ D-Bus не предоставляет аналогичного per-link профиля.
Desktop GUI/Linux, Android APK+instrumentation (arm64/x86_64), WinRT cross-build PASS.
./check.sh: 230/230 + proxy/burst/load; BLE common/BlueZ/identity/ETCP/UI: 5/5;
BLE ASAN/UBSAN: 3/3; Android app/router unit tests: 770/770.
Телефон RZ8R72MG64B, один desktop BLE-сервис на адаптере:
- Android central: 512/512 ETCP echo по 1500 байт, window=16, по 768000 байт
в каждом направлении за 61.694 с; суммарный goodput 24897 B/s (12448 B/s
на направление). Приглашения 939 байт и ACK приложений прошли в обе стороны.
PHY2M TX/RX, MTU517; для Android central подтверждён interval=12 (15 ms).
- Сырой BLE, Android central: 96/96 echo, по 45636 байт за 4.473 с,
суммарно 20407 B/s. Размеры пакетов различаются, напрямую с ETCP не сравнивать.
- Desktop central: приглашения/ACK прошли, но за окно 85 с ETCP подтвердил
только 20/512 echo. Повтор без приглашений, window=1: 0/32 echo за окно 65 с,
после первого send 50.060 с повторялись INIT/INIT_RESPONSE и DATA RTO,
DATA_RTT_us=0; BLE-сборщик не регистрировал отбросов. Причина не установлена;
исправление этого сбоя не входит в подтверждённый результат профиля скорости.
Журналы текущего сеанса: /tmp/ble-speed-android-central-{desktop,logcat}.log,
/tmp/ble-speed-desktop-central-{desktop,logcat}.log,
/tmp/ble-speed-desktop-central-serial-retry-desktop.log и
/tmp/ble-speed-desktop-central-serial-live-logcat.log.
После аппаратных проб обычный desktop VibeChat перезапущен новой сборкой;
Android instrumentation восстановила обычную Bluetooth-политику в finally.
+15
View File
@@ -4,6 +4,21 @@
## Текущие задачи
[ ] **BLE/ETCP: повторные INIT и отсутствие DATA ACK при desktop central** — 29.10.2026.
После включения Write Without Response/Notification GATT/MTU517 и PHY2M работают,
но desktop central подтвердил 20/512 echo за 85 с; повтор window=1 — 0/32 за 65 с.
На desktop повторяются INIT/INIT_RESPONSE и DATA RTO с DATA_RTT_us=0;
BLE-сборщик не регистрирует потерь фрагментов. Точная причина не установлена.
Android central: 512/512 echo и приглашения в обе стороны, суммарный goodput 24897 B/s.
Результаты, параметры проб и пути диагностических журналов: [ble_etcp.txt](ble_etcp.txt).
[+] **BLE: DATA без ATT ACK и профиль скорости desktop/Android** — 29.10.2026.
Write Without Response/Notification для DATA в Android/BlueZ/WinRT; INVITE сохраняет Request/Indication.
Android HIGH/MTU517/2M, Windows ThroughputOptimized с проверкой API и фактическими параметрами.
Сводка скорости/очередей/ожиданий GATT; нагрузочная проба с ограниченным окном и проверкой содержимого.
Общие тесты 230/230 + proxy/burst/load, BLE 5/5, ASAN/UBSAN 3/3, Android unit 770/770.
Desktop и APK собираются; WinRT cross-build PASS. Ограничение обратной роли вынесено выше.
[ ] **Windows: единые UTF-8 пути конфигурации** — 29.10.2026.
GUI передаёт toUtf8, а config_parser/config_updater используют fopen и ANSI Win32 API.
Перевести эти операции на существующий file_io с wide-путями, проверить профиль в каталоге с кириллицей.
+36 -8
View File
@@ -18,7 +18,7 @@ static unsigned verified;
static uint64_t transfer_started, transfer_finished;
static int invitations, invitation_sent, invitation_received, invitation_delivered;
static char invitation_link[LOCAL_TRANSPORT_DATA_MAX + 1];
static int failed, radio_ready;
static int failed, radio_ready, connection_closed;
static struct ble_etcp* driver;
static struct UTUN_INSTANCE* instance;
static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) {
@@ -37,8 +37,15 @@ static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int
}
static void receive(struct ETCP_CONN* conn, struct ll_entry* e) {
(void)conn;
if (e->len != 1500) failed = 1;
for (unsigned i = 1; i < e->len; i++) if (e->dgram[i] != (uint8_t)(verified + i * 37)) failed = 1;
if (e->len != 1500) {
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE probe size mismatch packet=%u expected=1500 actual=%u", verified, e->len);
failed = 1;
}
for (unsigned i = 1; i < e->len; i++) if (e->dgram[i] != (uint8_t)(verified + i * 37)) {
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE probe byte mismatch packet=%u offset=%u expected=%u actual=%u",
verified, i, (uint8_t)(verified + i * 37), e->dgram[i]);
failed = 1; break;
}
DEBUG_TRACE(DEBUG_CATEGORY_DISCOVERY, "VERIFY ETCP packet=%u bytes=%u ok=%d", verified, e->len, !failed);
verified++; transfer_finished = get_time_us();
queue_dgram_free(e); queue_entry_free(e);
@@ -51,6 +58,10 @@ static void status(void* arg, enum ble_state s, const char* reason) {
if (ble_advertise(ble_etcp_radio(driver), bytes, n)) failed = 1;
}
}
static void connection(void* arg, ble_link_id id, uint64_t peer, enum ble_state state, const char* reason) {
(void)arg; (void)id; (void)peer; (void)reason;
if (state == BLE_CLOSED) connection_closed = 1;
}
int main(int argc, char** argv) {
int seconds = argc > 1 ? atoi(argv[1]) : 60;
unsigned packets = argc > 4 ? (unsigned)atoi(argv[4]) : 32;
@@ -64,6 +75,10 @@ int main(int argc, char** argv) {
snprintf(config, sizeof(config), "[global]\nmy_private_key=%s\nmy_public_key=%s\nauto_sockets=no\n[ntp]\nenabled=no\n", priv, pub);
instance = utun_instance_create_from_str(ua, config);
if (!instance) { uasync_destroy(ua, 0); return 1; }
if (getenv("UTUN_TEST_DEBUG")) {
debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_TRACE);
debug_set_category_level(DEBUG_CATEGORY_CONNECTION, DEBUG_LEVEL_DEBUG);
}
invitations = argc > 3 && !strcmp(argv[3], "invites");
if (invitations) {
struct InviteData invite = {.channelId = 0x424c4554455354ULL, .join_key = 123, .addrCount = 24};
@@ -75,7 +90,8 @@ int main(int argc, char** argv) {
if (invite_link_encode(&invite, NULL, invitation_link, sizeof(invitation_link)) < 0) failed = 1;
chat_event_set_handler(instance, event); chat_setting_set(instance, "bluetooth_invites_enabled", "1");
}
struct ble_config c = {.node_id = instance->node_id, .company_id = 0xffff}; c.callbacks.status = status;
struct ble_config c = {.node_id = instance->node_id, .company_id = 0xffff};
c.callbacks.status = status; c.callbacks.connection = connection;
driver = ble_etcp_create(ua, instance, &c);
if (!driver || etcp_bind(instance, ETCP_ID_BLE_PROBE, receive) || ble_start(ble_etcp_radio(driver))) failed = 1;
uint64_t end = get_time_us() + (uint64_t)seconds * 1000000, peer = 0, retry = 0;
@@ -84,6 +100,12 @@ int main(int argc, char** argv) {
while (!failed && (verified < packets || (invitations && (!invitation_received || !invitation_delivered))) && get_time_us() < end) {
uasync_poll(ua, 100);
if (failed) break;
if (connection_closed) {
connection_closed = 0;
if (transfer_started) { DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE probe connection lost during transfer"); failed = 1; break; }
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE probe connection closed before transfer; retrying discovery");
peer = 0; retry = get_time_us() + 1000000;
}
if (!peer && dial && radio_ready && get_time_us() >= retry) {
struct ble_neighbor neighbors[BLE_NEIGHBORS_MAX]; size_t n = ble_etcp_neighbors(driver, neighbors, BLE_NEIGHBORS_MAX);
for (size_t i = 0; i < n; i++) if (!strcmp(neighbors[i].identity.name, "ETCP-probe")) {
@@ -110,12 +132,18 @@ int main(int argc, char** argv) {
if (etcp_send(conn, e)) { queue_dgram_free(e); queue_entry_free(e); failed = 1; }
else { if (!transfer_started) transfer_started = get_time_us(); sent++; }
}
uint64_t measured_end = verified == packets ? transfer_finished : get_time_us();
if (verified != packets || (invitations && (!invitation_delivered || invitation_received != 1))) {
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE probe incomplete target=%u sent=%u verified=%u invite_delivered=%d invite_received=%d",
packets, sent, verified, invitation_delivered, invitation_received);
failed = 1;
}
ble_etcp_destroy(driver); utun_instance_destroy(instance); uasync_destroy(ua, 0);
printf("RESULT BLE ETCP sent=%u verified=%u bytes=%u failed=%d\n", sent, verified, verified * 1500, failed);
if (transfer_started && transfer_finished > transfer_started) {
double elapsed = (transfer_finished - transfer_started) / 1000000.0;
printf("THROUGHPUT window=%u verified_bytes_each_direction=%u seconds=%.3f aggregate_bytes_per_second=%.0f\n",
window, verified * 1500, elapsed, verified * 3000.0 / elapsed);
if (transfer_started && measured_end > transfer_started) {
double elapsed = (measured_end - transfer_started) / 1000000.0;
printf("THROUGHPUT complete=%d window=%u verified_bytes_each_direction=%u seconds=%.3f aggregate_bytes_per_second=%.0f\n",
!failed, window, verified * 1500, elapsed, verified * 3000.0 / elapsed);
}
if (invitations) printf("RESULT BLE invitations sent=%d delivered=%d received=%d\n", invitation_sent, invitation_delivered, invitation_received);
return failed || verified != packets || (invitations && (!invitation_delivered || invitation_received != 1));