Coverage Report

Created: 2026-03-11 06:29

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.47k
{
36
3.47k
  clear();
37
3.47k
}
38
39
void
40
nl::wpantund::SpinelNCPTaskGetNetworkTopology::TableEntry::clear(void)
41
6.18k
{
42
6.18k
  memset(mExtAddress, 0, sizeof(mExtAddress));
43
6.18k
  mRloc16 = 0;
44
6.18k
  mAge = 0;
45
6.18k
  mLinkQualityIn = 0;
46
6.18k
  mAverageRssi = 0;
47
6.18k
  mLastRssi = 0;
48
6.18k
  mRxOnWhenIdle = false;
49
6.18k
  mSecureDataRequest = false;
50
6.18k
  mFullFunction = false;
51
6.18k
  mFullNetworkData = false;
52
6.18k
  mTimeout = 0;
53
6.18k
  mNetworkDataVersion = 0;
54
6.18k
  mLinkFrameCounter = 0;
55
6.18k
  mMleFrameCounter = 0;
56
6.18k
  mIsChild = false;
57
6.18k
  mRouterId = 0;
58
6.18k
  mNextHop = 0;
59
6.18k
  mPathCost = 0;
60
6.18k
  mLinkQualityOut = 0;
61
6.18k
  mLinkEstablished = false;
62
6.18k
  mIPv6Addresses.clear();
63
6.18k
  mFrameErrorRate = 0;
64
6.18k
  mMessageErrorRate = 0;
65
6.18k
}
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.01k
) {
83
2.01k
  int ret = kWPANTUNDStatus_Ok;
84
85
2.01k
  table.clear();
86
87
2.68k
  while (data_len > 0) {
88
2.26k
    spinel_ssize_t len = 0;
89
2.26k
    const uint8_t *struct_data;
90
2.26k
    spinel_size_t struct_len;
91
2.26k
    TableEntry entry;
92
93
2.26k
    len = spinel_datatype_unpack(
94
2.26k
      data_in,
95
2.26k
      data_len,
96
2.26k
      SPINEL_DATATYPE_DATA_WLEN_S,
97
2.26k
      &struct_data,
98
2.26k
      &struct_len
99
2.26k
    );
100
101
2.26k
    require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
102
103
1.49k
    switch (type)
104
1.49k
    {
105
192
    case kChildTable:
106
192
      ret = parse_child_entry(struct_data, struct_len, entry);
107
192
      break;
108
109
0
    case kChildTableAddresses:
110
0
      ret = parse_child_addresses_entry(struct_data, struct_len, entry);
111
0
      break;
112
113
397
    case kNeighborTable:
114
397
      ret = parse_neighbor_entry(struct_data, struct_len, entry);
115
397
      break;
116
117
335
    case kNeighborTableErrorRates:
118
335
      ret = parse_neighbor_error_rates_entry(struct_data, struct_len, entry);
119
335
      break;
120
121
569
    case kRouterTable:
122
569
      ret = parse_router_entry(struct_data, struct_len, entry);
123
569
      break;
124
1.49k
    }
125
126
1.49k
    require_noerr(ret, bail);
127
128
667
    table.push_back(entry);
129
130
667
    data_in += len;
131
667
    data_len -= len;
132
667
  }
133
134
2.01k
bail:
135
2.01k
  return ret;
136
2.01k
}
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
785
) {
144
785
  return parse_table(kChildTable, data_in, data_len, child_table);
145
785
}
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
332
) {
162
332
  return parse_table(kNeighborTable, data_in, data_len, neighbor_table);
163
332
}
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
349
) {
171
349
  return parse_table(kNeighborTableErrorRates, data_in, data_len, neighbor_err_rate_table);
172
349
}
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
552
) {
180
552
  return parse_table(kRouterTable, data_in, data_len, router_table);
181
552
}
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
675
) {
189
675
  int ret = kWPANTUNDStatus_Ok;
190
675
  spinel_ssize_t len = 0;
191
675
  const spinel_eui64_t *eui64 = NULL;
192
675
  uint8_t mode;
193
194
675
  child_info.clear();
195
675
  child_info.mType = kChildTable;
196
197
675
  len = spinel_datatype_unpack(
198
675
    data_in,
199
675
    data_len,
200
675
    (
201
675
      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
675
      SPINEL_DATATYPE_INT8_S          // Last Rssi
210
675
    ),
211
675
    &eui64,
212
675
    &child_info.mRloc16,
213
675
    &child_info.mTimeout,
214
675
    &child_info.mAge,
215
675
    &child_info.mNetworkDataVersion,
216
675
    &child_info.mLinkQualityIn,
217
675
    &child_info.mAverageRssi,
218
675
    &mode,
219
675
    &child_info.mLastRssi
220
675
  );
221
222
675
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
223
224
339
  memcpy(child_info.mExtAddress, eui64, sizeof(child_info.mExtAddress));
225
226
339
  child_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
227
339
  child_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
228
339
  child_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
229
339
  child_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
230
231
675
bail:
232
675
  return ret;
233
339
}
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
343
  memcpy(neighbor_info.mExtAddress, eui64, sizeof(neighbor_info.mExtAddress));
332
333
343
  neighbor_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
334
343
  neighbor_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
335
343
  neighbor_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
336
343
  neighbor_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
337
343
  neighbor_info.mIsChild = is_child;
338
339
1.12k
bail:
340
1.12k
  return ret;
341
343
}
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
335
) {
349
335
  int ret = kWPANTUNDStatus_Ok;
350
335
  spinel_ssize_t len = 0;
351
335
  const spinel_eui64_t *eui64 = NULL;
352
353
335
  neighbor_err_rates_info.clear();
354
335
  neighbor_err_rates_info.mType = kNeighborTableErrorRates;
355
356
335
  len = spinel_datatype_unpack(
357
335
    data_in,
358
335
    data_len,
359
335
    (
360
335
      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
335
      SPINEL_DATATYPE_INT8_S          // Last Rssi
366
335
    ),
367
335
    &eui64,
368
335
    &neighbor_err_rates_info.mRloc16,
369
335
    &neighbor_err_rates_info.mFrameErrorRate,
370
335
    &neighbor_err_rates_info.mMessageErrorRate,
371
335
    &neighbor_err_rates_info.mAverageRssi,
372
335
    &neighbor_err_rates_info.mLastRssi
373
335
  );
374
375
335
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
376
377
133
  memcpy(neighbor_err_rates_info.mExtAddress, eui64, sizeof(neighbor_err_rates_info.mExtAddress));
378
379
335
bail:
380
335
  return ret;
381
133
}
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
569
) {
389
569
  int ret = kWPANTUNDStatus_Ok;
390
569
  spinel_ssize_t len = 0;
391
569
  const spinel_eui64_t *eui64 = NULL;
392
569
  uint8_t age;
393
569
  bool link_established = false;
394
395
569
  router_info.clear();
396
569
  router_info.mType = kRouterTable;
397
398
569
  len = spinel_datatype_unpack(
399
569
    data_in,
400
569
    data_len,
401
569
    (
402
569
      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
569
      SPINEL_DATATYPE_BOOL_S          // Is Link Established
411
569
    ),
412
569
    &eui64,
413
569
    &router_info.mRloc16,
414
569
    &router_info.mRouterId,
415
569
    &router_info.mNextHop,
416
569
    &router_info.mPathCost,
417
569
    &router_info.mLinkQualityIn,
418
569
    &router_info.mLinkQualityOut,
419
569
    &age,
420
569
    &link_established
421
569
  );
422
423
569
  require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure);
424
425
174
  memcpy(router_info.mExtAddress, eui64, sizeof(router_info.mExtAddress));
426
427
174
  router_info.mAge = age;
428
174
  router_info.mLinkEstablished = link_established;
429
430
569
bail:
431
569
  return ret;
432
174
}
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
989
{
586
989
  char c_string[800];
587
588
989
  c_string[0] = 0;
589
590
989
  switch (mType)
591
989
  {
592
339
  case kChildTable:
593
339
    snprintf(c_string, sizeof(c_string),
594
339
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
595
339
      "RLOC16:%04x, "
596
339
      "NetDataVer:%d, "
597
339
      "LQIn:%d, "
598
339
      "AveRssi:%d, "
599
339
      "LastRssi:%d, "
600
339
      "Timeout:%u, "
601
339
      "Age:%u, "
602
339
      "RxOnIdle:%s, "
603
339
      "FTD:%s, "
604
339
      "SecDataReq:%s, "
605
339
      "FullNetData:%s",
606
339
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
607
339
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
608
339
      mRloc16,
609
339
      mNetworkDataVersion,
610
339
      mLinkQualityIn,
611
339
      mAverageRssi,
612
339
      mLastRssi,
613
339
      mTimeout,
614
339
      mAge,
615
339
      mRxOnWhenIdle ? "yes" : "no",
616
339
      mFullFunction ? "yes" : "no",
617
339
      mSecureDataRequest ? "yes" : "no",
618
339
      mFullNetworkData ? "yes" : "no"
619
339
    );
620
339
    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
343
  case kNeighborTable:
668
343
    snprintf(c_string, sizeof(c_string),
669
343
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
670
343
      "RLOC16:%04x, "
671
343
      "LQIn:%d, "
672
343
      "AveRssi:%d, "
673
343
      "LastRssi:%d, "
674
343
      "Age:%u, "
675
343
      "LinkFC:%u, "
676
343
      "MleFC:%u, "
677
343
      "IsChild:%s, "
678
343
      "RxOnIdle:%s, "
679
343
      "FTD:%s, "
680
343
      "SecDataReq:%s, "
681
343
      "FullNetData:%s",
682
343
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
683
343
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
684
343
      mRloc16,
685
343
      mLinkQualityIn,
686
343
      mAverageRssi,
687
343
      mLastRssi,
688
343
      mAge,
689
343
      mLinkFrameCounter,
690
343
      mMleFrameCounter,
691
343
      mIsChild ? "yes" : "no",
692
343
      mRxOnWhenIdle ? "yes" : "no",
693
343
      mFullFunction ? "yes" : "no",
694
343
      mSecureDataRequest ? "yes" : "no",
695
343
      mFullNetworkData ? "yes" : "no"
696
343
    );
697
343
    break;
698
699
133
  case kNeighborTableErrorRates:
700
133
    snprintf(c_string, sizeof(c_string),
701
133
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
702
133
      "RLOC16:%04x, "
703
133
      "FrameErrRate:%.2lf%%, "
704
133
      "MsgErrorRate:%.2lf%%, "
705
133
      "AveRssi:%d, "
706
133
      "LastRssi:%d, ",
707
133
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
708
133
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
709
133
      mRloc16,
710
133
      static_cast<double>(mFrameErrorRate) * 100.0 / 0xffff,
711
133
      static_cast<double>(mMessageErrorRate) * 100.0 / 0xffff,
712
133
      mAverageRssi,
713
133
      mLastRssi
714
133
    );
715
133
    break;
716
717
174
  case kRouterTable:
718
174
    snprintf(c_string, sizeof(c_string),
719
174
      "%02X%02X%02X%02X%02X%02X%02X%02X, "
720
174
      "RLOC16:%04x, "
721
174
      "RouterId:%d, "
722
174
      "NextHop:%d, "
723
174
      "PathCost:%d, "
724
174
      "LQIn:%d, "
725
174
      "LQOut:%d, "
726
174
      "Age:%d, "
727
174
      "LinkEst:%s",
728
174
      mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
729
174
      mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
730
174
      mRloc16,
731
174
      mRouterId,
732
174
      mNextHop,
733
174
      mPathCost,
734
174
      mLinkQualityIn,
735
174
      mLinkQualityOut,
736
174
      mAge,
737
174
      mLinkEstablished ? "yes" : "no"
738
174
    );
739
174
    break;
740
741
0
  default:
742
0
    c_string[0] = 0;
743
0
    break;
744
989
  }
745
746
989
bail:
747
989
  return std::string(c_string);
748
989
}
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
}