Coverage Report

Created: 2025-12-14 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wpantund/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.cpp
Line
Count
Source
1
/*
2
 *
3
 * Copyright (c) 2016 Nest Labs, Inc.
4
 * All rights reserved.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 *
18
 */
19
20
#if HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include "assert-macros.h"
25
#include <syslog.h>
26
#include <errno.h>
27
#include "SpinelNCPTaskGetNetworkTopology.h"
28
#include "SpinelNCPInstance.h"
29
#include "spinel-extra.h"
30
31
using namespace nl;
32
using namespace nl::wpantund;
33
34
nl::wpantund::SpinelNCPTaskGetNetworkTopology::TableEntry::TableEntry(void)
35
3.62k
{
36
3.62k
  clear();
37
3.62k
}
38
39
void
40
nl::wpantund::SpinelNCPTaskGetNetworkTopology::TableEntry::clear(void)
41
6.42k
{
42
6.42k
  memset(mExtAddress, 0, sizeof(mExtAddress));
43
6.42k
  mRloc16 = 0;
44
6.42k
  mAge = 0;
45
6.42k
  mLinkQualityIn = 0;
46
6.42k
  mAverageRssi = 0;
47
6.42k
  mLastRssi = 0;
48
6.42k
  mRxOnWhenIdle = false;
49
6.42k
  mSecureDataRequest = false;
50
6.42k
  mFullFunction = false;
51
6.42k
  mFullNetworkData = false;
52
6.42k
  mTimeout = 0;
53
6.42k
  mNetworkDataVersion = 0;
54
6.42k
  mLinkFrameCounter = 0;
55
6.42k
  mMleFrameCounter = 0;
56
6.42k
  mIsChild = false;
57
6.42k
  mRouterId = 0;
58
6.42k
  mNextHop = 0;
59
6.42k
  mPathCost = 0;
60
6.42k
  mLinkQualityOut = 0;
61
6.42k
  mLinkEstablished = false;
62
6.42k
  mIPv6Addresses.clear();
63
6.42k
  mFrameErrorRate = 0;
64
6.42k
  mMessageErrorRate = 0;
65
6.42k
}
66
67
nl::wpantund::SpinelNCPTaskGetNetworkTopology::SpinelNCPTaskGetNetworkTopology(
68
  SpinelNCPInstance* instance,
69
  CallbackWithStatusArg1 cb,
70
  Type table_type,
71
  ResultFormat result_format
72
0
) : SpinelNCPTask(instance, cb), mType(table_type), mTable(), mResultFormat(result_format)
73
0
{
74
0
}
75
76
int
77
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_table(
78
  Type type,
79
  const uint8_t *data_in,
80
  spinel_size_t data_len,
81
  Table& table
82
2.10k
) {
83
2.10k
  int ret = kWPANTUNDStatus_Ok;
84
85
2.10k
  table.clear();
86
87
2.82k
  while (data_len > 0) {
88
2.42k
    spinel_ssize_t len = 0;
89
2.42k
    const uint8_t *struct_data;
90
2.42k
    spinel_size_t struct_len;
91
2.42k
    TableEntry entry;
92
93
2.42k
    len = spinel_datatype_unpack(
94
2.42k
      data_in,
95
2.42k
      data_len,
96
2.42k
      SPINEL_DATATYPE_DATA_WLEN_S,
97
2.42k
      &struct_data,
98
2.42k
      &struct_len
99
2.42k
    );
100
101
2.42k
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
102
103
1.60k
    switch (type)
104
1.60k
    {
105
257
    case kChildTable:
106
257
      ret = parse_child_entry(struct_data, struct_len, entry);
107
257
      break;
108
109
0
    case kChildTableAddresses:
110
0
      ret = parse_child_addresses_entry(struct_data, struct_len, entry);
111
0
      break;
112
113
516
    case kNeighborTable:
114
516
      ret = parse_neighbor_entry(struct_data, struct_len, entry);
115
516
      break;
116
117
236
    case kNeighborTableErrorRates:
118
236
      ret = parse_neighbor_error_rates_entry(struct_data, struct_len, entry);
119
236
      break;
120
121
594
    case kRouterTable:
122
594
      ret = parse_router_entry(struct_data, struct_len, entry);
123
594
      break;
124
1.60k
    }
125
126
1.60k
    require_noerr(ret, bail);
127
128
716
    table.push_back(entry);
129
130
716
    data_in += len;
131
716
    data_len -= len;
132
716
  }
133
134
2.10k
bail:
135
2.10k
  return ret;
136
2.10k
}
137
138
int
139
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_child_table(
140
  const uint8_t *data_in,
141
  spinel_size_t data_len,
142
  Table& child_table
143
807
) {
144
807
  return parse_table(kChildTable, data_in, data_len, child_table);
145
807
}
146
147
int
148
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_child_addresses_table(
149
  const uint8_t *data_in,
150
  spinel_size_t data_len,
151
  Table& child_addr_table
152
0
) {
153
0
  return parse_table(kChildTableAddresses, data_in, data_len, child_addr_table);
154
0
}
155
156
int
157
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_neighbor_table(
158
  const uint8_t *data_in,
159
  spinel_size_t data_len,
160
  Table& neighbor_table
161
485
) {
162
485
  return parse_table(kNeighborTable, data_in, data_len, neighbor_table);
163
485
}
164
165
int
166
nl::wpantund::SpinelNCPTaskGetNetworkTopology::prase_neighbor_error_rates_table(
167
  const uint8_t *data_in,
168
  spinel_size_t data_len,
169
  Table& neighbor_err_rate_table
170
207
) {
171
207
  return parse_table(kNeighborTableErrorRates, data_in, data_len, neighbor_err_rate_table);
172
207
}
173
174
int
175
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_router_table(
176
  const uint8_t *data_in,
177
  spinel_size_t data_len,
178
  Table& router_table
179
608
) {
180
608
  return parse_table(kRouterTable, data_in, data_len, router_table);
181
608
}
182
183
int
184
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_child_entry(
185
  const uint8_t *data_in,
186
  spinel_size_t data_len,
187
  TableEntry& child_info
188
844
) {
189
844
  int ret = kWPANTUNDStatus_Ok;
190
844
  spinel_ssize_t len = 0;
191
844
  const spinel_eui64_t *eui64 = NULL;
192
844
  uint8_t mode;
193
194
844
  child_info.clear();
195
844
  child_info.mType = kChildTable;
196
197
844
  len = spinel_datatype_unpack(
198
844
    data_in,
199
844
    data_len,
200
844
    (
201
844
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
202
      SPINEL_DATATYPE_UINT16_S        // Rloc16
203
      SPINEL_DATATYPE_UINT32_S        // Timeout
204
      SPINEL_DATATYPE_UINT32_S        // Age
205
      SPINEL_DATATYPE_UINT8_S         // Network Data Version
206
      SPINEL_DATATYPE_UINT8_S         // Link Quality In
207
      SPINEL_DATATYPE_INT8_S          // Average RSS
208
      SPINEL_DATATYPE_UINT8_S         // Mode (flags)
209
844
      SPINEL_DATATYPE_INT8_S          // Last Rssi
210
844
    ),
211
844
    &eui64,
212
844
    &child_info.mRloc16,
213
844
    &child_info.mTimeout,
214
844
    &child_info.mAge,
215
844
    &child_info.mNetworkDataVersion,
216
844
    &child_info.mLinkQualityIn,
217
844
    &child_info.mAverageRssi,
218
844
    &mode,
219
844
    &child_info.mLastRssi
220
844
  );
221
222
844
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
223
224
316
  memcpy(child_info.mExtAddress, eui64, sizeof(child_info.mExtAddress));
225
226
316
  child_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
227
316
  child_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
228
316
  child_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
229
316
  child_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
230
231
844
bail:
232
844
  return ret;
233
316
}
234
235
int
236
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_child_addresses_entry(
237
  const uint8_t *data_in,
238
  spinel_size_t data_len,
239
  TableEntry& child_addr_info
240
0
) {
241
0
  int ret = kWPANTUNDStatus_Ok;
242
0
  spinel_ssize_t len = 0;
243
0
  const spinel_eui64_t *eui64 = NULL;
244
0
  struct in6_addr *ip6_addr = NULL;
245
246
0
  child_addr_info.clear();
247
0
  child_addr_info.mType = kChildTableAddresses;
248
249
0
  len = spinel_datatype_unpack(
250
0
    data_in,
251
0
    data_len,
252
0
    (
253
0
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
254
0
      SPINEL_DATATYPE_UINT16_S        // Rloc16
255
0
    ),
256
0
    &eui64,
257
0
    &child_addr_info.mRloc16
258
0
  );
259
260
0
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
261
262
0
  memcpy(child_addr_info.mExtAddress, eui64, sizeof(child_addr_info.mExtAddress));
263
264
0
  data_in += len;
265
0
  data_len -= len;
266
267
0
  while (data_len > 0) {
268
0
    len = spinel_datatype_unpack(
269
0
      data_in,
270
0
      data_len,
271
0
      SPINEL_DATATYPE_IPv6ADDR_S,
272
0
      &ip6_addr
273
0
    );
274
275
0
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
276
277
0
    child_addr_info.mIPv6Addresses.push_back(*ip6_addr);
278
279
0
    data_in += len;
280
0
    data_len -= len;
281
0
  }
282
283
0
bail:
284
0
  return ret;
285
0
}
286
287
int
288
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_neighbor_entry(
289
  const uint8_t *data_in,
290
  spinel_size_t data_len,
291
  TableEntry& neighbor_info
292
1.12k
) {
293
1.12k
  int ret = kWPANTUNDStatus_Ok;
294
1.12k
  spinel_ssize_t len = 0;
295
1.12k
  const spinel_eui64_t *eui64 = NULL;
296
1.12k
  uint8_t mode;
297
1.12k
  bool is_child = false;
298
299
1.12k
  neighbor_info.clear();
300
1.12k
  neighbor_info.mType = kNeighborTable;
301
302
1.12k
  len = spinel_datatype_unpack(
303
1.12k
    data_in,
304
1.12k
    data_len,
305
1.12k
    (
306
1.12k
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
307
      SPINEL_DATATYPE_UINT16_S        // Rloc16
308
      SPINEL_DATATYPE_UINT32_S        // Age
309
      SPINEL_DATATYPE_UINT8_S         // Link Quality In
310
      SPINEL_DATATYPE_INT8_S          // Average RSS
311
      SPINEL_DATATYPE_UINT8_S         // Mode (flags)
312
      SPINEL_DATATYPE_BOOL_S          // Is Child
313
      SPINEL_DATATYPE_UINT32_S        // Link Frame Counter
314
      SPINEL_DATATYPE_UINT32_S        // MLE Frame Counter
315
1.12k
      SPINEL_DATATYPE_INT8_S          // Last Rssi
316
1.12k
    ),
317
1.12k
    &eui64,
318
1.12k
    &neighbor_info.mRloc16,
319
1.12k
    &neighbor_info.mAge,
320
1.12k
    &neighbor_info.mLinkQualityIn,
321
1.12k
    &neighbor_info.mAverageRssi,
322
1.12k
    &mode,
323
1.12k
    &is_child,
324
1.12k
    &neighbor_info.mLinkFrameCounter,
325
1.12k
    &neighbor_info.mMleFrameCounter,
326
1.12k
    &neighbor_info.mLastRssi
327
1.12k
  );
328
329
1.12k
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
330
331
307
  memcpy(neighbor_info.mExtAddress, eui64, sizeof(neighbor_info.mExtAddress));
332
333
307
  neighbor_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
334
307
  neighbor_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
335
307
  neighbor_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
336
307
  neighbor_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
337
307
  neighbor_info.mIsChild = is_child;
338
339
1.12k
bail:
340
1.12k
  return ret;
341
307
}
342
343
int
344
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_neighbor_error_rates_entry(
345
  const uint8_t *data_in,
346
  spinel_size_t data_len,
347
  TableEntry& neighbor_err_rates_info
348
236
) {
349
236
  int ret = kWPANTUNDStatus_Ok;
350
236
  spinel_ssize_t len = 0;
351
236
  const spinel_eui64_t *eui64 = NULL;
352
353
236
  neighbor_err_rates_info.clear();
354
236
  neighbor_err_rates_info.mType = kNeighborTableErrorRates;
355
356
236
  len = spinel_datatype_unpack(
357
236
    data_in,
358
236
    data_len,
359
236
    (
360
236
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
361
      SPINEL_DATATYPE_UINT16_S        // Rloc16
362
      SPINEL_DATATYPE_UINT16_S        // Frame Error Rate (0->0%, 0xffff->100%)
363
      SPINEL_DATATYPE_UINT16_S        // Message Error Rate (0->0%, 0xffff->100%)
364
      SPINEL_DATATYPE_INT8_S          // Average RSS
365
236
      SPINEL_DATATYPE_INT8_S          // Last Rssi
366
236
    ),
367
236
    &eui64,
368
236
    &neighbor_err_rates_info.mRloc16,
369
236
    &neighbor_err_rates_info.mFrameErrorRate,
370
236
    &neighbor_err_rates_info.mMessageErrorRate,
371
236
    &neighbor_err_rates_info.mAverageRssi,
372
236
    &neighbor_err_rates_info.mLastRssi
373
236
  );
374
375
236
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
376
377
160
  memcpy(neighbor_err_rates_info.mExtAddress, eui64, sizeof(neighbor_err_rates_info.mExtAddress));
378
379
236
bail:
380
236
  return ret;
381
160
}
382
383
int
384
nl::wpantund::SpinelNCPTaskGetNetworkTopology::parse_router_entry(
385
  const uint8_t *data_in,
386
  spinel_size_t data_len,
387
  TableEntry& router_info
388
594
) {
389
594
  int ret = kWPANTUNDStatus_Ok;
390
594
  spinel_ssize_t len = 0;
391
594
  const spinel_eui64_t *eui64 = NULL;
392
594
  uint8_t age;
393
594
  bool link_established = false;
394
395
594
  router_info.clear();
396
594
  router_info.mType = kRouterTable;
397
398
594
  len = spinel_datatype_unpack(
399
594
    data_in,
400
594
    data_len,
401
594
    (
402
594
      SPINEL_DATATYPE_EUI64_S         // EUI64 Address
403
      SPINEL_DATATYPE_UINT16_S        // Rloc16
404
      SPINEL_DATATYPE_UINT8_S         // Router Id
405
      SPINEL_DATATYPE_UINT8_S         // Next hop
406
      SPINEL_DATATYPE_UINT8_S         // Path Cost
407
      SPINEL_DATATYPE_UINT8_S         // Link Quality In
408
      SPINEL_DATATYPE_UINT8_S         // Link Quality Out
409
      SPINEL_DATATYPE_UINT8_S         // Age
410
594
      SPINEL_DATATYPE_BOOL_S          // Is Link Established
411
594
    ),
412
594
    &eui64,
413
594
    &router_info.mRloc16,
414
594
    &router_info.mRouterId,
415
594
    &router_info.mNextHop,
416
594
    &router_info.mPathCost,
417
594
    &router_info.mLinkQualityIn,
418
594
    &router_info.mLinkQualityOut,
419
594
    &age,
420
594
    &link_established
421
594
  );
422
423
594
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
424
425
220
  memcpy(router_info.mExtAddress, eui64, sizeof(router_info.mExtAddress));
426
427
220
  router_info.mAge = age;
428
220
  router_info.mLinkEstablished = link_established;
429
430
594
bail:
431
594
  return ret;
432
220
}
433
434
unsigned int
435
nl::wpantund::SpinelNCPTaskGetNetworkTopology::property_key_for_type(Type type)
436
0
{
437
0
  unsigned int prop_key = 0;
438
439
0
  switch (type)
440
0
  {
441
0
  case kChildTable:
442
0
    prop_key = SPINEL_PROP_THREAD_CHILD_TABLE;
443
0
    break;
444
445
0
  case kChildTableAddresses:
446
0
    prop_key = SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES;
447
0
    break;
448
449
0
  case kNeighborTable:
450
0
    prop_key = SPINEL_PROP_THREAD_NEIGHBOR_TABLE;
451
0
    break;
452
453
0
  case kRouterTable:
454
0
    prop_key = SPINEL_PROP_THREAD_ROUTER_TABLE;
455
0
    break;
456
457
0
  case kNeighborTableErrorRates:
458
0
    prop_key = SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES;
459
0
    break;
460
0
  }
461
462
0
  return prop_key;
463
0
}
464
465
int
466
nl::wpantund::SpinelNCPTaskGetNetworkTopology::vprocess_event(int event, va_list args)
467
0
{
468
0
  int ret = kWPANTUNDStatus_Failure;
469
0
  unsigned int prop_key;
470
0
  const uint8_t *data_in;
471
0
  spinel_size_t data_len;
472
473
0
  EH_BEGIN();
474
475
0
  if (!mInstance->mEnabled) {
476
0
    ret = kWPANTUNDStatus_InvalidWhenDisabled;
477
0
    finish(ret);
478
0
    EH_EXIT();
479
0
  }
480
481
0
  if (mInstance->get_ncp_state() == UPGRADING) {
482
0
    ret = kWPANTUNDStatus_InvalidForCurrentState;
483
0
    finish(ret);
484
0
    EH_EXIT();
485
0
  }
486
487
  // Wait for a bit to see if the NCP will enter the right state.
488
0
  EH_REQUIRE_WITHIN(
489
0
    NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
490
0
    !ncp_state_is_initializing(mInstance->get_ncp_state()) && !mInstance->is_initializing_ncp(),
491
0
    on_error
492
0
  );
493
494
  // The first event to a task is EVENT_STARTING_TASK. The following
495
  // line makes sure that we don't start processing this task
496
  // until it is properly scheduled. All tasks immediately receive
497
  // the initial `EVENT_STARTING_TASK` event, but further events
498
  // will only be received by that task once it is that task's turn
499
  // to execute.
500
0
  EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
501
502
0
  mNextCommand = SpinelPackData(
503
0
    SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET,
504
0
    property_key_for_type(mType)
505
0
  );
506
507
0
  EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
508
509
0
  ret = mNextCommandRet;
510
511
0
  require_noerr(ret, on_error);
512
513
0
  require(EVENT_NCP_PROP_VALUE_IS == event, on_error);
514
515
0
  prop_key = va_arg(args, unsigned int);
516
0
  data_in = va_arg(args, const uint8_t*);
517
0
  data_len = va_arg_small(args, spinel_size_t);
518
519
0
  require(prop_key == property_key_for_type(mType), on_error);
520
521
0
  if (mType == kChildTable) {
522
0
    parse_child_table(data_in, data_len, mTable);
523
0
  } else if (mType == kChildTableAddresses) {
524
0
    parse_child_addresses_table(data_in, data_len, mTable);
525
0
  } else if (mType == kNeighborTable) {
526
0
    parse_neighbor_table(data_in, data_len, mTable);
527
0
  } else if (mType == kRouterTable) {
528
0
    parse_router_table(data_in, data_len, mTable);
529
0
  } else if (mType == kNeighborTableErrorRates) {
530
0
    prase_neighbor_error_rates_table(data_in, data_len, mTable);
531
0
  }
532
533
0
  ret = kWPANTUNDStatus_Ok;
534
535
0
  if (mResultFormat == kResultFormat_StringArray)
536
0
  {
537
0
    std::list<std::string> result;
538
0
    Table::iterator it;
539
540
0
    for (it = mTable.begin(); it != mTable.end(); it++)
541
0
    {
542
0
      result.push_back(it->get_as_string());
543
0
    }
544
545
0
    finish(ret, result);
546
0
  }
547
0
  else if (mResultFormat == kResultFormat_ValueMapArray)
548
0
  {
549
0
    std::list<ValueMap> result;
550
0
    Table::iterator it;
551
552
0
    for (it = mTable.begin(); it != mTable.end(); it++)
553
0
    {
554
0
      result.push_back(it->get_as_valuemap());
555
0
    }
556
557
0
    finish(ret, result);
558
0
  }
559
0
  else
560
0
  {
561
0
    finish(ret);
562
0
  }
563
564
0
  mTable.clear();
565
566
0
  EH_EXIT();
567
568
0
on_error:
569
570
0
  if (ret == kWPANTUNDStatus_Ok) {
571
0
    ret = kWPANTUNDStatus_Failure;
572
0
  }
573
574
0
  syslog(LOG_ERR, "Getting child/neighbor table failed: %d", ret);
575
576
0
  finish(ret);
577
578
0
  mTable.clear();
579
580
0
  EH_END();
581
0
}
582
583
std::string
584
SpinelNCPTaskGetNetworkTopology::TableEntry::get_as_string(void)
585
1.00k
{
586
1.00k
  char c_string[800];
587
588
1.00k
  c_string[0] = 0;
589
590
1.00k
  switch (mType)
591
1.00k
  {
592
316
  case kChildTable:
593
316
    snprintf(c_string, sizeof(c_string),
594
316
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
595
316
      "RLOC16:%04x, "
596
316
      "NetDataVer:%d, "
597
316
      "LQIn:%d, "
598
316
      "AveRssi:%d, "
599
316
      "LastRssi:%d, "
600
316
      "Timeout:%u, "
601
316
      "Age:%u, "
602
316
      "RxOnIdle:%s, "
603
316
      "FTD:%s, "
604
316
      "SecDataReq:%s, "
605
316
      "FullNetData:%s",
606
316
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
607
316
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
608
316
      mRloc16,
609
316
      mNetworkDataVersion,
610
316
      mLinkQualityIn,
611
316
      mAverageRssi,
612
316
      mLastRssi,
613
316
      mTimeout,
614
316
      mAge,
615
316
      mRxOnWhenIdle ? "yes" : "no",
616
316
      mFullFunction ? "yes" : "no",
617
316
      mSecureDataRequest ? "yes" : "no",
618
316
      mFullNetworkData ? "yes" : "no"
619
316
    );
620
316
    break;
621
622
0
  case kChildTableAddresses:
623
0
  {
624
0
    char *str = c_string;
625
0
    size_t remaning_len = sizeof(c_string);
626
0
    int len;
627
0
    bool is_first = true;
628
629
0
    len = snprintf(str, remaning_len,
630
0
      "%02X%02X%02X%02X%02X%02X%02X%02X, RLOC16:%04x%s",
631
0
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
632
0
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
633
0
      mRloc16,
634
0
      mIPv6Addresses.size() > 0 ? ", IPv6Addrs:[" : ""
635
0
    );
636
637
0
    require(len >= 0 && len < remaning_len, bail);
638
0
    str += len;
639
0
    remaning_len -= len;
640
641
0
    for (std::list<struct in6_addr>::iterator it = mIPv6Addresses.begin(); it != mIPv6Addresses.end(); ++it) {
642
643
0
      len = snprintf(
644
0
        str, remaning_len,
645
0
        "%s%s",
646
0
        is_first ? "" : ", ",
647
0
        in6_addr_to_string(*it).c_str()
648
0
      );
649
650
0
      require(len >= 0 && len < remaning_len, bail);
651
0
      str += len;
652
0
      remaning_len -= len;
653
654
0
      is_first = false;
655
0
    }
656
657
0
    if (mIPv6Addresses.size() > 0) {
658
0
      len = snprintf(str, remaning_len, "]");
659
0
      require(len >= 0 && len < remaning_len, bail);
660
0
      str += len;
661
0
      remaning_len -= len;
662
0
    }
663
664
0
    break;
665
0
  }
666
667
307
  case kNeighborTable:
668
307
    snprintf(c_string, sizeof(c_string),
669
307
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
670
307
      "RLOC16:%04x, "
671
307
      "LQIn:%d, "
672
307
      "AveRssi:%d, "
673
307
      "LastRssi:%d, "
674
307
      "Age:%u, "
675
307
      "LinkFC:%u, "
676
307
      "MleFC:%u, "
677
307
      "IsChild:%s, "
678
307
      "RxOnIdle:%s, "
679
307
      "FTD:%s, "
680
307
      "SecDataReq:%s, "
681
307
      "FullNetData:%s",
682
307
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
683
307
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
684
307
      mRloc16,
685
307
      mLinkQualityIn,
686
307
      mAverageRssi,
687
307
      mLastRssi,
688
307
      mAge,
689
307
      mLinkFrameCounter,
690
307
      mMleFrameCounter,
691
307
      mIsChild ? "yes" : "no",
692
307
      mRxOnWhenIdle ? "yes" : "no",
693
307
      mFullFunction ? "yes" : "no",
694
307
      mSecureDataRequest ? "yes" : "no",
695
307
      mFullNetworkData ? "yes" : "no"
696
307
    );
697
307
    break;
698
699
160
  case kNeighborTableErrorRates:
700
160
    snprintf(c_string, sizeof(c_string),
701
160
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
702
160
      "RLOC16:%04x, "
703
160
      "FrameErrRate:%.2lf%%, "
704
160
      "MsgErrorRate:%.2lf%%, "
705
160
      "AveRssi:%d, "
706
160
      "LastRssi:%d, ",
707
160
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
708
160
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
709
160
      mRloc16,
710
160
      static_cast<double>(mFrameErrorRate) * 100.0 / 0xffff,
711
160
      static_cast<double>(mMessageErrorRate) * 100.0 / 0xffff,
712
160
      mAverageRssi,
713
160
      mLastRssi
714
160
    );
715
160
    break;
716
717
220
  case kRouterTable:
718
220
    snprintf(c_string, sizeof(c_string),
719
220
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
720
220
      "RLOC16:%04x, "
721
220
      "RouterId:%d, "
722
220
      "NextHop:%d, "
723
220
      "PathCost:%d, "
724
220
      "LQIn:%d, "
725
220
      "LQOut:%d, "
726
220
      "Age:%d, "
727
220
      "LinkEst:%s",
728
220
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
729
220
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
730
220
      mRloc16,
731
220
      mRouterId,
732
220
      mNextHop,
733
220
      mPathCost,
734
220
      mLinkQualityIn,
735
220
      mLinkQualityOut,
736
220
      mAge,
737
220
      mLinkEstablished ? "yes" : "no"
738
220
    );
739
220
    break;
740
741
0
  default:
742
0
    c_string[0] = 0;
743
0
    break;
744
1.00k
  }
745
746
1.00k
bail:
747
1.00k
  return std::string(c_string);
748
1.00k
}
749
750
ValueMap
751
SpinelNCPTaskGetNetworkTopology::TableEntry::get_as_valuemap(void) const
752
0
{
753
0
  ValueMap entryMap;
754
0
  uint64_t addr;
755
756
0
  if ((mType == kRouterTable) || (mType == kChildTableAddresses)) {
757
0
    goto bail;
758
0
  }
759
760
0
  addr  = (uint64_t) mExtAddress[7];
761
0
  addr |= (uint64_t) mExtAddress[6] << 8;
762
0
  addr |= (uint64_t) mExtAddress[5] << 16;
763
0
  addr |= (uint64_t) mExtAddress[4] << 24;
764
0
  addr |= (uint64_t) mExtAddress[3] << 32;
765
0
  addr |= (uint64_t) mExtAddress[2] << 40;
766
0
  addr |= (uint64_t) mExtAddress[1] << 48;
767
0
  addr |= (uint64_t) mExtAddress[0] << 56;
768
769
0
#define SPINEL_TOPO_MAP_INSERT(KEY, VAL) entryMap.insert( std::pair<std::string, boost::any>( KEY, VAL ) )
770
771
0
  if ((mType == kChildTable) || (mType == kNeighborTable) || (mType == kNeighborTableErrorRates)) {
772
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_ExtAddress,         addr               );
773
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_RLOC16,             mRloc16            );
774
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_AverageRssi,        mAverageRssi       );
775
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_LastRssi,           mLastRssi          );
776
0
  }
777
778
0
  if ((mType == kChildTable) || (mType == kNeighborTable)) {
779
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn,      mLinkQualityIn     );
780
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_Age,                mAge               );
781
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_RxOnWhenIdle,       mRxOnWhenIdle      );
782
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_FullFunction,       mFullFunction      );
783
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_SecureDataRequest,  mSecureDataRequest );
784
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_FullNetworkData,    mFullNetworkData   );
785
0
  }
786
787
0
  if (mType == kChildTable) {
788
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_Timeout,            mTimeout           );
789
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_NetworkDataVersion, mNetworkDataVersion);
790
0
  }
791
792
0
  if (mType == kNeighborTable) {
793
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_LinkFrameCounter,   mLinkFrameCounter  );
794
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_MleFrameCounter,    mMleFrameCounter   );
795
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_IsChild,            mIsChild           );
796
0
  }
797
798
0
  if (mType == kNeighborTableErrorRates) {
799
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_FrameErrorRate,     mFrameErrorRate    );
800
0
    SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_MessageErrorRate,   mMessageErrorRate  );
801
0
  }
802
803
0
bail:
804
0
  return entryMap;
805
0
}