この質問は、以前に見つかった未回答の質問とほぼ同じです。ここカーネルのメーリング リストで (Simon Paillard 氏による)。要約すると次のようになります:
Linux カーネルを実行しているホストが IGMP スヌーピングが有効になっているスイッチに接続されると、次のシナリオが発生します。
- インターフェイスはマルチキャスト グループのメンバーです。(参加) レポートが実行されます。
- リンク障害が発生します(例:ケーブルの切断)。
- スイッチはそのポートのマルチキャスト メンバーシップをフラッシュします。
- リンクが復旧します(例:ケーブルが再接続されます)。
- この時点で、カーネルは新しい IGMP 参加メンバーシップ要求を送信する前に、スイッチからのクエリを待機します。
- これは、リンクが復旧してから次にスケジュールされた一般クエリまでの間に、アプリケーションがパケットを失っていることを意味します (RFC のデフォルト値: 125 秒)。
これは、Linux カーネルが再接続後の参加の再送信を処理しないことを示しているようです。IGMP 仕様に詳しい方は、再接続時に再参加が再送信されることになっているかどうかを確認できますか?
リンク障害をチェックし、再接続時にスイッチに参加要求を再発行するのは、ユーザー レベルのアプリケーションの役割ですか?
興味深いことに、Windows カーネルは、リンクがダウンした後に復旧したときに、参加要求の再送信を処理するようです。
答え1
論理的にはそうだと思います。Linux IPv6コードでそれがわかるからです。そしてRFCIPv6 MLD スヌーピングは IPv4 IGMP スヌーピングと非常によく似ていると言われています。
実際には、この addrconf コードは、カーネルが DAD と RS/RA をサポートする ipv6 用に追加されました。現在のカーネル バージョンで 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