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# 29import ipaddress 30import json 31import logging 32import unittest 33 34import config 35import pktverify.verify 36import thread_cert 37 38# Test description: 39# This test verifies Thread end-devices have UDP reachability to the infrastructure link via a Thread BR. 40# 41# Topology: 42# ----------------(eth)-------------------- 43# | | 44# BR1 HOST 45# / 46# FED1 47from pktverify.packet_verifier import PacketVerifier 48 49BR1 = 1 50FED1 = 2 51HOST = 3 52 53PORT = 11111 54UDP_PAYLOAD_LEN = 17 55 56 57class TestEndDeviceUdpReachability(thread_cert.TestCase): 58 USE_MESSAGE_FACTORY = False 59 60 TOPOLOGY = { 61 BR1: { 62 'name': 'BR1', 63 'is_otbr': True, 64 'version': '1.2', 65 }, 66 FED1: { 67 'name': 'FED1', 68 'router_eligible': False, 69 }, 70 HOST: { 71 'name': 'HOST', 72 'is_host': True 73 }, 74 } 75 76 def test(self): 77 br1 = self.nodes[BR1] 78 fed1 = self.nodes[FED1] 79 host = self.nodes[HOST] 80 81 host.start(start_radvd=False) 82 self.simulator.go(5) 83 84 br1.start() 85 self.simulator.go(config.LEADER_STARTUP_DELAY) 86 self.assertEqual('leader', br1.get_state()) 87 br1.udp_start("::", PORT, bind_unspecified=True) 88 89 fed1.start() 90 self.simulator.go(5) 91 self.assertEqual('child', fed1.get_state()) 92 93 self.simulator.go(20) 94 95 fed1_omr_addr = fed1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0] 96 host_addr = host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0] 97 print("Host address:", host_addr) 98 print('FED address:', fed1_omr_addr) 99 100 self.assertTrue(fed1.ping(host_addr)) 101 self.assertTrue(host.ping(fed1_omr_addr, backbone=True)) 102 103 fed1.udp_start("::", PORT) 104 105 fed1.udp_send(UDP_PAYLOAD_LEN, host_addr, PORT) 106 self.simulator.go(5) 107 108 host.udp_send_host(data='A' * UDP_PAYLOAD_LEN, ipaddr=fed1_omr_addr, port=PORT) 109 self.simulator.go(5) 110 111 self.collect_ipaddrs() 112 self.collect_extra_vars(FED1_OMR=fed1_omr_addr, HOST_ONLINK_ULA=host_addr) 113 114 def verify(self, pv: PacketVerifier): 115 pkts = pv.pkts 116 pv.summary.show() 117 118 BR1 = pv.vars['BR1'] 119 FED1 = pv.vars['FED1'] 120 BR1_ETH = pv.vars['BR1_ETH'] 121 HOST_ETH = pv.vars['HOST_ETH'] 122 123 udp_pkts = pkts.filter(""" 124 udp.srcport == {PORT} and 125 udp.dstport == {PORT} and 126 udp.length == {UDP_LENGTH} 127 """, 128 PORT=PORT, 129 UDP_LENGTH=UDP_PAYLOAD_LEN + 8) 130 131 # FED1 should send a UDP message to BR1 132 udp_pkts.filter_wpan_src64(FED1).must_next() 133 134 # BR1 should forward the UDP message to the infrastructure link 135 udp_pkts.filter_eth_src(BR1_ETH).must_next() 136 137 udp_pkts = pkts.filter(""" 138 udp.dstport == {PORT} and 139 udp.length == {UDP_LENGTH} 140 """, 141 PORT=PORT, 142 UDP_LENGTH=UDP_PAYLOAD_LEN + 8) 143 144 # Host should send a UDP message to BR1 145 udp_pkts.filter_eth_src(HOST_ETH).must_next() 146 147 # BR1 should forward the UDP message to FED1 148 udp_pkts.filter_wpan_src64(BR1).must_next() 149 150 151if __name__ == '__main__': 152 unittest.main() 153