ifconfig 学习

目录—网络丢包情形概览

  • 硬件网卡丢包

  • 网卡驱动丢包----//ethtool查看??

  • 以太网链路层丢包

  • 网络 IP 层丢包//ifconfig 查看??

  • 传输层 UDP/TCP 丢包

  • 应用层 socket 丢包

现象最近调试网络发现ifconfig 丢包:

rx dropped 27 errors 是4

ifconfig 学习_第1张图片

1、ifconfig 信息获取

查看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");
...
}

2、内核/proc/net/dev 文件

该文件得实现关系到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

3、rtnl_link_stats64 数据结构得数据获取

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

4、kerenl rx_dropped 得赋值

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

10、linuxkernel协议栈层

__netif_receive_skb_core

ifconfig 学习_第2张图片




# 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

你可能感兴趣的:(Linux网络,学习)