mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[tests] remove cert scripts migrated to Nexus (#12516)
This commit removes several Thread certification test scripts from tests/scripts/thread-cert/ that have been migrated to the Nexus testing framework. These tests are now implemented as Nexus tests under tests/nexus/. The following test scripts were removed: - Leader Reboot: - Cert_5_5_01_LeaderReboot.py - Cert_5_5_02_LeaderReboot.py - Cert_5_5_03_SplitMergeChildren.py - Cert_5_5_04_SplitMergeRouters.py - Cert_5_5_05_SplitMergeREED.py - Cert_5_5_07_SplitMergeThreeWay.py - Network Data: - Cert_5_6_01_NetworkDataRegisterBeforeAttachLeader.py - Cert_5_6_02_NetworkDataRegisterBeforeAttachRouter.py - Cert_5_6_03_NetworkDataRegisterAfterAttachLeader.py - Cert_5_6_04_NetworkDataRegisterAfterAttachRouter.py - Cert_5_6_05_NetworkDataRegisterAfterAttachRouter.py - Cert_5_6_06_NetworkDataExpiration.py - Cert_5_6_07_NetworkDataRequestREED.py - Cert_5_6_09_NetworkDataForwarding.py - COAP Diag: - Cert_5_7_01_CoapDiagCommands.py - Cert_5_7_02_CoapDiagCommands.py - Cert_5_7_03_CoapDiagCommands.py - Router/REED Attach: - Cert_6_1_01_RouterAttach.py - Cert_6_1_02_REEDAttach.py - Cert_6_1_03_RouterAttachConnectivity.py - Cert_6_1_04_REEDAttachConnectivity.py - Cert_6_1_05_REEDAttachConnectivity.py - Cert_6_1_06_REEDAttachLinkQuality.py - Cert_6_1_07_RouterAttachLinkQuality.py - Partition and Reattach: - Cert_6_2_01_NewPartition.py - Cert_6_2_02_NewPartition.py - Cert_6_3_01_OrphanReattach.py - Cert_6_3_02_NetworkDataUpdate.py - Cert_6_4_01_LinkLocal.py - Cert_6_4_02_RealmLocal.py - Cert_6_5_01_ChildResetReattach.py - Cert_6_5_02_ChildResetReattach.py - Cert_6_5_03_ChildResetSynchronize.py - Key Increment: - Cert_6_6_01_KeyIncrement.py - Cert_6_6_02_KeyIncrementRollOver.py - Border Router: - Cert_7_1_01_BorderRouterAsLeader.py - Cert_7_1_02_BorderRouterAsRouter.py - Cert_7_1_03_BorderRouterAsLeader.py - Cert_7_1_04_BorderRouterAsRouter.py - Cert_7_1_05_BorderRouterAsRouter.py - Cert_7_1_06_BorderRouterAsLeader.py - Cert_7_1_07_BorderRouterAsLeader.py - Cert_7_1_08_BorderRouterAsFED.py
This commit is contained in:
@@ -1,216 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2018, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import copy
|
||||
import unittest
|
||||
|
||||
import command
|
||||
import config
|
||||
import mle
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_LINK_REQUEST, MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, TLV_REQUEST_TLV, VERSION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
DUT_LEADER = 1
|
||||
DUT_ROUTER1 = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to show that when the Leader is rebooted for a time period shorter than the leader timeout, it does not trigger network partitioning and remains the leader when it reattaches to the network.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Router
|
||||
|
||||
|
||||
class Cert_5_5_1_LeaderReboot(thread_cert.TestCase):
|
||||
#USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
DUT_LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [DUT_ROUTER1]
|
||||
},
|
||||
DUT_ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [DUT_LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpLeader(self):
|
||||
self.nodes[DUT_LEADER].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64())
|
||||
self.nodes[DUT_LEADER].enable_allowlist()
|
||||
|
||||
def test(self):
|
||||
self.nodes[DUT_LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[DUT_ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
|
||||
|
||||
leader_rloc = self.nodes[DUT_LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC)
|
||||
|
||||
leader_rloc16 = self.nodes[DUT_LEADER].get_addr16()
|
||||
self.nodes[DUT_LEADER].reset()
|
||||
self.assertFalse(self.nodes[DUT_ROUTER1].ping(leader_rloc))
|
||||
self._setUpLeader()
|
||||
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
self.nodes[DUT_LEADER].start()
|
||||
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[DUT_LEADER].get_addr16(), leader_rloc16)
|
||||
|
||||
router1_link_local_address = self.nodes[DUT_ROUTER1].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[DUT_LEADER].ping(router1_link_local_address))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
|
||||
# Step 1: Verify topology is formed correctly.
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
|
||||
# Step 2: The DUT MUST send properly formatted MLE Advertisements with
|
||||
# an IP Hop Limit of 255 to the Link-Local All Nodes multicast
|
||||
# address (FF02::1).
|
||||
# The following TLVs MUST be present in the MLE Advertisements:
|
||||
# - Leader Data TLV
|
||||
# - Route64 TLV
|
||||
# - Source Address TLV
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_mle_advertisement('Router').\
|
||||
must_next()
|
||||
|
||||
pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER).\
|
||||
must_next()
|
||||
lstart = pkts.index
|
||||
|
||||
# Step 4: The Leader MUST send a multicast Link Request
|
||||
# The following TLVs MUST be present in the Link Request:
|
||||
# - Challenge TLV
|
||||
# - Version TLV
|
||||
# - TLV Request TLV: Address16 TLV, Route64 TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_LINK_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
VERSION_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV,
|
||||
ROUTE64_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.addr16 is nullField and\
|
||||
p.mle.tlv.route64.id_mask is nullField
|
||||
).\
|
||||
must_next()
|
||||
lend = pkts.index
|
||||
|
||||
# Step 3: Reset Leader. The Leader MUST stop sending MLE advertisements.
|
||||
# The Leader reboot time MUST be less than Leader Timeout value
|
||||
pkts.range(lstart, lend).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_not_next()
|
||||
|
||||
# Step 5: Router MUST reply with a Link Accept
|
||||
# The following TLVs MUST be present in the Link Accept:
|
||||
# - Leader Data TLV
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Response TLV
|
||||
# - Source Address TLV
|
||||
# - Address16 TLV
|
||||
# - Route64 TLV
|
||||
# - Version TLV
|
||||
# - Challenge TLV (situational)
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
# The Challenge TLV MUST be included
|
||||
# if the response is an Accept and Request message.
|
||||
_pkt = pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd2(MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST).\
|
||||
filter(lambda p: {
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
ADDRESS16_TLV,
|
||||
ROUTE64_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.addr16 is not nullField and\
|
||||
p.mle.tlv.route64.id_mask is not nullField
|
||||
).\
|
||||
must_next()
|
||||
if _pkt.mle.cmd == MLE_LINK_ACCEPT_AND_REQUEST:
|
||||
_pkt.must_verify(lambda p: {CHALLENGE_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 7: Router_1 MUST respond with an ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
must_next()
|
||||
lend2 = pkts.index
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
must_next()
|
||||
|
||||
# Step 6: The Leader MUST NOT send a Parent Request after it is re-enabled.
|
||||
pkts.range(lend, lend2).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
must_not_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,188 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_LINK_REQUEST, MLE_LINK_ACCEPT_AND_REQUEST, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED = 3
|
||||
|
||||
|
||||
class Cert_5_5_2_LeaderReboot(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpLeader(self):
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER].get_addr64())
|
||||
self.nodes[LEADER].enable_allowlist()
|
||||
self.nodes[LEADER].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].reset()
|
||||
self._setUpLeader()
|
||||
self.simulator.go(150)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_RESET_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'router')
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[ROUTER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
# Step 2: The DUT MUST send properly formatted MLE Advertisements
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_lpkts = leader_pkts.range(_rpkts.index)
|
||||
_lpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
_rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 4: Router_1 MUST attempt to reattach to its original partition by
|
||||
# sending MLE Parent Requests to the All-Routers multicast
|
||||
# address (FFxx::xx) with a hop limit of 255. MUST make two separate attempts
|
||||
for i in range(1, 3):
|
||||
_rpkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1)
|
||||
lreset_start = _rpkts.index
|
||||
|
||||
# Step 6:Router_1 MUST attempt to attach to any other Partition
|
||||
# within range by sending a MLE Parent Request.
|
||||
_rpkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type))
|
||||
lreset_stop = _rpkts.index
|
||||
|
||||
# Step 3: The Leader MUST stop sending MLE advertisements.
|
||||
leader_pkts.range(lreset_start, lreset_stop).filter_mle_cmd(MLE_ADVERTISEMENT).must_not_next()
|
||||
|
||||
# Step 5: Leader MUST NOT respond to the MLE Parent Requests
|
||||
leader_pkts.range(lreset_start, lreset_stop).filter_mle_cmd(MLE_PARENT_RESPONSE).must_not_next()
|
||||
|
||||
# Step 7: Take over leader role of a new Partition and
|
||||
# begin transmitting MLE Advertisements
|
||||
with _rpkts.save_index():
|
||||
_rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 8: Router_1 MUST respond with an MLE Child Update Response,
|
||||
# with the updated TLVs of the new partition
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 9: The Leader MUST send properly formatted MLE Parent
|
||||
# Requests to the All-Routers multicast address
|
||||
_lpkts.range(lreset_stop).filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: Router_1 MUST send an MLE Parent Response
|
||||
_rpkts.filter_mle_cmd(MLE_PARENT_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, LINK_LAYER_FRAME_COUNTER_TLV, RESPONSE_TLV, CHALLENGE_TLV,
|
||||
LINK_MARGIN_TLV, CONNECTIVITY_TLV, VERSION_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 11: Leader send MLE Child ID Request
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
#Step 12: Router_1 send MLE Child ID Response
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV} <= set(
|
||||
p.mle.tlv.type))
|
||||
|
||||
#Step 13: Leader send an Address Solicit Request
|
||||
_lpkts.filter_coap_request(ADDR_SOL_URI).must_next().must_verify(
|
||||
lambda p: p.thread_address.tlv.ext_mac_addr and p.thread_address.tlv.status != 0)
|
||||
|
||||
#Step 14: Router_1 send an Address Solicit Response
|
||||
_rpkts.filter_coap_ack(ADDR_SOL_URI).must_next().must_verify(
|
||||
lambda p: p.thread_address.tlv.router_mask_assigned and p.thread_address.tlv.rloc16 is not nullField and p.
|
||||
thread_address.tlv.status == 0)
|
||||
|
||||
#Step 15: Leader Send a Multicast Link Request
|
||||
#Step 16: Router_1 send a Unicast Link Accept
|
||||
# Steps 15 and 16 are skipped since new router no longer
|
||||
# send multicast Link Request.
|
||||
|
||||
#Step 17: Router_1 MUST respond with an ICMPv6 Echo Reply
|
||||
_rpkts.filter_ping_request().filter_wpan_dst64(MED).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,215 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import thread_cert
|
||||
import config
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, ACTIVE_TIMESTAMP_TLV, NL_PARENT_PARTITION_CHANGE
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ED2 = 4
|
||||
ED3 = 5
|
||||
|
||||
MTDS = [ED2, ED3]
|
||||
|
||||
|
||||
class Cert_5_5_3_SplitMergeChildren(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED2]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED3]
|
||||
},
|
||||
ED2: {
|
||||
'name': 'MED_2',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
ED3: {
|
||||
'name': 'MED_3',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER2]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpLeader(self):
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[LEADER].enable_allowlist()
|
||||
self.nodes[LEADER].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED2].get_state(), 'child')
|
||||
|
||||
self.nodes[ED3].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED2].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].reset()
|
||||
self._setUpLeader()
|
||||
self.nodes[ROUTER2].set_preferred_partition_id(0xffffffff)
|
||||
|
||||
self.simulator.go(150)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_RESET_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'router')
|
||||
|
||||
self.simulator.go(30)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'leader')
|
||||
|
||||
self.collect_rloc16s()
|
||||
|
||||
addrs = self.nodes[ED3].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ED2].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
MED_2 = pv.vars['MED_2']
|
||||
MED_3 = pv.vars['MED_3']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
_router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
|
||||
# Step 2: The Leader and Router_1 MUST send properly formatted MLE Advertisements
|
||||
pkts.filter_wpan_src64(LEADER).filter_LLANMA().filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
_pkt = pkts.filter_wpan_src64(ROUTER_1).filter_LLANMA().filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
_pkt.must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type) and p.ipv6.hlim == 255)
|
||||
|
||||
# Step 4: Router_1 MUST attempt to reattach to its original partition by
|
||||
# sending MLE Parent Requests to the All-Routers multicast address
|
||||
_router1_pkts.range(pkts.index).filter_LLARMA().filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1 and p.ipv6.hlim == 255)
|
||||
lreset_start = _router1_pkts.index
|
||||
|
||||
# Step 6: Router_1 MUST attempt to attach to any other Partition
|
||||
# within range by sending a MLE Parent Request.
|
||||
_router1_pkts.filter_LLARMA().filter_mle_cmd(MLE_PARENT_REQUEST).filter(
|
||||
lambda p: p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type
|
||||
) and p.ipv6.hlim == 255)
|
||||
lreset_stop = _router1_pkts.index
|
||||
|
||||
# Step 3: The Leader MUST stop sending MLE advertisements.
|
||||
_lpkts.range(lreset_start, lreset_stop).filter_LLARMA().filter_mle_cmd(MLE_ADVERTISEMENT).must_not_next()
|
||||
|
||||
# Step 5: Leader MUST NOT respond to the MLE Parent Requests
|
||||
_lpkts.range(lreset_start,
|
||||
lreset_stop).filter_wpan_src64(LEADER).filter_mle_cmd(MLE_PARENT_RESPONSE).must_not_next()
|
||||
|
||||
# Step 7: Router_1 takes over leader role of a new Partition and
|
||||
# begin transmitting MLE Advertisements
|
||||
with _router1_pkts.save_index():
|
||||
_router1_pkts.filter_LLANMA().filter_mle_cmd(MLE_ADVERTISEMENT).filter(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type) and p.mle.tlv.
|
||||
leader_data.partition_id != _pkt.mle.tlv.leader_data.partition_id and p.mle.tlv.leader_data.
|
||||
data_version != _pkt.mle.tlv.leader_data.data_version and p.mle.tlv.leader_data.stable_data_version !=
|
||||
_pkt.mle.tlv.leader_data.stable_data_version and p.ipv6.hlim == 255).must_next()
|
||||
|
||||
# Step 9: Router_1 MUST respond with an MLE Child Update Response,
|
||||
# with the updated TLVs of the new partition
|
||||
_router1_pkts.filter_wpan_dst64(MED_2).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: The Leader MUST send properly formatted MLE Parent
|
||||
# Requests to the All-Routers multicast address
|
||||
_lpkts.filter_LLARMA().filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type
|
||||
) and p.ipv6.hlim == 255)
|
||||
|
||||
# Step 11: Leader send MLE Child ID Request to Router_2
|
||||
_lpkts.filter_wpan_dst64(ROUTER_2).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 12: Leader send MLE ADVERTISEMENT
|
||||
_lpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type) and p.ipv6.hlim == 255)
|
||||
|
||||
# Step 13: Router_1 send an Address Solicit Request
|
||||
_router1_pkts.filter_coap_request(ADDR_SOL_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == LEADER_RLOC16 and p.thread_address.tlv.ext_mac_addr is not nullField and p.
|
||||
thread_address.tlv.status == NL_PARENT_PARTITION_CHANGE)
|
||||
|
||||
# Step 14: MED_2 MUST receive an ICMPv6 Echo Reply from MED_3
|
||||
p = pkts.filter_ping_request().filter_wpan_src64(MED_2).must_next()
|
||||
pkts.filter_ping_reply(identifier=p.icmpv6.echo.identifier).filter_wpan_src64(MED_3).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,150 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, ROUTE64_TLV, LEADER_DATA_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
ROUTER4 = 5
|
||||
|
||||
|
||||
class Cert_5_5_4_SplitMergeRouters(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER3]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER4]
|
||||
},
|
||||
ROUTER3: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
ROUTER4: {
|
||||
'name': 'ROUTER_4',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER2]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpLeader(self):
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[LEADER].enable_allowlist()
|
||||
self.nodes[LEADER].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER3].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER4].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER4].get_state(), 'router')
|
||||
|
||||
self.nodes[LEADER].reset()
|
||||
self._setUpLeader()
|
||||
self.simulator.go(150)
|
||||
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(50 + config.LEADER_RESET_DELAY)
|
||||
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'router')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ROUTER4].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ROUTER3].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_3 = pv.vars['ROUTER_3']
|
||||
ROUTER_4 = pv.vars['ROUTER_4']
|
||||
leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
|
||||
# Step 2: The Leader MUST send properly formatted MLE Advertisements
|
||||
router1_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
leader_pkts.range(router1_pkts.index).filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, ROUTE64_TLV, LEADER_DATA_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
|
||||
lreset_start = router1_pkts.index
|
||||
|
||||
router1_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
lreset_stop = router1_pkts.index
|
||||
|
||||
# Step 3: The Leader MUST stop sending MLE advertisements.
|
||||
leader_pkts.range(lreset_start, lreset_stop).filter_mle_cmd(MLE_ADVERTISEMENT).must_not_next()
|
||||
|
||||
# Step 5: Router_4 MUST send an ICMPv6 Echo Reply to Router_3
|
||||
router3_mleid = pv.vars['ROUTER_3_MLEID']
|
||||
router4_mleid = pv.vars['ROUTER_4_MLEID']
|
||||
pkts.filter_wpan_src64(ROUTER_3).filter(
|
||||
lambda p: p.ipv6.src == router3_mleid and p.ipv6.dst == router4_mleid).filter_ping_request().must_next()
|
||||
pkts.filter_wpan_src64(ROUTER_4).filter(
|
||||
lambda p: p.ipv6.src == router4_mleid and p.ipv6.dst == router3_mleid).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,215 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from 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
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
ROUTER15 = 16
|
||||
REED1 = 17
|
||||
|
||||
|
||||
class Cert_5_5_5_SplitMergeREED(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER2, ROUTER3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ROUTER15]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER3]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED1]
|
||||
},
|
||||
ROUTER3: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER1]
|
||||
},
|
||||
5: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
6: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
7: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
8: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
9: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
10: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
11: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
12: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
13: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
14: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
15: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER15: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
REED1: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in range(ROUTER2, ROUTER15 + 1):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[REED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED1].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER1].add_allowlist(self.nodes[REED1].get_addr64())
|
||||
self.nodes[REED1].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
|
||||
self.nodes[ROUTER3].stop()
|
||||
self.simulator.go(140)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[REED1].get_state(), 'router')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
|
||||
addrs = self.nodes[LEADER].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
ROUTER_3 = pv.vars['ROUTER_3']
|
||||
REED = pv.vars['REED']
|
||||
router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
router2_pkts = pkts.filter_wpan_src64(ROUTER_2)
|
||||
reed_pkts = pkts.filter_wpan_src64(REED)
|
||||
|
||||
router2_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(REED).must_next()
|
||||
_start_idx = router2_pkts.index
|
||||
reed_pkts.index = _start_idx
|
||||
|
||||
# Step 3: Remove Router_3 from the network
|
||||
# Router_1 attempt to re-attach to partition.
|
||||
# Sends multicast Parent Request to Routers and REEDs
|
||||
router1_pkts.range(_start_idx).must_next()
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
|
||||
|
||||
# filter MLE_ADVERTISEMENT with 16 routing table entry:
|
||||
# 1 byte ID Sequence + 8 bytes ID Mask + 16 bytes Routing Table Entry =
|
||||
# 25 (Router64 tlv length)
|
||||
pkts.range(_start_idx).filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: 25 in p.mle.tlv.len).must_next()
|
||||
_end_idx = pkts.index
|
||||
|
||||
# Step 2: The DUT MUST NOT attempt to become an active router by sending an Address Solicit Request
|
||||
reed_pkts.range(_start_idx, _end_idx).filter_coap_request(ADDR_SOL_URI).must_not_next()
|
||||
|
||||
# Step 4: The DUT send a Parent Response to Router_1
|
||||
reed_pkts.filter_mle_cmd(MLE_PARENT_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst64 == ROUTER_1)
|
||||
|
||||
# Step 5: Router_1 Send MLE Child ID Request to the DUT
|
||||
router1_pkts.range(reed_pkts.index).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
|
||||
# Step 6: DUT send an Address Solicit Request to Leader,
|
||||
# receives short address and becomes a router
|
||||
pkts.range(_end_idx).filter_wpan_src64(REED).filter_coap_request(ADDR_SOL_URI).must_next().must_verify(
|
||||
lambda p: {NL_MAC_EXTENDED_ADDRESS_TLV, NL_STATUS_TLV} <= set(p.coap.tlv.type))
|
||||
|
||||
# Step 7: DUT send a Multicast Link Request
|
||||
# Step 7 is skipped since new router no longer sends
|
||||
# multicast Link Request.
|
||||
|
||||
# Step 8: DUT send Child ID Response to Router_1
|
||||
reed_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst64 == ROUTER_1)
|
||||
|
||||
# Step 9: The DUT MUST route the ICMPv6 Echo request to the Leader.
|
||||
# The DUT MUST route the ICMPv6 Echo reply back to Router_1
|
||||
leader_mleid = pv.vars['LEADER_MLEID']
|
||||
router1_mleid = pv.vars['ROUTER_1_MLEID']
|
||||
reed_pkts.filter_ipv6_src_dst(router1_mleid, leader_mleid).filter_ping_request().must_next()
|
||||
reed_pkts.filter_ipv6_src_dst(leader_mleid, router1_mleid).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,188 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, LINK_LAYER_FRAME_COUNTER_TLV, RESPONSE_TLV, LINK_MARGIN_TLV, CONNECTIVITY_TLV, TIMEOUT_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER1 = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
|
||||
|
||||
class Cert_5_5_7_SplitMergeThreeWay(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER1: {
|
||||
'name': 'LEADER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2, ROUTER3]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1]
|
||||
},
|
||||
ROUTER3: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpLeader1(self):
|
||||
self.nodes[LEADER1].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[LEADER1].add_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[LEADER1].add_allowlist(self.nodes[ROUTER3].get_addr64())
|
||||
self.nodes[LEADER1].enable_allowlist()
|
||||
self.nodes[LEADER1].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER1].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER3].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
|
||||
|
||||
self.nodes[LEADER1].reset()
|
||||
self._setUpLeader1()
|
||||
self.simulator.go(140)
|
||||
|
||||
self.nodes[LEADER1].start()
|
||||
self.simulator.go(30 + config.LEADER_RESET_DELAY)
|
||||
|
||||
addrs = self.nodes[LEADER1].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
addrs = self.nodes[ROUTER2].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
addrs = self.nodes[ROUTER3].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER_1']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
ROUTER_3 = pv.vars['ROUTER_3']
|
||||
leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
router2_pkts = pkts.filter_wpan_src64(ROUTER_2)
|
||||
router3_pkts = pkts.filter_wpan_src64(ROUTER_3)
|
||||
|
||||
# Step 2: The Leader and Router_1 MUST send properly formatted MLE Advertisements
|
||||
leader_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_lpkts = leader_pkts.copy()
|
||||
_lpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
router1_pkts.range(leader_pkts.index).filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 4: Each router forms a partition with the lowest possible partition ID
|
||||
# Step 5: Router_1 MUST send MLE Parent Requests and MUST make two separate attempts
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1)
|
||||
lreset_start = router1_pkts.index
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1)
|
||||
|
||||
# Step 7: Router_1 MUST attempt to attach to any other Partition
|
||||
# within range by sending a MLE Parent Request.
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type))
|
||||
lreset_stop = router1_pkts.index
|
||||
|
||||
# Step 3: The Leader MUST stop sending MLE advertisements.
|
||||
leader_pkts.range(lreset_start, lreset_stop).filter_mle_cmd(MLE_ADVERTISEMENT).must_not_next()
|
||||
|
||||
# Step 6: The Leader does not respond to the Parent Requests
|
||||
leader_pkts.range(lreset_start, lreset_stop).filter_mle_cmd(MLE_PARENT_RESPONSE).must_not_next()
|
||||
|
||||
# Step 8: Router_1 take over leader role of a new Partition and begin transmitting
|
||||
# MLE Advertisements
|
||||
router1_pkts.copy().filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 9: The Leader MUST send properly formatted MLE Parent Requests to the
|
||||
# All-Routers multicast address
|
||||
_lpkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: Router_1 MUST send an MLE Parent Response
|
||||
router1_pkts.filter_mle_cmd(MLE_PARENT_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, LINK_LAYER_FRAME_COUNTER_TLV, RESPONSE_TLV, CHALLENGE_TLV,
|
||||
LINK_MARGIN_TLV, CONNECTIVITY_TLV, VERSION_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 11: Leader send MLE Child ID Request
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 12: DUT (Router or Leader) MUST respond with a ICMPv6 Echo Reply
|
||||
_lpkts.filter_ping_reply().must_next()
|
||||
router2_pkts.filter_ping_reply().must_next()
|
||||
router3_pkts.filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,173 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_LINK_REQUEST, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, 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
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_1_NetworkDataLeaderAsBr(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED1, SED1]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
_mpkts = pkts.filter_wpan_src64(MED)
|
||||
_spkts = pkts.filter_wpan_src64(SED)
|
||||
|
||||
# Step 3: The DUT MUST request the Network Data TLV during the
|
||||
# attaching procedure when sending MLE Child ID Request frame
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
_rpkts_med = _rpkts.copy()
|
||||
_rpkts_sed = _rpkts.copy()
|
||||
|
||||
# Step 6: The DUT MUST send an MLE Child ID Response to SED_1,
|
||||
# containing only stable Network Data
|
||||
_rpkts_sed.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV} <= set(p.thread_nwd.tlv.type) and
|
||||
{Ipv6Addr('2001:2:0:1::')} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p ==
|
||||
[1] and p.thread_nwd.tlv.border_router.flag.s == [1] and p.thread_nwd.tlv.border_router.flag.r == [1] and p
|
||||
.thread_nwd.tlv.border_router.flag.o == [1] and p.thread_nwd.tlv.stable == [1, 1, 1])
|
||||
|
||||
# Step 8: The DUT MUST send a MLE Child ID Response to MED_1,
|
||||
# containing the full Network Data
|
||||
_rpkts_med.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
|
||||
# Step 10: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to each of MED_1 and SED_1
|
||||
_rpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: p.wpan.dst64 == MED and
|
||||
{SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
_rpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: p.wpan.dst64 == SED and
|
||||
{SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 11: MED_1 and SED_1 MUST respond to each ICMPv6 Echo Request
|
||||
# with an ICMPv6 Echo Reply
|
||||
med_rloc16 = pv.vars['MED_RLOC16']
|
||||
sed_rloc16 = pv.vars['SED_RLOC16']
|
||||
router_rloc16 = pv.vars['ROUTER_RLOC16']
|
||||
_mpkts.range(_rpkts_med.index).filter(
|
||||
lambda p: p.wpan.src16 == med_rloc16 and p.wpan.dst16 == router_rloc16).filter_ping_reply().must_next()
|
||||
_spkts.range(_rpkts_sed.index).filter(
|
||||
lambda p: p.wpan.src16 == sed_rloc16 and p.wpan.dst16 == router_rloc16).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, MLE_CHILD_UPDATE_RESPONSE, MODE_TLV, LEADER_DATA_TLV, ROUTE64_TLV, SOURCE_ADDRESS_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ADDRESS_REGISTRATION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_2_NetworkDataRouterAsBr(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, ED1, SED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
|
||||
# Step 1: The DUT MUST send properly formatted MLE Advertisements
|
||||
_lpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {LEADER_DATA_TLV, ROUTE64_TLV, SOURCE_ADDRESS_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 3: The DUT MUST properly attach Router_1 device to the network,
|
||||
# and transmit Network Data during the attach phase in the
|
||||
# Child ID Response frame of the Network Data TLV
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst64 == ROUTER and {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 5: The DUT Automatically sends a CoAP Response frame and
|
||||
# MLE Data Response message
|
||||
_lpkts.filter_coap_ack(ADDR_SOL_URI).must_next()
|
||||
_lpkts.filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
_lpkts_med = _lpkts.copy()
|
||||
_lpkts_sed = _lpkts.copy()
|
||||
|
||||
# Step 7: The DUT MUST send a MLE Child ID Response to SED_1,
|
||||
# containing the stable Network Data
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {Ipv6Addr('2001:2:0:1::')} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.
|
||||
flag.p == [1] and p.thread_nwd.tlv.border_router.flag.s == [1] and p.thread_nwd.tlv.border_router.flag.r ==
|
||||
[1] and p.thread_nwd.tlv.border_router.flag.o == [1] and p.thread_nwd.tlv.stable == [1, 1, 1])
|
||||
|
||||
# Step 9: The DUT MUST send a MLE Child ID Response to MED_1,
|
||||
# containing the full Network Data
|
||||
_lpkts_med.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
|
||||
# Step 10: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to each of MED_1 and SED_1
|
||||
_lpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,155 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, ADDR_SOL_URI, MLE_CHILD_UPDATE_RESPONSE, MODE_TLV, LEADER_DATA_TLV, ROUTE64_TLV, SOURCE_ADDRESS_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ADDRESS_REGISTRATION_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_3_NetworkDataRegisterAfterAttachLeader(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED1, SED1]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.simulator.go(10)
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
_rpkts_med = _rpkts.copy()
|
||||
_rpkts_sed = _rpkts.copy()
|
||||
|
||||
# Step 3: The DUT MUST multicast a MLE Data Response for each
|
||||
# prefix sent by the Leader (Prefix 1 and Prefix 2)
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next(
|
||||
).must_verify(lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix)
|
||||
and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.border_router.flag.s ==
|
||||
[1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.border_router.
|
||||
flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
|
||||
# Step 5: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to MED_1
|
||||
_rpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 6: The DUT MUST send a unicast MLE Child Update
|
||||
# Request to SED_1
|
||||
_rpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and {Ipv6Addr('2001:2:0:1::')} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.
|
||||
border_router.flag.p == [1] and p.thread_nwd.tlv.border_router.flag.s == [1] and p.thread_nwd.tlv.
|
||||
border_router.flag.r == [1] and p.thread_nwd.tlv.border_router.flag.o == [1] and p.thread_nwd.tlv.stable ==
|
||||
[1, 1, 1] and p.thread_nwd.tlv.border_router_16 == [0xFFFE])
|
||||
|
||||
# Step 8: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to SED_1
|
||||
_rpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,162 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, SVR_DATA_URI, MLE_CHILD_UPDATE_RESPONSE, MODE_TLV, LEADER_DATA_TLV, ROUTE64_TLV, SOURCE_ADDRESS_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ADDRESS_REGISTRATION_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_4_NetworkDataRegisterAfterAttachRouter(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, ED1, SED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.simulator.go(10)
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next()
|
||||
|
||||
# Step 3: The DUT Automatically sends a CoAP Response frame and
|
||||
# MLE Data Response message
|
||||
_lpkts.copy().filter_coap_ack(SVR_DATA_URI).must_next()
|
||||
|
||||
_lpkts_med = _lpkts.copy()
|
||||
_lpkts_sed = _lpkts.copy()
|
||||
|
||||
# Step 4: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information collected from Router_1
|
||||
_lpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next(
|
||||
).must_verify(lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix)
|
||||
and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.border_router.flag.s ==
|
||||
[1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.border_router.
|
||||
flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
|
||||
# Step 7: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to MED_1
|
||||
_lpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 9: The DUT MUST send a unicast MLE Child Update
|
||||
# Request to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and {Ipv6Addr('2001:2:0:1::')} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.
|
||||
border_router.flag.p == [1] and p.thread_nwd.tlv.border_router.flag.s == [1] and p.thread_nwd.tlv.
|
||||
border_router.flag.r == [1] and p.thread_nwd.tlv.border_router.flag.o == [1] and p.thread_nwd.tlv.stable ==
|
||||
[1, 1, 1] and p.thread_nwd.tlv.border_router_16 == [0xFFFE])
|
||||
|
||||
# Step 11: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, SVR_DATA_URI, MLE_CHILD_UPDATE_RESPONSE, MODE_TLV, LEADER_DATA_TLV, ROUTE64_TLV, SOURCE_ADDRESS_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ADDRESS_REGISTRATION_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_5_NetworkDataRegisterAfterAttachRouter(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, ED1, SED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:3::/64', 'paos')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
self.simulator.set_lowpan_context(3, '2001:2:0:3::/64')
|
||||
|
||||
self.simulator.go(10)
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next()
|
||||
|
||||
# Step 3: The DUT Automatically sends a CoAP Response frame and
|
||||
# MLE Data Response message
|
||||
_lpkts.copy().filter_coap_ack(SVR_DATA_URI).must_next()
|
||||
|
||||
_lpkts_med = _lpkts.copy()
|
||||
_lpkts_sed = _lpkts.copy()
|
||||
|
||||
# Step 4: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information collected from Router_1
|
||||
_lpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next(
|
||||
).must_verify(lambda p: {Ipv6Addr('2001:2:0:1::'),
|
||||
Ipv6Addr('2001:2:0:2::'),
|
||||
Ipv6Addr('2001:2:0:3::')} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.
|
||||
border_router.flag.p == [1, 1, 1] and p.thread_nwd.tlv.border_router.flag.s == [1, 1, 1] and p.
|
||||
thread_nwd.tlv.border_router.flag.r == [1, 1, 0] and p.thread_nwd.tlv.border_router.flag.o ==
|
||||
[1, 1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0, 1, 1, 1])
|
||||
|
||||
# Step 7: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to MED_1
|
||||
_lpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 8: The DUT MUST send a unicast MLE Child Update
|
||||
# Request to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:3::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 0] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [1, 1, 1, 1, 1, 1])
|
||||
|
||||
# Step 10: The DUT MUST send a unicast MLE Child Update
|
||||
# Response to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,225 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, SVR_DATA_URI, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED1 = 3
|
||||
SED1 = 4
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_5_6_6_NetworkDataExpiration(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, ED1, SED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:3::/64', 'paos')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
self.simulator.set_lowpan_context(3, '2001:2:0:3::/64')
|
||||
|
||||
self.simulator.go(10)
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
self.nodes[ROUTER].remove_prefix('2001:2:0:3::/64')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
self.simulator.go(310)
|
||||
|
||||
addrs = self.nodes[ED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:3] == '200':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
self.nodes[ROUTER].stop()
|
||||
self.simulator.go(10)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_lpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next()
|
||||
|
||||
# Step 4: The DUT Automatically sends a CoAP Response frame to Router_1
|
||||
_lpkts.copy().filter_ipv6_dst(pv.vars['ROUTER_RLOC']).filter_coap_ack(SVR_DATA_URI).must_next()
|
||||
|
||||
# Step 5: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information collected from Router_1
|
||||
_lpkts_med = _lpkts.copy()
|
||||
_lpkts_sed = _lpkts.copy()
|
||||
_lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV,
|
||||
NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and {
|
||||
Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::'),
|
||||
Ipv6Addr('2001:2:0:3::')
|
||||
} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0, 1, 1, 1])
|
||||
|
||||
# Step 7: The DUT MUST send a unicast MLE Child Update Response to MED_1
|
||||
_lpkts_med.filter_wpan_dst64(MED).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 8: The DUT MUST send a unicast MLE Child Update Request to SED_1
|
||||
_lpkts_sed.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and {
|
||||
NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and {
|
||||
Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:3::')
|
||||
} == set(p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16))
|
||||
|
||||
# Step 10: The DUT MUST send a unicast MLE Child Update Response to SED_1
|
||||
_pkt = _lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next()
|
||||
_pkt.must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 12: The DUT updates Router ID Set and removes Router_1
|
||||
# from Network Data TLV after Router_1 power off
|
||||
# Step 13: The DUT MUST multicast a MLE Data Response with the
|
||||
# new network information
|
||||
_lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
).must_next().must_verify(
|
||||
lambda p: {
|
||||
NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV,
|
||||
NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and
|
||||
{Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::'),
|
||||
Ipv6Addr('2001:2:0:3::')} == set(p.thread_nwd.tlv.prefix) and p.mle.tlv.leader_data.data_version ==
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256)
|
||||
|
||||
# Step 15: The DUT MUST send a unicast MLE Child Update Response to MED_1
|
||||
_lpkts_med.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(MED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type)
|
||||
and p.mle.tlv.leader_data.data_version == (_pkt.mle.tlv.leader_data.data_version + 1) % 256 and p.mle.tlv.
|
||||
leader_data.stable_data_version == (_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256)
|
||||
|
||||
# Step 16: The DUT MUST send a unicast MLE Child Update Request to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.leader_data.data_version ==
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256)
|
||||
|
||||
# Step 18: The DUT MUST send a unicast MLE Child Update Response to SED_1
|
||||
_lpkts_sed.filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).filter_wpan_dst64(SED).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,181 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE, MLE_DATA_REQUEST, MLE_DATA_RESPONSE, TLV_REQUEST_TLV, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
ROUTER15 = 16
|
||||
REED1 = 17
|
||||
|
||||
|
||||
class Cert_5_6_7_NetworkDataRequestREED(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2, ROUTER3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ROUTER15]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED1]
|
||||
},
|
||||
ROUTER3: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
5: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
6: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
7: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
8: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
9: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
10: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
11: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
12: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
13: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
14: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
15: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER15: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
REED1: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in range(ROUTER1, ROUTER15 + 1):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.nodes[REED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED1].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER2].remove_allowlist(self.nodes[REED1].get_addr64())
|
||||
self.nodes[REED1].remove_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:3::/64', 'paros')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:3::/64')
|
||||
|
||||
self.simulator.go(2)
|
||||
|
||||
self.nodes[ROUTER2].add_allowlist(self.nodes[REED1].get_addr64())
|
||||
self.nodes[REED1].add_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
|
||||
self.simulator.go(30)
|
||||
self.simulator.go(600)
|
||||
|
||||
addrs = self.nodes[REED1].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:3' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:3':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
REED = pv.vars['REED']
|
||||
|
||||
# Step 4: Leader multicasts a MLE Data Response with the new information
|
||||
_pkt = pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(REED).must_next()
|
||||
pkts.filter_wpan_src64(LEADER).filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV} <= set(p.thread_nwd.tlv.type))
|
||||
|
||||
# Step 8: REED1 MUST send a MLE Data Request to its parent to get the new Network Dataset.
|
||||
# MLE Data Request includes a TLV Request TLV for Network Data TLV
|
||||
pkts.filter_wpan_src64(REED).filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
|
||||
lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: REED1 send MLE Advertisement
|
||||
pkts.filter_wpan_src64(REED).filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: p.mle.tlv.leader_data.data_version == (_pkt.mle.tlv.leader_data.data_version + 1) % 256)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,226 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_HAS_ROUTER_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ED = 4
|
||||
SED = 5
|
||||
|
||||
MTDS = [ED, SED]
|
||||
|
||||
|
||||
class Cert_5_6_9_NetworkDataForwarding(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED, SED]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
SED: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[SED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
self.collect_ipaddrs()
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'aros', 'med')
|
||||
self.nodes[LEADER].add_route('2001:2:0:2::/64', stable=True, prf='med')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
|
||||
self.simulator.go(10)
|
||||
|
||||
self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'aos', 'med')
|
||||
self.nodes[ROUTER2].add_route('2001:2:0:2::/64', stable=True, prf='high')
|
||||
self.nodes[ROUTER2].register_netdata()
|
||||
self.simulator.go(15)
|
||||
|
||||
self.assertFalse(self.nodes[SED].ping('2001:2:0:2::1', timeout=10))
|
||||
|
||||
self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10))
|
||||
|
||||
self.nodes[ROUTER2].remove_prefix('2001:2:0:1::/64')
|
||||
self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'paros', 'high')
|
||||
self.nodes[ROUTER2].register_netdata()
|
||||
self.simulator.go(15)
|
||||
|
||||
self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10))
|
||||
|
||||
self.nodes[ROUTER2].remove_prefix('2001:2:0:1::/64')
|
||||
self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'paros', 'med')
|
||||
self.nodes[ROUTER2].register_netdata()
|
||||
self.simulator.go(15)
|
||||
|
||||
self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next()
|
||||
|
||||
# Step 4: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next(
|
||||
).must_verify(lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1] and p.thread_nwd.tlv.border_router.flag.r == [1] and p.thread_nwd.tlv
|
||||
.border_router.flag.o == [1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1])
|
||||
|
||||
# Step 5: The DUT MUST send a unicast MLE Child Update
|
||||
# Request to SED_1
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next(
|
||||
).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type
|
||||
) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set(
|
||||
p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16))
|
||||
|
||||
# Step 6: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2
|
||||
# due to higher preference
|
||||
router1_rloc16 = pv.vars['ROUTER_1_RLOC16']
|
||||
leader_rloc16 = pv.vars['LEADER_RLOC16']
|
||||
_rpkts.filter_ping_request().filter_ipv6_dst('2001:2:0:2::1').must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16)
|
||||
|
||||
# Step 7: The DUT MUST forward the MED_1 ICMPv6 Echo Request to the
|
||||
# Leader due to default route
|
||||
_rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16)
|
||||
|
||||
# Step 9: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify(
|
||||
lambda p: {
|
||||
NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV,
|
||||
NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and {
|
||||
Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')
|
||||
} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0, 1] and p.thread_nwd.
|
||||
tlv.border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd
|
||||
.tlv.border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1])
|
||||
|
||||
# Step 10: The DUT MUST send a unicast MLE Child Update Request to SED_1
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next(
|
||||
).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type
|
||||
) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set(
|
||||
p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16))
|
||||
|
||||
# Step 11: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2
|
||||
# due to higher preference
|
||||
_rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16)
|
||||
|
||||
# Step 13: The DUT MUST send a multicast MLE Data Response with
|
||||
# the new network information
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify(
|
||||
lambda p: {
|
||||
NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV,
|
||||
NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'),
|
||||
Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix))
|
||||
|
||||
# Step 14: The DUT MUST send a unicast MLE Child Update Request to SED_1
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next(
|
||||
).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type
|
||||
) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set(
|
||||
p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16))
|
||||
|
||||
# Step 15: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2
|
||||
# due to higher preference
|
||||
_rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,420 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import copy
|
||||
import mle
|
||||
import network_diag
|
||||
import network_layer
|
||||
import thread_cert
|
||||
from network_diag import TlvType
|
||||
from pktverify.consts import DIAG_RST_URI, DIAG_GET_URI, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_CONNECTIVITY_TLV, DG_ROUTE64_TLV, DG_LEADER_DATA_TLV, DG_NETWORK_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV, DG_TYPE_LIST_TLV, DG_MAC_COUNTERS_TLV, DG_TIMEOUT_TLV, DG_BATTERY_LEVEL_TLV, DG_SUPPLY_VOLTAGE_TLV, DG_CHILD_TABLE_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
REED1 = 3
|
||||
SED1 = 4
|
||||
MED1 = 5
|
||||
FED1 = 6
|
||||
|
||||
MTDS = [MED1, SED1]
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# These cases test the Diagnostic Get and Reset Commands as a part of the
|
||||
# Network Management
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# FED - Router - REED
|
||||
# / \
|
||||
# MED SED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
# FED
|
||||
|
||||
|
||||
class Cert_5_7_01_CoapDiagCommands_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1],
|
||||
},
|
||||
ROUTER1: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED1, SED1, MED1, FED1],
|
||||
},
|
||||
REED1: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1],
|
||||
'router_upgrade_threshold': 0
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'allowlist': [ROUTER1],
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT
|
||||
},
|
||||
MED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
FED1: {
|
||||
'allowlist': [ROUTER1],
|
||||
'router_upgrade_threshold': 0
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
# 1 - Form topology
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
for i in range(3, 7):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(10)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'child')
|
||||
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
self.collect_ipaddrs()
|
||||
|
||||
DUT = ROUTER1
|
||||
if self.TOPOLOGY[FED1]['name'] == 'DUT':
|
||||
DUT = FED1
|
||||
|
||||
dut_rloc = self.nodes[DUT].get_ip6_address(config.ADDRESS_TYPE.RLOC)
|
||||
|
||||
# 2 - Leader sends DIAG_GET.req
|
||||
tlv_types = [
|
||||
TlvType.EXT_ADDRESS, TlvType.ADDRESS16, TlvType.MODE, TlvType.CONNECTIVITY, TlvType.ROUTE64,
|
||||
TlvType.LEADER_DATA, TlvType.NETWORK_DATA, TlvType.IPV6_ADDRESS_LIST, TlvType.CHANNEL_PAGES
|
||||
]
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, tlv_types)
|
||||
self.simulator.go(2)
|
||||
|
||||
# 3 - Leader sends DIAG_GET.req (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 4 - Leader sends DIAG_GET.req (Timeout/Polling Period TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.POLLING_PERIOD])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 5 - Leader sends DIAG_GET.req (Battery Level and Supply Voltage TLV types included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.BATTERY_LEVEL, TlvType.SUPPLY_VOLTAGE])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 6 - Leader sends DIAG_GET.req (Child Table TLV types included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.CHILD_TABLE])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 7 - Leader sends DIAG_RST.ntf (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_reset(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 8 - Leader Sends DIAG_GET.req (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC = pv.vars['DUT_RLOC']
|
||||
DUT_RLOC16 = pv.vars['DUT_RLOC16']
|
||||
REED = pv.vars['REED']
|
||||
REED_RLOC = pv.vars['REED_RLOC']
|
||||
MED = pv.vars['MED']
|
||||
MED_RLOC = pv.vars['MED_RLOC']
|
||||
SED = pv.vars['SED']
|
||||
SED_RLOC = pv.vars['SED_RLOC']
|
||||
MM = pv.vars['MM_PORT']
|
||||
|
||||
#DUT_IPADDR =
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
if self.TOPOLOGY[ROUTER1]['name'] == 'DUT':
|
||||
FED = pv.vars['FED']
|
||||
pv.verify_attached('DUT', 'LEADER')
|
||||
pv.verify_attached('REED', 'DUT')
|
||||
pv.verify_attached('SED', 'DUT', 'MTD')
|
||||
pv.verify_attached('MED', 'DUT', 'MTD')
|
||||
pv.verify_attached('FED', 'DUT', 'FTD-ED')
|
||||
else:
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('REED', 'ROUTER')
|
||||
pv.verify_attached('SED', 'ROUTER', 'MTD')
|
||||
pv.verify_attached('MED', 'ROUTER', 'MTD')
|
||||
pv.verify_attached('DUT', 'ROUTER', 'FTD-ED')
|
||||
|
||||
# Step 2: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 4 – Connectivity
|
||||
# TLV Type 5 – Route64
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 7 – Network Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 17 – Channel Pages
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_EXTENDED_ADDRESS_TLV,
|
||||
DG_MAC_ADDRESS_TLV,
|
||||
DG_MODE_TLV,
|
||||
DG_CONNECTIVITY_TLV,
|
||||
DG_ROUTE64_TLV,
|
||||
DG_LEADER_DATA_TLV,
|
||||
DG_NETWORK_DATA_TLV,
|
||||
DG_IPV6_ADDRESS_LIST_TLV,
|
||||
DG_CHANNEL_PAGES_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_MAC_EXTENDED_ADDRESS_TLV,
|
||||
DG_MAC_ADDRESS_TLV,
|
||||
DG_MODE_TLV,
|
||||
DG_CONNECTIVITY_TLV,
|
||||
DG_ROUTE64_TLV,
|
||||
DG_LEADER_DATA_TLV,
|
||||
DG_NETWORK_DATA_TLV,
|
||||
DG_IPV6_ADDRESS_LIST_TLV,
|
||||
DG_CHANNEL_PAGES_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 9 - MAC Counters
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 3 - Timeout MUST be omitted from the response
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_TIMEOUT_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 3 - Timeout MUST be omitted from the response
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_BATTERY_LEVEL_TLV,
|
||||
DG_SUPPLY_VOLTAGE_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 16 - Child Table (is empty if FED is DUT)
|
||||
#
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_CHILD_TABLE_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
if self.TOPOLOGY[ROUTER1]['name'] == 'DUT':
|
||||
_pkt = pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_CHILD_TABLE_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
else:
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader to send DIAG_RST.req to DUT’s RLOC for the following diagnostic
|
||||
# TLV type:
|
||||
# TLV Type 9 - MAC Counters
|
||||
# The DUT MUST respond with a CoAP response
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_RST_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_RST_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 9 - MAC Counters
|
||||
# TLV Type 9 - MAC Counters MUST contain a list of MAC Counters
|
||||
# with 0 value or less than value returned in step 3.
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_5_7_01_CoapDiagCommands_Base_ROUTER(Cert_5_7_01_CoapDiagCommands_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_5_7_01_CoapDiagCommands_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'DUT'
|
||||
TOPOLOGY[FED1]['name'] = 'FED'
|
||||
|
||||
|
||||
class Cert_5_7_01_CoapDiagCommands_Base_FED(Cert_5_7_01_CoapDiagCommands_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_5_7_01_CoapDiagCommands_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
|
||||
TOPOLOGY[FED1]['name'] = 'DUT'
|
||||
|
||||
|
||||
del (Cert_5_7_01_CoapDiagCommands_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,421 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import copy
|
||||
import mle
|
||||
import network_diag
|
||||
import network_layer
|
||||
import thread_cert
|
||||
from network_diag import TlvType
|
||||
from pktverify.consts import DIAG_RST_URI, DIAG_GET_URI, DIAG_GET_QRY_URI, DIAG_GET_ANS_URI, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_CONNECTIVITY_TLV, DG_ROUTE64_TLV, DG_LEADER_DATA_TLV, DG_NETWORK_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV, DG_TYPE_LIST_TLV, DG_MAC_COUNTERS_TLV, DG_TIMEOUT_TLV, DG_BATTERY_LEVEL_TLV, DG_SUPPLY_VOLTAGE_TLV, DG_CHILD_TABLE_TLV, REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
from pktverify.utils import colon_hex
|
||||
|
||||
LEADER = 1
|
||||
ROUTER15 = 16
|
||||
REED = 17
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# This test case exercises the Diagnostic Get Query and Answer commands
|
||||
# as part of the Network Management. This test case topology is specific
|
||||
# to REED DUTs.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# / \
|
||||
# Router1 .. Router15
|
||||
# |
|
||||
# REED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# REED
|
||||
|
||||
|
||||
class Cert_5_7_02_CoapDiagCommands(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ROUTER15]
|
||||
},
|
||||
2: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
3: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
4: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
5: {
|
||||
'name': 'ROUTER_4',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
6: {
|
||||
'name': 'ROUTER_5',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
7: {
|
||||
'name': 'ROUTER_6',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
8: {
|
||||
'name': 'ROUTER_7',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
9: {
|
||||
'name': 'ROUTER_8',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
10: {
|
||||
'name': 'ROUTER_9',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
11: {
|
||||
'name': 'ROUTER_10',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
12: {
|
||||
'name': 'ROUTER_11',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
13: {
|
||||
'name': 'ROUTER_12',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
14: {
|
||||
'name': 'ROUTER_13',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
15: {
|
||||
'name': 'ROUTER_14',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER15: {
|
||||
'name': 'ROUTER_15',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED]
|
||||
},
|
||||
REED: {
|
||||
'name': 'DUT',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER15]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
# 1 - Form topology
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in range(2, 17):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.nodes[REED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED].get_state(), 'child')
|
||||
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
dut_rloc = self.nodes[REED].get_ip6_address(config.ADDRESS_TYPE.RLOC)
|
||||
|
||||
# 2 - Leader sends DIAG_GET.req
|
||||
tlv_types = [
|
||||
TlvType.EXT_ADDRESS, TlvType.ADDRESS16, TlvType.MODE, TlvType.CONNECTIVITY, TlvType.ROUTE64,
|
||||
TlvType.LEADER_DATA, TlvType.IPV6_ADDRESS_LIST, TlvType.CHANNEL_PAGES
|
||||
]
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, tlv_types)
|
||||
self.simulator.go(2)
|
||||
|
||||
# 3 - Leader sends DIAG_GET.req (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 4 - Leader sends DIAG_GET.req (Timeout/Polling Period TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.POLLING_PERIOD, TlvType.CHILD_TABLE])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 5 - Leader sends DIAG_GET.req (Battery Level and Supply Voltage TLV types included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.BATTERY_LEVEL, TlvType.SUPPLY_VOLTAGE])
|
||||
self.simulator.go(20)
|
||||
|
||||
# 6 - Leader sends DIAG_RST.ntf (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_reset(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 7 - Leader Sends DIAG_GET.req (MAC Counters TLV type included)
|
||||
self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS])
|
||||
self.simulator.go(2)
|
||||
|
||||
# 8 - Leader sends DIAG_GET.query
|
||||
self.nodes[LEADER].send_network_diag_get(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS, tlv_types)
|
||||
self.simulator.go(2)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC = pv.vars['DUT_RLOC']
|
||||
DUT_RLOC16 = pv.vars['DUT_RLOC16']
|
||||
MM = pv.vars['MM_PORT']
|
||||
|
||||
dut_addr16 = "%04x" % DUT_RLOC16
|
||||
dut_payload_tlvs = {
|
||||
DG_TYPE_LIST_TLV, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_CONNECTIVITY_TLV,
|
||||
DG_ROUTE64_TLV, DG_LEADER_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV
|
||||
}
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
for i in range(1, 16):
|
||||
with pkts.save_index():
|
||||
pv.verify_attached('ROUTER_%d' % i, 'LEADER')
|
||||
pv.verify_attached('DUT', 'ROUTER_15')
|
||||
|
||||
# Step 2: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 4 – Connectivity
|
||||
# TLV Type 5 – Route64(optional)
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 17 – Channel Pages
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type)).\
|
||||
must_next()
|
||||
dut_payload_tlvs.remove(DG_TYPE_LIST_TLV)
|
||||
dut_payload_tlvs.remove(DG_ROUTE64_TLV)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p:
|
||||
dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type) and\
|
||||
{str(p.wpan.src64), colon_hex(dut_addr16, 2), '0f'}
|
||||
< set(p.thread_diagnostic.tlv.general)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 9 - MAC Counters
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 3 - Timeout MUST be omitted from the response
|
||||
# TLV Type 16 – Child Table TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_TIMEOUT_TLV,
|
||||
DG_CHILD_TABLE_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 14 – Battery Level (optional)
|
||||
# TLV Type 15 – Supply Voltage (optional)
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_BATTERY_LEVEL_TLV,
|
||||
DG_SUPPLY_VOLTAGE_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader to send DIAG_RST.req to DUT’s RLOC for the following diagnostic
|
||||
# TLV type:
|
||||
# TLV Type 9 - MAC Counters
|
||||
# The DUT MUST respond with a CoAP response
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_RST_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_RST_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader to send DIAG_GET.req to DUT’s RLOC.
|
||||
# The DUT MUST respond with a DIAG_GET.rsp response containing
|
||||
# the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 9 - MAC Counters
|
||||
# TLV Type 9 - MAC Counters MUST contain a list of MAC Counters
|
||||
# with 0 value or less than value returned in step 3.
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(DUT_RLOC).\
|
||||
filter_coap_request(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_TYPE_LIST_TLV,
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_ack(DIAG_GET_URI).\
|
||||
filter(lambda p: {
|
||||
DG_MAC_COUNTERS_TLV
|
||||
} <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader sends DIAG_GET.qry to the Realm-Local All-Thread-Nodes
|
||||
# multicast address containing the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 4 – Connectivity
|
||||
# TLV Type 5 – Route64(optional)
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 7 – Network Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 17 – Channel Pagesi
|
||||
dut_payload_tlvs.add(DG_TYPE_LIST_TLV)
|
||||
dut_payload_tlvs.add(DG_ROUTE64_TLV)
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS).\
|
||||
filter_coap_request(DIAG_GET_QRY_URI).\
|
||||
filter(lambda p: dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
dut_payload_tlvs.remove(DG_TYPE_LIST_TLV)
|
||||
dut_payload_tlvs.remove(DG_ROUTE64_TLV)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_request(DIAG_GET_ANS_URI).\
|
||||
filter(lambda p:
|
||||
dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type) and\
|
||||
{str(p.wpan.src64), colon_hex(dut_addr16, 2), '0f'}
|
||||
< set(p.thread_diagnostic.tlv.general)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import copy
|
||||
import mle
|
||||
import network_diag
|
||||
import network_layer
|
||||
import thread_cert
|
||||
from network_diag import TlvType
|
||||
from pktverify.consts import DIAG_GET_QRY_URI, DIAG_GET_ANS_URI, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_CONNECTIVITY_TLV, DG_ROUTE64_TLV, DG_LEADER_DATA_TLV, DG_NETWORK_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV, DG_TYPE_LIST_TLV, DG_MAC_COUNTERS_TLV, DG_TIMEOUT_TLV, DG_CHILD_TABLE_TLV, REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.utils import colon_hex
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
SED1 = 3
|
||||
MED1 = 4
|
||||
FED1 = 5
|
||||
|
||||
MTDS = [MED1, SED1]
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify functionality of commands
|
||||
# Diagnostic_Get.query and Diagnostic_Get.ans. Thread Diagnostic commands
|
||||
# MUST be supported by FTDs.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# FED - Router
|
||||
# / \
|
||||
# MED SED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
# FED
|
||||
|
||||
|
||||
class Cert_5_7_03_CoapDiagCommands_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1],
|
||||
},
|
||||
ROUTER1: {
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, SED1, MED1, FED1],
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'allowlist': [ROUTER1],
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT
|
||||
},
|
||||
MED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
FED1: {
|
||||
'allowlist': [ROUTER1],
|
||||
'router_upgrade_threshold': 0
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
# 1 - Form topology
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
for i in range(3, 6):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(10)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'child')
|
||||
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
tlv_types = [
|
||||
TlvType.EXT_ADDRESS, TlvType.ADDRESS16, TlvType.MODE, TlvType.CONNECTIVITY, TlvType.ROUTE64,
|
||||
TlvType.LEADER_DATA, TlvType.NETWORK_DATA, TlvType.IPV6_ADDRESS_LIST, TlvType.CHILD_TABLE,
|
||||
TlvType.CHANNEL_PAGES
|
||||
]
|
||||
if self.TOPOLOGY[FED1]['name'] == 'DUT':
|
||||
tlv_types = [
|
||||
TlvType.EXT_ADDRESS, TlvType.ADDRESS16, TlvType.MODE, TlvType.LEADER_DATA, TlvType.NETWORK_DATA,
|
||||
TlvType.IPV6_ADDRESS_LIST, TlvType.CHANNEL_PAGES
|
||||
]
|
||||
|
||||
# 2 - Leader sends DIAG_GET.query
|
||||
self.nodes[LEADER].send_network_diag_get(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS, tlv_types)
|
||||
self.simulator.go(2)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC16 = pv.vars['DUT_RLOC16']
|
||||
SED = pv.vars['SED']
|
||||
|
||||
dut_addr16 = "%04x" % DUT_RLOC16
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
if self.TOPOLOGY[ROUTER1]['name'] == 'DUT':
|
||||
FED = pv.vars['FED']
|
||||
pv.verify_attached('DUT', 'LEADER')
|
||||
pv.verify_attached('SED', 'DUT', 'MTD')
|
||||
pv.verify_attached('MED', 'DUT', 'MTD')
|
||||
pv.verify_attached('FED', 'DUT', 'FTD-ED')
|
||||
else:
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('SED', 'ROUTER', 'MTD')
|
||||
pv.verify_attached('MED', 'ROUTER', 'MTD')
|
||||
pv.verify_attached('DUT', 'ROUTER', 'FTD-ED')
|
||||
|
||||
# Step 2: Leader sends DIAG_GET.qry to the Realm-Local All-Thread-Nodes
|
||||
# multicast address containing the requested diagnostic TLVs:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 7 – Network Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 17 – Channel Pagesi
|
||||
#
|
||||
# if DUT is Router, containing the following as well:
|
||||
# TLV Type 4 – Connectivity
|
||||
# TLV Type 5 – Route64
|
||||
# TLV Type 16 – Child Table
|
||||
_qr_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS).\
|
||||
filter_coap_request(DIAG_GET_QRY_URI).\
|
||||
must_next()
|
||||
dut_payload_tlvs = {
|
||||
DG_TYPE_LIST_TLV, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_LEADER_DATA_TLV,
|
||||
DG_NETWORK_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV
|
||||
}
|
||||
if self.TOPOLOGY[ROUTER1]['name'] == 'DUT':
|
||||
dut_payload_tlvs.update({DG_CONNECTIVITY_TLV, DG_ROUTE64_TLV, DG_CHILD_TABLE_TLV})
|
||||
_qr_pkt.must_verify(lambda p: dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type))
|
||||
|
||||
# Step 3: The DUT automatically responds with a DIAG_GET.ans response
|
||||
# MUST contain the requested diagnostic TLVs:
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 4 – Connectivity
|
||||
# TLV Type 5 – Route64
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 7 – Network Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 16 – Child Table
|
||||
# TLV Type 17 – Channel Pages
|
||||
dut_payload_tlvs.remove(DG_TYPE_LIST_TLV)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_request(DIAG_GET_ANS_URI).\
|
||||
filter(lambda p:
|
||||
dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type) and\
|
||||
{str(p.wpan.src64), colon_hex(dut_addr16, 2), '0f'}
|
||||
< set(p.thread_diagnostic.tlv.general)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: The DUT MUST use IEEE 802.15.4 indirect transmissions to forward
|
||||
# the DIAG_GET.query to SED
|
||||
dut_payload_tlvs.add(DG_TYPE_LIST_TLV)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS).\
|
||||
filter_coap_request(DIAG_GET_QRY_URI).\
|
||||
filter(lambda p:
|
||||
dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
else:
|
||||
# Step 5: The DUT automatically responds with a DIAG_GET.ans response
|
||||
# MUST contain the requested diagnostic TLVs:
|
||||
# TLV Type 0 - MAC Extended Address (64- bit)
|
||||
# TLV Type 1 - MAC Address (16-bit)
|
||||
# TLV Type 2 - Mode (Capability information)
|
||||
# TLV Type 6 – Leader Data
|
||||
# TLV Type 7 – Network Data
|
||||
# TLV Type 8 – IPv6 address list
|
||||
# TLV Type 17 – Channel Pages
|
||||
dut_payload_tlvs.remove(DG_TYPE_LIST_TLV)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_request(DIAG_GET_ANS_URI).\
|
||||
filter(lambda p:
|
||||
dut_payload_tlvs <= set(p.thread_diagnostic.tlv.type) and\
|
||||
{str(p.wpan.src64), colon_hex(dut_addr16, 2), '0f'}
|
||||
< set(p.thread_diagnostic.tlv.general)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_5_7_03_CoapDiagCommands_Base_ROUTER(Cert_5_7_03_CoapDiagCommands_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_5_7_03_CoapDiagCommands_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'DUT'
|
||||
TOPOLOGY[FED1]['name'] = 'FED'
|
||||
|
||||
|
||||
class Cert_5_7_03_CoapDiagCommands_Base_FED(Cert_5_7_03_CoapDiagCommands_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_5_7_03_CoapDiagCommands_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
|
||||
TOPOLOGY[FED1]['name'] = 'DUT'
|
||||
|
||||
|
||||
del (Cert_5_7_03_CoapDiagCommands_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import copy
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import mle
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate that the DUT is able to successfully
|
||||
# attach to a network
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_1_1_RouterAttach_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
|
||||
ed_addr = self.nodes[ED].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[LEADER].ping(ed_addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_LLA = pv.vars['LEADER_LLA']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Ensure the Leader is sending MLE Advertisements.
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
# Step 2: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# If the DUT sends multiple MLE Parent Requests
|
||||
# - The first one MUST be sent only to all Routers
|
||||
# - Subsequent ones MAY be sent to all Routers and REEDS
|
||||
# - Version TLV
|
||||
# If the first MLE Parent Request was sent to all Routers and
|
||||
# REEDS, the test fails.
|
||||
# In securing the first three messages of the attaching process,
|
||||
# the full four-byte key sequence number MUST be included in
|
||||
# the Auxiliary Security Header used for MLE security.
|
||||
#
|
||||
# To send the full four-byte key sequence number, the Key
|
||||
# Identifier Mode of the Security Control Field SHALL be set to
|
||||
# ‘0x02’, indicating the presence of a four-byte Key Source,
|
||||
# which SHALL contain the four-byte key sequence number in
|
||||
# network byte order.
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 0 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader responds with a MLE Parent Response.
|
||||
# The following TLVs MUST be present in the MLE Parent Response:
|
||||
# - Challenge TLV
|
||||
# - Connectivity TLV
|
||||
# - Leader Data TLV
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Link Margin TLV
|
||||
# - Response TLV
|
||||
# - Source Address
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Router sends a MLE Child ID Request.
|
||||
# The following TLVs MUST be present in the MLE Child ID Request:
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Address Registration TLV
|
||||
# - Mode TLV
|
||||
# - Response TLV
|
||||
# - Timeout TLV
|
||||
# - TLV Request TLV
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
ADDRESS_REGISTRATION_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
RESPONSE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader responds with a Child ID Response.
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
ADDRESS16_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Verify connectivity by sending an ICMPv6 Echo Request
|
||||
# to the DUT link local address
|
||||
# DUT responds with ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_1_1_RouterAttach_ED(Cert_6_1_1_RouterAttach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_1_RouterAttach_Base.TOPOLOGY)
|
||||
TOPOLOGY[ED]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_1_1_RouterAttach_SED(Cert_6_1_1_RouterAttach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_1_RouterAttach_Base.TOPOLOGY)
|
||||
TOPOLOGY[ED]['mode'] = '-'
|
||||
TOPOLOGY[ED]['timeout'] = config.DEFAULT_CHILD_TIMEOUT
|
||||
|
||||
|
||||
del (Cert_6_1_1_RouterAttach_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,368 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2018, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import thread_cert
|
||||
import config
|
||||
from pktverify.consts import WPAN_DATA_REQUEST, WPAN_ACK, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
REED = 2
|
||||
MTD = 3
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate that the DUT is able to successfully
|
||||
# attach to a network as an End Device through a REED.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# REED
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_1_2_REEDAttach_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [REED]
|
||||
},
|
||||
REED: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [REED]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[REED].start()
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
self.assertEqual(self.nodes[REED].get_state(), 'child')
|
||||
self.collect_rloc16s()
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[REED].get_state(), 'router')
|
||||
self.collect_ipaddrs()
|
||||
self.collect_rlocs()
|
||||
|
||||
self.simulator.go(config.DEFAULT_CHILD_TIMEOUT)
|
||||
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[REED].ping(dut_addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
REED = pv.vars['REED']
|
||||
REED_RLOC = pv.vars['REED_RLOC']
|
||||
REED_LLA = pv.vars['REED_LLA']
|
||||
REED_RLOC16 = pv.vars['REED_RLOC16']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC = pv.vars['DUT_RLOC']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Ensure the Leader is sending MLE Advertisements and is connected to REED
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
pv.verify_attached('REED', 'LEADER')
|
||||
|
||||
# Step 2: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify that the first one is sent to routers only
|
||||
# - Version TLV
|
||||
# If the first MLE Parent Request was sent to all Routers and
|
||||
# REEDS, the test fails.
|
||||
# In securing the first three messages of the attaching process,
|
||||
# the full four-byte key sequence number MUST be included in
|
||||
# the Auxiliary Security Header used for MLE security.
|
||||
#
|
||||
# To send the full four-byte key sequence number, the Key
|
||||
# Identifier Mode of the Security Control Field SHALL be set to
|
||||
# ‘0x02’, indicating the presence of a four-byte Key Source,
|
||||
# which SHALL contain the four-byte key sequence number in
|
||||
# network byte order.
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 0 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
index1 = pkts.index
|
||||
|
||||
# Step 4: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify that it is sent to Routers AND REEDs
|
||||
# - Version TLV
|
||||
# If request was not sent to all routers and REEDS, then the test
|
||||
# has failed.
|
||||
# In securing the first three messages of the attaching process,
|
||||
# the full four-byte key sequence number MUST be included in
|
||||
# the Auxiliary Security Header used for MLE security.
|
||||
# To send the full four-byte key sequence number, the Key
|
||||
# Identifier Mode of the Security Control Field SHALL be set to
|
||||
# ‘0x02’, indicating the presence of a four-byte Key Source,
|
||||
# which SHALL contain the four-byte key sequence number in
|
||||
# network byte order.
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 1 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
index2 = pkts.index
|
||||
|
||||
# Step 3: REED doesn't response to the first Parent Request
|
||||
|
||||
pkts.range(index1, index2).\
|
||||
filter_wpan_src64(REED).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
must_not_next()
|
||||
|
||||
# Step 5: REED responds with MLE Parent Response for the second Parent Request
|
||||
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 6: DUT sends a MLE Child ID Request.
|
||||
# The following TLVs MUST be present in the MLE Child ID Request:
|
||||
# - Address Registration TLV
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Mode TLV
|
||||
# - Response TLV
|
||||
# - Timeout TLV
|
||||
# - TLV Request TLV
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(REED).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
ADDRESS_REGISTRATION_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
RESPONSE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: REED sends an Address Solicit Request to Leader;
|
||||
# Leader responds with an Address Solicit Response and REED
|
||||
# becomes active router;
|
||||
# REED sends Child ID Response with DUT’s new 16-bit Address.
|
||||
|
||||
_pkt = pkts.filter_wpan_src64(REED).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_request(ADDR_SOL_URI).\
|
||||
filter(lambda p: {
|
||||
NL_MAC_EXTENDED_ADDRESS_TLV,
|
||||
NL_STATUS_TLV
|
||||
} <= set(p.coap.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst16(_pkt.wpan.src16).\
|
||||
filter_coap_ack(ADDR_SOL_URI).\
|
||||
filter(lambda p: {
|
||||
NL_STATUS_TLV,
|
||||
NL_RLOC16_TLV,
|
||||
NL_ROUTER_MASK_TLV
|
||||
} <= set(p.coap.tlv.type) and\
|
||||
p.coap.code == COAP_CODE_ACK and\
|
||||
p.thread_address.tlv.status == 0\
|
||||
).\
|
||||
must_next()
|
||||
_pkt = pkts.filter_wpan_src64(REED).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
ADDRESS16_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.source_addr != REED_RLOC16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
if self.TOPOLOGY[MTD]['mode'] == 'rn':
|
||||
# Step 8: DUT sends periodic Child Update messages as part of the
|
||||
# keep-alive message
|
||||
# The DUT MUST send MLE Child Update messages containing
|
||||
# the following TLVs:
|
||||
# - Leader Data TLV
|
||||
# - Mode TLV
|
||||
# - Source Address TLV
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(REED).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: REED Respond to Child Update messages with a MLE Update
|
||||
# Response.
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Go to Step 12
|
||||
|
||||
else:
|
||||
# Step 11: DUT sends periodic 802.15.4 Data Request messages as part
|
||||
# of the keep-alive message
|
||||
# The DUT must send a 802.15.4 Data Request command to the
|
||||
# parent device and receive an ACK message in response
|
||||
_pkt2 = pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(_pkt.mle.tlv.source_addr).\
|
||||
filter_wpan_cmd(WPAN_DATA_REQUEST).\
|
||||
must_next()
|
||||
|
||||
pkts.filter(lambda p:
|
||||
p.wpan.seq_no == _pkt2.wpan.seq_no and\
|
||||
p.wpan.frame_type == WPAN_ACK
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 12: REED verifies connectivity by sending an ICMPv6 Echo Request
|
||||
# to the DUT link local address
|
||||
# DUT responds with ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(REED_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, REED_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_1_2_REEDAttach_ED(Cert_6_1_2_REEDAttach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_2_REEDAttach_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_1_2_REEDAttach_SED(Cert_6_1_2_REEDAttach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_2_REEDAttach_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_1_2_REEDAttach_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,132 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, TIMEOUT_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
ED = 5
|
||||
|
||||
|
||||
class Cert_6_1_3_RouterAttachConnectivity(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2, ROUTER3]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER3]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED]
|
||||
},
|
||||
ROUTER3: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER1, ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER2, ROUTER3]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in range(2, 5):
|
||||
self.nodes[i].start()
|
||||
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
|
||||
for i in range(2, 5):
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[ROUTER3].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER_3 = pv.vars['ROUTER_3']
|
||||
ED = pv.vars['ED']
|
||||
_router3_pkts = pkts.filter_wpan_src64(ROUTER_3)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 2: The DUT MUST send a MLE Parent Request to the
|
||||
# All-Routers multicast address
|
||||
_ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(p.mle.tlv.type
|
||||
) and p.mle.tlv.scan_mask.r == 1)
|
||||
|
||||
# Step 3: Router_2, Router_3 Respond with MLE Parent Response
|
||||
# Step 4: DUT Send a Child ID Request to Router_3 due to better connectivity
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV,
|
||||
ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 5: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
ed_mleid = pv.vars['ED_MLEID']
|
||||
router3_mleid = pv.vars['ROUTER_3_MLEID']
|
||||
_pkt = _router3_pkts.filter(
|
||||
lambda p: p.ipv6.src == router3_mleid and p.ipv6.dst == ed_mleid).filter_ping_request().must_next()
|
||||
_ed_pkts.filter(lambda p: p.ipv6.src == ed_mleid and p.ipv6.dst == router3_mleid).filter_ping_reply(
|
||||
identifier=_pkt.icmpv6.echo.identifier).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,322 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import thread_cert
|
||||
import config
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
REED_1 = 3
|
||||
REED_2 = 4
|
||||
MTD = 5
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate that the DUT will pick REED_1
|
||||
# as its parent because of its better connectivity.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Router - Leader
|
||||
# | / |
|
||||
# REED_1 REED_2
|
||||
# \ /
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_1_4_REEDAttachConnectivity_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, REED_1, REED_2]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED_1]
|
||||
},
|
||||
REED_1: {
|
||||
'name': 'REED_1',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, ROUTER, MTD]
|
||||
},
|
||||
REED_2: {
|
||||
'name': 'REED_2',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [REED_1, REED_2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
for i in (3, 4):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
self.collect_rlocs()
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[REED_1].get_state(), 'router')
|
||||
|
||||
self.simulator.go(config.DEFAULT_CHILD_TIMEOUT)
|
||||
self.collect_ipaddrs()
|
||||
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[REED_1].ping(dut_addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
REED_1 = pv.vars['REED_1']
|
||||
REED_1_RLOC = pv.vars['REED_1_RLOC']
|
||||
REED_1_LLA = pv.vars['REED_1_LLA']
|
||||
REED_1_RLOC16 = pv.vars['REED_1_RLOC16']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC = pv.vars['DUT_RLOC']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Setup the topology without the DUT. Ensure all routers and
|
||||
# leader are sending MLE advertisements
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
|
||||
# Step 2: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify that the first one is sent to routers only
|
||||
# - Version TLV
|
||||
# If the first MLE Parent Request was sent to all Routers and
|
||||
# REED_1S, the test fails.
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 0 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
index1 = pkts.index
|
||||
|
||||
# Step 4: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify that it is sent to Routers AND REED_1s
|
||||
# - Version TLV
|
||||
# If request was not sent to all routers and REED_1S, then the test
|
||||
# has failed.
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 1 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
index2 = pkts.index
|
||||
|
||||
# Step 3: REED_1 and REED_2 sends no response to Parent Request after
|
||||
# DUT sent the first Parent Request
|
||||
for i in (1, 2):
|
||||
pkts.range(index1, index2).\
|
||||
filter_wpan_src64(pv.vars['REED_%d' %i]).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
must_not_next()
|
||||
|
||||
# Step 5: REED_1 Respond with MLE Parent Response
|
||||
for i in (1, 2):
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(pv.vars['REED_%d' %i]).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 6: DUT sends a MLE Child ID Request to REED_1
|
||||
# The following TLVs MUST be present in the MLE Child ID Request:
|
||||
# - Address Registration TLV
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Mode TLV
|
||||
# - Response TLV
|
||||
# - Timeout TLV
|
||||
# - TLV Request TLV
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(REED_1).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
ADDRESS_REGISTRATION_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
RESPONSE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: REED_1 sends an Address Solicit Request to Leader;
|
||||
# Leader responds with an Address Solicit Response and REED_1
|
||||
# becomes active router;
|
||||
# REED_1 sends Child ID Response with DUT’s new 16-bit Address.
|
||||
|
||||
pkts.filter_wpan_src64(REED_1).\
|
||||
filter_ipv6_dst(LEADER_RLOC).\
|
||||
filter_coap_request(ADDR_SOL_URI).\
|
||||
filter(lambda p: {
|
||||
NL_MAC_EXTENDED_ADDRESS_TLV,
|
||||
NL_STATUS_TLV
|
||||
} <= set(p.coap.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(REED_1_RLOC).\
|
||||
filter_coap_ack(ADDR_SOL_URI).\
|
||||
filter(lambda p: {
|
||||
NL_STATUS_TLV,
|
||||
NL_RLOC16_TLV,
|
||||
NL_ROUTER_MASK_TLV
|
||||
} <= set(p.coap.tlv.type) and\
|
||||
p.thread_address.tlv.status == 0
|
||||
).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(REED_1).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
ADDRESS16_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.source_addr != REED_1_RLOC16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: REED_1 verifies connectivity by sending an ICMPv6 Echo Request
|
||||
# to the DUT link local address
|
||||
# DUT responds with ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(REED_1_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, REED_1_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_1_4_REEDAttachConnectivity_ED(Cert_6_1_4_REEDAttachConnectivity_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_4_REEDAttachConnectivity_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_1_4_REEDAttachConnectivity_SED(Cert_6_1_4_REEDAttachConnectivity_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_4_REEDAttachConnectivity_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_1_4_REEDAttachConnectivity_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, TIMEOUT_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
REED1 = 3
|
||||
REED2 = 4
|
||||
ED = 5
|
||||
|
||||
|
||||
class Cert_6_1_5_REEDAttachConnectivity(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, REED1, REED2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, REED2]
|
||||
},
|
||||
REED1: {
|
||||
'name': 'REED_1',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, ROUTER1, ED]
|
||||
},
|
||||
REED2: {
|
||||
'name': 'REED_2',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, (ED, -85)]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [REED1, REED2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[REED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED1].get_state(), 'child')
|
||||
|
||||
self.nodes[REED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED2].get_state(), 'child')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(10)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[REED1].get_state(), 'router')
|
||||
|
||||
self.num_parent_requests = 1 if self.nodes[ED].version in ['1.1', '1.2'] else 2
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[REED1].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
REED_1 = pv.vars['REED_1']
|
||||
ED = pv.vars['ED']
|
||||
_reed1_pkts = pkts.filter_wpan_src64(REED_1)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 2: The DUT MUST send MLE Parent Requests to the
|
||||
# All-Routers multicast address
|
||||
|
||||
for num in range(self.num_parent_requests):
|
||||
_ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1)
|
||||
|
||||
# Step 3: REED_1 and REED_2 No response to Parent Request
|
||||
# Step 4: DUT Send MLE Parent Request with Scan Mask set to Routers AND REEDs
|
||||
_ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1)
|
||||
|
||||
# Step 5: The DUT MUST send a MLE Child ID Request
|
||||
_ed_pkts.filter_wpan_dst64(REED_1).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV,
|
||||
ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 8: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
ed_mleid = pv.vars['ED_MLEID']
|
||||
reed1_mleid = pv.vars['REED_1_MLEID']
|
||||
_pkt = _reed1_pkts.filter(
|
||||
lambda p: p.ipv6.src == reed1_mleid and p.ipv6.dst == ed_mleid).filter_ping_request().must_next()
|
||||
_ed_pkts.filter(lambda p: p.ipv6.src == ed_mleid and p.ipv6.dst == reed1_mleid).filter_ping_reply(
|
||||
identifier=_pkt.icmpv6.echo.identifier).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,254 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2019, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import copy
|
||||
import mle
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
REED = 2
|
||||
ROUTER = 3
|
||||
MTD = 4
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test is to verify that the DUT sends a second Parent Request
|
||||
# to the all-routers and all-reeds multicast address if it gets a reply from the
|
||||
# first Parent Request to the all-routers address with a bad link quality.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# / \
|
||||
# REED ROUTER
|
||||
# \ /
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_1_6_REEDAttachLinkQuality_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [REED, ROUTER]
|
||||
},
|
||||
REED: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, (MTD, -85)]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [REED, ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[REED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[REED].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(10)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[REED].get_state(), 'router')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
self.collect_rlocs()
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
REED = pv.vars['REED']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
DUT = pv.vars['DUT']
|
||||
|
||||
# Step 1: Setup the topology without the DUT. Ensure all routers and leader
|
||||
# are sending MLE advertisements
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
pv.verify_attached('REED', 'LEADER')
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
|
||||
# Step 3: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify sent to routers only
|
||||
# - Version TLV
|
||||
# If the first Request was sent to all routers and REEDS, then
|
||||
# the test has failed.
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 0 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Router responds with MLE Parent Response
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 5: DUT sends a MLE Parent Request with an IP hop limit of
|
||||
# 255 to the Link-Local All Routers multicast address (FF02::2).
|
||||
# The following TLVs MUST be present in the MLE Parent Request:
|
||||
# - Challenge TLV
|
||||
# - Mode TLV
|
||||
# - Scan Mask TLV
|
||||
# Verify that it is sent to Routers AND REEDs
|
||||
# - Version TLV
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 1 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
index2 = pkts.index
|
||||
|
||||
# Step 6: REED sends MLE Parent Response to DUT
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 6: DUT sends a MLE Child ID Request to REED
|
||||
# The following TLVs MUST be present in the MLE Child ID Request:
|
||||
# - Address Registration TLV
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Mode TLV
|
||||
# - Response TLV
|
||||
# - Timeout TLV
|
||||
# - TLV Request TLV
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(REED).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
ADDRESS_REGISTRATION_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
RESPONSE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_1_6_REEDAttachLinkQuality_ED(Cert_6_1_6_REEDAttachLinkQuality_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_6_REEDAttachLinkQuality_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_1_6_REEDAttachLinkQuality_SED(Cert_6_1_6_REEDAttachLinkQuality_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_1_6_REEDAttachLinkQuality_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_1_6_REEDAttachLinkQuality_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,122 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, TIMEOUT_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ED = 4
|
||||
|
||||
|
||||
class Cert_6_1_7_RouterAttachLinkQuality(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, (ED, -85)]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ED = pv.vars['ED']
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 3: The DUT MUST send a MLE Parent Request to the
|
||||
# All-Routers multicast address
|
||||
_ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).filter_ipv6_dst(
|
||||
LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0)
|
||||
|
||||
# Step 5: The DUT MUST send a MLE Child ID Request to Router_1
|
||||
_ed_pkts.filter_wpan_dst64(ROUTER_1).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV,
|
||||
ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 6: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
ed_mleid = pv.vars['ED_MLEID']
|
||||
router1_mleid = pv.vars['ROUTER_1_MLEID']
|
||||
_pkt = pkts.range(_ed_pkts.index).filter_ipv6_src_dst(router1_mleid,
|
||||
ed_mleid).filter_ping_request().must_next()
|
||||
_ed_pkts.filter_ipv6_src_dst(
|
||||
ed_mleid, router1_mleid).filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,159 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
MTD = 3
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to show that the DUT upholds connectivity, or
|
||||
# reattaches with its parent, when the Leader is removed and the Router creates a
|
||||
# new partition
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_2_1_NewPartition_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].stop()
|
||||
self.simulator.go(150)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(dut_addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_LLA = pv.vars['ROUTER_LLA']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('DUT', 'ROUTER', 'MTD')
|
||||
|
||||
# Step 3: Router automatically creates new partition and begins transmitting
|
||||
# MLE Advertisements
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_mle_advertisement('Router').\
|
||||
must_next()
|
||||
|
||||
# Step 5: Router verifies connectivity by sending an ICMPv6 Echo Request
|
||||
# to the DUT link local address
|
||||
# DUT responds with ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(ROUTER_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, ROUTER_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_2_1_NewPartition_ED(Cert_6_2_1_NewPartition_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_2_1_NewPartition_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_2_1_NewPartition_SED(Cert_6_2_1_NewPartition_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_2_1_NewPartition_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_2_1_NewPartition_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,122 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_ADVERTISEMENT, MLE_CHILD_UPDATE_REQUEST, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ED = 4
|
||||
|
||||
|
||||
class Cert_6_2_2_NewPartition(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1, ROUTER2]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER2, ED]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'network_id_timeout': 110,
|
||||
'allowlist': [LEADER, ROUTER1]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].stop()
|
||||
self.simulator.go(140)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ED = pv.vars['ED']
|
||||
_router1_pkts = pkts.filter_wpan_src64(ROUTER_1)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 1: Ensure that the DUT successfully attached to Router_1
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).filter_wpan_dst64(ROUTER_1).must_next()
|
||||
|
||||
# Step 2-6 : remove Leader and make ROUTER_2 as new Leader
|
||||
# Step 7: The DUT MUST send a MLE Child Update Request to Router_1
|
||||
_ed_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_not_next()
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_not_next()
|
||||
_ed_pkts.filter_wpan_dst64(ROUTER_1).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 8: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
_ed_pkts.filter('ipv6.dst == {ROUTER_1_MLEID} and ipv6.src == {ED_MLEID}',
|
||||
**pv.vars).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_CHILD_ID_REQUEST, MLE_CHILD_UPDATE_REQUEST, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, MODE_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED = 3
|
||||
|
||||
|
||||
class Cert_6_3_1_OrphanReattach(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'timeout': 10,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
self.nodes[ROUTER].stop()
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ED].get_addr64())
|
||||
self.nodes[ED].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(20)
|
||||
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ED = pv.vars['ED']
|
||||
_epkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
_epkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
|
||||
# Step 2: Remove Router from the network
|
||||
# Step 3: The DUT MUST send three MLE Child Update Requests to its parent
|
||||
for i in range(1, 3):
|
||||
_epkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(ROUTER).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, MODE_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 5: The DUT MUST perform the attach procedure with the Leader
|
||||
_epkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
|
||||
_epkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).filter_wpan_dst64(LEADER).must_next()
|
||||
|
||||
# Step 6: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
_epkts.filter('ipv6.src == {ED_MLEID} and ipv6.dst == {LEADER_MLEID}',
|
||||
**pv.vars).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,129 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DATA_REQUEST, MLE_CHILD_UPDATE_REQUEST, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, MODE_TLV, TIMEOUT_TLV, TLV_REQUEST_TLV, NETWORK_DATA_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
|
||||
class Cert_6_3_2_NetworkDataUpdate(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'timeout': 10,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
|
||||
self.simulator.go(5)
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
self.nodes[LEADER].remove_allowlist(self.nodes[ED].get_addr64())
|
||||
self.nodes[ED].remove_allowlist(self.nodes[LEADER].get_addr64())
|
||||
|
||||
self.nodes[LEADER].add_prefix('2001:2:0:2::/64', 'paros')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ED].get_addr64())
|
||||
self.nodes[ED].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(10)
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
MED = pv.vars['MED']
|
||||
_epkts = pkts.filter_wpan_src64(MED)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_src64(LEADER).must_next()
|
||||
|
||||
# Step 3: The DUT MUST send a MLE Child Update Request to the Leader
|
||||
_epkts.range(pkts.index).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: p.wpan.dst64 == LEADER and {LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, MODE_TLV, TIMEOUT_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: The DUT MUST send a MLE Data Request frame to
|
||||
# request the updated Network Data
|
||||
_epkts.filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
|
||||
lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 12: The DUT MUST send a MLE Child Update Request to the Leader
|
||||
_epkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(LEADER).must_next().must_verify(
|
||||
lambda p: {ADDRESS_REGISTRATION_TLV, MODE_TLV, TIMEOUT_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,206 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import LINK_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
MTD = 2
|
||||
FRAGMENTED_DATA_LEN = 256
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate the Link-Local addresses
|
||||
# that the DUT auto-configures.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_4_1_LinkLocal_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.assertTrue(self.nodes[LEADER].ping(dut_addr, size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(dut_addr))
|
||||
self.simulator.go(1)
|
||||
|
||||
self.assertTrue(self.nodes[LEADER].ping(config.LINK_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS,
|
||||
size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(config.LINK_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS))
|
||||
self.simulator.go(1)
|
||||
|
||||
if self.TOPOLOGY[MTD]['mode'] == 'rn':
|
||||
self.assertTrue(self.nodes[LEADER].ping(config.LINK_LOCAL_ALL_NODES_ADDRESS, size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(config.LINK_LOCAL_ALL_NODES_ADDRESS))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_LLA = pv.vars['LEADER_LLA']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('DUT', 'LEADER', 'MTD')
|
||||
|
||||
# Step 2: Leader sends a Fragmented ICMPv6 Echo Request to DUT’s
|
||||
# MAC extended address based Link-Local address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_LLA, DUT_LLA).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends an Unfragmented ICMPv6 Echo Request to DUT’s
|
||||
# MAC extended address based Link-Local address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Leader sends a Fragmented ICMPv6 Echo Request to the
|
||||
# Link-Local All thread nodes multicast address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLATNMA().\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends an Unfragmented ICMPv6 Echo Request to the
|
||||
# Link-Local All thread nodes multicast address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLATNMA().\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
must_next()
|
||||
|
||||
if self.TOPOLOGY[MTD]['mode'] == 'rn':
|
||||
# Step 6: Leader sends a Fragmented ICMPv6 Echo Request to the
|
||||
# Link-Local All Nodes multicast address (FF02::1)
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader sends an Unfragmented ICMPv6 Echo Request to the
|
||||
# Link-Local All Nodes multicast address (FF02::1)
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_4_1_LinkLocal_ED(Cert_6_4_1_LinkLocal_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_4_1_LinkLocal_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_4_1_LinkLocal_SED(Cert_6_4_1_LinkLocal_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_4_1_LinkLocal_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_4_1_LinkLocal_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,250 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
MTD = 3
|
||||
FRAGMENTED_DATA_LEN = 256
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate the Realm-Local addresses
|
||||
# that the DUT configures.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_4_2_RealmLocal_Base(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(dut_addr,
|
||||
size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(dut_addr))
|
||||
self.simulator.go(1)
|
||||
|
||||
if self.TOPOLOGY[MTD]['mode'] == 'rn':
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(config.REALM_LOCAL_ALL_NODES_ADDRESS,
|
||||
num_responses=2,
|
||||
size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(2)
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(config.REALM_LOCAL_ALL_NODES_ADDRESS,
|
||||
num_responses=2))
|
||||
self.simulator.go(2)
|
||||
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(config.REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS,
|
||||
num_responses=2,
|
||||
size=FRAGMENTED_DATA_LEN))
|
||||
self.simulator.go(2)
|
||||
self.assertTrue(self.nodes[LEADER].\
|
||||
ping(config.REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS,
|
||||
num_responses=2))
|
||||
self.simulator.go(2)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_MLEID = pv.vars['LEADER_MLEID']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_MLEID = pv.vars['ROUTER_MLEID']
|
||||
ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_MLEID = pv.vars['DUT_MLEID']
|
||||
DUT_RLOC16 = pv.vars['DUT_RLOC16']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('DUT', 'ROUTER', 'MTD')
|
||||
|
||||
# Step 2: Leader sends a Fragmented ICMPv6 Echo Request to
|
||||
# DUT's ML-EID
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_MLEID, DUT_MLEID).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_MLEID, LEADER_MLEID).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends an Unfragmented ICMPv6 Echo Request to
|
||||
# DUT’s ML-EID
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_MLEID, DUT_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_MLEID, LEADER_MLEID).\
|
||||
must_next()
|
||||
|
||||
if self.TOPOLOGY[MTD]['mode'] == 'rn':
|
||||
# Step 4: Leader sends a Fragmented ICMPv6 Echo Request to the
|
||||
# Realm-Local All Nodes multicast address (FF03::1)
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt1 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_RLANMA().\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
with pkts.save_index():
|
||||
pkts.filter_ping_reply(identifier=_pkt1.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(ROUTER_MLEID, LEADER_MLEID).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_request(identifier=_pkt1.icmpv6.echo.identifier).\
|
||||
filter_wpan_src16_dst16(ROUTER_RLOC16, DUT_RLOC16).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_not_next()
|
||||
|
||||
# Step 5: Leader sends an Unfragmented ICMPv6 Echo Request to the
|
||||
# Realm-Local All Nodes multicast address (FF03::1)
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt2 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_RLANMA().\
|
||||
filter(lambda p: p.icmpv6.echo.sequence_number !=
|
||||
_pkt1.icmpv6.echo.sequence_number
|
||||
).\
|
||||
must_next()
|
||||
with pkts.save_index():
|
||||
pkts.filter_ping_reply(identifier=_pkt2.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(ROUTER_MLEID, LEADER_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_request(identifier = _pkt2.icmpv6.echo.identifier).\
|
||||
filter_wpan_src16_dst16(ROUTER_RLOC16, DUT_RLOC16).\
|
||||
must_not_next()
|
||||
|
||||
# Step 6: Leader sends a Fragmented ICMPv6 Echo Request to the
|
||||
# Realm-Local All Thread Nodes multicast address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_RLATNMA().\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_MLEID).\
|
||||
filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader sends an Unfragmented ICMPv6 Echo Request to the
|
||||
# Realm-Local All Thread Nodes multicast address
|
||||
# The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_RLATNMA().\
|
||||
filter(lambda p: p.icmpv6.data.len != FRAGMENTED_DATA_LEN).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_ipv6_dst(LEADER_MLEID).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_4_2_RealmLocal_ED(Cert_6_4_2_RealmLocal_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_4_2_RealmLocal_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_4_2_RealmLocal_SED(Cert_6_4_2_RealmLocal_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_4_2_RealmLocal_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_4_2_RealmLocal_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,114 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_CHILD_UPDATE_REQUEST, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
|
||||
class Cert_6_5_1_ChildResetReattach(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpEd(self):
|
||||
self.nodes[ED].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[ED].enable_allowlist()
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].remove_allowlist(self.nodes[ED].get_addr64())
|
||||
self.nodes[ED].remove_allowlist(self.nodes[LEADER].get_addr64())
|
||||
|
||||
self.nodes[ED].reset()
|
||||
self._setUpEd()
|
||||
self.simulator.go(5)
|
||||
self.nodes[ED].start()
|
||||
|
||||
self.simulator.go(5)
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ED].get_addr64())
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] == 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ED = pv.vars['ED']
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 2: Reset the DUT for a time greater than
|
||||
# the Child Timeout Duration.
|
||||
# Step 3: Send MLE Child Update Request to Leader
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 5: DUT reattaches to Leader
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(
|
||||
lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV,
|
||||
ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 6: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
_ed_pkts.filter_ping_reply().filter(lambda p: p.wpan.src64 == ED and p.wpan.dst64 == LEADER).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,262 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import thread_cert
|
||||
import config
|
||||
from pktverify.consts import WPAN_DATA_REQUEST, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
MTD = 3
|
||||
POLL_PERIOD = 3 # seconds
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate that after the DUT resets and receives
|
||||
# no response from its parent, it will reattach to the network through a different parent.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_6_5_2_ChildResetReattach_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, MTD]
|
||||
},
|
||||
MTD: {
|
||||
'name': 'DUT',
|
||||
'is_mtd': True,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpMTD(self):
|
||||
self.nodes[MTD].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[MTD].enable_allowlist()
|
||||
if self.TOPOLOGY[MTD]['mode'] == '-':
|
||||
self.nodes[MTD].set_pollperiod(POLL_PERIOD * 1000)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
self.collect_rloc16s()
|
||||
|
||||
self.nodes[LEADER].clear_allowlist()
|
||||
self.nodes[MTD].clear_allowlist()
|
||||
self.nodes[ROUTER].stop()
|
||||
|
||||
self.nodes[MTD].reset()
|
||||
self._setUpMTD()
|
||||
self.simulator.go(5)
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[MTD].get_addr64())
|
||||
self.simulator.go(5)
|
||||
self.nodes[MTD].start()
|
||||
self.simulator.go(10)
|
||||
self.assertEqual(self.nodes[MTD].get_state(), 'child')
|
||||
self.simulator.go(360)
|
||||
|
||||
self.collect_ipaddrs()
|
||||
dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
self.nodes[LEADER].ping(dut_addr)
|
||||
self.simulator.go(15)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_LLA = pv.vars['LEADER_LLA']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16']
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_LLA = pv.vars['DUT_LLA']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('DUT', 'ROUTER', 'MTD')
|
||||
|
||||
# Step 4: DUT sends an MLE Child Update Request.
|
||||
# The following TLVs MUST be included in the Child Update
|
||||
# Request:
|
||||
# - Mode TLV
|
||||
# - Address Registration TLV (optional)
|
||||
# If the DUT is a SED, it MUST resume polling after sending
|
||||
# MLE Child Update.
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
filter(lambda p: {
|
||||
MODE_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
if self.TOPOLOGY[MTD]['mode'] == '-':
|
||||
_pkt = pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(ROUTER_RLOC16).\
|
||||
filter_wpan_cmd(WPAN_DATA_REQUEST).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(ROUTER_RLOC16).\
|
||||
filter_wpan_cmd(WPAN_DATA_REQUEST).\
|
||||
filter(lambda p:
|
||||
p.sniff_timestamp - _pkt.sniff_timestamp <=
|
||||
POLL_PERIOD + 0.1
|
||||
).\
|
||||
must_next()
|
||||
lstart = pkts.index
|
||||
|
||||
# Step 6: The DUT MUST attach to the Leader
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_LLARMA().\
|
||||
filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
MODE_TLV,
|
||||
SCAN_MASK_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.ipv6.hlim == 255 and\
|
||||
p.mle.tlv.scan_mask.r == 1 and\
|
||||
p.mle.tlv.scan_mask.e == 0 and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
lend = pkts.index
|
||||
|
||||
# Step 5: No response from Router.
|
||||
pkts.range(lstart, lend).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
must_not_next()
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_PARENT_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
CONNECTIVITY_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
LINK_MARGIN_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
ADDRESS_REGISTRATION_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
RESPONSE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.wpan.aux_sec.key_id_mode == 0x2
|
||||
).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
ADDRESS16_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader Verifies connectivity by sending an ICMPv6 Echo Request
|
||||
# to the DUT link local address
|
||||
# The End Device MUST respond with ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_LLA, DUT_LLA).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_LLA, LEADER_LLA).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_6_5_2_ChildResetReattach_ED(Cert_6_5_2_ChildResetReattach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_5_2_ChildResetReattach_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = 'rn'
|
||||
|
||||
|
||||
class Cert_6_5_2_ChildResetReattach_SED(Cert_6_5_2_ChildResetReattach_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_6_5_2_ChildResetReattach_Base.TOPOLOGY)
|
||||
TOPOLOGY[MTD]['mode'] = '-'
|
||||
|
||||
|
||||
del (Cert_6_5_2_ChildResetReattach_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MODE_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
|
||||
class Cert_6_5_3_ChildResetSynchronize(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpEd(self):
|
||||
self.nodes[ED].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[ED].enable_allowlist()
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.nodes[ED].reset()
|
||||
self._setUpEd()
|
||||
self.simulator.go(1)
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(1)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] == 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ED = pv.vars['ED']
|
||||
_leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 2: Reset the DUT for a time shorter than
|
||||
# the Child Timeout Duration.
|
||||
# Step 3: Send MLE Child Update Request to Leader
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
_leader_pkts.range(_ed_pkts.index).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_ed_pkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 4: Leader send an MLE Child Update Response
|
||||
_leader_pkts.range(_ed_pkts.index).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next()
|
||||
_ed_pkts.range(_leader_pkts.index).filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_not_next()
|
||||
|
||||
# Step 5: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
_ed_pkts.filter_ping_reply().filter(lambda p: p.wpan.src64 == ED and p.wpan.dst64 == LEADER).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
|
||||
class Cert_6_6_1_KeyIncrement(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), "leader")
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), "child")
|
||||
|
||||
self.collect_rloc16s()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
key_sequence_counter = self.nodes[LEADER].get_key_sequence_counter()
|
||||
self.nodes[LEADER].set_key_sequence_counter(key_sequence_counter + 1)
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ED = pv.vars['ED']
|
||||
_leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 1: The DUT must start the network using
|
||||
# thrKeySequenceCounter = 0
|
||||
_leader_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_source == 0)
|
||||
|
||||
# Step 2: Verify that the topology described above is created.
|
||||
# MLE Auxiliary security header shall contain Key Source = 0,
|
||||
# KeyIndex = 1, KeyID Mode = 2
|
||||
_ed_pkts.filter_mle_cmd(
|
||||
MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.
|
||||
key_id_mode == 2 and p.wpan.aux_sec.key_source == 0)
|
||||
|
||||
# Step 3: Leader send an ICMPv6 Echo Request to DUT.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
lp = _leader_pkts.filter_ping_request().filter(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1 and p.wpan.dst16 == pv.vars[
|
||||
'ED_RLOC16']).must_next()
|
||||
|
||||
# Step 4: DUT send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
_ed_pkts.filter_ping_reply(identifier=lp.icmpv6.echo.identifier).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 5: Leader increment thrKeySequenceCounter by 1 to force a key switch.
|
||||
# Step 6: Leader Send an ICMPv6 Echo Request to DUT.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 2, KeyID Mode = 1
|
||||
lp = _leader_pkts.filter_ping_request().filter(
|
||||
lambda p: p.wpan.aux_sec.key_index == 2 and p.wpan.aux_sec.key_id_mode == 1 and p.wpan.dst16 == pv.vars[
|
||||
'ED_RLOC16']).must_next()
|
||||
|
||||
# Step 7: DUT send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 2, KeyID Mode = 1
|
||||
_ed_pkts.filter_ping_reply(identifier=lp.icmpv6.echo.identifier).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 2 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,128 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ED = 2
|
||||
|
||||
|
||||
class Cert_6_6_2_KeyIncrement1(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'key_sequence_counter': 127,
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED]
|
||||
},
|
||||
ED: {
|
||||
'name': 'ED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
key_sequence_counter = self.nodes[LEADER].get_key_sequence_counter()
|
||||
self.nodes[LEADER].set_key_sequence_counter(key_sequence_counter + 1)
|
||||
|
||||
addrs = self.nodes[ED].get_addrs()
|
||||
for addr in addrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ED = pv.vars['ED']
|
||||
_leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
_ed_pkts = pkts.filter_wpan_src64(ED)
|
||||
|
||||
# Step 1: The DUT must start the network using
|
||||
# thrKeySequenceCounter = 127
|
||||
_leader_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_source == 127)
|
||||
|
||||
# Step 2: Verify that the topology described above is created.
|
||||
# MLE Auxiliary security header shall contain Key Source = 127,
|
||||
# KeyIndex = 128, KeyID Mode = 2
|
||||
_ed_pkts.filter_mle_cmd(
|
||||
MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.
|
||||
key_id_mode == 2 and p.wpan.aux_sec.key_source == 127)
|
||||
|
||||
# Step 3: Leader send an ICMPv6 Echo Request to DUT.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 128, KeyID Mode = 1
|
||||
lp = _leader_pkts.filter_ping_request().filter(
|
||||
lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.key_id_mode == 1 and p.wpan.dst16 == pv.vars[
|
||||
'ED_RLOC16']).must_next()
|
||||
|
||||
# Step 4: DUT send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 128, KeyID Mode = 1
|
||||
_ed_pkts.filter_ping_reply(identifier=lp.icmpv6.echo.identifier).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 5: Leader increment thrKeySequenceCounter by 1 to force a key switch.
|
||||
# Step 6: Leader Send an ICMPv6 Echo Request to DUT.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
lp = _leader_pkts.filter_ping_request().filter(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1 and p.wpan.dst16 == pv.vars[
|
||||
'ED_RLOC16']).must_next()
|
||||
|
||||
# Step 7: DUT send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
_ed_pkts.filter_ping_reply(identifier=lp.icmpv6.echo.identifier).must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,296 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from 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
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
SED1 = 3
|
||||
MED1 = 4
|
||||
|
||||
MTDS = [SED1, MED1]
|
||||
PREFIX_2001 = '2001::/64'
|
||||
PREFIX_2002 = '2002::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that the DUT, as a Border Router,
|
||||
# acts properly as a Leader device in a Thread network, correctly sets the
|
||||
# Network Data (stable/non-stable) and successfully propagates the Network Data
|
||||
# to the devices that attach to it.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# SED
|
||||
# |
|
||||
# ROUTER - Leader(DUT) - MED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_7_1_1_BorderRouterAsLeader(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, SED1, MED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
MED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
# override wireshark preferences with case needed parameters
|
||||
CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS)
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_2001
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2002
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[LEADER].add_prefix(PREFIX_2002, 'paro')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[MED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED1].get_state(), 'child')
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
|
||||
# Step 1: The DUT forms the network properly sends MLE Advertisements
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_advertisement('Leader').\
|
||||
must_next()
|
||||
|
||||
# Step 3: Router attaches to the Leader (DUT) and requests complete
|
||||
# network data
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
RESPONSE_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
VERSION_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ROUTE64_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.mode.network_data == 1
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: The DUT MUST send a MLE Child ID Response to Router,
|
||||
# including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least two Prefix TLVs (Prefix 1 and Prefix 2),
|
||||
# each including:
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Border Router sub-TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: SED attaches to the Leader (DUT) and requests only stable
|
||||
# network data
|
||||
pkts.filter_wpan_src64(SED).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
RESPONSE_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
VERSION_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.mode.network_data == 0
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: The DUT MUST send a MLE Child ID Response to SED,
|
||||
# including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least one Prefix TLVs (Prefix 1),including:
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Border Router sub-TLV
|
||||
# - P_border_router_16 <0xFFFE>
|
||||
# Prefix 2 TLV MUST NOT be included
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
MODE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
CHALLENGE_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] == p.thread_nwd.tlv.prefix and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1] and\
|
||||
p.thread_nwd.tlv.stable == [1, 1, 1]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
lstart = pkts.index
|
||||
|
||||
# Step 7: MED attaches to the Leader (DUT) and requests complete
|
||||
# network data
|
||||
pkts.filter_wpan_src64(MED).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter(lambda p: {
|
||||
RESPONSE_TLV,
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
MODE_TLV,
|
||||
TIMEOUT_TLV,
|
||||
VERSION_TLV,
|
||||
TLV_REQUEST_TLV,
|
||||
ADDRESS16_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.mode.network_data == 1
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: The DUT MUST send a MLE Child ID Response to MED,
|
||||
# including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least two Prefix TLVs (Prefix 1 and Prefix 2),
|
||||
# each including:
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Border Router sub-TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(MED).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: After attaching, each Child automatically sends its global address
|
||||
# configured to the Leader, in the Address Registration TLV from the
|
||||
# Child Update request command
|
||||
|
||||
# Step 10: The DUT MUST send a MLE Child Update Response, each, to MED & SED
|
||||
# The following TLVs MUST be present in the Child Update Response:
|
||||
# - Source Address TLV
|
||||
# - Address Registration TLV
|
||||
# - Echoes back addresses configured in step 9
|
||||
# - Mode TLV
|
||||
for child in (SED, MED):
|
||||
_pkt = pkts.range(lstart).\
|
||||
filter_wpan_src64(child).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
must_next()
|
||||
pkts.range(lstart).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(child).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,171 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SVR_DATA_URI, SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ROUTE64_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED2 = 3
|
||||
SED2 = 4
|
||||
|
||||
MTDS = [ED2, SED2]
|
||||
|
||||
|
||||
class Cert_7_1_2_BorderRouterAsRouter(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED2, SED2]
|
||||
},
|
||||
ED2: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED2: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
self.nodes[ED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED2].get_state(), 'child')
|
||||
|
||||
self.nodes[SED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED2].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
addrs = self.nodes[ED2].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED2].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
# Step 2: The DUT MUST send properly formatted MLE Advertisements
|
||||
# The DUT MUST send a CoAP Server Data Notification message
|
||||
# with the server’s information (Prefix, Border Router) to the Leader
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
_rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
_rpkts.filter_coap_request(SVR_DATA_URI).must_next().must_verify(
|
||||
lambda p: p.wpan.dst16 == pv.vars['LEADER_RLOC16'] and {
|
||||
Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')
|
||||
} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [1, 1, 0, 0])
|
||||
|
||||
# Step 3: Automatically transmits a 2.04 Changed CoAP response to the DUT
|
||||
# Step 4: The DUT MUST multicast the MLE Data Response message sent by the Leader
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.
|
||||
type))
|
||||
|
||||
# Step 5: MED_1 to attach to DUT and request complete network data
|
||||
# Step 6: The DUT MUST send an MLE Child ID Response to MED_1
|
||||
p = _rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
p.must_verify(lambda p: p.wpan.dst64 == MED and {Ipv6Addr('2001:2:0:1::'),
|
||||
Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix))
|
||||
_rpkts_med = _rpkts.copy()
|
||||
|
||||
# Step 7: SED_1 to attach to DUT and request only stable data
|
||||
# Step 8: The DUT MUST send an MLE Child Response to SED_1
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(
|
||||
lambda p: p.wpan.dst64 == SED and {Ipv6Addr('2001:2:0:1::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router_16 == [0xFFFE])
|
||||
_rpkts_sed = _rpkts.copy()
|
||||
|
||||
# Step 9: SED_1 and MED_1 send its configured global address to the DUT
|
||||
# Step 10: The DUT MUST send a Child Update Response to MED_1 & SED_1
|
||||
_med_pkt = pkts.range(
|
||||
_rpkts_med.index).filter_wpan_src64(MED).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next()
|
||||
_sed_pkt = pkts.range(
|
||||
_rpkts_sed.index).filter_wpan_src64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next()
|
||||
_rpkts_med.filter_wpan_dst64(MED).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type) and p.wpan.dst64
|
||||
== MED and set(p.mle.tlv.addr_reg_iid) < set(_med_pkt.mle.tlv.addr_reg_iid))
|
||||
_rpkts_sed.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type) and set(
|
||||
p.mle.tlv.addr_reg_iid) < set(_sed_pkt.mle.tlv.addr_reg_iid))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,239 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_DATA_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ACTIVE_TIMESTAMP_TLV, 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
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
SED1 = 3
|
||||
MED1 = 4
|
||||
|
||||
MTDS = [SED1, MED1]
|
||||
PREFIX_2001 = '2001::/64'
|
||||
PREFIX_2002 = '2002::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that global prefix information can
|
||||
# be set on the DUT, which is acting as a Leader in the Thread network. The DUT
|
||||
# must also demonstrate that it correctly sets the Network Data (stable/non-stable)
|
||||
# and propagates it properly in an already formed network.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# SED
|
||||
# |
|
||||
# ROUTER - Leader(DUT) - MED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_7_1_3_BorderRouterAsLeader(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER, SED1, MED1]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
MED1: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
# override wireshark preferences with case needed parameters
|
||||
CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS)
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_2001
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2002
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[MED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED1].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[LEADER].add_prefix(PREFIX_2002, 'paro')
|
||||
self.nodes[LEADER].register_netdata()
|
||||
self.simulator.go(5)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
SED = pv.vars['SED']
|
||||
MED = pv.vars['MED']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('SED', 'LEADER', 'MTD')
|
||||
pv.verify_attached('MED', 'LEADER', 'MTD')
|
||||
|
||||
# Step 3: The DUT MUST send a multicast MLE Data Response,
|
||||
# including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least two Prefix TLVs (Prefix 1 and Prefix 2),
|
||||
# each including:
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Border Router sub-TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: MED automatically sends the global address configured to its parent
|
||||
# (the DUT), via the Address Registration TLV included in its Child
|
||||
# Update Request keep-alive message.
|
||||
|
||||
# Step 5: The DUT MUST send a MLE Child Update Response to MED
|
||||
# The following TLVs MUST be present in the Child Update Response:
|
||||
# - Source Address TLV
|
||||
# - Address Registration TLV
|
||||
# - Echoes back addresses configured in step 4
|
||||
# - Mode TLV
|
||||
with pkts.save_index():
|
||||
_pkt = pkts.filter_wpan_src64(MED).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(MED).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.addr_reg_iid is not nullField and\
|
||||
set(_pkt.mle.tlv.addr_reg_iid) > set(p.mle.tlv.addr_reg_iid)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: The DUT MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] == p.thread_nwd.tlv.prefix and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1] and\
|
||||
p.thread_nwd.tlv.stable == [1, 1, 1]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: After receiving the MLE Data Response or MLE Child Update Request,
|
||||
# SED automatically sends its global address configured to the Leader,
|
||||
# in the Address Registration TLV from the Child Update request command
|
||||
|
||||
# Step 10: The DUT MUST send a MLE Child Update Response, each, to SED
|
||||
# The following TLVs MUST be present in the Child Update Response:
|
||||
# - Source Address TLV
|
||||
# - Address Registration TLV
|
||||
# - Echoes back addresses configured in step 9
|
||||
# - Mode TLV
|
||||
_pkt = pkts.filter_wpan_src64(SED).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.addr_reg_iid is not nullField and\
|
||||
set(_pkt.mle.tlv.addr_reg_iid) > set(p.mle.tlv.addr_reg_iid)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,166 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_UPDATE_REQUEST, SVR_DATA_URI, SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ROUTE64_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
ED2 = 3
|
||||
SED2 = 4
|
||||
|
||||
MTDS = [SED2, ED2]
|
||||
|
||||
|
||||
class Cert_7_1_4_BorderRouterAsRouter(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED2, SED2]
|
||||
},
|
||||
ED2: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED2: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED2].get_state(), 'child')
|
||||
|
||||
self.nodes[SED2].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED2].get_state(), 'child')
|
||||
|
||||
self.collect_rloc16s()
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
|
||||
self.nodes[ROUTER].add_prefix('2001:2:0:2::/64', 'paro')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
self.simulator.go(5)
|
||||
|
||||
# Set lowpan context of sniffer
|
||||
self.simulator.set_lowpan_context(1, '2001:2:0:1::/64')
|
||||
self.simulator.set_lowpan_context(2, '2001:2:0:2::/64')
|
||||
|
||||
addrs = self.nodes[ED2].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertTrue(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
addrs = self.nodes[SED2].get_addrs()
|
||||
self.assertTrue(any('2001:2:0:1' in addr[0:10] for addr in addrs))
|
||||
self.assertFalse(any('2001:2:0:2' in addr[0:10] for addr in addrs))
|
||||
for addr in addrs:
|
||||
if addr[0:10] == '2001:2:0:1' or addr[0:10] == '2001:2:0:2':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
# Step 3: The DUT MUST send properly formatted MLE Advertisements
|
||||
# The DUT MUST send a CoAP Server Data Notification message
|
||||
# with the server’s information (Prefix, Border Router) to the Leader
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
_rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV} <= set(p.mle.tlv.type))
|
||||
_pkt = _rpkts.filter_coap_request(SVR_DATA_URI).must_next()
|
||||
_pkt.must_verify(lambda p: p.wpan.dst16 == pv.vars['LEADER_RLOC16'] and {
|
||||
Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')
|
||||
} == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.
|
||||
thread_nwd.tlv.border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [1, 1, 0, 0])
|
||||
_rpkts_med = _rpkts.copy()
|
||||
_rpkts_sed = _rpkts.copy()
|
||||
|
||||
# Step 4: Automatically transmits a 2.04 Changed CoAP response to the DUT
|
||||
# Step 5: The DUT MUST send a multicast MLE Data Response
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set(
|
||||
p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd.tlv.
|
||||
border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0])
|
||||
|
||||
# Step 6: The DUT MUST send a Child Update Response to MED_1
|
||||
_rpkts_med.filter_wpan_dst64(MED).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 7: The DUT MUST send an MLE Child Update Request to SED_1
|
||||
_rpkts_sed.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(
|
||||
lambda p: {Ipv6Addr('2001:2:0:1::')} == set(p.thread_nwd.tlv.prefix
|
||||
) and p.thread_nwd.tlv.border_router_16 == [0xFFFE])
|
||||
|
||||
# Step 8: SED_1 send its configured global address to the DUT
|
||||
# Step 9: The DUT MUST send a Child Update Response to SED_1
|
||||
_sed_pkt = pkts.range(
|
||||
_rpkts_sed.index).filter_wpan_src64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).must_next()
|
||||
_rpkts_sed.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, MODE_TLV, ADDRESS_REGISTRATION_TLV} <= set(p.mle.tlv.type) and set(
|
||||
p.mle.tlv.addr_reg_iid) < set(_sed_pkt.mle.tlv.addr_reg_iid))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,257 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_DATA_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SVR_DATA_URI, ACTIVE_TIMESTAMP_TLV, 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
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
MED = 3
|
||||
SED = 4
|
||||
|
||||
MTDS = [MED, SED]
|
||||
PREFIX_2001 = '2001::/64'
|
||||
PREFIX_2002 = '2002::/64'
|
||||
PREFIX_2003 = '2003::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that the DUT sends properly formatted
|
||||
# Server Data Notification CoAP frame when a third global prefix information is
|
||||
# set on the DUT. The DUT must also correctly set Network Data aggregated and
|
||||
# disseminated by the Leader and transmit it properly to all child devices already
|
||||
# attached to it.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# SED
|
||||
# |
|
||||
# Router(DUT) - MED
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
|
||||
|
||||
class Cert_7_1_5_BorderRouterAsRouter(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, MED, SED]
|
||||
},
|
||||
MED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[MED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
self.nodes[SED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED].get_state(), 'child')
|
||||
|
||||
self.nodes[ROUTER].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[ROUTER].add_prefix(PREFIX_2002, 'paro')
|
||||
self.nodes[ROUTER].add_prefix(PREFIX_2003, 'paos')
|
||||
self.nodes[ROUTER].register_netdata()
|
||||
self.simulator.go(10)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
SED = pv.vars['SED']
|
||||
MED = pv.vars['MED']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('MED', 'ROUTER', 'MTD')
|
||||
pv.verify_attached('SED', 'ROUTER', 'MTD')
|
||||
|
||||
# Step 3: The DUT MUST send a CoAP Server Data Notification frame
|
||||
# to the Leader including the server’s information(Prefix,
|
||||
# Border Router) for all three prefixes (Prefix 1, 2 and 3):
|
||||
# CoAP Request URI
|
||||
# coap://[<Leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# Thread Network Data TLV
|
||||
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3]),
|
||||
Ipv6Addr(PREFIX_2003[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix)
|
||||
).\
|
||||
must_next()
|
||||
_index = pkts.index
|
||||
|
||||
# Step 5: The DUT MUST send a multicast MLE Data Response,
|
||||
# including at least three Prefix TLVs (Prefix 1, Prefix2,
|
||||
# and Prefix 3).
|
||||
with pkts.save_index():
|
||||
_dv_pkt = pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3]),
|
||||
Ipv6Addr(PREFIX_2003[:-3])
|
||||
} <= set(p.thread_nwd.tlv.prefix)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: MED automatically sends MLE Child Update Request to its parent
|
||||
# (DUT), reporting its configured global addresses in the Address
|
||||
# Registration TLV
|
||||
|
||||
# Step 7: The DUT MUST send a MLE Child Update Response to MED
|
||||
# The following TLVs MUST be present in the Child Update Response:
|
||||
# - Source Address TLV
|
||||
# - Address Registration TLV
|
||||
# - Echoes back addresses configured in step 4
|
||||
# - Mode TLV
|
||||
_pkt = pkts.filter_wpan_src64(MED).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 4).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(MED).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
len(p.mle.tlv.addr_reg_iid) >= 3 and\
|
||||
set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: The DUT MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least two Prefix TLVs (Prefix 1 and Prefix3)
|
||||
# - Border Router TLV
|
||||
# - P_border_router_16<0xFFFE>
|
||||
# Prefix 2 TLV MUST NOT be included
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be the same as the ones
|
||||
# sent in the multicast data response in step 5.
|
||||
# - Active Timestamp TLV
|
||||
pkts.range(_index).filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2003[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_dv_pkt.mle.tlv.leader_data.data_version and\
|
||||
[0xFFFE, 0xFFFE] == p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: SED automatically sends its global address configured to the Leader,
|
||||
# in the Address Registration TLV from the Child Update request command
|
||||
|
||||
# Step 10: The DUT MUST send a MLE Child Update Response, each, to SED
|
||||
# The following TLVs MUST be present in the Child Update Response:
|
||||
# - Source Address TLV
|
||||
# - Address Registration TLV
|
||||
# - Echoes back addresses configured in step 9
|
||||
# - Mode TLV
|
||||
_pkt = pkts.filter_wpan_src64(SED).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
|
||||
filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 3).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
MODE_TLV,
|
||||
ADDRESS_REGISTRATION_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
len(p.mle.tlv.addr_reg_iid) >= 2 and\
|
||||
set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,485 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, SVR_DATA_URI, ACTIVE_TIMESTAMP_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, VERSION_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, CHALLENGE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.bytes import Bytes
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER_1 = 2
|
||||
ROUTER_2 = 3
|
||||
MED = 4
|
||||
SED = 5
|
||||
|
||||
MTDS = [MED, SED]
|
||||
PREFIX_2001 = '2001:0db8:0001::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that network data is properly updated
|
||||
# when a server from the network leaves and rejoins.
|
||||
# Router_1 is configured as Border Router for prefix 2001:db8:1::/64.
|
||||
# Router_2 is configured as Border Router for prefix 2001:db8:1::/64.
|
||||
# MED is configured to require complete network data.
|
||||
# SED is configured to request only stable network data.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# SED
|
||||
# |
|
||||
# Router_1 - Leader(DUT) - MED
|
||||
# |
|
||||
# Router_2
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_7_1_6_BorderRouterAsLeader(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER_1, ROUTER_2, MED, SED]
|
||||
},
|
||||
ROUTER_1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER_2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
MED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
# override wireshark preferences with case needed parameters
|
||||
CASE_WIRESHARK_PREFS = WIRESHARK_OVERRIDE_PREFS
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_2001
|
||||
|
||||
def _setUpRouter_1(self):
|
||||
self.nodes[ROUTER_1].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[ROUTER_1].enable_allowlist()
|
||||
self.nodes[ROUTER_1].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in (2, 3):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.nodes[MED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
self.nodes[SED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
|
||||
self.nodes[ROUTER_1].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[ROUTER_1].register_netdata()
|
||||
self.nodes[ROUTER_2].add_prefix(PREFIX_2001, 'paro')
|
||||
self.nodes[ROUTER_2].register_netdata()
|
||||
self.simulator.go(10)
|
||||
self.collect_ipaddrs()
|
||||
|
||||
self.nodes[ROUTER_1].reset()
|
||||
self._setUpRouter_1()
|
||||
self.simulator.go(720)
|
||||
|
||||
self.nodes[ROUTER_1].start()
|
||||
self.simulator.go(config.ROUTER_RESET_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER_1].get_state(), 'router')
|
||||
self.collect_rloc16s()
|
||||
|
||||
self.nodes[ROUTER_1].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[ROUTER_1].register_netdata()
|
||||
self.simulator.go(10)
|
||||
|
||||
dut_addr = self.nodes[LEADER].get_addr(PREFIX_2001)
|
||||
self.assertTrue(self.nodes[ROUTER_1].ping(dut_addr))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[SED].ping(dut_addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16']
|
||||
ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16']
|
||||
SED = pv.vars['SED']
|
||||
MED = pv.vars['MED']
|
||||
GUA = {}
|
||||
|
||||
for node in ('LEADER', 'ROUTER_1', 'SED'):
|
||||
for addr in pv.vars['%s_IPADDRS' % node]:
|
||||
if addr.startswith(Bytes(PREFIX_2001[:-5])):
|
||||
GUA[node] = addr
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER_1', 'LEADER')
|
||||
pv.verify_attached('ROUTER_2', 'LEADER')
|
||||
pv.verify_attached('MED', 'LEADER', 'MTD')
|
||||
pv.verify_attached('SED', 'LEADER', 'MTD')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 2,3: Router_1 and Router_2 MUST send a CoAP Server Data
|
||||
# Notification frame to the Leader including the server’s
|
||||
# information(Prefix, Border Router):
|
||||
# CoAP Request URI
|
||||
# coap://[<Leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# Thread Network Data TLV
|
||||
|
||||
# Step 4: Leader sends a CoAP ACK frame to each of Router_1 and
|
||||
# Router_2
|
||||
for i in (1, 2):
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(pv.vars['ROUTER_%d' %i]).\
|
||||
filter_wpan_dst16(LEADER_RLOC16).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[pv.vars['ROUTER_%d_RLOC16' %i]] ==
|
||||
p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(pv.vars['ROUTER_%d_RLOC' %i]).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader MUST multicast MLE Data Response with the new
|
||||
# information collected from Router_1 and Router_2,
|
||||
# including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - At least one Prefix TLV (Prefix 1)
|
||||
# - Two Border Router sub-TLVs
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
_dr_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1] and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix
|
||||
).\
|
||||
must_next()
|
||||
with pkts.save_index():
|
||||
_dr_pkt1 = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_dr_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256 or\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least one Prefix TLV (Prefix 1) including:
|
||||
# - Border Router sub-TLV(corresponding to Router_1)
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - P_border_router_16<0xFFFE>
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be the same as the ones
|
||||
# sent in the multicast data response in step 5.
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
p.thread_nwd.tlv.stable == [1, 1, 1] and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_dr_pkt1.mle.tlv.leader_data.data_version and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_dr_pkt1.mle.tlv.leader_data.stable_data_version and\
|
||||
[0xFFFE] == p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader MUST detect that Router_1 is removed from the network and
|
||||
# update the Router ID Set. Leader MUST remove the Network Data
|
||||
# section corresponding to Router_1 and increment the Data Version
|
||||
# and Stable Data Version
|
||||
|
||||
# Step 9: Leader MUST multicast MLE Data Response neighbors and rx-on-when-idle
|
||||
# Children (MED) including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - Router_1’s Network Data section MUST be removed
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[ROUTER_2_RLOC16] == p.thread_nwd.tlv.border_router_16 and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.stable_data_version + 1) % 256
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: The DUT MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, containing the updated Network Data:
|
||||
# - Network Data TLV
|
||||
# - Source Address TLV
|
||||
# - Active Timestamp TLV
|
||||
_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
p.thread_nwd.tlv.border_router_16 is nullField and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.stable_data_version + 1) % 256
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 12: Leader MUST send MLE Child ID Response to Router_1, which
|
||||
# includes the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Address16 TLV
|
||||
# - Route64 TLV
|
||||
# - Network Data TLV
|
||||
# - At least one Prefix TLV (Prefix 1)
|
||||
# including:
|
||||
# - Border Router sub-tlv corresponding to Router_2
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER_1).\
|
||||
filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
ADDRESS16_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
ROUTE64_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[ROUTER_2_RLOC16] == p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Router_1 MUST send a CoAP Server DataNotification frame to
|
||||
# the Leader including the server’s information(Prefix, Border Router):
|
||||
# CoAP Request URI
|
||||
# coap://[<Leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# Thread Network Data TLV
|
||||
|
||||
# Step 14: Leader sends a CoAP ACK frame to each of Router_1
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst16(LEADER_RLOC16).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[ROUTER_1_RLOC16] ==
|
||||
p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_1_RLOC).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
must_next()
|
||||
|
||||
# Step 15: Leader MUST multicast MLE Data Response with the new
|
||||
# information collected from Router_1 and Router_2,
|
||||
# including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - At least one Prefix TLV (Prefix 1)
|
||||
# - Two Border Router sub-TLVs
|
||||
# corresponding to Router_1 and Router_2
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
_dr_pkt2 = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{ROUTER_1_RLOC16, ROUTER_2_RLOC16} ==
|
||||
set(p.thread_nwd.tlv.border_router_16) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 16: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least one Prefix TLV (Prefix 1)
|
||||
# - Border Router TLV (corresponding to Router_1)
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - P_border_router_16<0xFFFE>
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be the same as those
|
||||
# sent in the multicast data response in step 15.
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_2001[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_dr_pkt2.mle.tlv.leader_data.data_version and\
|
||||
p.thread_nwd.tlv.stable == [1, 1, 1] and\
|
||||
[0xFFFE] == p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 17: Verifies connectivity by sending ICMPv6 Echo Requests from
|
||||
# Router_1 and SED_1 to the Leader Prefix_1 based address.
|
||||
# Leader must respond with ICMPv6 Echo Replies
|
||||
for node in ('ROUTER_1', 'SED'):
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(GUA[node], GUA['LEADER']).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(GUA['LEADER'], GUA[node]).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,562 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, SVR_DATA_URI, ACTIVE_TIMESTAMP_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, VERSION_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, CHALLENGE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.bytes import Bytes
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
from pktverify.null_field import nullField
|
||||
from pktverify.utils import is_sublist
|
||||
|
||||
LEADER = 1
|
||||
ROUTER_1 = 2
|
||||
ROUTER_2 = 3
|
||||
MED = 4
|
||||
SED = 5
|
||||
|
||||
MTDS = [MED, SED]
|
||||
PREFIX_1 = '2001:0db8:0001::/64'
|
||||
PREFIX_2 = '2001:0db8:0002::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that network data is properly updated
|
||||
# when a server from the network leaves and rejoins.
|
||||
# Router_1 is configured as Border Router for prefix 2001:db8:1::/64.
|
||||
# Router_2 is configured as Border Router for prefix 2001:db8:1::/64.
|
||||
# MED is configured to require complete network data.
|
||||
# SED is configured to request only stable network data.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# SED
|
||||
# |
|
||||
# Router_1 - Leader(DUT) - MED
|
||||
# |
|
||||
# Router_2
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_7_1_7_BorderRouterAsLeader(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER_1, ROUTER_2, MED, SED]
|
||||
},
|
||||
ROUTER_1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
ROUTER_2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
MED: {
|
||||
'name': 'MED',
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
SED: {
|
||||
'name': 'SED',
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
# override wireshark preferences with case needed parameters
|
||||
CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS)
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_1
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
for i in (2, 3):
|
||||
self.nodes[i].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
self.nodes[MED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
self.nodes[SED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
|
||||
self.nodes[ROUTER_1].add_prefix(PREFIX_1, 'paosr')
|
||||
self.nodes[ROUTER_1].register_netdata()
|
||||
self.simulator.go(5)
|
||||
self.nodes[ROUTER_2].add_prefix(PREFIX_1, 'paro')
|
||||
self.nodes[ROUTER_2].register_netdata()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER_2].set_preferred_partition_id(1)
|
||||
self.nodes[ROUTER_2].set_network_id_timeout(50)
|
||||
|
||||
self.nodes[ROUTER_2].remove_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[LEADER].remove_allowlist(self.nodes[ROUTER_2].get_addr64())
|
||||
|
||||
# Wait for NETWORK_ID_TIMEOUT taking effect
|
||||
# Router_2 creates a new partition
|
||||
self.simulator.go(80)
|
||||
self.assertEqual(self.nodes[ROUTER_2].get_state(), 'leader')
|
||||
self.nodes[ROUTER_2].remove_domain_prefix(PREFIX_1)
|
||||
self.nodes[ROUTER_2].add_prefix(PREFIX_2, 'paros')
|
||||
self.nodes[ROUTER_2].register_netdata()
|
||||
|
||||
# Router_2 reattaches to Leader
|
||||
self.nodes[ROUTER_2].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER_2].get_addr64())
|
||||
|
||||
# Wait for Router_2 reattachment and network data propagation
|
||||
# ADVERTISEMENT_I_MAX + DEFAULT_CHILD_TIMEOUT + ATTACH_DELAY + Extra
|
||||
self.simulator.go(120)
|
||||
self.assertEqual(self.nodes[ROUTER_2].get_state(), 'router')
|
||||
self.collect_ipaddrs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
# ping Leader's PREFIX_1 and PREFIX_2 addrs
|
||||
dut_addrs = []
|
||||
dut_addrs.append(self.nodes[LEADER].get_addr(PREFIX_1))
|
||||
dut_addrs.append(self.nodes[LEADER].get_addr(PREFIX_2))
|
||||
for addr in dut_addrs:
|
||||
self.assertTrue(self.nodes[ROUTER_1].ping(addr))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[SED].ping(addr))
|
||||
self.simulator.go(1)
|
||||
|
||||
self.nodes[ROUTER_2].remove_domain_prefix(PREFIX_2)
|
||||
self.nodes[ROUTER_2].register_netdata()
|
||||
self.simulator.go(5)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16']
|
||||
ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16']
|
||||
ROUTER_2_RLOC = pv.vars['ROUTER_2_RLOC']
|
||||
SED = pv.vars['SED']
|
||||
MED = pv.vars['MED']
|
||||
GUA = [{}, {}]
|
||||
PREFIXES = [Bytes(PREFIX_1[:-5]), Bytes(PREFIX_2[:-5])]
|
||||
|
||||
for i in (0, 1):
|
||||
for node in ('LEADER', 'ROUTER_1', 'SED'):
|
||||
for addr in pv.vars['%s_IPADDRS' % node]:
|
||||
if addr.startswith(PREFIXES[i]):
|
||||
GUA[i][node] = addr
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER_1', 'LEADER')
|
||||
pv.verify_attached('ROUTER_2', 'LEADER')
|
||||
pv.verify_attached('MED', 'LEADER', 'MTD')
|
||||
pv.verify_attached('SED', 'LEADER', 'MTD')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 2,3: Router_1 and Router_2 MUST send a CoAP Server Data
|
||||
# Notification frame to the Leader including the server’s
|
||||
# information(Prefix, Border Router):
|
||||
# CoAP Request URI
|
||||
# coap://[<Leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# Thread Network Data TLV
|
||||
|
||||
# Step 4: Leader sends a CoAP ACK frame to each of Router_1 and
|
||||
# Router_2
|
||||
with pkts.save_index():
|
||||
for node in ('ROUTER_1', 'ROUTER_2'):
|
||||
_dn_pkt = pkts.filter_wpan_src64(pv.vars['%s' %node]).\
|
||||
filter_wpan_dst16(LEADER_RLOC16).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
[Ipv6Addr(PREFIX_1[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[pv.vars['%s_RLOC16' %node]] ==
|
||||
p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(pv.vars['%s_RLOC' %node]).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader MUST multicast MLE Data Response with the new
|
||||
# information collected from Router_1 and Router_2,
|
||||
# including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - Stable Flag set
|
||||
# - At least one Prefix TLV (Prefix 1)
|
||||
# - Two Border Router sub-TLVs
|
||||
# Border Router1 TLV: Stable Flag set
|
||||
# Border Router2 TLV: Stable Flag not set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# Stable Flag set
|
||||
_dr_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
[Ipv6Addr(PREFIX_1[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256
|
||||
).\
|
||||
must_next()
|
||||
with pkts.save_index():
|
||||
_dr_pkt1 = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_dr_pkt.mle.tlv.leader_data.stable_data_version and\
|
||||
is_sublist([ROUTER_1_RLOC16, ROUTER_2_RLOC16],
|
||||
p.thread_nwd.tlv.border_router_16) and\
|
||||
is_sublist([0, 1, 1, 1, 0], p.thread_nwd.tlv.stable) and\
|
||||
is_sublist([1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3])], p.thread_nwd.tlv.prefix)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Network Data TLV
|
||||
# At least one Prefix TLV (Prefix 1) including:
|
||||
# - Stable Flag set
|
||||
# - Border Router sub-TLV(corresponding to Router_1)
|
||||
# - P_border_router_16<0xFFFE>
|
||||
# - Stable Flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable Flag set
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3])], p.thread_nwd.tlv.prefix) and\
|
||||
is_sublist([1, 1, 1], p.thread_nwd.tlv.stable) and\
|
||||
is_sublist([1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
|
||||
is_sublist([0xFFFE], p.thread_nwd.tlv.border_router_16)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Router_2 automatically reattaches to the Leader and sends
|
||||
# a CoAP Server Data Notification message with the server’s
|
||||
# information (Prefix, Border Router) to the Leader:
|
||||
# CoAP Request URI
|
||||
# coap://[<leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# Thread Network Data TLV
|
||||
|
||||
# Step 11: Leader sends a CoAP ACK frame to each of Routers
|
||||
pv.verify_attached('ROUTER_2', 'LEADER')
|
||||
with pkts.save_index():
|
||||
_dn_pkt = pkts.filter_wpan_src64(ROUTER_2).\
|
||||
filter_wpan_dst16(LEADER_RLOC16).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
[Ipv6Addr(PREFIX_2[:-3])] ==
|
||||
p.thread_nwd.tlv.prefix and\
|
||||
[ROUTER_2_RLOC16] ==
|
||||
p.thread_nwd.tlv.border_router_16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_2_RLOC).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
|
||||
must_next()
|
||||
|
||||
# Step 12: Leader MUST multicast MLE Data Response with the new
|
||||
# information collected from Router_2,
|
||||
# including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - Stable Flag set
|
||||
# - At least two Prefix TLVs (Prefix 1 and Prefix 2)
|
||||
# - Prefix 1 TLV
|
||||
# - Stable Flag set
|
||||
# - Only one Border Router sub-TLV
|
||||
# corresponding to Router_1
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable Flag set
|
||||
# - Prefix 2 TLV
|
||||
# - Stable Flag set
|
||||
# - Only one Border Router sub-TLV
|
||||
# corresponding to Router_2
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
_dr_pkt2 = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
is_sublist([ROUTER_1_RLOC16, ROUTER_2_RLOC16],
|
||||
p.thread_nwd.tlv.border_router_16) and\
|
||||
is_sublist([0, 1, 1, 1, 1, 1, 1],
|
||||
p.thread_nwd.tlv.stable) and\
|
||||
is_sublist([1, 1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
|
||||
p.thread_nwd.tlv.prefix) and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_dr_pkt1.mle.tlv.leader_data.stable_data_version + 1) % 256
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, containing the stable Network Data
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - At least two Prefix TLVs (Prefix 1 and Prefix 2)
|
||||
# - Prefix 1 TLV
|
||||
# - Stable Flag set
|
||||
# - Border Router sub-TLV
|
||||
# corresponding to Router_1
|
||||
# - P_border_router_16 <0xFFFE>
|
||||
# - Stable flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable flag set
|
||||
# - Prefix 2 TLV
|
||||
# - Stable Flag set
|
||||
# - Border Router sub-TLV
|
||||
# corresponding to Router_2
|
||||
# - P_border_router_16 <0xFFFE>
|
||||
# - Stable flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable flag set
|
||||
# - Active Timestamp TLV
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
is_sublist([1, 1, 1, 1, 1, 1],
|
||||
p.thread_nwd.tlv.stable) and\
|
||||
is_sublist([1, 1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
|
||||
p.thread_nwd.tlv.prefix) and\
|
||||
is_sublist([0xFFFE, 0xFFFE], p.thread_nwd.tlv.border_router_16)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 14: Verifies connectivity by sending ICMPv6 Echo Requests from
|
||||
# Router_1 and SED_1 to the Leader Prefix_1 and Prefix_2-based
|
||||
# address.
|
||||
# Leader must respond with ICMPv6 Echo Replies
|
||||
for i in (0, 1):
|
||||
for node in ('ROUTER_1', 'SED'):
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(GUA[i][node], GUA[i]['LEADER']).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(GUA[i]['LEADER'], GUA[i][node]).\
|
||||
must_next()
|
||||
|
||||
# Step 15: Router_2 sends a CoAP Server Data Notification message with
|
||||
# the server’s information (Prefix, Border Router) to the Leader:
|
||||
# CoAP Request URI
|
||||
# coap://[<leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# empty payload
|
||||
|
||||
# Step 16: Leader sends a CoAP ACK frame to each of Router_1 and
|
||||
# Router_2
|
||||
with pkts.save_index():
|
||||
_dn_pkt = pkts.filter_wpan_src64(ROUTER_2).\
|
||||
filter_wpan_dst16(LEADER_RLOC16).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
p.thread_nwd.tlv.border_router_16 is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_2_RLOC).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
|
||||
must_next()
|
||||
|
||||
# Step 17: Leader MUST multicast MLE Data Response with the new
|
||||
# information collected from Router_2,
|
||||
# including the following TLVs:,
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Data Version field <incremented>
|
||||
# - Stable Data Version field <incremented>
|
||||
# - Network Data TLV
|
||||
# - Stable Flag set
|
||||
# - At least two Prefix TLVs (Prefix 1 and Prefix 2)
|
||||
# - Prefix 1 TLV
|
||||
# - Stable Flag set
|
||||
# - Only one Border Router sub-TLV
|
||||
# corresponding to Router_1
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable Flag set
|
||||
# - Prefix 2 TLV
|
||||
# - Stable Flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable Flag set
|
||||
# - compression flag set to 0
|
||||
_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_BORDER_ROUTER_TLV,
|
||||
NWD_6LOWPAN_ID_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
(_dr_pkt2.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
(_dr_pkt2.mle.tlv.leader_data.stable_data_version + 1) % 256 and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
|
||||
p.thread_nwd.tlv.prefix) and\
|
||||
is_sublist([1,0], getattr(p.thread_nwd.tlv, '6co').flag.c)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 18: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, containing the stable Network Data
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - At least two Prefix TLVs (Prefix 1 and Prefix 2)
|
||||
# - Prefix 1 TLV
|
||||
# - Stable Flag set
|
||||
# - Border Router sub-TLV
|
||||
# corresponding to Router_1
|
||||
# - P_border_router_16 <0xFFFE>
|
||||
# - Stable flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable flag set
|
||||
# - Prefix 2 TLV
|
||||
# - Stable Flag set
|
||||
# - 6LoWPAN ID sub-TLV
|
||||
# - Stable flag set
|
||||
# - compression flag set to 0
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
|
||||
p.thread_nwd.tlv.prefix) and\
|
||||
is_sublist([1, 1, 1, 1, 1], p.thread_nwd.tlv.stable) and\
|
||||
is_sublist([0xFFFE], p.thread_nwd.tlv.border_router_16) and\
|
||||
is_sublist([1,0], getattr(p.thread_nwd.tlv, '6co').flag.c)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,210 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_DATA_RESPONSE, SVR_DATA_URI, NWD_6LOWPAN_ID_TLV, NL_RLOC16_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
FED = 3
|
||||
|
||||
PREFIX_2001 = '2001::/64'
|
||||
PREFIX_2002 = '2002::/64'
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that when global prefix information
|
||||
# is set on the FED, the DUT properly disseminates the associated network data.
|
||||
# It also verifies that the DUT sends revised server data information to the
|
||||
# Leader when the FED is removed.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# FED
|
||||
# |
|
||||
# Router(DUT)
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
|
||||
|
||||
class Cert_7_1_8_BorderRouterAsFED(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, FED]
|
||||
},
|
||||
FED: {
|
||||
'name': 'FED',
|
||||
'mode': 'rdn',
|
||||
'router_upgrade_threshold': 0,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
# override wireshark preferences with case needed parameters
|
||||
CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS)
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_2001
|
||||
CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2002
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[FED].start()
|
||||
self.simulator.go(3)
|
||||
self.assertEqual(self.nodes[FED].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
self.collect_leader_aloc(LEADER)
|
||||
|
||||
self.nodes[FED].add_prefix(PREFIX_2001, 'paros')
|
||||
self.nodes[FED].add_prefix(PREFIX_2002, 'paro')
|
||||
self.nodes[FED].register_netdata()
|
||||
self.simulator.go(10)
|
||||
|
||||
self.nodes[FED].stop()
|
||||
self.simulator.go(250)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_ALOC = pv.vars['LEADER_ALOC']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_RLOC = pv.vars['ROUTER_RLOC']
|
||||
ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16']
|
||||
FED = pv.vars['FED']
|
||||
FED_RLOC = pv.vars['FED_RLOC']
|
||||
FED_RLOC16 = pv.vars['FED_RLOC16']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
pv.verify_attached('FED', 'ROUTER', 'MTD')
|
||||
|
||||
# Step 2: FED automatically sends a CoAP Server Data Notification
|
||||
# message with the server’s information (Prefix, Border Router)
|
||||
# to the Leader.
|
||||
pkts.filter_wpan_src64(FED).\
|
||||
filter_ipv6_dst(LEADER_ALOC).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
p.thread_nwd.tlv.border_router_16 == [FED_RLOC16, FED_RLOC16]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader transmits a 2.04 Changed CoAP response to the DUT.
|
||||
# And transmits multicast MLE Data Response with the new information
|
||||
# collected, adding also 6LoWPAN ID TLV for the prefix set on FED.
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(FED_RLOC).\
|
||||
filter_coap_ack(SVR_DATA_URI).\
|
||||
must_next()
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
NWD_6LOWPAN_ID_TLV in p.thread_nwd.tlv.type and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: The DUT transmits multicast MLE Data Response with the new information
|
||||
# collected, adding also 6LoWPAN ID TLV for the prefix set on FED.
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
Ipv6Addr(PREFIX_2001[:-3]),
|
||||
Ipv6Addr(PREFIX_2002[:-3])
|
||||
} == set(p.thread_nwd.tlv.prefix) and\
|
||||
NWD_6LOWPAN_ID_TLV in p.thread_nwd.tlv.type and\
|
||||
p.thread_nwd.tlv.border_router.flag.p == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.s == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.r == [1, 1] and\
|
||||
p.thread_nwd.tlv.border_router.flag.o == [1, 1] and\
|
||||
p.thread_nwd.tlv.stable == [0, 1, 1, 1, 0, 0, 0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: The DUT notifies Leader of removed server’s (FED’s) RLOC16.
|
||||
# The DUT MUST send a CoAP Server Data Notification frame
|
||||
# to the Leader containing only the removed server’s RLOC16:
|
||||
# CoAP Request URI
|
||||
# coap://[<Leader address>]:MM/a/sd
|
||||
# CoAP Payload
|
||||
# RLOC16 TLV
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_coap_request(SVR_DATA_URI).\
|
||||
filter(lambda p:
|
||||
p.thread_address.tlv.type == [NL_RLOC16_TLV] and\
|
||||
p.thread_address.tlv.rloc16 == FED_RLOC16
|
||||
).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user