linux内核网络协议栈--linux网络设备理解(十四)

1、网络设备驱动结构在这里插入图片描述

1)网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接受数据。这一层的存在使得上层协议独立于具体的设备。

2)网络设备接口层向协议接口层提供统一的用于描述具体网络设备属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。实际上,网络设备接口层从宏观上规划了具体操作硬件的设备驱动功能层的结构。

3)设备驱动功能层各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,他通过hard_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接受操作。

4)网络设备与媒介层是完成数据包发送和接受的物理实体,包括网络适配器和具体的传输媒介,网络适配器被驱动功能层中的函数物理上驱动。对于Linux系统而言,网络设备和媒介都可以是虚拟的。

2、网卡驱动中重要的数据结构

2.1 net_device

struct net_device {
    /* 设备名称,如eth0 */
    char            name[IFNAMSIZ];
    /* 名称hash */
    struct hlist_node    name_hlist;
    char             *ifalias;
    /*
     *    I/O specific fields
     *    FIXME: Merge these and struct ifmap into one
     */
    /*
        描述设备所用的共享内存,用于设备与内核沟通
        其初始化和访问只会在设备驱动程序内进行
    */
    unsigned long        mem_end;
    unsigned long        mem_start;

    /* 设备自有内存映射到I/O内存的起始地址 */
    unsigned long        base_addr;

    /*
        设备与内核对话的中断编号,此值可由多个设备共享
        驱动程序使用request_irq函数分配此变量,使用free_irq予以释放
    */
    int            irq;

    /* 侦测网络状态的改变次数 */
    atomic_t        carrier_changes;

    /*
     *    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.
     */

    /*
        网络队列子系统使用的一组标识
        由__LINK_STATE_xxx标识
    */
    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;

    /*
        用于存在其他一些设备功能
        可报告适配卡的功能,以便与CPU通信
        使用NETIF_F_XXX标识功能特性
    */
    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;

    /* 设备组,默认都属于0组 */
    int            group;

    struct net_device_stats    stats;

    atomic_long_t        rx_dropped;
    atomic_long_t        tx_dropped;
    atomic_long_t        rx_nohandler;

#ifdef CONFIG_WIRELESS_EXT
    const struct iw_handler_def *wireless_handlers;
    struct iw_public_data    *wireless_data;
#endif
    /* 设备操作接口 */
    const struct net_device_ops *netdev_ops;
    /* ethtool操作接口 */
    const struct ethtool_ops *ethtool_ops;
#ifdef CONFIG_NET_SWITCHDEV
    const struct switchdev_ops *switchdev_ops;
#endif
#ifdef CONFIG_NET_L3_MASTER_DEV
    const struct l3mdev_ops    *l3mdev_ops;
#endif
#if IS_ENABLED(CONFIG_IPV6)
    const struct ndisc_ops *ndisc_ops;
#endif

#ifdef CONFIG_XFRM
    const struct xfrmdev_ops *xfrmdev_ops;
#endif

    /* 头部一些操作,如链路层缓存,校验等 */
    const struct header_ops *header_ops;

    /* 标识接口特性,IFF_XXX,如IFF_UP */
    unsigned int        flags;

    /*
        用于存储用户空间不可见的标识
        由VLAN和Bridge虚拟设备使用
    */
    unsigned int        priv_flags;

    /* 几乎不使用,为了兼容保留 */
    unsigned short        gflags;

    /* 结构对齐填充 */
    unsigned short        padded;

    /* 与interface group mib中的IfOperStatus相关 */
    unsigned char        operstate;
    unsigned char        link_mode;

    /*
        接口使用的端口类型
    */
    unsigned char        if_port;

    /*
        设备使用的DMA通道
        并非所有设备都可以用DMA,有些总线不支持DMA
    */
    unsigned char        dma;

    /*
        最大传输单元,标识设备能处理帧的最大尺寸
        Ethernet-1500
    */
    unsigned int        mtu;
    /* 最小mtu,Ethernet-68 */
    unsigned int        min_mtu;
    /* 最大mut,Ethernet-65535 */
    unsigned int        max_mtu;

    /*     设备所属类型
        ARP模块中,用type判断接口的硬件地址类型
        以太网接口为ARPHRD_ETHER
    */
    unsigned short        type;
    /*
        设备头部长度
        Ethernet报头是ETH_HLEN=14字节
    */
    unsigned short        hard_header_len;
    unsigned char        min_header_len;

    /* 必须的头部空间 */
    unsigned short        needed_headroom;
    unsigned short        needed_tailroom;

    /* Interface address info. */
    /* 硬件地址,通常在初始化过程中从硬件读取 */
    unsigned char        perm_addr[MAX_ADDR_LEN];
    unsigned char        addr_assign_type;
    /* 硬件地址长度 */
    unsigned char        addr_len;
    unsigned short        neigh_priv_len;
    unsigned short          dev_id;
    unsigned short          dev_port;
    spinlock_t        addr_list_lock;
    /* 设备名赋值类型,如NET_NAME_UNKNOWN */
    unsigned char        name_assign_type;
    bool            uc_promisc;
    struct netdev_hw_addr_list    uc;
    struct netdev_hw_addr_list    mc;
    struct netdev_hw_addr_list    dev_addrs;

#ifdef CONFIG_SYSFS
    struct kset        *queues_kset;
#endif
    /* 混杂模式开启数量 */
    unsigned int        promiscuity;

    /* 非零值时,设备监听所有多播地址 */
    unsigned int        allmulti;


    /* Protocol-specific pointers */
/* 特定协议的指针 */
#if IS_ENABLED(CONFIG_VLAN_8021Q)
    struct vlan_info __rcu    *vlan_info;
#endif
#if IS_ENABLED(CONFIG_NET_DSA)
    struct dsa_switch_tree    *dsa_ptr;
#endif
#if IS_ENABLED(CONFIG_TIPC)
    struct tipc_bearer __rcu *tipc_ptr;
#endif
    void             *atalk_ptr;
    /* ip指向in_device结构 */
    struct in_device __rcu    *ip_ptr;
    struct dn_dev __rcu     *dn_ptr;
    struct inet6_dev __rcu    *ip6_ptr;
    void            *ax25_ptr;
    struct wireless_dev    *ieee80211_ptr;
    struct wpan_dev        *ieee802154_ptr;
#if IS_ENABLED(CONFIG_MPLS_ROUTING)
    struct mpls_dev __rcu    *mpls_ptr;
#endif

/*
 * Cache lines mostly used on receive path (including eth_type_trans())
 */
    /* Interface address info used in eth_type_trans() */
    unsigned char        *dev_addr;

#ifdef CONFIG_SYSFS
    /* 接收队列 */
    struct netdev_rx_queue    *_rx;

    /* 接收队列数 */
    unsigned int        num_rx_queues;
    unsigned int        real_num_rx_queues;
#endif

    struct bpf_prog __rcu    *xdp_prog;
    unsigned long        gro_flush_timeout;

    /* 如网桥等的收包回调 */
    rx_handler_func_t __rcu    *rx_handler;
    /* 回调参数 */
    void __rcu        *rx_handler_data;

#ifdef CONFIG_NET_CLS_ACT
    struct tcf_proto __rcu  *ingress_cl_list;
#endif
    struct netdev_queue __rcu *ingress_queue;
#ifdef CONFIG_NETFILTER_INGRESS
    /* netfilter入口 */
    struct nf_hook_entry __rcu *nf_hooks_ingress;
#endif

    /* 链路层广播地址 */
    unsigned char        broadcast[MAX_ADDR_LEN];
#ifdef CONFIG_RFS_ACCEL
    struct cpu_rmap        *rx_cpu_rmap;
#endif
    /* 接口索引hash */
    struct hlist_node    index_hlist;

/*
 * Cache lines mostly used on transmit path
 */
     /* 发送队列 */
    struct netdev_queue    *_tx ____cacheline_aligned_in_smp;
    /* 发送队列数 */
    unsigned int        num_tx_queues;
    unsigned int        real_num_tx_queues;
    /* 排队规则 */
    struct Qdisc        *qdisc;
#ifdef CONFIG_NET_SCHED
    DECLARE_HASHTABLE    (qdisc_hash, 4);
#endif
    /*
        可在设备发送队列中排队的最大数据包数
    */
    unsigned long        tx_queue_len;
    spinlock_t        tx_global_lock;

    /*     网络层确定传输超时,
        调用驱动程序tx_timeout接口的最短时间
    */
    int            watchdog_timeo;

#ifdef CONFIG_XPS
    struct xps_dev_maps __rcu *xps_maps;
#endif
#ifdef CONFIG_NET_CLS_ACT
    struct tcf_proto __rcu  *egress_cl_list;
#endif

    /* These may be needed for future network-power-down code. */
    /* watchdog定时器 */
    struct timer_list    watchdog_timer;

    /* 引用计数 */
    int __percpu        *pcpu_refcnt;

    /*     网络设备的注册和除名以两步进行,
        该字段用于处理第二步
    */
    struct list_head    todo_list;

    struct list_head    link_watch_list;

    /* 设备的注册状态 */
    enum { NETREG_UNINITIALIZED=0,
           NETREG_REGISTERED,    /* completed register_netdevice */
           NETREG_UNREGISTERING,    /* called unregister_netdevice */
           NETREG_UNREGISTERED,    /* completed unregister todo */
           NETREG_RELEASED,        /* called free_netdev */
           NETREG_DUMMY,        /* dummy device for NAPI poll */
    } reg_state:8;

    /* 设备要被释放标记 */
    bool dismantle;

    enum {
        RTNL_LINK_INITIALIZED,
        RTNL_LINK_INITIALIZING,
    } rtnl_link_state:16;

    bool needs_free_netdev;
    void (*priv_destructor)(struct net_device *dev);

#ifdef CONFIG_NETPOLL
    struct netpoll_info __rcu    *npinfo;
#endif

    possible_net_t            nd_net;

    /* mid-layer private */
    union {
        void                    *ml_priv;
        struct pcpu_lstats __percpu        *lstats;
        struct pcpu_sw_netstats __percpu    *tstats;
        struct pcpu_dstats __percpu        *dstats;
        struct pcpu_vstats __percpu        *vstats;
    };

#if IS_ENABLED(CONFIG_GARP)
    struct garp_port __rcu    *garp_port;
#endif
#if IS_ENABLED(CONFIG_MRP)
    struct mrp_port __rcu    *mrp_port;
#endif

    struct device        dev;
    const struct attribute_group *sysfs_groups[4];
    const struct attribute_group *sysfs_rx_queue_group;

    const struct rtnl_link_ops *rtnl_link_ops;

    /* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE        65536
    unsigned int        gso_max_size;
#define GSO_MAX_SEGS        65535
    u16            gso_max_segs;

#ifdef CONFIG_DCB
    const struct dcbnl_rtnl_ops *dcbnl_ops;
#endif
    u8            num_tc;
    struct netdev_tc_txq    tc_to_txq[TC_MAX_QUEUE];
    u8            prio_tc_map[TC_BITMASK + 1];

#if IS_ENABLED(CONFIG_FCOE)
    unsigned int        fcoe_ddp_xid;
#endif
#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
    struct netprio_map __rcu *priomap;
#endif
    struct phy_device    *phydev;
    struct lock_class_key    *qdisc_tx_busylock;
    struct lock_class_key    *qdisc_running_key;
    bool            proto_down;
};

2.2 net_device_ops

struct net_device_ops {
    int            (*ndo_init)(struct net_device *dev);
    void            (*ndo_uninit)(struct net_device *dev);
    int            (*ndo_open)(struct net_device *dev);
    int            (*ndo_stop)(struct net_device *dev);
    netdev_tx_t        (*ndo_start_xmit)(struct sk_buff *skb,
                          struct net_device *dev);
    netdev_features_t    (*ndo_features_check)(struct sk_buff *skb,
                              struct net_device *dev,
                              netdev_features_t features);
    u16            (*ndo_select_queue)(struct net_device *dev,
                            struct sk_buff *skb,
                            void *accel_priv,
                            select_queue_fallback_t fallback);
    void            (*ndo_change_rx_flags)(struct net_device *dev,
                               int flags);
    void            (*ndo_set_rx_mode)(struct net_device *dev);
    int            (*ndo_set_mac_address)(struct net_device *dev,
                               void *addr);
    int            (*ndo_validate_addr)(struct net_device *dev);
    int            (*ndo_do_ioctl)(struct net_device *dev,
                            struct ifreq *ifr, int cmd);
    int            (*ndo_set_config)(struct net_device *dev,
                              struct ifmap *map);
    int            (*ndo_change_mtu)(struct net_device *dev,
                          int new_mtu);
    int            (*ndo_neigh_setup)(struct net_device *dev,
                           struct neigh_parms *);
    void            (*ndo_tx_timeout) (struct net_device *dev);

    void            (*ndo_get_stats64)(struct net_device *dev,
                           struct rtnl_link_stats64 *storage);
    bool            (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id);
    int            (*ndo_get_offload_stats)(int attr_id,
                             const struct net_device *dev,
                             void *attr_data);
    struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);

    int            (*ndo_vlan_rx_add_vid)(struct net_device *dev,
                               __be16 proto, u16 vid);
    int            (*ndo_vlan_rx_kill_vid)(struct net_device *dev,
                                __be16 proto, u16 vid);
#ifdef CONFIG_NET_POLL_CONTROLLER
    void                    (*ndo_poll_controller)(struct net_device *dev);
    int            (*ndo_netpoll_setup)(struct net_device *dev,
                             struct netpoll_info *info);
    void            (*ndo_netpoll_cleanup)(struct net_device *dev);
#endif
    int            (*ndo_set_vf_mac)(struct net_device *dev,
                          int queue, u8 *mac);
    int            (*ndo_set_vf_vlan)(struct net_device *dev,
                           int queue, u16 vlan,
                           u8 qos, __be16 proto);
    int            (*ndo_set_vf_rate)(struct net_device *dev,
                           int vf, int min_tx_rate,
                           int max_tx_rate);
    int            (*ndo_set_vf_spoofchk)(struct net_device *dev,
                               int vf, bool setting);
    int            (*ndo_set_vf_trust)(struct net_device *dev,
                            int vf, bool setting);
    int            (*ndo_get_vf_config)(struct net_device *dev,
                             int vf,
                             struct ifla_vf_info *ivf);
    int            (*ndo_set_vf_link_state)(struct net_device *dev,
                             int vf, int link_state);
    int            (*ndo_get_vf_stats)(struct net_device *dev,
                            int vf,
                            struct ifla_vf_stats
                            *vf_stats);
    int            (*ndo_set_vf_port)(struct net_device *dev,
                           int vf,
                           struct nlattr *port[]);
    int            (*ndo_get_vf_port)(struct net_device *dev,
                           int vf, struct sk_buff *skb);
    int            (*ndo_set_vf_guid)(struct net_device *dev,
                           int vf, u64 guid,
                           int guid_type);
    int            (*ndo_set_vf_rss_query_en)(
                           struct net_device *dev,
                           int vf, bool setting);
    int            (*ndo_setup_tc)(struct net_device *dev,
                        u32 handle,
                        __be16 protocol,
                        struct tc_to_netdev *tc);
#if IS_ENABLED(CONFIG_FCOE)
    int            (*ndo_fcoe_enable)(struct net_device *dev);
    int            (*ndo_fcoe_disable)(struct net_device *dev);
    int            (*ndo_fcoe_ddp_setup)(struct net_device *dev,
                              u16 xid,
                              struct scatterlist *sgl,
                              unsigned int sgc);
    int            (*ndo_fcoe_ddp_done)(struct net_device *dev,
                             u16 xid);
    int            (*ndo_fcoe_ddp_target)(struct net_device *dev,
                               u16 xid,
                               struct scatterlist *sgl,
                               unsigned int sgc);
    int            (*ndo_fcoe_get_hbainfo)(struct net_device *dev,
                            struct netdev_fcoe_hbainfo *hbainfo);
#endif

#if IS_ENABLED(CONFIG_LIBFCOE)
#define NETDEV_FCOE_WWNN 0
#define NETDEV_FCOE_WWPN 1
    int            (*ndo_fcoe_get_wwn)(struct net_device *dev,
                            u64 *wwn, int type);
#endif

#ifdef CONFIG_RFS_ACCEL
    int            (*ndo_rx_flow_steer)(struct net_device *dev,
                             const struct sk_buff *skb,
                             u16 rxq_index,
                             u32 flow_id);
#endif
    int            (*ndo_add_slave)(struct net_device *dev,
                         struct net_device *slave_dev);
    int            (*ndo_del_slave)(struct net_device *dev,
                         struct net_device *slave_dev);
    netdev_features_t    (*ndo_fix_features)(struct net_device *dev,
                            netdev_features_t features);
    int            (*ndo_set_features)(struct net_device *dev,
                            netdev_features_t features);
    int            (*ndo_neigh_construct)(struct net_device *dev,
                               struct neighbour *n);
    void            (*ndo_neigh_destroy)(struct net_device *dev,
                             struct neighbour *n);

    int            (*ndo_fdb_add)(struct ndmsg *ndm,
                           struct nlattr *tb[],
                           struct net_device *dev,
                           const unsigned char *addr,
                           u16 vid,
                           u16 flags);
    int            (*ndo_fdb_del)(struct ndmsg *ndm,
                           struct nlattr *tb[],
                           struct net_device *dev,
                           const unsigned char *addr,
                           u16 vid);
    int            (*ndo_fdb_dump)(struct sk_buff *skb,
                        struct netlink_callback *cb,
                        struct net_device *dev,
                        struct net_device *filter_dev,
                        int *idx);

    int            (*ndo_bridge_setlink)(struct net_device *dev,
                              struct nlmsghdr *nlh,
                              u16 flags);
    int            (*ndo_bridge_getlink)(struct sk_buff *skb,
                              u32 pid, u32 seq,
                              struct net_device *dev,
                              u32 filter_mask,
                              int nlflags);
    int            (*ndo_bridge_dellink)(struct net_device *dev,
                              struct nlmsghdr *nlh,
                              u16 flags);
    int            (*ndo_change_carrier)(struct net_device *dev,
                              bool new_carrier);
    int            (*ndo_get_phys_port_id)(struct net_device *dev,
                            struct netdev_phys_item_id *ppid);
    int            (*ndo_get_phys_port_name)(struct net_device *dev,
                              char *name, size_t len);
    void            (*ndo_udp_tunnel_add)(struct net_device *dev,
                              struct udp_tunnel_info *ti);
    void            (*ndo_udp_tunnel_del)(struct net_device *dev,
                              struct udp_tunnel_info *ti);
    void*            (*ndo_dfwd_add_station)(struct net_device *pdev,
                            struct net_device *dev);
    void            (*ndo_dfwd_del_station)(struct net_device *pdev,
                            void *priv);

    netdev_tx_t        (*ndo_dfwd_start_xmit) (struct sk_buff *skb,
                            struct net_device *dev,
                            void *priv);
    int            (*ndo_get_lock_subclass)(struct net_device *dev);
    int            (*ndo_set_tx_maxrate)(struct net_device *dev,
                              int queue_index,
                              u32 maxrate);
    int            (*ndo_get_iflink)(const struct net_device *dev);
    int            (*ndo_change_proto_down)(struct net_device *dev,
                             bool proto_down);
    int            (*ndo_fill_metadata_dst)(struct net_device *dev,
                               struct sk_buff *skb);
    void            (*ndo_set_rx_headroom)(struct net_device *dev,
                               int needed_headroom);
    int            (*ndo_xdp)(struct net_device *dev,
                       struct netdev_xdp *xdp);
};

原文链接:https://blog.csdn.net/xy010902100449/article/details/47157113

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值