Skip to content

mrib: re-evaluate forwarding state of known sources on membership change - #26

Open
yveming wants to merge 1 commit into
openwrt:masterfrom
yveming:mrib-refresh-on-membership
Open

yveming wants to merge 1 commit into
openwrt:masterfrom
yveming:mrib-refresh-on-membership

Conversation

@yveming

@yveming yveming commented Oct 7, 2026

Copy link
Copy Markdown

Problem

Multicast sources are only discovered via IGMPMSG_NOCACHE, i.e. when the first packet of a flow arrives on the upstream without a matching MFC entry. At that moment the MFC route is installed with the outgoing interfaces derived from the current downstream group state.

With pre-provisioned streams this goes wrong: some IPTV carriers (commonly seen with Chinese ISPs, e.g. IPTV over EPON ONTs) continuously push a set of (S,G) RTP flows towards the subscriber regardless of any join. omcproxy then installs the (S,G) route as a placeholder without outgoing interfaces long before the first downstream member subscribes.

When a client later joins the group, proxy_trigger() only updates the upstream IGMP membership via client_set() — it never re-evaluates the existing MFC entries. The pre-provisioned source therefore keeps being dropped by its placeholder route until the lifetime-based cleanup (mrib_clean()) removes it after MRIB_DEFAULT_LIFETIME (125 seconds) and the next packet re-triggers NOCACHE. A channel-zapping STB gives up within seconds, and since subscribers come and go, the placeholder is usually re-installed without members again — the affected channels may effectively never become watchable, while channels whose data only starts flowing after the join work fine.

This matches ip mroute observations on an affected Airoha AN758x EPON setup: pushed-source entries stuck with Iif only, join-triggered sources with Oifs set.

Fix

  • Extract the filter construction from mrib_notify_newsource() into mrib_filter_build().
  • Add mrib_refresh_user() to rebuild the MFC entries of all known sources of a group from the current downstream state.
  • Call it from proxy_trigger() whenever the combined downstream state of a group changed, so that joins activate forwarding for already-known sources immediately (milliseconds instead of up to 125s) and leaves retract it right away. The 125s cleanup stays in place as a fallback for sources that disappear.

Testing

  • aarch64 build (OpenWrt, musl / gcc-14), no warnings.
  • Production test: Airoha AN7583 EPON ONT, omcproxy upstream pon0.3990 (IPTV multicast VLAN) / downstream br-lan, ISP pre-pushing 4 randomly-varying channels. Before the patch those 4 channels were consistently unwatchable; after the patch the pushed-source (S,G) entries gain br-lan in ip mroute immediately on join, STB channel zapping is instant, and leaving retracts the outgoing interface.

Multicast sources are only discovered via IGMPMSG_NOCACHE, i.e. when
the first packet of a flow arrives without a matching MFC entry. With
pre-provisioned streams (e.g. IPTV carriers pushing a set of channels
regardless of subscription), such routes are installed as placeholders
without outgoing interfaces long before the first downstream member
subscribes. As a group state change only updates the upstream IGMP
membership (client_set), the placeholder is not re-evaluated and keeps
dropping the stream until the lifetime-based cleanup removes it after
MRIB_DEFAULT_LIFETIME (125s) - long after a channel-zapping STB has
given up. With subscribers cycling, affected channels may never become
watchable.

Extract the filter construction from mrib_notify_newsource() into
mrib_filter_build() and add mrib_refresh_user() to rebuild the MFC
entries of all known sources of a group. Call it from proxy_trigger()
whenever the combined downstream state of a group changed, so joins
activate forwarding immediately and leaves retract it right away.

Signed-off-by: yveming <yveming@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant