• 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 unittest
31
32import config
33import thread_cert
34from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_DATA_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, VERSION_TLV, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, CHALLENGE_TLV, LINK_MARGIN_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, PENDING_OPERATION_DATASET_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS, NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV, NM_ACTIVE_TIMESTAMP_TLV
35from pktverify.packet_verifier import PacketVerifier
36
37CHANNEL_INIT = 19
38PANID_INIT = 0xface
39
40CHANNEL_FINAL = 16
41PANID_FINAL = 0xafce
42
43COMMISSIONER = 1
44LEADER = 2
45ROUTER1 = 3
46ED1 = 4
47SED1 = 5
48
49MTDS = [ED1, SED1]
50
51
52class Cert_9_2_10_PendingPartition(thread_cert.TestCase):
53    SUPPORT_NCP = False
54
55    TOPOLOGY = {
56        COMMISSIONER: {
57            'name': 'COMMISSIONER',
58            'active_dataset': {
59                'timestamp': 15,
60                'channel': 19
61            },
62            'mode': 'rdn',
63            'allowlist': [LEADER]
64        },
65        LEADER: {
66            'name': 'LEADER',
67            'active_dataset': {
68                'timestamp': 15,
69                'channel': 19
70            },
71            'mode': 'rdn',
72            'partition_id': 0xffffffff,
73            'allowlist': [COMMISSIONER, ROUTER1]
74        },
75        ROUTER1: {
76            'name': 'ROUTER',
77            'active_dataset': {
78                'timestamp': 15,
79                'channel': 19
80            },
81            'mode': 'rdn',
82            'allowlist': [LEADER, ED1, SED1]
83        },
84        ED1: {
85            'name': 'MED',
86            'channel': 19,
87            'is_mtd': True,
88            'mode': 'rn',
89            'allowlist': [ROUTER1]
90        },
91        SED1: {
92            'name': 'SED',
93            'channel': 19,
94            'is_mtd': True,
95            'mode': '-',
96            'timeout': config.DEFAULT_CHILD_TIMEOUT,
97            'allowlist': [ROUTER1]
98        },
99    }
100
101    def test(self):
102        self.nodes[LEADER].start()
103        self.simulator.go(config.LEADER_STARTUP_DELAY)
104        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
105
106        self.nodes[COMMISSIONER].start()
107        self.simulator.go(config.ROUTER_STARTUP_DELAY)
108        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
109        self.nodes[COMMISSIONER].commissioner_start()
110        self.simulator.go(3)
111
112        self.nodes[ROUTER1].start()
113        self.simulator.go(config.ROUTER_STARTUP_DELAY)
114        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
115
116        self.nodes[ED1].start()
117        self.simulator.go(5)
118        self.assertEqual(self.nodes[ED1].get_state(), 'child')
119
120        self.nodes[SED1].start()
121        self.simulator.go(5)
122        self.assertEqual(self.nodes[SED1].get_state(), 'child')
123
124        self.nodes[COMMISSIONER].send_mgmt_pending_set(
125            pending_timestamp=30,
126            active_timestamp=165,
127            delay_timer=250,
128            channel=CHANNEL_FINAL,
129            panid=PANID_FINAL,
130        )
131        self.simulator.go(260)
132
133        self.nodes[LEADER].remove_allowlist(self.nodes[ROUTER1].get_addr64())
134        self.nodes[ROUTER1].remove_allowlist(self.nodes[LEADER].get_addr64())
135        self.simulator.go(300)
136
137        self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
138        self.assertEqual(self.nodes[ED1].get_state(), 'child')
139        self.assertEqual(self.nodes[SED1].get_state(), 'child')
140
141        self.assertEqual(self.nodes[ROUTER1].get_panid(), PANID_FINAL)
142        self.assertEqual(self.nodes[ED1].get_panid(), PANID_FINAL)
143        self.assertEqual(self.nodes[SED1].get_panid(), PANID_FINAL)
144
145        self.assertEqual(self.nodes[ROUTER1].get_channel(), CHANNEL_FINAL)
146        self.assertEqual(self.nodes[ED1].get_channel(), CHANNEL_FINAL)
147        self.assertEqual(self.nodes[SED1].get_channel(), CHANNEL_FINAL)
148
149        self.nodes[LEADER].add_allowlist(self.nodes[ROUTER1].get_addr64())
150        self.nodes[ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64())
151        self.simulator.go(60)
152
153        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
154        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
155        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
156        self.assertEqual(self.nodes[ED1].get_state(), 'child')
157        self.assertEqual(self.nodes[SED1].get_state(), 'child')
158
159        ipaddrs = self.nodes[ED1].get_addrs()
160        for ipaddr in ipaddrs:
161            if ipaddr[0:4] != 'fe80':
162                break
163
164        self.assertTrue(self.nodes[LEADER].ping(ipaddr))
165
166    def verify(self, pv):
167        pkts = pv.pkts
168        pv.summary.show()
169
170        LEADER = pv.vars['LEADER']
171        ROUTER = pv.vars['ROUTER']
172        MED = pv.vars['MED']
173        SED = pv.vars['SED']
174        COMMISSIONER = pv.vars['COMMISSIONER']
175        _rpkts = pkts.filter_wpan_src64(ROUTER, cascade=False)
176
177        # Step 1: Ensure the topology is formed correctly
178        _rpkts.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
179
180        # Step 5: Router MUST send a unicast MLE Data Request to the Leader
181        _rpkts.filter_wpan_dst64(LEADER).filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
182            lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
183        _rpkts_med = _rpkts.copy()
184
185        # Step 7: Router MUST multicast a MLE Data Response
186        _rpkts.filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
187            MLE_DATA_RESPONSE).must_next().must_verify(lambda p: {
188                SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
189            } <= set(p.mle.tlv.type) and {NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV} <= set(
190                p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
191
192        # Step 8: MED MUST send a unicast MLE Data Request to Router_1,
193        with pkts.save_index():
194            pkts.filter_wpan_src64(MED).filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_REQUEST).must_next(
195            ).must_verify(lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
196
197        # Step 9: Router MUST send a unicast MLE Data Response to MED_1
198        _rpkts_med.filter_wpan_dst64(MED).filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(lambda p: {
199            SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV
200        } <= set(p.mle.tlv.type) and {
201            NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV,
202            NM_ACTIVE_TIMESTAMP_TLV
203        } <= set(p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
204
205        # Step 10: Router MUST send MLE Child Update Request to SED_1
206        _rpkts.range(pkts.index).filter_wpan_dst64(SED).filter_mle_cmd(
207            MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(lambda p: {
208                SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
209            } <= set(p.mle.tlv.type))
210
211        # Step 11: SED MUST send a unicast MLE Data Request to Router_1
212        pkts.filter_wpan_src64(SED).filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
213            lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
214
215        # Step 12: Router MUST send a unicast MLE Data Response to SED_1
216        _pkt = _rpkts.filter_wpan_dst64(SED).filter_mle_cmd(MLE_DATA_RESPONSE).must_next()
217        _pkt.must_verify(lambda p: {
218            SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV
219        } <= set(p.mle.tlv.type) and {
220            NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV,
221            NM_ACTIVE_TIMESTAMP_TLV
222        } <= set(p.thread_meshcop.tlv.type))
223
224        # Step 14: After NETWORK_ID_TIMEOUT, Router MUST start a new partition
225        _rpkts.filter_ipv6_dst(LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).filter_mle_cmd(
226            MLE_PARENT_REQUEST).must_next().must_verify(lambda p: p.sniff_timestamp - _pkt.sniff_timestamp > 300)
227        _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter(lambda p: p.wpan.dst_pan == PANID_FINAL).must_next()
228
229        # Step 16: After the Delay Timer expires, Router MUST move to the Secondary channel
230        _rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: p.wpan.dst_pan == PANID_FINAL).must_next()
231
232        # Step 19: Router MUST reattach to the Leader and the partitions MUST merge
233        pkts.filter_wpan_src64(LEADER).filter_wpan_dst64(ROUTER).filter_mle_cmd(
234            MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.mle.tlv.leader_data.partition_id == 0xffffffff)
235
236        # Step 20: MED MUST respond with an ICMPv6 Echo Reply
237        p = pkts.filter_ping_request().filter_wpan_src64(LEADER).must_next()
238        pkts.filter_ping_reply(identifier=p.icmpv6.echo.identifier).filter_wpan_src64(MED).must_next()
239
240
241if __name__ == '__main__':
242    unittest.main()
243