[thread-cert] refactor case 5.2.7 using pktverify (#5786)

This commit is contained in:
Jing Ma
2020-11-17 23:01:28 -08:00
committed by GitHub
parent 1d722c561e
commit 5bd9aba799
@@ -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 REEDs 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__':