• 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_LINK_REQUEST, MLE_PARENT_REQUEST, MLE_PARENT_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, NL_MAC_EXTENDED_ADDRESS_TLV, NL_STATUS_TLV
35from pktverify.packet_verifier import PacketVerifier
36
37LEADER = 1
38ROUTER1 = 2
39ROUTER2 = 3
40ROUTER3 = 4
41ROUTER15 = 16
42REED1 = 17
43
44
45class Cert_5_5_5_SplitMergeREED(thread_cert.TestCase):
46    TOPOLOGY = {
47        LEADER: {
48            'name': 'LEADER',
49            'mode': 'rdn',
50            'allowlist': [ROUTER2, ROUTER3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ROUTER15]
51        },
52        ROUTER1: {
53            'name': 'ROUTER_1',
54            'mode': 'rdn',
55            'allowlist': [ROUTER3]
56        },
57        ROUTER2: {
58            'name': 'ROUTER_2',
59            'mode': 'rdn',
60            'allowlist': [LEADER, REED1]
61        },
62        ROUTER3: {
63            'name': 'ROUTER_3',
64            'mode': 'rdn',
65            'allowlist': [LEADER, ROUTER1]
66        },
67        5: {
68            'mode': 'rdn',
69            'allowlist': [LEADER]
70        },
71        6: {
72            'mode': 'rdn',
73            'allowlist': [LEADER]
74        },
75        7: {
76            'mode': 'rdn',
77            'allowlist': [LEADER]
78        },
79        8: {
80            'mode': 'rdn',
81            'allowlist': [LEADER]
82        },
83        9: {
84            'mode': 'rdn',
85            'allowlist': [LEADER]
86        },
87        10: {
88            'mode': 'rdn',
89            'allowlist': [LEADER]
90        },
91        11: {
92            'mode': 'rdn',
93            'allowlist': [LEADER]
94        },
95        12: {
96            'mode': 'rdn',
97            'allowlist': [LEADER]
98        },
99        13: {
100            'mode': 'rdn',
101            'allowlist': [LEADER]
102        },
103        14: {
104            'mode': 'rdn',
105            'allowlist': [LEADER]
106        },
107        15: {
108            'mode': 'rdn',
109            'allowlist': [LEADER]
110        },
111        ROUTER15: {
112            'mode': 'rdn',
113            'allowlist': [LEADER]
114        },
115        REED1: {
116            'name': 'REED',
117            'mode': 'rdn',
118            'allowlist': [ROUTER2]
119        },
120    }
121
122    def test(self):
123        self.nodes[LEADER].start()
124        self.simulator.go(config.LEADER_STARTUP_DELAY)
125        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
126
127        for i in range(ROUTER2, ROUTER15 + 1):
128            self.nodes[i].start()
129            self.simulator.go(config.ROUTER_STARTUP_DELAY)
130            self.assertEqual(self.nodes[i].get_state(), 'router')
131
132        self.nodes[ROUTER1].start()
133        self.simulator.go(config.ROUTER_STARTUP_DELAY)
134        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
135
136        self.nodes[REED1].start()
137        self.simulator.go(5)
138        self.assertEqual(self.nodes[REED1].get_state(), 'child')
139
140        self.nodes[ROUTER1].add_allowlist(self.nodes[REED1].get_addr64())
141        self.nodes[REED1].add_allowlist(self.nodes[ROUTER1].get_addr64())
142
143        self.nodes[ROUTER3].stop()
144        self.simulator.go(140)
145
146        self.assertEqual(self.nodes[ROUTER1].get_state(), 'child')
147        self.assertEqual(self.nodes[REED1].get_state(), 'router')
148
149        self.collect_ipaddrs()
150
151        addrs = self.nodes[LEADER].get_addrs()
152        for addr in addrs:
153            if addr[0:4] != 'fe80':
154                self.assertTrue(self.nodes[ROUTER1].ping(addr))
155
156    def verify(self, pv):
157        pkts = pv.pkts
158        pv.summary.show()
159
160        LEADER = pv.vars['LEADER']
161        ROUTER_1 = pv.vars['ROUTER_1']
162        ROUTER_2 = pv.vars['ROUTER_2']
163        ROUTER_3 = pv.vars['ROUTER_3']
164        REED = pv.vars['REED']
165        router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
166        router2_pkts = pkts.filter_wpan_src64(ROUTER_2)
167        reed_pkts = pkts.filter_wpan_src64(REED)
168
169        router2_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(REED).must_next()
170        _start_idx = router2_pkts.index
171        reed_pkts.index = _start_idx
172
173        # Step 3: Remove Router_3 from the network
174        # Router_1 attempt to re-attach to partition.
175        # Sends multicast Parent Request to Routers and REEDs
176        router1_pkts.range(_start_idx).must_next()
177        router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
178
179        # filter MLE_ADVERTISEMENT with 16 routing table entry:
180        # 1 byte ID Sequence + 8 bytes ID Mask + 16 bytes Routing Table Entry =
181        # 25 (Router64 tlv length)
182        pkts.range(_start_idx).filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: 25 in p.mle.tlv.len).must_next()
183        _end_idx = pkts.index
184
185        # Step 2: The DUT MUST NOT attempt to become an active router by sending an Address Solicit Request
186        reed_pkts.range(_start_idx, _end_idx).filter_coap_request(ADDR_SOL_URI).must_not_next()
187
188        # Step 4: The DUT send a Parent Response to Router_1
189        reed_pkts.filter_mle_cmd(MLE_PARENT_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst64 == ROUTER_1)
190
191        # Step 5: Router_1 Send MLE Child ID Request to the DUT
192        router1_pkts.range(reed_pkts.index).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
193
194        # Step 6: DUT send an Address Solicit Request to Leader,
195        # receives short address and becomes a router
196        pkts.range(_end_idx).filter_wpan_src64(REED).filter_coap_request(ADDR_SOL_URI).must_next().must_verify(
197            lambda p: {NL_MAC_EXTENDED_ADDRESS_TLV, NL_STATUS_TLV} <= set(p.coap.tlv.type))
198
199        # Step 7: DUT send a Multicast Link Request
200        pkts.filter_wpan_src64(REED).filter_mle_cmd(MLE_LINK_REQUEST).must_next().must_verify(lambda p: {
201            VERSION_TLV, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, CHALLENGE_TLV, LINK_MARGIN_TLV
202        } <= set(p.mle.tlv.type))
203
204        # Step 8: DUT send Child ID Response to Router_1
205        reed_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst64 == ROUTER_1)
206
207        # Step 9: The DUT MUST route the ICMPv6 Echo request to the Leader.
208        # The DUT MUST route the ICMPv6 Echo reply back to Router_1
209        leader_mleid = pv.vars['LEADER_MLEID']
210        router1_mleid = pv.vars['ROUTER_1_MLEID']
211        reed_pkts.filter_ipv6_src_dst(router1_mleid, leader_mleid).filter_ping_request().must_next()
212        reed_pkts.filter_ipv6_src_dst(leader_mleid, router1_mleid).filter_ping_reply().must_next()
213
214
215if __name__ == '__main__':
216    unittest.main()
217