Этот вопрос почти такой же, как и более старый неотвеченный вопрос, найденныйздесьв списке рассылки ядра (спасибо Саймону Пайярду). Вот (перефразированный) обзор:
Когда хост, работающий под управлением ядра Linux, подключен к коммутатору с включенным IGMP-отслеживанием, мы имеем следующий сценарий:
- Интерфейс является членом многоадресной группы. Выполняются (присоединяются) отчеты.
- Произошел сбой связи (например, отключение кабеля).
- Коммутатор очищает многоадресное членство для этого порта.
- Связь восстанавливается (например, кабель снова подключается).
- На этом этапе ядро ждет запроса от коммутатора, прежде чем отправить новый запрос на присоединение к IGMP.
- Это означает, что приложение пропускает пакеты между моментом восстановления соединения и запланированным общим запросом (значение по умолчанию в RFC: 125 секунд).
Кажется, это указывает на то, что ядро Linux не заботится о повторной отправке joins после повторного подключения. Может ли кто-нибудь с более глубоким знанием спецификации IGMP подтвердить, должны ли rejoins повторно отправляться после повторного подключения?
Является ли задачей приложения пользовательского уровня проверку наличия сбоев в соединении и повторную отправку запросов на присоединение к коммутатору при повторном подключении?
Интересно, что ядро Windows, похоже, заботится о повторной отправке запросов на присоединение, когда соединения восстанавливаются после сбоя.
решение1
Логично, я так думаю. Потому что я вижу это в коде Linux IPv6. ИЗапрос на предложение (ЗП)говорится, что отслеживание IPv6 MLD должно быть очень похоже на отслеживание IPv4 IGMP.
На практике этот код addrconf был добавлен для ipv6 - где ядро поддерживает DAD и RS/RA. Я не удивлюсь, если в текущих версиях ядра нет эквивалента для ipv4.
} else if (event == NETDEV_CHANGE) {
if (!addrconf_link_ready(dev)) {
/* device is still not ready. */
rt6_sync_down_dev(dev, event);
break;
}
if (!IS_ERR_OR_NULL(idev)) {
if (idev->if_flags & IF_READY) {
/* device is already configured -
* but resend MLD reports, we might
* have roamed and need to update
* multicast snooping switches
*/
ipv6_mc_up(idev);
change_info = ptr;
if (change_info->flags_changed & IFF_NOARP)
addrconf_dad_run(idev, true);
rt6_sync_up(dev, RTNH_F_LINKDOWN);
break;
}
idev->if_flags |= IF_READY;
}
pr_info("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready\n",
dev->name);
https://elixir.bootlin.com/linux/v5.1/source/net/ipv6/addrconf.c#L3546