sniffer.py: remove scapy dependency. (#921)

Added to spinel.codec a method to register a callback for a given message type.
Pulled all IPv6 packet parsing from spinel.codec using the new callback mechanism.
This commit is contained in:
Martin Turon
2016-11-03 13:32:14 -07:00
committed by Jonathan Hui
parent 1a81edba82
commit e399632aa5
8 changed files with 130 additions and 77 deletions
+18 -18
View File
@@ -1,13 +1,13 @@
# Spinel CLI Reference # Spinel CLI Reference
The Spinel CLI exposes the OpenThread configuration and management APIs The Spinel CLI exposes the OpenThread configuration and management APIs
running on an NCP build via a command line interface. Spinel CLI is primarily running on an NCP build via a command line interface. Spinel CLI is primarily
targeted for driving the automated continuous integration tests, and is targeted for driving the automated continuous integration tests, and is
suitable for manual experimentation with controlling OpenThread NCP instances. suitable for manual experimentation with controlling OpenThread NCP instances.
For a production grade host driver, see [wpantund]: https://github.com/openthread/wpantund. 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 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 platform, including starting a basic tunnel interface to allow IPv6
applications to run on the HOST and use the Thread network. applications to run on the HOST and use the Thread network.
The power of this tool is three fold: The power of this tool is three fold:
@@ -31,9 +31,9 @@ The power of this tool is three fold:
``` ```
sudo easy_install pip sudo easy_install pip
sudo pip install blessed sudo pip install --user pyserial
sudo pip install ipaddress sudo pip install --user ipaddress
sudo pip install scapy sudo pip install --user scapy==2.3.2
``` ```
## Usage ## Usage
@@ -56,7 +56,7 @@ sudo pip install scapy
-p <PIPE>, --pipe=<PIPE> -p <PIPE>, --pipe=<PIPE>
Open a piped process connection to the OpenThread NCP device Open a piped process connection to the OpenThread NCP device
where <PIPE> is the command to start an emulator, such as where <PIPE> is the command to start an emulator, such as
"ot-ncp". Spinel-cli will communicate with the child process "ot-ncp". Spinel-cli will communicate with the child process
via stdin/stdout. via stdin/stdout.
@@ -80,9 +80,9 @@ sudo pip install scapy
## Quick Start ## Quick Start
The spinel-cli tool provides an intuitive command line interface, including The spinel-cli tool provides an intuitive command line interface, including
all the standard OpenThread CLI commands, plus full history accessible by 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 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 that spinel-cli provides as well that aren't part of the standard set
documented in the command reference section. documented in the command reference section.
``` ```
@@ -118,7 +118,7 @@ spinel-cli >
## Running the NCP Tests ## Running the NCP Tests
The OpenThread automated test suite can be run against any of the following The OpenThread automated test suite can be run against any of the following
node types by passing the NODE_TYPE environment variable: node types by passing the NODE_TYPE environment variable:
| NODE_TYPE | Description | | NODE_TYPE | Description |
@@ -152,7 +152,7 @@ NODE_TYPE=ncp-sim BUILD_TARGET=posix-distcheck DISTCHECK_CONFIGURE_FLAGS="--with
### OpenThread CLI Commands ### OpenThread CLI Commands
The primary intent of spinel-cli is to support the exact syntax and output 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 of the OpenThread CLI command set in order to seamlessly reapply the
thread-cert automated test suite against NCP targets. thread-cert automated test suite against NCP targets.
See [cli module][1] for more information on these commands. See [cli module][1] for more information on these commands.
@@ -161,7 +161,7 @@ See [cli module][1] for more information on these commands.
### Diagnostics CLI Commands ### Diagnostics CLI Commands
The Diagnostics module is enabled only when building OpenThread with The Diagnostics module is enabled only when building OpenThread with
the --enable-diag configure option. the --enable-diag configure option.
See [diag module][2] for more information on these commands. See [diag module][2] for more information on these commands.
@@ -171,7 +171,7 @@ See [diag module][2] for more information on these commands.
### NCP CLI Commands ### NCP CLI Commands
These commands extend beyond the core OpenThread CLI, and are specific to 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 the spinel-cli tool for the purposes of debugging, access to NCP-specific
Spinel parameters, and support of advanced configurations. Spinel parameters, and support of advanced configurations.
@@ -287,8 +287,8 @@ DEBUG_ENABLE = 0
spinel-cli > debug 1 spinel-cli > debug 1
DEBUG_ENABLE = 1 DEBUG_ENABLE = 1
spinel-cli > version spinel-cli > version
TX Pay: (3) ['81', '02', '02'] 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'] 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 OPENTHREAD/g8bc4b1d-dirty; Aug 31 2016 10:48:53
Done Done
``` ```
@@ -306,7 +306,7 @@ Set whether debug terminal title bar is enabled.
Control sideband tunnel interface. Control sideband tunnel interface.
#### ncp-tun up #### ncp-tun up
Bring up Thread TUN interface. Bring up Thread TUN interface.
```bash ```bash
@@ -315,7 +315,7 @@ Done
``` ```
#### ncp-tun down #### ncp-tun down
Bring down Thread TUN interface. Bring down Thread TUN interface.
```bash ```bash
@@ -335,7 +335,7 @@ Done
#### ncp-tun del \<ipaddr\> #### ncp-tun del \<ipaddr\>
Delete an IPv6 address from the Thread TUN interface. Delete an IPv6 address from the Thread TUN interface.
```bash ```bash
spinel-cli > ncp-tun del 2001::dead:beef:cafe spinel-cli > ncp-tun del 2001::dead:beef:cafe
Done Done
+7 -9
View File
@@ -1,6 +1,6 @@
# Spinel Sniffer Reference # Spinel Sniffer Reference
Any Spinel NCP node can be made into a promiscuous packet sniffer, and this 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 tool both intializes a device into this mode and outputs a pcap stream that
can be saved or piped directly into Wireshark. can be saved or piped directly into Wireshark.
@@ -21,9 +21,8 @@ The tool has been tested on the following platforms:
``` ```
sudo easy_install pip sudo easy_install pip
sudo pip install ipaddress sudo pip install --user pyserial
sudo pip install scapy sudo pip install --user ipaddress
sudo pip install pyserial
``` ```
## Usage ## Usage
@@ -46,7 +45,7 @@ sudo pip install pyserial
-p <PIPE>, --pipe=<PIPE> -p <PIPE>, --pipe=<PIPE>
Open a piped process connection to the OpenThread NCP device Open a piped process connection to the OpenThread NCP device
where <PIPE> is the command to start an emulator, such as where <PIPE> is the command to start an emulator, such as
"ot-ncp". Spinel-cli will communicate with the child process "ot-ncp". Spinel-cli will communicate with the child process
via stdin/stdout. via stdin/stdout.
@@ -90,9 +89,9 @@ From openthread root:
sudo ./tools/spinel-cli/sniffer.py -c 11 -n 1 -u /dev/ttyUSB0 | wireshark -k -i - 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, This will connect to stock openthread ncp firmware over the given UART,
make the node into a promiscuous mode sniffer on the given channel, make the node into a promiscuous mode sniffer on the given channel,
open up wireshark, and start streaming packets into wireshark. open up wireshark, and start streaming packets into wireshark.
## Troubleshooting ## Troubleshooting
Q: sniffer.py throws ```ImportError: No module named dnet``` on OSX Q: sniffer.py throws ```ImportError: No module named dnet``` on OSX
@@ -107,4 +106,3 @@ echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >>
you may need to reinstall the scapy pip dependency listed above 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 you can read more about this issue here: http://stackoverflow.com/questions/26229057/scapy-installation-fails-on-osx-with-dnet-import-error
+32 -8
View File
@@ -57,6 +57,7 @@ import traceback
import optparse import optparse
import struct
import string import string
import textwrap import textwrap
@@ -65,7 +66,6 @@ import logging.config
import logging.handlers import logging.handlers
from cmd import Cmd from cmd import Cmd
from struct import pack
from spinel.const import SPINEL from spinel.const import SPINEL
from spinel.const import kThread from spinel.const import kThread
@@ -79,6 +79,7 @@ import ipaddress
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.layers.inet6 import IPv6 from scapy.layers.inet6 import IPv6
from scapy.layers.inet6 import ICMPv6EchoReply
from scapy.layers.inet6 import ICMPv6EchoRequest from scapy.layers.inet6 import ICMPv6EchoRequest
@@ -96,9 +97,12 @@ class SpinelCliCmd(Cmd, SpinelCodec):
def __init__(self, stream_desc, nodeid, *_a, **kw): def __init__(self, stream_desc, nodeid, *_a, **kw):
self.nodeid = kw.get('nodeid', '1')
self.wpan_api = WpanApi(stream_desc, nodeid) self.wpan_api = WpanApi(stream_desc, nodeid)
self.wpan_api.queue_register(SPINEL.HEADER_DEFAULT) self.wpan_api.queue_register(SPINEL.HEADER_DEFAULT)
self.nodeid = kw.get('nodeid', '1') self.wpan_api.callback_register(SPINEL.PROP_STREAM_NET,
self.wpan_callback)
Cmd.__init__(self) Cmd.__init__(self)
Cmd.identchars = string.ascii_letters + string.digits + '-' Cmd.identchars = string.ascii_letters + string.digits + '-'
@@ -203,6 +207,26 @@ class SpinelCliCmd(Cmd, SpinelCodec):
] ]
@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 @classmethod
def log(cls, text): def log(cls, text):
""" Common log handler. """ """ Common log handler. """
@@ -908,11 +932,11 @@ class SpinelCliCmd(Cmd, SpinelCodec):
args = line.split(" ") args = line.split(" ")
if args[0] == "counter": if args[0] == "counter":
newline = line.replace("counter","") newline = line.replace("counter", "")
self.handle_property(newline, SPINEL.PROP_NET_KEY_SEQUENCE_COUNTER, 'L') self.handle_property(newline, SPINEL.PROP_NET_KEY_SEQUENCE_COUNTER, 'L')
elif args[0] == "guardtime": elif args[0] == "guardtime":
newline = line.replace("guardtime","") newline = line.replace("guardtime", "")
self.handle_property(newline, SPINEL.PROP_NET_KEY_SWITCH_GUARDTIME, 'L') self.handle_property(newline, SPINEL.PROP_NET_KEY_SWITCH_GUARDTIME, 'L')
def do_leaderdata(self, line): def do_leaderdata(self, line):
@@ -1028,7 +1052,7 @@ class SpinelCliCmd(Cmd, SpinelCodec):
try: try:
# remap string state names to integer # remap string state names to integer
line = map_arg_name[line] line = map_arg_name[line]
except KeyError, _ex: except KeyError:
print("Error") print("Error")
return return
@@ -1138,7 +1162,7 @@ class SpinelCliCmd(Cmd, SpinelCodec):
ml64 = self.prop_get_value(SPINEL.PROP_IPV6_ML_ADDR) ml64 = self.prop_get_value(SPINEL.PROP_IPV6_ML_ADDR)
ml64 = str(ipaddress.IPv6Address(ml64)) ml64 = str(ipaddress.IPv6Address(ml64))
timenow = int(round(time.time() * 1000)) & 0xFFFFFFFF timenow = int(round(time.time() * 1000)) & 0xFFFFFFFF
timenow = pack('>I', timenow) timenow = struct.pack('>I', timenow)
ping_req = str(IPv6(src=ml64, dst=addr) / ping_req = str(IPv6(src=ml64, dst=addr) /
ICMPv6EchoRequest() / timenow) ICMPv6EchoRequest() / timenow)
self.wpan_api.ip_send(ping_req) self.wpan_api.ip_send(ping_req)
@@ -1625,13 +1649,13 @@ class SpinelCliCmd(Cmd, SpinelCodec):
rssi = int(params[2]) rssi = int(params[2])
except: except:
rssi = SPINEL.RSSI_OVERRIDE rssi = SPINEL.RSSI_OVERRIDE
arr += pack('b', rssi) arr += struct.pack('b', rssi)
value = self.prop_insert_value(SPINEL.PROP_MAC_WHITELIST, arr, value = self.prop_insert_value(SPINEL.PROP_MAC_WHITELIST, arr,
str(len(arr)) + 's') str(len(arr)) + 's')
elif params[0] == "remove": elif params[0] == "remove":
arr = util.hex_to_bytes(params[1]) arr = util.hex_to_bytes(params[1])
arr += pack('b', SPINEL.RSSI_OVERRIDE) arr += struct.pack('b', SPINEL.RSSI_OVERRIDE)
value = self.prop_remove_value(SPINEL.PROP_MAC_WHITELIST, arr, value = self.prop_remove_value(SPINEL.PROP_MAC_WHITELIST, arr,
str(len(arr)) + 's') str(len(arr)) + 's')
+36 -34
View File
@@ -29,13 +29,20 @@
Module providing a Spienl coder / decoder class. Module providing a Spienl coder / decoder class.
""" """
from __future__ import print_function
import os import os
import sys
import time import time
import logging import logging
import threading import threading
import traceback import traceback
import Queue 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 pack
from struct import unpack from struct import unpack
@@ -44,10 +51,6 @@ from collections import defaultdict
import ipaddress import ipaddress
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.layers.inet6 import IPv6
from scapy.layers.inet6 import ICMPv6EchoReply
import spinel.util as util import spinel.util as util
import spinel.config as CONFIG import spinel.config as CONFIG
from spinel.const import kThread from spinel.const import kThread
@@ -161,8 +164,8 @@ class SpinelCodec(object):
} }
try: try:
return map_decode[spinel_format[0]](payload) return map_decode[spinel_format[0]](payload)
except KeyError, _ex: except KeyError:
print traceback.format_exc() print(traceback.format_exc())
return None return None
@classmethod @classmethod
@@ -232,8 +235,8 @@ class SpinelCodec(object):
} }
try: try:
return map_encode[code](value) return map_encode[code](value)
except KeyError, _ex: except KeyError:
print traceback.format_exc() print(traceback.format_exc())
return None return None
def next_code(self, spinel_format): def next_code(self, spinel_format):
@@ -400,7 +403,7 @@ class SpinelPropertyHandler(SpinelCodec):
ipaddr_str = str(ipaddress.IPv6Address(prefix)) + \ ipaddr_str = str(ipaddress.IPv6Address(prefix)) + \
str(self.wpan_api.nodeid) str(self.wpan_api.nodeid)
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
print "\n>>>> new PREFIX add ipaddr: " + ipaddr_str print("\n>>>> new PREFIX add ipaddr: " + ipaddr_str)
valid = 1 valid = 1
preferred = 1 preferred = 1
@@ -443,10 +446,10 @@ class SpinelPropertyHandler(SpinelCodec):
self.handle_ipaddr_insert(*prefix) self.handle_ipaddr_insert(*prefix)
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
print "\n========= PREFIX ============" print("\n========= PREFIX ============")
print "ipaddrs: " + str(self.autoAddresses) print("ipaddrs: " + str(self.autoAddresses))
print "slaac prefix set: " + str(slaacPrefixSet) print("slaac prefix set: " + str(slaacPrefixSet))
print "==============================\n" print("==============================\n")
# ==> ipaddrs - query current addresses # ==> ipaddrs - query current addresses
# #
@@ -584,8 +587,6 @@ class SpinelCommandHandler(SpinelCodec):
if ((prop_id == SPINEL.PROP_STREAM_NET) or if ((prop_id == SPINEL.PROP_STREAM_NET) or
(prop_id == SPINEL.PROP_STREAM_NET_INSECURE)): (prop_id == SPINEL.PROP_STREAM_NET_INSECURE)):
logging.debug("PROP_VALUE_" + name + ": " + prop_name) logging.debug("PROP_VALUE_" + name + ": " + prop_name)
pkt = IPv6(prop_value[2:])
pkt.show()
elif prop_id == SPINEL.PROP_STREAM_DEBUG: elif prop_id == SPINEL.PROP_STREAM_DEBUG:
logging.debug("DEBUG: " + prop_value) logging.debug("DEBUG: " + prop_value)
@@ -593,12 +594,12 @@ class SpinelCommandHandler(SpinelCodec):
if wpan_api: if wpan_api:
wpan_api.queue_add(prop_id, prop_value, tid) wpan_api.queue_add(prop_id, prop_value, tid)
else: else:
print "no wpan_api" print("no wpan_api")
except Exception as _ex: except Exception as _ex:
prop_name = "Property Unknown" prop_name = "Property Unknown"
logging.info("\n%s (%i): ", prop_name, prop_id) logging.info("\n%s (%i): ", prop_name, prop_id)
print traceback.format_exc() print(traceback.format_exc())
def PROP_VALUE_IS(self, wpan_api, payload, tid): def PROP_VALUE_IS(self, wpan_api, payload, tid):
self.handle_prop(wpan_api, "IS", payload, tid) self.handle_prop(wpan_api, "IS", payload, tid)
@@ -734,11 +735,12 @@ class WpanApi(SpinelCodec):
# PARSER state # PARSER state
self.rx_pkt = [] self.rx_pkt = []
self.callback = defaultdict(list) # Map prop_id to list of callbacks.
# Fire up threads # Fire up threads
self._reader_alive = True self._reader_alive = True
self.tid_filter = set() self.tid_filter = set()
self.__queue_prop = defaultdict(Queue.Queue) self.__queue_prop = defaultdict(Queue.Queue) # Map tid to Queue.
self.queue_register() self.queue_register()
self.__start_reader() self.__start_reader()
@@ -789,7 +791,7 @@ class WpanApi(SpinelCodec):
handler(self, payload, tid) handler(self, payload, tid)
except Exception as _ex: except Exception as _ex:
print traceback.format_exc() print(traceback.format_exc())
cmd_name = "CB_Unknown" cmd_name = "CB_Unknown"
logging.info("\n%s (%i): ", cmd_name, cmd_id) logging.info("\n%s (%i): ", cmd_name, cmd_id)
@@ -821,6 +823,9 @@ class WpanApi(SpinelCodec):
self.value = value self.value = value
self.tid = tid self.tid = tid
def callback_register(self, prop, cb):
self.callback[prop].append(cb)
def queue_register(self, tid=SPINEL.HEADER_DEFAULT): def queue_register(self, tid=SPINEL.HEADER_DEFAULT):
self.tid_filter.add(tid) self.tid_filter.add(tid)
return self.__queue_prop[tid] return self.__queue_prop[tid]
@@ -829,15 +834,12 @@ class WpanApi(SpinelCodec):
self.queue_clear(tid) self.queue_clear(tid)
def queue_add(self, prop, value, tid): def queue_add(self, prop, value, tid):
# Asynchronous handlers don't actually add to queue. cb_list = self.callback[prop]
if prop == SPINEL.PROP_STREAM_NET:
pkt = IPv6(value[2:]) # Asynchronous handlers can consume message and not add to queue.
if ICMPv6EchoReply in pkt: if len(cb_list) > 0:
timenow = int(round(time.time() * 1000)) & 0xFFFFFFFF consumed = cb_list[0](prop, value, tid)
timedelta = (timenow - unpack('>I', pkt.data)[0]) if consumed: return
print "\n%d bytes from %s: icmp_seq=%d hlim=%d time=%dms" % (
pkt.plen, pkt.src, pkt.seq, pkt.hlim, timedelta)
return
if tid not in self.tid_filter: if tid not in self.tid_filter:
return return
@@ -861,7 +863,7 @@ class WpanApi(SpinelCodec):
if os.geteuid() == 0: if os.geteuid() == 0:
self.tun_if = TunInterface(nodeid) self.tun_if = TunInterface(nodeid)
else: else:
print "Warning: superuser required to start tun interface." print("Warning: superuser required to start tun interface.")
def if_down(self): def if_down(self):
if self.tun_if: if self.tun_if:
@@ -922,7 +924,7 @@ class WpanApi(SpinelCodec):
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
handler = SPINEL_PROP_DISPATCH[prop_id] handler = SPINEL_PROP_DISPATCH[prop_id]
prop_name = handler.__name__ prop_name = handler.__name__
print "PROP_VALUE_GET [tid=%d]: %s" % (tid & 0xF, prop_name) print("PROP_VALUE_GET [tid=%d]: %s" % (tid & 0xF, prop_name))
return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_GET, prop_id, return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_GET, prop_id,
None, None, tid) None, None, tid)
@@ -932,7 +934,7 @@ class WpanApi(SpinelCodec):
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
handler = SPINEL_PROP_DISPATCH[prop_id] handler = SPINEL_PROP_DISPATCH[prop_id]
prop_name = handler.__name__ prop_name = handler.__name__
print "PROP_VALUE_SET [tid=%d]: %s" % (tid & 0xF, prop_name) print("PROP_VALUE_SET [tid=%d]: %s" % (tid & 0xF, prop_name))
return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_SET, prop_id, return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_SET, prop_id,
value, py_format, tid) value, py_format, tid)
@@ -942,7 +944,7 @@ class WpanApi(SpinelCodec):
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
handler = SPINEL_PROP_DISPATCH[prop_id] handler = SPINEL_PROP_DISPATCH[prop_id]
prop_name = handler.__name__ prop_name = handler.__name__
print "PROP_VALUE_INSERT [tid=%d]: %s" % (tid & 0xF, prop_name) print("PROP_VALUE_INSERT [tid=%d]: %s" % (tid & 0xF, prop_name))
return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_INSERT, prop_id, return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_INSERT, prop_id,
value, py_format, tid) value, py_format, tid)
@@ -952,7 +954,7 @@ class WpanApi(SpinelCodec):
if CONFIG.DEBUG_LOG_PROP: if CONFIG.DEBUG_LOG_PROP:
handler = SPINEL_PROP_DISPATCH[prop_id] handler = SPINEL_PROP_DISPATCH[prop_id]
prop_name = handler.__name__ prop_name = handler.__name__
print "PROP_VALUE_REMOVE [tid=%d]: %s" % (tid & 0xF, prop_name) print("PROP_VALUE_REMOVE [tid=%d]: %s" % (tid & 0xF, prop_name))
return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_REMOVE, prop_id, return self.__prop_change_value(SPINEL.CMD_PROP_VALUE_REMOVE, prop_id,
value, py_format, tid) value, py_format, tid)
+1 -1
View File
@@ -110,4 +110,4 @@ def debug_set_level(level):
DEBUG_STREAM_RX = 1 DEBUG_STREAM_RX = 1
DEBUG_STREAM_TX = 1 DEBUG_STREAM_TX = 1
print "DEBUG_ENABLE = " + str(DEBUG_ENABLE) print("DEBUG_ENABLE = " + str(DEBUG_ENABLE))
+7 -5
View File
@@ -31,6 +31,8 @@ Module providing a generic stream interface.
Also includes adapter implementations for serial, socket, and pipes. Also includes adapter implementations for serial, socket, and pipes.
""" """
from __future__ import print_function
import sys import sys
import logging import logging
import traceback import traceback
@@ -67,7 +69,7 @@ class StreamSerial(IStream):
self.serial = serial.Serial(dev, baudrate) self.serial = serial.Serial(dev, baudrate)
except: except:
logging.error("Couldn't open " + dev) logging.error("Couldn't open " + dev)
print traceback.format_exc() traceback.print_exc()
def write(self, data): def write(self, data):
self.serial.write(data) self.serial.write(data)
@@ -113,7 +115,7 @@ class StreamPipe(IStream):
stderr=sys.stdout.fileno()) stderr=sys.stdout.fileno())
except: except:
logging.error("Couldn't open " + filename) logging.error("Couldn't open " + filename)
print traceback.format_exc() traceback.print_exc()
def write(self, data): def write(self, data):
if CONFIG.DEBUG_STREAM_TX: if CONFIG.DEBUG_STREAM_TX:
@@ -151,21 +153,21 @@ def StreamOpen(stream_type, descriptor, verbose=True):
if stream_type == 'p': if stream_type == 'p':
if verbose: if verbose:
print "Opening pipe to " + str(descriptor) print("Opening pipe to " + str(descriptor))
return StreamPipe(descriptor) return StreamPipe(descriptor)
elif stream_type == 's': elif stream_type == 's':
port = int(descriptor) port = int(descriptor)
hostname = "localhost" hostname = "localhost"
if verbose: if verbose:
print "Opening socket to " + hostname + ":" + str(port) print("Opening socket to " + hostname + ":" + str(port))
return StreamSocket(hostname, port) return StreamSocket(hostname, port)
elif stream_type == 'u': elif stream_type == 'u':
dev = str(descriptor) dev = str(descriptor)
baudrate = 115200 baudrate = 115200
if verbose: if verbose:
print "Opening serial to " + dev + " @ " + str(baudrate) print("Opening serial to " + dev + " @ " + str(baudrate))
return StreamSerial(dev, baudrate) return StreamSerial(dev, baudrate)
else: else:
+25
View File
@@ -27,6 +27,7 @@
# #
""" Unittest for spinel.codec module. """ """ Unittest for spinel.codec module. """
import time
import unittest import unittest
from spinel.const import SPINEL from spinel.const import SPINEL
@@ -69,3 +70,27 @@ class TestCodec(unittest.TestCase):
# print "value "+util.hexify_str(value) # print "value "+util.hexify_str(value)
# print "truth "+util.hexify_str(truth_value) # print "truth "+util.hexify_str(truth_value)
self.failUnless(value == truth_value) self.failUnless(value == truth_value)
def cb_test_callback(self, prop, value, tid):
self.test_callback_pass = True
def test_callback(self):
""" Unit test of WpanApi.callback_register. """
vector = [
"800672340060000000000c3a40fe80000000000000020d6f00055715d3fddead00beef0000cd9bb7814c5619ea8100b0ca00000000267fc789" # PROP_STREAM_NET
]
mock_stream = MockStream({})
nodeid = 1
use_hdlc = False
wpan_api = WpanApi(mock_stream, nodeid, use_hdlc)
self.test_callback_pass = False
wpan_api.callback_register(SPINEL.PROP_STREAM_NET, self.cb_test_callback)
for pkt in vector:
mock_stream.write_child_hex(pkt)
time.sleep(0.1)
self.failUnless(self.test_callback_pass)
+4 -2
View File
@@ -27,6 +27,8 @@
# #
""" Utility class for creating TUN network interfaces on Linux and OSX. """ """ Utility class for creating TUN network interfaces on Linux and OSX. """
from __future__ import print_function
import os import os
import sys import sys
import fcntl import fcntl
@@ -103,7 +105,7 @@ class TunInterface(object):
def ping6(self, args): def ping6(self, args):
""" Ping an address. """ """ Ping an address. """
cmd = 'ping6 ' + args cmd = 'ping6 ' + args
print cmd print(cmd)
self.command(cmd) self.command(cmd)
def addr_add(self, addr): def addr_add(self, addr):
@@ -137,7 +139,7 @@ class TunInterface(object):
util.hexify_str(packet)) util.hexify_str(packet))
self.write(packet) self.write(packet)
except: except:
print traceback.format_exc() traceback.print_exc()
break break
logging.info("TUN: exiting") logging.info("TUN: exiting")