Русский
Русский
English
Статистика
Реклама

Wireshark

Прерывается голос, слышу эхо Проблема качества связи ip телефонии. Как можно решить самостоятельно?

07.04.2021 08:12:05 | Автор: admin
Источник: ЯндексКартинкиИсточник: ЯндексКартинки

Качество связи во время разговора играет весомую роль в работе компании. Это сказывается и на эффективности работы сотрудников, и на имидже компании в целом. Основные жалобы это: пропадают слова, прерывается голос, слышно эхо или речь приходит с задержкой.

Некоторые провайдеры, конечно подсказывают, что можно предпринять со своей стороны, в чем может быть проблема. Снимут дамп, сделают анализ и дадут рекомендации. Но таких крайне мало. Из памяти, пожалуй вспомню оператора Мобилон. Привет техподдержке, если читаете!

А что происходит, если провайдер не дал рекомендаций, не указал на причину?

Несомненно, у вас начнет закрадываться мысль о смене провайдера. Но решит ли это проблему? Если причина на нашей стороне, то очевидно, что проблема не решится, и качество будет также неудовлетворительным с новым провайдером. А переход, дело не простое и затратное. За такой исход событий руководство компании спасибо нам не скажет.

Можно еще обратиться к какой-нибудь аутсорсинговой фирме, которая имеет кейсы в решении подобных проблем. Но это дополнительные затраты. Да и нет никаких гарантий, что потраченные средства в итоге оправдают себя.

Что же еще можно предпринять? Казалось бы, вариантов больше не осталось...

Но может быть, все таки, разобраться самому? Возможно, это не так сложно?

Да, дорогие друзья!
Отвечу я вам. Всё гораздо проще, чем кажется на первый взгляд!

Имея позитивный опыт в решении подобных проблем у разных компаний, хочу поделиться с вами способом ее диагностики и решения, не прибегая к кардинальным мерам и помощи сторонних лиц.

Для диагностики нам понадобится научиться снимать дамп сети (sniffer) с роутера и маршрутизатор Mikrotik. А также, настроить очереди (QoS) на роутере.

Для упрощения схемы, я поделил весь процесс на этапы:

  1. Настроить и запустить sniffer

  2. Воспроизвести проблемный вызов

  3. Проанализировать sniffer в Wireshark

  4. Настроить на роутере выделенную полосу (QoS) для телефонии

  5. Протестировать связь

1. Настройка и запуск packet sniffer

Для того чтобы определить причину проблемы, необходимо снять dump звонка. В нем будет содержаться вся информация о состоянии сети во время вызова.

Настраиваем на Микротике packet sniffer: Tools->Packet Sniffer

На вкладке General оставляем значения по умолчанию.

Открываем настройку Packet SnifferОткрываем настройку Packet Sniffer

Вкладка Streaming: галочки Streaming Enabled и Filter Stream, в поле Server пишем адрес, куда будем отправлять данные, собираемые сниффером.

Прописываем адрес хоста куда слать снифферПрописываем адрес хоста куда слать сниффер

Я отправляю на свой ПК в той же сети, поэтому прописываю его локальный адрес. Но можно слать и на удаленный сервер, тогда прописываем его внешний ip.

Вкладка Filter: здесь необходимо в поле IP Address прописать ip адрес провайдера телефонии.

Желательно уточнить у самого провайдера адреса серверов, с каким сервером осуществляется обмен сигнальными сообщениями, а с каким - RTP.

Если не получилось выяснить адреса провайдера, то можно прописать просто 0.0.0.0/0

Но тогда в дампе будет очень много лишней информации, что затруднит анализ.

Я пообщался с техподдержкой своего провайдера, они порекомендовали прописать всю подсеть.

Прописываем адрес провайдера ip телефонииПрописываем адрес провайдера ip телефонии

Нажимаем Apply и Start. Внизу окна появится статус: running

Packet Sniffer запущенPacket Sniffer запущен

Сниффер на роутере запущен, теперь необходимо поймать пакеты.

На том ПК или сервере, адрес которого указали в поле Server, нужно запустить tcpdump.

На Windows:

а) нужно скачать утилиту tcpdump

Скачиваем с официального сайта версию не для коммерческого использования.

tcpdump.exe можно запустить даже с флэшки

Для этого запускаем cmd от имени администратора и проваливаемся в директорию с файлом tcpdump.exe

Запускаем tcpdump на WindowsЗапускаем tcpdump на Windows

Вводим команду tcpdump -D

Нам отобразится список доступных интерфейсов.

Выводим список доступных интерфейсовВыводим список доступных интерфейсов

Запускаем дамп в онлайн режиме, чтобы найти интерфейс, который нам нужно слушать.

Например: tcpdump -i 1 -v -n host 192.168.88.1

где 1 - это номер интерфейса, а host - адрес роутера.

У меня пакеты летят на интерфейсе под 4, его и буду слушать.

Запускаем tcpdump onlineЗапускаем tcpdump online

Далее запускаем команду для отлова сниффера с Микротика:

tcpdump host 192.168.88.1 -i 4 -C50 -n -v -w name_sniffer.pcap

где i - номер интерфейса, С50 - ограничение размера записываемого файла до 50Мб, n - отображать IP адреса вместо имени хостов, v - уровень отображения получаемой информации (1-й уровень), w - записывать данные в файл.

Запустили tcpdump для отлова Packet SnifferЗапустили tcpdump для отлова Packet Sniffer

На Linux :

Необходимо установить утилиту tcpdump. Обычно она присутствует в стандартном репозитории.

Более подробно про установку можно посмотреть, например, здесь.

Запускаем команду:

tcpdump host 192.168.88.1 -i any -C50 -n -v -w /var/tmp/name_sniffer.pcap

После запуска tcpdump вы должны увидеть отсчет улавливаемых пакетов (на Linux), в поле Got. Если отсчет не идет, значит что-то сделали неверно, перепроверьте.

Запустили tcpdump для отлова Packet SnifferЗапустили tcpdump для отлова Packet Sniffer

2. Фиксируем проблемный звонок

Теперь, когда у нас tcpdump ловит сниффер с Микротика, нужно зафиксировать проблемный звонок.

Если проблема плавающая, тогда следуют попросить сотрудников, чтобы записали время и номер телефона, когда возникнет деградация голоса.

У меня получилось зафиксировать такой пример самостоятельно с одним из сотрудников:

Как мы слышим на записи, голос идет с прерываниями.

Но может быть и так, что на записи из личного кабинета виртуальной АТС провайдера всё будет отлично, а мы слышали человека на том конце провода плохо. Это значит, что к провайдеру голос приходит хорошего качества, а уже по пути от провайдера до нашего конечного устройства голос доходит с потерей пакетов. Для того, чтобы проверить это, нам поможет сниффер.

3. Останавливаем sniffer и анализируем его в Wireshark

Проблемный вызов необходимо проанализировать. Останавливаем tcpdump (Ctrl+C) и sniffer на Микротике (нажать Stop). Создастся файл name_sniffer.pcap.

Устанавливаем программу Wireshark. Скачать ее можно бесплатно с официального сайта. А на Линуксе можно установить из стандартного репозитория.

Открываем pcap файл в Wireshark и переходим в Телефония->Вызовы VoIP

Открываем pcap файл для анализаОткрываем pcap файл для анализа

В новом окне отобразятся все вызовы, которые попали в дамп. У меня такой один.

VoIP вызов в дампеVoIP вызов в дампе

Для удобства поиска вызовов (когда их в дампе много) установите галочку Время дня.

Выберите вызов и откройте Последовательность потоков, чтобы увидеть движение запросов по вашему звонку.

Дамп движения запросов звонка (последовательность потоков)Дамп движения запросов звонка (последовательность потоков)

Здесь мы увидим, с каким сервером провайдера идет обмен сигнальными сообщениями, а с каким сервером осуществляется передача голосовых пакетов (RTP).

В случае, когда не проходит вызов или наблюдается односторонняя слышимость, мы можем с помощью дампа последовательности потоков увидеть, где кроется проблема.

Но для анализа качества голоса, данная информация нам нужна только, чтобы увидеть адрес сервера передачи голосовых сообщений.

Далее нас интересуют RTCP пакеты.

Из всего перехваченного сниффером трафика нужно отфильтровать только RTCP пакеты.

Прописываем фильтр:

(rtcp.ssrc.fraction>10)||(rtcp.ssrc.jitter>35)

- отобразить RTCP со значением потерь пакетов больше 10 или RTCP со значением джиттера больше 35.

Выбираем сообщение и разворачиваем RTCP -> Source 1 -> SSRC Contents

Анализ RTCP по звонкуАнализ RTCP по звонку

Здесь видим, что потеряно 50 пакетов из 256 и уровень джиттера 166 (хотя нормальный уровень это 30-70).

Так можно полистать по всем найденным сообщениям и убедиться, что деградация качества голоса возникает из-за потери голосовых пакетов на нашем интернет канале.

По каким причинам это может происходить?

  1. Забивается линия выделенная вам от интернет провайдера.
    Например, у нас 3Mб/с на "внешку". Устройства в локальной сети потребляют все 3Mб/с, но если просто сёрфить в браузере, то мы не заметим нехватку канала. Так как в этом случае, используется транспортный протокол TCP. А телефония использует UDP, которому свойственно теряться в процессе передачи, если весь ваш выделенный канал занят.

  2. Устройства подключены по воздуху (Wi-Fi).
    В таком случае будет высокий показатель джиттера.

  3. У провайдера на линии есть радиоканал.

  4. Проблема с вашим маршрутизатором.

  5. Проблемы на линии интернет провайдера

В этой статье, более подробно, рассмотрена причина под пунктом 1.

По остальным скажу кратко.

Пункт 2 - если на устройствах есть функция джиттер-буфер, то нужно установить режим Fixed. Если нет такой опции, то подключить устройство витой парой.

Пункт 3 и 5 - обратиться к интернет провайдеру, предоставив наши дампы, подтверждающие проблему.

Пункт 4 - диагностировать или заменить роутер.

Но в первую очередь, рекомендую всегда сначала проработать пункт 1.

4. Настраиваем выделенную полосу для ip телефонии

Необходимо в вашей локальной сети обеспечить для ip телефонии отдельную полосу пропускания (QoS), чтобы трафик других устройств не мешал.

Для начала, измерьте фактическую скорость интернета на "внешку".

Я измеряю через speedtest.net

Можно еще с помощью 2ip.ru или утилитой iperf

На speedtest.net я выбираю Change Server город отличный от моего, чтобы исключить вероятность замера скорости в пиринге.

Настраиваю speedtest.net для замера скоростиНастраиваю speedtest.net для замера скоростиВыбираю Change ServerВыбираю Change ServerРезультаты измерения скорости интернетаРезультаты измерения скорости интернета

У меня на загрузку скорость 11Мб/с, на отдачу 14Мб/с. Хотя по договору должно быть 15М в обе стороны. Поэтому и рекомендую измерять, какая у вас скорость по факту, а не по бумагам. Это поможет корректно настроить очереди на роутере.

Для настройки очередей открываем на Микротике Queues

QueuesQueues

Cоздаем правила в разделе Simple Queues.

На вкладке General задаем ограничение по скорости для всей локальной сети.

Я устанавливаю максимальные значения лимита меньше на 2М, чем полученные при замере.

Почему 2М? Беру с запасом, так как скорость может быть не постоянной и в моменте меняться как в большую, так и в меньшую сторону.

Настройки на вкладке GeneralНастройки на вкладке General

В Advanced выставить Queue Type распределение по pcq (это делается для того, чтобы устройства не мешали друг другу и равномерно использовали трафик).

Настройки на вкладке AdvancedНастройки на вкладке Advanced

Сохраняем это правило и создаем еще одно, для SIP.

Прописываем ip адрес (можно всю подсеть) провайдера ip телефонии.

Максимальные лимиты устанавливаем, как заявлено по договору интернет провайдера.

Настройки General для SIPНастройки General для SIP

В Advanced устанавливаем Limit At. Это позволит для телефонии оставлять 1Мб/с в любом случае, даже если идет максимальная нагрузка на канал другими устройствами.

Вкладка Advanced при настройке QoS для SIPВкладка Advanced при настройке QoS для SIP

Сохраняем и устанавливаем правило SIP на верхнюю позицию.

Порядок QoS правилПорядок QoS правил

ВНИМАНИЕ!

  1. Чтобы очереди (QoS) начали работать, необходимо деактивировать правило Fasttrack в IP -> Firewall -> Filter Rules.

  2. Учитывайте порядок настроенных правил. Обработка осуществляется сверху вниз. Поэтому обязательно правило SIP поднимаем на самый верх.

Пояснение по настроенным QoS:

  • весь трафик, который идет на ip адреса отличные от адреса voip провайдера, ограничивается 12Мб/с на загрузку и 9Мб/с на отдачу

  • весь остаток от этого до 15Мб/с оставляем для телефонии

  • и на тот случай, что если даже трафик проскочит выше лимитов, для телефонии отведен 1Мб/с принудительно

Далее проверяем ходит ли вообще трафик в настроенных QoS.

Нужно открыть настройки очереди и перейти на вкладку Traffic.

График трафика local QoSГрафик трафика local QoSГрафик трафика sip QoSГрафик трафика sip QoS

На вкладке Statistic можно увидеть, количество дропнутых пакетов и распределенных по pcq.

Статистика local QoSСтатистика local QoS

Также можно проверить, как отрабатывают очереди, с помощью утилиты iperf.

5. Тестируем связь

Теперь, когда QoS настроены, нужно протестировать связь.

Ставим дамп и делаем несколько тестовых звонков.

Я сделал несколько вызовов сотрудникам, и мы вместе убедились, что теперь прерываний не наблюдалось.

Вот пример одного из звонков.

В дампе этого вызова потерь пакетов не наблюдается.

Дамп звонка после настройки QoSДамп звонка после настройки QoSДамп звонка после настройки QoSДамп звонка после настройки QoS

Единственное, можно заметить, что уровень джиттера выше нормы.

Это обусловлено подключением voip устройства через Wi-Fi. И, так как устройство позволяет настроить джиттер-буфер, качество голоса не страдает.

Вы можете также и сами наглядно всё это увидеть в моих дампах. Скачать можно здесь:
дамп звонка до настройки QoS
дамп звонка после настройки QoS

Итог:

Когда у вас возникла проблема с качеством голоса цифрового характера, всегда, в первую очередь, произведите анализ вашей сети и настройте QoS для телефонии. Если даже выяснится, что причина была не на вашей стороне, то у вас уже будут технические данные (дампы), которые вы сможете предоставить провайдерам для подтверждения.

В некоторых организациях в локальной сети может находиться большое количество устройств с разными категориями. Например, помимо ip телефонии еще ip камеры, которые также используют udp протокол для передачи данных. Следовательно для ip камер тоже необходимо выделять QoS.

Вам не обязательно настраивать очереди точно также, как у меня. Главное, что я хотел показать, это логику решения проблемы с качеством голоса.

Более подробно про QoS можно изучить еще в этой статье.

Подробнее..

Анализ сетевого трафика и базовый траблшутиг (бесплатный видео курс)

08.04.2021 10:11:09 | Автор: admin

Прошло уже почти два года с момента публикации моего последнего курса и наконец я опять в деле! Как и прежде, весь контент на ресурсе NetSkills предназначен для подготовки начинающих инженеров. Этот курс не стал исключением и посвящен основам анализа трафика и базовому траблшутингу с помощью таких популярнейших инструментов как tcpdump и wireshark! Одна из важнейших тем, которая совершенно точно пригодится любому сетевику, админу или даже безопаснику. Я бы рекомендовал приступать к этому курсу только после окончания Курса молодого бойца, т.к. данный материал предполагает, что вы понимаете базовые принципы работы компьютерных сетей. В этом же курсе мы погрузимся в детальное изучение работы стэка TCP/IP - тема, которую многие старательно избегают. Однако, по завершению курса вы получите знания и навыки, которые выведут ваше понимание сетей на принципиально новый уровень. Вы поймете саму суть работы сетей и что важнее - научитесь видеть проблемы в ее работе.

Повторюсь, мы будем анализировать трафик с помощью утилит tcpdump и wireshark, которые уже давно являются стандартом в мире анализа и траблшутинга. Вы просто обязаны уметь ими пользоваться! При этом большинство использует их от силы на 10% от возможностей (если вообще используют). Я же постараюсь научить вас это делать, как профессионалы.

Содержание

  1. Три главных способа сбора сетевого трафика

    Обсудим, что такое вообще сбор, как он осуществляется и какие преимущества и недостатки у этих способов.

  2. Основы tcpdump

    Поработаем с утилитой tcpdump, рассмотрим основные ключи и пару практических кейсов. Думаю, после урока вы будете работать с этой утилитой гораздо увереннее.

  3. Фреймы, пакеты, сегменты

    Возможно кому-то покажется, что это тема здесь лишняя, но это заблуждение. Невозможно нормально анализировать трафик, и уж тем более траблшутить, если вы не понимаете основы. Я постараюсь рассказать о самом главном и показать, как это работает в реальной жизни.

  4. Основы Wireshark

    Запустим Wireshark и обсудим основы сбора трафика. Поупражняемся с интерфейсами, профилями и т.д.

  5. Исследование сети

    Попробуем применить полученные навыки в реальном кейсе - а именно исследование сети по дампу трафика. Вы удивитесь, сколько всего можно узнать об инфраструктуре, всего лишь по одному дампу.

  6. Основы фильтрации

    Более плотно поработаем с фильтрацией, колонками, протоколами, полями и т.д. Т.е. научимся выделять нужную информацию в большом объеме данных. Это очень важный навык в работе с Wireshark.

  7. Основы TCP

    Опять перейдем к фундаментальным вещам - основам TCP. Уже на примере дампа реального трафика рассмотрим как работает 3 way tcp handshake - важнейший механизм в сетевом взаимодействии.

  8. RTT & Window Size

    Параметры, которые во многом определяют надежность и стабильность сети. Здесь вы на практике поймете, почему широкий канал это не всегда быстрый канал и почему так важно время отклика для онлайн игр.

  9. Визуализация данных

    Да, wireshark умеет и это. Причем в некоторых кейсах это очень помогает в решении проблем.

  10. Реальные кейсы

    Ну и под конец мы рассмотрим несколько типовых проблем в сети и научимся их решать с помощью Wireshark.

Видео курс

Данный курс, как и Курс молодого бойца, бесплатно опубликован на ютуб-канале:

Смотрите, оставляйте комментарии, принимается любая конструктивная критика.

Спасибо за внимание!

Подробнее..

Баг в ESP-IDF MDNS, Wireshark и при чём тут единороги

29.11.2020 22:13:53 | Автор: admin

Всем привет. Я занимаюсь коммерческой разработкой в IoT, в основном мы используем модули от Espressif - ESP8266 и ESP32.

В рамках "догфудинга" мы иногда берём свои продукты домой и используем в повседневной жизни. И вот, однажды, от одного из сотрудников поступила жалоба: после установки новой тестовой прошивки на устройстве, его домашняя сеть сначала начала жестоко глючить и зависать, а потом ситуация нормализовалась, но наш девайс более не был виден ни в локальной сети, ни в облаке.

Налицо какой-то коллапс. Но какой? На других сетях мы такого поведения не наблюдали, так что было решено высадить к сотруднику развед-десант в лице меня, экипированного всем необходимым.

Разведка

Для начала, я решил собрать максимальное количество данных про ситуацию в её терминальной стадии. Не перезагружая устройство, я запустил Wireshark в режиме Monitor Mode, настроив фильтрацию на MAC-адрес устройства. Выяснилось, что девайс уверен, что его сеть в порядке - он упорно слал роутеру какие-то данные, однако роутер ему ничего не отвечал. Хм, подозрительно.

В админке роутера девайс тоже был виден как подключенный. Но почему же нету обратной связи? На этот вопрос я получил ответ, когда решил подключить к этому же роутеру ещё одно устройство (точнее, один из своих devkit-ов), и убрал фильтрацию в Wireshark. Оказывается, у роутера поменялся MAC-адрес! Хм, подозрительно. Поменялся он ровно на один последний бит, при этом вся остальная техника эту подмену осознала, а вот наше устройство - нет, и упорно отсылало данные на старый мак-адрес, который, конечно же, никто уже не слушал.

Ладно, пришло время узнать больше. Перезагружаем роутер. Теоретически, это же должно вернуть его MAC в "обычное" состояние? И действительно, MAC вернулся. Но зависший девайс уже был "в коме", и упорно не хотел ничего делать. Ничего нового мы от него уже не узнаем, так что перезагружаем и его. А заодно, дабы собрать больше данных, пропишем в Wireshark пароль от роутера, чтобы он расшифровал весь трафик.

Коллапс

Тут произошло что-то странное. Сначала девайс, как положено, вернулся в сеть. А дальше началось... Количество сообщений в окне Wireshark начало расти с невероятной скоростью. Впрочем, через несколько минут всё остановилось - роутер снова решил проявить свою альтернативную, отличающуюся на один бит, сущность. Ладно, у нас есть дамп, давайте посмотрим, что это было.

And the winner is... 99% захваченных пакетов были про MDNS. Мы действительно используем его, чтобы телефоны могли найти наши девайсы в локальной сети, и работать с ними даже в условиях отсутствия облака (что иногда случается по разным причинам, начиная с "забыли заплатить за интернет", и заканчивая сбоями у Amazon). Но почему так много? Интервал между сообщениями - десятки миллисекунд, и соотношение "входящих/исходящих" (по отношению к девайсу) примерно одинаковое. Что ж, пора раскуривать.

Последовательность пакетов была следующая:

  1. Девайс регистрируется в multicast-группе MDNS, чтобы иметь возможность получать запросы на обнаружение.

  2. Девайс отправляет collision-query-пакет с запросом ANY на полный адрес своего "сервиса", чтобы узнать, есть ли в сети кто-то, кому он может "помешать".

  3. Роутер перенаправляет collision-query-пакет всем устройствам multicast-группы, включая сам девайс.

  4. Девайс отправляет advertise-пакет с PTR, SRV, TXT и A/AAAA записями multicast-группе MDNS, сообщая, что он появился в сети.

  5. Роутер перенаправляет advertise-пакет всем устройствам multicast-группы, включая сам девайс.

  6. 2-5 пункты начинают повторяться с большой скоростью.

Сразу становится понятно, почему проблема не проявлялась на нашем тестовом окружении в офисе - наши роутеры не перенаправляют multicast самому отправителю. Но почему мы не видели этого поведения на старой прошивке? И действительно, откатив девайс до старой версии, я стабилизировал ситуацию. Начинаем бить в бубен.

Делаем diff. Видим, что немного поменялся код внутренней логики, не влияющий на сетевую часть. Что ж, это можно отмести почти сразу. Ещё поменялся номер версии... Ну да, с 0.9 на 0.10. Не может же это влиять? Или... Ладно, пока оставим эту мысль. Ищем, где отправляются пакеты из MDNS.

Debugger? printf!

Как поступил бы на моём месте любой профессиональный разработчик? Правильно: начал обмазывать логами все места отправки пакетов в файле mdns.c. Поиск быстро привёл меня к функции _mdns_create_probe_packet. Поискав по файлу места, из которых она вызывается (и пройдя по стеку вызовов немного дальше), я остановился на строчке #2917 в функции mdns_parse_packet. В логах это место действительно появлялось очень часто. Подозрение пало на вызов _mdns_check_txt_collision. Тут начала вырисовываться картина происходящего: девайс, получая свой же advertise, находил в нём TXT-запись, и сравнивал его со своим TXT. Но ведь он сам его отправил! Ладно, смотрим код самой функции. Я даже приведу его тут по частям, с описанием происходящего.

size_t data_len = 1;if (len == 1 && service->txt) {  return -1;//we win} else if (len > 1 && !service->txt) {  return 1;//they win} else if (len == 1 && !service->txt) {  return 0;//same}

Тут мы создаём переменную data_len, а так же проверяем наличие TXT-записи в нашем service. Вроде бы всё нормально - тут мы проходим дальше.

mdns_txt_linked_item_t * txt = service->txt;while (txt) {  data_len += 2 + strlen(service->txt->key) + strlen(service->txt->value);  txt = txt->next;}if (len > data_len) {  return 1;//they win} else if (len < data_len) {  return -1;//we win}

Тут мы высчитываем длину буфера, в который должен влезть наш TXT из сервиса, а заодно сравниваем эту длину с тем, что мы получили из эфира.

uint8_t ours[len];uint16_t index = 0;char * tmp;txt = service->txt;while (txt) {  tmp = (char *)malloc(2 + strlen(txt->key) + strlen(txt->value));  if (tmp) {    sprintf(tmp, "%s=%s", txt->key, txt->value);    _mdns_append_string(ours, &index, tmp);    free(tmp);  } else {    HOOK_MALLOC_FAILED;    // continue  }  txt = txt->next;}int ret = memcmp(ours, data, len);if (ret > 0) {  return -1;//we win} else if (ret < 0) {  return 1;//they win}return 0;//same

Ну и тут мы кодируем наш TXT в буфер, размер которого уже просчитали (и проверили), и сравниваем его содержимое с полученным.

Уже нашли ошибку? Я тоже заметил её не сразу, поэтому решил пройтись по коду построчно. Опять же, помог мне с этим printf.

Когда я "упал" на проверке длины, я немного удивился. Но как? Ведь "правильная" длина (которую 10мс назад отправил сам девайс) точно совпадает с "входящей"! Давайте ещё раз взглянем на её подсчёт.

mdns_txt_linked_item_t * txt = service->txt;while (txt) {  data_len += 2 + strlen(service->txt->key) + strlen(service->txt->value);  txt = txt->next;}

Окей, тут явно виден проход по linked-list. Мы берём очередной элемент, берём длину его key и value... Стоп. Его или service->txt? Так, понятно...

Выходит, из-за бага в коде (который, если верить git blame, лежит там уже очень много лет), мы всегда берём длину от первого элемента. Но как это работало всё это время? А вот так: нам повезло. Всё это время TXT-записи, которые мы добавляли, по сумме длин чётко совпадали с длиной первого, умноженного на N. Получается, стоило нам добавить новый элемент, поменять порядок элементов, или изменить длину любого из них - и всё, баг начинал проявляться. Но при чём тут номер версии? Ах да, мы же передаём его в MDNS... Паззл сошёлся.

И что дальше?

Соответствующий issue в ESP-IDF я отправил, в своих рабочих копиях мы это место исправили, и наши девайсы прекратили сводить с ума бедные роутеры.

Но тут встал правильный вопрос: а сколько ещё таких багов может быть в SDK? Проект большой, кода много (а часть ещё и стороннего - в виде submodule). Наверняка есть что-то интересное, странное, ужасное...? То, что не вылезает у нас на тестировании, но может создать нам проблем в случайный момент времени.

Так при чём тут единороги?

С этой мыслью я написал @Andrey2008 вспоминая про PVS-Studio. Он любезно согласился попробовать посмотреть на этот проект, а также поделился триальной версией ключа для PVS-Studio, чтобы я мог попытаться проанализировать код самостоятельно. Забегая вперёд, скажу, что там есть, на что посмотреть... Но об этом - в следующей серии.

А поймал ли единорог этот баг?

К сожалению, data flow PVS-Studio не нашёл этой проблемы с linked-list. Но будем справедливы - я тоже обратил внимание на эту ошибку не с первого раза (и даже не с третьей вычитки кода). Андрей говорит, что подобную диагностику добавить можно - а значит, одна из следующих версий может начать ловить такие гейзенбаги.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru