PIM-SM IPv6 issues?

I’ve been exploring Multicast Querier functionality that is compatible with VLAN tagged interfaces, and that led me to playing around with PIM-SM on RouterOS. My observations are that PIM-SM with IPv4 looks reasonably good, but PIM-SM with IPv6 doesn’t do what I’d expect.

At this point I should probably highlight that I don’t consider myself an expert in multicast, so I’m looking for comment on whether I’m missing something or whether there is in fact a problem?

The issues I found are:

  • It doesn’t appear that any (IPv6) MLD Queries are sent out at all? I see an MLD Report sent from the router in the packet capture, but I was expecting to see a query asking other hosts which groups they are members of.
  • The PIMv2 Hello messages that are sent over IPv6 are flagged in Wireshark as having an incorrect checksum.
  • If I use GMP (“/routing/gmp”) to add an IPv4 group and an IPv6 group to the interface, and ping the group addresses from a host on the same segment, I see only the IPv4 group listed in the CLI under “/routing/pimsm/uib-g print” & “/routing/pimsm/uib-sg print”; the IPv6 group is absent. (This may be related to the previous issues?) NB: This step isn’t included in my script below.
  • The equivalent tabs in Webfig (i.e. Routing → PIM SM → UIB G & Routing → PIM SM → UIB SG) don’t show any IPv4 or IPv6 information.
  • It would be nice if there was the ability to configure whether IGMP/MLD queries are sent out, or PIM messages, or both? (FYI This was a useful feature of the ROS6 implementation.)

I’d be grateful if anyone could replicate my testing to confirm if you see the same issues? To make it easy I’ve written a script that creates some configuration, runs a 3 minute packet capture and then reverts everything back to how it was:

:onerror e in={
	# Create bridge with no member ports for testing
	:put "Creating bridge for testing";
	/interface/bridge add name=bridge_temp;

	# Add an IPv4 address
	:put "Adding IPv4 address to bridge";
	/ip/address add address=192.168.25.1/24 interface=bridge_temp;

	# Verify that interface has operational IPv4 and IPv6 addresses
	:put "Waiting for link-local IPv6 address to be added to bridge";
	:local ipv4address;
	:local ipv6address;
	:for i from=1 to=5 do={
		:if ([:typeof $ipv4address]!="str" || [:typeof $ipv6address]!="str") do={
			:delay 1;

			:if ([:typeof $ipv4address]="nothing") do={
				:set ipv4address ([/ip/address print as-value where interface=bridge_temp]->0->"address");
			};
			:if ([:typeof $ipv6address]="nothing") do={
				:set ipv6address ([/ipv6/address print as-value where interface=bridge_temp]->0->"address");
			};
		};
	};
	:if ([:typeof $ipv4address]="nothing" || [:typeof $ipv6address]="nothing") do={
		error "IPv4 or IPv6 address not assigned";
	};
	:put "Bridge has IPv4 address: $ipv4address";
	:put "Bridge has IPv6 address: $ipv6address";

	# Save original sniffer settings
	:local sniffersettings [/tool/sniffer print as-value];

	:onerror e in={
		# Run packet capture
		:put "Starting packet capture";
		/tool/sniffer set file-name="" memory-limit=100KiB memory-scroll=no only-headers=no streaming-enabled=no;
		/tool/sniffer start interface=bridge_temp;

		# Create PIM-SM instances for IPv4 and IPv6
		:put "Configuring PIM-SM";
		/routing/pimsm/instance add name=pimsm_temp4 afi=ipv4;
		/routing/pimsm/instance add name=pimsm_temp6 afi=ipv6;
		/routing/pimsm/interface-template add instance=pimsm_temp4 interfaces=bridge_temp;
		/routing/pimsm/interface-template add instance=pimsm_temp6 interfaces=bridge_temp;

		:put "Waiting for 3 minutes...";
		:delay 180;

		:put "Stopping packet capture";
		/tool/sniffer stop;
		/tool/sniffer save file-name=pim_test.pcap;
	} do={
		:put $e;
		/tool/sniffer stop;
	};

	# Restore original sniffer settings
	:put "Restoring original sniffer settings";
	:local restoresniffercommand "/tool/sniffer set";
	:foreach k,v in=$sniffersettings do={
		:if ($k!="running") do={
			:if ([:typeof $v]="bool") do={
				:if ($v) do={
					:set v "yes";
				} else={
					:set v "no";
				};
			};
			:set restoresniffercommand "$restoresniffercommand $k=\"$v\"";
		};
	};
	#:put $restoresniffercommand;
	[:parse $restoresniffercommand];
} do={
	:put $e;
};

# Clean-up
:put "Removing test settings";
/routing/pimsm/interface-template remove [find instance=pimsm_temp4 or instance=pimsm_temp6];
/routing/pimsm/instance remove [find name=pimsm_temp4 or name=pimsm_temp6];
/ip/address remove [find interface=bridge_temp];
/interface/bridge remove [find name=bridge_temp];

:put "Remember to delete script and PCAP file from router when finished";