diff --git a/test/case/services/mdns/all.yaml b/test/case/services/mdns/all.yaml index 79c69f2c..f1932d02 100644 --- a/test/case/services/mdns/all.yaml +++ b/test/case/services/mdns/all.yaml @@ -4,3 +4,6 @@ - name: mDNS allow/deny interfaces case: mdns_allow_deny/test.py + +- name: mDNS reflector + case: mdns_reflector/test.py diff --git a/test/case/services/mdns/mdns_reflector/Readme.adoc b/test/case/services/mdns/mdns_reflector/Readme.adoc new file mode 120000 index 00000000..ae32c841 --- /dev/null +++ b/test/case/services/mdns/mdns_reflector/Readme.adoc @@ -0,0 +1 @@ +test.adoc \ No newline at end of file diff --git a/test/case/services/mdns/mdns_reflector/test.adoc b/test/case/services/mdns/mdns_reflector/test.adoc new file mode 100644 index 00000000..4937cd74 --- /dev/null +++ b/test/case/services/mdns/mdns_reflector/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 + + diff --git a/test/case/services/mdns/mdns_reflector/test.py b/test/case/services/mdns/mdns_reflector/test.py new file mode 100755 index 00000000..65d38764 --- /dev/null +++ b/test/case/services/mdns/mdns_reflector/test.py @@ -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() diff --git a/test/case/services/mdns/mdns_reflector/topology.dot b/test/case/services/mdns/mdns_reflector/topology.dot new file mode 100644 index 00000000..4138b9b6 --- /dev/null +++ b/test/case/services/mdns/mdns_reflector/topology.dot @@ -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 | data1 | data2 | data3 }", + pos="0,12!", + requires="controller", + ]; + + dut [ + label="{ mgmt | data1 | data2 | 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"] +} diff --git a/test/case/services/mdns/mdns_reflector/topology.svg b/test/case/services/mdns/mdns_reflector/topology.svg new file mode 100644 index 00000000..0c0344b1 --- /dev/null +++ b/test/case/services/mdns/mdns_reflector/topology.svg @@ -0,0 +1,64 @@ + + + + + + +1x4 + + + +host + +host + +mgmt + +data1 + +data2 + +data3 + + + +dut + +mgmt + +data1 + +data2 + +data3 + +dut +10.0.X.1/24 + + + +host:mgmt--dut:mgmt + + + + +host:data1--dut:data1 + +10.0.1.2/24 + + + +host:data2--dut:data2 + +10.0.2.2/24 + + + +host:data3--dut:data3 + +10.0.3.2/24 + + +