1#!/usr/bin/env python3 2# 3# Copyright (c) 2020, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import unittest 31 32from config import ADDRESS_TYPE 33from mac802154 import MacHeader 34from pktverify import consts 35from pktverify.packet_verifier import PacketVerifier 36 37import config 38import thread_cert 39 40LEADER = 1 41ROUTER = 2 42SSED_1 = 3 43 44 45class LowPower_5_3_01_SSEDAttachment(thread_cert.TestCase): 46 USE_MESSAGE_FACTORY = False 47 TOPOLOGY = { 48 LEADER: { 49 'version': '1.2', 50 'name': 'LEADER', 51 'mode': 'rdn', 52 'allowlist': [ROUTER, SSED_1] 53 }, 54 ROUTER: { 55 'version': '1.2', 56 'name': 'ROUTER', 57 'mode': 'rdn', 58 'allowlist': [LEADER], 59 }, 60 SSED_1: { 61 'version': '1.2', 62 'name': 'SSED_1', 63 'is_mtd': True, 64 'mode': '-', 65 'allowlist': [LEADER], 66 }, 67 } 68 69 def test(self): 70 self.nodes[LEADER].start() 71 self.simulator.go(config.LEADER_STARTUP_DELAY) 72 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 73 74 self.nodes[ROUTER].start() 75 self.simulator.go(config.ROUTER_STARTUP_DELAY) 76 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 77 78 self.nodes[SSED_1].set_csl_period(consts.CSL_DEFAULT_PERIOD) 79 self.nodes[SSED_1].start() 80 self.simulator.go(5) 81 self.assertEqual(self.nodes[SSED_1].get_state(), 'child') 82 83 self.simulator.go(5) 84 85 self.collect_rloc16s() 86 self.collect_rlocs() 87 88 # Verify connectivity by sending an ICMP Echo Request from the Router to SSED_1 mesh-local address via the DUT 89 self.assertTrue(self.nodes[ROUTER].ping(self.nodes[SSED_1].get_ip6_address(ADDRESS_TYPE.RLOC))) 90 91 # Verify fragmented CSL transmission 92 self.assertTrue(self.nodes[ROUTER].ping(self.nodes[SSED_1].get_ip6_address(ADDRESS_TYPE.RLOC), size=128)) 93 94 self.simulator.go(5) 95 96 def verify(self, pv): 97 pkts = pv.pkts 98 pv.summary.show() 99 LEADER = pv.vars['LEADER'] 100 ROUTER = pv.vars['ROUTER'] 101 SSED_1 = pv.vars['SSED_1'] 102 103 # Step 1: ensure the Leader is sending MLE Advertisements 104 pkts.filter_wpan_src64(LEADER) \ 105 .filter_mle_cmd(consts.MLE_ADVERTISEMENT) \ 106 .must_next() 107 108 # Step 2: Verify that the frame version is IEEE Std 802.15.4-2015 of the MLE Child Update Response from the 109 # DUT to SSED_1 110 pkts.filter_wpan_src64(LEADER) \ 111 .filter_wpan_dst64(SSED_1) \ 112 .filter_mle_cmd(consts.MLE_CHILD_UPDATE_RESPONSE) \ 113 .filter_wpan_version(consts.MAC_FRAME_VERSION_2015) \ 114 .must_next() 115 116 # Step 3: 117 # Verify that SSED_1 does not send a MAC Data Request prior to receiving the ICMP Echo Request from the Leader. 118 # Verify that the frame version is IEEE Std 802.15.4-2015 of the ICMP Echo Request sent to SSED_1 from the DUT 119 # Verify that the Router successfully receives an Echo Response from SSED_1 120 ssed_rloc16 = pv.vars['SSED_1_RLOC16'] 121 ssed_rloc = pv.vars['SSED_1_RLOC'] 122 leader_rloc16 = pv.vars['LEADER_RLOC16'] 123 router_rloc16 = pv.vars['ROUTER_RLOC16'] 124 router_rloc = pv.vars['ROUTER_RLOC'] 125 pkts.filter_wpan_src64(LEADER) \ 126 .filter('wpan.dst16 == {rloc16}', rloc16 = ssed_rloc16) \ 127 .filter_ipv6_dst(ssed_rloc) \ 128 .filter_ping_request() \ 129 .filter_wpan_version(consts.MAC_FRAME_VERSION_2015) \ 130 .must_next() 131 idx1 = pkts.index 132 pkts.filter_wpan_src64(SSED_1) \ 133 .filter('wpan.dst16 == {rloc16}', rloc16 = leader_rloc16) \ 134 .filter_ipv6_dst(router_rloc) \ 135 .filter_ping_reply() \ 136 .filter_wpan_version(consts.MAC_FRAME_VERSION_2015) \ 137 .must_next() \ 138 .must_verify(lambda p: (p.wpan.ie_present == 1) and (consts.CSL_IE_ID in p.wpan.header_ie.id)) 139 idx2 = pkts.index 140 pkts.range(idx1, idx2).filter(lambda p: p.wpan.cmd == MacHeader.CommandIdentifier.DATA_REQUEST) \ 141 .must_not_next() 142 143 144if __name__ == '__main__': 145 unittest.main() 146