From 1484847c559bcd93a0d2472b4926cd26c823de5b Mon Sep 17 00:00:00 2001 From: Jing Ma Date: Tue, 17 Nov 2020 14:29:25 +0800 Subject: [PATCH] [thread-cert] refactor case 5.2.6 using pktverify (#5777) --- .../Cert_5_2_06_RouterDowngrade.py | 165 +++++++++++++++--- 1 file changed, 142 insertions(+), 23 deletions(-) diff --git a/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py b/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py index 89fd91672..fa6be1be4 100755 --- a/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py +++ b/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py @@ -33,16 +33,39 @@ import command import config import mle import thread_cert +import thread_cert +from pktverify.consts import MLE_PARENT_REQUEST, MLE_CHILD_ID_REQUEST, ADDR_REL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, COAP_CODE_ACK +from pktverify.packet_verifier import PacketVerifier +from pktverify.null_field import nullField LEADER = 1 DUT_ROUTER1 = 2 ROUTER2 = 3 -ROUTER24 = 24 +ROUTER23 = 24 + +# Test Purpose and Description: +# ----------------------------- +# The purpose of this test case is to verify that the DUT will downgrade +# to a REED when the network becomes too dense and the Router Downgrade +# Threshold conditions are met. +# +# Test Topology: +# ------------- +# Leader +# / \ +# Router_1 [DUT] ... Router_23 +# +# DUT Types: +# ---------- +# Router class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + TOPOLOGY = { LEADER: { + 'name': 'LEADER', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -50,11 +73,13 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, DUT_ROUTER1: { + 'name': 'ROUTER_1', 'mode': 'rdn', 'panid': 0xface, 'router_selection_jitter': 1 }, ROUTER2: { + 'name': 'ROUTER_2', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -62,6 +87,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 4: { + 'name': 'ROUTER_3', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -69,6 +95,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 5: { + 'name': 'ROUTER_4', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -76,6 +103,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 6: { + 'name': 'ROUTER_5', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -83,6 +111,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 7: { + 'name': 'ROUTER_6', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -90,6 +119,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 8: { + 'name': 'ROUTER_7', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -97,6 +127,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 9: { + 'name': 'ROUTER_8', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -104,6 +135,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 10: { + 'name': 'ROUTER_9', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -111,6 +143,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 11: { + 'name': 'ROUTER_10', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -118,6 +151,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 12: { + 'name': 'ROUTER_11', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -125,6 +159,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 13: { + 'name': 'ROUTER_12', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -132,6 +167,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 14: { + 'name': 'ROUTER_13', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -139,6 +175,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 15: { + 'name': 'ROUTER_14', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -146,6 +183,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 16: { + 'name': 'ROUTER_15', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -153,6 +191,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 17: { + 'name': 'ROUTER_16', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -160,6 +199,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 18: { + 'name': 'ROUTER_17', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -167,6 +207,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 19: { + 'name': 'ROUTER_18', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -174,6 +215,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 20: { + 'name': 'ROUTER_19', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -181,6 +223,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 21: { + 'name': 'ROUTER_20', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -188,6 +231,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 22: { + 'name': 'ROUTER_21', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -195,13 +239,15 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): 'router_upgrade_threshold': 32 }, 23: { + 'name': 'ROUTER_22', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, 'router_selection_jitter': 1, 'router_upgrade_threshold': 32 }, - ROUTER24: { + ROUTER23: { + 'name': 'ROUTER_23', 'mode': 'rdn', 'panid': 0xface, 'router_downgrade_threshold': 32, @@ -211,7 +257,7 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): } def test(self): - # 1 Ensure topology is formed correctly without ROUTER24. + # 1 Ensure topology is formed correctly without ROUTER23. self.nodes[LEADER].start() self.simulator.go(5) self.assertEqual(self.nodes[LEADER].get_state(), 'leader') @@ -220,37 +266,110 @@ class Cert_5_2_06_RouterDowngrade(thread_cert.TestCase): self.nodes[i].start() self.simulator.go(5) self.assertEqual(self.nodes[i].get_state(), 'router') + self.collect_rloc16s() - # This method flushes the message queue so calling this method again - # will return only the newly logged messages. - dut_messages = self.simulator.get_messages_sent_by(DUT_ROUTER1) - - # 2 ROUTER24: Attach to network. # All reference testbed devices have been configured with downgrade threshold as 32 except DUT_ROUTER1, - # so we don't need to ensure ROUTER24 has a better link quality on + # so we don't need to ensure ROUTER23 has a better link quality on # posix. - self.nodes[ROUTER24].start() + self.nodes[ROUTER23].start() self.simulator.go(5) - self.assertEqual(self.nodes[ROUTER24].get_state(), 'router') + self.assertEqual(self.nodes[ROUTER23].get_state(), 'router') - # 3 DUT_ROUTER1: self.simulator.go(10) self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'child') + self.collect_rlocs() - # Verify it sent a Parent Request and Child ID Request. - dut_messages = self.simulator.get_messages_sent_by(DUT_ROUTER1) - dut_messages.next_mle_message(mle.CommandType.PARENT_REQUEST) - dut_messages.next_mle_message(mle.CommandType.CHILD_ID_REQUEST) - - # Verify it sent an Address Release Message to the Leader when it - # attached as a child. - msg = dut_messages.next_coap_message('0.02') - command.check_address_release(msg, self.nodes[LEADER]) - - # 4 & 5 router1_rloc = self.nodes[DUT_ROUTER1].get_ip6_address(config.ADDRESS_TYPE.RLOC) self.assertTrue(self.nodes[LEADER].ping(router1_rloc)) + def verify(self, pv): + pkts = pv.pkts + pv.summary.show() + + LEADER = pv.vars['LEADER'] + LEADER_RLOC = pv.vars['LEADER_RLOC'] + ROUTER_1 = pv.vars['ROUTER_1'] + ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC'] + ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16'] + + # Step 1: Ensure topology is formed correctly + + for i in range(1, 24): + pv.verify_attached('ROUTER_%d' % i) + + # Step 3: Allow enough time for the DUT to get Network Data Updates + # and resign its Router ID. + # The DUT MUST first reconnect to the network as a Child by + # sending properly formatted Parent Request and Child ID Request + # messages. + # Once the DUT attaches as a Child, it MUST send an Address + # Release Message to the Leader: + # CoAP Request URI + # coap://[]:MM/a/ar + # CoAP Payload + # MAC Extended Address TLV + # RLOC16 TLV + + pkts.filter_wpan_src64(ROUTER_1).\ + filter_LLARMA().\ + filter_mle_cmd(MLE_PARENT_REQUEST).\ + filter(lambda p: { + CHALLENGE_TLV, + MODE_TLV, + SCAN_MASK_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type) and\ + p.ipv6.hlim == 255 and\ + p.mle.tlv.scan_mask.r == 1 and\ + p.mle.tlv.scan_mask.e == 0 + ).\ + must_next() + + _pkt = pkts.filter_wpan_src64(ROUTER_1).\ + filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ + filter(lambda p: { + LINK_LAYER_FRAME_COUNTER_TLV, + MODE_TLV, + RESPONSE_TLV, + TIMEOUT_TLV, + TLV_REQUEST_TLV, + ADDRESS16_TLV, + NETWORK_DATA_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type) and\ + p.mle.tlv.addr16 is nullField and\ + p.thread_nwd.tlv.type is nullField + ).\ + must_next() + _pkt.must_not_verify(lambda p: (ADDRESS_REGISTRATION_TLV) in p.mle.tlv.type) + + pkts.filter_wpan_src64(ROUTER_1).\ + filter_ipv6_dst(LEADER_RLOC).\ + filter_coap_request(ADDR_REL_URI).\ + filter(lambda p: { + NL_MAC_EXTENDED_ADDRESS_TLV, + NL_RLOC16_TLV + } == set(p.coap.tlv.type) and\ + p.thread_address.tlv.rloc16 == ROUTER_1_RLOC16 + ).\ + must_next() + + # Step 4: Leader receives Address Release messages and sends a2.04 + # Changed CoAP response. + + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(ROUTER_1_RLOC).\ + filter_coap_ack(ADDR_REL_URI).\ + must_next() + + # Step 5: ROUTER_1 responds with ICMPv6 Echo Reply + _pkt = pkts.filter_ipv6_src_dst(LEADER_RLOC, ROUTER_1_RLOC).\ + filter_ping_request().\ + must_next() + pkts.filter_ipv6_src_dst(ROUTER_1_RLOC, LEADER_RLOC).\ + filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + must_next() + if __name__ == '__main__': unittest.main()