У меня есть приложение, в котором запущен необработанный 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
сокеты (а также сам ARP / ND), но я бы не стал вдаваться в подробности.
Я улучшил поведение своей системы, изменив поведение при изменении маршрута. Когда мне нужно обновить следующий переход, я смотрю на уже установленный маршрут и принимаю меры на его основе:
Хотя это стабилизировало большинство моих проблем, я все еще иногда вижу, что то же самое происходит (хотя и гораздо реже), когда происходит фактическое удаление + добавление (последний случай в новом механизме). Кроме того, это на самом деле все еще не объясняет, что идет не так (это просто обходит это), поэтому я оставлю этот вопрос пока открытым, поскольку мне действительно любопытно, что здесь идет не так.
К вашему сведению: у меня проблема с centos, насколько я понимаю, переход от centos4 к centos6, 32-бит.
Есть ли маршрут по умолчанию (или другой маршрут, охватывающий 10.10.10.10/32) через eth0? Если вы сначала удаляете, а затем добавляете, у вас может быть состояние гонки, когда происходит удаление, пакеты выходят по маршруту по умолчанию в течение времени между удалением и добавлением, затем происходит добавление, и пакеты начинают идти туда, куда вы ожидаете.
Для меня это определенно звучит как некоторая форма состояния гонки, скорее всего из-за неатомарной природы двух упомянутых вами операций маршрутизации (как указано в Законе 29).
Если я правильно понимаю, пакеты всегда должны выходить из eth1, и ваша проблема в том, что при обновлении до нового nexthop на eth1 ваши пакеты иногда выходят из eth0? Это было бы потому, что ваше удаление + добавление не является атомарной операцией.
Попробуйте сначала выполнить добавление, а затем удаление. Удаление должно быть конкретным (я считаю, с устройством и следующим магазином), чтобы он также не удалял только что добавленный новый маршрут.