Пока отладка проблема с сетевой конфигурацией для набора виртуальных машин, работающих под KVM, я обнаружил обстоятельство, когда ядро в гостевой виртуальной машине решило пометить исходящий кадр Ethernet с адресом назначения, который находится в конфликте с адресом, который он выбрал бы, если он соблюдает таблицу IP-маршрутов ядра.
Итак, в этом примере я ожидал, что исходящий кадр будет доставлен на de: ad: be: 3b: 24: 48, что соответствует хосту, которому принадлежит IP-адрес 10.11.11.2 и которому принадлежит маршрут к 10.8.0.0/24. .
На самом деле произошло то, что ядро решило пометить фрейм адресом 00: 10: db: ff: 70: 01, которое отправило фрейм в направлении 10.11.11.1, который не знает, как маршрутизировать к 10.8.0.0. / 24, и в результате пакет был отброшен.
Это решение противоречило локальной таблице маршрутизации, в которой четко указывалось, что маршрут к 10.8.0.0/24 проходит через 10.11.11.2. См. Подробности в исходном отчете о проблеме.
[Неверный адрес назначения был виден при запуске tcpdump на гостевой виртуальной машине, которая отправляла фрейм в неправильном направлении.].
Фактически, путем объединения локальной таблицы arp для того, чтобы кажущийся MAC-адрес 10.11.11.1 был идентичен фактическому MAC-адресу 10.11.11.2, я смог добиться того, чтобы фрейм шел в правильном направлении.
Итак, мой вопрос: какой механизм, в гостевой виртуальной машине или на хосте KVM, может заставить гостевое ядро игнорировать локальную таблицу маршрутов и отправлять пакет в кадре на (неправильный) хост в 10.11.11.1, хотя 10.11 .11.1 не указан в качестве шлюза для сети назначения (10.8.0.0/24)?
Примечание: iptables в то время был отключен в гостевой системе. Я не знаю, включен ли ebtables на хосте KVM, но даже если бы это было так, как это могло бы заставить ядро в гостевой виртуальной машине отправить пакет в направлении 10.11.11.1?
Одно поведение, которое я заметил, заключается в том, что если я очищаю таблицы ARP затронутого хоста и отправляю запрос ping на затронутый хост из сети 10.8.0.0/24, он получает запрос, а затем немедленно отправляет широковещательное сообщение arp для 10.11.11.1 перед отправкой ответа ping в направлении 10.11.11.1 вместо 10.11.11.2 и, следовательно, 10.8.0.0/24. Что заставляет его попробовать 10.11.11.1, который не указан в качестве шлюза?
Может быть, маршрутизация на основе источника или политики? Linux может иметь несколько таблиц маршрутизации и выбирать, какую из них использовать, исходя из нескольких условий. Проверьте Документация OpenVZ по маршрутизации на основе исходного кода