1#!/usr/bin/env python3 2# 3# Copyright (c) 2021, 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 logging 31import pktverify 32from pktverify import packet_verifier 33from pktverify.consts import MA1, PBBR_ALOC 34import unittest 35 36import config 37import thread_cert 38 39# Test description: 40# The purpose of this test case is to verify that a Primary BBR ignores a 41# Timeout TLV if included in an MLR.req that does not contain a Commissioner 42# Session ID TLV nor is signed by a Commissioner. 43# 44# Topology: 45# ----------------(eth)------------------ 46# | | | 47# BR1 (Leader) ----- BR2 HOST 48# | | 49# | | 50# Router_1------------+ 51# 52 53BR_1 = 1 54BR_2 = 2 55ROUTER_1 = 3 56HOST = 4 57 58 59class MATN_03_InvalidCommissionerDeregistration(thread_cert.TestCase): 60 USE_MESSAGE_FACTORY = False 61 62 TOPOLOGY = { 63 BR_1: { 64 'name': 'BR_1', 65 'is_otbr': True, 66 'allowlist': [BR_2, ROUTER_1], 67 'version': '1.2', 68 }, 69 BR_2: { 70 'name': 'BR_2', 71 'allowlist': [BR_1, ROUTER_1], 72 'is_otbr': True, 73 'version': '1.2', 74 }, 75 ROUTER_1: { 76 'name': 'Router_1', 77 'allowlist': [BR_1, BR_2], 78 'version': '1.2', 79 }, 80 HOST: { 81 'name': 'Host', 82 'is_host': True 83 }, 84 } 85 86 def test(self): 87 br1 = self.nodes[BR_1] 88 br2 = self.nodes[BR_2] 89 router = self.nodes[ROUTER_1] 90 host = self.nodes[HOST] 91 92 br1.start() 93 self.simulator.go(config.LEADER_STARTUP_DELAY) 94 self.assertEqual('leader', br1.get_state()) 95 self.assertTrue(br1.is_primary_backbone_router) 96 97 router.start() 98 self.simulator.go(5) 99 self.assertEqual('router', router.get_state()) 100 101 br2.start() 102 self.simulator.go(5) 103 self.assertEqual('router', router.get_state()) 104 self.assertFalse(br2.is_primary_backbone_router) 105 106 host.start(start_radvd=False) 107 self.simulator.go(5) 108 109 router.add_ipmaddr(MA1) 110 self.simulator.go(5) 111 112 # Ensure that router can receive a multicast ping packet sent to MA1. 113 self.assertTrue( 114 host.ping(MA1, backbone=True, ttl=10, interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])) 115 self.simulator.go(5) 116 117 # 1. Router attempts to deregister for multicast address, MA1, at BR_1. 118 router.register_multicast_listener(MA1, timeout=0) 119 120 # 3. Host sends a ping packet to the multicast address, MA1. 121 self.assertTrue( 122 host.ping(MA1, backbone=True, ttl=10, interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])) 123 self.simulator.go(5) 124 125 self.collect_ipaddrs() 126 self.collect_rloc16s() 127 self.collect_rlocs() 128 self.collect_leader_aloc(BR_1) 129 self.collect_extra_vars() 130 131 def verify(self, pv: pktverify.packet_verifier.PacketVerifier): 132 pkts = pv.pkts 133 vars = pv.vars 134 pv.summary.show() 135 136 # Ensure the topology is formed correctly 137 pv.verify_attached('Router_1', 'BR_1') 138 pv.verify_attached('BR_2') 139 140 # 1. Router attempts to deregister for multicast address, MA1, at BR_1. 141 # Router unicasts an MLR.req CoAP request to BR_1 as follows: 142 # coap://[<BR_1 RLOC>]:MM/n/mr 143 # Where the payload contains: 144 # IPv6 Addresses TLV: MA1 145 # Timeout TLV: 0 146 pkts.filter_wpan_src64(vars['Router_1']) \ 147 .filter_ipv6_2dsts(vars['BR_1_RLOC'], PBBR_ALOC) \ 148 .filter_coap_request('/n/mr') \ 149 .filter(lambda p: p.thread_meshcop.tlv.ipv6_addr == [MA1] and 150 p.thread_nm.tlv.timeout == 0) \ 151 .must_next() 152 153 # 2. BR_1 responds to the multicast registration successfully, 154 # ignoring the timeout value. 155 pkts.filter_wpan_src64(vars['BR_1']) \ 156 .filter_ipv6_dst(vars['Router_1_RLOC']) \ 157 .filter_coap_ack('/n/mr') \ 158 .filter(lambda p: p.thread_nm.tlv.status == 0) \ 159 .must_next() 160 161 # 3. Host sends a ping packet to the multicast address, MA1. 162 _pkt = pkts.filter_eth_src(vars['Host_ETH']) \ 163 .filter_ipv6_dst(MA1) \ 164 .filter_ping_request() \ 165 .must_next() 166 167 # 4. BR_1 forwards the ping packet with multicast address, MA1, to its 168 # Thread Network encapsulated in an MPL packet. 169 pkts.filter_wpan_src64(vars['BR_1']) \ 170 .filter_AMPLFMA(mpl_seed_id=vars['BR_1_RLOC']) \ 171 .filter_ping_request(identifier=_pkt.icmpv6.echo.identifier) \ 172 .must_next() 173 174 # 5. Router receives the MPL packet containing an encapsulated ping 175 # packet to MA1, sent by Host, and unicasts a ping response packet back 176 # to Host. 177 pkts.filter_wpan_src64(vars['Router_1']) \ 178 .filter_ipv6_dst(_pkt.ipv6.src) \ 179 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 180 .must_next() 181 182 183if __name__ == '__main__': 184 unittest.main() 185