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 31import copy 32 33import config 34import thread_cert 35from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV 36from pktverify.packet_verifier import PacketVerifier 37from pktverify.addrs import Ipv6Addr 38 39LEADER = 1 40ROUTER = 2 41SED1 = 3 42MED1 = 4 43 44MTDS = [SED1, MED1] 45PREFIX_2001 = '2001::/64' 46PREFIX_2002 = '2002::/64' 47 48# Test Purpose and Description: 49# ----------------------------- 50# The purpose of this test case is to verify that the DUT, as a Border Router, 51# acts properly as a Leader device in a Thread network, correctly sets the 52# Network Data (stable/non-stable) and successfully propagates the Network Data 53# to the devices that attach to it. 54# 55# Test Topology: 56# ------------- 57# SED 58# | 59# ROUTER - Leader(DUT) - MED 60# 61# DUT Types: 62# ---------- 63# Leader 64 65 66class Cert_7_1_1_BorderRouterAsLeader(thread_cert.TestCase): 67 USE_MESSAGE_FACTORY = False 68 69 TOPOLOGY = { 70 LEADER: { 71 'name': 'LEADER', 72 'mode': 'rdn', 73 'allowlist': [ROUTER, SED1, MED1] 74 }, 75 ROUTER: { 76 'name': 'ROUTER', 77 'mode': 'rdn', 78 'allowlist': [LEADER] 79 }, 80 SED1: { 81 'name': 'SED', 82 'is_mtd': True, 83 'mode': '-', 84 'timeout': config.DEFAULT_CHILD_TIMEOUT, 85 'allowlist': [LEADER] 86 }, 87 MED1: { 88 'name': 'MED', 89 'is_mtd': True, 90 'mode': 'rn', 91 'allowlist': [LEADER] 92 }, 93 } 94 # override wireshark preferences with case needed parameters 95 CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS) 96 CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_2001 97 CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2002 98 99 def test(self): 100 self.nodes[LEADER].start() 101 self.simulator.go(config.LEADER_STARTUP_DELAY) 102 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 103 104 self.nodes[LEADER].add_prefix(PREFIX_2001, 'paros') 105 self.nodes[LEADER].add_prefix(PREFIX_2002, 'paro') 106 self.nodes[LEADER].register_netdata() 107 108 self.nodes[ROUTER].start() 109 self.simulator.go(config.ROUTER_STARTUP_DELAY) 110 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 111 112 self.nodes[SED1].start() 113 self.simulator.go(5) 114 self.assertEqual(self.nodes[SED1].get_state(), 'child') 115 116 self.nodes[MED1].start() 117 self.simulator.go(5) 118 self.assertEqual(self.nodes[MED1].get_state(), 'child') 119 120 def verify(self, pv): 121 pkts = pv.pkts 122 pv.summary.show() 123 124 LEADER = pv.vars['LEADER'] 125 ROUTER = pv.vars['ROUTER'] 126 MED = pv.vars['MED'] 127 SED = pv.vars['SED'] 128 129 # Step 1: The DUT forms the network properly sends MLE Advertisements 130 pkts.filter_wpan_src64(LEADER).\ 131 filter_mle_advertisement('Leader').\ 132 must_next() 133 134 # Step 3: Router attaches to the Leader (DUT) and requests complete 135 # network data 136 pkts.filter_wpan_src64(ROUTER).\ 137 filter_wpan_dst64(LEADER).\ 138 filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ 139 filter(lambda p: { 140 RESPONSE_TLV, 141 LINK_LAYER_FRAME_COUNTER_TLV, 142 MODE_TLV, 143 TIMEOUT_TLV, 144 VERSION_TLV, 145 TLV_REQUEST_TLV, 146 ADDRESS16_TLV, 147 NETWORK_DATA_TLV, 148 ROUTE64_TLV 149 } < set(p.mle.tlv.type) and\ 150 p.mle.tlv.mode.network_data == 1 151 ).\ 152 must_next() 153 154 # Step 4: The DUT MUST send a MLE Child ID Response to Router, 155 # including the following TLVs: 156 # - Network Data TLV 157 # At least two Prefix TLVs (Prefix 1 and Prefix 2), 158 # each including: 159 # - 6LoWPAN ID sub-TLV 160 # - Border Router sub-TLV 161 pkts.filter_wpan_src64(LEADER).\ 162 filter_wpan_dst64(ROUTER).\ 163 filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\ 164 filter(lambda p: { 165 Ipv6Addr(PREFIX_2001[:-3]), 166 Ipv6Addr(PREFIX_2002[:-3]) 167 } == set(p.thread_nwd.tlv.prefix) and\ 168 p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\ 169 p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\ 170 p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\ 171 p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\ 172 p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0] 173 ).\ 174 must_next() 175 176 # Step 5: SED attaches to the Leader (DUT) and requests only stable 177 # network data 178 pkts.filter_wpan_src64(SED).\ 179 filter_wpan_dst64(LEADER).\ 180 filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ 181 filter(lambda p: { 182 RESPONSE_TLV, 183 LINK_LAYER_FRAME_COUNTER_TLV, 184 MODE_TLV, 185 TIMEOUT_TLV, 186 VERSION_TLV, 187 TLV_REQUEST_TLV, 188 ADDRESS16_TLV, 189 NETWORK_DATA_TLV, 190 ADDRESS_REGISTRATION_TLV 191 } <= set(p.mle.tlv.type) and\ 192 p.mle.tlv.mode.network_data == 0 193 ).\ 194 must_next() 195 196 # Step 6: The DUT MUST send a MLE Child ID Response to SED, 197 # including the following TLVs: 198 # - Network Data TLV 199 # At least one Prefix TLVs (Prefix 1),including: 200 # - 6LoWPAN ID sub-TLV 201 # - Border Router sub-TLV 202 # - P_border_router_16 <0xFFFE> 203 # Prefix 2 TLV MUST NOT be included 204 pkts.filter_wpan_src64(LEADER).\ 205 filter_wpan_dst64(SED).\ 206 filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\ 207 filter(lambda p: { 208 MODE_TLV, 209 TIMEOUT_TLV, 210 CHALLENGE_TLV 211 } == set(p.thread_nwd.tlv.type) and\ 212 [Ipv6Addr(PREFIX_2001[:-3])] == p.thread_nwd.tlv.prefix and\ 213 p.thread_nwd.tlv.border_router.flag.p == [1] and\ 214 p.thread_nwd.tlv.border_router.flag.s == [1] and\ 215 p.thread_nwd.tlv.border_router.flag.r == [1] and\ 216 p.thread_nwd.tlv.border_router.flag.o == [1] and\ 217 p.thread_nwd.tlv.stable == [1, 1, 1] 218 ).\ 219 must_next() 220 221 lstart = pkts.index 222 223 # Step 7: MED attaches to the Leader (DUT) and requests complete 224 # network data 225 pkts.filter_wpan_src64(MED).\ 226 filter_wpan_dst64(LEADER).\ 227 filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ 228 filter(lambda p: { 229 RESPONSE_TLV, 230 LINK_LAYER_FRAME_COUNTER_TLV, 231 MODE_TLV, 232 TIMEOUT_TLV, 233 VERSION_TLV, 234 TLV_REQUEST_TLV, 235 ADDRESS16_TLV, 236 NETWORK_DATA_TLV, 237 ADDRESS_REGISTRATION_TLV 238 } < set(p.mle.tlv.type) and\ 239 p.mle.tlv.mode.network_data == 1 240 ).\ 241 must_next() 242 243 # Step 8: The DUT MUST send a MLE Child ID Response to MED, 244 # including the following TLVs: 245 # - Network Data TLV 246 # At least two Prefix TLVs (Prefix 1 and Prefix 2), 247 # each including: 248 # - 6LoWPAN ID sub-TLV 249 # - Border Router sub-TLV 250 pkts.filter_wpan_src64(LEADER).\ 251 filter_wpan_dst64(MED).\ 252 filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\ 253 filter(lambda p: { 254 Ipv6Addr(PREFIX_2001[:-3]), 255 Ipv6Addr(PREFIX_2002[:-3]) 256 } == set(p.thread_nwd.tlv.prefix) and\ 257 p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\ 258 p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\ 259 p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\ 260 p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\ 261 p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0] 262 ).\ 263 must_next() 264 265 # Step 9: After attaching, each Child automatically sends its global address 266 # configured to the Leader, in the Address Registration TLV from the 267 # Child Update request command 268 269 # Step 10: The DUT MUST send a MLE Child Update Response, each, to MED & SED 270 # The following TLVs MUST be present in the Child Update Response: 271 # - Source Address TLV 272 # - Address Registration TLV 273 # - Echoes back addresses configured in step 9 274 # - Mode TLV 275 for child in (SED, MED): 276 _pkt = pkts.range(lstart).\ 277 filter_wpan_src64(child).\ 278 filter_wpan_dst64(LEADER).\ 279 filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\ 280 must_next() 281 pkts.range(lstart).\ 282 filter_wpan_src64(LEADER).\ 283 filter_wpan_dst64(child).\ 284 filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\ 285 filter(lambda p: { 286 SOURCE_ADDRESS_TLV, 287 MODE_TLV, 288 ADDRESS_REGISTRATION_TLV 289 } < set(p.mle.tlv.type) and\ 290 set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid) 291 ).\ 292 must_next() 293 294 295if __name__ == '__main__': 296 unittest.main() 297