Skip to content

Commit 7d2fc8e

Browse files
net: rpc: openthread: add networkdiagnostic APIs
Add APIs for getting and resetting network diagnostic TLVs. Signed-off-by: Maciej Baczmanski <maciej.baczmanski@nordicsemi.no>
1 parent 6e0664e commit 7d2fc8e

File tree

6 files changed

+905
-1
lines changed

6 files changed

+905
-1
lines changed

doc/nrf/libraries/networking/ot_rpc.rst

+3
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,14 @@ OpenThread RPC currently supports the serialization of the following OpenThread
162162
* :c:func:`otThreadGetMeshLocalPrefix`
163163
* :c:func:`otThreadGetMleCounters`
164164
* :c:func:`otThreadGetNetworkName`
165+
* :c:func:`otThreadGetNextDiagnosticTlv`
165166
* :c:func:`otThreadGetPartitionId`
166167
* :c:func:`otThreadGetVendorName`
167168
* :c:func:`otThreadGetVendorModel`
168169
* :c:func:`otThreadGetVendorSwVersion`
169170
* :c:func:`otThreadGetVersion`
171+
* :c:func:`otThreadSendDiagnosticGet`
172+
* :c:func:`otThreadSendDiagnosticReset`
170173
* :c:func:`otThreadSetEnabled`
171174
* :c:func:`otThreadSetLinkMode`
172175
* :c:func:`otThreadSetVendorName`

samples/nrf_rpc/protocols_serialization/client/src/ot_shell.c

+251
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ static void service_free(otSrpClientService *service)
7979
}
8080
}
8181

82+
static void print_bytes(const uint8_t *data, size_t data_len)
83+
{
84+
printk("Data:\n");
85+
for (size_t i = 0; i < data_len; i++) {
86+
printk("%02x", data[i]);
87+
if ((i + 1) % 16 == 0) {
88+
printk("\n");
89+
} else if ((i + 1) % 8 == 0) {
90+
printk(" ");
91+
}
92+
}
93+
printk("\n");
94+
}
95+
8296
static int ot_cli_output_cb(void *context, const char *format, va_list arg)
8397
{
8498
const struct shell *sh = context;
@@ -1042,6 +1056,240 @@ static int cmd_test_vendor_data(const struct shell *sh, size_t argc, char *argv[
10421056
return 0;
10431057
}
10441058

1059+
static void handle_receive_diagnostic_get(otError aError, otMessage *aMessage,
1060+
const otMessageInfo *aMessageInfo, void *aContext)
1061+
{
1062+
otNetworkDiagTlv diagTlv;
1063+
otNetworkDiagIterator iterator = OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT;
1064+
1065+
char addr_string[NET_IPV6_ADDR_LEN];
1066+
1067+
ARG_UNUSED(aContext);
1068+
1069+
if (!net_addr_ntop(AF_INET6, aMessageInfo->mPeerAddr.mFields.m8,
1070+
addr_string, sizeof(addr_string))) {
1071+
printk("Failed to convert the IPv6 address");
1072+
return;
1073+
}
1074+
1075+
printk("------------------------------------------------------------------\n");
1076+
printk("Received DIAG_GET.rsp/ans from %s\n", addr_string);
1077+
1078+
while (otThreadGetNextDiagnosticTlv(aMessage, &iterator, &diagTlv) == OT_ERROR_NONE) {
1079+
printk("\nTLV type: 0x%x ", diagTlv.mType);
1080+
switch (diagTlv.mType) {
1081+
case OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS:
1082+
printk("(MAC Extended Address TLV)\n");
1083+
print_bytes(diagTlv.mData.mExtAddress.m8, OT_EXT_ADDRESS_SIZE);
1084+
break;
1085+
case OT_NETWORK_DIAGNOSTIC_TLV_EUI64:
1086+
printk("(EUI64 TLV)\n");
1087+
print_bytes(diagTlv.mData.mEui64.m8, OT_EXT_ADDRESS_SIZE);
1088+
break;
1089+
case OT_NETWORK_DIAGNOSTIC_TLV_MODE:
1090+
printk("(Mode TLV)\n");
1091+
printk("RX on when idle: %s\n", diagTlv.mData.mMode.mRxOnWhenIdle ?
1092+
"true" : "false");
1093+
printk("Device type: %s\n", diagTlv.mData.mMode.mDeviceType ?
1094+
"true" : "false");
1095+
printk("Network data: %s\n", diagTlv.mData.mMode.mNetworkData ?
1096+
"true" : "false");
1097+
break;
1098+
case OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY:
1099+
printk("(Connectivity TLV)\n");
1100+
printk("Parent priority: %d\n",
1101+
diagTlv.mData.mConnectivity.mParentPriority);
1102+
printk("Link quality 3: %u\n", diagTlv.mData.mConnectivity.mLinkQuality3);
1103+
printk("Link quality 2: %u\n", diagTlv.mData.mConnectivity.mLinkQuality2);
1104+
printk("Link quality 1: %u\n", diagTlv.mData.mConnectivity.mLinkQuality1);
1105+
printk("Leader cost: %u\n", diagTlv.mData.mConnectivity.mLeaderCost);
1106+
printk("ID sequence: %u\n", diagTlv.mData.mConnectivity.mIdSequence);
1107+
printk("Active routers: %u\n", diagTlv.mData.mConnectivity.mActiveRouters);
1108+
printk("SED buffer size: %u\n",
1109+
diagTlv.mData.mConnectivity.mSedBufferSize);
1110+
printk("SED datagram count: %u\n",
1111+
diagTlv.mData.mConnectivity.mSedDatagramCount);
1112+
break;
1113+
case OT_NETWORK_DIAGNOSTIC_TLV_ROUTE:
1114+
printk("(Route64 TLV)\n");
1115+
printk("ID sequence: %u\n", diagTlv.mData.mRoute.mIdSequence);
1116+
printk("Route count: %u\n\n", diagTlv.mData.mRoute.mRouteCount);
1117+
1118+
for (int i = 0; i < diagTlv.mData.mRoute.mRouteCount; i++) {
1119+
printk("Router ID: %u\n",
1120+
diagTlv.mData.mRoute.mRouteData[i].mRouterId);
1121+
printk("Link quality in: %u\n",
1122+
diagTlv.mData.mRoute.mRouteData[i].mLinkQualityIn);
1123+
printk("Link quality out: %u\n",
1124+
diagTlv.mData.mRoute.mRouteData[i].mLinkQualityOut);
1125+
printk("Route cost: %u\n\n",
1126+
diagTlv.mData.mRoute.mRouteData[i].mRouteCost);
1127+
}
1128+
break;
1129+
case OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA:
1130+
printk("(Leader Data TLV)\n");
1131+
printk("Partition ID: 0x%x\n", diagTlv.mData.mLeaderData.mPartitionId);
1132+
printk("Weighting: %u\n", diagTlv.mData.mLeaderData.mWeighting);
1133+
printk("Data version: %u\n", diagTlv.mData.mLeaderData.mDataVersion);
1134+
printk("Stable data version: %u\n",
1135+
diagTlv.mData.mLeaderData.mStableDataVersion);
1136+
printk("Leader router ID: 0x%x\n",
1137+
diagTlv.mData.mLeaderData.mLeaderRouterId);
1138+
break;
1139+
case OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS:
1140+
printk("(MAC Counters TLV)\n");
1141+
printk("IfInUnknownProtos: %u\n",
1142+
diagTlv.mData.mMacCounters.mIfInUnknownProtos);
1143+
printk("IfInErrors: %u\n", diagTlv.mData.mMacCounters.mIfInErrors);
1144+
printk("IfOutErrors: %u\n", diagTlv.mData.mMacCounters.mIfOutErrors);
1145+
printk("IfInUcastPkts: %u\n", diagTlv.mData.mMacCounters.mIfInUcastPkts);
1146+
printk("IfInBroadcastPkts: %u\n",
1147+
diagTlv.mData.mMacCounters.mIfInBroadcastPkts);
1148+
printk("IfInDiscards: %u\n", diagTlv.mData.mMacCounters.mIfInDiscards);
1149+
printk("IfOutUcastPkts: %u\n", diagTlv.mData.mMacCounters.mIfOutUcastPkts);
1150+
printk("IfOutBroadcastPkts: %u\n",
1151+
diagTlv.mData.mMacCounters.mIfOutBroadcastPkts);
1152+
printk("IfOutDiscards: %u\n", diagTlv.mData.mMacCounters.mIfOutDiscards);
1153+
break;
1154+
case OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS:
1155+
printk("(MLE Counters TLV)\n");
1156+
printk("DisabledRole: %u\n", diagTlv.mData.mMleCounters.mDisabledRole);
1157+
printk("DetachedRole: %u\n", diagTlv.mData.mMleCounters.mDetachedRole);
1158+
printk("ChildRole: %u\n", diagTlv.mData.mMleCounters.mChildRole);
1159+
printk("RouterRole: %u\n", diagTlv.mData.mMleCounters.mRouterRole);
1160+
printk("LeaderRole: %u\n", diagTlv.mData.mMleCounters.mLeaderRole);
1161+
printk("AttachAttempts: %u\n", diagTlv.mData.mMleCounters.mAttachAttempts);
1162+
printk("PartitionIdChanges: %u\n",
1163+
diagTlv.mData.mMleCounters.mPartitionIdChanges);
1164+
printk("BetterPartitionAttachAttempts: %u\n",
1165+
diagTlv.mData.mMleCounters.mBetterPartitionAttachAttempts);
1166+
printk("ParentChanges: %u\n", diagTlv.mData.mMleCounters.mParentChanges);
1167+
printk("TrackedTime: %llu\n", diagTlv.mData.mMleCounters.mTrackedTime);
1168+
printk("DisabledTime: %llu\n", diagTlv.mData.mMleCounters.mDisabledTime);
1169+
printk("DetachedTime: %llu\n", diagTlv.mData.mMleCounters.mDetachedTime);
1170+
printk("ChildTime: %llu\n", diagTlv.mData.mMleCounters.mChildTime);
1171+
printk("RouterTime: %llu\n", diagTlv.mData.mMleCounters.mRouterTime);
1172+
printk("LeaderTime: %llu\n", diagTlv.mData.mMleCounters.mLeaderTime);
1173+
break;
1174+
case OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL:
1175+
printk("(Battery Level TLV)\n");
1176+
printk("Battery level: %u\n", diagTlv.mData.mBatteryLevel);
1177+
break;
1178+
case OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT:
1179+
printk("(Timeout TLV)\n");
1180+
printk("Timeout: %u\n", diagTlv.mData.mTimeout);
1181+
break;
1182+
case OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT:
1183+
printk("(Max Child Timeout TLV)\n");
1184+
printk("Max child timeout: %u\n", diagTlv.mData.mMaxChildTimeout);
1185+
break;
1186+
case OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS:
1187+
printk("(Address16 TLV)\n");
1188+
printk("Rloc16: 0x%x\n", diagTlv.mData.mAddr16);
1189+
break;
1190+
case OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE:
1191+
printk("(Supply Voltage TLV)\n");
1192+
printk("Supply voltage: %u\n", diagTlv.mData.mSupplyVoltage);
1193+
break;
1194+
case OT_NETWORK_DIAGNOSTIC_TLV_VERSION:
1195+
printk("(Thread Version TLV)\n");
1196+
printk("Version: %u\n", diagTlv.mData.mVersion);
1197+
break;
1198+
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME:
1199+
printk("(Vendor Name TLV)\n");
1200+
printk("Vendor name: %s\n", diagTlv.mData.mVendorName);
1201+
break;
1202+
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL:
1203+
printk("(Vendor Model TLV)\n");
1204+
printk("Vendor model: %s\n", diagTlv.mData.mVendorModel);
1205+
break;
1206+
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION:
1207+
printk("(Vendor SW Version TLV)\n");
1208+
printk("Vendor SW version: %s\n", diagTlv.mData.mVendorSwVersion);
1209+
break;
1210+
case OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION:
1211+
printk("(Thread Stack Version TLV)\n");
1212+
printk("Thread stack version: %s\n", diagTlv.mData.mThreadStackVersion);
1213+
break;
1214+
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL:
1215+
printk("(Vendor App URL TLV)\n");
1216+
printk("Vendor app URL: %s\n", diagTlv.mData.mVendorAppUrl);
1217+
break;
1218+
case OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA:
1219+
printk("(Network Data TLV)\n");
1220+
print_bytes(diagTlv.mData.mNetworkData.m8,
1221+
diagTlv.mData.mNetworkData.mCount);
1222+
break;
1223+
case OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES:
1224+
printk("(Channel Pages TLV)\n");
1225+
print_bytes(diagTlv.mData.mChannelPages.m8,
1226+
diagTlv.mData.mChannelPages.mCount);
1227+
break;
1228+
case OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST:
1229+
printk("(IPv6 Address List TLV)\n");
1230+
for (int i = 0; i < diagTlv.mData.mIp6AddrList.mCount; i++) {
1231+
print_bytes(diagTlv.mData.mIp6AddrList.mList[i].mFields.m8,
1232+
OT_IP6_ADDRESS_SIZE);
1233+
}
1234+
break;
1235+
case OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE:
1236+
printk("(Child Table TLV)\n");
1237+
for (int i = 0; i < diagTlv.mData.mChildTable.mCount; i++) {
1238+
printk("Child ID: %u\n",
1239+
diagTlv.mData.mChildTable.mTable[i].mChildId);
1240+
printk("Timeout: %u\n",
1241+
diagTlv.mData.mChildTable.mTable[i].mTimeout);
1242+
printk("Link quality: %u\n",
1243+
diagTlv.mData.mChildTable.mTable[i].mLinkQuality);
1244+
printk("RX on when idle: %s\n",
1245+
diagTlv.mData.mChildTable.mTable[i].mMode.mRxOnWhenIdle ?
1246+
"true" : "false");
1247+
printk("Device type: %s\n",
1248+
diagTlv.mData.mChildTable.mTable[i].mMode.mDeviceType ?
1249+
"true" : "false");
1250+
printk("Network data: %s\n",
1251+
diagTlv.mData.mChildTable.mTable[i].mMode.mNetworkData ?
1252+
"true" : "false");
1253+
}
1254+
break;
1255+
1256+
default:
1257+
printk("(Unknown TLV)\n");
1258+
}
1259+
}
1260+
}
1261+
1262+
static int cmd_test_net_diag(const struct shell *sh, size_t argc, char *argv[])
1263+
{
1264+
uint8_t tlv_types[35];
1265+
uint8_t count = 0;
1266+
otIp6Address addr;
1267+
1268+
if (net_addr_pton(AF_INET6, argv[2], addr.mFields.m8)) {
1269+
shell_error(sh, "Failed to parse IPv6 address: %s", argv[1]);
1270+
return -EINVAL;
1271+
}
1272+
1273+
for (int arg = 3; arg < argc; ++arg) {
1274+
tlv_types[count] = shell_strtoul(argv[arg], 0, NULL);
1275+
count++;
1276+
}
1277+
1278+
if (strcmp(argv[1], "get") == 0) {
1279+
otThreadSendDiagnosticGet(NULL, &addr, tlv_types, count,
1280+
handle_receive_diagnostic_get, NULL);
1281+
1282+
} else if (strcmp(argv[1], "reset") == 0) {
1283+
otThreadSendDiagnosticReset(NULL, &addr, tlv_types, count);
1284+
1285+
} else {
1286+
shell_error(sh, "Invalid argument %s", argv[1]);
1287+
return -EINVAL;
1288+
}
1289+
1290+
return 0;
1291+
}
1292+
10451293
static void print_txt_entry(const struct shell *sh, const otDnsTxtEntry *entry)
10461294
{
10471295
char buffer[128];
@@ -1592,6 +1840,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
15921840
SHELL_CMD_ARG(test_vendor_data, NULL, "Vendor data, args: <vendor-name> <vendor-model>"
15931841
" <vendor-sw-version>",
15941842
cmd_test_vendor_data, 4, 0),
1843+
SHELL_CMD_ARG(test_net_diag, NULL, "Network diag, args: <get|reset> <IPv6-address>"
1844+
" <tlv-type ...>",
1845+
cmd_test_net_diag, 4, 255),
15951846
SHELL_SUBCMD_SET_END);
15961847

15971848
SHELL_CMD_ARG_REGISTER(ot, &ot_cmds,

0 commit comments

Comments
 (0)