1#!/usr/bin/env python3 2# 3# Copyright (c) 2020, 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# This test verifies that the MLR timeout configured by Commissioner works for multicast routing. 30# 31import unittest 32import config 33 34from pktverify.consts import NM_COMMISSIONER_SESSION_ID_TLV 35from pktverify.packet_verifier import PacketVerifier 36from test_mlr_multicast_routing_timeout import ROUTER, HOST 37from test_mlr_multicast_routing_timeout import TestMlrTimeout, MLR_TIMEOUT, WAIT_REDUNDANCE, MA1 38 39COMMISSIONER_MLR_TIMEOUT = 360 40 41assert COMMISSIONER_MLR_TIMEOUT > MLR_TIMEOUT + WAIT_REDUNDANCE * 3, "COMMISSIONER_MLR_TIMEOUT should be significantly larger than MLR_TIMEOUT" 42 43 44class TestMlrCommissionerTimeout(TestMlrTimeout): 45 46 # Topology (same as TestMlrTimeout): 47 # --------(eth)--------- 48 # | | 49 # PBBR(Leader) HOST 50 # | 51 # ROUTER 52 # 53 54 def test(self): 55 self._bootstrap() 56 57 # Ping 1: PBBR should not forward to Thread network 58 self.assertFalse(self.nodes[HOST].ping(MA1, backbone=True, ttl=10)) 59 60 # Router starts Commissioner 61 self.nodes[ROUTER].commissioner_start() 62 self.simulator.go(10) 63 self.assertEqual('active', self.nodes[ROUTER].commissioner_state()) 64 65 # Router (Commissioner) registers MA1 66 self.nodes[ROUTER].register_multicast_listener(MA1, timeout=COMMISSIONER_MLR_TIMEOUT) 67 self.simulator.go(WAIT_REDUNDANCE) 68 69 # Ping 2: PBBR should forward to Thread network 70 self.nodes[HOST].ping(MA1, backbone=True, ttl=10) 71 72 self.simulator.go(MLR_TIMEOUT + WAIT_REDUNDANCE) 73 74 # Ping 3: PBBR should forward to Thread network 75 self.nodes[HOST].ping(MA1, backbone=True, ttl=10) 76 77 self.simulator.go(COMMISSIONER_MLR_TIMEOUT - MLR_TIMEOUT) 78 79 # Ping 4: PBBR should NOT forward to Thread network 80 self.assertFalse(self.nodes[HOST].ping(MA1, backbone=True, ttl=10)) 81 82 def verify(self, pv: PacketVerifier): 83 pkts = pv.pkts 84 pv.add_common_vars() 85 pv.summary.show() 86 87 ROUTER = pv.vars['ROUTER'] 88 PBBR = pv.vars['PBBR'] 89 MM = pv.vars['MM_PORT'] 90 HOST_ETH = pv.vars['Host_ETH'] 91 HOST_BGUA = pv.vars['Host_BGUA'] 92 93 start = pkts.index 94 95 # Verify that Router sends MLR.req for MA1 with Commissioner timeout 96 pkts.filter_wpan_src64(ROUTER).filter_coap_request('/n/mr', port=MM).must_next().must_verify( 97 """ 98 thread_meshcop.tlv.ipv6_addr == {ipv6_addr} 99 and thread_nm.tlv.timeout == {timeout} 100 and {NM_COMMISSIONER_SESSION_ID_TLV} in thread_nm.tlv.type 101 """, 102 ipv6_addr=[MA1], 103 timeout=COMMISSIONER_MLR_TIMEOUT, 104 NM_COMMISSIONER_SESSION_ID_TLV=NM_COMMISSIONER_SESSION_ID_TLV) 105 106 mr_index = pkts.index 107 108 # Ping 1: Host pings Router before MLR.reg 109 before_mr_pkts = pkts.range(start, mr_index, cascade=False) 110 ping1 = before_mr_pkts.filter_eth_src(HOST_ETH).filter_ipv6_dst(MA1).filter_ping_request().must_next() 111 112 # PBBR should not forward Ping 1 to Thread network 113 before_mr_pkts.filter_wpan_src64(PBBR).filter_ipv6_dst(MA1).filter_ping_request( 114 identifier=ping1.icmpv6.echo.identifier).must_not_next() 115 116 # Ping 2: Host pings Router after MLR.req 117 ping2 = pkts.filter_eth_src(HOST_ETH).filter_ipv6_dst(MA1).filter_ping_request().must_next() 118 # PBBR should forward this ping request to Thread network 119 pkts.filter_wpan_src64(PBBR).filter_AMPLFMA().filter_ping_request( 120 identifier=ping2.icmpv6.echo.identifier).must_next() 121 122 # Ping 3: Host pings Router after delayed MLR Timeout 123 ping3 = pkts.filter_eth_src(HOST_ETH).filter_ipv6_dst(MA1).filter_ping_request().must_next() 124 # PBBR should forward this ping request to Thread network because MA doesn't expire yet 125 pkts.filter_wpan_src64(PBBR).filter_AMPLFMA().filter_ping_request( 126 identifier=ping3.icmpv6.echo.identifier).must_next() 127 128 # Ping 4: Host pings Router after delayed Commissioner MLR Timeout 129 ping4 = pkts.filter_eth_src(HOST_ETH).filter_ipv6_dst(MA1).filter_ping_request().must_next() 130 # PBBR should NOT forward this ping request to Thread network because MLR has timeout 131 pkts.filter_wpan_src64(PBBR).filter_AMPLFMA().filter_ping_request( 132 identifier=ping4.icmpv6.echo.identifier).must_not_next() 133 134 135del TestMlrTimeout 136 137if __name__ == '__main__': 138 unittest.main() 139