проблема синхронизации после добавления/удаления маршрута (маршрут не используется)

проблема синхронизации после добавления/удаления маршрута (маршрут не используется)

У меня есть приложение, которое запускает сырой IP-сокет, пункт назначения этого сокета управляется маршрутами, установленными с помощью команды 'ip route add'. Эти маршруты могут меняться в течение срока службы сокета (например, из-за изменения следующего перехода)

Упрощенно, предположим, что у меня есть 2 интерфейса, eth0и eth1. У меня также есть маршрут по умолчанию через eth0.

Например 10.10.10.10, конечная точка сырого сокета — eth1 имеет адрес 100.0.0.1, я делаю следующее в течение времени жизни сырого сокета:

ip -f inet route delete 10.10.10.10
ip -f inet route add 100.0.0.2 dev eth1
ip -f inet route add 10.10.10.10/32 via 100.0.0.2 dev eth1

Теперь я вижу, что после этой операции трафик проходит корректно eth1в течение нескольких секунд, затем на короткое время (менее полсекунды) происходит сбой (через eth0), а затем снова все корректно (насколько я могу судить, постоянно).

Итак, мой главный вопрос: может ли кто-нибудь объяснить, что здесь может пойти не так? Я пробовал добавлять ip route flush cacheпосле последовательности, упомянутой ранее, но это ничего не дало. В настоящее время я озадачен тем, почему трафик иногда теряется. Я думаю, что это либо проблема синхронизации в командах маршрутизации, либо какой-то другой триггер, отключающий маршрут на долю секунды, но у меня заканчиваются варианты.

Я пытался использовать эту SO_BINDTODEVICEопцию на моем сыром сокете, но, увы, это не помогло, главное отличие в том, что когда трафик идет не так, он не отправляетсясовсем, потому что он пойдет через неправильный интерфейс. Однако я надеялся, что это установит errno на что-то вроде E_CANNOTROUTE (такого не существует), чтобы я мог перехватить это и повторить отправку пакета. В настоящее время он этого не делает, но есть ли способ перехватить такой сбой? У меня (почти) полный контроль над системой и приложением, которое запускает сокет.

Одно из решений, которое, как я знаю, сработает, — это не использовать необработанные сокеты L3, а AF_PACKETиспользовать сокеты L3 (а также самостоятельно использовать ARP/ND), но я бы пока не хотел вдаваться в подробности.

Обновлять

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

  • Если его там нет, я просто устанавливаю новый маршрут и пропускаю удаление.
  • Если точный маршрут уже присутствует (тот же nh, то же dev), то я ничего не делаю.
  • Если для этого маршрута присутствует другой nh, я теперь делаю более конкретное удаление только для этого nh, а затем добавляю.

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

К вашему сведению: у меня возникла проблема на Centos, насколько я понимаю, при переходе с Centos4 на Centos6, 32-бит.

решение1

Если я правильно понимаю, пакеты всегда должны выходить из eth1, а ваша проблема в том, что при обновлении на новый nexthop на eth1 ваши пакеты иногда выходят из eth0? Это потому, что ваше удаление+добавление не является атомарной операцией.

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

решение2

Есть ли маршрут по умолчанию (или другой маршрут, охватывающий 10.10.10.10/32) через eth0? Если вы сначала удаляете, а затем добавляете, у вас может возникнуть состояние гонки, когда происходит удаление, пакеты выходят за пределы маршрута по умолчанию в течение времени между удалением и добавлением, затем происходит добавление, и пакеты начинают идти туда, куда вы ожидаете.

Мне это определенно напоминает некую форму состояния гонки, скорее всего, из-за неатомарной природы двух упомянутых вами операций маршрутизации (как утверждает Law29).

Связанный контент