mirror of
https://github.com/espressif/openthread.git
synced 2026-08-30 05:49:54 +00:00
[mle] 1.2 MED registers MA (scope > 3) to its parent via AR TLV (#4837)
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
|
||||
import binascii
|
||||
|
||||
import ipaddress
|
||||
import ipv6
|
||||
import network_data
|
||||
import network_layer
|
||||
@@ -586,11 +587,24 @@ def get_sub_tlv(tlvs, tlv_type):
|
||||
return sub_tlv
|
||||
|
||||
|
||||
def check_address_registration_tlv(addr_reg_tlv, address_set):
|
||||
"""Verify all addresses contained in address_set are contained in add_reg_tlv
|
||||
def check_address_registration_tlv(
|
||||
command_msg,
|
||||
full_address,
|
||||
):
|
||||
"""Check whether or not a full IPv6 address in AddressRegistrationTlv.
|
||||
"""
|
||||
assert all(addr in addr_reg_tlv.addresses for addr in address_set
|
||||
), 'Some addresses are not included in AddressRegistration TLV'
|
||||
found = False
|
||||
addr = ipaddress.ip_address(full_address)
|
||||
addresses = command_msg.assertMleMessageContainsTlv(
|
||||
mle.AddressRegistration).addresses
|
||||
|
||||
for item in addresses:
|
||||
if isinstance(item, mle.AddressFull) and ipaddress.ip_address(
|
||||
item.ipv6_address) == addr:
|
||||
found = True
|
||||
break
|
||||
|
||||
return found
|
||||
|
||||
|
||||
def assert_contains_tlv(tlvs, check_type, tlv_type):
|
||||
|
||||
@@ -704,6 +704,11 @@ class Node:
|
||||
self.send_command(cmd)
|
||||
self._expect('Done')
|
||||
|
||||
def add_ipmaddr(self, ipmaddr):
|
||||
cmd = 'ipmaddr add %s' % ipmaddr
|
||||
self.send_command(cmd)
|
||||
self._expect('Done')
|
||||
|
||||
def get_addrs(self):
|
||||
self.send_command('ipaddr')
|
||||
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
#!/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',
|
||||
'whitelist': [MED_1_2, SED_1_2, MED_1_1, SED_1_1, ROUTER_1_1],
|
||||
},
|
||||
MED_1_2: {
|
||||
'mode': 'rsn',
|
||||
'version': '1.2',
|
||||
'whitelist': [LEADER_1_2],
|
||||
},
|
||||
SED_1_2: {
|
||||
'mode': 'sn',
|
||||
'version': '1.2',
|
||||
'whitelist': [LEADER_1_2],
|
||||
},
|
||||
MED_1_1: {
|
||||
'mode': 'rsn',
|
||||
'version': '1.1',
|
||||
'whitelist': [LEADER_1_2],
|
||||
},
|
||||
SED_1_1: {
|
||||
'mode': 'sn',
|
||||
'version': '1.1',
|
||||
'whitelist': [LEADER_1_2],
|
||||
},
|
||||
ROUTER_1_1: {
|
||||
'version': '1.1',
|
||||
'whitelist': [LEADER_1_2, MED_1_2_2, SED_1_2_2],
|
||||
},
|
||||
MED_1_2_2: {
|
||||
'mode': 'rsn',
|
||||
'version': '1.2',
|
||||
'whitelist': [ROUTER_1_1],
|
||||
},
|
||||
SED_1_2_2: {
|
||||
'mode': 'sn',
|
||||
'version': '1.2',
|
||||
'whitelist': [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
|
||||
Registraion 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: %s %s in AddressRegistrationTLV %s'.format(
|
||||
'Expected', multicast_address, ' not found')
|
||||
else:
|
||||
assert not is_in, 'Error: %s %s in AddressRegistrationTLV %s'.format(
|
||||
'Unexpected', 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)
|
||||
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()
|
||||
Reference in New Issue
Block a user