简介
本文只讲述网卡的statistics数据注册和获取流程,典型的如:
/sys/class/net/eth0/statistics/rx_packets
/sys/class/net/eth0/statistics/tx_packets
/sys/class/net/eth0/statistics/rx_bytes
/sys/class/net/eth0/statistics/tx_bytes
/sys/class/net/eth0/statistics/rx_dropped
/sys/class/net/eth0/statistics/tx_dropped
或者通过# ifconfig eth0查看到的数据
设备节点的创建
注册
在网卡加入到kernel的时候都必须通过register_netdevice()进行注册,该函数通过调用netdev_register_kobject()函数来设置相关信息并注册对应的设备节点。
-
/* Create sysfs entries for network device. */
-
int netdev_register_kobject(struct net_device *ndev){
-
struct device *dev = &(ndev->dev);
-
const struct attribute_group **groups = ndev->sysfs_groups;
-
...
-
dev->groups = groups;
-
...
-
*groups++ = &netstat_group;
-
...
-
device_add(dev);
-
}
device_add()->device_add_attrs()->device_add_groups(dev->groups)->sysfs_create_groups()
netstat_group定义
-
#define NETSTAT_ENTRY(name) \
-
static ssize_t name##_show(struct device *d, \
-
struct device_attribute *attr, char *buf) \
-
{ \
-
return netstat_show(d, attr, buf, \
-
offsetof(struct rtnl_link_stats64, name)); \
-
} \
-
static DEVICE_ATTR_RO(name)
-
-
NETSTAT_ENTRY(rx_packets);
-
NETSTAT_ENTRY(tx_packets);
-
NETSTAT_ENTRY(rx_bytes);
-
NETSTAT_ENTRY(tx_bytes);
-
NETSTAT_ENTRY(rx_errors);
-
NETSTAT_ENTRY(tx_errors);
-
NETSTAT_ENTRY(rx_dropped);
-
NETSTAT_ENTRY(tx_dropped);
-
NETSTAT_ENTRY(multicast);
-
NETSTAT_ENTRY(collisions);
-
NETSTAT_ENTRY(rx_length_errors);
-
NETSTAT_ENTRY(rx_over_errors);
-
NETSTAT_ENTRY(rx_crc_errors);
-
NETSTAT_ENTRY(rx_frame_errors);
-
NETSTAT_ENTRY(rx_fifo_errors);
-
NETSTAT_ENTRY(rx_missed_errors);
-
NETSTAT_ENTRY(tx_aborted_errors);
-
NETSTAT_ENTRY(tx_carrier_errors);
-
NETSTAT_ENTRY(tx_fifo_errors);
-
NETSTAT_ENTRY(tx_heartbeat_errors);
-
NETSTAT_ENTRY(tx_window_errors);
-
NETSTAT_ENTRY(rx_compressed);
-
NETSTAT_ENTRY(tx_compressed);
-
NETSTAT_ENTRY(rx_nohandler);
-
-
static struct attribute *netstat_attrs[] = {
-
&dev_attr_rx_packets.attr,
-
&dev_attr_tx_packets.attr,
-
&dev_attr_rx_bytes.attr,
-
&dev_attr_tx_bytes.attr,
-
&dev_attr_rx_errors.attr,
-
&dev_attr_tx_errors.attr,
-
&dev_attr_rx_dropped.attr,
-
&dev_attr_tx_dropped.attr,
-
&dev_attr_multicast.attr,
-
&dev_attr_collisions.attr,
-
&dev_attr_rx_length_errors.attr,
-
&dev_attr_rx_over_errors.attr,
-
&dev_attr_rx_crc_errors.attr,
-
&dev_attr_rx_frame_errors.attr,
-
&dev_attr_rx_fifo_errors.attr,
-
&dev_attr_rx_missed_errors.attr,
-
&dev_attr_tx_aborted_errors.attr,
-
&dev_attr_tx_carrier_errors.attr,
-
&dev_attr_tx_fifo_errors.attr,
-
&dev_attr_tx_heartbeat_errors.attr,
-
&dev_attr_tx_window_errors.attr,
-
&dev_attr_rx_compressed.attr,
-
&dev_attr_tx_compressed.attr,
-
&dev_attr_rx_nohandler.attr,
-
NULL
-
};
-
-
static struct attribute_group netstat_group = {
-
.name = "statistics",
-
.attrs = netstat_attrs,
-
};
netstat_show函数
-
#define __stringify_1(x...) #x
-
#define __stringify(x...) __stringify_1(x)
-
-
#define __ATTR_RO(_name) { \
-
.attr = { .name = __stringify(_name), .mode = S_IRUGO }, \
-
.show = _name##_show, \
-
}
-
-
#define DEVICE_ATTR_RO(_name) \
-
struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
-
-
struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
-
struct rtnl_link_stats64 *storage)
-
{
-
const struct net_device_ops *ops = dev->netdev_ops;
-
-
if (ops->ndo_get_stats64) {
-
memset(storage, 0, sizeof(*storage));
-
ops->ndo_get_stats64(dev, storage);
-
} else if (ops->ndo_get_stats) {
-
netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
-
} else {
-
netdev_stats_to_stats64(storage, &dev->stats);
-
}
-
storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
-
storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
-
storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
-
return storage;
-
}
-
static ssize_t netstat_show(const struct device *d,
-
struct device_attribute *attr, char *buf,
-
unsigned long offset)
-
{
-
struct net_device *dev = to_net_dev(d);
-
ssize_t ret = -EINVAL;
-
-
WARN_ON(offset > sizeof(struct rtnl_link_stats64) ||
-
offset % sizeof(u64) != 0);
-
-
read_lock(&dev_base_lock);
-
if (dev_isalive(dev)) {
-
struct rtnl_link_stats64 temp;
-
const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
-
-
ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset));
-
}
-
read_unlock(&dev_base_lock);
-
return ret;
-
}
dev_get_stats
通过dev_get_stats()函数可以知道,如果网卡有注册ndo_get_stats64()函数或者ndo_get_stats()函数,则通过网卡驱动获取stats数据,否则直接通过dev->stats获取。
其他
net/core/dev.c
register_netdevice
net/core/net-sysfs.c
netdev_register_kobject()->
dev->groups = groups;
*groups++ = &netstat_group;
device_add()->device_add_attrs()->device_add_groups(dev->groups)->sysfs_create_groups()
阅读(9185) | 评论(0) | 转发(0) |