mirror of
https://github.com/espressif/openthread.git
synced 2026-08-21 09:59:52 +00:00
[thread-cert] refactor case 5.2.7 using pktverify (#5786)
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import copy
|
||||
import unittest
|
||||
|
||||
import command
|
||||
@@ -34,105 +35,150 @@ import config
|
||||
import ipv6
|
||||
import mle
|
||||
import thread_cert
|
||||
from pktverify.consts import ADDR_SOL_URI, MLE_LINK_REQUEST, MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, LEADER_DATA_TLV, VERSION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
LEADER = 1
|
||||
DUT_ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
DUT_REED = 17
|
||||
|
||||
MLE_MIN_LINKS = 3
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to validate the REED’s Synchronization
|
||||
# procedure after attaching to a network with multiple Routers. A REED
|
||||
# MUST process incoming Advertisements and perform a one-way frame-counter
|
||||
# synchronization with at least 3 neighboring Routers. When Router receives
|
||||
# unicast MLE Link Request from REED, it replies with MLE Link Accept.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Router_15 - Leader
|
||||
# ... / \
|
||||
# Router_n Router_1(DUT)
|
||||
# |
|
||||
# REED(DUT)
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
# REED
|
||||
|
||||
|
||||
class Cert_5_2_7_REEDSynchronization_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
class Cert_5_2_7_REEDSynchronization(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
DUT_ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
3: {
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
4: {
|
||||
'name': 'ROUTER_3',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
5: {
|
||||
'name': 'ROUTER_4',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
6: {
|
||||
'name': 'ROUTER_5',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
7: {
|
||||
'name': 'ROUTER_6',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
8: {
|
||||
'name': 'ROUTER_7',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
9: {
|
||||
'name': 'ROUTER_8',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
10: {
|
||||
'name': 'ROUTER_9',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
11: {
|
||||
'name': 'ROUTER_10',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
12: {
|
||||
'name': 'ROUTER_11',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
13: {
|
||||
'name': 'ROUTER_12',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
14: {
|
||||
'name': 'ROUTER_13',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
15: {
|
||||
'name': 'ROUTER_14',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
16: {
|
||||
'name': 'ROUTER_15',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
DUT_REED: {
|
||||
'name': 'REED',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xface,
|
||||
'router_selection_jitter': 1
|
||||
},
|
||||
}
|
||||
|
||||
DUT = 0
|
||||
|
||||
def test(self):
|
||||
# 1. Ensure topology is formed correctly without DUT_ROUTER1.
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
@@ -144,48 +190,107 @@ class Cert_5_2_7_REEDSynchronization(thread_cert.TestCase):
|
||||
for i in range(2, 17):
|
||||
self.assertEqual(self.nodes[i].get_state(), 'router')
|
||||
|
||||
# 2. DUT_REED: Attach to network. Verify it didn't send an Address Solicit Request.
|
||||
# Avoid DUT_REED attach to DUT_ROUTER1.
|
||||
self.nodes[DUT_REED].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(), config.RSSI['LINK_QULITY_1'])
|
||||
if self.DUT == DUT_REED:
|
||||
self.nodes[DUT_REED].\
|
||||
add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(),
|
||||
config.RSSI['LINK_QULITY_1'])
|
||||
|
||||
if self.DUT == DUT_ROUTER1:
|
||||
self.nodes[DUT_REED].\
|
||||
add_allowlist(self.nodes[DUT_ROUTER1].get_addr64(),
|
||||
config.RSSI['LINK_QULITY_1'])
|
||||
self.nodes[DUT_REED].add_allowlist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[DUT_REED].enable_allowlist()
|
||||
|
||||
self.nodes[DUT_REED].start()
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
self.assertEqual(self.nodes[DUT_REED].get_state(), 'child')
|
||||
|
||||
# The DUT_REED must not send a coap message here.
|
||||
reed_messages = self.simulator.get_messages_sent_by(DUT_REED)
|
||||
msg = reed_messages.does_not_contain_coap_message()
|
||||
assert (msg is True), "Error: The DUT_REED sent an Address Solicit Request"
|
||||
|
||||
# 3. DUT_REED: Verify sent a Link Request to at least 3 neighboring
|
||||
# Routers.
|
||||
for i in range(0, MLE_MIN_LINKS):
|
||||
msg = reed_messages.next_mle_message(mle.CommandType.LINK_REQUEST)
|
||||
command.check_link_request(
|
||||
msg,
|
||||
source_address=command.CheckType.CONTAIN,
|
||||
leader_data=command.CheckType.CONTAIN,
|
||||
)
|
||||
|
||||
# 4. DUT_REED: Verify at least 3 Link Accept messages sent to DUT_REED.
|
||||
self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
|
||||
|
||||
link_accept_count = 0
|
||||
destination_link_local = self.nodes[DUT_REED].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
for i in range(1, DUT_REED):
|
||||
dut_messages = self.simulator.get_messages_sent_by(i)
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
REED = pv.vars['REED']
|
||||
|
||||
while True:
|
||||
msg = dut_messages.next_mle_message(mle.CommandType.LINK_ACCEPT, False)
|
||||
if msg is None:
|
||||
break
|
||||
if (ipv6.ip_address(destination_link_local) == msg.ipv6_packet.ipv6_header.destination_address):
|
||||
command.check_link_accept(msg, self.nodes[DUT_REED])
|
||||
link_accept_count += 1
|
||||
break
|
||||
# Step 1: Verify topology is formed correctly except REED.
|
||||
|
||||
assert (link_accept_count >= MLE_MIN_LINKS) is True, "Error: too few Link Accept sent to DUT_REED"
|
||||
for i in range(1, 16):
|
||||
with pkts.save_index():
|
||||
pv.verify_attached('ROUTER_%d' % i)
|
||||
|
||||
# Step 2: REED attaches to the network and MUST NOT attempt to become
|
||||
# an active router by sending an Address Solicit Request
|
||||
|
||||
pv.verify_attached('REED')
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_coap_request(ADDR_SOL_URI).\
|
||||
filter(lambda p: {
|
||||
NL_MAC_EXTENDED_ADDRESS_TLV,
|
||||
NL_STATUS_TLV
|
||||
} == set(p.coap.tlv.type)
|
||||
).\
|
||||
must_not_next()
|
||||
|
||||
# Step 3: REED sends a unicast Link Request message to at lease 3 Routers
|
||||
#
|
||||
# The Link Request Message MUST contain the following TLVs:
|
||||
# - Challenge TLV
|
||||
# - Leader Data TLV
|
||||
# - Source Address TLV
|
||||
# - Version TLV
|
||||
|
||||
if self.DUT == DUT_REED:
|
||||
for i in range(0, MLE_MIN_LINKS):
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_mle_cmd(MLE_LINK_REQUEST).\
|
||||
filter(lambda p: {
|
||||
CHALLENGE_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Router_1 sends Link Accept message
|
||||
# The following TLVs MUST be present in the Link Accept message:
|
||||
# - Link-layer Frame Counter TLV
|
||||
# - Source Address TLV
|
||||
# - Response TLV
|
||||
# - Version TLV
|
||||
# - MLE Frame Counter TLV (optional)
|
||||
#
|
||||
# The recipient does not make any change to its local state and
|
||||
# MUST NOT reply with a Link Accept And Request message.
|
||||
|
||||
if self.DUT == DUT_ROUTER1:
|
||||
pkts.filter_wpan_dst64(REED).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_mle_cmd(MLE_LINK_ACCEPT).\
|
||||
filter(lambda p: {
|
||||
LINK_LAYER_FRAME_COUNTER_TLV,
|
||||
RESPONSE_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
VERSION_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(REED).\
|
||||
filter_mle_cmd(MLE_LINK_ACCEPT_AND_REQUEST).\
|
||||
must_not_next()
|
||||
|
||||
|
||||
class Cert_5_2_7_REEDSynchronization_REED(Cert_5_2_7_REEDSynchronization_Base):
|
||||
DUT = DUT_REED
|
||||
|
||||
|
||||
class Cert_5_2_7_REEDSynchronization_ROUTER(Cert_5_2_7_REEDSynchronization_Base):
|
||||
DUT = DUT_ROUTER1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user