netdev_statistics.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /****************************************************************************
  2. * net/procfs/netdev_statistics.c
  3. *
  4. * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <debug.h>
  43. #include <netinet/ether.h>
  44. #include <nuttx/net/netdev.h>
  45. #include <nuttx/net/sixlowpan.h>
  46. #include "netdev/netdev.h"
  47. #include "utils/utils.h"
  48. #include "procfs/procfs.h"
  49. #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \
  50. !defined(CONFIG_FS_PROCFS_EXCLUDE_NET)
  51. /****************************************************************************
  52. * Private Function Prototypes
  53. ****************************************************************************/
  54. static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile);
  55. #ifdef CONFIG_NET_IPv4
  56. static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile);
  57. #endif
  58. #ifdef CONFIG_NET_IPv6
  59. static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile);
  60. static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile);
  61. #endif
  62. #if !defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_IPv6)
  63. static int netprocfs_blank_line(FAR struct netprocfs_file_s *netfile);
  64. #endif
  65. #ifdef CONFIG_NETDEV_STATISTICS
  66. static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile);
  67. static int netprocfs_rxstatistics(FAR struct netprocfs_file_s *netfile);
  68. static int netprocfs_rxpackets_header(FAR struct netprocfs_file_s *netfile);
  69. static int netprocfs_rxpackets(FAR struct netprocfs_file_s *netfile);
  70. static int netprocfs_txstatistics_header(FAR struct netprocfs_file_s *netfile);
  71. static int netprocfs_txstatistics(FAR struct netprocfs_file_s *netfile);
  72. static int netprocfs_errors(FAR struct netprocfs_file_s *netfile);
  73. #endif /* CONFIG_NETDEV_STATISTICS */
  74. /****************************************************************************
  75. * Private Data
  76. ****************************************************************************/
  77. /* Line generating functions */
  78. static const linegen_t g_netstat_linegen[] =
  79. {
  80. netprocfs_linklayer
  81. #ifdef CONFIG_NET_IPv4
  82. , netprocfs_inet4addresses
  83. #endif
  84. #ifdef CONFIG_NET_IPv6
  85. , netprocfs_inet6address
  86. , netprocfs_inet6draddress
  87. #endif
  88. #if !defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_IPv6)
  89. , netprocfs_blank_line
  90. #endif
  91. #ifdef CONFIG_NETDEV_STATISTICS
  92. , netprocfs_rxstatistics_header,
  93. netprocfs_rxstatistics,
  94. netprocfs_rxpackets_header,
  95. netprocfs_rxpackets,
  96. netprocfs_txstatistics_header,
  97. netprocfs_txstatistics,
  98. netprocfs_errors
  99. #endif /* CONFIG_NETDEV_STATISTICS */
  100. };
  101. #define NSTAT_LINES (sizeof(g_netstat_linegen) / sizeof(linegen_t))
  102. /****************************************************************************
  103. * Private Functions
  104. ****************************************************************************/
  105. #if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154)
  106. static int netprocfs_radio_linklayer(FAR struct netprocfs_file_s *netfile,
  107. int len)
  108. {
  109. FAR struct netdev_varaddr_s *addr;
  110. FAR struct net_driver_s *dev;
  111. #if RADIO_MAX_ADDRLEN > 1
  112. int i;
  113. #endif
  114. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  115. dev = netfile->dev;
  116. addr = &dev->d_mac.radio;
  117. #ifdef CONFIG_NET_6LOWPAN
  118. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  119. "%s\tLink encap:6LoWPAN HWaddr ",
  120. dev->d_ifname);
  121. #else
  122. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  123. "%s\tLink encap:Raw HWaddr ",
  124. dev->d_ifname);
  125. #endif
  126. if (addr->nv_addrlen < 1 || addr->nv_addrlen > RADIO_MAX_ADDRLEN)
  127. {
  128. nwarn("WARNING: Bad or undefined node address: %u\n",
  129. addr->nv_addrlen);
  130. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  131. "--");
  132. }
  133. else
  134. {
  135. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  136. "%02x", addr->nv_addr[0]);
  137. #if RADIO_MAX_ADDRLEN > 1 /* Avoids a warning */
  138. for (i = 1; i < addr->nv_addrlen; i++)
  139. {
  140. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  141. ":%02x", addr->nv_addr[i]);
  142. }
  143. #endif
  144. }
  145. return len;
  146. }
  147. #endif
  148. /****************************************************************************
  149. * Name: netprocfs_linklayer
  150. ****************************************************************************/
  151. static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile)
  152. {
  153. FAR struct net_driver_s *dev;
  154. FAR const char *status;
  155. int len = 0;
  156. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  157. dev = netfile->dev;
  158. /* Get the interface status: RUNNING, UP, or DOWN */
  159. if ((dev->d_flags & IFF_RUNNING) != 0)
  160. {
  161. status = "RUNNING";
  162. }
  163. else if ((dev->d_flags & IFF_UP) != 0)
  164. {
  165. status = "UP";
  166. }
  167. else
  168. {
  169. status = "DOWN";
  170. }
  171. /* Select the output appropriate for the link type associated with
  172. * this device.
  173. */
  174. switch (dev->d_lltype)
  175. {
  176. #if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_DRIVERS_IEEE80211)
  177. case NET_LL_ETHERNET:
  178. case NET_LL_IEEE80211:
  179. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  180. "%s\tLink encap:Ethernet HWaddr %s",
  181. dev->d_ifname, ether_ntoa(&dev->d_mac.ether));
  182. break;
  183. #endif
  184. #if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154)
  185. case NET_LL_IEEE802154:
  186. case NET_LL_PKTRADIO:
  187. {
  188. len += netprocfs_radio_linklayer(netfile, len);
  189. }
  190. break;
  191. #endif /* CONFIG_NET_6LOWPAN || CONFIG_NET_IEEE802154 */
  192. #ifdef CONFIG_NET_LOOPBACK
  193. case NET_LL_LOOPBACK:
  194. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  195. "%s\tLink encap:Local Loopback",
  196. dev->d_ifname);
  197. break;
  198. #endif
  199. #ifdef CONFIG_NET_SLIP
  200. case NET_LL_SLIP:
  201. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  202. "%s\tLink encap:SLIP", dev->d_ifname);
  203. break;
  204. #endif
  205. #ifdef CONFIG_NET_PPP
  206. case NET_LL_PPP:
  207. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  208. "%s\tLink encap:P-t-P", dev->d_ifname);
  209. break;
  210. #endif
  211. #ifdef CONFIG_NET_TUN
  212. case NET_LL_TUN:
  213. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  214. "%s\tLink encap:TUN", dev->d_ifname);
  215. break;
  216. #endif
  217. default:
  218. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  219. "%s\tLink encap:UNSPEC", dev->d_ifname);
  220. }
  221. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  222. " at %s\n", status);
  223. return len;
  224. }
  225. /****************************************************************************
  226. * Name: netprocfs_inet4addresses
  227. ****************************************************************************/
  228. #ifdef CONFIG_NET_IPv4
  229. static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile)
  230. {
  231. FAR struct net_driver_s *dev;
  232. struct in_addr addr;
  233. int len = 0;
  234. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  235. dev = netfile->dev;
  236. /* Show the IPv4 address */
  237. addr.s_addr = dev->d_ipaddr;
  238. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  239. "\tinet addr:%s ", inet_ntoa(addr));
  240. /* Show the IPv4 default router address */
  241. addr.s_addr = dev->d_draddr;
  242. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  243. "DRaddr:%s ", inet_ntoa(addr));
  244. /* Show the IPv4 network mask */
  245. addr.s_addr = dev->d_netmask;
  246. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  247. #ifdef CONFIG_NET_IPv6
  248. "Mask:%s\n", /* IPv6 addresses will follow */
  249. #else
  250. "Mask:%s\n\n", /* Double space at end of device description */
  251. #endif
  252. inet_ntoa(addr));
  253. return len;
  254. }
  255. #endif
  256. /****************************************************************************
  257. * Name: netprocfs_inet6address
  258. ****************************************************************************/
  259. #ifdef CONFIG_NET_IPv6
  260. static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile)
  261. {
  262. FAR struct net_driver_s *dev;
  263. char addrstr[INET6_ADDRSTRLEN];
  264. uint8_t preflen;
  265. int len = 0;
  266. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  267. dev = netfile->dev;
  268. /* Convert the 128 network mask to a human friendly prefix length */
  269. preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
  270. /* Show the assigned IPv6 address */
  271. if (inet_ntop(AF_INET6, dev->d_ipv6addr, addrstr, INET6_ADDRSTRLEN))
  272. {
  273. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  274. "\tinet6 addr: %s/%d\n", addrstr, preflen);
  275. }
  276. return len;
  277. }
  278. #endif
  279. /****************************************************************************
  280. * Name: netprocfs_inet6draddress
  281. ****************************************************************************/
  282. #ifdef CONFIG_NET_IPv6
  283. static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile)
  284. {
  285. FAR struct net_driver_s *dev;
  286. char addrstr[INET6_ADDRSTRLEN];
  287. uint8_t preflen;
  288. int len = 0;
  289. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  290. dev = netfile->dev;
  291. /* Convert the 128 network mask to a human friendly prefix length */
  292. preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
  293. /* Show the IPv6 default router address */
  294. if (inet_ntop(AF_INET6, dev->d_ipv6draddr, addrstr, INET6_ADDRSTRLEN))
  295. {
  296. len += snprintf(&netfile->line[len], NET_LINELEN - len,
  297. "\tinet6 DRaddr: %s/%d\n\n", addrstr, preflen);
  298. }
  299. return len;
  300. }
  301. #endif
  302. /****************************************************************************
  303. * Name: netprocfs_blank_line
  304. ****************************************************************************/
  305. #if !defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_IPv6)
  306. static int netprocfs_blank_line(FAR struct netprocfs_file_s *netfile)
  307. {
  308. netfile->line[0] = '\n';
  309. netfile->line[1] = '\0';
  310. return 1;
  311. }
  312. #endif
  313. /****************************************************************************
  314. * Name: netprocfs_rxstatistics_header
  315. ****************************************************************************/
  316. #ifdef CONFIG_NETDEV_STATISTICS
  317. static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile)
  318. {
  319. DEBUGASSERT(netfile != NULL);
  320. return snprintf(netfile->line, NET_LINELEN , "\tRX: %-8s %-8s %-8s\n",
  321. "Received", "Fragment", "Errors");
  322. }
  323. #endif /* CONFIG_NETDEV_STATISTICS */
  324. /****************************************************************************
  325. * Name: netprocfs_rxstatistics
  326. ****************************************************************************/
  327. #ifdef CONFIG_NETDEV_STATISTICS
  328. static int netprocfs_rxstatistics(FAR struct netprocfs_file_s *netfile)
  329. {
  330. FAR struct netdev_statistics_s *stats;
  331. FAR struct net_driver_s *dev;
  332. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  333. dev = netfile->dev;
  334. stats = &dev->d_statistics;
  335. return snprintf(netfile->line, NET_LINELEN, "\t %08lx %08lx %08lx\n",
  336. (unsigned long)stats->rx_packets,
  337. (unsigned long)stats->rx_fragments,
  338. (unsigned long)stats->rx_errors);
  339. }
  340. #endif /* CONFIG_NETDEV_STATISTICS */
  341. /****************************************************************************
  342. * Name: netprocfs_rxpackets_header
  343. ****************************************************************************/
  344. #ifdef CONFIG_NETDEV_STATISTICS
  345. static int netprocfs_rxpackets_header(FAR struct netprocfs_file_s *netfile)
  346. {
  347. FAR char *fmt;
  348. DEBUGASSERT(netfile != NULL);
  349. fmt = "\t "
  350. #ifdef CONFIG_NET_IPv4
  351. "%-8s "
  352. #endif
  353. #ifdef CONFIG_NET_IPv6
  354. "%-8s "
  355. #endif
  356. #ifdef CONFIG_NET_ARP
  357. "%-8s "
  358. #endif
  359. "%-8s\n";
  360. return snprintf(netfile->line, NET_LINELEN, fmt
  361. #ifdef CONFIG_NET_IPv4
  362. , "IPv4"
  363. #endif
  364. #ifdef CONFIG_NET_IPv6
  365. , "IPv6"
  366. #endif
  367. #ifdef CONFIG_NET_ARP
  368. , "ARP"
  369. #endif
  370. , "Dropped");
  371. }
  372. #endif /* CONFIG_NETDEV_STATISTICS */
  373. /****************************************************************************
  374. * Name: netprocfs_rxpackets
  375. ****************************************************************************/
  376. #ifdef CONFIG_NETDEV_STATISTICS
  377. static int netprocfs_rxpackets(FAR struct netprocfs_file_s *netfile)
  378. {
  379. FAR struct netdev_statistics_s *stats;
  380. FAR struct net_driver_s *dev;
  381. FAR char *fmt;
  382. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  383. dev = netfile->dev;
  384. stats = &dev->d_statistics;
  385. fmt = "\t "
  386. #ifdef CONFIG_NET_IPv4
  387. "%08lx "
  388. #endif
  389. #ifdef CONFIG_NET_IPv6
  390. "%08lx "
  391. #endif
  392. #ifdef CONFIG_NET_ARP
  393. "%08lx "
  394. #endif
  395. "%08lx\n";
  396. return snprintf(netfile->line, NET_LINELEN, fmt
  397. #ifdef CONFIG_NET_IPv4
  398. , (unsigned long)stats->rx_ipv4
  399. #endif
  400. #ifdef CONFIG_NET_IPv6
  401. , (unsigned long)stats->rx_ipv6
  402. #endif
  403. #ifdef CONFIG_NET_ARP
  404. , (unsigned long)stats->rx_arp
  405. #endif
  406. , (unsigned long)stats->rx_dropped);
  407. }
  408. #endif /* CONFIG_NETDEV_STATISTICS */
  409. /****************************************************************************
  410. * Name: netprocfs_txstatistics_header
  411. ****************************************************************************/
  412. #ifdef CONFIG_NETDEV_STATISTICS
  413. static int netprocfs_txstatistics_header(FAR struct netprocfs_file_s *netfile)
  414. {
  415. DEBUGASSERT(netfile != NULL);
  416. return snprintf(netfile->line, NET_LINELEN, "\tTX: %-8s %-8s %-8s %-8s\n",
  417. "Queued", "Sent", "Errors", "Timeouts");
  418. }
  419. #endif /* CONFIG_NETDEV_STATISTICS */
  420. /****************************************************************************
  421. * Name: netprocfs_txstatistics
  422. ****************************************************************************/
  423. #ifdef CONFIG_NETDEV_STATISTICS
  424. static int netprocfs_txstatistics(FAR struct netprocfs_file_s *netfile)
  425. {
  426. FAR struct netdev_statistics_s *stats;
  427. FAR struct net_driver_s *dev;
  428. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  429. dev = netfile->dev;
  430. stats = &dev->d_statistics;
  431. return snprintf(netfile->line, NET_LINELEN, "\t %08lx %08lx %08lx %08lx\n",
  432. (unsigned long)stats->tx_packets,
  433. (unsigned long)stats->tx_done,
  434. (unsigned long)stats->tx_errors,
  435. (unsigned long)stats->tx_timeouts);
  436. }
  437. #endif /* CONFIG_NETDEV_STATISTICS */
  438. /****************************************************************************
  439. * Name: netprocfs_errors
  440. ****************************************************************************/
  441. #ifdef CONFIG_NETDEV_STATISTICS
  442. static int netprocfs_errors(FAR struct netprocfs_file_s *netfile)
  443. {
  444. FAR struct netdev_statistics_s *stats;
  445. FAR struct net_driver_s *dev;
  446. DEBUGASSERT(netfile != NULL && netfile->dev != NULL);
  447. dev = netfile->dev;
  448. stats = &dev->d_statistics;
  449. return snprintf(netfile->line, NET_LINELEN , "\tTotal Errors: %08x\n\n",
  450. (unsigned long)stats->errors);
  451. }
  452. #endif /* CONFIG_NETDEV_STATISTICS */
  453. /****************************************************************************
  454. * Public Functions
  455. ****************************************************************************/
  456. /****************************************************************************
  457. * Name: netprocfs_read_devstats
  458. *
  459. * Description:
  460. * Read and format network device statistics.
  461. *
  462. * Input Parameters:
  463. * priv - A reference to the network procfs file structure
  464. * buffer - The user-provided buffer into which device status will be
  465. * returned.
  466. * bulen - The size in bytes of the user provided buffer.
  467. *
  468. * Returned Value:
  469. * Zero (OK) is returned on success; a negated errno value is returned
  470. * on failure.
  471. *
  472. ****************************************************************************/
  473. ssize_t netprocfs_read_devstats(FAR struct netprocfs_file_s *priv,
  474. FAR char *buffer, size_t buflen)
  475. {
  476. return netprocfs_read_linegen(priv, buffer, buflen, g_netstat_linegen,
  477. NSTAT_LINES);
  478. }
  479. #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS &&
  480. * !CONFIG_FS_PROCFS_EXCLUDE_NET */