troglobit / pimd

PIM-SM/SSM multicast routing for UNIX and Linux
http://troglobit.com/projects/pimd/
BSD 3-Clause "New" or "Revised" License
200 stars 90 forks source link

Add support for IGMP v3 Membership Reports #26

Closed troglobit closed 10 years ago

troglobit commented 10 years ago

Gil Beniamini reports (via mail) having patched up pimd with basic IGMP v3 support.

Issue which lead to investigation: In one setup multicast stream would start and work for about 5 minutes and stop forever (until pimd is restarted), apparently I found out that PIMd neighbor which was WinXP started with sending iGMPv2 membership_report(==join), but after 2 reports switched to iGMPv3 MEMBERSHIP_REPORT which is not handled by pimd v2.1.8, and so after timeout delete_leaf() is called and receive of multicast by that neighbor is stopped!

Further findings: pimd v2.1.8 did not support iGMP v3, and if neighbor "node" was sending MEMBERSHIP_REPORT in iGMPv3 ((even if not SSM) for PIM-SM with EXCLUDE "source"), it was not received by pimd and MCAST tree failed to be created as expected => need to support iGMPv3 in iGMPv2 compatibility mode (our patch marked with GIL_SUPPORT_IGMPV3, related files vif.c & igmp.c).

ROOT-CAUSE: Why did our neighbor "node" switch to iGMPv3 after ~2 minutes? In our case on our subnet there is an ADSL-router who sends once every 125sec iGMPv3-Query. When our "pimd" comes up it also sends one iGMPv2-Query and cause our listen/Mcast-Receiver PC to switch to iGMPv2, but once our "pimd" receive iGMPv3-Query from the neighbor ADSL-router it replies but also stop sending it's iGMPv2 Query. After timeout (260sec from last iGMPv2 MEMBERSHIP_REPORT) and when only the ADSL-router V3 Queries are on our subnet, it cause the neighbor Mcast-Receiver PC to switch to iGMPv3 MEMBERSHIP_REPORTS!

This is the root cause to add support for accepting IGMPv3 MEMBERSHIP_REPORT!

I have created a small patch, to enable “pimd” receive iGMPv3 messages, and also handle iGMPv3_MEMBERSHIP_REPORTS with source-exclude to trigger the correct accept_group_report() / accept_leave_message().

Now the above setup is perfectly working.