История одного 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.
Ок, сортируем по тому принципу, который обозначили выше, а именно - это IPv6, это BFD и у пакета HopLimit - 253, получаем вот такой фильтр - (bfd && ipv6) && (ipv6.hlim == 253).
Ура! Вот они, наши ожидаемые BFD, выходит мы оказались изначально правы, что лог генерится этими самыми сообщениями.
Теперь дело осталось за малым, понять кто же это всё-таки был и починить. Тут мы немного поковырялись с разными идеями и догадками, пока наконец не пришли к самой простой из имеющихся - посмотреть в наш Akvorado! Благо sFlow со всех коробок собирается.
Указали адреса источника и получателя в качестве фильтра и вуаля - виновник найден! Им оказался один из лифов. Отлично, пойдём туда и посмотрим, что же с ним не так...
Опа, а вот и любопытный лог, который совпадает минута в минуту со временем, когда у нас появилась ошибка. Выясняется, что это подключили новый сервер, который собственно и отправлял в сторону свича BFD, только вот destination адрес был неверно указан и свич его у себя не находил и посылал дальше по фабрике. Ну а там уже пакет доходил до коммутатора, где уже по счастливой случайности оказался тот самый destination адрес!
Т.е. окончательная цепочка выглядела вот так:
SRV —> LeafX --> Spine1 --> LeafY
Сообщили коллегам, которые занимаются серверами, они в свою очередь подтвердили, что действительно такое есть, тотчас поправили и ошибка пропала!