Используйте ip route add для добавления многоадресных маршрутов к нескольким интерфейсам.

TLDR: есть ли способ использовать "ip route" для добавления многоадресных маршрутов для нескольких сетевых карт?

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

Для этого программа создает два сокета. Каждый из них привязан к одному из IP-адресов отдельной NICS. Затем этот сокет присоединяется к группе многоадресной рассылки, которая существует в этой сети, например, сокет 1 связан с группой 192.168.0.2 и присоединяется к группе многоадресной рассылки 233.255.10.1, тогда как сокет 2 связан с группой 10.57.31.2 и присоединяется к группе многоадресной рассылки 239.255.100.1.

В настоящее время мы используем скрипт bash (ядро Linux 3.14.39) для установки многоадресных маршрутов на двух сетевых интерфейсах с использованием маршрута, например

route add -net 224.0.0.0 netmask 240.0.0.0 eth0
route add -net 224.0.0.0 netmask 240.0.0.0 eth1

и проверено по маршруту -n

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth0
224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth1

Я недавно прочитал, что маршрут устарел / устарел, и что вместо этого мы должны использовать ip route, например

ip route add 224.0.0.0/4 dev eth0
ip route add 224.0.0.0/4 dev eth1

К сожалению, второй вызов завершается с ошибкой "ответы RTNETLINK: файл существует", и, конечно, второй маршрут не отображается после этих вызовов.

Есть ли способ использовать IP-маршрут для добавления многоадресных маршрутов для нескольких сетевых карт?

Я могу использовать /8 в качестве сетевой маски? например

ip route add 233.0.0.0/8 dev eth0

а также

ip route add 239.0.0.0/8 dev eth1

но это проблематично, так как скрипт, который делает это, не знает, какой адрес многоадресной рассылки связан с каким устройством, и его не всегда гарантированно будет одинаковым в зависимости от конфигурации системы. Используя мой первый пример добавления маршрута, это не проблема.

ОБНОВЛЕНИЯ Благодаря расширенному обсуждению с @Ron Maupin, я понял, что ошибка была в нашем коде. Мы не настраивали интерфейс для многоадресной рассылки с IP_MULTICAST_IF. После того, как я добавил вызов setsockopt для установки IP_MULTICAST_IF, мне больше не нужно было добавлять таблицы маршрутизации.

struct in_addr multicastInterface = {};
multicastInterface.s_addr = interfaceAddressNetworkOrder;

// Set which outgoing interface to use
int result = setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)&multicastInterface, sizeof(struct in_addr));

1 ответ

Решение

То, что у вас есть многоадресная рассылка, проходящая через ваш Linux-сервер с использованием одноадресной маршрутизации, является комбинацией нескольких счастливых обстоятельств.

Многоадресная маршрутизация отличается от одноадресной маршрутизации. Одноадресная маршрутизация основана на том, что трафик отправляется на один адрес, а многоадресный трафик отправляется на групповой адрес, представляющий хосты, которые хотят подписаться на многоадресную группу.

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

Современные коммутаторы будут использовать IGMP Snooping, чтобы определить, какие порты коммутатора имеют узлы, запрашивающие присоединение к определенной группе многоадресной рассылки, и они будут отправлять трафик только для этой группы многоадресной рассылки на порты коммутатора, где узлы запросили присоединение к группе многоадресной рассылки.

Сам по себе Linux не поддерживает многоадресную маршрутизацию, и вам нужно что-то добавить на устройство Linux для поддержки многоадресной маршрутизации. Обратитесь к диаграмме ниже:

Когда источник многоадресной рассылки начинает отправлять многоадресный трафик для группы многоадресной рассылки, коммутатор, вероятно, не видел никаких запросов IGMP о присоединении к группе многоадресной рассылки, поэтому многоадресный трафик для этой группы не идет никуда.

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

Если ПК на другой стороне маршрутизатора Linux хочет присоединиться к группе многоадресной рассылки, это не повезло, поскольку многоадресный трафик не передается на ту сторону маршрутизатора Linux. Маршрутизатор Linux даже не присоединился к группе многоадресной рассылки, поэтому коммутатор никогда не отправляет ему многоадресный трафик.

Когда вы запускаете многоадресную маршрутизацию на маршрутизаторе, маршрутизатор ответит на запрос IGMP хоста, и коммутатор узнает, что это многоадресный маршрутизатор, и отправит многоадресный трафик на порт коммутатора, к которому подключен многоадресный маршрутизатор. Проще говоря, маршрутизатор не будет отправлять многоадресный трафик на другой интерфейс, если на другом интерфейсе не будет активного получателя (это зависит от версии многоадресной рассылки, например, PIM-DM начнет отправку, но отключится, если не будут замечены запросы IGMP),

Если на маршрутизаторе включена многоадресная маршрутизация, ПК, подключенный к другому интерфейсу, отправит сообщение IGMP Join, и маршрутизатор Linux начнет отправку многоадресного трафика для запрошенной группы на интерфейс. Коммутатор отслеживает запрос и отправляет многоадресный трафик на порт коммутатора, к которому подключен ПК, который запросил присоединение к многоадресной группе.

Это становится более сложным, если вам нужно маршрутизировать через несколько маршрутизаторов. IGMP используется между хостами и локальным многоадресным маршрутизатором. PIM (или какой-либо другой протокол многоадресной маршрутизации) используется между многоадресными маршрутизаторами.

Все это предотвращает отправку многоадресного трафика туда, где он не нужен.

В Linux есть дополнения, помогающие правильно обрабатывать IGMP и многоадресную маршрутизацию.

Чтобы добавить несколько маршрутов к цели, вы можете добавить первый, как вы это сделали, используя ip route add <address> dev <interface>. Чтобы добавить второй, используйте ip route append <address> dev <interface2>.

Для ipv4 вам понадобится что-то для управления IGMP или любого другого протокола управления многоадресной рассылкой, который вы используете. Для ipv6 это встроено в протокол icmpv6, поэтому я понимаю, что Linux должен справиться с этим из коробки за вас.

Другие вопросы по тегам