From 075d23370a0f3aa8f30c5e6c55e6f08dcb8bab60 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 10 May 2017 15:05:51 -0700 Subject: [PATCH] spinel-cli is now maintained in a separate repo. (#1742) --- configure.ac | 2 - tools/Makefile.am | 2 - tools/spinel-cli/MANIFEST.in | 2 - tools/spinel-cli/Makefile.am | 64 - tools/spinel-cli/README.md | 364 ---- tools/spinel-cli/SNIFFER.md | 108 -- tools/spinel-cli/setup.py | 62 - tools/spinel-cli/sniffer.py | 154 -- tools/spinel-cli/spinel-cli.py | 2108 ----------------------- tools/spinel-cli/spinel/Makefile.am | 51 - tools/spinel-cli/spinel/__init__.py | 27 - tools/spinel-cli/spinel/codec.py | 1121 ------------ tools/spinel-cli/spinel/config.py | 113 -- tools/spinel-cli/spinel/const.py | 417 ----- tools/spinel-cli/spinel/hdlc.py | 165 -- tools/spinel-cli/spinel/pcap.py | 63 - tools/spinel-cli/spinel/stream.py | 174 -- tools/spinel-cli/spinel/test_codec.py | 96 -- tools/spinel-cli/spinel/test_hdlc.py | 58 - tools/spinel-cli/spinel/test_sniffer.py | 66 - tools/spinel-cli/spinel/test_stream.py | 85 - tools/spinel-cli/spinel/tests.py | 32 - tools/spinel-cli/spinel/tun.py | 159 -- tools/spinel-cli/spinel/util.py | 48 - tools/spinel-cli/test_spinel.py | 55 - 25 files changed, 5596 deletions(-) delete mode 100644 tools/spinel-cli/MANIFEST.in delete mode 100644 tools/spinel-cli/Makefile.am delete mode 100644 tools/spinel-cli/README.md delete mode 100644 tools/spinel-cli/SNIFFER.md delete mode 100644 tools/spinel-cli/setup.py delete mode 100755 tools/spinel-cli/sniffer.py delete mode 100755 tools/spinel-cli/spinel-cli.py delete mode 100644 tools/spinel-cli/spinel/Makefile.am delete mode 100644 tools/spinel-cli/spinel/__init__.py delete mode 100644 tools/spinel-cli/spinel/codec.py delete mode 100644 tools/spinel-cli/spinel/config.py delete mode 100644 tools/spinel-cli/spinel/const.py delete mode 100644 tools/spinel-cli/spinel/hdlc.py delete mode 100644 tools/spinel-cli/spinel/pcap.py delete mode 100644 tools/spinel-cli/spinel/stream.py delete mode 100644 tools/spinel-cli/spinel/test_codec.py delete mode 100644 tools/spinel-cli/spinel/test_hdlc.py delete mode 100644 tools/spinel-cli/spinel/test_sniffer.py delete mode 100644 tools/spinel-cli/spinel/test_stream.py delete mode 100644 tools/spinel-cli/spinel/tests.py delete mode 100644 tools/spinel-cli/spinel/tun.py delete mode 100644 tools/spinel-cli/spinel/util.py delete mode 100755 tools/spinel-cli/test_spinel.py diff --git a/configure.ac b/configure.ac index 387d9335b..9eb0c0f0e 100644 --- a/configure.ac +++ b/configure.ac @@ -1294,8 +1294,6 @@ tools/Makefile tools/harness-automation/Makefile tools/harness-thci/Makefile tools/spi-hdlc-adapter/Makefile -tools/spinel-cli/Makefile -tools/spinel-cli/spinel/Makefile tests/Makefile tests/scripts/Makefile tests/scripts/thread-cert/Makefile diff --git a/tools/Makefile.am b/tools/Makefile.am index 252c7eb0a..4eeded266 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -34,13 +34,11 @@ DIST_SUBDIRS = \ harness-automation \ harness-thci \ spi-hdlc-adapter \ - spinel-cli \ $(NULL) # Always build (e.g. for 'make all') these subdirectories. SUBDIRS = \ - spinel-cli \ $(NULL) if OPENTHREAD_BUILD_TOOLS diff --git a/tools/spinel-cli/MANIFEST.in b/tools/spinel-cli/MANIFEST.in deleted file mode 100644 index db8845234..000000000 --- a/tools/spinel-cli/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include README.md -include SNIFFER.md \ No newline at end of file diff --git a/tools/spinel-cli/Makefile.am b/tools/spinel-cli/Makefile.am deleted file mode 100644 index f5aeecb54..000000000 --- a/tools/spinel-cli/Makefile.am +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - -include $(abs_top_nlbuild_autotools_dir)/automake/pre.am - -EXTRA_DIST = \ - spinel-cli.py \ - sniffer.py \ - test_spinel.py \ - $(NULL) - -DIST_SUBDIRS = \ - spinel \ - $(NULL) - -# Always build (e.g. for 'make all') these subdirectories. - -SUBDIRS = \ - $(NULL) - -# Always pretty (e.g. for 'make pretty') these subdirectories. - -PRETTY_SUBDIRS = \ - $(NULL) - -if OPENTHREAD_ENABLE_NCP - -# List all essential script tests that MUST be run. - -TESTS_ENVIRONMENT = \ - $(NULL) - -TESTS = \ - test_spinel.py \ - $(NULL) - -endif # OPENTHREAD_ENABLE_NCP - -include $(abs_top_nlbuild_autotools_dir)/automake/post.am diff --git a/tools/spinel-cli/README.md b/tools/spinel-cli/README.md deleted file mode 100644 index fe31db603..000000000 --- a/tools/spinel-cli/README.md +++ /dev/null @@ -1,364 +0,0 @@ -# Spinel CLI Reference - -The Spinel CLI exposes the OpenThread configuration and management APIs -running on an NCP build via a command line interface. Spinel CLI is primarily -targeted for driving the automated continuous integration tests, and is -suitable for manual experimentation with controlling OpenThread NCP instances. -For a production grade host driver, see [wpantund]: https://github.com/openthread/wpantund. - -Use the CLI to play with NCP builds of OpenThread on a Linux or Mac OS -platform, including starting a basic tunnel interface to allow IPv6 -applications to run on the HOST and use the Thread network. - -The power of this tool is three fold: - -1. As a path to add testing of the NCP in simulation to continuous integration -2. As a path to automated testing of testbeds running NCP firmware on hardware -3. As a simple debugging tool for NCP builds of OpenThread - -## System Requirements - -| OS | Minimum Version | -|--------|------------------| -| Ubuntu | 14.04 Trusty | -| Mac OS | 10.11 El Capitan | - -| Language | Minimum Version | -|----------|------------------| -| Python | 2.7.10 | - -### Package Installation - -``` -# From openthread root -cd tools/spinel-cli -sudo python setup.py install -``` - -## Usage - -### NAME - spinel-cli.py - shell tool for controlling OpenThread NCP instances - -### SYNOPSIS - spinel-cli.py [-hupsnqv] - -### DESCRIPTION - -``` - -h, --help - Show this help message and exit - - -u , --uart= - Open a serial connection to the OpenThread NCP device - where is a device path such as "/dev/ttyUSB0". - - -p , --pipe= - Open a piped process connection to the OpenThread NCP device - where is the command to start an emulator, such as - "ot-ncp-ftd". Spinel-cli will communicate with the child process - via stdin/stdout. - - -s , --socket= - Open a socket connection to the OpenThread NCP device - where is the port to open. - This is useful for SPI configurations when used in conjunction - with a spinel spi-driver daemon. - Note: will eventually map to hostname:port tuple. - - -n NODEID, --nodeid=NODEID - The unique nodeid for the HOST and NCP instance. - - -q, --quiet - Minimize debug and log output. - - -v, --verbose - Maximize debug and log output. -``` - -## Quick Start - -The spinel-cli tool provides an intuitive command line interface, including -all the standard OpenThread CLI commands, plus full history accessible by -pressing the up/down keys, or searchable via ^R. There are a few commands -that spinel-cli provides as well that aren't part of the standard set -documented in the command reference section. - -``` -openthread$ cd tools/spinel-cli/ -spinel-cli$ ./spinel-cli.py -Opening pipe to ../../examples/apps/ncp/ot-ncp-ftd 1 -spinel-cli > help - -Available commands (type help for more information): -============================================================ -channel extaddr mode route -child extpanid netdataregister router -childtimeout h networkidtimeout routerupgradethreshold -clear help networkname scan -contextreusedelay history panid state -counter ifconfig ping thread -debug ipaddr prefix v -debug-term keysequence q version -eidcache leaderdata quit whitelist -enabled leaderweight releaserouterid -exit masterkey rloc16 - -spinel-cli > version -OPENTHREAD/gd4d4e9d-dirty; Aug 11 2016 14:40:44 -Done -spinel-cli > thread start -Done -spinel-cli > state -leader -Done -spinel-cli > -``` - -## Running the NCP Tests - -The OpenThread automated test suite can be run against any of the following -node types by passing the NODE_TYPE environment variable: - -| NODE_TYPE | Description | -|---------------|----------------------------------------------------| -| sim (default) | Runs against ot-cli posix emulator | -| ncp-sim | Runs against ot-ncp posix emulator with spinel-cli | -| soc | Runs against CLI firmware on a device connected via /dev/ttyUSB | - -### Manual run of NCP thread-cert test - -``` -# From top-level of openthread tree -./bootstrap -./configure --with-examples=posix --enable-cli-app=all --enable-ncp-app=all --with-ncp-bus=uart -make -cd tests/scripts/thread-cert -NODE_TYPE=ncp-sim top_builddir=../../.. python Cert_5_1_02_ChildAddressTimeout.py VERBOSE=1 -``` - -### Run entire NCP thread-cert suite - -``` -# From top-level of openthread tree -make distclean -./bootstrap -NODE_TYPE=ncp-sim BUILD_TARGET=posix-distcheck DISTCHECK_CONFIGURE_FLAGS="--with-examples=posix --enable-cli-app --enable-ncp-app=all --with-ncp-bus=uart --with-tests=all" make -f examples/Makefile-posix distcheck BuildJobs=10 VERBOSE=1 -``` - -## Command Reference - -### OpenThread CLI Commands - -The primary intent of spinel-cli is to support the exact syntax and output -of the OpenThread CLI command set in order to seamlessly reapply the -thread-cert automated test suite against NCP targets. - -See [cli module][1] for more information on these commands. - -[1]:../../src/cli/README.md - -### Diagnostics CLI Commands - -The Diagnostics module is enabled only when building OpenThread with -the --enable-diag configure option. - -See [diag module][2] for more information on these commands. - -[2]:../../src/diag/README.md - - -### NCP CLI Commands - -These commands extend beyond the core OpenThread CLI, and are specific to -the spinel-cli tool for the purposes of debugging, access to NCP-specific -Spinel parameters, and support of advanced configurations. - -* [help](#help) -* [?](#help) -* [v](#v) -* [exit](#exit) -* [quit](#quit) -* [q](#quit) -* [clear](#clear) -* [history](#history) -* [h](#history) -* [debug](#debug) -* [debug-term](#debug-term) -* [ncp-tun](#ncp-tun) -* [ncp-ml64](#ncp-ml64) -* [ncp-ll64](#ncp-ll64) - - -#### help - -Display help all top-level commands supported by spinel-cli. - -```bash -spinel-cli > help - -Available commands (type help for more information): -============================================================ -channel diag-start leaderdata quit -child diag-stats leaderweight releaserouterid -childtimeout diag-stop masterkey rloc16 -clear discover mode route -contextreusedelay eidcache ncp-ll64 router -counter exit ncp-ml64 routerupgradethreshold -debug extaddr ncp-tun scan -debug-term extpanid netdataregister state -diag h networkidtimeout thread -diag-channel help networkname tun -diag-power history panid v -diag-repeat ifconfig ping version -diag-send ipaddr prefix whitelist -diag-sleep keysequence q - -``` - -#### help \ - -Display detailed help on a specific command. - -```bash -spinel-cli > help version - -version - - Print the build version information. - - > version - OPENTHREAD/gf4f2f04; Jul 1 2016 17:00:09 - Done -``` - -#### v - -Display version of spinel-cli tool. - -```bash -spinel-cli > v -spinel-cli ver. 0.1.0 -Copyright (c) 2016 The OpenThread Authors. -``` - -#### exit - -Exit spinel-cli. CTRL+C is also okay. - -#### quit - -Exit spinel-cli. CTRL+C is also okay. - -### clear - -Clear screen. - -#### history - -Display history of most recent commands run. - -```bash -spinel-cli > history -ping fd00::1 -quit -help -history -``` - -#### debug - -Get whether debug verbose output is enabled. - -```bash -spinel-cli > debug -DEBUG_ENABLE = 0 -``` - -#### debug \ - -Set whether debug verbose output is enabled. - -spinel-cli > debug -DEBUG_ENABLE = 0 - -```bash -spinel-cli > debug 1 -DEBUG_ENABLE = 1 -spinel-cli > version -TX Pay: (3) ['81', '02', '02'] -RX Pay: (53) ['81', '06', '02', '4F', '50', '45', '4E', '54', '48', '52', '45', '41', '44', '2F', '67', '38', '62', '63', '34', '62', '31', '64', '2D', '64', '69', '72', '74', '79', '3B', '20', '41', '75', '67', '20', '33', '31', '20', '32', '30', '31', '36', '20', '31', '30', '3A', '34', '38', '3A', '35', '33', '00', '40', '33'] -OPENTHREAD/g8bc4b1d-dirty; Aug 31 2016 10:48:53 -Done -``` - -#### debug-term - -Get whether debug terminal title bar is enabled. - -#### debug-term \ - -Set whether debug terminal title bar is enabled. - -#### ncp-tun - -Control sideband tunnel interface. - -#### ncp-tun up - -Bring up Thread TUN interface. - -```bash -spinel-cli > ncp-tun up -Done -``` - -#### ncp-tun down - -Bring down Thread TUN interface. - -```bash -spinel-cli > ncp-tun down -Done -``` - -#### ncp-tun add \ - -Add an IPv6 address to the Thread TUN interface. - -```bash -spinel-cli > ncp-tun add 2001::dead:beef:cafe -Done -``` - -#### ncp-tun del \ - -Delete an IPv6 address from the Thread TUN interface. - -```bash -spinel-cli > ncp-tun del 2001::dead:beef:cafe -Done -``` - -#### ncp-tun ping \ \[size\] \[count\] \[interval\] - -Send an ICMPv6 Echo Request via a posix host system call. - -```bash -spinel-cli > ncp-tun ping fdde:ad00:beef:0:558:f56b:d688:799 -16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms -``` - -#### ncp-ml64 - -Return the Mesh Local 64-bit IPv6 address for the node. - -``` -spinel-cli > ncp-ml64 -fdde:ad00:beef:0:558:f56b:d688:799 -Done -``` - -#### ncp-ll64 - -Return the Link Local 64-bit IPv6 address for the node. diff --git a/tools/spinel-cli/SNIFFER.md b/tools/spinel-cli/SNIFFER.md deleted file mode 100644 index befabc26f..000000000 --- a/tools/spinel-cli/SNIFFER.md +++ /dev/null @@ -1,108 +0,0 @@ -# Spinel Sniffer Reference - -Any Spinel NCP node can be made into a promiscuous packet sniffer, and this -tool both intializes a device into this mode and outputs a pcap stream that -can be saved or piped directly into Wireshark. - -## System Requirements - -The tool has been tested on the following platforms: - -| Platforms | Version | -|-----------|------------------| -| Ubuntu | 14.04 Trusty | -| Mac OS | 10.11 El Capitan | - -| Language | Version | -|-----------|------------------| -| Python | 2.7.10 | - -### Package Installation - -``` -sudo easy_install pip -sudo pip install --user pyserial -sudo pip install --user ipaddress -``` - -## Usage - -### NAME - sniffer.py - shell tool for controlling OpenThread NCP instances - -### SYNOPSIS - sniffer.py [-hupsnqvdxc] - -### DESCRIPTION - -``` - -h, --help - Show this help message and exit - - -u , --uart= - Open a serial connection to the OpenThread NCP device - where is a device path such as "/dev/ttyUSB0". - - -p , --pipe= - Open a piped process connection to the OpenThread NCP device - where is the command to start an emulator, such as - "ot-ncp-ftd". Spinel-cli will communicate with the child process - via stdin/stdout. - - -s , --socket= - Open a socket connection to the OpenThread NCP device - where is the port to open. - This is useful for SPI configurations when used in conjunction - with a spinel spi-driver daemon. - Note: will eventually map to hostname:port tuple. - - -n NODEID, --nodeid= - The unique nodeid for the HOST and NCP instance. - - -q, --quiet - Minimize debug and log output. - - -v, --verbose - Maximize debug and log output. - - -d , --debug= - Set the debug level. Enabling debug output is typically coupled with -x. - 0: Supress all debug output. Required to stream to Wireshark. - 1: Show spinel property changes and values. - 2: Show spinel IPv6 packet bytes. - 3: Show spinel raw packet bytes (after HDLC decoding). - 4: Show spinel HDLC bytes. - 5: Show spinel raw stream bytes: all serial traffic to NCP. - - -x, --hex - Output packets as ASCII HEX rather than pcap. - - -c, --channel - Set the channel upon which to listen. -``` - -## Quick Start - -From openthread root: - -``` - sudo ./tools/spinel-cli/sniffer.py -c 11 -n 1 -u /dev/ttyUSB0 | wireshark -k -i - -``` - -This will connect to stock openthread ncp firmware over the given UART, -make the node into a promiscuous mode sniffer on the given channel, -open up wireshark, and start streaming packets into wireshark. - -## Troubleshooting -Q: sniffer.py throws ```ImportError: No module named dnet``` on OSX - -A: install the libdnet package for OSX - -``` -brew install --with-python libdnet -mkdir -p /Users/YourUsernameHere/Library/Python/2.7/lib/python/site-packages -touch /Users/YourUsernameHere/Library/Python/2.7/lib/python/site-packages/homebrew.pth -echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users/YourUsernameHere/Library/Python/2.7/lib/python/site-packages/homebrew.pth -``` -you may need to reinstall the scapy pip dependency listed above - -you can read more about this issue here: http://stackoverflow.com/questions/26229057/scapy-installation-fails-on-osx-with-dnet-import-error diff --git a/tools/spinel-cli/setup.py b/tools/spinel-cli/setup.py deleted file mode 100644 index 7b5f76078..000000000 --- a/tools/spinel-cli/setup.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -u -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -from setuptools import setup, find_packages - -setup( - name='spinel', - version='1.0.0a1', - description='A Python interface to the OpenThread Network Co-Processor (NCP)', - url='https://github.com/openthread/openthread', - author='The OpenThread Authors', - author_email='openthread-users@googlegroups.com', - license='BSD', - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - - 'Operating System :: MacOS', - 'Operating System :: POSIX :: Linux', - - 'License :: OSI Approved :: BSD License', - - 'Topic :: System :: Networking', - 'Topic :: System :: Hardware :: Hardware Drivers', - 'Topic :: Software Development :: Embedded Systems', - - 'Programming Language :: Python :: 2.7', - ], - keywords='openthread thread spinel ncp', - packages=find_packages(), - install_requires=[ - 'pyserial', - 'ipaddress', - 'scapy==2.3.2' - ], - scripts=['spinel-cli.py', 'sniffer.py'] -) \ No newline at end of file diff --git a/tools/spinel-cli/sniffer.py b/tools/spinel-cli/sniffer.py deleted file mode 100755 index f5d6e4039..000000000 --- a/tools/spinel-cli/sniffer.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python -u -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" - Sniffer tool that outputs raw pcap. - - Real-time stream to wireshark: - ./sniffer.py | wireshark -k -i - - - Save stream to file or pipe: - ./sniffer.py > trace.pcap -""" - -import sys -import optparse - -import spinel.util as util -import spinel.config as CONFIG -from spinel.const import SPINEL -from spinel.codec import WpanApi -from spinel.stream import StreamOpen -from spinel.pcap import PcapCodec - - -# Nodeid is required to execute ot-ncp-ftd for its sim radio socket port. -# This is maximum that works for MacOS. -DEFAULT_NODEID = 34 # same as WELLKNOWN_NODE_ID -DEFAULT_CHANNEL = 11 - -def parse_args(): - """ Parse command line arguments for this applications. """ - - args = sys.argv[1:] - - opt_parser = optparse.OptionParser() - opt_parser.add_option("-u", "--uart", action="store", - dest="uart", type="string") - opt_parser.add_option("-p", "--pipe", action="store", - dest="pipe", type="string") - opt_parser.add_option("-s", "--socket", action="store", - dest="socket", type="string") - opt_parser.add_option("-n", "--nodeid", action="store", - dest="nodeid", type="string", default=str(DEFAULT_NODEID)) - - opt_parser.add_option("-q", "--quiet", action="store_true", dest="quiet") - opt_parser.add_option("-v", "--verbose", action="store_false", dest="verbose") - opt_parser.add_option("-d", "--debug", action="store", - dest="debug", type="int", default=CONFIG.DEBUG_ENABLE) - opt_parser.add_option("-x", "--hex", action="store_true", dest="hex") - - opt_parser.add_option("-c", "--channel", action="store", - dest="channel", type="int", default=DEFAULT_CHANNEL) - - return opt_parser.parse_args(args) - -def sniffer_init(wpan_api, options): - """" Send spinel commands to initialize sniffer node. """ - wpan_api.queue_register(SPINEL.HEADER_DEFAULT) - wpan_api.queue_register(SPINEL.HEADER_ASYNC) - - wpan_api.cmd_send(SPINEL.CMD_RESET) - wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) - wpan_api.prop_set_value(SPINEL.PROP_MAC_FILTER_MODE, SPINEL.MAC_FILTER_MODE_MONITOR) - wpan_api.prop_set_value(SPINEL.PROP_PHY_CHAN, options.channel) - wpan_api.prop_set_value(SPINEL.PROP_MAC_15_4_PANID, 0xFFFF, 'H') - wpan_api.prop_set_value(SPINEL.PROP_MAC_RAW_STREAM_ENABLED, 1) - wpan_api.prop_set_value(SPINEL.PROP_NET_IF_UP, 1) - -def main(): - """ Top-level main for sniffer host-side tool. """ - (options, remaining_args) = parse_args() - - if options.debug: - CONFIG.debug_set_level(options.debug) - - # Set default stream to pipe - stream_type = 'p' - stream_descriptor = "../../examples/apps/ncp/ot-ncp-ftd "+options.nodeid - - if options.uart: - stream_type = 'u' - stream_descriptor = options.uart - elif options.socket: - stream_type = 's' - stream_descriptor = options.socket - elif options.pipe: - stream_type = 'p' - stream_descriptor = options.pipe - if options.nodeid: - stream_descriptor += " "+str(options.nodeid) - else: - if len(remaining_args) > 0: - stream_descriptor = " ".join(remaining_args) - - stream = StreamOpen(stream_type, stream_descriptor, False) - if stream is None: exit() - wpan_api = WpanApi(stream, options.nodeid) - sniffer_init(wpan_api, options) - - pcap = PcapCodec() - hdr = pcap.encode_header() - if options.hex: - hdr = util.hexify_str(hdr)+"\n" - sys.stdout.write(hdr) - sys.stdout.flush() - - try: - tid = SPINEL.HEADER_ASYNC - prop_id = SPINEL.PROP_STREAM_RAW - while True: - result = wpan_api.queue_wait_for_prop(prop_id, tid) - if result and result.prop == prop_id: - length = wpan_api.parse_S(result.value) - pkt = result.value[2:2+length] - pkt = pcap.encode_frame(pkt) - if options.hex: - pkt = util.hexify_str(pkt)+"\n" - sys.stdout.write(pkt) - sys.stdout.flush() - - except KeyboardInterrupt: - pass - - if wpan_api: - wpan_api.stream.close() - - -if __name__ == "__main__": - main() diff --git a/tools/spinel-cli/spinel-cli.py b/tools/spinel-cli/spinel-cli.py deleted file mode 100755 index 9ad2c5ec9..000000000 --- a/tools/spinel-cli/spinel-cli.py +++ /dev/null @@ -1,2108 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" -spinel-cli.py - -available commands (type help for more information): -============================================================ -channel diag-sleep leaderdata releaserouterid -child diag-start leaderweight rloc16 -childmax diag-stats masterkey route -childtimeout diag-stop mode router -clear discover ncp-ll64 routerupgradethreshold -commissioner eidcache ncp-ml64 scan -contextreusedelay exit ncp-tun state -counter extaddr netdataregister thread -debug extpanid networkidtimeout tun -debug-mem h networkname v -diag help panid version -diag-channel history ping whitelist -diag-power ifconfig prefix -diag-repeat ipaddr q -diag-send keysequence quit -""" - -from __future__ import print_function - -import os -import sys -import time -import traceback - -import optparse - -import binascii -import struct -import string -import textwrap - -import logging -import logging.config -import logging.handlers - -from cmd import Cmd - -from spinel.const import SPINEL -from spinel.const import kThread -from spinel.codec import WpanApi -from spinel.codec import SpinelCodec -from spinel.stream import StreamOpen -from spinel.tun import TunInterface -import spinel.config as CONFIG -import spinel.util as util - -import ipaddress - -logging.getLogger("scapy.runtime").setLevel(logging.ERROR) -from scapy.layers.inet6 import IPv6 -from scapy.layers.inet6 import ICMPv6EchoReply -from scapy.layers.inet6 import ICMPv6EchoRequest - - -__copyright__ = "Copyright (c) 2016 The OpenThread Authors." -__version__ = "0.1.0" - -MASTER_PROMPT = "spinel-cli" - - -class SpinelCliCmd(Cmd, SpinelCodec): - """ - A command line shell for controlling OpenThread NCP nodes - via the Spinel protocol. - """ - - def __init__(self, stream_desc, nodeid, *_a, **kw): - - self.nodeid = kw.get('nodeid', '1') - self.tun_if = None - - self.wpan_api = WpanApi(stream_desc, nodeid) - self.wpan_api.queue_register(SPINEL.HEADER_DEFAULT) - self.wpan_api.callback_register(SPINEL.PROP_STREAM_NET, - self.wpan_callback) - - Cmd.__init__(self) - Cmd.identchars = string.ascii_letters + string.digits + '-' - - if sys.stdin.isatty(): - self.prompt = MASTER_PROMPT + " > " - else: - self.use_rawinput = 0 - self.prompt = "" - - SpinelCliCmd.command_names.sort() - - self.history_filename = os.path.expanduser("~/.spinel-cli-history") - - try: - import readline - try: - readline.read_history_file(self.history_filename) - except IOError: - pass - except ImportError: - print("Module readline unavailable") - else: - #import rlcompleter - readline.parse_and_bind("tab: complete") - if sys.platform == 'darwin': - readline.parse_and_bind("bind ^I rl_complete") - - self.prop_set_value(SPINEL.PROP_IPv6_ICMP_PING_OFFLOAD, 1) - self.prop_set_value(SPINEL.PROP_THREAD_RLOC16_DEBUG_PASSTHRU, 1) - - command_names = [ - # Shell commands - 'exit', - 'quit', - 'clear', - 'history', - 'debug', - 'debug-mem', - - 'v', - 'h', - 'q', - - # OpenThread CLI commands - 'help', - 'bufferinfo', - 'channel', - 'child', - 'childmax', - 'childtimeout', - 'commissioner', - 'contextreusedelay', - 'counter', - 'discover', - 'eidcache', - 'extaddr', - 'extpanid', - 'ifconfig', - 'ipaddr', - 'joiner', - 'keysequence', - 'leaderdata', - 'leaderweight', - 'masterkey', - 'mode', - 'netdataregister', - 'networkidtimeout', - 'networkname', - 'panid', - 'parent', - 'ping', - 'prefix', - 'releaserouterid', - 'rloc16', - 'route', - 'router', - 'routerselectionjitter', - 'routerupgradethreshold', - 'routerdowngradethreshold', - 'scan', - 'state', - 'thread', - 'version', - 'whitelist', - - # OpenThread Diagnostics Module CLI - 'diag', - 'diag-start', - 'diag-channel', - 'diag-power', - 'diag-send', - 'diag-repeat', - 'diag-sleep', - 'diag-stats', - 'diag-stop', - - # OpenThread Spinel-specific commands - 'ncp-ml64', - 'ncp-ll64', - 'ncp-tun', - 'ncp-raw', - 'ncp-filter', - - ] - - @classmethod - def wpan_callback(cls, prop, value, tid): - consumed = False - - if prop == SPINEL.PROP_STREAM_NET: - consumed = True - - pkt = IPv6(value[2:]) - - if CONFIG.DEBUG_LOG_PKT: - pkt.show() - - if ICMPv6EchoReply in pkt: - timenow = int(round(time.time() * 1000)) & 0xFFFFFFFF - timedelta = (timenow - struct.unpack('>I', pkt.data)[0]) - print("\n%d bytes from %s: icmp_seq=%d hlim=%d time=%dms" % ( - pkt.plen, pkt.src, pkt.seq, pkt.hlim, timedelta)) - - return consumed - - @classmethod - def log(cls, text): - """ Common log handler. """ - logging.info(text) - - def parseline(self, line): - cmd, arg, line = Cmd.parseline(self, line) - if cmd: - cmd = self.short_command_name(cmd) - line = cmd + ' ' + arg - return cmd, arg, line - - def completenames(self, text, *ignored): - return [name + ' ' for name in SpinelCliCmd.command_names - if name.startswith(text) - or self.short_command_name(name).startswith(text)] - - @classmethod - def short_command_name(cls, cmd): - return cmd.replace('-', '') - - def postloop(self): - try: - import readline - try: - readline.write_history_file(self.history_filename) - except IOError: - pass - except ImportError: - pass - - def prop_get_value(self, prop_id): - """ Blocking helper to return value for given propery identifier. """ - return self.wpan_api.prop_get_value(prop_id) - - def prop_set_value(self, prop_id, value, py_format='B'): - """ Blocking helper to set value for given propery identifier. """ - return self.wpan_api.prop_set_value(prop_id, value, py_format) - - def prop_insert_value(self, prop_id, value, py_format='B'): - """ Blocking helper to insert entry for given list property. """ - return self.wpan_api.prop_insert_value(prop_id, value, py_format) - - def prop_remove_value(self, prop_id, value, py_format='B'): - """ Blocking helper to remove entry for given list property. """ - return self.wpan_api.prop_remove_value(prop_id, value, py_format) - - def prop_get_or_set_value(self, prop_id, line, mixed_format='B'): - """ Helper to get or set a property value based on line arguments. """ - if line: - value = self.prep_line(line, mixed_format) - py_format = self.prep_format(value, mixed_format) - value = self.prop_set_value(prop_id, value, py_format) - else: - value = self.prop_get_value(prop_id) - return value - - @classmethod - def prep_line(cls, line, mixed_format='B'): - """ Convert a command line argument to proper binary encoding (pre-pack). """ - value = line - if line != None: - if mixed_format == 'U': # For UTF8, just a pass through line unmodified - value = line.encode('utf-8') + '\0' - elif mixed_format == 'D': # Expect raw data to be hex string w/o delimeters - value = util.hex_to_bytes(line) - else: - # Most everything else is some type of integer - value = int(line) - return value - - @classmethod - def prep_format(cls, value, mixed_format='B'): - """ Convert a spinel format to a python pack format. """ - py_format = mixed_format - if value == "": - py_format = '0s' - elif mixed_format == 'D' or mixed_format == 'U': - py_format = str(len(value)) + 's' - return py_format - - def prop_get(self, prop_id, mixed_format='B'): - """ Helper to get a propery and output the value with Done or Error. """ - value = self.prop_get_value(prop_id) - if value is None: - print("Error") - return None - - if (mixed_format == 'D') or (mixed_format == 'E'): - print(util.hexify_str(value, '')) - else: - print(str(value)) - print("Done") - - return value - - def prop_set(self, prop_id, line, mixed_format='B'): - """ Helper to set a propery and output Done or Error. """ - value = self.prep_line(line, mixed_format) - py_format = self.prep_format(value, mixed_format) - result = self.prop_set_value(prop_id, value, py_format) - - if result is None: - print("Error") - else: - print("Done") - - return result - - def handle_property(self, line, prop_id, mixed_format='B', output=True): - """ Helper to set property when line argument passed, get otherwise. """ - value = self.prop_get_or_set_value(prop_id, line, mixed_format) - if not output: - return value - - if value is None or value == "": - print("Error") - return None - - if line is None or line == "": - # Only print value on PROP_VALUE_GET - if mixed_format == '6': - print(str(ipaddress.IPv6Address(value))) - elif (mixed_format == 'D') or (mixed_format == 'E'): - print(util.hexify_str(value, '')) - elif mixed_format == 'H': - print("%04x" % value) - else: - print(str(value)) - - print("Done") - return value - - def do_help(self, line): - if line: - cmd, _arg, _unused = self.parseline(line) - try: - doc = getattr(self, 'do_' + cmd).__doc__ - except AttributeError: - doc = None - if doc: - self.log("%s\n" % textwrap.dedent(doc)) - else: - self.log("No help on %s\n" % (line)) - else: - self.print_topics( - "\nAvailable commands (type help for more information):", - SpinelCliCmd.command_names, 15, 80) - - def do_v(self, _line): - """ - version - Shows detailed version information on spinel-cli tool: - """ - self.log(MASTER_PROMPT + " ver. " + __version__) - self.log(__copyright__) - - @classmethod - def do_clear(cls, _line): - """ Clean up the display. """ - os.system('reset') - - def do_history(self, _line): - """ - history - - Show previously executed commands. - """ - - try: - import readline - hist = readline.get_current_history_length() - for idx in range(1, hist + 1): - self.log(readline.get_history_item(idx)) - except ImportError: - pass - - def do_h(self, line): - """ Shortcut for history. """ - self.do_history(line) - - def do_exit(self, _line): - """ Exit the shell. """ - self.log("exit") - return True - - def do_quit(self, line): - """ Exit the shell. """ - return self.do_exit(line) - - def do_q(self, line): - """ Exit the shell. """ - return self.do_exit(line) - - def do_EOF(self, _line): - """ End of file handler for when commands are piped into shell. """ - self.log("\n") - return True - - def emptyline(self): - pass - - def default(self, line): - if line[0] == "#": - logging.debug(line) - else: - logging.info(line + ": command not found") - # exec(line) - - def do_debug(self, line): - """ - Enables detail logging of bytes over the wire to the radio modem. - Usage: debug <1=enable | 0=disable> - """ - - if line != None and line != "": - level = int(line) - else: - level = 0 - - CONFIG.debug_set_level(level) - - def do_debugmem(self, _line): - """ Profile python memory usage. """ - from guppy import hpy - heap_stats = hpy() - print(heap_stats.heap()) - print() - print(heap_stats.heap().byrcs) - - def do_bufferinfo(self, line): - """ - \033[1mbufferinfo\033[0m - - Get the mesh forwarder buffer info. - \033[2m - > bufferinfo - total: 128 - free: 128 - 6lo send: 0 0 - 6lo reas: 0 0 - ip6: 0 0 - mpl: 0 0 - mle: 0 0 - arp: 0 0 - coap: 0 0 - Done - \033[0m - """ - - result = self.prop_get_value(SPINEL.PROP_MSG_BUFFER_COUNTERS) - if result != None: - result = result[0] - - print("total: %d" % result[0]) - print("free: %d" % result[1]) - print("6lo send: %d %d" % result[2:4]) - print("6lo reas: %d %d" % result[4:6]) - print("ip6: %d %d" % result[6:8]) - print("mpl: %d %d" % result[8:10]) - print("mle: %d %d" % result[10:12]) - print("arp: %d %d" % result[12:14]) - print("coap: %d %d" % result[14:16]) - print("Done") - else: - print("Error") - - def do_channel(self, line): - """ - \033[1mchannel\033[0m - - Get the IEEE 802.15.4 Channel value. - \033[2m - > channel - 11 - Done - \033[0m - \033[1mchannel \033[0m - - Set the IEEE 802.15.4 Channel value. - \033[2m - > channel 11 - Done - \033[0m - """ - self.handle_property(line, SPINEL.PROP_PHY_CHAN) - - def do_child(self, line): - """\033[1m - child list - \033[0m - List attached Child IDs - \033[2m - > child list - 1 2 3 6 7 8 - Done - \033[0m\033[1m - child - \033[0m - Print diagnostic information for an attached Thread Child. - The id may be a Child ID or an RLOC16. - \033[2m - > child 1 - Child ID: 1 - Rloc: 9c01 - Ext Addr: e2b3540590b0fd87 - Mode: rsn - Net Data: 184 - Timeout: 100 - Age: 0 - LQI: 3 - RSSI: -20 - Done - \033[0m - """ - child_table = self.prop_get_value(SPINEL.PROP_THREAD_CHILD_TABLE)[0] - - if line == 'list': - result = '' - for child_data in child_table: - child_data = child_data[0] - child_id = child_data[1] & 0x1FF - result += '{} '.format(child_id) - print(result) - print("Done") - - else: - try: - child_id = int(line) - printed = False - for child_data in child_table: - child_data = child_data[0] - id = child_data[1] & 0x1FF - - if id == child_id: - mode = '' - if child_data[7] & 0x08: - mode += 'r' - if child_data[7] & 0x04: - mode += 's' - if child_data[7] & 0x02: - mode += 'd' - if child_data[7] & 0x01: - mode += 'n' - - print("Child ID: {}".format(id)) - print("Rloc: {:04x}".format(child_data[1])) - print("Ext Addr: {}".format(binascii.hexlify(child_data[0]))) - print("Mode: {}".format(mode)) - print("Net Data: {}".format(child_data[4])) - print("Timeout: {}".format(child_data[2])) - print("Age: {}".format(child_data[3])) - print("LQI: {}".format(child_data[5])) - print("RSSI: {}".format(child_data[6])) - print("Done") - - printed = True - - if not printed: - print("Error") - except ValueError: - print("Error") - - def do_childmax(self, line): - """\033[1m - childmax - \033[0m - Get the Thread Child Count Max value. - \033[2m - > childmax - 10 - Done - \033[0m\033[1m - childmax - \033[0m - Set the Thread Child Count Max value. - \033[2m - > childmax 5 - Done - \033[0m - """ - self.handle_property(line, SPINEL.PROP_THREAD_CHILD_COUNT_MAX) - - def do_childtimeout(self, line): - """\033[1m - childtimeout - \033[0m - Get the Thread Child Timeout value. - \033[2m - > childtimeout - 300 - Done - \033[0m\033[1m - childtimeout - \033[0m - Set the Thread Child Timeout value. - \033[2m - > childtimeout 300 - Done - \033[0m - """ - self.handle_property(line, SPINEL.PROP_THREAD_CHILD_TIMEOUT, 'L') - - def do_commissioner(self, line): - """ - These commands are enabled when configuring with --enable-commissioner. - - \033[1m - commissioner start - \033[0m - Start the Commissioner role on this node. - \033[2m - > commissioner start - Done - \033[0m\033[1m - commissioner stop - \033[0m - Stop the Commissioner role on this node. - \033[2m - > commissioner stop - Done - \033[0m\033[1m - commissioner panid - \033[0m - Perform panid query. - \033[2m - > commissioner panid 57005 4294967295 ff33:0040:fdde:ad00:beef:0:0:1 - Conflict: dead, 00000800 - Done - \033[0m\033[1m - commissioner energy - \033[0m - Perform energy scan. - \033[2m - > commissioner energy 327680 2 32 1000 fdde:ad00:beef:0:0:ff:fe00:c00 - Energy: 00050000 0 0 0 0 - Done - \033[0m - """ - pass - - def do_contextreusedelay(self, line): - """ - contextreusedelay - - Get the CONTEXT_ID_REUSE_DELAY value. - - > contextreusedelay - 11 - Done - - contextreusedelay - - Set the CONTEXT_ID_REUSE_DELAY value. - - > contextreusedelay 11 - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_CONTEXT_REUSE_DELAY, 'L') - - def do_counter(self, line): - """ - counter - - Get the supported counter names. - - >counter - mac - Done - - counter - - Get the counter value. - - >counter mac - TxTotal: 10 - TxAckRequested: 4 - TxAcked: 4 - TxNoAckRequested: 6 - TxData: 10 - TxDataPoll: 0 - TxBeacon: 0 - TxBeaconRequest: 0 - TxOther: 0 - TxRetry: 0 - TxErrCca: 0 - RxTotal: 11 - RxData: 11 - RxDataPoll: 0 - RxBeacon: 0 - RxBeaconRequest: 0 - RxOther: 0 - RxWhitelistFiltered: 0 - RxDestAddrFiltered: 0 - RxErrNoFrame: 0 - RxErrNoUnknownNeighbor: 0 - RxErrInvalidSrcAddr: 0 - RxErrSec: 0 - RxErrFcs: 0 - RxErrOther: 0 - """ - pass - - def do_discover(self, line): - """ - discover [channel] - - Perform an MLE Discovery operation. - - channel: The channel to discover on. If no channel is provided, - the discovery will cover all valid channels. - - > discover - | J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI | - +---+------------------+------------------+------+------------------+----+-----+-----+ - | 0 | OpenThread | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 | 0 | - Done - """ - pass - - def do_eidcache(self, line): - """ - eidcache - - Print the EID-to-RLOC cache entries. - - > eidcache - fdde:ad00:beef:0:bb1:ebd6:ad10:f33 ac00 - fdde:ad00:beef:0:110a:e041:8399:17cd 6000 - Done - """ - pass - - def do_extaddr(self, line): - """ - extaddr - - Get the IEEE 802.15.4 Extended Address. - - > extaddr - dead00beef00cafe - Done - - extaddr - - Set the IEEE 802.15.4 Extended Address. - - > extaddr dead00beef00cafe - dead00beef00cafe - Done - """ - self.handle_property(line, SPINEL.PROP_MAC_15_4_LADDR, 'E') - - def do_extpanid(self, line): - """ - extpanid - - Get the Thread Extended PAN ID value. - - > extpanid - dead00beef00cafe - Done - - extpanid - - Set the Thread Extended PAN ID value. - - > extpanid dead00beef00cafe - Done - """ - self.handle_property(line, SPINEL.PROP_NET_XPANID, 'D') - - def do_joiner(self, line): - """ - These commands are enabled when configuring with --enable-joiner. - - joiner start - - Start the Joiner role. - - * pskd: Pre-Shared Key for the Joiner. - * provisioningUrl: Provisioning URL for the Joiner (optional). - - This command will cause the device to perform an MLE Discovery and - initiate the Thread Commissioning process. - - > joiner start PSK - Done - - joiner stop - - Stop the Joiner role. - - > joiner stop - Done - """ - PSKd = "" - - params = line.split(" ") - if len(params) > 0: - sub_command = params[0] - if len(params) > 1: - PSKd = params[1] - - PSKd = self.prep_line(PSKd, 'U') - - if sub_command == "": - pass - - elif sub_command == "start": - py_format = self.prep_format(PSKd, 'U') - self.prop_set_value(SPINEL.PROP_MESHCOP_JOINER_CREDENTIAL, - PSKd, py_format) - self.prop_set_value(SPINEL.PROP_MESHCOP_JOINER_ENABLE, 1) - print("Done") - return - - elif sub_command == "stop": - self.prop_set_value(SPINEL.PROP_MESHCOP_JOINER_ENABLE, 0) - print("Done") - return - - print("Error") - - def complete_ifconfig(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for ifconfig command. """ - map_sub_commands = ('up', 'down') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_ifconfig(self, line): - """ - ifconfig up - - Bring up the IPv6 interface. - - > ifconfig up - Done - - ifconfig down - - Bring down the IPv6 interface. - - > ifconfig down - Done - - ifconfig - - Show the status of the IPv6 interface. - - > ifconfig - down - Done - """ - - params = line.split(" ") - - if params[0] == "": - value = self.prop_get_value(SPINEL.PROP_NET_IF_UP) - if value != None: - map_arg_value = { - 0: "down", - 1: "up", - } - print(map_arg_value[value]) - - elif params[0] == "up": - self.prop_set(SPINEL.PROP_NET_IF_UP, '1') - return - - elif params[0] == "down": - self.prop_set(SPINEL.PROP_NET_IF_UP, '0') - return - - print("Done") - - def complete_ipaddr(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for ipaddr command. """ - map_sub_commands = ('add', 'remove') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_ipaddr(self, line): - """ - ipaddr - - List all IPv6 addresses assigned to the Thread interface. - - > ipaddr - fdde:ad00:beef:0:0:ff:fe00:0 - fe80:0:0:0:0:ff:fe00:0 - fdde:ad00:beef:0:558:f56b:d688:799 - fe80:0:0:0:f3d9:2a82:c8d8:fe43 - Done - - ipaddr add - - Add an IPv6 address to the Thread interface. - - > ipaddr add 2001::dead:beef:cafe - Done - - ipaddr del - - Delete an IPv6 address from the Thread interface. - - > ipaddr del 2001::dead:beef:cafe - Done - """ - params = line.split(" ") - valid = 1 - preferred = 1 - flags = 0 - # always use /64, as prefix.network.prefixlen returns /128. - prefix_len = 64 - - num = len(params) - if num > 1: - ipaddr = params[1] - prefix = ipaddress.IPv6Interface(unicode(ipaddr)) - arr = prefix.ip.packed - - if params[0] == "": - addrs = self.wpan_api.get_ipaddrs() - for addr in addrs: - print(str(addr)) - - elif params[0] == "add": - arr += self.wpan_api.encode_fields('CLLC', - prefix_len, - valid, - preferred, - flags) - - self.prop_insert_value(SPINEL.PROP_IPV6_ADDRESS_TABLE, - arr, str(len(arr)) + 's') - - if self.tun_if: - self.tun_if.addr_add(ipaddr) - - elif params[0] == "remove": - arr += self.wpan_api.encode_fields('CLLC', - prefix_len, - valid, - preferred, - flags) - - self.prop_remove_value(SPINEL.PROP_IPV6_ADDRESS_TABLE, - arr, str(len(arr)) + 's') - if self.tun_if: - self.tun_if.addr_del(ipaddr) - - print("Done") - - def do_keysequence(self, line): - """ - keysequence counter - - Get the Thread Key Sequence Counter. - - > keysequence counter - 10 - Done - - keysequence counter - - Set the Thread Key Sequence Counter. - - > keysequence counter 10 - Done - - keysequence guardtime - - Get the thrKeySwitchGuardTime (in hours). - - > keysequence guardtime - 0 - Done - - keysequence guardtime - - Set the thrKeySwitchGuardTime (in hours). - - > keysequence guardtime 0 - Done - """ - - args = line.split(" ") - - if args[0] == "counter": - newline = line.replace("counter", "") - self.handle_property(newline, SPINEL.PROP_NET_KEY_SEQUENCE_COUNTER, 'L') - - elif args[0] == "guardtime": - newline = line.replace("guardtime", "") - self.handle_property(newline, SPINEL.PROP_NET_KEY_SWITCH_GUARDTIME, 'L') - - def do_leaderdata(self, line): - """ - leaderdata - - Get the Thread network Leader Data. - - > leaderdata - Partition ID: 1987912443 - Weighting: 64 - Data Version: 4 - Stable Data Version: 129 - Leader Router ID: 47 - Done - """ - partition_id = self.prop_get_value(SPINEL.PROP_NET_PARTITION_ID) - weighting = self.prop_get_value(SPINEL.PROP_THREAD_LEADER_WEIGHT) - data_version = self.prop_get_value(SPINEL.PROP_THREAD_NETWORK_DATA_VERSION) - stable_version = self.prop_get_value(SPINEL.PROP_THREAD_STABLE_NETWORK_DATA_VERSION) - leader_id = self.prop_get_value(SPINEL.PROP_THREAD_LEADER_RID) - - if partition_id is None or \ - weighting is None or \ - data_version is None or \ - stable_version is None or \ - leader_id is None: - print("Error") - else: - print("Partition ID: %d" % partition_id) - print("Weighting: %d" % weighting) - print("Data Version: %d" % data_version) - print("Stable Data Version: %d" % stable_version) - print("Leader Router ID: %d" % leader_id) - print("Done") - - def do_leaderweight(self, line): - """ - leaderweight - - Get the Thread Leader Weight. - - > leaderweight - 128 - Done - - leaderweight - - Set the Thread Leader Weight. - - > leaderweight 128 - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_LOCAL_LEADER_WEIGHT) - - def do_masterkey(self, line): - """ - masterkey - - Get the Thread Master Key value. - - > masterkey - 00112233445566778899aabbccddeeff - Done - - masterkey - - Set the Thread Master Key value. - - > masterkey 00112233445566778899aabbccddeeff - Done - """ - self.handle_property(line, SPINEL.PROP_NET_MASTER_KEY, 'D') - - def do_mode(self, line): - """ - mode - - Get the Thread Device Mode value. - - r: rx-on-when-idle - s: Secure IEEE 802.15.4 data requests - d: Full Function Device - n: Full Network Data - - > mode - rsdn - Done - - mode [rsdn] - - Set the Thread Device Mode value. - - r: rx-on-when-idle - s: Secure IEEE 802.15.4 data requests - d: Full Function Device - n: Full Network Data - - > mode rsdn - Done - """ - map_arg_value = { - 0x00: "0", - 0x01: "n", - 0x02: "d", - 0x03: "dn", - 0x04: "s", - 0x05: "sn", - 0x06: "sd", - 0x07: "sdn", - 0x08: "r", - 0x09: "rn", - 0x0A: "rd", - 0x0B: "rdn", - 0x0C: "rs", - 0x0D: "rsn", - 0x0E: "rsd", - 0x0F: "rsdn", - } - - map_arg_name = { - "0": 0x00, - "n": 0x01, - "d": 0x02, - "dn": 0x03, - "s": 0x04, - "sn": 0x05, - "sd": 0x06, - "sdn": 0x07, - "r": 0x08, - "rn": 0x09, - "rd": 0x0A, - "rdn": 0x0B, - "rs": 0x0C, - "rsn": 0x0D, - "rsd": 0x0E, - "rsdn": 0x0F - } - - if line: - try: - # remap string state names to integer - line = map_arg_name[line] - except KeyError: - print("Error") - return - - result = self.prop_get_or_set_value(SPINEL.PROP_THREAD_MODE, line) - if result != None: - if not line: - print(map_arg_value[result]) - print("Done") - else: - print("Error") - - def do_netdataregister(self, _line): - """ - netdataregister - - Register local network data with Thread Leader. - - > netdataregister - Done - """ - self.prop_set_value(SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, 1) - self.handle_property( - "0", SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE) - - def do_networkidtimeout(self, line): - """ - networkidtimeout - - Get the NETWORK_ID_TIMEOUT parameter used in the Router role. - - > networkidtimeout - 120 - Done - - networkidtimeout - - Set the NETWORK_ID_TIMEOUT parameter used in the Router role. - - > networkidtimeout 120 - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_NETWORK_ID_TIMEOUT) - - def do_networkname(self, line): - """ - networkname - - Get the Thread Network Name. - - > networkname - OpenThread - Done - - networkname - - Set the Thread Network Name. - - > networkname OpenThread - Done - """ - self.handle_property(line, SPINEL.PROP_NET_NETWORK_NAME, 'U') - - def do_panid(self, line): - """ - panid - - Get the IEEE 802.15.4 PAN ID value. - - > panid - 0xdead - Done - - panid - - Set the IEEE 802.15.4 PAN ID value. - - > panid 0xdead - Done - """ - self.handle_property(line, SPINEL.PROP_MAC_15_4_PANID, 'H') - - def do_parent(self, line): - """ - parent - - Get the addresses of the parent node. - - > parent - Ext Addr: 3ad35f9846ceb9c7 - Rloc: bc00 - Done - """ - ext_addr, rloc = self.prop_get_value(SPINEL.PROP_THREAD_PARENT) - - if ext_addr is None or\ - rloc is None: - print("Error") - else: - print("Ext Addr: {}".format(binascii.hexlify(ext_addr))) - print("Rloc: {:04x}".format(rloc)) - - def do_ping(self, line): - """ - ping [size] [count] [interval] - - Send an ICMPv6 Echo Request. - - > ping fdde:ad00:beef:0:558:f56b:d688:799 - 16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms - """ - params = line.split(" ") - addr = "::1" - _size = "56" - _count = "1" - _interval = "1" - if len(params) > 0: - addr = params[0] - if len(params) > 1: - _size = params[1] - if len(params) > 2: - _count = params[2] - if len(params) > 3: - _interval = params[3] - - try: - # Generate local ping packet and send directly via spinel. - ml64 = self.prop_get_value(SPINEL.PROP_IPV6_ML_ADDR) - ml64 = str(ipaddress.IPv6Address(ml64)) - timenow = int(round(time.time() * 1000)) & 0xFFFFFFFF - timenow = struct.pack('>I', timenow) - ping_req = str(IPv6(src=ml64, dst=addr) / - ICMPv6EchoRequest() / timenow) - self.wpan_api.ip_send(ping_req) - # Let handler print result - except: - print("Fail") - print(traceback.format_exc()) - - def complete_prefix(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for prefix command. """ - map_sub_commands = ('add', 'remove') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_prefix(self, line): - """ - prefix add [pvdcsr] [prf] - - Add a valid prefix to the Network Data. - - p: Preferred flag - a: Stateless IPv6 Address Autoconfiguration flag - d: DHCPv6 IPv6 Address Configuration flag - c: DHCPv6 Other Configuration flag - r: Default Route flag - o: On Mesh flag - s: Stable flag - prf: Default router preference, which may be 'high', 'med', or 'low'. - > prefix add 2001:dead:beef:cafe::/64 paros med - Done - - prefix remove - - Invalidate a prefix in the Network Data. - - > prefix remove 2001:dead:beef:cafe::/64 - Done - """ - params = line.split(" ") - stable = 0 - flags = 0 - arr = "" - - num = len(params) - if num > 1: - prefix = ipaddress.IPv6Interface(unicode(params[1])) - arr = prefix.ip.packed - - if num > 2: - map_param_to_flag = { - 'p': kThread.PrefixPreferredFlag, - 'a': kThread.PrefixSlaacFlag, - 'd': kThread.PrefixDhcpFlag, - 'c': kThread.PrefixConfigureFlag, - 'r': kThread.PrefixDefaultRouteFlag, - 'o': kThread.PrefixOnMeshFlag, - } - for char in params[2]: - if char == 's': - stable = 1 # Stable flag - else: - flag = map_param_to_flag.get(char, None) - if flag is not None: - flags |= flag - - if num > 3: - map_arg_name = { - "high": 2, - "med": 1, - "low": 0, - } - prf = map_arg_name[params[3]] - flags |= (prf << kThread.PrefixPreferenceOffset) - - if params[0] == "": - self.prop_get_value(SPINEL.PROP_THREAD_ON_MESH_NETS) - - elif params[0] == "add": - arr += self.wpan_api.encode_fields('CbC', - prefix.network.prefixlen, - stable, - flags) - - self.prop_set_value( - SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, 1) - self.prop_insert_value(SPINEL.PROP_THREAD_ON_MESH_NETS, - arr, str(len(arr)) + 's') - - elif params[0] == "remove": - arr += self.wpan_api.encode_fields('CbC', - prefix.network.prefixlen, - stable, - flags) - - self.prop_set_value( - SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, 1) - self.prop_remove_value(SPINEL.PROP_THREAD_ON_MESH_NETS, - arr, str(len(arr)) + 's') - - print("Done") - - def do_releaserouterid(self, line): - """ - releaserouterid - - Release a Router ID that has been allocated by the device in the Leader role. - - > releaserouterid 16 - Done - """ - if line: - value = int(line) - self.prop_remove_value(SPINEL.PROP_THREAD_ACTIVE_ROUTER_IDS, value) - print("Done") - - def do_rloc16(self, line): - """ - rloc16 - - Get the Thread RLOC16 value. - - > rloc16 - 0xdead - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_RLOC16, 'H') - - def complete_route(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for route command. """ - map_sub_commands = ('add', 'remove') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_route(self, line): - """ - route add [s] [prf] - - Add a valid prefix to the Network Data. - - s: Stable flag - prf: Default Router Preference, which may be: 'high', 'med', or 'low'. - - > route add 2001:dead:beef:cafe::/64 s med - Done - - route remove - - Invalidate a prefix in the Network Data. - - > route remove 2001:dead:beef:cafe::/64 - Done - """ - params = line.split(" ") - stable = 0 - prf = 0 - - num = len(params) - if num > 1: - prefix = ipaddress.IPv6Interface(unicode(params[1])) - arr = prefix.ip.packed - - if params[0] == "": - self.prop_get_value(SPINEL.PROP_THREAD_LOCAL_ROUTES) - - elif params[0] == "add": - arr += self.wpan_api.encode_fields('CbC', - prefix.network.prefixlen, - stable, - prf) - - self.prop_set_value( - SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, 1) - self.prop_insert_value(SPINEL.PROP_THREAD_LOCAL_ROUTES, - arr, str(len(arr)) + 's') - - elif params[0] == "remove": - self.prop_set_value( - SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, 1) - self.prop_remove_value(SPINEL.PROP_THREAD_LOCAL_ROUTES, - arr, str(len(arr)) + 's') - - print("Done") - - def do_router(self, line): - """ - router list - - List allocated Router IDs - - > router list - 8 24 50 - Done - - router - - Print diagnostic information for a Thread Router. - The id may be a Router ID or an RLOC16. - - > router 50 - Alloc: 1 - Router ID: 50 - Rloc: c800 - Next Hop: c800 - Link: 1 - Ext Addr: e2b3540590b0fd87 - Cost: 0 - LQI In: 3 - LQI Out: 3 - Age: 3 - Done - - > router 0xc800 - Alloc: 1 - Router ID: 50 - Rloc: c800 - Next Hop: c800 - Link: 1 - Ext Addr: e2b3540590b0fd87 - Cost: 0 - LQI In: 3 - LQI Out: 3 - Age: 7 - Done - """ - pass - - def do_routerselectionjitter(self, line): - """ - routerselectionjitter - - Get the ROUTER_SELECTION_JITTER value. - - > routerselectionjitter - 120 - Done - - routerselectionjitter - - Set the ROUTER_SELECTION_JITTER value. - - > routerselectionjitter 120 - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_ROUTER_SELECTION_JITTER) - - def do_routerupgradethreshold(self, line): - """ - routerupgradethreshold - - Get the ROUTER_UPGRADE_THRESHOLD value. - - > routerupgradethreshold - 16 - Done - - routerupgradethreshold - - Set the ROUTER_UPGRADE_THRESHOLD value. - - > routerupgradethreshold 16 - Done - """ - self.handle_property(line, SPINEL.PROP_THREAD_ROUTER_UPGRADE_THRESHOLD) - - def do_routerdowngradethreshold(self, line): - """ - routerdowngradethreshold - - Get the ROUTER_DOWNGRADE_THRESHOLD value. - - > routerdowngradethreshold - 16 - Done - - routerdowngradethreshold - - Set the ROUTER_DOWNGRADE_THRESHOLD value. - - > routerdowngradethreshold 16 - Done - """ - self.handle_property( - line, SPINEL.PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD) - - def do_scan(self, _line): - """ - scan [channel] - - Perform an IEEE 802.15.4 Active Scan. - - channel: The channel to scan on. If no channel is provided, - the active scan will cover all valid channels. - - > scan - | J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI | - +---+------------------+------------------+------+------------------+----+-----+-----+ - | 0 | OpenThread | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 | 0 | - Done - """ - # Initial mock-up of scan - self.handle_property("15", SPINEL.PROP_MAC_SCAN_MASK) - self.handle_property("4", SPINEL.PROP_MAC_SCAN_PERIOD, 'H') - self.handle_property("1", SPINEL.PROP_MAC_SCAN_STATE) - time.sleep(5) - self.handle_property("", SPINEL.PROP_MAC_SCAN_BEACON, 'U') - - def complete_thread(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for thread command. """ - map_sub_commands = ('start', 'stop') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_thread(self, line): - """ - thread start - - Enable Thread protocol operation and attach to a Thread network. - - > thread start - Done - - thread stop - - Disable Thread protocol operation and detach from a Thread network. - - > thread stop - Done - """ - map_arg_value = { - 0: "stop", - 1: "start", - 2: "start", - 3: "start", - } - - map_arg_name = { - "stop": "0", - "start": "2", - } - - if line: - try: - # remap string state names to integer - line = map_arg_name[line] - except: - print("Error") - return - - result = self.prop_get_or_set_value(SPINEL.PROP_NET_STACK_UP, line) - if result != None: - if not line: - print(map_arg_value[result]) - print("Done") - else: - print("Error") - - def do_state(self, line): - """ - state - """ - map_arg_value = { - 0: "detached", - 1: "child", - 2: "router", - 3: "leader", - } - - map_arg_name = { - "disabled": "0", - "detached": "0", - "child": "1", - "router": "2", - "leader": "3", - } - - if line: - try: - # remap string state names to integer - line = map_arg_name[line] - except: - print("Error") - return - - result = self.prop_get_or_set_value(SPINEL.PROP_NET_ROLE, line) - if result != None: - if not line: - state = map_arg_value[result] - # TODO: if state="disabled": get NET_STATE to determine - # whether "disabled" or "detached" - print(state) - print("Done") - else: - print("Error") - - def do_version(self, line): - """ - version - - Print the build version information. - - > version - OPENTHREAD/gf4f2f04; Jul 1 2016 17:00:09 - Done - """ - self.handle_property(line, SPINEL.PROP_NCP_VERSION, 'U') - - def complete_whitelist(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for whitelist command. """ - map_sub_commands = ('add', 'remove', 'clear', 'enable', 'disable') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_whitelist(self, line): - """ - whitelist - - List the whitelist entries. - - > whitelist - Enabled - e2b3540590b0fd87 - d38d7f875888fccb - c467a90a2060fa0e - Done - - whitelist add [rssi] - - Add an IEEE 802.15.4 Extended Address to the whitelist. - - > whitelist add dead00beef00cafe - Done - - whitelist clear - - Clear all entries from the whitelist. - - > whitelist clear - Done - - whitelist disable - - Disable MAC whitelist filtering. - - > whitelist disable - Done - - whitelist enable - - Enable MAC whitelist filtering. - - > whitelist enable - Done - - whitelist remove - - Remove an IEEE 802.15.4 Extended Address from the whitelist. - - > whitelist remove dead00beef00cafe - Done - """ - map_arg_value = { - 0: "Disabled", - 1: "Enabled", - } - - params = line.split(" ") - - if params[0] == "": - value = self.prop_get_value(SPINEL.PROP_MAC_WHITELIST_ENABLED) - if value != None: - print(map_arg_value[value]) - value = self.prop_get_value(SPINEL.PROP_MAC_WHITELIST) - - elif params[0] == "enable": - self.prop_set(SPINEL.PROP_MAC_WHITELIST_ENABLED, '1') - return - - elif params[0] == "disable": - self.prop_set(SPINEL.PROP_MAC_WHITELIST_ENABLED, '0') - return - - elif params[0] == "clear": - value = self.prop_set_value(SPINEL.PROP_MAC_WHITELIST, None, None) - - elif params[0] == "add": - arr = util.hex_to_bytes(params[1]) - try: - rssi = int(params[2]) - except: - rssi = SPINEL.RSSI_OVERRIDE - arr += struct.pack('b', rssi) - value = self.prop_insert_value(SPINEL.PROP_MAC_WHITELIST, arr, - str(len(arr)) + 's') - - elif params[0] == "remove": - arr = util.hex_to_bytes(params[1]) - arr += struct.pack('b', SPINEL.RSSI_OVERRIDE) - value = self.prop_remove_value(SPINEL.PROP_MAC_WHITELIST, arr, - str(len(arr)) + 's') - - print("Done") - - def do_ncpll64(self, line): - """ Display the link local IPv6 address. """ - self.handle_property(line, SPINEL.PROP_IPV6_LL_ADDR, '6') - - def do_ncpml64(self, line): - """ Display the mesh local IPv6 address. """ - self.handle_property(line, SPINEL.PROP_IPV6_ML_ADDR, '6') - - def do_ncpraw(self, line): - """ Enable MAC raw stream. """ - self.handle_property(line, SPINEL.PROP_MAC_RAW_STREAM_ENABLED, 'B') - - def do_ncpfilter(self, line): - """ - Set MAC filter mode: - - 0 = MAC_FILTER_MODE_NORMAL Normal MAC filtering is in place. - 1 = MAC_FILTER_MODE_PROMISCUOUS All MAC packets matching network are passed up the stack. - 2 = MAC_FILTER_MODE_MONITOR All decoded MAC packets are passed up the stack. - """ - self.handle_property(line, SPINEL.PROP_MAC_FILTER_MODE, 'B') - - def complete_ncptun(self, text, _line, _begidx, _endidx): - """ Subcommand completion handler for ncp-tun command. """ - map_sub_commands = ('up', 'down', 'add', 'remove', 'ping') - return [i for i in map_sub_commands if i.startswith(text)] - - def do_ncptun(self, line): - """ - ncp-tun - - Control sideband tunnel interface. - - ncp-tun up - - Bring up Thread TUN interface. - - > ncp-tun up - Done - - ncp-tun down - - Bring down Thread TUN interface. - - > ncp-tun down - Done - - ncp-tun add - - Add an IPv6 address to the Thread TUN interface. - - > ncp-tun add 2001::dead:beef:cafe - Done - - ncp-tun del - - Delete an IPv6 address from the Thread TUN interface. - - > ncp-tun del 2001::dead:beef:cafe - Done - - ncp-tun ping [size] [count] [interval] - - Send an ICMPv6 Echo Request. - - > ncp-tun ping fdde:ad00:beef:0:558:f56b:d688:799 - 16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms - """ - params = line.split(" ") - - num = len(params) - if num > 1: - ipaddr = params[1] - prefix = ipaddress.IPv6Interface(unicode(ipaddr)) - _arr = prefix.ip.packed - - if params[0] == "": - pass - - elif params[0] == "add": - if self.tun_if: - self.tun_if.addr_add(ipaddr) - - elif params[0] == "remove": - if self.tun_if: - self.tun_if.addr_del(ipaddr) - - elif params[0] == "up": - if os.geteuid() == 0: - self.tun_if = TunInterface(nodeid) - else: - print("Warning: superuser required to start tun interface.") - - elif params[0] == "down": - if self.tun_if: - self.tun_if.close() - self.tun_if = None - - elif params[0] == "ping": - # Use tunnel to send ping - size = "56" - count = "1" - _interval = "1" - if len(params) > 1: - size = params[1] - if len(params) > 2: - count = params[2] - if len(params) > 3: - _interval = params[3] - - if self.tun_if: - self.tun_if.ping6( - " -c " + count + " -s " + size + " " + ipaddr) - - print("Done") - - def do_diag(self, line): - """ - diag - - Show diagnostics mode status. - - > diag - diagnostics mode is disabled - """ - pass - - def do_diagstart(self, line): - """ - diag-start - - Start diagnostics mode. - - > diag-start - start diagnostics mode - status 0x00 - """ - pass - - def do_diagchannel(self, line): - """ - diag-channel - - Get the IEEE 802.15.4 Channel value for diagnostics module. - - > diag-channel - channel: 11 - - diag-channel - - Set the IEEE 802.15.4 Channel value for diagnostics module. - - > diag-channel 11 - set channel to 11 - status 0x00 - """ - pass - - def do_diagpower(self, line): - """ - diag-power - - Get the tx power value(dBm) for diagnostics module. - - > diag-power - tx power: -10 dBm - - diag-power - - Set the tx power value(dBm) for diagnostics module. - - > diag-power -10 - set tx power to -10 dBm - status 0x00 - """ - pass - - def do_diagsend(self, line): - """ - diag-send - - Transmit a fixed number of packets with fixed length. - - > diag-send 20 100 - sending 0x14 packet(s), length 0x64 - status 0x00 - """ - pass - - def do_diagrepeat(self, line): - """ - diag-repeat - - Transmit packets repeatedly with a fixed interval. - - > diag repeat 100 100 - sending packets of length 0x64 at the delay of 0x64 ms - status 0x00 - - diag-repeat stop - - Stop repeated packet transmission. - - > diag-repeat stop - repeated packet transmission is stopped - status 0x00 - """ - pass - - def do_diagsleep(self, line): - """ - diag-sleep - - Enter radio sleep mode. - - > diag-sleep - sleeping now... - """ - pass - - def do_diagstats(self, line): - """ - diag-stats - - Print statistics during diagnostics mode. - - > diag-stats - received packets: 10 - sent packets: 10 - first received packet: rssi=-65, lqi=101 - """ - pass - - def do_diagstop(self, line): - """ - diag stop - - Stop diagnostics mode and print statistics. - - > diag-stop - received packets: 10 - sent packets: 10 - first received packet: rssi=-65, lqi=101 - - stop diagnostics mode - status 0x00 - """ - pass - -def parse_args(): - """" Send spinel commands to initialize sniffer node. """ - args = sys.argv[1:] - - opt_parser = optparse.OptionParser(usage=optparse.SUPPRESS_USAGE) - opt_parser.add_option("-u", "--uart", action="store", - dest="uart", type="string") - opt_parser.add_option("-p", "--pipe", action="store", - dest="pipe", type="string") - opt_parser.add_option("-s", "--socket", action="store", - dest="socket", type="string") - opt_parser.add_option("-n", "--nodeid", action="store", - dest="nodeid", type="string", default="1") - opt_parser.add_option("-q", "--quiet", action="store_true", dest="quiet") - opt_parser.add_option( - "-v", "--verbose", action="store_false", dest="verbose") - opt_parser.add_option("-d", "--debug", action="store", - dest="debug", type="int", default=CONFIG.DEBUG_ENABLE) - - return opt_parser.parse_args(args) - -def main(): - """ Top-level main for spinel-cli tool. """ - (options, remaining_args) = parse_args() - - if options.debug: - CONFIG.debug_set_level(options.debug) - - # Set default stream to pipe - stream_type = 'p' - stream_descriptor = "../../examples/apps/ncp/ot-ncp-ftd " + options.nodeid - - if options.uart: - stream_type = 'u' - stream_descriptor = options.uart - elif options.socket: - stream_type = 's' - stream_descriptor = options.socket - elif options.pipe: - stream_type = 'p' - stream_descriptor = options.pipe - if options.nodeid: - stream_descriptor += " " + str(options.nodeid) - else: - if len(remaining_args) > 0: - stream_descriptor = " ".join(remaining_args) - - stream = StreamOpen(stream_type, stream_descriptor) - shell = SpinelCliCmd(stream, nodeid=options.nodeid) - - try: - shell.cmdloop() - except KeyboardInterrupt: - logging.info('\nCTRL+C Pressed') - - if shell.wpan_api: - shell.wpan_api.stream.close() - -if __name__ == "__main__": - main() diff --git a/tools/spinel-cli/spinel/Makefile.am b/tools/spinel-cli/spinel/Makefile.am deleted file mode 100644 index 221ef1853..000000000 --- a/tools/spinel-cli/spinel/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - -include $(abs_top_nlbuild_autotools_dir)/automake/pre.am - -EXTRA_DIST = \ - __init__.py \ - codec.py \ - config.py \ - const.py \ - hdlc.py \ - stream.py \ - pcap.py \ - tun.py \ - util.py \ - $(NULL) - -EXTRA_DIST += \ - tests.py \ - test_codec.py \ - test_hdlc.py \ - test_stream.py \ - test_sniffer.py \ - $(NULL) - -include $(abs_top_nlbuild_autotools_dir)/automake/post.am diff --git a/tools/spinel-cli/spinel/__init__.py b/tools/spinel-cli/spinel/__init__.py deleted file mode 100644 index a573b7b67..000000000 --- a/tools/spinel-cli/spinel/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# diff --git a/tools/spinel-cli/spinel/codec.py b/tools/spinel-cli/spinel/codec.py deleted file mode 100644 index 64822ef2f..000000000 --- a/tools/spinel-cli/spinel/codec.py +++ /dev/null @@ -1,1121 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" -Module providing a Spienl coder / decoder class. -""" - -from __future__ import print_function - -import os -import sys -import time -import logging -import threading -import traceback - -is_py2 = sys.version[0] == '2' -if is_py2: - import Queue as Queue -else: - import queue as Queue - -from struct import pack -from struct import unpack -from collections import namedtuple -from collections import defaultdict - -import ipaddress - -import spinel.util as util -import spinel.config as CONFIG -from spinel.const import kThread -from spinel.const import SPINEL -from spinel.const import SPINEL_LAST_STATUS_MAP -from spinel.hdlc import Hdlc - - - -FEATURE_USE_HDLC = 1 -FEATURE_USE_SLACC = 1 - -TIMEOUT_PROP = 2 - -#========================================= -# SpinelCodec -#========================================= - -# 0: DATATYPE_NULL -#'.': DATATYPE_VOID: Empty data type. Used internally. -#'b': DATATYPE_BOOL: Boolean value. Encoded in 8-bits as either 0x00 or 0x01. -# All other values are illegal. -#'C': DATATYPE_UINT8: Unsigned 8-bit integer. -#'c': DATATYPE_INT8: Signed 8-bit integer. -#'S': DATATYPE_UINT16: Unsigned 16-bit integer. (Little-endian) -#'s': DATATYPE_INT16: Signed 16-bit integer. (Little-endian) -#'L': DATATYPE_UINT32: Unsigned 32-bit integer. (Little-endian) -#'l': DATATYPE_INT32: Signed 32-bit integer. (Little-endian) -#'i': DATATYPE_UINT_PACKED: Packed Unsigned Integer. (See section 7.2) -#'6': DATATYPE_IPv6ADDR: IPv6 Address. (Big-endian) -#'E': DATATYPE_EUI64: EUI-64 Address. (Big-endian) -#'e': DATATYPE_EUI48: EUI-48 Address. (Big-endian) -#'D': DATATYPE_DATA: Arbitrary Data. (See section 7.3) -#'d': DATATYPE_DATA_WLEN: Arbitrary Data with Prepended Length. (See section 7.3) -#'U': DATATYPE_UTF8: Zero-terminated UTF8-encoded string. -#'t': DATATYPE_STRUCT: Structured datatype. Compound type. Length prepended. (See section 7.4) -#'A': DATATYPE_ARRAY: Array of datatypes. Compound type. (See section 7.5) - - -class SpinelCodec(object): - """ A general coder / decoder class for Spinel protocol. """ - - @classmethod - def parse_b(cls, payload): return unpack(" 0 and idx < len(spinel_format)-1: - idx += 1 - if spinel_format[idx] == ')': - count -= 1 - elif spinel_format[idx] == '(': - count += 1 - if count != 0: - raise ValueError('Unbalanced parenthesis in format string "' + spinel_format + '", idx=' + idx) - return idx; - - - @classmethod - def parse_field(cls, payload, spinel_format): - map_decode = { - 'b': cls.parse_b, - 'c': cls.parse_c, - 'C': cls.parse_C, - 's': cls.parse_s, - 'S': cls.parse_S, - 'L': cls.parse_L, - 'l': cls.parse_l, - '6': cls.parse_6, - 'E': cls.parse_E, - 'e': cls.parse_e, - 'U': cls.parse_U, - 'D': cls.parse_D, - 'd': cls.parse_d, - 'i': cls.parse_i, - } - try: - return map_decode[spinel_format[0]](payload) - except KeyError: - print(traceback.format_exc()) - return None - - @classmethod - def get_payload_size(cls, payload, spinel_format): - map_lengths = { - 'b': 1, - 'c': 1, - 'C': 1, - 's': 2, - 'S': 2, - 'l': 4, - 'L': 4, - '6': 16, - 'E': 8, - 'e': 6, - } - - result = 0 - - idx = 0 - while idx < len(spinel_format): - format = spinel_format[idx] - - if format == 't': - if spinel_format[idx+1] != '(': - raise ValueError('Invalid structure format') - - struct_end = cls.index_of_ending_brace(spinel_format, idx + 1); - - result += 2 + cls.parse_S(payload[result:]); - idx = struct_end + 1 - - elif format == 'd': - result += 2 + cls.parse_S(payload[result:]); - idx += 1 - - elif format == 'D' or format == 'A': - if idx != len(spinel_format) - 1: - raise ValueError('Invalid type syntax for "' + format + '", must go at end of format string') - result = len(payload); - idx += 1 - - elif format == 'U': - result += payload[result:].index(0) + 1; - idx += 1 - - elif format == 'i': - result += cls.parse_i_len(payload[result:]) - idx += 1 - - else: - result += map_lengths[format] - idx += 1 - - return result - - @classmethod - def parse_fields(cls, payload, spinel_format): - result = [] - - idx = 0 - while idx < len(spinel_format): - format = spinel_format[idx] - - if format == 'A': - if spinel_format[idx+1] != '(': - raise ValueError('Invalid structure format') - - array_end = cls.index_of_ending_brace(spinel_format, idx + 1); - - array_format = spinel_format[idx+2:array_end] - - array = [] - while len(payload): - array.append(cls.parse_fields(payload, array_format)) - payload = payload[cls.get_payload_size(payload, array_format):] - - result.append(tuple(array)) - idx = array_end + 1 - - elif format == 't': - if spinel_format[idx+1] != '(': - raise ValueError('Invalid structure format') - - struct_end = cls.index_of_ending_brace(spinel_format, idx + 1); - - struct_format = spinel_format[idx+2:struct_end] - struct_len = cls.parse_S(payload); - - result.append(cls.parse_fields(payload[2:struct_len+2], struct_format)) - payload = payload[struct_len+2:] - - idx = struct_end + 1 - - else: - result.append(cls.parse_field(payload, format)) - payload = payload[cls.get_payload_size(payload, format):] - - idx += 1 - - return tuple(result) - - @classmethod - def encode_i(cls, data): - """ Encode EXI integer format. """ - result = "" - while data: - value = data & 0x7F - data >>= 7 - if data: - value |= 0x80 - result = result + pack("B", tid) - cmd = self.encode_i(command_id) - pkt = header + cmd + payload - return pkt - - -#========================================= - -class SpinelPropertyHandler(SpinelCodec): - - def LAST_STATUS(self, _, payload): return self.parse_i(payload)[0] - - def PROTOCOL_VERSION(self, _wpan_api, payload): pass - - def NCP_VERSION(self, _, payload): return self.parse_U(payload) - - def INTERFACE_TYPE(self, _, payload): return self.parse_i(payload)[0] - - def VENDOR_ID(self, _, payload): return self.parse_i(payload)[0] - - def CAPS(self, _wpan_api, payload): pass - - def INTERFACE_COUNT(self, _, payload): return self.parse_C(payload) - - def POWER_STATE(self, _, payload): return self.parse_C(payload) - - def HWADDR(self, _, payload): return self.parse_E(payload) - - def LOCK(self, _, payload): return self.parse_b(payload) - - def HBO_MEM_MAX(self, _, payload): return self.parse_L(payload) - - def HBO_BLOCK_MAX(self, _, payload): return self.parse_S(payload) - - def PHY_ENABLED(self, _, payload): return self.parse_b(payload) - - def PHY_CHAN(self, _, payload): return self.parse_C(payload) - - def PHY_CHAN_SUPPORTED(self, _wpan_api, payload): pass - - def PHY_FREQ(self, _, payload): return self.parse_L(payload) - - def PHY_CCA_THRESHOLD(self, _, payload): return self.parse_c(payload) - - def PHY_TX_POWER(self, _, payload): return self.parse_c(payload) - - def PHY_RSSI(self, _, payload): return self.parse_c(payload) - - def MAC_SCAN_STATE(self, _, payload): return self.parse_C(payload) - - def MAC_SCAN_MASK(self, _, payload): return self.parse_U(payload) - - def MAC_SCAN_PERIOD(self, _, payload): return self.parse_S(payload) - - def MAC_SCAN_BEACON(self, _, payload): return self.parse_U(payload) - - def MAC_15_4_LADDR(self, _, payload): return self.parse_E(payload) - - def MAC_15_4_SADDR(self, _, payload): return self.parse_S(payload) - - def MAC_15_4_PANID(self, _, payload): return self.parse_S(payload) - - def MAC_FILTER_MODE(self, _, payload): return self.parse_C(payload) - - def MAC_RAW_STREAM_ENABLED(self, _, payload): - return self.parse_b(payload) - - def MAC_WHITELIST(self, _, payload): pass - - def MAC_WHITELIST_ENABLED(self, _, payload): - return self.parse_b(payload) - - def NET_SAVED(self, _, payload): return self.parse_b(payload) - - def NET_IF_UP(self, _, payload): return self.parse_b(payload) - - def NET_STACK_UP(self, _, payload): return self.parse_C(payload) - - def NET_ROLE(self, _, payload): return self.parse_C(payload) - - def NET_NETWORK_NAME(self, _, payload): return self.parse_U(payload) - - def NET_XPANID(self, _, payload): return self.parse_D(payload) - - def NET_MASTER_KEY(self, _, payload): return self.parse_D(payload) - - def NET_KEY_SEQUENCE_COUNTER(self, _, payload): return self.parse_L(payload) - - def NET_PARTITION_ID(self, _, payload): return self.parse_L(payload) - - def NET_KEY_SWITCH_GUARDTIME(self, _, payload): return self.parse_L(payload) - - def THREAD_LEADER_ADDR(self, _, payload): return self.parse_6(payload) - - def THREAD_PARENT(self, _wpan_api, payload): return self.parse_fields(payload, "ES") - - def THREAD_CHILD_TABLE(self, _, payload): return self.parse_fields(payload, "A(t(ESLLCCcC))") - - def THREAD_LEADER_RID(self, _, payload): return self.parse_C(payload) - - def THREAD_LEADER_WEIGHT(self, _, payload): - return self.parse_C(payload) - - def THREAD_LOCAL_LEADER_WEIGHT(self, _, payload): - return self.parse_C(payload) - - def THREAD_NETWORK_DATA(self, _, payload): - return self.parse_D(payload) - - def THREAD_NETWORK_DATA_VERSION(self, _wpan_api, payload): - return self.parse_C(payload) - - def THREAD_STABLE_NETWORK_DATA(self, _wpan_api, payload): pass - - def THREAD_STABLE_NETWORK_DATA_VERSION(self, _wpan_api, payload): - return self.parse_C(payload) - - def __init__(self): - self.autoAddresses = set() - - self.wpan_api = None - self.__queue_prefix = Queue.Queue() - self.prefix_thread = threading.Thread(target=self.__run_prefix_handler) - self.prefix_thread.setDaemon(True) - self.prefix_thread.start() - - def handle_ipaddr_remove(self, ipaddr): - valid = 1 - preferred = 1 - flags = 0 - prefix_len = 64 # always use /64 - - arr = self.encode_fields('6CLLC', - ipaddr.ip.packed, - prefix_len, - valid, - preferred, - flags) - - self.wpan_api.prop_remove_async(SPINEL.PROP_IPV6_ADDRESS_TABLE, - arr, str(len(arr)) + 's', - SPINEL.HEADER_EVENT_HANDLER) - - def handle_ipaddr_insert(self, prefix, prefix_len, _stable, flags, _is_local): - """ Add an ip address for each prefix on prefix change. """ - - ipaddr_str = str(ipaddress.IPv6Address(prefix)) + \ - str(self.wpan_api.nodeid) - if CONFIG.DEBUG_LOG_PROP: - print("\n>>>> new PREFIX add ipaddr: " + ipaddr_str) - - valid = 1 - preferred = 1 - flags = 0 - ipaddr = ipaddress.IPv6Interface(unicode(ipaddr_str)) - self.autoAddresses.add(ipaddr) - - arr = self.encode_fields('6CLLC', - ipaddr.ip.packed, - prefix_len, - valid, - preferred, - flags) - - self.wpan_api.prop_insert_async(SPINEL.PROP_IPV6_ADDRESS_TABLE, - arr, str(len(arr)) + 's', - SPINEL.HEADER_EVENT_HANDLER) - - def handle_prefix_change(self, payload): - """ Automatically ipaddr add / remove addresses for each new prefix. """ - # As done by cli.cpp Interpreter::HandleNetifStateChanged - - # First parse payload and extract slaac prefix information. - pay = payload - Prefix = namedtuple("Prefix", "prefix prefixlen stable flags is_local") - prefixes = [] - slaacPrefixSet = set() - while len(pay) >= 22: - (_structlen) = unpack(' ipaddrs - query current addresses - # - # for ipaddr in ipaddrs: - # if lifetime > 0 and not in slaac prefixes - # ==> remove - for ipaddr in self.autoAddresses: - if not any(ipaddr in prefix for prefix in slaacPrefixSet): - self.handle_ipaddr_remove(ipaddr) - - # for slaac prefix in prefixes: - # if no ipaddr with lifetime > 0 in prefix: - # ==> add - - def __run_prefix_handler(self): - while 1: - (wpan_api, payload) = self.__queue_prefix.get(True) - self.wpan_api = wpan_api - self.handle_prefix_change(payload) - self.__queue_prefix.task_done() - - def THREAD_ON_MESH_NETS(self, wpan_api, payload): - if FEATURE_USE_SLACC: - # Kick prefix handler thread to allow serial rx thread to work. - self.__queue_prefix.put_nowait((wpan_api, payload)) - - return self.parse_D(payload) - - def THREAD_LOCAL_ROUTES(self, _wpan_api, payload): pass - - def THREAD_ASSISTING_PORTS(self, _wpan_api, payload): pass - - def THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(self, _, payload): - return self.parse_b(payload) - - def THREAD_MODE(self, _, payload): return self.parse_C(payload) - - def THREAD_CHILD_COUNT_MAX(self, _, payload): return self.parse_C(payload) - - def THREAD_CHILD_TIMEOUT(self, _, payload): return self.parse_L(payload) - - def THREAD_RLOC16(self, _, payload): return self.parse_S(payload) - - def THREAD_ROUTER_UPGRADE_THRESHOLD(self, _, payload): - return self.parse_C(payload) - - def THREAD_ROUTER_DOWNGRADE_THRESHOLD(self, _, payload): - return self.parse_C(payload) - - def THREAD_ROUTER_SELECTION_JITTER(self, _, payload): - return self.parse_C(payload) - - def THREAD_NEIGHBOR_TABLE(self, _, payload): - return self.parse_fields(payload, 'A(t(ESLCcCbLL))') - - def THREAD_CONTEXT_REUSE_DELAY(self, _, payload): - return self.parse_L(payload) - - def THREAD_NETWORK_ID_TIMEOUT(self, _, payload): - return self.parse_C(payload) - - def THREAD_ACTIVE_ROUTER_IDS(self, _, payload): - return self.parse_D(payload) - - def THREAD_RLOC16_DEBUG_PASSTHRU(self, _, payload): - return self.parse_b(payload) - - def MESHCOP_JOINER_ENABLE(self, _, payload): - return self.parse_b(payload) - - def MESHCOP_JOINER_CREDENTIAL(self, _, payload): - return self.parse_D(payload) - - def MESHCOP_JOINER_URL(self, _, payload): - return self.parse_U(payload) - - def MESHCOP_BORDER_AGENT_ENABLE(self, _, payload): - return self.parse_b(payload) - - def IPV6_LL_ADDR(self, _, payload): return self.parse_6(payload) - - def IPV6_ML_ADDR(self, _, payload): return self.parse_6(payload) - - def IPV6_ML_PREFIX(self, _, payload): return self.parse_E(payload) - - def IPV6_ADDRESS_TABLE(self, _, payload): return self.parse_D(payload) - - def IPV6_ROUTE_TABLE(self, _, payload): return self.parse_D(payload) - - def IPv6_ICMP_PING_OFFLOAD(self, _, payload): - return self.parse_b(payload) - - def STREAM_DEBUG(self, _, payload): return self.parse_D(payload) - - def STREAM_RAW(self, _, payload): return self.parse_D(payload) - - def STREAM_NET(self, _, payload): return self.parse_D(payload) - - def STREAM_NET_INSECURE(self, _, payload): return self.parse_D(payload) - - def PIB_PHY_CHANNELS_SUPPORTED(self, _wpan_api, payload): pass - - def PIB_MAC_PROMISCUOUS_MODE(self, _wpan_api, payload): pass - - def PIB_MAC_SECURITY_ENABLED(self, _wpan_api, payload): pass - - def MSG_BUFFER_COUNTERS(self, _wpan_api, payload): return self.parse_fields(payload, "SSSSSSSSSSSSSSSS") - -#========================================= - - -class SpinelCommandHandler(SpinelCodec): - - def handle_prop(self, wpan_api, name, payload, tid): - (prop_id, prop_len) = self.parse_i(payload) - - if prop_id in SPINEL_PROP_DISPATCH: - handler = SPINEL_PROP_DISPATCH[prop_id] - prop_name = handler.__name__ - prop_value = handler(wpan_api, payload[prop_len:]) - - if CONFIG.DEBUG_LOG_PROP: - - # Generic output - if isinstance(prop_value, basestring): - prop_value_str = util.hexify_str(prop_value) - logging.debug("PROP_VALUE_%s [tid=%d]: %s = %s", - name, (tid & 0xF), prop_name, prop_value_str) - else: - prop_value_str = str(prop_value) - - logging.debug("PROP_VALUE_%s [tid=%d]: %s = %s", - name, (tid & 0xF), prop_name, prop_value_str) - - # Extend output for certain properties. - if prop_id == SPINEL.PROP_LAST_STATUS: - logging.debug(SPINEL_LAST_STATUS_MAP[prop_value]) - - if CONFIG.DEBUG_LOG_PKT: - if ((prop_id == SPINEL.PROP_STREAM_NET) or - (prop_id == SPINEL.PROP_STREAM_NET_INSECURE)): - logging.debug("PROP_VALUE_" + name + ": " + prop_name) - - elif prop_id == SPINEL.PROP_STREAM_DEBUG: - logging.debug("DEBUG: " + prop_value) - - if wpan_api: - wpan_api.queue_add(prop_id, prop_value, tid) - else: - print("no wpan_api") - else: - prop_name = "Property Unknown" - logging.info("\n%s (%i): ", prop_name, prop_id) - - def PROP_VALUE_IS(self, wpan_api, payload, tid): - self.handle_prop(wpan_api, "IS", payload, tid) - - def PROP_VALUE_INSERTED(self, wpan_api, payload, tid): - self.handle_prop(wpan_api, "INSERTED", payload, tid) - - def PROP_VALUE_REMOVED(self, wpan_api, payload, tid): - self.handle_prop(wpan_api, "REMOVED", payload, tid) - - -WPAN_CMD_HANDLER = SpinelCommandHandler() - -SPINEL_COMMAND_DISPATCH = { - SPINEL.RSP_PROP_VALUE_IS: WPAN_CMD_HANDLER.PROP_VALUE_IS, - SPINEL.RSP_PROP_VALUE_INSERTED: WPAN_CMD_HANDLER.PROP_VALUE_INSERTED, - SPINEL.RSP_PROP_VALUE_REMOVED: WPAN_CMD_HANDLER.PROP_VALUE_REMOVED, -} - -WPAN_PROP_HANDLER = SpinelPropertyHandler() - -SPINEL_PROP_DISPATCH = { - SPINEL.PROP_LAST_STATUS: WPAN_PROP_HANDLER.LAST_STATUS, - SPINEL.PROP_PROTOCOL_VERSION: WPAN_PROP_HANDLER.PROTOCOL_VERSION, - SPINEL.PROP_NCP_VERSION: WPAN_PROP_HANDLER.NCP_VERSION, - SPINEL.PROP_INTERFACE_TYPE: WPAN_PROP_HANDLER.INTERFACE_TYPE, - SPINEL.PROP_VENDOR_ID: WPAN_PROP_HANDLER.VENDOR_ID, - SPINEL.PROP_CAPS: WPAN_PROP_HANDLER.CAPS, - SPINEL.PROP_INTERFACE_COUNT: WPAN_PROP_HANDLER.INTERFACE_COUNT, - SPINEL.PROP_POWER_STATE: WPAN_PROP_HANDLER.POWER_STATE, - SPINEL.PROP_HWADDR: WPAN_PROP_HANDLER.HWADDR, - SPINEL.PROP_LOCK: WPAN_PROP_HANDLER.LOCK, - SPINEL.PROP_HBO_MEM_MAX: WPAN_PROP_HANDLER.HBO_MEM_MAX, - SPINEL.PROP_HBO_BLOCK_MAX: WPAN_PROP_HANDLER.HBO_BLOCK_MAX, - - SPINEL.PROP_PHY_ENABLED: WPAN_PROP_HANDLER.PHY_ENABLED, - SPINEL.PROP_PHY_CHAN: WPAN_PROP_HANDLER.PHY_CHAN, - SPINEL.PROP_PHY_CHAN_SUPPORTED: WPAN_PROP_HANDLER.PHY_CHAN_SUPPORTED, - SPINEL.PROP_PHY_FREQ: WPAN_PROP_HANDLER.PHY_FREQ, - SPINEL.PROP_PHY_CCA_THRESHOLD: WPAN_PROP_HANDLER.PHY_CCA_THRESHOLD, - SPINEL.PROP_PHY_TX_POWER: WPAN_PROP_HANDLER.PHY_TX_POWER, - SPINEL.PROP_PHY_RSSI: WPAN_PROP_HANDLER.PHY_RSSI, - - SPINEL.PROP_MAC_SCAN_STATE: WPAN_PROP_HANDLER.MAC_SCAN_STATE, - SPINEL.PROP_MAC_SCAN_MASK: WPAN_PROP_HANDLER.MAC_SCAN_MASK, - SPINEL.PROP_MAC_SCAN_PERIOD: WPAN_PROP_HANDLER.MAC_SCAN_PERIOD, - SPINEL.PROP_MAC_SCAN_BEACON: WPAN_PROP_HANDLER.MAC_SCAN_BEACON, - SPINEL.PROP_MAC_15_4_LADDR: WPAN_PROP_HANDLER.MAC_15_4_LADDR, - SPINEL.PROP_MAC_15_4_SADDR: WPAN_PROP_HANDLER.MAC_15_4_SADDR, - SPINEL.PROP_MAC_15_4_PANID: WPAN_PROP_HANDLER.MAC_15_4_PANID, - SPINEL.PROP_MAC_RAW_STREAM_ENABLED: WPAN_PROP_HANDLER.MAC_RAW_STREAM_ENABLED, - SPINEL.PROP_MAC_FILTER_MODE: WPAN_PROP_HANDLER.MAC_FILTER_MODE, - - SPINEL.PROP_MAC_WHITELIST: WPAN_PROP_HANDLER.MAC_WHITELIST, - SPINEL.PROP_MAC_WHITELIST_ENABLED: WPAN_PROP_HANDLER.MAC_WHITELIST_ENABLED, - - SPINEL.PROP_NET_SAVED: WPAN_PROP_HANDLER.NET_SAVED, - SPINEL.PROP_NET_IF_UP: WPAN_PROP_HANDLER.NET_IF_UP, - SPINEL.PROP_NET_STACK_UP: WPAN_PROP_HANDLER.NET_STACK_UP, - SPINEL.PROP_NET_ROLE: WPAN_PROP_HANDLER.NET_ROLE, - SPINEL.PROP_NET_NETWORK_NAME: WPAN_PROP_HANDLER.NET_NETWORK_NAME, - SPINEL.PROP_NET_XPANID: WPAN_PROP_HANDLER.NET_XPANID, - SPINEL.PROP_NET_MASTER_KEY: WPAN_PROP_HANDLER.NET_MASTER_KEY, - SPINEL.PROP_NET_KEY_SEQUENCE_COUNTER: WPAN_PROP_HANDLER.NET_KEY_SEQUENCE_COUNTER, - SPINEL.PROP_NET_PARTITION_ID: WPAN_PROP_HANDLER.NET_PARTITION_ID, - SPINEL.PROP_NET_KEY_SWITCH_GUARDTIME: WPAN_PROP_HANDLER.NET_KEY_SWITCH_GUARDTIME, - - SPINEL.PROP_THREAD_LEADER_ADDR: WPAN_PROP_HANDLER.THREAD_LEADER_ADDR, - SPINEL.PROP_THREAD_PARENT: WPAN_PROP_HANDLER.THREAD_PARENT, - SPINEL.PROP_THREAD_CHILD_TABLE: WPAN_PROP_HANDLER.THREAD_CHILD_TABLE, - SPINEL.PROP_THREAD_LEADER_RID: WPAN_PROP_HANDLER.THREAD_LEADER_RID, - SPINEL.PROP_THREAD_LEADER_WEIGHT: WPAN_PROP_HANDLER.THREAD_LEADER_WEIGHT, - SPINEL.PROP_THREAD_LOCAL_LEADER_WEIGHT: WPAN_PROP_HANDLER.THREAD_LOCAL_LEADER_WEIGHT, - SPINEL.PROP_THREAD_NETWORK_DATA: WPAN_PROP_HANDLER.THREAD_NETWORK_DATA, - SPINEL.PROP_THREAD_NETWORK_DATA_VERSION: WPAN_PROP_HANDLER.THREAD_NETWORK_DATA_VERSION, - SPINEL.PROP_THREAD_STABLE_NETWORK_DATA: WPAN_PROP_HANDLER.THREAD_STABLE_NETWORK_DATA, - SPINEL.PROP_THREAD_STABLE_NETWORK_DATA_VERSION: - WPAN_PROP_HANDLER.THREAD_STABLE_NETWORK_DATA_VERSION, - SPINEL.PROP_THREAD_ON_MESH_NETS: WPAN_PROP_HANDLER.THREAD_ON_MESH_NETS, - SPINEL.PROP_THREAD_LOCAL_ROUTES: WPAN_PROP_HANDLER.THREAD_LOCAL_ROUTES, - SPINEL.PROP_THREAD_ASSISTING_PORTS: WPAN_PROP_HANDLER.THREAD_ASSISTING_PORTS, - SPINEL.PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE: - WPAN_PROP_HANDLER.THREAD_ALLOW_LOCAL_NET_DATA_CHANGE, - SPINEL.PROP_THREAD_MODE: WPAN_PROP_HANDLER.THREAD_MODE, - SPINEL.PROP_THREAD_CHILD_COUNT_MAX: WPAN_PROP_HANDLER.THREAD_CHILD_COUNT_MAX, - SPINEL.PROP_THREAD_CHILD_TIMEOUT: WPAN_PROP_HANDLER.THREAD_CHILD_TIMEOUT, - SPINEL.PROP_THREAD_RLOC16: WPAN_PROP_HANDLER.THREAD_RLOC16, - SPINEL.PROP_THREAD_ROUTER_UPGRADE_THRESHOLD: WPAN_PROP_HANDLER.THREAD_ROUTER_UPGRADE_THRESHOLD, - SPINEL.PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD: - WPAN_PROP_HANDLER.THREAD_ROUTER_DOWNGRADE_THRESHOLD, - SPINEL.PROP_THREAD_ROUTER_SELECTION_JITTER: WPAN_PROP_HANDLER.THREAD_ROUTER_SELECTION_JITTER, - SPINEL.PROP_THREAD_CONTEXT_REUSE_DELAY: WPAN_PROP_HANDLER.THREAD_CONTEXT_REUSE_DELAY, - SPINEL.PROP_THREAD_NETWORK_ID_TIMEOUT: WPAN_PROP_HANDLER.THREAD_NETWORK_ID_TIMEOUT, - SPINEL.PROP_THREAD_ACTIVE_ROUTER_IDS: WPAN_PROP_HANDLER.THREAD_ACTIVE_ROUTER_IDS, - SPINEL.PROP_THREAD_RLOC16_DEBUG_PASSTHRU: WPAN_PROP_HANDLER.THREAD_RLOC16_DEBUG_PASSTHRU, - SPINEL.PROP_THREAD_NEIGHBOR_TABLE: WPAN_PROP_HANDLER.THREAD_NEIGHBOR_TABLE, - - SPINEL.PROP_MESHCOP_JOINER_ENABLE: WPAN_PROP_HANDLER.MESHCOP_JOINER_ENABLE, - SPINEL.PROP_MESHCOP_JOINER_CREDENTIAL: WPAN_PROP_HANDLER.MESHCOP_JOINER_CREDENTIAL, - SPINEL.PROP_MESHCOP_JOINER_URL: WPAN_PROP_HANDLER.MESHCOP_JOINER_URL, - SPINEL.PROP_MESHCOP_BORDER_AGENT_ENABLE: WPAN_PROP_HANDLER.MESHCOP_BORDER_AGENT_ENABLE, - - - SPINEL.PROP_IPV6_LL_ADDR: WPAN_PROP_HANDLER.IPV6_LL_ADDR, - SPINEL.PROP_IPV6_ML_ADDR: WPAN_PROP_HANDLER.IPV6_ML_ADDR, - SPINEL.PROP_IPV6_ML_PREFIX: WPAN_PROP_HANDLER.IPV6_ML_PREFIX, - SPINEL.PROP_IPV6_ADDRESS_TABLE: WPAN_PROP_HANDLER.IPV6_ADDRESS_TABLE, - SPINEL.PROP_IPV6_ROUTE_TABLE: WPAN_PROP_HANDLER.IPV6_ROUTE_TABLE, - SPINEL.PROP_IPv6_ICMP_PING_OFFLOAD: WPAN_PROP_HANDLER.IPv6_ICMP_PING_OFFLOAD, - - SPINEL.PROP_STREAM_DEBUG: WPAN_PROP_HANDLER.STREAM_DEBUG, - SPINEL.PROP_STREAM_RAW: WPAN_PROP_HANDLER.STREAM_RAW, - SPINEL.PROP_STREAM_NET: WPAN_PROP_HANDLER.STREAM_NET, - SPINEL.PROP_STREAM_NET_INSECURE: WPAN_PROP_HANDLER.STREAM_NET_INSECURE, - - SPINEL.PROP_PIB_15_4_PHY_CHANNELS_SUPPORTED: WPAN_PROP_HANDLER.PIB_PHY_CHANNELS_SUPPORTED, - SPINEL.PROP_PIB_15_4_MAC_PROMISCUOUS_MODE: WPAN_PROP_HANDLER.PIB_MAC_PROMISCUOUS_MODE, - SPINEL.PROP_PIB_15_4_MAC_SECURITY_ENABLED: WPAN_PROP_HANDLER.PIB_MAC_SECURITY_ENABLED, - - SPINEL.PROP_MSG_BUFFER_COUNTERS: WPAN_PROP_HANDLER.MSG_BUFFER_COUNTERS -} - - -class WpanApi(SpinelCodec): - """ Helper class to format wpan command packets """ - - def __init__(self, stream, nodeid, use_hdlc=FEATURE_USE_HDLC): - self.stream = stream - self.nodeid = nodeid - - self.use_hdlc = use_hdlc - if self.use_hdlc: - self.hdlc = Hdlc(self.stream) - - # PARSER state - self.rx_pkt = [] - self.callback = defaultdict(list) # Map prop_id to list of callbacks. - - # Fire up threads - self._reader_alive = True - self.tid_filter = set() - self.__queue_prop = defaultdict(Queue.Queue) # Map tid to Queue. - self.queue_register() - self.__start_reader() - - def __del__(self): - self._reader_alive = False - - def __start_reader(self): - """Start reader thread""" - self._reader_alive = True - # start serial->console thread - self.receiver_thread = threading.Thread(target=self.stream_rx) - self.receiver_thread.setDaemon(True) - self.receiver_thread.start() - - def transact(self, command_id, payload="", tid=SPINEL.HEADER_DEFAULT): - pkt = self.encode_packet(command_id, payload, tid) - if CONFIG.DEBUG_LOG_SERIAL: - msg = "TX Pay: (%i) %s " % (len(pkt), util.hexify_bytes(pkt)) - logging.debug(msg) - - if self.use_hdlc: - pkt = self.hdlc.encode(pkt) - self.stream_tx(pkt) - - def parse_rx(self, pkt): - if not pkt: - return - - if CONFIG.DEBUG_LOG_SERIAL: - msg = "RX Pay: (%i) %s " % ( - len(pkt), str(map(util.hexify_int, pkt))) - logging.debug(msg) - - length = len(pkt) - 2 - if length < 0: - return - - spkt = "".join(map(chr, pkt)) - - tid = self.parse_C(spkt[:1]) - (cmd_id, cmd_length) = self.parse_i(spkt[1:]) - pay_start = cmd_length + 1 - payload = spkt[pay_start:] - - try: - handler = SPINEL_COMMAND_DISPATCH[cmd_id] - cmd_name = handler.__name__ - handler(self, payload, tid) - - except Exception as _ex: - print(traceback.format_exc()) - cmd_name = "CB_Unknown" - logging.info("\n%s (%i): ", cmd_name, cmd_id) - - if CONFIG.DEBUG_CMD_RESPONSE: - logging.info("\n%s (%i): ", cmd_name, cmd_id) - logging.info("===> %s", util.hexify_str(payload)) - - def stream_tx(self, pkt): - # Encapsulate lagging and Framer support in self.stream class. - self.stream.write(pkt) - - def stream_rx(self): - """ Recieve thread and parser. """ - while self._reader_alive: - if self.use_hdlc: - self.rx_pkt = self.hdlc.collect() - else: - # size=None: Assume stream will always deliver packets - pkt = self.stream.read(None) - self.rx_pkt = util.packed_to_array(pkt) - - self.parse_rx(self.rx_pkt) - - class PropertyItem(object): - """ Queue item for NCP response to property commands. """ - - def __init__(self, prop, value, tid): - self.prop = prop - self.value = value - self.tid = tid - - def callback_register(self, prop, cb): - self.callback[prop].append(cb) - - def queue_register(self, tid=SPINEL.HEADER_DEFAULT): - self.tid_filter.add(tid) - return self.__queue_prop[tid] - - def queue_wait_prepare(self, _prop_id, tid=SPINEL.HEADER_DEFAULT): - self.queue_clear(tid) - - def queue_add(self, prop, value, tid): - cb_list = self.callback[prop] - - # Asynchronous handlers can consume message and not add to queue. - if len(cb_list) > 0: - consumed = cb_list[0](prop, value, tid) - if consumed: return - - if tid not in self.tid_filter: - return - item = self.PropertyItem(prop, value, tid) - self.__queue_prop[tid].put_nowait(item) - - def queue_clear(self, tid): - with self.__queue_prop[tid].mutex: - self.__queue_prop[tid].queue.clear() - - def queue_get(self, tid, timeout = None): - try: - if (timeout): - item = self.__queue_prop[tid].get(True, timeout) - else: - item = self.__queue_prop[tid].get_nowait() - except Queue.Empty: - item = None - return item - - def queue_wait_for_prop(self, _prop, tid=SPINEL.HEADER_DEFAULT, timeout=TIMEOUT_PROP): - start = time.time() - item = self.queue_get(tid, timeout) - if (_prop is not None): - while (item and (item.prop != _prop)): - self.__queue_prop[tid].put_nowait(item) - reminder = timeout - (time.time() - start) - if (reminder <= 0.0): - item = None - break - item = self.queue_get(tid, reminder) - # self.__queue_prop[tid].task_done() - return item - - def ip_send(self, pkt): - pay = self.encode_i(SPINEL.PROP_STREAM_NET) - - pkt_len = len(pkt) - pay += pack("= 1: - DEBUG_LOG_PROP = 1 - if level >= 2: - DEBUG_LOG_PKT = 1 - if level >= 3: - DEBUG_LOG_SERIAL = 1 - if level >= 4: - DEBUG_HDLC = 1 - if level >= 5: - DEBUG_STREAM_RX = 1 - DEBUG_STREAM_TX = 1 - - print("DEBUG_ENABLE = " + str(DEBUG_ENABLE)) diff --git a/tools/spinel-cli/spinel/const.py b/tools/spinel-cli/spinel/const.py deleted file mode 100644 index acfe47c36..000000000 --- a/tools/spinel-cli/spinel/const.py +++ /dev/null @@ -1,417 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" Module-wide constants for spinel package. """ - -class SPINEL(object): - """ Singular class that contains all Spinel constants. """ - HEADER_ASYNC = 0x80 - HEADER_DEFAULT = 0x81 - HEADER_EVENT_HANDLER = 0x82 - - #========================================= - # Spinel Commands: Host -> NCP - #========================================= - - CMD_NOOP = 0 - CMD_RESET = 1 - CMD_PROP_VALUE_GET = 2 - CMD_PROP_VALUE_SET = 3 - CMD_PROP_VALUE_INSERT = 4 - CMD_PROP_VALUE_REMOVE = 5 - - #========================================= - # Spinel Command Responses: NCP -> Host - #========================================= - RSP_PROP_VALUE_IS = 6 - RSP_PROP_VALUE_INSERTED = 7 - RSP_PROP_VALUE_REMOVED = 8 - - CMD_NET_SAVE = 9 - CMD_NET_CLEAR = 10 - CMD_NET_RECALL = 11 - - RSP_HBO_OFFLOAD = 12 - RSP_HBO_RECLAIM = 13 - RSP_HBO_DROP = 14 - - CMD_HBO_OFFLOADED = 15 - CMD_HBO_RECLAIMED = 16 - CMD_HBO_DROPPED = 17 - - CMD_NEST__BEGIN = 15296 - CMD_NEST__END = 15360 - - CMD_VENDOR__BEGIN = 15360 - CMD_VENDOR__END = 16384 - - CMD_EXPERIMENTAL__BEGIN = 2000000 - CMD_EXPERIMENTAL__END = 2097152 - - #========================================= - # Spinel Properties - #========================================= - - PROP_LAST_STATUS = 0 # < status [i] - PROP_PROTOCOL_VERSION = 1 # < major, minor [i,i] - PROP_NCP_VERSION = 2 # < version string [U] - PROP_INTERFACE_TYPE = 3 # < [i] - PROP_VENDOR_ID = 4 # < [i] - PROP_CAPS = 5 # < capability list [A(i)] - PROP_INTERFACE_COUNT = 6 # < Interface count [C] - PROP_POWER_STATE = 7 # < PowerState [C] - PROP_HWADDR = 8 # < PermEUI64 [E] - PROP_LOCK = 9 # < PropLock [b] - PROP_HBO_MEM_MAX = 10 # < Max offload mem [S] - PROP_HBO_BLOCK_MAX = 11 # < Max offload block [S] - - PROP_PHY__BEGIN = 0x20 - PROP_PHY_ENABLED = PROP_PHY__BEGIN + 0 # < [b] - PROP_PHY_CHAN = PROP_PHY__BEGIN + 1 # < [C] - PROP_PHY_CHAN_SUPPORTED = PROP_PHY__BEGIN + 2 # < [A(C)] - PROP_PHY_FREQ = PROP_PHY__BEGIN + 3 # < kHz [L] - PROP_PHY_CCA_THRESHOLD = PROP_PHY__BEGIN + 4 # < dBm [c] - PROP_PHY_TX_POWER = PROP_PHY__BEGIN + 5 # < [c] - PROP_PHY_RSSI = PROP_PHY__BEGIN + 6 # < dBm [c] - PROP_PHY__END = 0x30 - - PROP_MAC__BEGIN = 0x30 - PROP_MAC_SCAN_STATE = PROP_MAC__BEGIN + 0 # < [C] - PROP_MAC_SCAN_MASK = PROP_MAC__BEGIN + 1 # < [A(C)] - PROP_MAC_SCAN_PERIOD = PROP_MAC__BEGIN + 2 # < ms-per-channel [S] - # < chan,rssi,(laddr,saddr,panid,lqi),(proto,xtra) [Cct(ESSC)t(i)] - PROP_MAC_SCAN_BEACON = PROP_MAC__BEGIN + 3 - PROP_MAC_15_4_LADDR = PROP_MAC__BEGIN + 4 # < [E] - PROP_MAC_15_4_SADDR = PROP_MAC__BEGIN + 5 # < [S] - PROP_MAC_15_4_PANID = PROP_MAC__BEGIN + 6 # < [S] - PROP_MAC_RAW_STREAM_ENABLED = PROP_MAC__BEGIN + 7 # < [C] - PROP_MAC_FILTER_MODE = PROP_MAC__BEGIN + 8 # < [C] - PROP_MAC__END = 0x40 - - PROP_MAC_EXT__BEGIN = 0x1300 - # Format: `A(T(Ec))` - # * `E`: EUI64 address of node - # * `c`: Optional fixed RSSI. -127 means not set. - PROP_MAC_WHITELIST = PROP_MAC_EXT__BEGIN + 0 - PROP_MAC_WHITELIST_ENABLED = PROP_MAC_EXT__BEGIN + 1 # < [b] - PROP_MAC_EXT__END = 0x1400 - - PROP_NET__BEGIN = 0x40 - PROP_NET_SAVED = PROP_NET__BEGIN + 0 # < [b] - PROP_NET_IF_UP = PROP_NET__BEGIN + 1 # < [b] - PROP_NET_STACK_UP = PROP_NET__BEGIN + 2 # < [C] - PROP_NET_ROLE = PROP_NET__BEGIN + 3 # < [C] - PROP_NET_NETWORK_NAME = PROP_NET__BEGIN + 4 # < [U] - PROP_NET_XPANID = PROP_NET__BEGIN + 5 # < [D] - PROP_NET_MASTER_KEY = PROP_NET__BEGIN + 6 # < [D] - PROP_NET_KEY_SEQUENCE_COUNTER = PROP_NET__BEGIN + 7 # < [L] - PROP_NET_PARTITION_ID = PROP_NET__BEGIN + 8 # < [L] - PROP_NET_KEY_SWITCH_GUARDTIME = PROP_NET__BEGIN + 10 # < [L] - PROP_NET__END = 0x50 - - PROP_THREAD__BEGIN = 0x50 - PROP_THREAD_LEADER_ADDR = PROP_THREAD__BEGIN + 0 # < [6] - PROP_THREAD_PARENT = PROP_THREAD__BEGIN + 1 # < LADDR, SADDR [ES] - PROP_THREAD_CHILD_TABLE = PROP_THREAD__BEGIN + 2 # < [A(t(ES))] - PROP_THREAD_LEADER_RID = PROP_THREAD__BEGIN + 3 # < [C] - PROP_THREAD_LEADER_WEIGHT = PROP_THREAD__BEGIN + 4 # < [C] - PROP_THREAD_LOCAL_LEADER_WEIGHT = PROP_THREAD__BEGIN + 5 # < [C] - PROP_THREAD_NETWORK_DATA = PROP_THREAD__BEGIN + 6 # < [D] - PROP_THREAD_NETWORK_DATA_VERSION = PROP_THREAD__BEGIN + 7 # < [S] - PROP_THREAD_STABLE_NETWORK_DATA = PROP_THREAD__BEGIN + 8 # < [D] - PROP_THREAD_STABLE_NETWORK_DATA_VERSION = PROP_THREAD__BEGIN + 9 # < [S] - # < array(ipv6prefix,prefixlen,stable,flags) [A(t(6CbC))] - PROP_THREAD_ON_MESH_NETS = PROP_THREAD__BEGIN + 10 - # < array(ipv6prefix,prefixlen,stable,flags) [A(t(6CbC))] - PROP_THREAD_LOCAL_ROUTES = PROP_THREAD__BEGIN + 11 - PROP_THREAD_ASSISTING_PORTS = PROP_THREAD__BEGIN + 12 # < array(portn) [A(S)] - PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE = PROP_THREAD__BEGIN + 13 # < [b] - PROP_THREAD_MODE = PROP_THREAD__BEGIN + 14 - PROP_THREAD__END = 0x60 - - PROP_THREAD_EXT__BEGIN = 0x1500 - PROP_THREAD_CHILD_TIMEOUT = PROP_THREAD_EXT__BEGIN + 0 # < [L] - PROP_THREAD_RLOC16 = PROP_THREAD_EXT__BEGIN + 1 # < [S] - PROP_THREAD_ROUTER_UPGRADE_THRESHOLD = PROP_THREAD_EXT__BEGIN + 2 # < [C] - PROP_THREAD_CONTEXT_REUSE_DELAY = PROP_THREAD_EXT__BEGIN + 3 # < [L] - PROP_THREAD_NETWORK_ID_TIMEOUT = PROP_THREAD_EXT__BEGIN + 4 # < [b] - PROP_THREAD_ACTIVE_ROUTER_IDS = PROP_THREAD_EXT__BEGIN + 5 # < [A(b)] - PROP_THREAD_RLOC16_DEBUG_PASSTHRU = PROP_THREAD_EXT__BEGIN + 6 # < [b] - PROP_THREAD_ROUTER_ROLE_ENABLED = PROP_THREAD_EXT__BEGIN + 7 # < [b] - PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD = PROP_THREAD_EXT__BEGIN + 8 # < [C] - PROP_THREAD_ROUTER_SELECTION_JITTER = PROP_THREAD_EXT__BEGIN + 9 # < [C] - PROP_THREAD_PREFERRED_ROUTER_ID = PROP_THREAD_EXT__BEGIN + 10 # < [C] - PROP_THREAD_NEIGHBOR_TABLE = PROP_THREAD_EXT__BEGIN + 11 # < [A(t(ESLCcCbLL))] - PROP_THREAD_CHILD_COUNT_MAX = PROP_THREAD_EXT__BEGIN + 12 # < [C] - - PROP_THREAD_EXT__END = 0x1600 - - PROP_MESHCOP_EXT__BEGIN = 0x1600 - PROP_MESHCOP_JOINER_ENABLE = PROP_MESHCOP_EXT__BEGIN + 0 # < [b] - PROP_MESHCOP_JOINER_CREDENTIAL = PROP_MESHCOP_EXT__BEGIN + 1 # < [D] - PROP_MESHCOP_JOINER_URL = PROP_MESHCOP_EXT__BEGIN + 2 # < [U] - PROP_MESHCOP_BORDER_AGENT_ENABLE = PROP_MESHCOP_EXT__BEGIN + 3 # < [b] - PROP_MESHCOP_EXT__END = 0x1700 - - PROP_IPV6__BEGIN = 0x60 - PROP_IPV6_LL_ADDR = PROP_IPV6__BEGIN + 0 # < [6] - PROP_IPV6_ML_ADDR = PROP_IPV6__BEGIN + 1 # < [6C] - PROP_IPV6_ML_PREFIX = PROP_IPV6__BEGIN + 2 # < [6C] - # < array(ipv6addr,prefixlen,valid,preferred,flags) [A(t(6CLLC))] - PROP_IPV6_ADDRESS_TABLE = PROP_IPV6__BEGIN + 3 - # < array(ipv6prefix,prefixlen,iface,flags) [A(t(6CCC))] - PROP_IPV6_ROUTE_TABLE = PROP_IPV6__BEGIN + 4 - PROP_IPv6_ICMP_PING_OFFLOAD = PROP_IPV6__BEGIN + 5 # < [b] - - PROP_STREAM__BEGIN = 0x70 - PROP_STREAM_DEBUG = PROP_STREAM__BEGIN + 0 # < [U] - PROP_STREAM_RAW = PROP_STREAM__BEGIN + 1 # < [D] - PROP_STREAM_NET = PROP_STREAM__BEGIN + 2 # < [D] - PROP_STREAM_NET_INSECURE = PROP_STREAM__BEGIN + 3 # < [D] - PROP_STREAM__END = 0x80 - - # UART Bitrate - # Format: `L` - PROP_UART_BITRATE = 0x100 - - # UART Software Flow Control - # Format: `b` - PROP_UART_XON_XOFF = 0x101 - - PROP_PIB_15_4__BEGIN = 1024 - PROP_PIB_15_4_PHY_CHANNELS_SUPPORTED = PROP_PIB_15_4__BEGIN + 0x01 # < [A(L)] - PROP_PIB_15_4_MAC_PROMISCUOUS_MODE = PROP_PIB_15_4__BEGIN + 0x51 # < [b] - PROP_PIB_15_4_MAC_SECURITY_ENABLED = PROP_PIB_15_4__BEGIN + 0x5d # < [b] - PROP_PIB_15_4__END = 1280 - - PROP_CNTR__BEGIN = 1280 - - # Counter reset behavior - # Format: `C` - PROP_CNTR_RESET = PROP_CNTR__BEGIN + 0 - - # The total number of transmissions. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_TOTAL = PROP_CNTR__BEGIN + 1 - - # The number of transmissions with ack request. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_ACK_REQ = PROP_CNTR__BEGIN + 2 - - # The number of transmissions that were acked. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_ACKED = PROP_CNTR__BEGIN + 3 - - # The number of transmissions without ack request. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_NO_ACK_REQ = PROP_CNTR__BEGIN + 4 - - # The number of transmitted data. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_DATA = PROP_CNTR__BEGIN + 5 - - # The number of transmitted data poll. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_DATA_POLL = PROP_CNTR__BEGIN + 6 - - # The number of transmitted beacon. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_BEACON = PROP_CNTR__BEGIN + 7 - - # The number of transmitted beacon request. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_BEACON_REQ = PROP_CNTR__BEGIN + 8 - - # The number of transmitted other types of frames. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_OTHER = PROP_CNTR__BEGIN + 9 - - # The number of retransmission times. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_PKT_RETRY = PROP_CNTR__BEGIN + 10 - - # The number of CCA failure times. - # Format: `L` (Read-only) */ - PROP_CNTR_TX_ERR_CCA = PROP_CNTR__BEGIN + 11 - - # The total number of received packets. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_TOTAL = PROP_CNTR__BEGIN + 100 - - # The number of received data. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_DATA = PROP_CNTR__BEGIN + 101 - - # The number of received data poll. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_DATA_POLL = PROP_CNTR__BEGIN + 102 - - # The number of received beacon. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_BEACON = PROP_CNTR__BEGIN + 103 - - # The number of received beacon request. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_BEACON_REQ = PROP_CNTR__BEGIN + 104 - - # The number of received other types of frames. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_OTHER = PROP_CNTR__BEGIN + 105 - - # The number of received packets filtered by whitelist. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_FILT_WL = PROP_CNTR__BEGIN + 106 - - # The number of received packets filtered by destination check. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_PKT_FILT_DA = PROP_CNTR__BEGIN + 107 - - # The number of received packets that are empty. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_EMPTY = PROP_CNTR__BEGIN + 108 - - # The number of received packets from an unknown neighbor. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_UKWN_NBR = PROP_CNTR__BEGIN + 109 - - # The number of received packets whose source address is invalid. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_NVLD_SADDR = PROP_CNTR__BEGIN + 110 - - # The number of received packets with a security error. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_SECURITY = PROP_CNTR__BEGIN + 111 - - # The number of received packets with a checksum error. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_BAD_FCS = PROP_CNTR__BEGIN + 112 - - # The number of received packets with other errors. - # Format: `L` (Read-only) */ - PROP_CNTR_RX_ERR_OTHER = PROP_CNTR__BEGIN + 113 - - # The message buffer counter info - # Format: `SSSSSSSSSSSSSSSS` (Read-only) - # `S`, (TotalBuffers) The number of buffers in the pool. - # `S`, (FreeBuffers) The number of free message buffers. - # `S`, (6loSendMessages) The number of messages in the 6lo send queue. - # `S`, (6loSendBuffers) The number of buffers in the 6lo send queue. - # `S`, (6loReassemblyMessages) The number of messages in the 6LoWPAN reassembly queue. - # `S`, (6loReassemblyBuffers) The number of buffers in the 6LoWPAN reassembly queue. - # `S`, (Ip6Messages) The number of messages in the IPv6 send queue. - # `S`, (Ip6Buffers) The number of buffers in the IPv6 send queue. - # `S`, (MplMessages) The number of messages in the MPL send queue. - # `S`, (MplBuffers) The number of buffers in the MPL send queue. - # `S`, (MleMessages) The number of messages in the MLE send queue. - # `S`, (MleBuffers) The number of buffers in the MLE send queue. - # `S`, (ArpMessages) The number of messages in the ARP send queue. - # `S`, (ArpBuffers) The number of buffers in the ARP send queue. - # `S`, (CoapClientMessages) The number of messages in the CoAP client send queue. - # `S` (CoapClientBuffers) The number of buffers in the CoAP client send queue. - PROP_MSG_BUFFER_COUNTERS = PROP_CNTR__BEGIN + 400 - - #========================================= - - MAC_FILTER_MDOE_NORMAL = 0 - MAC_FILTER_MODE_PROMISCUOUS = 1 - MAC_FILTER_MODE_MONITOR = 2 - - #========================================= - - RSSI_OVERRIDE = 127 - - #========================================= - - -class kThread(object): - """ OpenThread constant class. """ - PrefixPreferenceOffset = 6 - PrefixPreferredFlag = 1 << 5 - PrefixSlaacFlag = 1 << 4 - PrefixDhcpFlag = 1 << 3 - PrefixConfigureFlag = 1 << 2 - PrefixDefaultRouteFlag = 1 << 1 - PrefixOnMeshFlag = 1 << 0 - -#========================================= - -SPINEL_LAST_STATUS_MAP = { - 0: "STATUS_OK: Operation has completed successfully.", - 1: "STATUS_FAILURE: Operation has failed for some undefined reason.", - 2: "STATUS_UNIMPLEMENTED: The given operation has not been implemented.", - 3: "STATUS_INVALID_ARGUMENT: An argument to the given operation is invalid.", - 4: "STATUS_INVALID_STATE : The given operation is invalid for the current state of the device.", - 5: "STATUS_INVALID_COMMAND: The given command is not recognized.", - 6: "STATUS_INVALID_INTERFACE: The given Spinel interface is not supported.", - 7: "STATUS_INTERNAL_ERROR: An internal runtime error has occured.", - 8: "STATUS_SECURITY_ERROR: A security or authentication error has occured.", - 9: "STATUS_PARSE_ERROR: An error has occured while parsing the command.", - 10: "STATUS_IN_PROGRESS: The operation is in progress and will be completed asynchronously.", - 11: "STATUS_NOMEM: The operation has been prevented due to memory pressure.", - 12: "STATUS_BUSY: The device is currently performing a mutually exclusive operation.", - 13: "STATUS_PROPERTY_NOT_FOUND: The given property is not recognized.", - 14: "STATUS_PACKET_DROPPED: The packet was dropped.", - 15: "STATUS_EMPTY: The result of the operation is empty.", - 16: "STATUS_CMD_TOO_BIG: The command was too large to fit in the internal buffer.", - 17: "STATUS_NO_ACK: The packet was not acknowledged.", - 18: "STATUS_CCA_FAILURE: The packet was not sent due to a CCA failure.", - 19: "SPINEL_STATUS_ALREADY: The operation is already in progress.", - 20: "SPINEL_STATUS_ITEM_NOT_FOUND: The given item could not be found.", - - 104: "SPINEL_STATUS_JOIN_FAILURE", - 105: "SPINEL_STATUS_JOIN_SECURITY: The network key has been set incorrectly.", - 106: "SPINEL_STATUS_JOIN_NO_PEERS: The node was unable to find any other peers on the network.", - 107: "SPINEL_STATUS_JOIN_INCOMPATIBLE: The only potential peer nodes found are incompatible.", - - 112: "STATUS_RESET_POWER_ON", - 113: "STATUS_RESET_EXTERNAL", - 114: "STATUS_RESET_SOFTWARE", - 115: "STATUS_RESET_FAULT", - 116: "STATUS_RESET_CRASH", - 117: "STATUS_RESET_ASSERT", - 118: "STATUS_RESET_OTHER", - 119: "STATUS_RESET_UNKNOWN", - 120: "STATUS_RESET_WATCHDOG", - - 0x4000: "kThreadError_None", - 0x4001: "kThreadError_Failed", - 0x4002: "kThreadError_Drop", - 0x4003: "kThreadError_NoBufs", - 0x4004: "kThreadError_NoRoute", - 0x4005: "kThreadError_Busy", - 0x4006: "kThreadError_Parse", - 0x4007: "kThreadError_InvalidArgs", - 0x4008: "kThreadError_Security", - 0x4009: "kThreadError_AddressQuery", - 0x400A: "kThreadError_NoAddress", - 0x400B: "kThreadError_NotReceiving", - 0x400C: "kThreadError_Abort", - 0x400D: "kThreadError_NotImplemented", - 0x400E: "kThreadError_InvalidState", - 0x400F: "kThreadError_NoTasklets", - -} diff --git a/tools/spinel-cli/spinel/hdlc.py b/tools/spinel-cli/spinel/hdlc.py deleted file mode 100644 index 8c50e223f..000000000 --- a/tools/spinel-cli/spinel/hdlc.py +++ /dev/null @@ -1,165 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" High-Level Data Link Control (HDLC) module. """ - -import logging - -from struct import pack - -import spinel.config as CONFIG -from spinel.stream import IStream -from spinel.util import hexify_int -from spinel.util import hexify_bytes - -HDLC_FLAG = 0x7e -HDLC_ESCAPE = 0x7d - -# RFC 1662 Appendix C - -HDLC_FCS_INIT = 0xFFFF -HDLC_FCS_POLY = 0x8408 -HDLC_FCS_GOOD = 0xF0B8 - - -class Hdlc(IStream): - """ Utility class for HDLC encoding and decoding. """ - - def __init__(self, stream): - self.stream = stream - self.fcstab = self.mkfcstab() - - @classmethod - def mkfcstab(cls): - """ Make a static lookup table for byte value to FCS16 result. """ - polynomial = HDLC_FCS_POLY - - def valiter(): - """ Helper to yield FCS16 table entries for each byte value. """ - for byte in range(256): - fcs = byte - i = 8 - while i: - fcs = (fcs >> 1) ^ polynomial if fcs & 1 else fcs >> 1 - i -= 1 - - yield fcs & 0xFFFF - - return tuple(valiter()) - - def fcs16(self, byte, fcs): - """ - Return the next iteration of an fcs16 calculation - given the next data byte and current fcs accumulator. - """ - fcs = (fcs >> 8) ^ self.fcstab[(fcs ^ byte) & 0xff] - return fcs - - def collect(self): - """ Return the next valid packet to pass HDLC decoding on the stream. """ - fcs = HDLC_FCS_INIT - packet = [] - raw = [] - - # Synchronize - while 1: - byte = self.stream.read() - if CONFIG.DEBUG_HDLC: - raw.append(byte) - if byte == HDLC_FLAG: - break - - # Read packet, updating fcs, and escaping bytes as needed - while 1: - byte = self.stream.read() - if CONFIG.DEBUG_HDLC: - raw.append(byte) - if byte == HDLC_FLAG: - if len(packet) != 0: - break - else: - # If multiple FLAG bytes in a row, keep looking for data. - continue - if byte == HDLC_ESCAPE: - byte = self.stream.read() - if CONFIG.DEBUG_HDLC: - raw.append(byte) - byte ^= 0x20 - packet.append(byte) - fcs = self.fcs16(byte, fcs) - - if CONFIG.DEBUG_HDLC: - logging.debug("RX Hdlc: " + str(map(hexify_int, raw))) - - if fcs != HDLC_FCS_GOOD: - packet = None - else: - packet = packet[:-2] # remove FCS16 from end - - return packet - - @classmethod - def encode_byte(cls, byte, packet=[]): - """ HDLC encode and append a single byte to the given packet. """ - if (byte == HDLC_ESCAPE) or (byte == HDLC_FLAG): - packet.append(HDLC_ESCAPE) - packet.append(byte ^ 0x20) - else: - packet.append(byte) - return packet - - def encode(self, payload=""): - """ Return the HDLC encoding of the given packet. """ - fcs = HDLC_FCS_INIT - packet = [] - packet.append(HDLC_FLAG) - for byte in payload: - byte = ord(byte) - fcs = self.fcs16(byte, fcs) - packet = self.encode_byte(byte, packet) - - fcs ^= 0xffff - byte = fcs & 0xFF - packet = self.encode_byte(byte, packet) - byte = fcs >> 8 - packet = self.encode_byte(byte, packet) - packet.append(HDLC_FLAG) - packet = pack("%dB" % len(packet), *packet) - - if CONFIG.DEBUG_HDLC: - logging.debug("TX Hdlc: " + hexify_bytes(packet)) - return packet - - def write(self, data): - """ HDLC encode and write the given data to this stream. """ - pkt = self.encode(data) - self.stream.write(pkt) - - def read(self, _size=None): - """ Read and HDLC decode the next packet from this stream. """ - pkt = self.collect() - return pkt diff --git a/tools/spinel-cli/spinel/pcap.py b/tools/spinel-cli/spinel/pcap.py deleted file mode 100644 index 46e9d26e7..000000000 --- a/tools/spinel-cli/spinel/pcap.py +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -""" Module to provide codec utilities for .pcap formatters. """ - -import struct -from datetime import datetime - -DLT_IEEE802_15_4 = 195 -PCAP_MAGIC_NUMBER = 0xa1b2c3d4 -PCAP_VERSION_MAJOR = 2 -PCAP_VERSION_MINOR = 4 - - -class PcapCodec(object): - """ Utility class for .pcap formatters. """ - - @classmethod - def encode_header(cls): - """ Returns a pcap file header. """ - return struct.pack("