net_device

来源:互联网 发布:微信在线客服系统源码 编辑:程序博客网 时间:2024/04/29 15:26

struct net_device表示一个网卡,通过init_net串在一起(不考虑net namespace)

struct net init_net;EXPORT_SYMBOL(init_net);

struct net定义了一个链表头以及两个hash表头用于快速寻找相应的net_device数据结构

struct net {    atomic_t        passive;    /* To decided when the network                         * namespace should be freed.                         */    atomic_t        count;      /* To decided when the network                         *  namespace should be shut down.                         */#ifdef NETNS_REFCNT_DEBUG    atomic_t        use_count;  /* To track references we                         * destroy on demand                         */#endif    spinlock_t      rules_mod_lock;    struct list_head    list;       /* list of network namespaces */    struct list_head    cleanup_list;   /* namespaces on death row */    struct list_head    exit_list;  /* Use only net_mutex */    struct proc_dir_entry   *proc_net;    struct proc_dir_entry   *proc_net_stat;#ifdef CONFIG_SYSCTL    struct ctl_table_set    sysctls;#endif    struct sock         *rtnl;          /* rtnetlink socket */    struct sock     *genl_sock;    struct list_head    dev_base_head;    struct hlist_head   *dev_name_head;    struct hlist_head   *dev_index_head;    unsigned int        dev_base_seq;   /* protected by rtnl_mutex */    /* core fib_rules */};

对应的net_device的分量如下:

struct net_device {    /*     * This is the first field of the "visible" part of this structure     * (i.e. as seen by users in the "Space.c" file).  It is the name     * of the interface.     */    char            name[IFNAMSIZ];    struct pm_qos_request_list pm_qos_req;    /* device name hash chain */    struct hlist_node   name_hlist;    struct list_head    dev_list;    struct hlist_node   index_hlist;    int         ifindex;    ...};

dev_base_head用于遍历:

#define for_each_netdev(net, d)     \        list_for_each_entry(d, &(net)->dev_base_head, dev_list)
dev_name_head以及dev_index_head用于根据设备名或者index获取net_device数据结构

struct net_device *dev_get_by_name_rcu(struct net *net, const char *name){    struct hlist_node *p;    struct net_device *dev;    struct hlist_head *head = dev_name_hash(net, name);    hlist_for_each_entry_rcu(dev, p, head, name_hlist)        if (!strncmp(dev->name, name, IFNAMSIZ))            return dev;    return NULL;}EXPORT_SYMBOL(dev_get_by_name_rcu);

struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex){    struct hlist_node *p;    struct net_device *dev;    struct hlist_head *head = dev_index_hash(net, ifindex);    hlist_for_each_entry_rcu(dev, p, head, index_hlist)        if (dev->ifindex == ifindex)            return dev;    return NULL;}
通过驱动的方式可以获取当前系统net_device的情况:

 struct net_device *dev_tmp;    for_each_netdev(&init_net, dev_tmp)        printk("dev name=%s,index=%d\n",dev_tmp->name,dev_tmp->ifindex);
输出如下:

[ 2472.696920] dev name=lo,index=1[ 2472.696926] dev name=eth0,index=2[ 2472.696929] dev name=wlan0,index=3

struct net_device数据结构一般在网卡驱动程序中申请注册以及卸载,卸载加载后index可能改变,

如卸载eth0对应的驱动后再重新加载后:

[ 3135.110849] dev name=lo,index=1[ 3135.110854] dev name=wlan0,index=3[ 3135.110858] dev name=eth0,index=4

以r8169驱动为例,调用 dev = alloc_etherdev(sizeof (*tp))函数分配net_device

struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,                      unsigned int rxqs){    return alloc_netdev_mqs(sizeof_priv, "eth%d", ether_setup, txqs, rxqs);}

void ether_setup(struct net_device *dev){    dev->header_ops     = &eth_header_ops;    dev->type       = ARPHRD_ETHER;    dev->hard_header_len    = ETH_HLEN;    dev->mtu        = ETH_DATA_LEN;    dev->addr_len       = ETH_ALEN;    dev->tx_queue_len   = 1000; /* Ethernet wants good queues */    dev->flags      = IFF_BROADCAST|IFF_MULTICAST;    dev->priv_flags     |= IFF_TX_SKB_SHARING;    memset(dev->broadcast, 0xFF, ETH_ALEN);}

调用register_netdev注册,加入到链表中:

static int list_netdevice(struct net_device *dev){    struct net *net = dev_net(dev);    ASSERT_RTNL();    write_lock_bh(&dev_base_lock);    list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);    hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));    hlist_add_head_rcu(&dev->index_hlist,               dev_index_hash(net, dev->ifindex));    write_unlock_bh(&dev_base_lock);    dev_base_seq_inc(net);    return 0;}


0 0
原创粉丝点击