1#!/usr/bin/env python3 2# 3# Copyright (c) 2023, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import unittest 31 32from config import ADDRESS_TYPE 33from mle import LinkMetricsSubTlvType, TlvType 34from pktverify import consts 35from pktverify.null_field import nullField 36from pktverify.packet_verifier import PacketVerifier 37 38import config 39import thread_cert 40 41LEADER = 1 42ROUTER = 2 43CHILD = 3 44""" 45Acronyms: 46- EAP - Enhanced-ACK Based Probing 47 48Test Process: 491. Initiate a leader and a router at the beginning. 502. Enable Link Metrics Manager on leader. 513. Wait a few seconds. 52 - At this moment, leader should have configured EAP successfully at router. 534. Instruct the leader ping the router. 54 - Enhanced ACK sent by router should have Thread IE containing Link Metrics data. 555. Add a child into the network. The child should attach to the leader. 566. Wait 150 seconds. 57 - At this moment, leader should have configured EAP successfully at the child. 587. Instruct both the router and the child ping the leader. 59 - Enhanced ACK sent by router and child should have Thread IE containing Link Metrics data. 608. Shutdown the child. 619. Wait 300 seconds. 62 - The leader should not send a Link Management Request to the child. 63 - The leader should have sent a Link Management Request to the router and get a response. 6410. Disable Link Metrics Manager on leader. 65 - The leader shonld send a Link Management Request to the router to unregister EAP. 66""" 67 68 69class LowPower_test_LinkMetricsManager(thread_cert.TestCase): 70 TOPOLOGY = { 71 LEADER: { 72 'version': '1.2', 73 'name': 'LEADER', 74 'mode': 'rdn', 75 'allowlist': [ROUTER, CHILD], 76 }, 77 ROUTER: { 78 'version': '1.2', 79 'name': 'ROUTER', 80 'mode': 'rdn', 81 'allowlist': [LEADER], 82 }, 83 CHILD: { 84 'version': '1.2', 85 'name': 'CHILD', 86 'mode': 'r', 87 'allowlist': [LEADER], 88 } 89 } 90 """All nodes are created with default configurations""" 91 92 def test(self): 93 self.nodes[LEADER].start() 94 self.simulator.go(config.LEADER_STARTUP_DELAY) 95 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 96 97 self.nodes[ROUTER].start() 98 self.simulator.go(config.ROUTER_STARTUP_DELAY) 99 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 100 101 leader_addr = self.nodes[LEADER].get_ip6_address(ADDRESS_TYPE.LINK_LOCAL) 102 router_addr = self.nodes[ROUTER].get_ip6_address(ADDRESS_TYPE.LINK_LOCAL) 103 104 # Step 2 - Enable Link Metrics Manager on leader. 105 self.nodes[LEADER].link_metrics_mgr_set_enabled(True) 106 107 self.simulator.go(10) 108 109 # Step 4 - Instruct the leader ping the router. 110 self.nodes[LEADER].ping(router_addr) 111 112 # Step 5 - Add a child into the network. 113 self.nodes[CHILD].start() 114 self.simulator.go(10) 115 self.assertEqual(self.nodes[CHILD].get_state(), 'child') 116 child_addr = self.nodes[CHILD].get_ip6_address(ADDRESS_TYPE.LINK_LOCAL) 117 118 # Step 6 - Wait the leader to configure EAP at the child. 119 self.simulator.go(150) 120 121 # Step 7 - Instruct both the router and the child ping the leader. 122 self.nodes[LEADER].ping(router_addr) 123 self.nodes[LEADER].ping(child_addr) 124 125 # Step 8 - Shutdown the child. 126 self.nodes[CHILD].stop() 127 128 # Step 9 - Wait the leader to refresh EAP. 129 self.simulator.go(300) 130 131 # Step 10 - Disable Link Metrics Manager on leader. 132 self.nodes[LEADER].link_metrics_mgr_set_enabled(False) 133 134 def verify(self, pv): 135 pkts = pv.pkts 136 pv.summary.show() 137 LEADER = pv.vars['LEADER'] 138 ROUTER = pv.vars['ROUTER'] 139 CHILD = pv.vars['CHILD'] 140 141 # Step 3 - Leader enables IEEE 802.15.4-2015 Enhanced ACK based Probing by sending a Link Metrics Management 142 # Request to the Router 143 # MLE Link Metrics Management TLV Payload: 144 # - Enhanced ACK Configuration Sub-TLV 145 # -- Enh-ACK Flags = 1 (register a configuration) 146 # -- Concatenation of Link Metric Type ID Flags = 0x00: 147 # --- Item1: (0)(0)(001)(010) = 0x0a 148 # ---- E = 0 149 # ---- L = 0 150 # ---- Type/Average Enum = 1 (Exponential Moving Avg) 151 # ---- Metrics Enum = 2 (Link Margin) 152 pkts.filter_wpan_src64(LEADER) \ 153 .filter_wpan_dst64(ROUTER) \ 154 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_REQUEST) \ 155 .filter(lambda p: consts.LM_ENHANCED_ACK_CONFIGURATION_SUB_TLV in p.mle.tlv.link_sub_tlv) \ 156 .filter(lambda p: p.mle.tlv.link_enh_ack_flags == consts.LINK_METRICS_ENH_ACK_PROBING_REGISTER) \ 157 .filter(lambda p: p.mle.tlv.link_requested_type_id_flags == '0a0b') \ 158 .must_next() 159 160 # Step 3 - The Router MUST send a Link Metrics Management Response to Leader containing the following TLVs: 161 # - MLE LInk Metrics Management TLV 162 # -- Link Metrics Status Sub-TLV = 0 (Success) 163 pkts.filter_wpan_src64(ROUTER) \ 164 .filter_wpan_dst64(LEADER) \ 165 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_RESPONSE) \ 166 .filter(lambda p: p.mle.tlv.link_status_sub_tlv == consts.LINK_METRICS_STATUS_SUCCESS) \ 167 .must_next() 168 169 # Step 4 - The Enhanced Ack sent by both Router should contain Thread specific IE 170 pkt = pkts.filter_wpan_src64(LEADER) \ 171 .filter_wpan_dst64(ROUTER) \ 172 .filter_ping_request() \ 173 .must_next() 174 ack_seq_no = pkt.wpan.seq_no 175 pkts.filter_wpan_ack() \ 176 .filter_wpan_seq(ack_seq_no) \ 177 .filter(lambda p: p.wpan.payload_ie.vendor.oui == consts.THREAD_IEEE_802154_COMPANY_ID) \ 178 .must_next() 179 180 # Step 6 - Leader enables IEEE 802.15.4-2015 Enhanced ACK based Probing by sending a Link Metrics Management 181 # Request to the Child 182 # MLE Link Metrics Management TLV Payload: 183 # - Enhanced ACK Configuration Sub-TLV 184 # -- Enh-ACK Flags = 1 (register a configuration) 185 # -- Concatenation of Link Metric Type ID Flags = 0x00: 186 # --- Item1: (0)(0)(001)(010) = 0x0a 187 # ---- E = 0 188 # ---- L = 0 189 # ---- Type/Average Enum = 1 (Exponential Moving Avg) 190 # ---- Metrics Enum = 2 (Link Margin) 191 pkts.filter_wpan_src64(LEADER) \ 192 .filter_wpan_dst64(CHILD) \ 193 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_REQUEST) \ 194 .filter(lambda p: consts.LM_ENHANCED_ACK_CONFIGURATION_SUB_TLV in p.mle.tlv.link_sub_tlv) \ 195 .filter(lambda p: p.mle.tlv.link_enh_ack_flags == consts.LINK_METRICS_ENH_ACK_PROBING_REGISTER) \ 196 .filter(lambda p: p.mle.tlv.link_requested_type_id_flags == '0a0b') \ 197 .must_next() 198 199 # Step 6 - The Child MUST send a Link Metrics Management Response to Leader containing the following TLVs: 200 # - MLE LInk Metrics Management TLV 201 # -- Link Metrics Status Sub-TLV = 0 (Success) 202 pkts.filter_wpan_src64(CHILD) \ 203 .filter_wpan_dst64(LEADER) \ 204 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_RESPONSE) \ 205 .filter(lambda p: p.mle.tlv.link_status_sub_tlv == consts.LINK_METRICS_STATUS_SUCCESS) \ 206 .must_next() 207 208 # Step 7 - The Enhanced Ack sent by both Router and Child should contain Thread specific IE 209 pkt1 = pkts.filter_wpan_src64(LEADER) \ 210 .filter_wpan_dst64(ROUTER) \ 211 .filter_ping_request() \ 212 .must_next() 213 ack_seq_no = pkt1.wpan.seq_no 214 pkts.filter_wpan_ack() \ 215 .filter_wpan_seq(ack_seq_no) \ 216 .filter(lambda p: p.wpan.payload_ie.vendor.oui == consts.THREAD_IEEE_802154_COMPANY_ID) \ 217 .must_next() 218 219 pkt2 = pkts.filter_wpan_src64(LEADER) \ 220 .filter_wpan_dst64(CHILD) \ 221 .filter_ping_request() \ 222 .must_next() 223 ack_seq_no = pkt2.wpan.seq_no 224 pkts.filter_wpan_ack() \ 225 .filter_wpan_seq(ack_seq_no) \ 226 .filter(lambda p: p.wpan.payload_ie.vendor.oui == consts.THREAD_IEEE_802154_COMPANY_ID) \ 227 .must_next() 228 229 # Step 9 - Leader refreshes IEEE 802.15.4-2015 Enhanced ACK based Probing by sending a Link Metrics Management 230 # Request to the Router 231 # MLE Link Metrics Management TLV Payload: 232 # - Enhanced ACK Configuration Sub-TLV 233 # -- Enh-ACK Flags = 1 (register a configuration) 234 # -- Concatenation of Link Metric Type ID Flags = 0x00: 235 # --- Item1: (0)(0)(001)(010) = 0x0a 236 # ---- E = 0 237 # ---- L = 0 238 # ---- Type/Average Enum = 1 (Exponential Moving Avg) 239 # ---- Metrics Enum = 2 (Link Margin) 240 pkts.filter_wpan_src64(LEADER) \ 241 .filter_wpan_dst64(ROUTER) \ 242 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_REQUEST) \ 243 .filter(lambda p: consts.LM_ENHANCED_ACK_CONFIGURATION_SUB_TLV in p.mle.tlv.link_sub_tlv) \ 244 .filter(lambda p: p.mle.tlv.link_enh_ack_flags == consts.LINK_METRICS_ENH_ACK_PROBING_REGISTER) \ 245 .filter(lambda p: p.mle.tlv.link_requested_type_id_flags == '0a0b') \ 246 .must_next() 247 248 # Step 9 - The Router MUST send a Link Metrics Management Response to Leader containing the following TLVs: 249 # - MLE LInk Metrics Management TLV 250 # -- Link Metrics Status Sub-TLV = 0 (Success) 251 pkts.filter_wpan_src64(ROUTER) \ 252 .filter_wpan_dst64(LEADER) \ 253 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_RESPONSE) \ 254 .filter(lambda p: p.mle.tlv.link_status_sub_tlv == consts.LINK_METRICS_STATUS_SUCCESS) \ 255 .must_next() 256 257 # Step 10 - Leader unregisters IEEE 802.15.4-2015 Enhanced ACK based Probing by sending a Link Metrics Management 258 # Request to the Router 259 # MLE Link Metrics Management TLV Payload: 260 # - Enhanced ACK Configuration Sub-TLV 261 # -- Enh-ACK Flags = 0 (unregister a configuration) 262 pkts.filter_wpan_src64(LEADER) \ 263 .filter_wpan_dst64(ROUTER) \ 264 .filter_mle_cmd(consts.MLE_LINK_METRICS_MANAGEMENT_REQUEST) \ 265 .filter(lambda p: consts.LM_ENHANCED_ACK_CONFIGURATION_SUB_TLV in p.mle.tlv.link_sub_tlv) \ 266 .filter(lambda p: p.mle.tlv.link_enh_ack_flags == consts.LINK_METRICS_ENH_ACK_PROBING_CLEAR) \ 267 .must_next() 268 269 270if __name__ == '__main__': 271 unittest.main() 272