硬件网卡丢包
网卡驱动丢包----//ethtool查看??
以太网链路层丢包
网络 IP 层丢包//ifconfig 查看??
传输层 UDP/TCP 丢包
应用层 socket 丢包
现象最近调试网络发现ifconfig 丢包:
rx dropped 27 errors 是4
查看busybox源码: ifconfig 读取信息是从系统得/proc/net/dev文件获取
busybox源码如下:
./networking/interface.c
#define _PATH_PROCNET_DEV "/proc/net/dev" 该文件获取得
ifconfig_main-->display_interfaces-->if_readlist-->if_readlist_proc-->
static int if_readlist_proc(struct iface_list *ilist, char *ifname)
{
FILE *fh;
char buf[512];
struct interface *ife;
int procnetdev_vsn;
int ret;
fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");
...
}
该文件得实现关系到linux kernel net/core/net-procfs.c
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
struct rtnl_link_stats64 temp;
const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu "
"%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n",
dev->name, stats->rx_bytes, stats->rx_packets,
stats->rx_errors,
stats->rx_dropped + stats->rx_missed_errors,
stats->rx_fifo_errors,
stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors,
stats->rx_compressed, stats->multicast,
stats->tx_bytes, stats->tx_packets,
stats->tx_errors, stats->tx_dropped,
stats->tx_fifo_errors, stats->collisions,
stats->tx_carrier_errors +
stats->tx_aborted_errors +
stats->tx_window_errors +
stats->tx_heartbeat_errors,
stats->tx_compressed);
}
基于linux kernel 4.20版本数据结构如下:
include/uapi/linux/if_link.h
/* The main device statistics structure */
struct rtnl_link_stats64 {
__u64 rx_packets; /* total packets received */
__u64 tx_packets; /* total packets transmitted */
__u64 rx_bytes; /* total bytes received */
__u64 tx_bytes; /* total bytes transmitted */
__u64 rx_errors; /* bad packets received */
__u64 tx_errors; /* packet transmit problems */
__u64 rx_dropped; /* no space in linux buffers */ ifconfig丢包统计
__u64 tx_dropped; /* no space available in linux */ ifconfig丢包统计
__u64 multicast; /* multicast packets received */
__u64 collisions;
/* detailed rx_errors: */
__u64 rx_length_errors;
__u64 rx_over_errors; /* receiver ring buff overflow */
__u64 rx_crc_errors; /* recved pkt with crc error */
__u64 rx_frame_errors; /* recv'd frame alignment error */
__u64 rx_fifo_errors; /* recv'r fifo overrun */
__u64 rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
__u64 tx_aborted_errors;
__u64 tx_carrier_errors;
__u64 tx_fifo_errors;
__u64 tx_heartbeat_errors;
__u64 tx_window_errors;
/* for cslip etc */
__u64 rx_compressed;
__u64 tx_compressed;
__u64 rx_nohandler; /* dropped, no handler found */
};
include/linux/netdevice.h
struct net_device {
char name[IFNAMSIZ];
struct hlist_node name_hlist;
struct dev_ifalias __rcu *ifalias;
/*
* I/O specific fields
* FIXME: Merge these and struct ifmap into one
*/
unsigned long mem_end;
unsigned long mem_start;
unsigned long base_addr;
int irq;
/*
* Some hardware also needs these fields (state,dev_list,
* napi_list,unreg_list,close_list) but they are not
* part of the usual set specified in Space.c.
*/
unsigned long state;
struct list_head dev_list;
struct list_head napi_list;
struct list_head unreg_list;
struct list_head close_list;
struct list_head ptype_all;
struct list_head ptype_specific;
struct {
struct list_head upper;
struct list_head lower;
} adj_list;
netdev_features_t features;
netdev_features_t hw_features;
netdev_features_t wanted_features;
netdev_features_t vlan_features;
netdev_features_t hw_enc_features;
netdev_features_t mpls_features;
netdev_features_t gso_partial_features;
int ifindex;
int group;
struct net_device_stats stats;
atomic_long_t rx_dropped;//__netif_receive_skb_core在该函数中通过
atomic_long_t tx_dropped;
atomic_long_t rx_nohandler;
cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
eth4: 111224 522 1 154 0 0 0 0 0 0 1 0 0 0 0 0
eth2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth3: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
/proc/net/dev
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 += (unsigned long)atomic_long_read(&dev->rx_dropped);
storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped);
storage->rx_nohandler += (unsigned long)atomic_long_read(&dev->rx_nohandler);
//printk("%s:%d--------->dropped:%d \n", __func__, __LINE__, dev->rx_dropped);
return storage;
}
下边是调用栈关系。
[ 34.710000] Call Trace:
[ 34.710000] [] walk_stackframe+0x0/0xa6
[ 34.710000] [] show_stack+0x2a/0x34
[ 34.710000] [] dump_stack+0x66/0x80
[ 34.710000] [] dev_get_stats+0x76/0xda
[ 34.710000] [] dev_seq_printf_stats+0x1a/0xb2
[ 34.710000] [] dev_seq_show+0x12/0x36
[ 34.710000] [] seq_read+0x288/0x2f8
[ 34.710000] [] proc_reg_read+0x44/0x82
[ 34.710000] [] __vfs_read+0x1a/0xfc
[ 34.710000] [] vfs_read+0x60/0xdc
[ 34.710000] [] ksys_read+0x3a/0x7a
[ 34.710000] [] sys_read+0xe/0x16
[ 34.710000] [] ret_from_syscall+0x0/0xe
ifconfig rx_dropped统计实际上是在函数做得统计
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
struct packet_type **ppt_prev)
{
...
drop:
if (!deliver_exact)
atomic_long_inc(&skb->dev->rx_dropped);//在这里统计实际丢包
else
atomic_long_inc(&skb->dev->rx_nohandler);
kfree_skb(skb);
/* Jamal, now you will not able to escape explaining
* me how you were going to use this. :-)
*/
printk("%s:%d--------->dropped:%d \n", __func__, __LINE__, skb->dev->rx_dropped);
ret = NET_RX_DROP;
}
out:
return ret;
}
[ 309.780000] [] walk_stackframe+0x0/0xa6
[ 309.780000] [] show_stack+0x2a/0x34
[ 309.790000] [] dump_stack+0x66/0x80
[ 309.790000] [] __netif_receive_skb_core+0x660/0x662
[ 309.800000] [] __netif_receive_skb_one_core+0x1e/0x3a
[ 309.810000] [] netif_receive_skb_internal+0x44/0xe6
[ 309.810000] [] napi_gro_receive+0x50/0x94
[ 309.820000] [] stmmac_napi_poll+0x60c/0xfb6
[ 309.820000] [] net_rx_action+0xe4/0x29e
[ 309.830000] ndesc_get_rx_status: Oversized frame spanned multiple buffers
__netif_receive_skb_core
# ethtool -S eth4//dump_stack 调用栈如下:
[ 88.480000] CPU: 0 PID: 109 Comm: ethtool Not tainted 4.20.0-44676-g167af5483671-dirty #123
[ 88.480000] Call Trace:
[ 88.480000] [] walk_stackframe+0x0/0xa6
[ 88.480000] [] show_stack+0x2a/0x34
[ 88.480000] [] dump_stack+0x66/0x80
[ 88.480000] [] stmmac_get_ethtool_stats+0x38/0x196
[ 88.480000] [] dev_ethtool+0xd26/0x19c4
[ 88.480000] [] dev_ioctl+0x1a8/0x2b0
[ 88.480000] [] sock_ioctl+0x1c4/0x2ca
[ 88.480000] [] do_vfs_ioctl+0x366/0x534
[ 88.480000] [] sys_ioctl+0x3a/0x60
[ 88.480000] [] ret_from_syscall+0x0/0xe
NIC statistics:
结论:ethtool 获取得网卡信息是从网卡驱动里获取。
ifconfig 获取得rx tx 是从内核协议中获取
学习连接:
https://blog.csdn.net/rikeyone/article/details/110957428
https://blog.csdn.net/mabin2005/article/details/124317863
https://cloud.tencent.com/developer/article/2050526