421 lines
41 KiB
Plaintext
421 lines
41 KiB
Plaintext
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-политика после проб восстановлены.
|