1*cfb92d14SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cfb92d14SAndroid Build Coastguard Worker# 3*cfb92d14SAndroid Build Coastguard Worker# Copyright (c) 2021, The OpenThread Authors. 4*cfb92d14SAndroid Build Coastguard Worker# All rights reserved. 5*cfb92d14SAndroid Build Coastguard Worker# 6*cfb92d14SAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without 7*cfb92d14SAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are met: 8*cfb92d14SAndroid Build Coastguard Worker# 1. Redistributions of source code must retain the above copyright 9*cfb92d14SAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer. 10*cfb92d14SAndroid Build Coastguard Worker# 2. Redistributions in binary form must reproduce the above copyright 11*cfb92d14SAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer in the 12*cfb92d14SAndroid Build Coastguard Worker# documentation and/or other materials provided with the distribution. 13*cfb92d14SAndroid Build Coastguard Worker# 3. Neither the name of the copyright holder nor the 14*cfb92d14SAndroid Build Coastguard Worker# names of its contributors may be used to endorse or promote products 15*cfb92d14SAndroid Build Coastguard Worker# derived from this software without specific prior written permission. 16*cfb92d14SAndroid Build Coastguard Worker# 17*cfb92d14SAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18*cfb92d14SAndroid Build Coastguard Worker# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*cfb92d14SAndroid Build Coastguard Worker# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*cfb92d14SAndroid Build Coastguard Worker# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21*cfb92d14SAndroid Build Coastguard Worker# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22*cfb92d14SAndroid Build Coastguard Worker# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*cfb92d14SAndroid Build Coastguard Worker# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*cfb92d14SAndroid Build Coastguard Worker# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25*cfb92d14SAndroid Build Coastguard Worker# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*cfb92d14SAndroid Build Coastguard Worker# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27*cfb92d14SAndroid Build Coastguard Worker# POSSIBILITY OF SUCH DAMAGE. 28*cfb92d14SAndroid Build Coastguard Worker# 29*cfb92d14SAndroid Build Coastguard Worker 30*cfb92d14SAndroid Build Coastguard Workerimport sys 31*cfb92d14SAndroid Build Coastguard Workerimport os 32*cfb92d14SAndroid Build Coastguard Workerimport time 33*cfb92d14SAndroid Build Coastguard Workerimport re 34*cfb92d14SAndroid Build Coastguard Workerimport random 35*cfb92d14SAndroid Build Coastguard Workerimport string 36*cfb92d14SAndroid Build Coastguard Workerimport subprocess 37*cfb92d14SAndroid Build Coastguard Workerimport pexpect 38*cfb92d14SAndroid Build Coastguard Workerimport pexpect.popen_spawn 39*cfb92d14SAndroid Build Coastguard Workerimport signal 40*cfb92d14SAndroid Build Coastguard Workerimport inspect 41*cfb92d14SAndroid Build Coastguard Workerimport weakref 42*cfb92d14SAndroid Build Coastguard Worker 43*cfb92d14SAndroid Build Coastguard Worker# ---------------------------------------------------------------------------------------------------------------------- 44*cfb92d14SAndroid Build Coastguard Worker# Constants 45*cfb92d14SAndroid Build Coastguard Worker 46*cfb92d14SAndroid Build Coastguard WorkerJOIN_TYPE_ROUTER = 'router' 47*cfb92d14SAndroid Build Coastguard WorkerJOIN_TYPE_END_DEVICE = 'ed' 48*cfb92d14SAndroid Build Coastguard WorkerJOIN_TYPE_SLEEPY_END_DEVICE = 'sed' 49*cfb92d14SAndroid Build Coastguard WorkerJOIN_TYPE_REED = 'reed' 50*cfb92d14SAndroid Build Coastguard Worker 51*cfb92d14SAndroid Build Coastguard Worker# for use as `radios` parameter in `Node.__init__()` 52*cfb92d14SAndroid Build Coastguard WorkerRADIO_15_4 = "-15.4" 53*cfb92d14SAndroid Build Coastguard WorkerRADIO_TREL = "-trel" 54*cfb92d14SAndroid Build Coastguard WorkerRADIO_15_4_TREL = "-15.4-trel" 55*cfb92d14SAndroid Build Coastguard Worker 56*cfb92d14SAndroid Build Coastguard Worker# ---------------------------------------------------------------------------------------------------------------------- 57*cfb92d14SAndroid Build Coastguard Worker 58*cfb92d14SAndroid Build Coastguard Worker 59*cfb92d14SAndroid Build Coastguard Workerdef _log(text, new_line=True, flush=True): 60*cfb92d14SAndroid Build Coastguard Worker sys.stdout.write(text) 61*cfb92d14SAndroid Build Coastguard Worker if new_line: 62*cfb92d14SAndroid Build Coastguard Worker sys.stdout.write('\n') 63*cfb92d14SAndroid Build Coastguard Worker if flush: 64*cfb92d14SAndroid Build Coastguard Worker sys.stdout.flush() 65*cfb92d14SAndroid Build Coastguard Worker 66*cfb92d14SAndroid Build Coastguard Worker 67*cfb92d14SAndroid Build Coastguard Worker# ---------------------------------------------------------------------------------------------------------------------- 68*cfb92d14SAndroid Build Coastguard Worker# CliError class 69*cfb92d14SAndroid Build Coastguard Worker 70*cfb92d14SAndroid Build Coastguard Worker 71*cfb92d14SAndroid Build Coastguard Workerclass CliError(Exception): 72*cfb92d14SAndroid Build Coastguard Worker 73*cfb92d14SAndroid Build Coastguard Worker def __init__(self, error_code, message): 74*cfb92d14SAndroid Build Coastguard Worker self._error_code = error_code 75*cfb92d14SAndroid Build Coastguard Worker self._message = message 76*cfb92d14SAndroid Build Coastguard Worker 77*cfb92d14SAndroid Build Coastguard Worker @property 78*cfb92d14SAndroid Build Coastguard Worker def error_code(self): 79*cfb92d14SAndroid Build Coastguard Worker return self._error_code 80*cfb92d14SAndroid Build Coastguard Worker 81*cfb92d14SAndroid Build Coastguard Worker @property 82*cfb92d14SAndroid Build Coastguard Worker def message(self): 83*cfb92d14SAndroid Build Coastguard Worker return self._message 84*cfb92d14SAndroid Build Coastguard Worker 85*cfb92d14SAndroid Build Coastguard Worker 86*cfb92d14SAndroid Build Coastguard Worker# ---------------------------------------------------------------------------------------------------------------------- 87*cfb92d14SAndroid Build Coastguard Worker# Node class 88*cfb92d14SAndroid Build Coastguard Worker 89*cfb92d14SAndroid Build Coastguard Worker 90*cfb92d14SAndroid Build Coastguard Workerclass Node(object): 91*cfb92d14SAndroid Build Coastguard Worker """ An OT CLI instance """ 92*cfb92d14SAndroid Build Coastguard Worker 93*cfb92d14SAndroid Build Coastguard Worker # defines the default verbosity setting (can be changed per `Node`) 94*cfb92d14SAndroid Build Coastguard Worker _VERBOSE = os.getenv('TORANJ_VERBOSE', 'no').lower() in ['true', '1', 't', 'y', 'yes', 'on'] 95*cfb92d14SAndroid Build Coastguard Worker 96*cfb92d14SAndroid Build Coastguard Worker _SPEED_UP_FACTOR = 1 # defines the default time speed up factor 97*cfb92d14SAndroid Build Coastguard Worker 98*cfb92d14SAndroid Build Coastguard Worker # Determine whether to save logs in a file. 99*cfb92d14SAndroid Build Coastguard Worker _SAVE_LOGS = True 100*cfb92d14SAndroid Build Coastguard Worker 101*cfb92d14SAndroid Build Coastguard Worker # name of log file (if _SAVE_LOGS is `True`) 102*cfb92d14SAndroid Build Coastguard Worker _LOG_FNAME = 'ot-logs' 103*cfb92d14SAndroid Build Coastguard Worker 104*cfb92d14SAndroid Build Coastguard Worker _OT_BUILDDIR = os.getenv('top_builddir', '../../..') 105*cfb92d14SAndroid Build Coastguard Worker 106*cfb92d14SAndroid Build Coastguard Worker _OT_CLI_FTD = '%s/examples/apps/cli/ot-cli-ftd' % _OT_BUILDDIR 107*cfb92d14SAndroid Build Coastguard Worker 108*cfb92d14SAndroid Build Coastguard Worker _WAIT_TIME = 10 109*cfb92d14SAndroid Build Coastguard Worker 110*cfb92d14SAndroid Build Coastguard Worker _START_INDEX = 1 111*cfb92d14SAndroid Build Coastguard Worker _cur_index = _START_INDEX 112*cfb92d14SAndroid Build Coastguard Worker 113*cfb92d14SAndroid Build Coastguard Worker _all_nodes = weakref.WeakSet() 114*cfb92d14SAndroid Build Coastguard Worker 115*cfb92d14SAndroid Build Coastguard Worker def __init__(self, radios='', index=None, verbose=_VERBOSE): 116*cfb92d14SAndroid Build Coastguard Worker """Creates a new `Node` instance""" 117*cfb92d14SAndroid Build Coastguard Worker 118*cfb92d14SAndroid Build Coastguard Worker if index is None: 119*cfb92d14SAndroid Build Coastguard Worker index = Node._cur_index 120*cfb92d14SAndroid Build Coastguard Worker Node._cur_index += 1 121*cfb92d14SAndroid Build Coastguard Worker 122*cfb92d14SAndroid Build Coastguard Worker self._index = index 123*cfb92d14SAndroid Build Coastguard Worker self._verbose = verbose 124*cfb92d14SAndroid Build Coastguard Worker 125*cfb92d14SAndroid Build Coastguard Worker cmd = f'{self._OT_CLI_FTD}{radios} --time-speed={self._SPEED_UP_FACTOR} ' 126*cfb92d14SAndroid Build Coastguard Worker 127*cfb92d14SAndroid Build Coastguard Worker if Node._SAVE_LOGS: 128*cfb92d14SAndroid Build Coastguard Worker log_file_name = self._LOG_FNAME + str(index) + '.log' 129*cfb92d14SAndroid Build Coastguard Worker cmd = cmd + f'--log-file={log_file_name} ' 130*cfb92d14SAndroid Build Coastguard Worker 131*cfb92d14SAndroid Build Coastguard Worker cmd = cmd + f'{self._index}' 132*cfb92d14SAndroid Build Coastguard Worker 133*cfb92d14SAndroid Build Coastguard Worker if self._verbose: 134*cfb92d14SAndroid Build Coastguard Worker _log(f'$ Node{index}.__init__() cmd: `{cmd}`') 135*cfb92d14SAndroid Build Coastguard Worker 136*cfb92d14SAndroid Build Coastguard Worker self._cli_process = pexpect.popen_spawn.PopenSpawn(cmd) 137*cfb92d14SAndroid Build Coastguard Worker Node._all_nodes.add(self) 138*cfb92d14SAndroid Build Coastguard Worker 139*cfb92d14SAndroid Build Coastguard Worker def __del__(self): 140*cfb92d14SAndroid Build Coastguard Worker self._finalize() 141*cfb92d14SAndroid Build Coastguard Worker 142*cfb92d14SAndroid Build Coastguard Worker def __repr__(self): 143*cfb92d14SAndroid Build Coastguard Worker return f'Node(index={self._index})' 144*cfb92d14SAndroid Build Coastguard Worker 145*cfb92d14SAndroid Build Coastguard Worker @property 146*cfb92d14SAndroid Build Coastguard Worker def index(self): 147*cfb92d14SAndroid Build Coastguard Worker return self._index 148*cfb92d14SAndroid Build Coastguard Worker 149*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 150*cfb92d14SAndroid Build Coastguard Worker # Executing a `cli` command 151*cfb92d14SAndroid Build Coastguard Worker 152*cfb92d14SAndroid Build Coastguard Worker def cli(self, *args): 153*cfb92d14SAndroid Build Coastguard Worker """ Issues a CLI command on the given node and returns the resulting output. 154*cfb92d14SAndroid Build Coastguard Worker 155*cfb92d14SAndroid Build Coastguard Worker The returned result is a list of strings (with `\r\n` removed) as outputted by the CLI. 156*cfb92d14SAndroid Build Coastguard Worker If executing the command fails, `CliError` is raised with error code and error message. 157*cfb92d14SAndroid Build Coastguard Worker """ 158*cfb92d14SAndroid Build Coastguard Worker 159*cfb92d14SAndroid Build Coastguard Worker cmd = ' '.join([f'{arg}' for arg in args if arg is not None]).strip() 160*cfb92d14SAndroid Build Coastguard Worker 161*cfb92d14SAndroid Build Coastguard Worker if self._verbose: 162*cfb92d14SAndroid Build Coastguard Worker _log(f'$ Node{self._index}.cli(\'{cmd}\')', new_line=False) 163*cfb92d14SAndroid Build Coastguard Worker 164*cfb92d14SAndroid Build Coastguard Worker self._cli_process.send(cmd + '\n') 165*cfb92d14SAndroid Build Coastguard Worker index = self._cli_process.expect(['(.*)Done\r\n', '.*Error (\d+):(.*)\r\n']) 166*cfb92d14SAndroid Build Coastguard Worker 167*cfb92d14SAndroid Build Coastguard Worker if index == 0: 168*cfb92d14SAndroid Build Coastguard Worker result = [ 169*cfb92d14SAndroid Build Coastguard Worker line for line in self._cli_process.match.group(1).decode().splitlines() 170*cfb92d14SAndroid Build Coastguard Worker if not self._is_ot_logg_line(line) if not line.strip().endswith(cmd) 171*cfb92d14SAndroid Build Coastguard Worker ] 172*cfb92d14SAndroid Build Coastguard Worker 173*cfb92d14SAndroid Build Coastguard Worker if self._verbose: 174*cfb92d14SAndroid Build Coastguard Worker if len(result) > 1: 175*cfb92d14SAndroid Build Coastguard Worker _log(':') 176*cfb92d14SAndroid Build Coastguard Worker for line in result: 177*cfb92d14SAndroid Build Coastguard Worker _log(' ' + line) 178*cfb92d14SAndroid Build Coastguard Worker elif len(result) == 1: 179*cfb92d14SAndroid Build Coastguard Worker _log(f' -> {result[0]}') 180*cfb92d14SAndroid Build Coastguard Worker else: 181*cfb92d14SAndroid Build Coastguard Worker _log('') 182*cfb92d14SAndroid Build Coastguard Worker 183*cfb92d14SAndroid Build Coastguard Worker return result 184*cfb92d14SAndroid Build Coastguard Worker else: 185*cfb92d14SAndroid Build Coastguard Worker match = self._cli_process.match 186*cfb92d14SAndroid Build Coastguard Worker e = CliError(int(match.group(1).decode()), match.group(2).decode().strip()) 187*cfb92d14SAndroid Build Coastguard Worker if self._verbose: 188*cfb92d14SAndroid Build Coastguard Worker _log(f': Error {e.message} ({e.error_code})') 189*cfb92d14SAndroid Build Coastguard Worker raise e 190*cfb92d14SAndroid Build Coastguard Worker 191*cfb92d14SAndroid Build Coastguard Worker def _is_ot_logg_line(self, line): 192*cfb92d14SAndroid Build Coastguard Worker return any(level in line for level in [' [D] ', ' [I] ', ' [N] ', ' [W] ', ' [C] ', ' [-] ']) 193*cfb92d14SAndroid Build Coastguard Worker 194*cfb92d14SAndroid Build Coastguard Worker def _cli_no_output(self, cmd, *args): 195*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli(cmd, *args) 196*cfb92d14SAndroid Build Coastguard Worker verify(len(outputs) == 0) 197*cfb92d14SAndroid Build Coastguard Worker 198*cfb92d14SAndroid Build Coastguard Worker def _cli_single_output(self, cmd, *args, expected_outputs=None): 199*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli(cmd, *args) 200*cfb92d14SAndroid Build Coastguard Worker verify(len(outputs) == 1) 201*cfb92d14SAndroid Build Coastguard Worker verify((expected_outputs is None) or (outputs[0] in expected_outputs)) 202*cfb92d14SAndroid Build Coastguard Worker return outputs[0] 203*cfb92d14SAndroid Build Coastguard Worker 204*cfb92d14SAndroid Build Coastguard Worker def _finalize(self): 205*cfb92d14SAndroid Build Coastguard Worker if self._cli_process.proc.poll() is None: 206*cfb92d14SAndroid Build Coastguard Worker if self._verbose: 207*cfb92d14SAndroid Build Coastguard Worker _log(f'$ Node{self.index} terminating') 208*cfb92d14SAndroid Build Coastguard Worker self._cli_process.send('exit\n') 209*cfb92d14SAndroid Build Coastguard Worker self._cli_process.wait() 210*cfb92d14SAndroid Build Coastguard Worker 211*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 212*cfb92d14SAndroid Build Coastguard Worker # cli commands 213*cfb92d14SAndroid Build Coastguard Worker 214*cfb92d14SAndroid Build Coastguard Worker def get_state(self): 215*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('state', expected_outputs=['detached', 'child', 'router', 'leader', 'disabled']) 216*cfb92d14SAndroid Build Coastguard Worker 217*cfb92d14SAndroid Build Coastguard Worker def get_version(self): 218*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('version') 219*cfb92d14SAndroid Build Coastguard Worker 220*cfb92d14SAndroid Build Coastguard Worker def get_channel(self): 221*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('channel') 222*cfb92d14SAndroid Build Coastguard Worker 223*cfb92d14SAndroid Build Coastguard Worker def set_channel(self, channel): 224*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('channel', channel) 225*cfb92d14SAndroid Build Coastguard Worker 226*cfb92d14SAndroid Build Coastguard Worker def get_csl_config(self): 227*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('csl') 228*cfb92d14SAndroid Build Coastguard Worker result = {} 229*cfb92d14SAndroid Build Coastguard Worker for line in outputs: 230*cfb92d14SAndroid Build Coastguard Worker fields = line.split(':') 231*cfb92d14SAndroid Build Coastguard Worker result[fields[0].strip()] = fields[1].strip() 232*cfb92d14SAndroid Build Coastguard Worker return result 233*cfb92d14SAndroid Build Coastguard Worker 234*cfb92d14SAndroid Build Coastguard Worker def set_csl_period(self, period): 235*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('csl period', period) 236*cfb92d14SAndroid Build Coastguard Worker 237*cfb92d14SAndroid Build Coastguard Worker def get_ext_addr(self): 238*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('extaddr') 239*cfb92d14SAndroid Build Coastguard Worker 240*cfb92d14SAndroid Build Coastguard Worker def set_ext_addr(self, ext_addr): 241*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('extaddr', ext_addr) 242*cfb92d14SAndroid Build Coastguard Worker 243*cfb92d14SAndroid Build Coastguard Worker def get_ext_panid(self): 244*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('extpanid') 245*cfb92d14SAndroid Build Coastguard Worker 246*cfb92d14SAndroid Build Coastguard Worker def set_ext_panid(self, ext_panid): 247*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('extpanid', ext_panid) 248*cfb92d14SAndroid Build Coastguard Worker 249*cfb92d14SAndroid Build Coastguard Worker def get_mode(self): 250*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('mode') 251*cfb92d14SAndroid Build Coastguard Worker 252*cfb92d14SAndroid Build Coastguard Worker def set_mode(self, mode): 253*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('mode', mode) 254*cfb92d14SAndroid Build Coastguard Worker 255*cfb92d14SAndroid Build Coastguard Worker def get_network_key(self): 256*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('networkkey') 257*cfb92d14SAndroid Build Coastguard Worker 258*cfb92d14SAndroid Build Coastguard Worker def set_network_key(self, networkkey): 259*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('networkkey', networkkey) 260*cfb92d14SAndroid Build Coastguard Worker 261*cfb92d14SAndroid Build Coastguard Worker def get_network_name(self): 262*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('networkname') 263*cfb92d14SAndroid Build Coastguard Worker 264*cfb92d14SAndroid Build Coastguard Worker def set_network_name(self, network_name): 265*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('networkname', network_name) 266*cfb92d14SAndroid Build Coastguard Worker 267*cfb92d14SAndroid Build Coastguard Worker def get_panid(self): 268*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('panid') 269*cfb92d14SAndroid Build Coastguard Worker 270*cfb92d14SAndroid Build Coastguard Worker def set_panid(self, panid): 271*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('panid', panid) 272*cfb92d14SAndroid Build Coastguard Worker 273*cfb92d14SAndroid Build Coastguard Worker def get_router_upgrade_threshold(self): 274*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('routerupgradethreshold') 275*cfb92d14SAndroid Build Coastguard Worker 276*cfb92d14SAndroid Build Coastguard Worker def set_router_upgrade_threshold(self, threshold): 277*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('routerupgradethreshold', threshold) 278*cfb92d14SAndroid Build Coastguard Worker 279*cfb92d14SAndroid Build Coastguard Worker def get_router_selection_jitter(self): 280*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('routerselectionjitter') 281*cfb92d14SAndroid Build Coastguard Worker 282*cfb92d14SAndroid Build Coastguard Worker def set_router_selection_jitter(self, jitter): 283*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('routerselectionjitter', jitter) 284*cfb92d14SAndroid Build Coastguard Worker 285*cfb92d14SAndroid Build Coastguard Worker def get_router_eligible(self): 286*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('routereligible') 287*cfb92d14SAndroid Build Coastguard Worker 288*cfb92d14SAndroid Build Coastguard Worker def set_router_eligible(self, enable): 289*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('routereligible', enable) 290*cfb92d14SAndroid Build Coastguard Worker 291*cfb92d14SAndroid Build Coastguard Worker def get_context_reuse_delay(self): 292*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('contextreusedelay') 293*cfb92d14SAndroid Build Coastguard Worker 294*cfb92d14SAndroid Build Coastguard Worker def set_context_reuse_delay(self, delay): 295*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('contextreusedelay', delay) 296*cfb92d14SAndroid Build Coastguard Worker 297*cfb92d14SAndroid Build Coastguard Worker def interface_up(self): 298*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ifconfig up') 299*cfb92d14SAndroid Build Coastguard Worker 300*cfb92d14SAndroid Build Coastguard Worker def interface_down(self): 301*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ifconfig down') 302*cfb92d14SAndroid Build Coastguard Worker 303*cfb92d14SAndroid Build Coastguard Worker def get_interface_state(self): 304*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ifconfig') 305*cfb92d14SAndroid Build Coastguard Worker 306*cfb92d14SAndroid Build Coastguard Worker def thread_start(self): 307*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('thread start') 308*cfb92d14SAndroid Build Coastguard Worker 309*cfb92d14SAndroid Build Coastguard Worker def thread_stop(self): 310*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('thread stop') 311*cfb92d14SAndroid Build Coastguard Worker 312*cfb92d14SAndroid Build Coastguard Worker def get_rloc16(self): 313*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('rloc16') 314*cfb92d14SAndroid Build Coastguard Worker 315*cfb92d14SAndroid Build Coastguard Worker def get_ip_addrs(self, verbose=None): 316*cfb92d14SAndroid Build Coastguard Worker return self.cli('ipaddr', verbose) 317*cfb92d14SAndroid Build Coastguard Worker 318*cfb92d14SAndroid Build Coastguard Worker def add_ip_addr(self, address): 319*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ipaddr add', address) 320*cfb92d14SAndroid Build Coastguard Worker 321*cfb92d14SAndroid Build Coastguard Worker def remove_ip_addr(self, address): 322*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ipaddr del', address) 323*cfb92d14SAndroid Build Coastguard Worker 324*cfb92d14SAndroid Build Coastguard Worker def get_mleid_ip_addr(self): 325*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ipaddr mleid') 326*cfb92d14SAndroid Build Coastguard Worker 327*cfb92d14SAndroid Build Coastguard Worker def get_linklocal_ip_addr(self): 328*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ipaddr linklocal') 329*cfb92d14SAndroid Build Coastguard Worker 330*cfb92d14SAndroid Build Coastguard Worker def get_rloc_ip_addr(self): 331*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ipaddr rloc') 332*cfb92d14SAndroid Build Coastguard Worker 333*cfb92d14SAndroid Build Coastguard Worker def get_mesh_local_prefix(self): 334*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('prefix meshlocal') 335*cfb92d14SAndroid Build Coastguard Worker 336*cfb92d14SAndroid Build Coastguard Worker def get_ip_maddrs(self): 337*cfb92d14SAndroid Build Coastguard Worker return self.cli('ipmaddr') 338*cfb92d14SAndroid Build Coastguard Worker 339*cfb92d14SAndroid Build Coastguard Worker def add_ip_maddr(self, maddr): 340*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('ipmaddr add', maddr) 341*cfb92d14SAndroid Build Coastguard Worker 342*cfb92d14SAndroid Build Coastguard Worker def get_leader_weight(self): 343*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('leaderweight') 344*cfb92d14SAndroid Build Coastguard Worker 345*cfb92d14SAndroid Build Coastguard Worker def set_leader_weight(self, weight): 346*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('leaderweight', weight) 347*cfb92d14SAndroid Build Coastguard Worker 348*cfb92d14SAndroid Build Coastguard Worker def get_pollperiod(self): 349*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('pollperiod') 350*cfb92d14SAndroid Build Coastguard Worker 351*cfb92d14SAndroid Build Coastguard Worker def set_pollperiod(self, period): 352*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('pollperiod', period) 353*cfb92d14SAndroid Build Coastguard Worker 354*cfb92d14SAndroid Build Coastguard Worker def get_partition_id(self): 355*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('partitionid') 356*cfb92d14SAndroid Build Coastguard Worker 357*cfb92d14SAndroid Build Coastguard Worker def get_nexthop(self, rloc16): 358*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('nexthop', rloc16) 359*cfb92d14SAndroid Build Coastguard Worker 360*cfb92d14SAndroid Build Coastguard Worker def get_parent_info(self): 361*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('parent') 362*cfb92d14SAndroid Build Coastguard Worker result = {} 363*cfb92d14SAndroid Build Coastguard Worker for line in outputs: 364*cfb92d14SAndroid Build Coastguard Worker fields = line.split(':') 365*cfb92d14SAndroid Build Coastguard Worker result[fields[0].strip()] = fields[1].strip() 366*cfb92d14SAndroid Build Coastguard Worker return result 367*cfb92d14SAndroid Build Coastguard Worker 368*cfb92d14SAndroid Build Coastguard Worker def get_child_table(self): 369*cfb92d14SAndroid Build Coastguard Worker return Node.parse_table(self.cli('child table')) 370*cfb92d14SAndroid Build Coastguard Worker 371*cfb92d14SAndroid Build Coastguard Worker def get_neighbor_table(self): 372*cfb92d14SAndroid Build Coastguard Worker return Node.parse_table(self.cli('neighbor table')) 373*cfb92d14SAndroid Build Coastguard Worker 374*cfb92d14SAndroid Build Coastguard Worker def get_router_table(self): 375*cfb92d14SAndroid Build Coastguard Worker return Node.parse_table(self.cli('router table')) 376*cfb92d14SAndroid Build Coastguard Worker 377*cfb92d14SAndroid Build Coastguard Worker def get_eidcache(self): 378*cfb92d14SAndroid Build Coastguard Worker return self.cli('eidcache') 379*cfb92d14SAndroid Build Coastguard Worker 380*cfb92d14SAndroid Build Coastguard Worker def get_vendor_name(self): 381*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('vendor name') 382*cfb92d14SAndroid Build Coastguard Worker 383*cfb92d14SAndroid Build Coastguard Worker def set_vendor_name(self, name): 384*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('vendor name', name) 385*cfb92d14SAndroid Build Coastguard Worker 386*cfb92d14SAndroid Build Coastguard Worker def get_vendor_model(self): 387*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('vendor model') 388*cfb92d14SAndroid Build Coastguard Worker 389*cfb92d14SAndroid Build Coastguard Worker def set_vendor_model(self, model): 390*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('vendor model', model) 391*cfb92d14SAndroid Build Coastguard Worker 392*cfb92d14SAndroid Build Coastguard Worker def get_vendor_sw_version(self): 393*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('vendor swversion') 394*cfb92d14SAndroid Build Coastguard Worker 395*cfb92d14SAndroid Build Coastguard Worker def set_vendor_sw_version(self, version): 396*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('vendor swversion', version) 397*cfb92d14SAndroid Build Coastguard Worker 398*cfb92d14SAndroid Build Coastguard Worker def get_vendor_app_url(self): 399*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('vendor appurl') 400*cfb92d14SAndroid Build Coastguard Worker 401*cfb92d14SAndroid Build Coastguard Worker def set_vendor_app_url(self, url): 402*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('vendor appurl', url) 403*cfb92d14SAndroid Build Coastguard Worker 404*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 405*cfb92d14SAndroid Build Coastguard Worker # netdata 406*cfb92d14SAndroid Build Coastguard Worker 407*cfb92d14SAndroid Build Coastguard Worker def get_netdata(self, rloc16=None): 408*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('netdata show', rloc16) 409*cfb92d14SAndroid Build Coastguard Worker outputs = [line.strip() for line in outputs] 410*cfb92d14SAndroid Build Coastguard Worker routes_index = outputs.index('Routes:') 411*cfb92d14SAndroid Build Coastguard Worker services_index = outputs.index('Services:') 412*cfb92d14SAndroid Build Coastguard Worker if rloc16 is None: 413*cfb92d14SAndroid Build Coastguard Worker contexts_index = outputs.index('Contexts:') 414*cfb92d14SAndroid Build Coastguard Worker commissioning_index = outputs.index('Commissioning:') 415*cfb92d14SAndroid Build Coastguard Worker result = {} 416*cfb92d14SAndroid Build Coastguard Worker result['prefixes'] = outputs[1:routes_index] 417*cfb92d14SAndroid Build Coastguard Worker result['routes'] = outputs[routes_index + 1:services_index] 418*cfb92d14SAndroid Build Coastguard Worker if rloc16 is None: 419*cfb92d14SAndroid Build Coastguard Worker result['services'] = outputs[services_index + 1:contexts_index] 420*cfb92d14SAndroid Build Coastguard Worker result['contexts'] = outputs[contexts_index + 1:commissioning_index] 421*cfb92d14SAndroid Build Coastguard Worker result['commissioning'] = outputs[commissioning_index + 1:] 422*cfb92d14SAndroid Build Coastguard Worker else: 423*cfb92d14SAndroid Build Coastguard Worker result['services'] = outputs[services_index + 1:] 424*cfb92d14SAndroid Build Coastguard Worker 425*cfb92d14SAndroid Build Coastguard Worker return result 426*cfb92d14SAndroid Build Coastguard Worker 427*cfb92d14SAndroid Build Coastguard Worker def get_netdata_prefixes(self): 428*cfb92d14SAndroid Build Coastguard Worker return self.get_netdata()['prefixes'] 429*cfb92d14SAndroid Build Coastguard Worker 430*cfb92d14SAndroid Build Coastguard Worker def get_netdata_routes(self): 431*cfb92d14SAndroid Build Coastguard Worker return self.get_netdata()['routes'] 432*cfb92d14SAndroid Build Coastguard Worker 433*cfb92d14SAndroid Build Coastguard Worker def get_netdata_services(self): 434*cfb92d14SAndroid Build Coastguard Worker return self.get_netdata()['services'] 435*cfb92d14SAndroid Build Coastguard Worker 436*cfb92d14SAndroid Build Coastguard Worker def get_netdata_contexts(self): 437*cfb92d14SAndroid Build Coastguard Worker return self.get_netdata()['contexts'] 438*cfb92d14SAndroid Build Coastguard Worker 439*cfb92d14SAndroid Build Coastguard Worker def get_netdata_versions(self): 440*cfb92d14SAndroid Build Coastguard Worker leaderdata = Node.parse_list(self.cli('leaderdata')) 441*cfb92d14SAndroid Build Coastguard Worker return (int(leaderdata['Data Version']), int(leaderdata['Stable Data Version'])) 442*cfb92d14SAndroid Build Coastguard Worker 443*cfb92d14SAndroid Build Coastguard Worker def get_netdata_length(self): 444*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('netdata length') 445*cfb92d14SAndroid Build Coastguard Worker 446*cfb92d14SAndroid Build Coastguard Worker def add_prefix(self, prefix, flags=None, prf=None): 447*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('prefix add', prefix, flags, prf) 448*cfb92d14SAndroid Build Coastguard Worker 449*cfb92d14SAndroid Build Coastguard Worker def add_route(self, prefix, flags=None, prf=None): 450*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('route add', prefix, flags, prf) 451*cfb92d14SAndroid Build Coastguard Worker 452*cfb92d14SAndroid Build Coastguard Worker def remove_prefix(self, prefix): 453*cfb92d14SAndroid Build Coastguard Worker return self._cli_no_output('prefix remove', prefix) 454*cfb92d14SAndroid Build Coastguard Worker 455*cfb92d14SAndroid Build Coastguard Worker def register_netdata(self): 456*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('netdata register') 457*cfb92d14SAndroid Build Coastguard Worker 458*cfb92d14SAndroid Build Coastguard Worker def get_netdata_full(self): 459*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('netdata full') 460*cfb92d14SAndroid Build Coastguard Worker 461*cfb92d14SAndroid Build Coastguard Worker def reset_netdata_full(self): 462*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('netdata full reset') 463*cfb92d14SAndroid Build Coastguard Worker 464*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 465*cfb92d14SAndroid Build Coastguard Worker # ping and counters 466*cfb92d14SAndroid Build Coastguard Worker 467*cfb92d14SAndroid Build Coastguard Worker def ping(self, address, size=0, count=1, verify_success=True): 468*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('ping', address, size, count) 469*cfb92d14SAndroid Build Coastguard Worker m = re.match(r'(\d+) packets transmitted, (\d+) packets received.', outputs[-1].strip()) 470*cfb92d14SAndroid Build Coastguard Worker verify(m is not None) 471*cfb92d14SAndroid Build Coastguard Worker verify(int(m.group(1)) == count) 472*cfb92d14SAndroid Build Coastguard Worker if verify_success: 473*cfb92d14SAndroid Build Coastguard Worker verify(int(m.group(2)) == count) 474*cfb92d14SAndroid Build Coastguard Worker 475*cfb92d14SAndroid Build Coastguard Worker def get_mle_counter(self): 476*cfb92d14SAndroid Build Coastguard Worker return self.cli('counters mle') 477*cfb92d14SAndroid Build Coastguard Worker 478*cfb92d14SAndroid Build Coastguard Worker def get_ip_counters(self): 479*cfb92d14SAndroid Build Coastguard Worker return Node.parse_list(self.cli('counters ip')) 480*cfb92d14SAndroid Build Coastguard Worker 481*cfb92d14SAndroid Build Coastguard Worker def get_br_counter_unicast_outbound_packets(self): 482*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('counters br') 483*cfb92d14SAndroid Build Coastguard Worker for line in outputs: 484*cfb92d14SAndroid Build Coastguard Worker m = re.match(r'Outbound Unicast: Packets (\d+) Bytes (\d+)', line.strip()) 485*cfb92d14SAndroid Build Coastguard Worker if m is not None: 486*cfb92d14SAndroid Build Coastguard Worker counter = int(m.group(1)) 487*cfb92d14SAndroid Build Coastguard Worker break 488*cfb92d14SAndroid Build Coastguard Worker else: 489*cfb92d14SAndroid Build Coastguard Worker verify(False) 490*cfb92d14SAndroid Build Coastguard Worker return counter 491*cfb92d14SAndroid Build Coastguard Worker 492*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 493*cfb92d14SAndroid Build Coastguard Worker # Misc 494*cfb92d14SAndroid Build Coastguard Worker 495*cfb92d14SAndroid Build Coastguard Worker def get_mle_adv_imax(self): 496*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('mleadvimax') 497*cfb92d14SAndroid Build Coastguard Worker 498*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 499*cfb92d14SAndroid Build Coastguard Worker # Border Agent 500*cfb92d14SAndroid Build Coastguard Worker 501*cfb92d14SAndroid Build Coastguard Worker def ba_get_state(self): 502*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ba state') 503*cfb92d14SAndroid Build Coastguard Worker 504*cfb92d14SAndroid Build Coastguard Worker def ba_get_port(self): 505*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ba port') 506*cfb92d14SAndroid Build Coastguard Worker 507*cfb92d14SAndroid Build Coastguard Worker def ba_is_ephemeral_key_active(self): 508*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('ba ephemeralkey') 509*cfb92d14SAndroid Build Coastguard Worker 510*cfb92d14SAndroid Build Coastguard Worker def ba_set_ephemeral_key(self, keystring, timeout=None, port=None): 511*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ba ephemeralkey set', keystring, timeout, port) 512*cfb92d14SAndroid Build Coastguard Worker 513*cfb92d14SAndroid Build Coastguard Worker def ba_clear_ephemeral_key(self): 514*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('ba ephemeralkey clear') 515*cfb92d14SAndroid Build Coastguard Worker 516*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 517*cfb92d14SAndroid Build Coastguard Worker # UDP 518*cfb92d14SAndroid Build Coastguard Worker 519*cfb92d14SAndroid Build Coastguard Worker def udp_open(self): 520*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('udp open') 521*cfb92d14SAndroid Build Coastguard Worker 522*cfb92d14SAndroid Build Coastguard Worker def udp_close(self): 523*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('udp close') 524*cfb92d14SAndroid Build Coastguard Worker 525*cfb92d14SAndroid Build Coastguard Worker def udp_bind(self, address, port): 526*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('udp bind', address, port) 527*cfb92d14SAndroid Build Coastguard Worker 528*cfb92d14SAndroid Build Coastguard Worker def udp_send(self, address, port, text): 529*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('udp send', address, port, '-t', text) 530*cfb92d14SAndroid Build Coastguard Worker 531*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 532*cfb92d14SAndroid Build Coastguard Worker # multiradio 533*cfb92d14SAndroid Build Coastguard Worker 534*cfb92d14SAndroid Build Coastguard Worker def multiradio_get_radios(self): 535*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('multiradio') 536*cfb92d14SAndroid Build Coastguard Worker 537*cfb92d14SAndroid Build Coastguard Worker def multiradio_get_neighbor_list(self): 538*cfb92d14SAndroid Build Coastguard Worker return self.cli('multiradio neighbor list') 539*cfb92d14SAndroid Build Coastguard Worker 540*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 541*cfb92d14SAndroid Build Coastguard Worker # SRP client 542*cfb92d14SAndroid Build Coastguard Worker 543*cfb92d14SAndroid Build Coastguard Worker def srp_client_start(self, server_address, server_port): 544*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client start', server_address, server_port) 545*cfb92d14SAndroid Build Coastguard Worker 546*cfb92d14SAndroid Build Coastguard Worker def srp_client_stop(self): 547*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client stop') 548*cfb92d14SAndroid Build Coastguard Worker 549*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_state(self): 550*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client state', expected_outputs=['Enabled', 'Disabled']) 551*cfb92d14SAndroid Build Coastguard Worker 552*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_auto_start_mode(self): 553*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client autostart', expected_outputs=['Enabled', 'Disabled']) 554*cfb92d14SAndroid Build Coastguard Worker 555*cfb92d14SAndroid Build Coastguard Worker def srp_client_enable_auto_start_mode(self): 556*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client autostart enable') 557*cfb92d14SAndroid Build Coastguard Worker 558*cfb92d14SAndroid Build Coastguard Worker def srp_client_disable_auto_start_mode(self): 559*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client autostart disable') 560*cfb92d14SAndroid Build Coastguard Worker 561*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_server_address(self): 562*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client server address') 563*cfb92d14SAndroid Build Coastguard Worker 564*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_server_port(self): 565*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client server port') 566*cfb92d14SAndroid Build Coastguard Worker 567*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_host_state(self): 568*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client host state') 569*cfb92d14SAndroid Build Coastguard Worker 570*cfb92d14SAndroid Build Coastguard Worker def srp_client_set_host_name(self, name): 571*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client host name', name) 572*cfb92d14SAndroid Build Coastguard Worker 573*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_host_name(self): 574*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp client host name') 575*cfb92d14SAndroid Build Coastguard Worker 576*cfb92d14SAndroid Build Coastguard Worker def srp_client_remove_host(self, remove_key=False, send_unreg_to_server=False): 577*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client host remove', int(remove_key), int(send_unreg_to_server)) 578*cfb92d14SAndroid Build Coastguard Worker 579*cfb92d14SAndroid Build Coastguard Worker def srp_client_clear_host(self): 580*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client host clear') 581*cfb92d14SAndroid Build Coastguard Worker 582*cfb92d14SAndroid Build Coastguard Worker def srp_client_enable_auto_host_address(self): 583*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client host address auto') 584*cfb92d14SAndroid Build Coastguard Worker 585*cfb92d14SAndroid Build Coastguard Worker def srp_client_set_host_address(self, *addrs): 586*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client host address', *addrs) 587*cfb92d14SAndroid Build Coastguard Worker 588*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_host_address(self): 589*cfb92d14SAndroid Build Coastguard Worker return self.cli('srp client host address') 590*cfb92d14SAndroid Build Coastguard Worker 591*cfb92d14SAndroid Build Coastguard Worker def srp_client_add_service(self, 592*cfb92d14SAndroid Build Coastguard Worker instance_name, 593*cfb92d14SAndroid Build Coastguard Worker service_name, 594*cfb92d14SAndroid Build Coastguard Worker port, 595*cfb92d14SAndroid Build Coastguard Worker priority=0, 596*cfb92d14SAndroid Build Coastguard Worker weight=0, 597*cfb92d14SAndroid Build Coastguard Worker txt_entries=[], 598*cfb92d14SAndroid Build Coastguard Worker lease=0, 599*cfb92d14SAndroid Build Coastguard Worker key_lease=0): 600*cfb92d14SAndroid Build Coastguard Worker txt_record = "".join(self._encode_txt_entry(entry) for entry in txt_entries) 601*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client service add', instance_name, service_name, port, priority, weight, txt_record, 602*cfb92d14SAndroid Build Coastguard Worker lease, key_lease) 603*cfb92d14SAndroid Build Coastguard Worker 604*cfb92d14SAndroid Build Coastguard Worker def srp_client_remove_service(self, instance_name, service_name): 605*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client service remove', instance_name, service_name) 606*cfb92d14SAndroid Build Coastguard Worker 607*cfb92d14SAndroid Build Coastguard Worker def srp_client_clear_service(self, instance_name, service_name): 608*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp client service clear', instance_name, service_name) 609*cfb92d14SAndroid Build Coastguard Worker 610*cfb92d14SAndroid Build Coastguard Worker def srp_client_get_services(self): 611*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('srp client service') 612*cfb92d14SAndroid Build Coastguard Worker return [self._parse_srp_client_service(line) for line in outputs] 613*cfb92d14SAndroid Build Coastguard Worker 614*cfb92d14SAndroid Build Coastguard Worker def _encode_txt_entry(self, entry): 615*cfb92d14SAndroid Build Coastguard Worker """Encodes the TXT entry to the DNS-SD TXT record format as a HEX string. 616*cfb92d14SAndroid Build Coastguard Worker 617*cfb92d14SAndroid Build Coastguard Worker Example usage: 618*cfb92d14SAndroid Build Coastguard Worker self._encode_txt_entries(['abc']) -> '03616263' 619*cfb92d14SAndroid Build Coastguard Worker self._encode_txt_entries(['def=']) -> '046465663d' 620*cfb92d14SAndroid Build Coastguard Worker self._encode_txt_entries(['xyz=XYZ']) -> '0778797a3d58595a' 621*cfb92d14SAndroid Build Coastguard Worker """ 622*cfb92d14SAndroid Build Coastguard Worker return '{:02x}'.format(len(entry)) + "".join("{:02x}".format(ord(c)) for c in entry) 623*cfb92d14SAndroid Build Coastguard Worker 624*cfb92d14SAndroid Build Coastguard Worker def _parse_srp_client_service(self, line): 625*cfb92d14SAndroid Build Coastguard Worker """Parse one line of srp service list into a dictionary which 626*cfb92d14SAndroid Build Coastguard Worker maps string keys to string values. 627*cfb92d14SAndroid Build Coastguard Worker 628*cfb92d14SAndroid Build Coastguard Worker Example output for input 629*cfb92d14SAndroid Build Coastguard Worker 'instance:\"%s\", name:\"%s\", state:%s, port:%d, priority:%d, weight:%d"' 630*cfb92d14SAndroid Build Coastguard Worker { 631*cfb92d14SAndroid Build Coastguard Worker 'instance': 'my-service', 632*cfb92d14SAndroid Build Coastguard Worker 'name': '_ipps._udp', 633*cfb92d14SAndroid Build Coastguard Worker 'state': 'ToAdd', 634*cfb92d14SAndroid Build Coastguard Worker 'port': '12345', 635*cfb92d14SAndroid Build Coastguard Worker 'priority': '0', 636*cfb92d14SAndroid Build Coastguard Worker 'weight': '0' 637*cfb92d14SAndroid Build Coastguard Worker } 638*cfb92d14SAndroid Build Coastguard Worker 639*cfb92d14SAndroid Build Coastguard Worker Note that value of 'port', 'priority' and 'weight' are represented 640*cfb92d14SAndroid Build Coastguard Worker as strings but not integers. 641*cfb92d14SAndroid Build Coastguard Worker """ 642*cfb92d14SAndroid Build Coastguard Worker key_values = [word.strip().split(':') for word in line.split(', ')] 643*cfb92d14SAndroid Build Coastguard Worker return {key_value[0].strip(): key_value[1].strip('"') for key_value in key_values} 644*cfb92d14SAndroid Build Coastguard Worker 645*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 646*cfb92d14SAndroid Build Coastguard Worker # SRP server 647*cfb92d14SAndroid Build Coastguard Worker 648*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_state(self): 649*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp server state', expected_outputs=['disabled', 'running', 'stopped']) 650*cfb92d14SAndroid Build Coastguard Worker 651*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_addr_mode(self): 652*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp server addrmode', expected_outputs=['unicast', 'anycast']) 653*cfb92d14SAndroid Build Coastguard Worker 654*cfb92d14SAndroid Build Coastguard Worker def srp_server_set_addr_mode(self, mode): 655*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server addrmode', mode) 656*cfb92d14SAndroid Build Coastguard Worker 657*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_anycast_seq_num(self): 658*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('srp server seqnum') 659*cfb92d14SAndroid Build Coastguard Worker 660*cfb92d14SAndroid Build Coastguard Worker def srp_server_set_anycast_seq_num(self, seqnum): 661*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server seqnum', seqnum) 662*cfb92d14SAndroid Build Coastguard Worker 663*cfb92d14SAndroid Build Coastguard Worker def srp_server_enable(self): 664*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server enable') 665*cfb92d14SAndroid Build Coastguard Worker 666*cfb92d14SAndroid Build Coastguard Worker def srp_server_disable(self): 667*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server disable') 668*cfb92d14SAndroid Build Coastguard Worker 669*cfb92d14SAndroid Build Coastguard Worker def srp_server_auto_enable(self): 670*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server auto enable') 671*cfb92d14SAndroid Build Coastguard Worker 672*cfb92d14SAndroid Build Coastguard Worker def srp_server_auto_disable(self): 673*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server auto disable') 674*cfb92d14SAndroid Build Coastguard Worker 675*cfb92d14SAndroid Build Coastguard Worker def srp_server_set_lease(self, min_lease, max_lease, min_key_lease, max_key_lease): 676*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('srp server lease', min_lease, max_lease, min_key_lease, max_key_lease) 677*cfb92d14SAndroid Build Coastguard Worker 678*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_hosts(self): 679*cfb92d14SAndroid Build Coastguard Worker """Returns the host list on the SRP server as a list of property 680*cfb92d14SAndroid Build Coastguard Worker dictionary. 681*cfb92d14SAndroid Build Coastguard Worker 682*cfb92d14SAndroid Build Coastguard Worker Example output: 683*cfb92d14SAndroid Build Coastguard Worker [{ 684*cfb92d14SAndroid Build Coastguard Worker 'fullname': 'my-host.default.service.arpa.', 685*cfb92d14SAndroid Build Coastguard Worker 'name': 'my-host', 686*cfb92d14SAndroid Build Coastguard Worker 'deleted': 'false', 687*cfb92d14SAndroid Build Coastguard Worker 'addresses': ['2001::1', '2001::2'] 688*cfb92d14SAndroid Build Coastguard Worker }] 689*cfb92d14SAndroid Build Coastguard Worker """ 690*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('srp server host') 691*cfb92d14SAndroid Build Coastguard Worker host_list = [] 692*cfb92d14SAndroid Build Coastguard Worker while outputs: 693*cfb92d14SAndroid Build Coastguard Worker host = {} 694*cfb92d14SAndroid Build Coastguard Worker host['fullname'] = outputs.pop(0).strip() 695*cfb92d14SAndroid Build Coastguard Worker host['name'] = host['fullname'].split('.')[0] 696*cfb92d14SAndroid Build Coastguard Worker host['deleted'] = outputs.pop(0).strip().split(':')[1].strip() 697*cfb92d14SAndroid Build Coastguard Worker if host['deleted'] == 'true': 698*cfb92d14SAndroid Build Coastguard Worker host_list.append(host) 699*cfb92d14SAndroid Build Coastguard Worker continue 700*cfb92d14SAndroid Build Coastguard Worker addresses = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',') 701*cfb92d14SAndroid Build Coastguard Worker map(str.strip, addresses) 702*cfb92d14SAndroid Build Coastguard Worker host['addresses'] = [addr for addr in addresses if addr] 703*cfb92d14SAndroid Build Coastguard Worker host_list.append(host) 704*cfb92d14SAndroid Build Coastguard Worker return host_list 705*cfb92d14SAndroid Build Coastguard Worker 706*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_host(self, host_name): 707*cfb92d14SAndroid Build Coastguard Worker """Returns host on the SRP server that matches given host name. 708*cfb92d14SAndroid Build Coastguard Worker 709*cfb92d14SAndroid Build Coastguard Worker Example usage: 710*cfb92d14SAndroid Build Coastguard Worker self.srp_server_get_host("my-host") 711*cfb92d14SAndroid Build Coastguard Worker """ 712*cfb92d14SAndroid Build Coastguard Worker for host in self.srp_server_get_hosts(): 713*cfb92d14SAndroid Build Coastguard Worker if host_name == host['name']: 714*cfb92d14SAndroid Build Coastguard Worker return host 715*cfb92d14SAndroid Build Coastguard Worker 716*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_services(self): 717*cfb92d14SAndroid Build Coastguard Worker """Returns the service list on the SRP server as a list of property 718*cfb92d14SAndroid Build Coastguard Worker dictionary. 719*cfb92d14SAndroid Build Coastguard Worker 720*cfb92d14SAndroid Build Coastguard Worker Example output: 721*cfb92d14SAndroid Build Coastguard Worker [{ 722*cfb92d14SAndroid Build Coastguard Worker 'fullname': 'my-service._ipps._tcp.default.service.arpa.', 723*cfb92d14SAndroid Build Coastguard Worker 'instance': 'my-service', 724*cfb92d14SAndroid Build Coastguard Worker 'name': '_ipps._tcp', 725*cfb92d14SAndroid Build Coastguard Worker 'deleted': 'false', 726*cfb92d14SAndroid Build Coastguard Worker 'port': '12345', 727*cfb92d14SAndroid Build Coastguard Worker 'priority': '0', 728*cfb92d14SAndroid Build Coastguard Worker 'weight': '0', 729*cfb92d14SAndroid Build Coastguard Worker 'ttl': '7200', 730*cfb92d14SAndroid Build Coastguard Worker 'lease': '7200', 731*cfb92d14SAndroid Build Coastguard Worker 'key-lease', '1209600', 732*cfb92d14SAndroid Build Coastguard Worker 'TXT': ['abc=010203'], 733*cfb92d14SAndroid Build Coastguard Worker 'host_fullname': 'my-host.default.service.arpa.', 734*cfb92d14SAndroid Build Coastguard Worker 'host': 'my-host', 735*cfb92d14SAndroid Build Coastguard Worker 'addresses': ['2001::1', '2001::2'] 736*cfb92d14SAndroid Build Coastguard Worker }] 737*cfb92d14SAndroid Build Coastguard Worker 738*cfb92d14SAndroid Build Coastguard Worker Note that the TXT data is output as a HEX string. 739*cfb92d14SAndroid Build Coastguard Worker """ 740*cfb92d14SAndroid Build Coastguard Worker outputs = self.cli('srp server service') 741*cfb92d14SAndroid Build Coastguard Worker service_list = [] 742*cfb92d14SAndroid Build Coastguard Worker while outputs: 743*cfb92d14SAndroid Build Coastguard Worker service = {} 744*cfb92d14SAndroid Build Coastguard Worker service['fullname'] = outputs.pop(0).strip() 745*cfb92d14SAndroid Build Coastguard Worker name_labels = service['fullname'].split('.') 746*cfb92d14SAndroid Build Coastguard Worker service['instance'] = name_labels[0] 747*cfb92d14SAndroid Build Coastguard Worker service['name'] = '.'.join(name_labels[1:3]) 748*cfb92d14SAndroid Build Coastguard Worker service['deleted'] = outputs.pop(0).strip().split(':')[1].strip() 749*cfb92d14SAndroid Build Coastguard Worker if service['deleted'] == 'true': 750*cfb92d14SAndroid Build Coastguard Worker service_list.append(service) 751*cfb92d14SAndroid Build Coastguard Worker continue 752*cfb92d14SAndroid Build Coastguard Worker # 'subtypes', port', 'priority', 'weight', 'ttl', 'lease', 'key-lease' 753*cfb92d14SAndroid Build Coastguard Worker for i in range(0, 7): 754*cfb92d14SAndroid Build Coastguard Worker key_value = outputs.pop(0).strip().split(':') 755*cfb92d14SAndroid Build Coastguard Worker service[key_value[0].strip()] = key_value[1].strip() 756*cfb92d14SAndroid Build Coastguard Worker txt_entries = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',') 757*cfb92d14SAndroid Build Coastguard Worker txt_entries = map(str.strip, txt_entries) 758*cfb92d14SAndroid Build Coastguard Worker service['TXT'] = [txt for txt in txt_entries if txt] 759*cfb92d14SAndroid Build Coastguard Worker service['host_fullname'] = outputs.pop(0).strip().split(':')[1].strip() 760*cfb92d14SAndroid Build Coastguard Worker service['host'] = service['host_fullname'].split('.')[0] 761*cfb92d14SAndroid Build Coastguard Worker addresses = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',') 762*cfb92d14SAndroid Build Coastguard Worker addresses = map(str.strip, addresses) 763*cfb92d14SAndroid Build Coastguard Worker service['addresses'] = [addr for addr in addresses if addr] 764*cfb92d14SAndroid Build Coastguard Worker service_list.append(service) 765*cfb92d14SAndroid Build Coastguard Worker return service_list 766*cfb92d14SAndroid Build Coastguard Worker 767*cfb92d14SAndroid Build Coastguard Worker def srp_server_get_service(self, instance_name, service_name): 768*cfb92d14SAndroid Build Coastguard Worker """Returns service on the SRP server that matches given instance 769*cfb92d14SAndroid Build Coastguard Worker name and service name. 770*cfb92d14SAndroid Build Coastguard Worker 771*cfb92d14SAndroid Build Coastguard Worker Example usage: 772*cfb92d14SAndroid Build Coastguard Worker self.srp_server_get_service("my-service", "_ipps._tcp") 773*cfb92d14SAndroid Build Coastguard Worker """ 774*cfb92d14SAndroid Build Coastguard Worker for service in self.srp_server_get_services(): 775*cfb92d14SAndroid Build Coastguard Worker if (instance_name == service['instance'] and service_name == service['name']): 776*cfb92d14SAndroid Build Coastguard Worker return service 777*cfb92d14SAndroid Build Coastguard Worker 778*cfb92d14SAndroid Build Coastguard Worker #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 779*cfb92d14SAndroid Build Coastguard Worker # br 780*cfb92d14SAndroid Build Coastguard Worker 781*cfb92d14SAndroid Build Coastguard Worker def br_init(self, if_inex, is_running): 782*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br init', if_inex, is_running) 783*cfb92d14SAndroid Build Coastguard Worker 784*cfb92d14SAndroid Build Coastguard Worker def br_enable(self): 785*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br enable') 786*cfb92d14SAndroid Build Coastguard Worker 787*cfb92d14SAndroid Build Coastguard Worker def br_disable(self): 788*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br disable') 789*cfb92d14SAndroid Build Coastguard Worker 790*cfb92d14SAndroid Build Coastguard Worker def br_get_state(self): 791*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br state') 792*cfb92d14SAndroid Build Coastguard Worker 793*cfb92d14SAndroid Build Coastguard Worker def br_get_favored_omrprefix(self): 794*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br omrprefix favored') 795*cfb92d14SAndroid Build Coastguard Worker 796*cfb92d14SAndroid Build Coastguard Worker def br_get_local_omrprefix(self): 797*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br omrprefix local') 798*cfb92d14SAndroid Build Coastguard Worker 799*cfb92d14SAndroid Build Coastguard Worker def br_get_favored_onlinkprefix(self): 800*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br onlinkprefix favored') 801*cfb92d14SAndroid Build Coastguard Worker 802*cfb92d14SAndroid Build Coastguard Worker def br_get_local_onlinkprefix(self): 803*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br onlinkprefix local') 804*cfb92d14SAndroid Build Coastguard Worker 805*cfb92d14SAndroid Build Coastguard Worker def br_set_test_local_onlinkprefix(self, prefix): 806*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br onlinkprefix test', prefix) 807*cfb92d14SAndroid Build Coastguard Worker 808*cfb92d14SAndroid Build Coastguard Worker def br_get_routeprf(self): 809*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br routeprf') 810*cfb92d14SAndroid Build Coastguard Worker 811*cfb92d14SAndroid Build Coastguard Worker def br_set_routeprf(self, prf): 812*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br routeprf', prf) 813*cfb92d14SAndroid Build Coastguard Worker 814*cfb92d14SAndroid Build Coastguard Worker def br_clear_routeprf(self): 815*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('br routeprf clear') 816*cfb92d14SAndroid Build Coastguard Worker 817*cfb92d14SAndroid Build Coastguard Worker def br_get_routers(self): 818*cfb92d14SAndroid Build Coastguard Worker return self.cli('br routers') 819*cfb92d14SAndroid Build Coastguard Worker 820*cfb92d14SAndroid Build Coastguard Worker def br_get_peer_brs(self): 821*cfb92d14SAndroid Build Coastguard Worker return self.cli('br peers') 822*cfb92d14SAndroid Build Coastguard Worker 823*cfb92d14SAndroid Build Coastguard Worker def br_count_peers(self): 824*cfb92d14SAndroid Build Coastguard Worker return self._cli_single_output('br peers count') 825*cfb92d14SAndroid Build Coastguard Worker 826*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 827*cfb92d14SAndroid Build Coastguard Worker # Helper methods 828*cfb92d14SAndroid Build Coastguard Worker 829*cfb92d14SAndroid Build Coastguard Worker def form(self, network_name=None, network_key=None, channel=None, panid=0x1234, xpanid=None): 830*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset init new') 831*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset panid', panid) 832*cfb92d14SAndroid Build Coastguard Worker if network_name is not None: 833*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset networkname', network_name) 834*cfb92d14SAndroid Build Coastguard Worker if network_key is not None: 835*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset networkkey', network_key) 836*cfb92d14SAndroid Build Coastguard Worker if channel is not None: 837*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset channel', channel) 838*cfb92d14SAndroid Build Coastguard Worker if xpanid is not None: 839*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset extpanid', xpanid) 840*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset commit active') 841*cfb92d14SAndroid Build Coastguard Worker self.set_mode('rdn') 842*cfb92d14SAndroid Build Coastguard Worker self.interface_up() 843*cfb92d14SAndroid Build Coastguard Worker self.thread_start() 844*cfb92d14SAndroid Build Coastguard Worker verify_within(_check_node_is_leader, self._WAIT_TIME, arg=self) 845*cfb92d14SAndroid Build Coastguard Worker 846*cfb92d14SAndroid Build Coastguard Worker def join(self, node, type=JOIN_TYPE_ROUTER): 847*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset clear') 848*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset networkname', node.get_network_name()) 849*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset networkkey', node.get_network_key()) 850*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset channel', node.get_channel()) 851*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset panid', node.get_panid()) 852*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('dataset commit active') 853*cfb92d14SAndroid Build Coastguard Worker if type == JOIN_TYPE_END_DEVICE: 854*cfb92d14SAndroid Build Coastguard Worker self.set_mode('rn') 855*cfb92d14SAndroid Build Coastguard Worker elif type == JOIN_TYPE_SLEEPY_END_DEVICE: 856*cfb92d14SAndroid Build Coastguard Worker self.set_mode('-') 857*cfb92d14SAndroid Build Coastguard Worker elif type == JOIN_TYPE_REED: 858*cfb92d14SAndroid Build Coastguard Worker self.set_mode('rdn') 859*cfb92d14SAndroid Build Coastguard Worker self.set_router_eligible('disable') 860*cfb92d14SAndroid Build Coastguard Worker else: 861*cfb92d14SAndroid Build Coastguard Worker self.set_mode('rdn') 862*cfb92d14SAndroid Build Coastguard Worker self.set_router_selection_jitter(1) 863*cfb92d14SAndroid Build Coastguard Worker self.interface_up() 864*cfb92d14SAndroid Build Coastguard Worker self.thread_start() 865*cfb92d14SAndroid Build Coastguard Worker if type == JOIN_TYPE_ROUTER: 866*cfb92d14SAndroid Build Coastguard Worker verify_within(_check_node_is_router, self._WAIT_TIME, arg=self) 867*cfb92d14SAndroid Build Coastguard Worker else: 868*cfb92d14SAndroid Build Coastguard Worker verify_within(_check_node_is_child, self._WAIT_TIME, arg=self) 869*cfb92d14SAndroid Build Coastguard Worker 870*cfb92d14SAndroid Build Coastguard Worker def allowlist_node(self, node): 871*cfb92d14SAndroid Build Coastguard Worker """Adds a given node to the allowlist of `self` and enables allowlisting on `self`""" 872*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('macfilter addr add', node.get_ext_addr()) 873*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('macfilter addr allowlist') 874*cfb92d14SAndroid Build Coastguard Worker 875*cfb92d14SAndroid Build Coastguard Worker def un_allowlist_node(self, node): 876*cfb92d14SAndroid Build Coastguard Worker """Removes a given node (of node `Node) from the allowlist""" 877*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('macfilter addr remove', node.get_ext_addr()) 878*cfb92d14SAndroid Build Coastguard Worker 879*cfb92d14SAndroid Build Coastguard Worker def set_macfilter_lqi_to_node(self, node, lqi): 880*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('macfilter rss add-lqi', node.get_ext_addr(), lqi) 881*cfb92d14SAndroid Build Coastguard Worker 882*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 883*cfb92d14SAndroid Build Coastguard Worker # Radio nodeidfilter 884*cfb92d14SAndroid Build Coastguard Worker 885*cfb92d14SAndroid Build Coastguard Worker def nodeidfilter_clear(self, node): 886*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('nodeidfilter clear') 887*cfb92d14SAndroid Build Coastguard Worker 888*cfb92d14SAndroid Build Coastguard Worker def nodeidfilter_allow(self, node): 889*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('nodeidfilter allow', node.index) 890*cfb92d14SAndroid Build Coastguard Worker 891*cfb92d14SAndroid Build Coastguard Worker def nodeidfilter_deny(self, node): 892*cfb92d14SAndroid Build Coastguard Worker self._cli_no_output('nodeidfilter deny', node.index) 893*cfb92d14SAndroid Build Coastguard Worker 894*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 895*cfb92d14SAndroid Build Coastguard Worker # Parsing helpers 896*cfb92d14SAndroid Build Coastguard Worker 897*cfb92d14SAndroid Build Coastguard Worker @classmethod 898*cfb92d14SAndroid Build Coastguard Worker def parse_table(cls, table_lines): 899*cfb92d14SAndroid Build Coastguard Worker verify(len(table_lines) >= 2) 900*cfb92d14SAndroid Build Coastguard Worker headers = cls.split_table_row(table_lines[0]) 901*cfb92d14SAndroid Build Coastguard Worker info = [] 902*cfb92d14SAndroid Build Coastguard Worker for row in table_lines[2:]: 903*cfb92d14SAndroid Build Coastguard Worker if row.strip() == '': 904*cfb92d14SAndroid Build Coastguard Worker continue 905*cfb92d14SAndroid Build Coastguard Worker fields = cls.split_table_row(row) 906*cfb92d14SAndroid Build Coastguard Worker verify(len(fields) == len(headers)) 907*cfb92d14SAndroid Build Coastguard Worker info.append({headers[i]: fields[i] for i in range(len(fields))}) 908*cfb92d14SAndroid Build Coastguard Worker return info 909*cfb92d14SAndroid Build Coastguard Worker 910*cfb92d14SAndroid Build Coastguard Worker @classmethod 911*cfb92d14SAndroid Build Coastguard Worker def split_table_row(cls, row): 912*cfb92d14SAndroid Build Coastguard Worker return [field.strip() for field in row.strip().split('|')[1:-1]] 913*cfb92d14SAndroid Build Coastguard Worker 914*cfb92d14SAndroid Build Coastguard Worker @classmethod 915*cfb92d14SAndroid Build Coastguard Worker def parse_list(cls, list_lines): 916*cfb92d14SAndroid Build Coastguard Worker result = {} 917*cfb92d14SAndroid Build Coastguard Worker for line in list_lines: 918*cfb92d14SAndroid Build Coastguard Worker fields = line.split(':', 1) 919*cfb92d14SAndroid Build Coastguard Worker result[fields[0].strip()] = fields[1].strip() 920*cfb92d14SAndroid Build Coastguard Worker return result 921*cfb92d14SAndroid Build Coastguard Worker 922*cfb92d14SAndroid Build Coastguard Worker @classmethod 923*cfb92d14SAndroid Build Coastguard Worker def parse_multiradio_neighbor_entry(cls, line): 924*cfb92d14SAndroid Build Coastguard Worker # Example: "ExtAddr:42aa94ad67229f14, RLOC16:0x9400, Radios:[15.4(245), TREL(255)]" 925*cfb92d14SAndroid Build Coastguard Worker result = {} 926*cfb92d14SAndroid Build Coastguard Worker for field in line.split(', ', 2): 927*cfb92d14SAndroid Build Coastguard Worker key_value = field.split(':') 928*cfb92d14SAndroid Build Coastguard Worker result[key_value[0]] = key_value[1] 929*cfb92d14SAndroid Build Coastguard Worker radios = {} 930*cfb92d14SAndroid Build Coastguard Worker for item in result['Radios'][1:-1].split(','): 931*cfb92d14SAndroid Build Coastguard Worker name, prf = item.strip().split('(') 932*cfb92d14SAndroid Build Coastguard Worker verify(prf.endswith(')')) 933*cfb92d14SAndroid Build Coastguard Worker radios[name] = int(prf[:-1]) 934*cfb92d14SAndroid Build Coastguard Worker result['Radios'] = radios 935*cfb92d14SAndroid Build Coastguard Worker return result 936*cfb92d14SAndroid Build Coastguard Worker 937*cfb92d14SAndroid Build Coastguard Worker # ------------------------------------------------------------------------------------------------------------------ 938*cfb92d14SAndroid Build Coastguard Worker # class methods 939*cfb92d14SAndroid Build Coastguard Worker 940*cfb92d14SAndroid Build Coastguard Worker @classmethod 941*cfb92d14SAndroid Build Coastguard Worker def finalize_all_nodes(cls): 942*cfb92d14SAndroid Build Coastguard Worker """Finalizes all previously created `Node` instances (stops the CLI process)""" 943*cfb92d14SAndroid Build Coastguard Worker for node in Node._all_nodes: 944*cfb92d14SAndroid Build Coastguard Worker node._finalize() 945*cfb92d14SAndroid Build Coastguard Worker 946*cfb92d14SAndroid Build Coastguard Worker @classmethod 947*cfb92d14SAndroid Build Coastguard Worker def set_time_speedup_factor(cls, factor): 948*cfb92d14SAndroid Build Coastguard Worker """Sets up the time speed up factor - should be set before creating any `Node` objects""" 949*cfb92d14SAndroid Build Coastguard Worker if len(Node._all_nodes) != 0: 950*cfb92d14SAndroid Build Coastguard Worker raise Node._NodeError('set_time_speedup_factor() cannot be called after creating a `Node`') 951*cfb92d14SAndroid Build Coastguard Worker Node._SPEED_UP_FACTOR = factor 952*cfb92d14SAndroid Build Coastguard Worker 953*cfb92d14SAndroid Build Coastguard Worker 954*cfb92d14SAndroid Build Coastguard Workerdef _check_node_is_leader(node): 955*cfb92d14SAndroid Build Coastguard Worker verify(node.get_state() == 'leader') 956*cfb92d14SAndroid Build Coastguard Worker 957*cfb92d14SAndroid Build Coastguard Worker 958*cfb92d14SAndroid Build Coastguard Workerdef _check_node_is_router(node): 959*cfb92d14SAndroid Build Coastguard Worker verify(node.get_state() == 'router') 960*cfb92d14SAndroid Build Coastguard Worker 961*cfb92d14SAndroid Build Coastguard Worker 962*cfb92d14SAndroid Build Coastguard Workerdef _check_node_is_child(node): 963*cfb92d14SAndroid Build Coastguard Worker verify(node.get_state() == 'child') 964*cfb92d14SAndroid Build Coastguard Worker 965*cfb92d14SAndroid Build Coastguard Worker 966*cfb92d14SAndroid Build Coastguard Worker# ---------------------------------------------------------------------------------------------------------------------- 967*cfb92d14SAndroid Build Coastguard Worker 968*cfb92d14SAndroid Build Coastguard Worker 969*cfb92d14SAndroid Build Coastguard Workerclass VerifyError(Exception): 970*cfb92d14SAndroid Build Coastguard Worker pass 971*cfb92d14SAndroid Build Coastguard Worker 972*cfb92d14SAndroid Build Coastguard Worker 973*cfb92d14SAndroid Build Coastguard Worker_is_in_verify_within = False 974*cfb92d14SAndroid Build Coastguard Worker 975*cfb92d14SAndroid Build Coastguard Worker 976*cfb92d14SAndroid Build Coastguard Workerdef verify(condition): 977*cfb92d14SAndroid Build Coastguard Worker """Verifies that a `condition` is true, otherwise raises a VerifyError""" 978*cfb92d14SAndroid Build Coastguard Worker global _is_in_verify_within 979*cfb92d14SAndroid Build Coastguard Worker if not condition: 980*cfb92d14SAndroid Build Coastguard Worker calling_frame = inspect.currentframe().f_back 981*cfb92d14SAndroid Build Coastguard Worker error_message = 'verify() failed at line {} in "{}"'.format(calling_frame.f_lineno, 982*cfb92d14SAndroid Build Coastguard Worker calling_frame.f_code.co_filename) 983*cfb92d14SAndroid Build Coastguard Worker if not _is_in_verify_within: 984*cfb92d14SAndroid Build Coastguard Worker print(error_message) 985*cfb92d14SAndroid Build Coastguard Worker raise VerifyError(error_message) 986*cfb92d14SAndroid Build Coastguard Worker 987*cfb92d14SAndroid Build Coastguard Worker 988*cfb92d14SAndroid Build Coastguard Workerdef verify_within(condition_checker_func, wait_time, arg=None, delay_time=0.1): 989*cfb92d14SAndroid Build Coastguard Worker """Verifies that a given function `condition_checker_func` passes successfully within a given wait timeout. 990*cfb92d14SAndroid Build Coastguard Worker `wait_time` is maximum time waiting for condition_checker to pass (in seconds). 991*cfb92d14SAndroid Build Coastguard Worker `arg` is optional parameter and if it s not None, will be passed to `condition_checker_func()` 992*cfb92d14SAndroid Build Coastguard Worker `delay_time` specifies a delay interval added between failed attempts (in seconds). 993*cfb92d14SAndroid Build Coastguard Worker """ 994*cfb92d14SAndroid Build Coastguard Worker global _is_in_verify_within 995*cfb92d14SAndroid Build Coastguard Worker start_time = time.time() 996*cfb92d14SAndroid Build Coastguard Worker old_is_in_verify_within = _is_in_verify_within 997*cfb92d14SAndroid Build Coastguard Worker _is_in_verify_within = True 998*cfb92d14SAndroid Build Coastguard Worker while True: 999*cfb92d14SAndroid Build Coastguard Worker try: 1000*cfb92d14SAndroid Build Coastguard Worker if arg is None: 1001*cfb92d14SAndroid Build Coastguard Worker condition_checker_func() 1002*cfb92d14SAndroid Build Coastguard Worker else: 1003*cfb92d14SAndroid Build Coastguard Worker condition_checker_func(arg) 1004*cfb92d14SAndroid Build Coastguard Worker except VerifyError as e: 1005*cfb92d14SAndroid Build Coastguard Worker if time.time() - start_time > wait_time: 1006*cfb92d14SAndroid Build Coastguard Worker print('Took too long to pass the condition ({}>{} sec)'.format(time.time() - start_time, wait_time)) 1007*cfb92d14SAndroid Build Coastguard Worker if hasattr(e, 'message'): 1008*cfb92d14SAndroid Build Coastguard Worker print(e.message) 1009*cfb92d14SAndroid Build Coastguard Worker raise e 1010*cfb92d14SAndroid Build Coastguard Worker except BaseException: 1011*cfb92d14SAndroid Build Coastguard Worker raise 1012*cfb92d14SAndroid Build Coastguard Worker else: 1013*cfb92d14SAndroid Build Coastguard Worker break 1014*cfb92d14SAndroid Build Coastguard Worker if delay_time != 0: 1015*cfb92d14SAndroid Build Coastguard Worker time.sleep(delay_time) 1016*cfb92d14SAndroid Build Coastguard Worker _is_in_verify_within = old_is_in_verify_within 1017