mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
301 lines
14 KiB
Python
Executable File
301 lines
14 KiB
Python
Executable File
#!/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 command
|
|
import config
|
|
import mle
|
|
import thread_cert
|
|
|
|
LEADER_1_2 = 1
|
|
MED_1_2 = 2
|
|
SED_1_2 = 3
|
|
MED_1_1 = 4
|
|
SED_1_1 = 5
|
|
ROUTER_1_1 = 6
|
|
MED_1_2_2 = 7
|
|
SED_1_2_2 = 8
|
|
|
|
WAIT_ATTACH = 5
|
|
WAIT_REDUNDANCE = 3
|
|
ROUTER_SELECTION_JITTER = 1
|
|
|
|
MA1_LINKLOCAL = 'ff02::1:2:3:4'
|
|
MA2_ADMINSCOPE = 'ff04::1:2:3:4'
|
|
"""
|
|
Topology
|
|
|
|
SED_1_2
|
|
|
|
|
|
|
|
MED_1_2 --- LEADER_1_2 --- MED_1_1
|
|
| \
|
|
| \
|
|
SED_1_1 ROUTER_1_1 --- MED_1_2_2
|
|
|
|
|
|
|
|
SED_1_2_2
|
|
|
|
1) Bring up Leader_1_2.
|
|
|
|
2) Bring up MED_1_2, which attaches to Thread 1.2 parent, only register MA with scope larger than realm local.
|
|
a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
3) Bring up SED_1_2, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
|
|
a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
|
|
b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
4) Bring up MED_1_1, which attaches to Thread 1.2 parent, not register any external MA.
|
|
a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
5) Bring up SED_1_1, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
|
|
a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
|
|
b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
6) Bring up ROUTER_1_1.
|
|
|
|
7) Bring up MED_1_2_2 which attaches to Thread 1.1 parent, not register any external MA.
|
|
a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request
|
|
b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
8) Bring up SED_1_2_2 which attaches to Thread 1.1 parent, register any external MA for indirect transmission.
|
|
a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
|
|
b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
|
|
"""
|
|
|
|
|
|
class TestMulticastRegistration(thread_cert.TestCase):
|
|
TOPOLOGY = {
|
|
LEADER_1_2: {
|
|
'version': '1.2',
|
|
'allowlist': [MED_1_2, SED_1_2, MED_1_1, SED_1_1, ROUTER_1_1],
|
|
},
|
|
MED_1_2: {
|
|
'mode': 'rn',
|
|
'version': '1.2',
|
|
'allowlist': [LEADER_1_2],
|
|
},
|
|
SED_1_2: {
|
|
'mode': 'n',
|
|
'version': '1.2',
|
|
'allowlist': [LEADER_1_2],
|
|
},
|
|
MED_1_1: {
|
|
'mode': 'rn',
|
|
'version': '1.1',
|
|
'allowlist': [LEADER_1_2],
|
|
},
|
|
SED_1_1: {
|
|
'mode': 'n',
|
|
'version': '1.1',
|
|
'allowlist': [LEADER_1_2],
|
|
},
|
|
ROUTER_1_1: {
|
|
'version': '1.1',
|
|
'allowlist': [LEADER_1_2, MED_1_2_2, SED_1_2_2],
|
|
},
|
|
MED_1_2_2: {
|
|
'mode': 'rn',
|
|
'version': '1.2',
|
|
'allowlist': [ROUTER_1_1],
|
|
},
|
|
SED_1_2_2: {
|
|
'mode': 'n',
|
|
'version': '1.2',
|
|
'allowlist': [ROUTER_1_1],
|
|
},
|
|
}
|
|
"""All nodes are created with default configurations"""
|
|
|
|
def __check_multicast_registration(self,
|
|
node,
|
|
multicast_address,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True):
|
|
''' Check whether or not the addition of the multicast address on the specific node
|
|
would trigger Child Update Request for multicast address registration via Address
|
|
Registration TLV.
|
|
|
|
Args:
|
|
node (int) : The device id
|
|
multicast_address (string): The multicast address
|
|
child_update_request_assert (bool): whether or not the addition should trigger Child Update Request
|
|
in_address_registration (bool): Whether or not the multicast_address should be registered
|
|
'''
|
|
# Flush relative message queues.
|
|
self.flush_nodes([node])
|
|
|
|
self.nodes[node].add_ipmaddr(multicast_address)
|
|
WAIT_TIME = WAIT_REDUNDANCE
|
|
self.simulator.go(WAIT_TIME)
|
|
|
|
messages = self.simulator.get_messages_sent_by(node)
|
|
|
|
msg = messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST,
|
|
assert_enabled=child_update_request_assert)
|
|
|
|
if msg:
|
|
is_in = command.check_address_registration_tlv(msg, multicast_address)
|
|
|
|
if in_address_registration:
|
|
assert is_in, 'Error: Expected {} in AddressRegistrationTLV not found'.format(multicast_address)
|
|
else:
|
|
assert not is_in, 'Error: Unexpected {} in AddressRegistrationTLV'.format(multicast_address)
|
|
|
|
def test(self):
|
|
|
|
# 1) Bring up Leader_1_2.
|
|
self.nodes[LEADER_1_2].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME * 2)
|
|
self.assertEqual(self.nodes[LEADER_1_2].get_state(), 'leader')
|
|
|
|
# 2) Bring up MED_1_2, which attaches to Thread 1.2 parent, only register MA with scope larger than realm local.
|
|
self.nodes[MED_1_2].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[MED_1_2].get_state(), 'child')
|
|
|
|
# 2a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(MED_1_2,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=False,
|
|
in_address_registration=False)
|
|
|
|
# 2b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(MED_1_2,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
# 3) Bring up SED_1_2, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
|
|
self.nodes[SED_1_2].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[SED_1_2].get_state(), 'child')
|
|
|
|
# 3a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(SED_1_2,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
# 3b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(SED_1_2,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
# 4) Bring up MED_1_1, which attaches to Thread 1.2 parent, not register any external MA.
|
|
self.nodes[MED_1_1].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[MED_1_1].get_state(), 'child')
|
|
|
|
# 4a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(MED_1_1,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=False,
|
|
in_address_registration=False)
|
|
|
|
# 4b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(MED_1_1,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=False,
|
|
in_address_registration=False)
|
|
|
|
# 5) Bring up SED_1_1, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
|
|
self.nodes[SED_1_1].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[SED_1_1].get_state(), 'child')
|
|
|
|
# 5a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(SED_1_1,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
# 5b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(SED_1_1,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
#6) Bring up ROUTER_1_1.
|
|
self.nodes[ROUTER_1_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
|
|
self.nodes[ROUTER_1_1].start()
|
|
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router')
|
|
|
|
# 7) Bring up MED_1_2_2 which attaches to Thread 1.1 parent, not register any external MA.
|
|
self.nodes[MED_1_2_2].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[MED_1_2_2].get_state(), 'child')
|
|
|
|
# 7a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request
|
|
self.__check_multicast_registration(MED_1_2_2,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=False,
|
|
in_address_registration=False)
|
|
|
|
# 7b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(MED_1_2_2,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=False,
|
|
in_address_registration=False)
|
|
|
|
# 8) Bring up SED_1_2_2 which attaches to Thread 1.1 parent, register any external MA for indirect transmission.
|
|
self.nodes[SED_1_2_2].start()
|
|
WAIT_TIME = WAIT_ATTACH
|
|
self.simulator.go(WAIT_TIME)
|
|
self.assertEqual(self.nodes[SED_1_2_2].get_state(), 'child')
|
|
|
|
# 8a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
|
|
self.__check_multicast_registration(SED_1_2_2,
|
|
MA1_LINKLOCAL,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
# 8b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
|
|
self.__check_multicast_registration(SED_1_2_2,
|
|
MA2_ADMINSCOPE,
|
|
child_update_request_assert=True,
|
|
in_address_registration=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|