January 10

История одного tcpdump на b4com

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

Рассказ будет про моё заключительное дежурство в 2025 году, и выпало оно ровно на 30 декабря!

Началось всё с того, что в какой-то момент времени, коробка начала сыпать вот такое в лог:

2025 Dec 30 10:09:34: hostname: OAM: ERROR: [OAM_OPER_PKT_READ_ERR_3]: bfd_ipv6_async_pkt_read: HopLimit (253)! = 255

Ну ошибка и ошибка. Влияния никакого нет, по крайней мере мы его не наблюдаем. На всякий посмотрели все текущие сессии BFD – с ними порядок. Проверили всякие параметры, CPU, RAM, FIB/RIB – тоже ок.

Ладно, вроде ничего страшного не происходит, но хочется же всё-таки разобраться из-за чего такая штука возникает. Посовещались с коллегами и сообща поняли, что ошибку генерит не просто BFD, а наиболее вероятен сценарий, когда свич ждёт single-hop, а ему прилетает пакет с откусанным TTL, т.е. 253 вместо 255 (HopLimit – это и есть TTL в IPv6).

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

Отлично, осталось теперь найти того, кто может такое посылать.

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

Ладно, следующим шагом поиска отправителя, является дамп трафика. Благо собрать его можно сразу на общем интерфейсе шине, который идёт в сторону CPU.

Делается это вот так:

# заходим в шелл и становимся рутом
start-shell
su -
password

# запускаем tcpdump на порту broadcom0
tcpdump -ennie broadcom0 -w /tmp/dump1.pcap

Наверное стоит тут рассказать, что такое порт broadcom0, на котором мы собираем дамп. В моем понимании - это некий общий порт, в который сведены все физические интерфейсы и куда попадает весь входящий трафик, который идёт в сторону CPU.
То есть, свич получает BGP Update на интерфейсе ce1, он его перенаправляет в интерфейс broadcom0, или допустим он получает ARP - тоже самое, пакет уходит туда же. Аналогичная ситуация будет и с тем, если он получит BFD для multihop сессии.
При этом, если речь идёт про исходящий, то используется другой интерфейс - broadcom2.

Тут появляется небольшой нюанс, если попытаться открыть дамп трафика, который мы собрали, то там внутри будет абракадабра нечитабельная. Причина в том, что архитектура построена таким образом, что пакет дополнительно оборачивается в оверхед, который составляет размер в 100 байт.
Вы спросите зачем? Однозначного ответа у меня нет, но могу предположить, что делается это для того, чтобы разделять таким образом трафик, идущий от конкретного интерфейса и таким образом правильно его обработать, а затем отправить обратно.

В любом случае, мы знаем, что оверхед для входящего - это всегда ровно 100 байт. А значит, если мы их срежем, то получим наш чистый, незамутненный дамп. К слову, для исходящего оверхед уже другой - 48 байт.

Для этого у нас есть утилитка editcap:

# не выходя из шелла, срезаем лишние 100 байт
editcap -C 100 /tmp/dump1.pcap /tmp/dump1_edited.pcap


Отлично, дамп получили, качаем его с коробки себе локально и открываем через wireshark.

Буквально за те 20 секунд пока мы его собирали, туда набежало целых 18 тысяч пакетов.

Ок, сортируем по тому принципу, который обозначили выше, а именно - это IPv6, это BFD и у пакета HopLimit - 253, получаем вот такой фильтр - (bfd && ipv6) && (ipv6.hlim == 253).

После применения фильтра

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

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

Указали адреса источника и получателя в качестве фильтра и вуаля - виновник найден! Им оказался один из лифов. Отлично, пойдём туда и посмотрим, что же с ним не так...

Лог в момент появления ошибки

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

Т.е. окончательная цепочка выглядела вот так:

SRV —> LeafX --> Spine1 --> LeafY

Сообщили коллегам, которые занимаются серверами, они в свою очередь подтвердили, что действительно такое есть, тотчас поправили и ошибка пропала!