Files
utun2/doc/ble_etcp.txt
T

421 lines
41 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
BLE GATT → ETCP (chatgui desktop + Android)
Текущее состояние диагностики задержек (29.10.2026):
Write Without Response/Notify, HIGH и PHY2M включены. Исправлены готовность
BlueZ по ServicesResolved, использование старого ManufacturerData, входящий
HIGH Android и потолок DATA RTO=1s. Версия объявления повышена до 2, чтобы
не подключаться к старому DATA Write/Indicate сервису. Полная нагрузка обеих
аппаратных ролей пока не подтверждена: остаётся очередь между локальным
completion и HCI TX. Успех короткой пробы не означает устранения этой очереди.
Общий код: tools/cgathui_common/ble_etcp.c/h.
Платформенные backend остаются в lib/ble и android_ble.c; Qt не участвует в протоколе.
UTUN binary этот модуль не собирает. При активном UTUN-сервисе общего instance
BLE-драйвер не передаёт ETCP: CHAT и UTUN используют общий conn/normalizer,
поэтому разделить их уже упакованные пакеты внутри линка нельзя.
Обнаружение и объявления при этом остаются доступны.
Владелец в потоке uasync:
ble_etcp_create(ua, instance, &config)
ble_start(ble_etcp_radio(driver))
ble_advertise / ble_set_incoming — через заимствованный radio
ble_etcp_neighbors(driver, output, capacity) — копия свежих соседей
ble_etcp_connect(driver, node_id) — явное подключение к обнаруженному соседу
ble_etcp_destroy(driver) — обязательно до instance/uasync, вне callbacks
instance=NULL оставляет сырой BLE и discovery для аппаратных проб; штатные
frontend передают instance. config.callbacks — наблюдатели; received/writable
штатного ETCP принадлежат драйверу. Сырые TX/RX нельзя читать параллельно ETCP.
Таблица в управляющей структуре драйвера, не в instance и не в UI:
64 записи {node_id, UTF-8 name, endpoint, RSSI, seen_us}; срок свежести 30 секунд.
Объявление обновляет адрес и RSSI. По истечении срока запись удаляется.
Desktop формирует видимый список из snapshot общего драйвера. Android получает
тот же C API через android_ble_driver(). node_id/name в эфире не аутентифицированы.
Автоматическое подключение проверяется раз в секунду и при появлении соседа:
- только работающий CHAT-сервис, полная разрешённая запись мембера source=0/deleted=0;
- нет живого BGP-пути в конкретной группе, включая маршрут через посредника;
- группа получает TOPO_PEER_REQUEST и владеет NCD уже в CONNECTING;
- GATT прикрепляется к тому же ETCP_CONN, которым владеет NCD;
- один GATT к обнаруженному node_id разделяется запросами нескольких групп;
- запрос снимается на READY, удалении группы/членства либо через 20 секунд;
готовую сессию продолжает держать сама группа;
- повтор GATT ограничен интервалом 5..6 секунд; появление объявления само по себе
не создаёт подключения к постороннему узлу.
Каждый GATT-канал предоставляет packet_link_driver: ctx/ua/name, bind/get_state,
send/set_rx_enabled/stop/destroy. Контракт — doc/packet_link.txt.
max_packet=1500 — размер непрозрачного пакета BLE, включая заголовки ETCP.
Более длинное пользовательское сообщение дробит нормализатор ETCP; получившиеся
пакеты BLE транспорт дополнительно фрагментирует под фактический ATT MTU.
TX limit=1 включает пакет в процессе фрагментации. У адаптера нет второй TX-очереди:
send сразу передаёт ll_entry в ble_tx_put. Готовность читается через ble_tx_ready;
после завершения целого пакета writable будит ETCP. При отказе владение не меняется.
RX использует ll_queue общего транспорта и включается packet_link потребителем.
DATA передаётся через Write Without Response (client → server) и Notification
(server → client). BLE send завершает только локальную отправку; доставку и повторы
обеспечивает ETCP. INVITE остаётся отдельным Write Request/Indication каналом.
После BLE HELLO/ACCEPT первым целым кадром каждой стороны идёт 40 байт:
'V' 'C' 'E' 'T' 01 00 00 00 | 32 байта X25519 public key
Драйвер сверяет производный node_id с HELLO и ключом уже существующего ETCP_CONN,
затем прикрепляет динамический линк. Это ещё не доказательство владения ключом:
его обеспечивает штатный зашифрованный INIT и handshake эпох ETCP. Следующие
кадры — неизменённые зашифрованные ETCP-пакеты, без IP-заголовков/добавочного framing.
До завершения обмена ключами действует дедлайн 20 секунд.
Диагностика линка в обеих GUI использует общий etcp_link_get_snapshot: подпись BLE,
физическое направление из ble_get_outgoing и фактические link_state/link_status
ETCP. GATT READY сам по себе не включает зелёный индикатор. Адреса IP, порты и имя
сетевого сокета для BLE отсутствуют. До прикрепления к ETCP попытка GATT не входит
в список ETCP-линков; протокольный is_server не подменяется направлением GATT.
BLE callbacks только обновляют состояние/будят отложенную обработку. Закрытие
GATT делается вне этих callbacks; packet_link откладывает destroy. При выключении
frontend закрывает свои ETCP-линки, отсоединяет ctx от manager и уничтожает радио;
поздний destroy ctx не обращается к уже уничтоженному manager. Ключи не логируются.
Категория диагностики discovery; для handshake/маршрутов — etcp, connection, bgp, ncd.
Проверки:
- tools/chatgui/build/test_ble_etcp: настоящий BLE common protocol + fake async GATT,
encrypted ETCP handshake, MTU23, 1500-byte duplex, потеря DATA после успешного
локального send и восстановление ETCP, TX busy/ownership/resume,
несовпадающий public key, teardown, реальные SQLite/NCD/BGP и READY двух групп.
- test_desktop_ble: UI policy и discovery через общий snapshot.
- lib/ble/tests/test_ble_transport.c: MTU23/247/517, пропущенные фрагменты,
bounded queues, независимые соединения и stop.
- Android: ./gradlew assembleDebug assembleDebugAndroidTest.
Ручная аппаратная проверка (один процесс VibeChat/probe на BLE-адаптер):
adb -s SERIAL shell am instrument -w -e etcp true -e seconds 180 \
com.utun.chat.test/com.utun.chat.BlePeerProbe
tools/chatgui/build/ble_etcp_probe 150
Обратное направление: instrumentation -e initiator true, desktop ... 150 listen.
ETCP-probe объявляет тестовое имя; desktop подключается только к нему.
Временно включается ETCP_ID_BLE_PROBE echo, выключенный в обычном приложении.
32 пакета по 1500 байт сверяются побайтно; успех — RESULT ... verified=32 failed=0.
Instrumentation восстанавливает Bluetooth-политику в finally. PHY2M и HIGH priority
запрашивает native backend; фактические параметры/результат запроса смотреть в логах.
Нагрузочная проба: ble_etcp_probe seconds [connect|listen] [data|invites] [packets] [window].
По умолчанию packets=32/window=1. Для заполнения канала: например,
tools/chatgui/build/ble_etcp_probe 90 listen data 4096 16
и Android с -e etcp true -e initiator true -e seconds 100.
Обратная роль: desktop connect и Android без initiator. В полёте не более window
запросов (1..64); каждый из packets (1..1000000) сверяется побайтно.
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 неоднозначным.
Проверено 2026-10-29:
- desktop CMake и Android arm64-v8a/x86_64 APK собираются;
- ./check.sh: 230/230 + proxy/burst/load; выбранные GUI/ETCP/BLE: 6/6;
- test_ble_etcp под ASAN/UBSAN с detect_leaks=1: без ошибок;
- Android (RZ8R72MG64B) инициирует GATT к Linux: 32×1500 байт echo совпали,
PHY2M, MTU517, фактический connection interval=12 (15 ms);
- Linux инициирует GATT к тому же Android: несколько ETCP-пакетов передаются,
затем HCI Connection Timeout (0x08). Сырой ble_peer_probe без ETCP также
воспроизводит HCI 0x08 (подтверждено btmon). Этот сбой нижнего BLE-стека
не устранён данным драйвером; обе аппаратные роли нельзя считать проверенными.
Приглашения через Bluetooth
---------------------------
Общий владелец регистрирует заимствованный chat_local_provider в instance;
сам список соседей остаётся в ble_etcp. chat_local объединяет LAN и BT по node_id.
При отправке выбирается доступный LAN endpoint, иначе BLE; при синхронном отказе
LAN допустим BLE. После принятой отправки транспорт сам выдаёт один конечный
статус: асинхронный таймаут не запускает рассылку по другому транспорту.
Явная отправка приглашения создаёт GATT при необходимости, без проверки членства
или BGP-пути. При активном UTUN приглашения доступны без добавления BLE в ETCP.
Характеристика f61a9023-4abc-45ac-98e1-761df4c13811: Write + Indicate.
Клиент пишет запросы/ответы в неё; сервер адресует indications одному клиенту.
DATA и INVITE имеют отдельные ll_queue и сборщики фрагментов, но одну незавершённую
GATT-операцию на соединение. Планировщик чередует фрагменты, HELLO имеет приоритет.
DATA TX использует tx_limit, INVITE TX допускает один целый пакет; RX ограничены
64 пакетами на канал. Необходимы подписки на обе характеристики.
После сборки INVITE: version(1)=1, kind(1)=1 запрос/2 ответ,
epoch(8 BE), request_id(8 BE), status(1), payload.
Эпоха случайная ненулевая на экземпляр драйвера. Запрос содержит готовую join-ссылку
1..1100 байт (тот же предел, что LAN), status=0. Ответ без payload: status=0 FAILED,
1 RECEIVED, 2 FORBIDDEN. RECEIVED означает доставку в обработчик приложения,
не вступление в группу. ATT completion сам по себе доставку приложению не подтверждает.
Ожидающих отправок до 8, дедлайн 30 с, до 3 попыток с интервалом 8 с.
Разрыв соединения/остановка завершают pending с FAILED. Повторы принятого запроса
подавляются 60 с по peer/epoch/request и SHA256 содержимого (кеш 64 записи).
Заполненный кеш отказывает новым запросам, не вытесняя ещё действующую защиту.
Отправитель не получает гарантии отсутствия доставки при FAILED/потере ACK.
[chatserver] bluetooth_invites_enabled=0 — отдельное разрешение, по умолчанию выключено.
Проверяется при каждом запросе, в том числе на существующем GATT. Не влияет на DATA,
LAN-приглашения или исходящую отправку. Новому входящему GATT также нужно разрешение
«Allow incoming Bluetooth connections». Desktop и Android показывают переключатель
во вкладке Bluetooth. JOIN выполняется только по подтверждению пользователя.
Содержимое приглашения и пароль не выводятся в логи (категория discovery).
Формат join-ссылки не изменён: для последующего JOIN по-прежнему нужны её IP-адреса.
Проверка: test_ble_transport (MTU23/247/517, независимые каналы), test_ble_bluez
(два клиента, адресные fd), test_ble_etcp (приложение/ACK, запрет, повторы,
потеря ACK, совместный ETCP, teardown и GATT по запросу без ETCP).
Физическая проба: ble_etcp_probe 60 listen invites; Android BlePeerProbe
с -e etcp true -e initiator true -e invites true -e seconds 50.
Проба использует синтетическую ссылку, не запускает JOIN и восстанавливает политику.
Проверено 2026-10-29 на Android RZ8R72MG64B и Linux/BlueZ:
- Android инициирует GATT: приглашение 939 байт туда/обратно, ACK обоих приложений;
параллельно проверены все 32 ETCP echo-пакета по 1500 байт.
- Desktop инициирует GATT: те же приглашения и ACK в обе стороны; за окно 45 с
успели завершиться 7/32 ETCP echo-пакетов, затем проба остановлена по лимиту времени.
Это не полный нагрузочный проход обратной роли.
- 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.
Диагностика очередей и аудит ошибок 2026-10-29
---------------------------------------------
Последующие пробы уточнили причину просадки desktop central. Локальный completion
WriteValue(type=command) означает приём фрагмента стеком, а не его передачу по радио.
tx_limit=1 ограничивает только нашу ll_queue; очередь BlueZ/ядра этим не ограничена.
Доказательства по журналам, без сравнения часов разных устройств:
- /tmp/ble-errors-final-hci.btsnoop и /tmp/ble-speed-errors-final-desktop.log:
сопоставлены 882 исходящих целых кадра по seq/размеру/FNV-отпечатку ciphertext.
От локального BLE completion до последнего ACL-фрагмента в HCI проходит
3.548..20.167 с; следовательно, очередь находится перед границей HCI TX.
Для 675 совпавших входящих кадров HCI RX → BLE callback занимает 0.6..32.9 мс,
обычно 1..2 мс. Часовой сдвиг форматов времени исключён по HCI RX/callback.
- ETCP в этой пробе повторяет DATA по RTO=1000000 us, пока исходные кадры
ещё находятся в нижней очереди. Повторные копии увеличивают задержку.
Начальный INIT также повторяется примерно через 50 мс и содержит padding.
- Результат контрольного запуска: 42/128 echo по 1500 байт, window=16,
63000 подтверждённых байт на направление за 65.730 с после первого send,
complete=0; общий лимит запуска 75 с. drops=0 и missing=0 на BLE-сборщике.
- Более ранний cause-load1: desktop локально завершил 233 кадра, Android получил
только первые 40; обратно завершено 262, получены первые 76. У полученных
кадров совпали размеры/отпечатки, внутренних разрывов нет — отсутствуют хвосты.
Дополнительная задержка относительно первого кадра выросла на 15.982/10.012 с.
- Сбой перемежающийся: отдельная проба desktop central window=1 прошла 32/32
за 11.148 с, суммарно 8612 B/s. Это не подтверждает устойчивость под нагрузкой.
В контрольной пробе Android также каждые ~6 с подключался к соседу
4A:2F:B0:6D:A6:35 со старыми свойствами RX=8 (Write), TX=32 (Indicate).
Сервис найден со status=0, но не поддерживает новые DATA-свойства. Причина отказа
теперь явно указывает отсутствующий Write Without Response/Notification.
Влияние этих параллельных подключений на скорость отдельно не измерено.
Локальный completion недостаточен для оценки фактического продвижения кадров.
До изменения wire-протокола необходимо проверять готовность GATT, профиль
соединения и поведение ETCP при RTT больше секунды. Последующее расследование
ниже подтвердило ошибки готовности/профиля и воспроизвело очередь без ETCP.
Произвольная задержка между send и смена на AcquireWrite сами по себе не дают
гарантии ограниченной очереди. Дополнительный credit-протокол пока не вводился.
Аудит диагностики:
- Android: ошибки SDK/callback сохраняют status, роль/адрес/link/channel;
отказы CCC сохраняют код API33, MTU — requested/reported/effective;
неожиданные закрытия/отклонённые чтения/записи имеют WARN, потерянный callback
или таймер Handler — ERROR, timeout server writer содержит его состояние.
- JNI: переполнение mailbox содержит generation/capacity/discarded;
поздние события удалённого link видны на TRACE. Тестовые уровни discovery/debug
восстанавливаются при detach и не остаются включёнными после instrumentation.
- BLE common: разрывы последовательности целых кадров учитываются отдельно
как missing; partial/drop не смешивается с ними. Некорректные фрагменты,
замена неполного кадра, отказ allocation и completion имеют контекст ошибки.
- BlueZ: ошибки recv/reply/socketpair сохраняют errno/текст; D-Bus ошибки
сохраняют имя и сообщение. WinRT: HRESULT и ATT_error/status доступны при
WARN, включая discovery/subscription, без необходимости включать DEBUG.
- ETCP: проверяются RNG salt/sc_encrypt и фактические результаты отправки
INIT/keepalive; busy — DEBUG, отказ — WARN/ERROR. Успешный лог называется
submitted, поскольку он не подтверждает доставку получателю.
Для сопоставления кадров: discovery=debug, debug=trace; для RTO/ACK — etcp=trace,
connection=debug, keepalive=debug. Обычный профиль не включает пофрагментный TRACE.
На desktop UTUN_TEST_DEBUG=1 включает trace диагностической категории;
Android BlePeerProbe включает её на время пробы. Ключи/ссылки приглашений не выводятся.
Проверки после аудита: C-ядро, desktop GUI/probe, Android APK/instrumentation
для arm64-v8a/x86_64 и WinRT cross-build собираются. BLE transport/identity/BlueZ,
четыре desktop packet-link/BLE теста и ETCP connect/packet_link/session проходят.
HCI можно снимать через sudo btmon -w FILE; обычному пользователю monitor запрещён.
Обычный desktop VibeChat после пробы восстановлен, политика Android восстановлена.
Причина длительного ожидания и исправление входящего HIGH
---------------------------------------------------------
Это очередь перед HCI TX, а не единая пауза ожидания PHY negotiation:
- /tmp/ble-ready-baseline-hci.log: ACL Connected success, MTU517, LL TX/RX=251,
PHY TX/RX=2M success до отправки ETCP INIT. Linux central выбрал interval=45ms,
latency=0 и supervision timeout=420ms. В этой пробе также был HCI timeout 0x08.
- В Android HIGH запрашивался только из исходящего BluetoothGatt callback.
Входящий GATT server запрашивал 2M, но не connection priority, поэтому Linux
central сохранял медленный профиль. PHY2M сам по себе interval не сокращает.
- /tmp/ble-ready-raw-{hci,desktop}.log: без ETCP и его повторов прошли все 96
raw echo; по 45636 байт на направление за 27.585s, суммарно 3309B/s.
Все 96 кадров сопоставлены с HCI по seq/длине/отпечатку. Последний исходящий
кадр попал в HCI через 26.035s после локального completion, входящие callback
следовали за HCI RX через 1..2.7ms. Следовательно, ETCP не является необходимым
условием возникновения очереди: стек принимает burst быстрее, чем обслуживает ACL.
Контроллер сообщил 6 LE TX-буферов по 251 байту; по Completed Packets они заняты.
- При изменении interval 45→7.5ms в отдельной пробе частота HCI TX увеличилась
примерно в шесть раз. После обновления параметры подтверждены событием
LE Connection Update Complete status=0; долговременного pending negotiation нет.
hcitool lecup имеет собственные особенности ожидания результата/длины event:
вывод команды и её exit недостаточны, согласование проверяется по HCI event.
- ETCP усиливает перегрузку: INIT вначале повторяется примерно каждые 50ms
с padding; DATA RTO ограничен 1s даже при уже измеренном KA RTT=5..6s.
В результате повтор может попасть в очередь раньше физической отправки оригинала.
На этапе исправления incoming HIGH алгоритмы INIT/RTO ещё не менялись;
последующее исправление RTO описано ниже.
Отдельно найден мешающий discovery: D-Bus sender :1.70, PID3047 kdeconnectd,
каждые 60s устанавливает Transport=bredr. BlueZ объединяет его с нашим Transport=le,
и контроллер выполняет Inquiry по 10.24s почти непрерывно. Штатное disable-backend
объявило BluetoothLinkProvider disabled, но не остановило старую discovery-сессию.
В изолированной пробе потребовался краткий restart KDE Connect с этим backend
выключенным; отсутствие Inquiry подтверждено HCI до восстановления backend.
Медленный drain/повторы сохранились и без Inquiry: это дополнительный фактор,
а не достаточное объяснение всех задержек. Backend KDE Connect затем возвращён
в enabled; его LAN backend и постоянные настройки Bluetooth не менялись.
Исправления:
- BlueZ не открывает кешированные UUID до Connected=1 и ServicesResolved=1.
После resolve повторно читается snapshot/MTU. Регрессионный private-bus тест
с доступным кешем и ServicesResolved=false падал до исправления, теперь проходит;
после сигнала resolve используется актуальный MTU517 вместо прежнего MTU23.
В аппаратной пробе видны оба snapshot: connected=1/resolved=0, затем resolved=1.
- GetManagedObjects используется только как metadata snapshot: закешированное
ManufacturerData больше не обновляет discovery/last_seen. Иначе старый RPA
телефона мог выдаваться за актуальный endpoint. Новые объявления поступают
только из live InterfacesAdded/PropertiesChanged. Регрессионный тест со старым
ManufacturerData в snapshot падал до исправления и проходит после него.
- Android после первой входящей CCC открывает BluetoothGatt handle к тому же ACL
исключительно для requestConnectionPriority(HIGH). У BluetoothGattServer нет
соответствующего публичного метода. Новый handle не выполняет discovery/DATA,
хранится у входящего Link и закрывается при его teardown. Ошибка настройки
логируется WARN и не отменяет работоспособный GATT server.
- /tmp/ble-ready-priority-fixed-{hci,logcat}.log: incoming HIGH accepted=true;
контроллер получил remote request 11.25..15ms, latency=0, timeout=5000ms,
Linux ответил success, Update Complete success установил interval=15ms.
PHY2M/MTU517 сохранены. Клиентский handle переиспользовал существующий ACL.
Ручной HCI настройки и отключения KDE Connect в этой пробе не было.
- В этой нагрузочной пробе сопоставлены 715 TX кадров: локальный completion→HCI
занял до 1.713s вместо ранее измеренных 20..26s. У 684 входящих кадров
HCI→callback занял 0.8..2.8ms. Очередь существенно уменьшилась, остаточные
задержки и недостаточный для такого RTT RTO требуют отдельной работы.
За окно 80s подтверждено 266/512 echo, complete=0, после первого send 70.876s,
суммарно 11259B/s. Это неполная нагрузочная проба, не успешные 512/512.
Дополнительные журналы: /tmp/ble-ready-isolated-*, /tmp/ble-ready-quiet-*,
/tmp/ble-ready-priority-check-*, /tmp/ble-ready-dbus.log.
Поздние повторения ETCP с HIGH всё ещё нестабильны: 115/128 и 27/128 за разные
окна; один профиль не устранил проблему ETCP целиком, все такие пробы complete=0.
Чистое радио после HIGH: /tmp/ble-ready-raw-noscan-fresh-* (несмотря на имя файла,
pauseScan в аргументах этого запуска НЕ было, scanning оставался включённым):
96/96, по 45636 байт за 4.021s, суммарно 22700B/s. У 96 совпавших исходящих
кадров очередь до HCI достигала 3.753s: большой burst всё ещё буферизуется.
/tmp/ble-ready-raw-noscan-valid-*: scanning Android остановлен с явным логом,
96/96 за 10.620s, суммарно 8594B/s. Остановка scanning не дала ускорения;
одиночная парная проба не доказывает отсутствие любого его влияния.
Обе пробы начинались после сброса оставшегося ACL предыдущего теста/GUI.
Первые две попытки сравнения прервались до передачи с le-connection-abort-by-local
и не учитываются. Raw probe теперь повторяет discovery после разрыва до первого
send; разрыв после начала передачи остаётся ошибкой.
Радио-проба умеет выбирать точный node_id, чтобы не подключаться к соседнему
устройству со старым протоколом:
ble_peer_probe connect 80 1657b3ea8281c0a8
UTUN_TEST_DEBUG=1 включает отпечатки кадров также в raw probe.
Проверки кода: C-ядро, desktop GUI/probes, Android APK/instrumentation arm64/x86_64
собираются; Android unit tasks, private-bus BlueZ и четыре desktop BLE/packet-link
теста проходят. Пробы восстанавливают GUI, Android-политику и временное состояние
KDE Connect. Сборку APK и запуск instrumentation нужно выполнять последовательно:
одна проба во время установки завершилась Process crashed и не учитывается.
Изоляция старого протокола и RTO при RTT больше секунды
------------------------------------------------------
Сосед 1588291579282de3 публиковал DATA RX=Write/TX=Indicate. Android пытался
подключиться к нему примерно каждые 6s и обнаруживал несовместимые свойства.
Новый wire-profile требует объявления VC/version=2; версия 1 отклоняется
на discovery, до connectGatt. JNI передаёт scan prefix из общего C codec,
Kotlin не хранит отдельную версию. Нужны новые сборки на обоих пирах.
В /tmp/ble-ready-priority-v2-* нет этих подключений: 128/128 echo за10.623s,
суммарно36149B/s, TX queue до0.554s. Длинные повторения остались нестабильны:
/tmp/ble-ready-desktop-load-v2-* 49/512, /tmp/ble-ready-android-central-v2-* 439/512.
В desktop-load-v2 при KA_RTT_us=2025400 повтор DATA назначался через1000000us;
далее наблюдался RTT2..6s с тем же потолком. Попытки удалялись раньше ACK,
повторы увеличивали очередь и мешали получить действующие DATA/BBR samples.
etcp_tx_rto_us теперь сохраняет ceil(1.2*max(DATA_RTT,KA_RTT)+1.5*jitter+3000us),
минимум10ms и начальное1s без RTT; ограничение сверху — представимость uint32.
Переполнение формулы считается в uint64 и логируется WARN при насыщении.
test_etcp_windows проходит все63 сценария, включая RTT2s/ACK1.5s без повтора,
таймер7.8672s и предельные значения. Формат DATA/ACK и модель BBR не менялись.
Аппаратная проба после исправления: /tmp/ble-ready-rto-desktop-v2-*.
MTU517, HIGH принят, PHY2M. За71.328s подтверждено183/512 echo, complete=0,
суммарно7697B/s; это НЕ успешный нагрузочный проход. Сопоставлены534 TX кадра:
local completion→HCI до4.583s; у503 RX кадров HCI→callback0.7..2.5ms.
До первого INIT_RESPONSE отправлены24 INIT (вначале каждые~50ms), после готовности
линия продолжает передавать кадры. Исправление RTO не ограничивает очередь ОС.
Начальный RTO без RTT всё ещё1s, и в этой пробе он сработал до первого измерения.
Нужен отдельный выбор ограничения стартовых INIT/нижней TX-очереди; изменение
одного таймера не считается подтверждённым устранением всех задержек BLE.
При полном check обнаружена некорректная фикстура test_etcp_server_lifecycle:
синтетический линк MTU=0 не мог отправлять keepalive, но тест ожидал роста счётчика.
После аудита ошибок счётчик увеличивается только при принятии пакета транспортом.
Фикстура теперь явно задаёт результат отправки через codec без сетевого I/O;
добавлена проверка, что busy/error сохраняют счётчик, а успешная отправка увеличивает.
Обратная роль после RTO: /tmp/ble-ready-rto-android-central-v2-repeat-*.
За76.272s подтверждено475/512 echo, complete=0, суммарно18683B/s. У1133 TX кадров
local completion→HCI до1.497s; у1111 RX кадров HCI→callback0.3..2.6ms.
Первая попытка /tmp/ble-ready-rto-android-central-v2-* получила Android GATT133
до открытия/передачи; она не является измерением скорости. Повтор выполнил обмен,
но также не закончил512 пакетов в заданном окне80s. Начальная настройка HIGH/PHY
асинхронна: запрос не подтверждает её завершения, фактический результат виден в HCI.
Длинная очередь остаётся и после успешного LE Connection Update Complete.
Итоговые проверки: ./check.sh230/230, proxy/burst/load PASS (178s);
test_etcp_windows63 сценария и исправленный server_lifecycle PASS. Desktop GUI/probe
и Android APK/instrumentation arm64/x86_64 пересобраны; APK установлен на A52.
Обычный desktop VibeChat и Android-политика после проб восстановлены.