From 515b2bb0671d63f4ca4e2abcd028ccc4c6dc61af Mon Sep 17 00:00:00 2001 From: Jing Ma Date: Tue, 17 Nov 2020 00:57:36 +0800 Subject: [PATCH] [thread-cert] refactor case 5.3.5 using pktverify (#5814) --- .../Cert_5_3_05_RoutingLinkQuality.py | 157 ++++++++++++++++-- 1 file changed, 141 insertions(+), 16 deletions(-) diff --git a/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py b/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py index d227ee634..7499b5ae8 100755 --- a/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py +++ b/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py @@ -32,33 +32,57 @@ import unittest import command import config import thread_cert +from pktverify.packet_verifier import PacketVerifier LEADER = 1 DUT_ROUTER1 = 2 ROUTER2 = 3 ROUTER3 = 4 +# Test Purpose and Description: +# ----------------------------- +# The purpose of this test case is to ensure that the DUT routes traffic properly +# when link qualities between the nodes are adjusted. +# +# Test Topology: +# ------------- +# Leader +# / \ +# Router_2 - Router_1(DUT) +# | +# Router_3 +# +# DUT Types: +# ---------- +# Router + class Cert_5_3_5_RoutingLinkQuality(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + TOPOLOGY = { LEADER: { + 'name': 'LEADER', 'mode': 'rdn', 'panid': 0xface, 'allowlist': [DUT_ROUTER1, ROUTER2] }, DUT_ROUTER1: { + 'name': 'ROUTER_1', 'mode': 'rdn', 'panid': 0xface, 'router_selection_jitter': 1, 'allowlist': [LEADER, ROUTER2, ROUTER3] }, ROUTER2: { + 'name': 'ROUTER_2', 'mode': 'rdn', 'panid': 0xface, 'router_selection_jitter': 1, 'allowlist': [LEADER, DUT_ROUTER1] }, ROUTER3: { + 'name': 'ROUTER_3', 'mode': 'rdn', 'panid': 0xface, 'router_selection_jitter': 1, @@ -79,46 +103,147 @@ class Cert_5_3_5_RoutingLinkQuality(thread_cert.TestCase): for router in range(DUT_ROUTER1, ROUTER3 + 1): self.assertEqual(self.nodes[router].get_state(), 'router') + self.collect_rlocs() + self.collect_rloc16s() + # 2 & 3 leader_rloc = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC) - - # Verify the ICMPv6 Echo Request took the least cost path. self.assertTrue(self.nodes[ROUTER3].ping(leader_rloc)) - path = [ROUTER3, DUT_ROUTER1, LEADER] - command.check_icmp_path(self.simulator, path, self.nodes) # 4 & 5 self.nodes[LEADER].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(), config.RSSI['LINK_QULITY_1']) self.nodes[DUT_ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64(), config.RSSI['LINK_QULITY_1']) self.simulator.go(3 * config.MAX_ADVERTISEMENT_INTERVAL) - # Verify the ICMPv6 Echo Request took the longer path because it cost - # less. self.assertTrue(self.nodes[ROUTER3].ping(leader_rloc)) - path = [ROUTER3, DUT_ROUTER1, ROUTER2, LEADER] - command.check_icmp_path(self.simulator, path, self.nodes) # 6 & 7 self.nodes[LEADER].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(), config.RSSI['LINK_QULITY_2']) self.nodes[DUT_ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64(), config.RSSI['LINK_QULITY_2']) self.simulator.go(3 * config.MAX_ADVERTISEMENT_INTERVAL) - # Verify the direct neighbor would be prioritized when there are two - # paths with the same cost. self.assertTrue(self.nodes[ROUTER3].ping(leader_rloc)) - path = [ROUTER3, DUT_ROUTER1, LEADER] - command.check_icmp_path(self.simulator, path, self.nodes) # 8 & 9 self.nodes[LEADER].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(), config.RSSI['LINK_QULITY_0']) self.nodes[DUT_ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64(), config.RSSI['LINK_QULITY_0']) self.simulator.go(3 * config.MAX_ADVERTISEMENT_INTERVAL) - # Verify the ICMPv6 Echo Request took the longer path. - leader_rloc = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC) self.assertTrue(self.nodes[ROUTER3].ping(leader_rloc)) - path = [ROUTER3, DUT_ROUTER1, ROUTER2, LEADER] - command.check_icmp_path(self.simulator, path, self.nodes) + + def verify(self, pv): + pkts = pv.pkts + pv.summary.show() + + LEADER = pv.vars['LEADER'] + LEADER_RLOC = pv.vars['LEADER_RLOC'] + LEADER_RLOC16 = pv.vars['LEADER_RLOC16'] + ROUTER_1 = pv.vars['ROUTER_1'] + ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC'] + ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16'] + ROUTER_2 = pv.vars['ROUTER_2'] + ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16'] + ROUTER_2_RLOC = pv.vars['ROUTER_2_RLOC'] + ROUTER_3 = pv.vars['ROUTER_3'] + ROUTER_3_RLOC = pv.vars['ROUTER_3_RLOC'] + MM = pv.vars['MM_PORT'] + + # Step 1: Ensure topology is formed correctly + for i in range(1, 4): + with pkts.save_index(): + pv.verify_attached('ROUTER_%d' % i) + + # Step 2: Modify the link quality between the DUT and the Leader to be 3 + # Step 3: Router_3 sends an ICMPv6 Echo Request to the Leader + # The ICMPv6 Echo Request MUST take the shortest path: + # Router_3 -> DUT -> Leader + # The hopsLft field of the 6LoWPAN Mesh Header MUST be greater than + # the route cost to the destination + + _pkt = pkts.filter_ping_request().\ + filter_wpan_src64(ROUTER_3).\ + filter_ipv6_dst(LEADER_RLOC).\ + must_next() + _pkt.must_verify(lambda p: p.lowpan.mesh.hops > 2) + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_1).\ + filter_wpan_dst16(LEADER_RLOC16).\ + must_next() + pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(LEADER).\ + filter_ipv6_dst(ROUTER_3_RLOC).\ + must_next() + + # Step 4: Modify the link quality between the DUT and the Leader to be 1 + # Step 5: Router_3 sends an ICMPv6 Echo Request to the Leader + # The ICMPv6 Echo Request MUST take the shortest path: + # Router_3 -> DUT -> Router_2 -> Leader + # The hopsLft field of the 6LoWPAN Mesh Header MUST be greater than + # the route cost to the destination + + _pkt = pkts.filter_ping_request().\ + filter_wpan_src64(ROUTER_3).\ + filter_ipv6_dst(LEADER_RLOC).\ + must_next() + _pkt.must_verify(lambda p: p.lowpan.mesh.hops > 3) + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_1).\ + filter_wpan_dst16(ROUTER_2_RLOC16).\ + must_next() + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_2).\ + filter_wpan_dst16(LEADER_RLOC16).\ + must_next() + pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(LEADER).\ + filter_ipv6_dst(ROUTER_3_RLOC).\ + must_next() + + # Step 6: Modify the link quality between the DUT and the Leader to be 2 + # Step 7: Router_3 sends an ICMPv6 Echo Request to the Leader + # The ICMPv6 Echo Request MUST take the shortest path: + # Router_3 -> DUT -> Leader + # The hopsLft field of the 6LoWPAN Mesh Header MUST be greater than + # the route cost to the destination + + _pkt = pkts.filter_ping_request().\ + filter_wpan_src64(ROUTER_3).\ + filter_ipv6_dst(LEADER_RLOC).\ + must_next() + _pkt.must_verify(lambda p: p.lowpan.mesh.hops > 2) + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_1).\ + filter_wpan_dst16(LEADER_RLOC16).\ + must_next() + pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(LEADER).\ + filter_ipv6_dst(ROUTER_3_RLOC).\ + must_next() + + # Step 8: Modify the link quality between the DUT and the Leader to be 0 + # Step 9: Router_3 sends an ICMPv6 Echo Request to the Leader + # The ICMPv6 Echo Request MUST take the shortest path: + # Router_3 -> DUT -> Router_2 -> Leader + # The hopsLft field of the 6LoWPAN Mesh Header MUST be greater than + # the route cost to the destination + + _pkt = pkts.filter_ping_request().\ + filter_wpan_src64(ROUTER_3).\ + filter_ipv6_dst(LEADER_RLOC).\ + must_next() + _pkt.must_verify(lambda p: p.lowpan.mesh.hops > 3) + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_1).\ + filter_wpan_dst16(ROUTER_2_RLOC16).\ + must_next() + pkts.filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(ROUTER_2).\ + filter_wpan_dst16(LEADER_RLOC16).\ + must_next() + pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + filter_wpan_src64(LEADER).\ + filter_ipv6_dst(ROUTER_3_RLOC).\ + must_next() if __name__ == '__main__':