• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2016, 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 copy
31import unittest
32
33import config
34import thread_cert
35from pktverify.consts import MLE_CHILD_ID_RESPONSE, MGMT_ED_SCAN, MGMT_ED_REPORT, NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV
36from pktverify.packet_verifier import PacketVerifier
37
38COMMISSIONER = 1
39LEADER = 2
40ROUTER1 = 3
41ED = 4
42
43
44class Cert_9_2_13_EnergyScan_Base(thread_cert.TestCase):
45    SUPPORT_NCP = False
46
47    TOPOLOGY = {
48        COMMISSIONER: {
49            'name': 'COMMISSIONER',
50            'mode': 'rdn',
51            'allowlist': [LEADER]
52        },
53        LEADER: {
54            'name': 'LEADER',
55            'mode': 'rdn',
56            'allowlist': [COMMISSIONER, ROUTER1]
57        },
58        ROUTER1: {
59            'name': 'ROUTER',
60            'mode': 'rdn',
61            'allowlist': [LEADER, ED]
62        },
63        ED: {
64            'allowlist': [ROUTER1]
65        },
66    }
67
68    def test(self):
69        self.nodes[LEADER].start()
70        self.simulator.go(config.LEADER_STARTUP_DELAY)
71        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
72
73        self.nodes[COMMISSIONER].start()
74        self.simulator.go(config.ROUTER_STARTUP_DELAY)
75        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
76        self.nodes[COMMISSIONER].commissioner_start()
77        self.simulator.go(5)
78
79        self.nodes[ROUTER1].start()
80        self.simulator.go(config.ROUTER_STARTUP_DELAY)
81        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
82
83        self.nodes[ED].start()
84        self.simulator.go(5)
85        self.assertEqual(self.nodes[ED].get_state(), 'child')
86        self.collect_rlocs()
87
88        if self.TOPOLOGY[ED]['name'] == 'DUT':
89            ipaddrs = self.nodes[ED].get_addrs()
90        else:
91            ipaddrs = self.nodes[ROUTER1].get_addrs()
92
93        for ipaddr in ipaddrs:
94            if ipaddr[0:4] != 'fe80':
95                break
96
97        self.nodes[COMMISSIONER].energy_scan(0x50000, 0x02, 0x20, 0xc8, ipaddr)
98        self.simulator.go(3)
99        self.nodes[COMMISSIONER].energy_scan(0x50000, 0x02, 0x20, 0xc8, 'ff33:0040:fd00:db8:0:0:0:1')
100        self.simulator.go(3)
101
102        self.assertTrue(self.nodes[COMMISSIONER].ping(ipaddr))
103
104    def verify(self, pv):
105        pkts = pv.pkts
106        pv.summary.show()
107
108        DUT = pv.vars['DUT']
109        DUT_RLOC = pv.vars['DUT_RLOC']
110        COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
111        _pkts = pkts.filter_wpan_src64(DUT)
112
113        # Step 3: The DUT MUST send MGMT_ED_REPORT.ans to the Commissioner and report energy measurements
114        _pkts.filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_ED_REPORT).must_next().must_verify(
115            lambda p: {NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV} <= set(p.thread_meshcop.tlv.type) and p.thread_meshcop.
116            tlv.chan_mask_mask == '0000a000' and len(p.thread_meshcop.tlv.energy_list) == 2)
117
118        # Step 5: The DUT MUST send MGMT_ED_REPORT.ans to the Commissioner and report energy measurements
119        _pkts.filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_ED_REPORT).must_next().must_verify(
120            lambda p: {NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV} <= set(p.thread_meshcop.tlv.type) and p.thread_meshcop.
121            tlv.chan_mask_mask == '0000a000' and len(p.thread_meshcop.tlv.energy_list) == 2)
122
123        # Step 6: The DUT MUST respond with ICMPv6 Echo Reply
124        _pkts.filter_ping_reply().filter_ipv6_src_dst(DUT_RLOC, COMMISSIONER_RLOC).must_next()
125
126
127class Cert_9_2_13_EnergyScan_FED(Cert_9_2_13_EnergyScan_Base):
128    TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
129    TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
130    TOPOLOGY[ED]['name'] = 'DUT'
131    TOPOLOGY[ED]['router_upgrade_threshold'] = 0
132
133
134class Cert_9_2_13_EnergyScan_MED(Cert_9_2_13_EnergyScan_Base):
135    TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
136    TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
137    TOPOLOGY[ED]['name'] = 'DUT'
138    TOPOLOGY[ED]['mode'] = 'rn'
139    TOPOLOGY[ED]['is_mtd'] = True
140
141
142class Cert_9_2_13_EnergyScan_ROUTER(Cert_9_2_13_EnergyScan_Base):
143    TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
144    TOPOLOGY[ROUTER1]['name'] = 'DUT'
145    TOPOLOGY[ED]['name'] = 'ED'
146    TOPOLOGY[ED]['mode'] = 'rn'
147    TOPOLOGY[ED]['is_mtd'] = True
148
149
150class Cert_9_2_13_EnergyScan_SED(Cert_9_2_13_EnergyScan_Base):
151    TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
152    TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
153    TOPOLOGY[ED]['name'] = 'DUT'
154    TOPOLOGY[ED]['mode'] = '-'
155    TOPOLOGY[ED]['is_mtd'] = True
156    TOPOLOGY[ED]['timeout'] = config.DEFAULT_CHILD_TIMEOUT
157
158
159del (Cert_9_2_13_EnergyScan_Base)
160
161if __name__ == '__main__':
162    unittest.main()
163