Если я добавлю следующие настройки в гостевой kvm:
net.ipv4.conf.all.arp_ignore=1
Сеть гостя останавливается (очень прерывистая).
Хост kvm использует мостовую сеть:
auto lo
iface lo inet loopback
iface lo inet6 loopback
auto {{ vbox_interface }}
iface {{ vbox_interface }} inet static
address {{ vbox_main_ipv4 }}
netmask {{ vbox_ipv4_netmask }}
gateway {{ vbox_ipv4_gw }}
pointopoint {{ vbox_ipv4_gw }}
iface {{ vbox_interface }} inet6 static
address {{ vbox_main_ipv6 }}
netmask 128
gateway {{ vbox_ipv6_gw }}
auto br0
iface br0 inet static
address {{ vbox_main_ipv4 }}
netmask 255.255.255.255
bridge_ports none
bridge_stp off
bridge_fd 0
bridge_maxwait 0
{% for ip in vbox_addtl_ipv4 %}
up route add -host {{ ip }} dev br0
{% endfor %}
iface br0 inet6 static
address {{ vbox_main_ipv6 }}
netmask 64
Это почему?
Как указывает Майкл в комментариях, некоторый контекст:
arp_ignore
(http://kb.linuxvirtualserver.org/wiki/Using_arp_announce/arp_ignore_to_disable_ARP) - в основном я хочу сохранить эту настройку, поскольку нахожусь в ненадежной сетиarp_ignore=0
на гостевой виртуальной машине решит проблему. Однако я хотел бы знать, почему (потому что мне не нужно делать это на самом хосте), и я не могу принять это как ответ, потому что я не верю, что его настройка должна привести к отключению сети (например, я хочу решить проблему проблема без установления зависимости)Итак, я полагаю, что мой вопрос:
Почему arp_ignore=1
разорвать сеть kvm-guest <> kvm-host, когда kvm-guest использует pointopoint / 255.255.255.255?
Редактировать 23/10/2018: конфигурация гостевых интерфейсов
# The loopback network interface
auto lo
iface lo inet loopback
auto ens7
iface ens7 inet static
address IP from the pool {{ vbox_addtl_ipv4 }}
netmask 255.255.255.255
gateway {{ vbox_main_ipv4 }}
pointopoint {{ vbox_main_ipv4 }}
iface ens7 inet6 static
address xxx::xxx
netmask 64
gateway {{ vbox_main_ipv6 }}
Я проверил это поведение на Ubuntu 18.04 без каких-либо мостов, KVM или Hetzner вообще, и я думаю, что на самом деле это ошибка ядра в отношении обработки arp_ignore
на двухточечных интерфейсах Ethernet. Шаги для проверки:
netplan
не будет мешать, отключив его совсем.Настройте две системы с подключенными друг к другу интерфейсами Ethernet и назначенными IP-адресами следующим образом:
Север А:
ip addr add 192.168.100.1/32 peer 192.168.100.2 dev ens33
ip link set ens33 up
Сервер B:
ip addr add 192.168.100.2/32 peer 192.168.100.1 dev ens33
ip link set ens33 up
Наблюдайте нормальный пинг от сервера A к серверу B и ip addr show
вывод, содержащий эту строку:
inet 192.168.100.1 peer 192.168.100.2/32 scope global ens33
включить arp_ignore=1
с участием sysctl net.ipv4.conf.all.arp_ignore=1
на сервере A и увидите, что эхо-запросы останавливаются по истечении времени ожидания записи ARP. Через некоторое короткое время пингует возобновится на какое-то время, а затем снова закончится. Таким образом, этот процесс будет продолжаться бесконечно.
Запустить tcpdump
на сервере B и наблюдайте входящие пинги и исходящие бесконечные who-has
запросы для IP-адреса Сервера A, поступающие от Сервера B, без ответа. Иногда сервер A выдает who-has
запрос IP-адреса Сервера B получит ответ, и Сервер B временно кэширует исходный MAC-адрес, полученный из этого запроса ARP, и тогда пинги возобновятся.
Вот что происходит. Внутри ядра разница между двухточечными и стандартными широковещательными интерфейсами заключается в том, как iproute2
(и аналогичные инструменты) заполнить in_ifaddr
структура, определенная в include/linux/inetdevice.h
.
Для обычных интерфейсов это ifa_address
поле заполняется адрес локального интерфейса; для двухточечных интерфейсов ifa_address
заселяется адрес удаленного узла и ifa_local
заселяется адрес локального интерфейса.
Это нормальное и ожидаемое поведение, поскольку в старые времена любой интерфейс точка-точка сам считался подключенным удаленным устройством; соответствующий ему адрес локальной конечной точки может даже не существовать. Так что здесь ничего не сломано.
Что действительно сломано, так это то, что arp_ignore()
обработчик, определенный в net/ipv4/arp.c
косвенно использует confirm_addr_indev()
функция, определенная в net/ipv4/devinet.c
который итеративно пытается сопоставить целевой IP-адрес запроса ARP (то есть адрес локального интерфейса) с ifa_address
поле всех настроенных записей IP-адресов на интерфейсе.
Это хорошо работает на стандартных интерфейсах, поскольку их локальный IP-адрес записан в ifa_address
поле, однако с интерфейсами точка-точка он не работает, потому что вместо этого в этом поле записан IP-адрес однорангового узла.
Теперь настоящий вопрос заключается в том, действительно ли эта проблема нуждается в исправлении, поскольку уже было указано, что нет смысла использовать arp_ignore
по p2p ссылкам. Я думаю, что это так, поскольку может существовать ситуация, когда рассматриваемый хост имеет более одного интерфейса (и эти интерфейсы не являются p2p), и кто-то может включить этот материал с помощью conf.all
префикс только для того, чтобы увидеть, как его p2p-ссылки отключаются без видимой причины.
Ответ в определении:
arp_ignore -
0 - (default): reply for any local target IP address, configured
on any interface
1 - reply only if the target IP address is local address
configured on the incoming interface
2 - reply only if the target IP address is local address
configured on the incoming interface and both with the
sender's IP address are part from same subnet on this interface
3 - do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied
4-7 - reserved
8 - do not reply for all local addresses
По сути, поскольку сами двухточечные интерфейсы не имеют назначенных IP-адресов, нет «целевого IP-адреса на входящем интерфейсе». IP назначается интерфейсу моста ... не фактическому интерфейсу связи. Таким образом, ARP обрабатываться не будет.