mDNS reflection across vlans while using PPSK/single SSID in 24.10

Until recently I was running 23.05 on my Netgear R7800. I decided to re-build the router on 24.10 and make the transition to DSA, which has made looking for examples/instructions a bit tricky because most of what I'm finding is now outdated.

I've got a fairly typical vlan setup (lan, iot, guest). Initially I set up seperate SSIDs associated with each network but then I switched to a single SSID with Private PSKs and assign the vlan dynamically via the UCI network config for wifi-vlan/wifi-station. Overall it's working as expected.

My problem comes with trying to set up mDNS reflection between iot and lan using avahi-dbus-daemon. I can see mDNS traffic when connected via ethernet to lan or iot, but over wifi it refused to work. I finally narrowed it down to something connected to the dynamic wifi vlan assignment. If I assign a key to the AP interface directly and it's associated to network 'lan', I can join and see iot mDNS traffic. If I use one of the wifi-station psks, I join the correct vlan but do not see any mDNS traffic, even on the iot vlan.

It seems like both the wifi-vlans functionality and 24.10 have limited documentation at this point, so I'm hoping someone might know what I'm doing wrong here - or if this is just a limitation and I need to switch back to multiple SSIDs per vlan.


Relevant installed packages: wpad-mbedtls hostapd-utils avahi-dbus-daemon avahi-utils

ubus call system board

{
        "kernel": "6.6.73",
        "hostname": "OpenWrt",
        "system": "ARMv7 Processor rev 0 (v7l)",
        "model": "Netgear Nighthawk X4S R7800",
        "board_name": "netgear,r7800",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "24.10.0",
                "revision": "r28427-6df0e3d02a",
                "target": "ipq806x/generic",
                "description": "OpenWrt 24.10.0 r28427-6df0e3d02a",
                "builddate": "1738624177"
        }
}

/etc/avahi/avahi-daemon.conf

[server]
#host-name=foo
#domain-name=lan
use-ipv4=yes
use-ipv6=yes
allow-interfaces=br-lan.20,br-lan.30
#deny-interfaces=br-lan.40
check-response-ttl=no
use-iff-running=no
enable-dbus=yes

[publish]
add-service-cookie=yes
publish-addresses=yes
publish-hinfo=no
publish-workstation=no
publish-domain=yes

[reflector]
enable-reflector=yes
reflect-ipv=no

[rlimits]
#rlimit-as=
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=30
rlimit-stack=4194304
rlimit-nproc=3

/etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'XXXX:XXXX:XXXX::/48'
        option packet_steering '1'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'lan1'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'
        option stp '1'
        option igmp_snooping '1'

config interface 'lan'
        option device 'br-lan.20'
        option proto 'static'
        option ipaddr '192.168.20.1'
        option netmask '255.255.255.0'
        option ip6assign '64'
        list ip6class 'wan6lan'
        list ip6class 'local'

config interface 'wan'
        option device 'wan'
        option proto 'dhcp'
        option peerdns '0'

config interface 'wan6'
        option device 'wan'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option reqprefix 'no'
        option norelease '1'
        option peerdns '0'

config bridge-vlan
        option device 'br-lan'
        option vlan '20'
        list ports 'lan1:u*'
        list ports 'lan2:u*'

config bridge-vlan
        option device 'br-lan'
        option vlan '30'
        list ports 'lan3:u*'
        list ports 'lan4:u*'

config bridge-vlan
        option device 'br-lan'
        option vlan '40'

config interface 'guest'
        option proto 'static'
        option device 'br-lan.40'
        option ipaddr '192.168.40.1'
        option netmask '255.255.255.0'
        option ip6assign '64'
        option ip6hint '40'
        list ip6class 'wan6guest'
        list ip6class 'local'

config interface 'iot'
        option proto 'static'
        option device 'br-lan.30'
        option ipaddr '192.168.30.1'
        option netmask '255.255.255.0'
        option ip6assign '64'
        option ip6hint '30'
        list ip6class 'wan6iot'
        list ip6class 'local'

config device
        option type 'macvlan'
        option ifname 'wan'
        option mode 'vepa'
        option name 'vwan1'
        option macaddr 'XX:XX:XX:XX:XX:XX'

config interface 'wan6lan'
        option proto 'dhcpv6'
        option device 'vwan1'
        option reqaddress 'try'
        option reqprefix '64'
        option norelease '1'
        option peerdns '0'

config device
        option type 'macvlan'
        option ifname 'wan'
        option mode 'vepa'
        option name 'vwan2'
        option macaddr 'XX:XX:XX:XX:XX:XX'

config interface 'wan6iot'
        option proto 'dhcpv6'
        option device 'vwan2'
        option reqaddress 'try'
        option reqprefix '64'
        option norelease '1'
        option peerdns '0'

config device
        option type 'macvlan'
        option ifname 'wan'
        option mode 'vepa'
        option name 'vwan3'
        option macaddr 'XX:XX:XX:XX:XX:XX'

config interface 'wan6guest'
        option proto 'dhcpv6'
        option device 'vwan3'
        option reqaddress 'try'
        option reqprefix '64'
        option norelease '1'
        option peerdns '0'

/etc/config/wireless

config wifi-device 'radio0'
        option type 'mac80211'
        option path 'soc/1b700000.pci/pci0001:00/0001:00:00.0/0001:01:00.0'
        option band '2g'
        option channel '1'
        option cell_density '0'
        option htmode 'HT20'
        option legacy_rates '1'

config wifi-device 'radio1'
        option type 'mac80211'
        option path 'soc/1b500000.pci/pci0000:00/0000:00:00.0/0000:01:00.0'
        option band '5g'
        option channel '36'
        option htmode 'VHT80'
        option cell_density '0'

config wifi-iface 'wifinet0'
        option device 'radio0'
        option network 'guest'
        option mode 'ap'
        option ssid 'Home Wifi'
        option encryption 'psk2'
        option ieee80211r '1'
        option ft_over_ds '0'
        option ft_psk_generate_local '1'
        option ieee80211k '1'

config wifi-iface 'wifinet1'
        option device 'radio1'
        option network 'guest'
        option mode 'ap'
        option ssid 'Home Wifi'
        option encryption 'psk2'
        option ieee80211r '1'
        option ft_over_ds '0'
        option ft_psk_generate_local '1'
        option ieee80211k '1'

config wifi-iface 'wifinet2'
        option device 'radio0'
        option mode 'ap'
        option ssid 'Home Wifi (Legacy)'
        option encryption 'psk-mixed'
        option key 'XXXXXXXXX'
        option network 'iot'

config wifi-vlan
        option network 'lan'
        option vid '20'
        option name 'lan'

config wifi-vlan
        option network 'iot'
        option vid '30'
        option name 'iot'

config wifi-vlan
        option network 'guest'
        option vid '40'
        option name 'guest'

config wifi-station
        option vid '20'
        option key 'AAAAAAAAA'

config wifi-station
        option vid '30'
        option key 'BBBBBBBBB'

config wifi-station
        option vid '40'
        option key 'CCCCCCCCC'

config wifi-iface 'wifinet3'
	option device 'radio1'
	option mode 'ap'
	option ssid 'Home Wifi (LAN)'
	option encryption 'psk2'
	option key 'YYYYYYYYY'
	option ieee80211r '1'
	option ft_over_ds '0'
	option ft_psk_generate_local '1'
	option ieee80211k '1'
	option network 'lan'

Notes on /etc/config/wireless:

  • I did not specify option key on wifinet0/wifinet1 - the thought was to only allow joining with one of the vlan aware ppsks defined in wifi-station. However, joining with one of these keys is where mDNS reflection fails to work correctly.
  • If I set a key and network 'lan' on wifinet0/wifinet1, then I can join the lan and see mDNS packets from iot. i.e. using seperate wifi APs per-vlan works - it just defeats the purpose of the wifi-vlan tagging. (I created wifinet3 to serve the the same purpose for testing; it's temporary)
  • wifinet0/wifinet1 both have option network 'guest' set. This is intentional, and changing them to lan/iot does not affect mDNS behavior. The AP needs an option network defined even though the wifi-vlan will change it. If anything goes wrong, I'd rather the device get dumped into guest rather than lan.

/etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'
        list network 'wan6'
        list network 'wan6lan'
        list network 'wan6iot'
        list network 'wan6guest'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'iot'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'iot'

config zone
        option name 'guest'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'guest'

config forwarding
        option src 'lan'
        option dest 'wan'

config forwarding
        option src 'lan'
        option dest 'iot'

config forwarding
        option src 'iot'
        option dest 'wan'

config forwarding
        option src 'guest'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config rule
        option name 'Allow-Router-Admin-from-LAN'
        list proto 'tcp'
        option src 'lan'
        option dest_port '22 80 443'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCP+DHCPv6-LAN'
        list proto 'udp'
        option src 'lan'
        option src_port '68 546'
        option dest_port '67 547'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCP+DHCPv6-IOT'
        list proto 'udp'
        option src 'iot'
        option src_port '68 546'
        option dest_port '67 547'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCP+DHCPv6-Guest'
        list proto 'udp'
        option src 'guest'
        option src_port '68 546'
        option dest_port '67 547'
        option target 'ACCEPT'

config rule
        option name 'Allow-DNS-LAN'
        option src 'lan'
        option dest_port '53'
        option target 'ACCEPT'

config rule
        option name 'Allow-DNS-IOT'
        option src 'iot'
        option dest_port '53'
        option target 'ACCEPT'

config rule
        option name 'Allow-DNS-Guest'
        option src 'guest'
        option dest_port '53'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-SLAAC-IOT'
        option src 'iot'
        option proto 'icmp'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'
        list icmp_type 'neighbour-advertisement'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'router-solicitation'

config rule
        option name 'Allow-ICMPv6-SLAAC-Guest'
        option src 'guest'
        option proto 'icmp'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'
        list icmp_type 'neighbour-advertisement'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'router-solicitation'

config rule
        option name 'Allow-mDNS-LAN'
        list proto 'udp'
        option src 'lan'
        option src_port '5353'
        option dest_port '5353'
        option target 'ACCEPT'
        list dest_ip '224.0.0.0/24'
        list dest_ip 'ff02::fb'

config rule
        option name 'Allow-mDNS-IOT'
        list proto 'udp'
        option src 'iot'
        option src_port '5353'
        option dest_port '5353'
        option target 'ACCEPT'
        list dest_ip '224.0.0.0/24'
        list dest_ip 'ff02::fb'

config rule
        option name 'Allow-Plex-IOT-TVs-Only'
        list proto 'tcp'
        option src 'iot'
        option dest 'lan'
        option dest_port '32400'
        option target 'ACCEPT'
        list src_mac 'XX:XX:XX:XX:XX:XX'
        list src_mac 'XX:XX:XX:XX:XX:XX'
        list dest_ip '192.168.20.3'

config redirect
        option name 'Plex'
        option src 'wan'
        option dest 'lan'
        option src_dport '32400'
        option dest_ip '192.168.20.3'
        option dest_port '32400'
        option target 'DNAT'