test: mdns: Add test for mDNS reflector

This commit is contained in:
Mattias Walström
2026-01-23 13:05:34 +01:00
parent 0d55ea46e0
commit e401c5a080
6 changed files with 257 additions and 0 deletions
+3
View File
@@ -4,3 +4,6 @@
- name: mDNS allow/deny interfaces
case: mdns_allow_deny/test.py
- name: mDNS reflector
case: mdns_reflector/test.py
+1
View File
@@ -0,0 +1 @@
test.adoc
@@ -0,0 +1,29 @@
=== mDNS reflector
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/services/mdns/mdns_reflector]
==== Description
Verify the mDNS reflector functionality. The reflector forwards mDNS
requests and responses between different network interfaces, allowing
service discovery across network segments.
We verify operation with two scenarios:
1. Reflector enabled: mDNS traffic from host:data1 SHOULD be reflected
to host:data2 and host:data3
2. Reflector disabled: mDNS traffic from host:data1 should NOT be
reflected to host:data2 and host:data3
==== Topology
image::topology.svg[mDNS reflector topology, align=center, scaledwidth=75%]
==== Sequence
. Set up topology and attach to target DUT
. Configure device interfaces and enable mDNS
. Verify mDNS from host:data1 is reflected to host:data2 and host:data3
. Verify mDNS from host:data1 is not reflected after disabling reflector
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""mDNS reflector
Verify the mDNS reflector functionality. The reflector forwards mDNS
requests and responses between different network interfaces, allowing
service discovery across network segments.
We verify operation with two scenarios:
1. Reflector enabled: mDNS traffic from host:data1 SHOULD be reflected
to host:data2 and host:data3
2. Reflector disabled: mDNS traffic from host:data1 should NOT be
reflected to host:data2 and host:data3
"""
import infamy
from time import sleep
UNIQUE_MARKER = "infix-reflector-test"
def mdns_reflect_test():
"""Send mDNS from host:data1, check if it's reflected to host:data2/data3"""
snif2 = infamy.Sniffer(hdata2, "port 5353")
snif3 = infamy.Sniffer(hdata3, "port 5353")
with snif2, snif3:
# Send mDNS query for "infix-reflector-test.local" (raw DNS packet)
hdata1.runsh(
"echo -ne '\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00"
"\\x14infix-reflector-test\\x05local\\x00\\x00\\xff\\x00\\x01' | "
"socat - UDP4-DATAGRAM:224.0.0.251:5353,bind=10.0.1.2"
)
sleep(5)
out2 = snif2.packets()
out3 = snif3.packets()
return (UNIQUE_MARKER in out2, UNIQUE_MARKER in out3)
def disable_reflector():
"""Disable mDNS reflector"""
dut.put_config_dict("infix-services", {
"mdns": {
"reflector": {
"enabled": False
}
}
})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
dut = env.attach("dut", "mgmt")
_, ddata1 = env.ltop.xlate("dut", "data1")
_, ddata2 = env.ltop.xlate("dut", "data2")
_, ddata3 = env.ltop.xlate("dut", "data3")
_, hdata1 = env.ltop.xlate("host", "data1")
_, hdata2 = env.ltop.xlate("host", "data2")
_, hdata3 = env.ltop.xlate("host", "data3")
with test.step("Configure device interfaces and enable mDNS"):
dut.put_config_dicts(
{
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": ddata1,
"enabled": True,
"ipv4": {
"address": [{
"ip": "10.0.1.1",
"prefix-length": 24
}]
}
}, {
"name": ddata2,
"enabled": True,
"ipv4": {
"address": [{
"ip": "10.0.2.1",
"prefix-length": 24
}]
}
}, {
"name": ddata3,
"enabled": True,
"ipv4": {
"address": [{
"ip": "10.0.3.1",
"prefix-length": 24
}]
}
}]
}
},
"infix-services": {
"mdns": {
"enabled": True,
"reflector": {
"enabled": True
}
}
}
}
)
with infamy.IsolatedMacVlan(hdata1) as hdata1, \
infamy.IsolatedMacVlan(hdata2) as hdata2, \
infamy.IsolatedMacVlan(hdata3) as hdata3:
hdata1.addip("10.0.1.2")
hdata2.addip("10.0.2.2")
hdata3.addip("10.0.3.2")
with test.step("Verify mDNS from host:data1 is reflected to host:data2 and host:data3"):
hdata2.must_receive("port 5353")
hdata3.must_receive("port 5353")
reflected = mdns_reflect_test()
if reflected != (True, True):
test.fail(f"Expected reflection (True, True), got {reflected}")
with test.step("Verify mDNS from host:data1 is not reflected after disabling reflector"):
disable_reflector()
hdata2.must_receive("port 5353")
hdata3.must_receive("port 5353")
reflected = mdns_reflect_test()
if reflected != (False, False):
test.fail(f"Expected no reflection (False, False), got {reflected}")
test.succeed()
@@ -0,0 +1,26 @@
graph "1x4" {
layout="neato";
overlap="false";
esep="+80";
node [shape=record, fontname="DejaVu Sans Mono, Book"];
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
host [
label="host | { <mgmt> mgmt | <data1> data1 | <data2> data2 | <data3> data3 }",
pos="0,12!",
requires="controller",
];
dut [
label="{ <mgmt> mgmt | <data1> data1 | <data2> data2 | <data3> data3 } | dut \n\n10.0.X.1/24",
pos="10,12!",
requires="infix",
];
host:mgmt -- dut:mgmt [requires="mgmt", color="lightgray"]
host:data1 -- dut:data1 [color=black, fontcolor=black, taillabel="10.0.1.2/24"]
host:data2 -- dut:data2 [color=black, fontcolor=black, taillabel="10.0.2.2/24"]
host:data3 -- dut:data3 [color=black, fontcolor=black, taillabel="10.0.3.2/24"]
}
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Title: 1x4 Pages: 1 -->
<svg width="481pt" height="101pt"
viewBox="0.00 0.00 481.03 101.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 97)">
<title>1x4</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-97 477.03,-97 477.03,4 -4,4"/>
<!-- host -->
<g id="node1" class="node">
<title>host</title>
<polygon fill="none" stroke="black" points="0,-0.5 0,-92.5 108,-92.5 108,-0.5 0,-0.5"/>
<text text-anchor="middle" x="25" y="-42.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">host</text>
<polyline fill="none" stroke="black" points="50,-0.5 50,-92.5 "/>
<text text-anchor="middle" x="79" y="-77.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="50,-69.5 108,-69.5 "/>
<text text-anchor="middle" x="79" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
<polyline fill="none" stroke="black" points="50,-46.5 108,-46.5 "/>
<text text-anchor="middle" x="79" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
<polyline fill="none" stroke="black" points="50,-23.5 108,-23.5 "/>
<text text-anchor="middle" x="79" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data3</text>
</g>
<!-- dut -->
<g id="node2" class="node">
<title>dut</title>
<polygon fill="none" stroke="black" points="308.03,-0.5 308.03,-92.5 473.03,-92.5 473.03,-0.5 308.03,-0.5"/>
<text text-anchor="middle" x="337.03" y="-77.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="308.03,-69.5 366.03,-69.5 "/>
<text text-anchor="middle" x="337.03" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
<polyline fill="none" stroke="black" points="308.03,-46.5 366.03,-46.5 "/>
<text text-anchor="middle" x="337.03" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
<polyline fill="none" stroke="black" points="308.03,-23.5 366.03,-23.5 "/>
<text text-anchor="middle" x="337.03" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data3</text>
<polyline fill="none" stroke="black" points="366.03,-0.5 366.03,-92.5 "/>
<text text-anchor="middle" x="419.53" y="-58.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">dut </text>
<text text-anchor="middle" x="419.53" y="-27.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">10.0.X.1/24</text>
</g>
<!-- host&#45;&#45;dut -->
<g id="edge1" class="edge">
<title>host:mgmt&#45;&#45;dut:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M108,-81.5C108,-81.5 307.53,-81.5 307.53,-81.5"/>
</g>
<!-- host&#45;&#45;dut -->
<g id="edge2" class="edge">
<title>host:data1&#45;&#45;dut:data1</title>
<path fill="none" stroke="black" stroke-width="2" d="M108,-58.5C108,-58.5 307.53,-58.5 307.53,-58.5"/>
<text text-anchor="middle" x="149" y="-62.3" font-family="DejaVu Serif, Book" font-size="14.00">10.0.1.2/24</text>
</g>
<!-- host&#45;&#45;dut -->
<g id="edge3" class="edge">
<title>host:data2&#45;&#45;dut:data2</title>
<path fill="none" stroke="black" stroke-width="2" d="M108,-34.5C108,-34.5 307.53,-34.5 307.53,-34.5"/>
<text text-anchor="middle" x="149" y="-38.3" font-family="DejaVu Serif, Book" font-size="14.00">10.0.2.2/24</text>
</g>
<!-- host&#45;&#45;dut -->
<g id="edge4" class="edge">
<title>host:data3&#45;&#45;dut:data3</title>
<path fill="none" stroke="black" stroke-width="2" d="M108,-11.5C108,-11.5 307.53,-11.5 307.53,-11.5"/>
<text text-anchor="middle" x="149" y="-15.3" font-family="DejaVu Serif, Book" font-size="14.00">10.0.3.2/24</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB