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