mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
spinel-cli: Stability improvements to ping (#561)
* Improve ping reliability by making it fully async. Eliminate 5_1_07 from XFAIL list. * Some non-core changes: readd missing StreamSocket class, improve handling of command.
This commit is contained in:
committed by
Jonathan Hui
parent
d8f9e5baa0
commit
bb84b9a1f2
@@ -63,8 +63,6 @@ DEBUG_LOG_TUN = 0
|
||||
DEBUG_TERM = 0
|
||||
DEBUG_CMD_RESPONSE = 0
|
||||
|
||||
|
||||
TIMEOUT_PING = 2
|
||||
TIMEOUT_PROP = 2
|
||||
|
||||
gWpanApi = None
|
||||
@@ -73,7 +71,7 @@ def goodbye(signum=None, frame=None):
|
||||
logger.info('\nQuitting')
|
||||
if gWpanApi:
|
||||
gWpanApi.serial.close()
|
||||
exit(1)
|
||||
exit(0)
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -113,6 +111,7 @@ from select import select
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
|
||||
from scapy.all import IPv6
|
||||
from scapy.all import ICMPv6EchoRequest
|
||||
from scapy.all import ICMPv6EchoReply
|
||||
|
||||
|
||||
MASTER_PROMPT = "spinel-cli"
|
||||
@@ -181,10 +180,6 @@ class Color:
|
||||
DARKCYAN = "\033[36m"
|
||||
WHITE = "\033[37m"
|
||||
|
||||
IP_TYPE_UDP = 17
|
||||
IP_TYPE_ICMPv6 = 58
|
||||
|
||||
|
||||
SPINEL_RSSI_OVERRIDE = 127
|
||||
|
||||
SPINEL_HEADER_ASYNC = 0x80
|
||||
@@ -589,6 +584,21 @@ class StreamSerial(IStream):
|
||||
logger.debug("RX Raw: "+hexify_bytes(b))
|
||||
return b
|
||||
|
||||
class StreamSocket(IStream):
|
||||
def __init__(self, sock):
|
||||
self.sock = sock
|
||||
|
||||
def write(self, data):
|
||||
self.sock.send(data)
|
||||
if DEBUG_LOG_TX:
|
||||
logger.debug("TX Raw: "+str(map(hexify_chr,data)))
|
||||
|
||||
def read(self, size=1):
|
||||
b = self.sock.recv(size)
|
||||
if DEBUG_LOG_RX_BYTES:
|
||||
logger.debug("RX Raw: "+str(map(hexify_chr,b)))
|
||||
return b
|
||||
|
||||
class StreamPipe(IStream):
|
||||
def __init__(self, filename):
|
||||
""" Create a stream object from a piped system call """
|
||||
@@ -979,6 +989,9 @@ class SpinelCommandHandler(SpinelCodec):
|
||||
pkt = IPv6(prop_value[2:])
|
||||
pkt.show()
|
||||
|
||||
elif (prop_op == SPINEL_PROP_STREAM_DEBUG):
|
||||
logger.debug("DEBUG: "+prop_value)
|
||||
|
||||
if gWpanApi:
|
||||
gWpanApi.queue_add(prop_op, prop_value, tid)
|
||||
else:
|
||||
@@ -1214,7 +1227,6 @@ class WpanApi(SpinelCodec):
|
||||
self.__queue_prop = Queue.Queue()
|
||||
self.__start_reader()
|
||||
self.tid_filter = SPINEL_HEADER_DEFAULT
|
||||
self.ip_type_filter = IP_TYPE_ICMPv6
|
||||
|
||||
def __del__(self):
|
||||
self._reader_alive = False
|
||||
@@ -1274,8 +1286,7 @@ class WpanApi(SpinelCodec):
|
||||
|
||||
|
||||
def serial_rx(self):
|
||||
# Recieve thread and parser
|
||||
|
||||
""" Recieve thread and parser. """
|
||||
while self._reader_alive:
|
||||
if self.useHdlc:
|
||||
self.rx_pkt = self.hdlc.collect()
|
||||
@@ -1297,15 +1308,18 @@ class WpanApi(SpinelCodec):
|
||||
def queue_wait_prepare(self, prop_id, tid=SPINEL_HEADER_DEFAULT):
|
||||
self.tid_filter = tid
|
||||
self.prop_filter = prop_id
|
||||
#print "Q tid_filter = "+str(self.tid_filter)
|
||||
self.queue_clear()
|
||||
|
||||
def queue_add(self, prop, value, tid):
|
||||
#print "Q add: tid="+str(tid)+" prop="+str(prop)+" tid_filter="+str(self.tid_filter)
|
||||
if (tid != self.tid_filter) or (prop != self.prop_filter): return
|
||||
if (self.prop_filter == SPINEL_PROP_STREAM_NET):
|
||||
# Asynchronous handlers don't actually add to queue.
|
||||
if (prop == SPINEL_PROP_STREAM_NET):
|
||||
pkt = IPv6(value[2:])
|
||||
if pkt.nh != self.ip_type_filter: return
|
||||
if ICMPv6EchoReply in pkt:
|
||||
print "\n%d bytes from %s: icmp_seq=%d hlim=%d time=%dms" % (
|
||||
pkt.plen, pkt.src, pkt.seq, pkt.hlim, 80)
|
||||
return
|
||||
|
||||
if (tid != self.tid_filter) or (prop != self.prop_filter): return
|
||||
item = self.PropertyItem(prop, value, tid)
|
||||
self.__queue_prop.put_nowait(item)
|
||||
|
||||
@@ -1320,15 +1334,12 @@ class WpanApi(SpinelCodec):
|
||||
return None
|
||||
|
||||
while (item):
|
||||
#print "Q rx: tid="+str(item.tid)+" prop="+str(item.prop)
|
||||
if (item.tid == self.tid_filter) and (item.prop == prop):
|
||||
return item
|
||||
if (self.__queue_prop.empty()):
|
||||
#logger.debug("Q rx: wrong response")
|
||||
return None
|
||||
else:
|
||||
item = self.__queue_prop.get_nowait()
|
||||
#logger.debug("Q rx: null item")
|
||||
return None
|
||||
|
||||
|
||||
@@ -1402,6 +1413,11 @@ class WpanApi(SpinelCodec):
|
||||
class WpanDiagsCmd(Cmd, SpinelCodec):
|
||||
|
||||
def __init__(self, device, *a, **kw):
|
||||
|
||||
self.wpanApi = WpanApi(device)
|
||||
global gWpanApi
|
||||
gWpanApi = self.wpanApi
|
||||
|
||||
Cmd.__init__(self)
|
||||
Cmd.identchars = string.ascii_letters + string.digits + '-'
|
||||
|
||||
@@ -1431,12 +1447,6 @@ class WpanDiagsCmd(Cmd, SpinelCodec):
|
||||
if sys.platform == 'darwin':
|
||||
readline.parse_and_bind("bind ^I rl_complete")
|
||||
|
||||
|
||||
# === Initialize Shell with some important parameters ==
|
||||
self.wpanApi = WpanApi(device)
|
||||
global gWpanApi
|
||||
gWpanApi = self.wpanApi
|
||||
|
||||
self.nodeid = kw.get('nodeid','1')
|
||||
self.prop_set_value(SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU, 1)
|
||||
self.prop_set_value(SPINEL_PROP_IPv6_ICMP_PING_OFFLOAD, 1)
|
||||
@@ -1698,16 +1708,22 @@ class WpanDiagsCmd(Cmd, SpinelCodec):
|
||||
Usage: debug <1=enable | 0=disable>
|
||||
"""
|
||||
global DEBUG_ENABLE, DEBUG_LOG_PKT, DEBUG_LOG_PROP
|
||||
global DEBUG_LOG_TX, DEBUG_LOG_RX
|
||||
global DEBUG_LOG_TX, DEBUG_LOG_RX, DEBUG_LOG_HDLC
|
||||
|
||||
if line != None and line != "":
|
||||
level = int(line)
|
||||
|
||||
if level:
|
||||
DEBUG_ENABLE = level
|
||||
if level >= 1: DEBUG_LOG_PROP = 1
|
||||
if level >= 2: DEBUG_LOG_PKT = 1
|
||||
if level >= 3: DEBUG_LOG_HDLC = 1
|
||||
else:
|
||||
DEBUG_ENABLE = 0
|
||||
DEBUG_LOG_PROP = 0
|
||||
DEBUG_LOG_PKT = 0
|
||||
DEBUG_LOG_HDLC = 0
|
||||
|
||||
if line: line = int(line)
|
||||
if line:
|
||||
DEBUG_ENABLE = 1
|
||||
else:
|
||||
DEBUG_ENABLE = 0
|
||||
#DEBUG_LOG_TX = DEBUG_ENABLE
|
||||
DEBUG_LOG_PKT = DEBUG_ENABLE
|
||||
DEBUG_LOG_PROP = DEBUG_ENABLE
|
||||
print "DEBUG_ENABLE = "+str(DEBUG_ENABLE)
|
||||
|
||||
def do_debugterm(self, line):
|
||||
@@ -2275,20 +2291,8 @@ class WpanDiagsCmd(Cmd, SpinelCodec):
|
||||
ML64 = self.prop_get_value(SPINEL_PROP_IPV6_ML_ADDR)
|
||||
ML64 = str(ipaddress.IPv6Address(ML64))
|
||||
ping_req = str(IPv6(src=ML64, dst=addr)/ICMPv6EchoRequest())
|
||||
self.wpanApi.queue_wait_prepare(SPINEL_PROP_STREAM_NET,
|
||||
SPINEL_HEADER_ASYNC)
|
||||
self.wpanApi.ip_send(ping_req)
|
||||
result = self.wpanApi.queue_wait_for_prop(SPINEL_PROP_STREAM_NET,
|
||||
TIMEOUT_PING)
|
||||
if result:
|
||||
pkt = IPv6(result.value[2:])
|
||||
print "%d bytes from %s: icmp_seq=%d hlim=%d time=%dms" % (
|
||||
pkt.plen, pkt.src, pkt.seq, pkt.hlim, 80)
|
||||
print("Done")
|
||||
else:
|
||||
# Don't output anything when ping fails
|
||||
#print "Fail"
|
||||
pass
|
||||
# Let handler print result
|
||||
except:
|
||||
print "Fail"
|
||||
print traceback.format_exc()
|
||||
@@ -2944,6 +2948,13 @@ class WpanDiagsCmd(Cmd, SpinelCodec):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# register clean exit handlers.
|
||||
signal.signal(signal.SIGHUP, goodbye)
|
||||
signal.signal(signal.SIGINT, goodbye)
|
||||
signal.signal(signal.SIGCONT, goodbye)
|
||||
signal.signal(signal.SIGABRT, goodbye)
|
||||
signal.signal(signal.SIGTERM, goodbye)
|
||||
signal.signal(signal.SIGPIPE, goodbye)
|
||||
|
||||
args = sys.argv[1:]
|
||||
|
||||
@@ -2985,13 +2996,6 @@ if __name__ == "__main__":
|
||||
stream = StreamOpen(streamType, streamDescriptor)
|
||||
shell = WpanDiagsCmd(stream, nodeid=options.nodeid)
|
||||
|
||||
# register clean exit handlers.
|
||||
signal.signal(signal.SIGHUP, goodbye)
|
||||
signal.signal(signal.SIGINT, goodbye)
|
||||
signal.signal(signal.SIGABRT, goodbye)
|
||||
signal.signal(signal.SIGTERM, goodbye)
|
||||
signal.signal(signal.SIGPIPE, goodbye)
|
||||
|
||||
try:
|
||||
shell.cmdloop()
|
||||
except KeyboardInterrupt:
|
||||
|
||||
Reference in New Issue
Block a user