Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/infuse_iot/generated/rpc_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,18 @@ class rpc_struct_public_key_info_256bit(VLACompatLittleEndianStruct):
_pack_ = 1


class rpc_struct_thread_stats(VLACompatLittleEndianStruct):
"""IPv6 address"""

_fields_ = [
("stack_size", ctypes.c_uint32),
("stack_used", ctypes.c_uint32),
("utilization", ctypes.c_uint8),
]
vla_field = ("name", 0 * ctypes.c_char)
_pack_ = 1


class rpc_enum_bt_le_addr_type(enum.IntEnum):
"""Bluetooth LE address type"""

Expand Down Expand Up @@ -872,6 +884,25 @@ class response(VLACompatLittleEndianStruct):
_pack_ = 1


class thread_stats(RPCDefinitionBase):
"""Query runtime thread statistics"""

NAME = "thread_stats"
HELP = "Query runtime thread statistics"
DESCRIPTION = "Query runtime thread statistics"
COMMAND_ID = 26

class request(VLACompatLittleEndianStruct):
_fields_ = []
_pack_ = 1

class response(VLACompatLittleEndianStruct):
_fields_ = [
("num_threads", ctypes.c_uint16),
]
_pack_ = 1


class coap_download(RPCDefinitionBase):
"""Download a file from a COAP server (Infuse-IoT DTLS protected)"""

Expand Down Expand Up @@ -1334,6 +1365,7 @@ class response(VLACompatLittleEndianStruct):
lte_state_v2.COMMAND_ID: lte_state_v2,
data_logger_state_v2.COMMAND_ID: data_logger_state_v2,
data_logger_read_chunks.COMMAND_ID: data_logger_read_chunks,
thread_stats.COMMAND_ID: thread_stats,
coap_download.COMMAND_ID: coap_download,
zperf_upload.COMMAND_ID: zperf_upload,
coap_download_v2.COMMAND_ID: coap_download_v2,
Expand Down Expand Up @@ -1373,6 +1405,7 @@ class response(VLACompatLittleEndianStruct):
"rpc_struct_heap_info",
"rpc_struct_data_logger_chunk",
"rpc_struct_public_key_info_256bit",
"rpc_struct_thread_stats",
"rpc_enum_bt_le_addr_type",
"rpc_enum_file_action",
"rpc_enum_infuse_bt_characteristic",
Expand Down Expand Up @@ -1406,6 +1439,7 @@ class response(VLACompatLittleEndianStruct):
"lte_state_v2",
"data_logger_state_v2",
"data_logger_read_chunks",
"thread_stats",
"coap_download",
"zperf_upload",
"coap_download_v2",
Expand Down
8 changes: 6 additions & 2 deletions src/infuse_iot/rpc_wrappers/security_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ def add_parser(cls, parser):
parser.add_argument("--pem", type=ValidFile, help="Cloud .pem file for identity validation")

def __init__(self, args):
self.challenge = bytes_to_uint8(random.randbytes(16))
self.challenge = random.randbytes(16)
self.pem = args.pem

def auth_level(self):
return Auth.NETWORK

def request_struct(self):
return self.request(self.challenge)
return self.request(bytes_to_uint8(self.challenge))

def _decrypt_response(self, response):
rsp = response.response
Expand Down Expand Up @@ -87,13 +87,17 @@ def handle_response(self, return_code, response):
print(f"Failed to query current time ({errno.strerror(-return_code)})")
return

print("Challenge:")
print(f"\t Challenge Bytes: {bytes(self.challenge).hex()}")

# Decrypt identity information
print("Security State:")
print(f"\tDevice Public Key: {bytes(response.device_public_key).hex()}")
print(f"\t Cloud Public Key: {bytes(response.cloud_public_key).hex()}")
print(f"\t Network: 0x{response.network_id:06x}")
if self.pem is None:
print("\t Identity: Cannot validate")
print(f"\t Raw: {bytes(response.challenge_response).hex()}")
else:
challenge_rsp = self._decrypt_response(response)

Expand Down
53 changes: 53 additions & 0 deletions src/infuse_iot/rpc_wrappers/thread_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3

import ctypes

import tabulate

import infuse_iot.definitions.rpc as defs
from infuse_iot.commands import InfuseRpcCommand
from infuse_iot.zephyr.errno import errno


class thread_stats(InfuseRpcCommand, defs.thread_stats):
RPC_DATA_RECEIVE = True

@classmethod
def add_parser(cls, parser):
sort = parser.add_mutually_exclusive_group()
sort.add_argument("--sort-stack", action="store_true", help="Sort threads by stack usage (%)")

def __init__(self, args):
self.args = args
self._info = []

def request_struct(self):
return self.request()

def request_json(self):
return {}

def data_recv_cb(self, offset: int, data: bytes) -> None:
base_size = ctypes.sizeof(defs.rpc_struct_thread_stats)
while len(data) > 0:
base = defs.rpc_struct_thread_stats.from_buffer_copy(data)
data = data[base_size:]
name_len = data.find(b"\x00") + 1
name = data[:name_len].decode()
data = data[name_len:]
percent = int(100 * base.stack_used / base.stack_size)
self._info.append((name, base.stack_used, base.stack_size, percent, base.utilization))

def handle_response(self, return_code, response):
if return_code != 0:
print(f"Failed to query thread stats ({errno.strerror(-return_code)})")
return

if self.args.sort_stack:
# Sort by stack usage
display = sorted(self._info, key=lambda x: x[3], reverse=True)
else:
display = self._info

headings = ["Thread", "Stack Used", "Stack Size", "Stack %", "CPU %"]
print(tabulate.tabulate(display, headers=headings))