/**************************************************************************** * net/procfs/netdev_statistics.c * * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include "netdev/netdev.h" #include "utils/utils.h" #include "procfs/procfs.h" #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \ !defined(CONFIG_FS_PROCFS_EXCLUDE_NET) /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile); static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile); #ifdef CONFIG_NET_IPv6 static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile); #endif #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile); static int netprocfs_rxstatistics(FAR struct netprocfs_file_s *netfile); static int netprocfs_rxpackets_header(FAR struct netprocfs_file_s *netfile); static int netprocfs_rxpackets(FAR struct netprocfs_file_s *netfile); static int netprocfs_txstatistics_header(FAR struct netprocfs_file_s *netfile); static int netprocfs_txstatistics(FAR struct netprocfs_file_s *netfile); static int netprocfs_errors(FAR struct netprocfs_file_s *netfile); #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Private Data ****************************************************************************/ /* Line generating functions */ static const linegen_t g_linegen[] = { netprocfs_linklayer, netprocfs_ipaddresses #ifdef CONFIG_NET_IPv6 , netprocfs_dripaddress #endif #ifdef CONFIG_NETDEV_STATISTICS , netprocfs_rxstatistics_header, netprocfs_rxstatistics, netprocfs_rxpackets_header, netprocfs_rxpackets, netprocfs_txstatistics_header, netprocfs_txstatistics, netprocfs_errors #endif /* CONFIG_NETDEV_STATISTICS */ }; #define NSTAT_LINES (sizeof(g_linegen) / sizeof(linegen_t)) /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: netprocfs_linklayer ****************************************************************************/ static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile) { FAR struct net_driver_s *dev; #ifdef CONFIG_NET_6LOWPAN FAR struct ieee802154_driver_s *ieee; #endif FAR const char *status; int len = 0; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; /* Get the interface status: RUNNING, UP, or DOWN */ if ((dev->d_flags & IFF_RUNNING) != 0) { status = "RUNNING"; } else if ((dev->d_flags & IFF_UP) != 0) { status = "UP"; } else { status = "DOWN"; } #if defined(CONFIG_NET_MULTILINK) /* If there are multiple link types being supported, then selected the * output appropriate for the link type associated with this device. */ switch (dev->d_lltype) { #ifdef CONFIG_NET_ETHERNET case NET_LL_ETHERNET: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:Ethernet HWaddr %s", dev->d_ifname, ether_ntoa(&dev->d_mac)); break; #endif #ifdef CONFIG_NET_6LOWPAN case NET_LL_IEEE802154: { ieee = (FAR struct ieee802154_driver_s *)dev; #ifdef CONFIG_NET_6LOWPAN_RIMEADDR_EXTENDED len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:6loWPAN HWaddr " "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", dev->d_ifname, ieee->i_nodeaddr.u8[0], ieee->i_nodeaddr.u8[1], ieee->i_nodeaddr.u8[2], ieee->i_nodeaddr.u8[3], ieee->i_nodeaddr.u8[4], ieee->i_nodeaddr.u8[5], ieee->i_nodeaddr.u8[6], ieee->i_nodeaddr.u8[7]); #else len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:6loWPAN HWaddr %02x:%02x", dev->d_ifname, ieee->i_nodeaddr.u8[0], ieee->i_nodeaddr.u8[1]); #endif } break; #endif #ifdef CONFIG_NET_LOOPBACK case NET_LL_LOOPBACK: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:Local Loopback", dev->d_ifname); break; #endif #ifdef CONFIG_NET_SLIP case NET_LL_SLIP: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:SLIP", dev->d_ifname); break; #endif #ifdef CONFIG_NET_PPP case NET_LL_PPP: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:P-t-P", dev->d_ifname); break; #endif #ifdef CONFIG_NET_TUN case NET_LL_TUN: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:TUN", dev->d_ifname); break; #endif default: len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:UNSPEC", dev->d_ifname); } len += snprintf(&netfile->line[len], NET_LINELEN - len, " at %s\n", status); #elif defined(CONFIG_NET_ETHERNET) len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:Ethernet HWaddr %s at %s\n", dev->d_ifname, ether_ntoa(&dev->d_mac), status); #elif defined(CONFIG_NET_6LOWPAN) ieee = (FAR struct ieee802154_driver_s *)dev; #ifdef CONFIG_NET_6LOWPAN_RIMEADDR_EXTENDED len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:6loWPAN HWaddr " "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x at %s\n", dev->d_ifname, ieee->i_nodeaddr.u8[0], ieee->i_nodeaddr.u8[1], ieee->i_nodeaddr.u8[2], ieee->i_nodeaddr.u8[3], ieee->i_nodeaddr.u8[4], ieee->i_nodeaddr.u8[5], ieee->i_nodeaddr.u8[6], ieee->i_nodeaddr.u8[7], status); #else len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:6loWPAN HWaddr %02x:%02x at %s\n", dev->d_ifname, ieee->i_nodeaddr.u8[0], ieee->i_nodeaddr.u8[1], status); #endif #elif defined(CONFIG_NET_LOOPBACK) len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:Local Loopback at %s\n", dev->d_ifname, status); #elif defined(CONFIG_NET_SLIP) len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:SLIP at %s\n", dev->d_ifname, status); #elif defined(CONFIG_NET_PPP) len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:P-t-P at %s\n", dev->d_ifname, status); #elif defined(CONFIG_NET_TUN) len += snprintf(&netfile->line[len], NET_LINELEN - len, "%s\tLink encap:TUN at %s\n", dev->d_ifname, status); #endif return len; } /**************************************************************************** * Name: netprocfs_ipaddresses ****************************************************************************/ static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile) { FAR struct net_driver_s *dev; #ifdef CONFIG_NET_IPv4 struct in_addr addr; #endif #ifdef CONFIG_NET_IPv6 char addrstr[INET6_ADDRSTRLEN]; uint8_t preflen; #endif int len = 0; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; #ifdef CONFIG_NET_IPv4 /* Show the IPv4 address */ addr.s_addr = dev->d_ipaddr; len += snprintf(&netfile->line[len], NET_LINELEN - len, "\tinet addr:%s ", inet_ntoa(addr)); /* Show the IPv4 default router address */ addr.s_addr = dev->d_draddr; len += snprintf(&netfile->line[len], NET_LINELEN - len, "DRaddr:%s ", inet_ntoa(addr)); /* Show the IPv4 network mask */ addr.s_addr = dev->d_netmask; len += snprintf(&netfile->line[len], NET_LINELEN - len, "Mask:%s\n\n", inet_ntoa(addr)); #endif #ifdef CONFIG_NET_IPv6 /* Convert the 128 network mask to a human friendly prefix length */ preflen = net_ipv6_mask2pref(dev->d_ipv6netmask); /* Show the assigned IPv6 address */ if (inet_ntop(AF_INET6, dev->d_ipv6addr, addrstr, INET6_ADDRSTRLEN)) { len += snprintf(&netfile->line[len], NET_LINELEN - len, "\tinet6 addr:%s/%d\n", addrstr, preflen); } #endif return len; } /**************************************************************************** * Name: netprocfs_dripaddress ****************************************************************************/ #ifdef CONFIG_NET_IPv6 static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile) { FAR struct net_driver_s *dev; char addrstr[INET6_ADDRSTRLEN]; uint8_t preflen; int len = 0; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; /* Convert the 128 network mask to a human friendly prefix length */ preflen = net_ipv6_mask2pref(dev->d_ipv6netmask); /* Show the IPv6 default router address */ if (inet_ntop(AF_INET6, dev->d_ipv6draddr, addrstr, INET6_ADDRSTRLEN)) { len += snprintf(&netfile->line[len], NET_LINELEN - len, "\tinet6 DRaddr:%s/%d\n\n", addrstr, preflen); } return len; } #endif /**************************************************************************** * Name: netprocfs_rxstatistics_header ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile) { DEBUGASSERT(netfile != NULL); return snprintf(netfile->line, NET_LINELEN , "\tRX: %-8s %-8s %-8s\n", "Received", "Fragment", "Errors"); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_rxstatistics ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxstatistics(FAR struct netprocfs_file_s *netfile) { FAR struct netdev_statistics_s *stats; FAR struct net_driver_s *dev; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; stats = &dev->d_statistics; return snprintf(netfile->line, NET_LINELEN, "\t %08lx %08lx %08lx\n", (unsigned long)stats->rx_packets, (unsigned long)stats->rx_fragments, (unsigned long)stats->rx_errors); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_rxpackets_header ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxpackets_header(FAR struct netprocfs_file_s *netfile) { FAR char *fmt; DEBUGASSERT(netfile != NULL); fmt = "\t " #ifdef CONFIG_NET_IPv4 "%-8s " #endif #ifdef CONFIG_NET_IPv6 "%-8s " #endif #ifdef CONFIG_NET_ARP "%-8s " #endif "%-8s\n"; return snprintf(netfile->line, NET_LINELEN, fmt #ifdef CONFIG_NET_IPv4 , "IPv4" #endif #ifdef CONFIG_NET_IPv6 , "IPv6" #endif #ifdef CONFIG_NET_ARP , "ARP" #endif , "Dropped"); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_rxpackets ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxpackets(FAR struct netprocfs_file_s *netfile) { FAR struct netdev_statistics_s *stats; FAR struct net_driver_s *dev; FAR char *fmt; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; stats = &dev->d_statistics; fmt = "\t " #ifdef CONFIG_NET_IPv4 "%08lx " #endif #ifdef CONFIG_NET_IPv6 "%08lx " #endif #ifdef CONFIG_NET_ARP "%08lx " #endif "%08lx\n"; return snprintf(netfile->line, NET_LINELEN, fmt #ifdef CONFIG_NET_IPv4 , (unsigned long)stats->rx_ipv4 #endif #ifdef CONFIG_NET_IPv6 , (unsigned long)stats->rx_ipv6 #endif #ifdef CONFIG_NET_ARP , (unsigned long)stats->rx_arp #endif , (unsigned long)stats->rx_dropped); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_txstatistics_header ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_txstatistics_header(FAR struct netprocfs_file_s *netfile) { DEBUGASSERT(netfile != NULL); return snprintf(netfile->line, NET_LINELEN, "\tTX: %-8s %-8s %-8s %-8s\n", "Queued", "Sent", "Errors", "Timeouts"); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_txstatistics ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_txstatistics(FAR struct netprocfs_file_s *netfile) { FAR struct netdev_statistics_s *stats; FAR struct net_driver_s *dev; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; stats = &dev->d_statistics; return snprintf(netfile->line, NET_LINELEN, "\t %08lx %08lx %08lx %08lx\n", (unsigned long)stats->tx_packets, (unsigned long)stats->tx_done, (unsigned long)stats->tx_errors, (unsigned long)stats->tx_timeouts); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Name: netprocfs_errors ****************************************************************************/ #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_errors(FAR struct netprocfs_file_s *netfile) { FAR struct netdev_statistics_s *stats; FAR struct net_driver_s *dev; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; stats = &dev->d_statistics; return snprintf(netfile->line, NET_LINELEN , "\tTotal Errors: %08x\n\n", (unsigned long)stats->errors); } #endif /* CONFIG_NETDEV_STATISTICS */ /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: netprocfs_read_devstats * * Description: * Read and format network device statistics. * * Input Parameters: * priv - A reference to the network procfs file structure * buffer - The user-provided buffer into which device status will be * returned. * bulen - The size in bytes of the user provided buffer. * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned * on failure. * ****************************************************************************/ ssize_t netprocfs_read_devstats(FAR struct netprocfs_file_s *priv, FAR char *buffer, size_t buflen) { return netprocfs_read_linegen(priv, buffer, buflen, g_linegen, NSTAT_LINES); } #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS && * !CONFIG_FS_PROCFS_EXCLUDE_NET */