网络设备之分配net_device结构

注册网络设备时,会调用pci_driver->probe函数,以e100为例,最终会调用alloc_netdev_mqs来分配内存,并且在分配内存后调用setup函数(以太网为ether_setup)初始化二层地址等信息,这里主要分析alloc_netdev_mqs函数,以及ether_setup函数:

e100_probe----->alloc_etherdev----->alloc_netdev_mqs

|

|---->ether_setup

  1 /**
  2  * alloc_netdev_mqs - allocate network device
  3  * @sizeof_priv: size of private data to allocate space for
  4  * @name: device name format string
  5  * @name_assign_type: origin of device name
  6  * @setup: callback to initialize device
  7  * @txqs: the number of TX subqueues to allocate
  8  * @rxqs: the number of RX subqueues to allocate
  9  *
 10  * Allocates a struct net_device with private data area for driver use
 11  * and performs basic initialization.  Also allocates subqueue structs
 12  * for each queue on the device.
 13  */
 14 struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 15         unsigned char name_assign_type,
 16         void (*setup)(struct net_device *),
 17         unsigned int txqs, unsigned int rxqs)
 18 {
 19     struct net_device *dev;
 20     size_t alloc_size;
 21     struct net_device *p;
 22
 23     BUG_ON(strlen(name) >= sizeof(dev->name));
 24
 25     /* 检查发送队列数 */
 26     if (txqs < 1) {
 27         pr_err("alloc_netdev: Unable to allocate device with zero queues\n");
 28         return NULL;
 29     }
 30
 31     /* 检查接收队列数 */
 32 #ifdef CONFIG_SYSFS
 33     if (rxqs < 1) {
 34         pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n");
 35         return NULL;
 36     }
 37 #endif
 38
 39     /* 计算net_device结构大小 */
 40     alloc_size = sizeof(struct net_device);
 41     /* 加上私有数据大小 */
 42     if (sizeof_priv) {
 43         /* ensure 32-byte alignment of private area */
 44         alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
 45         alloc_size += sizeof_priv;
 46     }
 47     /* ensure 32-byte alignment of whole construct */
 48     /* 整个空间做对齐后的大小 */
 49     alloc_size += NETDEV_ALIGN - 1;
 50
 51     /* 分配内存 */
 52     p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_REPEAT);
 53     if (!p)
 54         return NULL;
 55
 56     /* 内存对齐 */
 57     dev = PTR_ALIGN(p, NETDEV_ALIGN);
 58
 59     /* 计算对齐的填充 */
 60     dev->padded = (char *)dev - (char *)p;
 61
 62     /* 分配设备引用 */
 63     dev->pcpu_refcnt = alloc_percpu(int);
 64     if (!dev->pcpu_refcnt)
 65         goto free_dev;
 66
 67     /* 地址列表初始化 */
 68     if (dev_addr_init(dev))
 69         goto free_pcpu;
 70
 71     /* 组播列表初始化 */
 72     dev_mc_init(dev);
 73
 74     /* 单播列表初始化 */
 75     dev_uc_init(dev);
 76
 77     /* 设置net */
 78     dev_net_set(dev, &init_net);
 79
 80     /* GSO设置 */
 81     dev->gso_max_size = GSO_MAX_SIZE;
 82     dev->gso_max_segs = GSO_MAX_SEGS;
 83
 84     /* 初始化各种链表 */
 85     INIT_LIST_HEAD(&dev->napi_list);
 86     INIT_LIST_HEAD(&dev->unreg_list);
 87     INIT_LIST_HEAD(&dev->close_list);
 88     INIT_LIST_HEAD(&dev->link_watch_list);
 89     INIT_LIST_HEAD(&dev->adj_list.upper);
 90     INIT_LIST_HEAD(&dev->adj_list.lower);
 91     INIT_LIST_HEAD(&dev->ptype_all);
 92     INIT_LIST_HEAD(&dev->ptype_specific);
 93 #ifdef CONFIG_NET_SCHED
 94     hash_init(dev->qdisc_hash);
 95 #endif
 96     dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
 97
 98     /* 初始化设备硬件地址,mtu等参数 */
 99     setup(dev);
100
101     /* 队列长度为0,则采用默认值 */
102     if (!dev->tx_queue_len) {
103         dev->priv_flags |= IFF_NO_QUEUE;
104         dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
105     }
106
107     /* 设置发送队列数 */
108     dev->num_tx_queues = txqs;
109     dev->real_num_tx_queues = txqs;
110
111     /* 分配初始化发送队列 */
112     if (netif_alloc_netdev_queues(dev))
113         goto free_all;
114
115 #ifdef CONFIG_SYSFS
116     /* 设置接收队列数 */
117     dev->num_rx_queues = rxqs;
118     dev->real_num_rx_queues = rxqs;
119
120     /* 分配初始化接收队列 */
121     if (netif_alloc_rx_queues(dev))
122         goto free_all;
123 #endif
124
125     /* 拷贝名字 */
126     strcpy(dev->name, name);
127
128     /* 赋值名字赋值类型 */
129     dev->name_assign_type = name_assign_type;
130
131     /* 设置设备组 */
132     dev->group = INIT_NETDEV_GROUP;
133
134     /* 设置默认ethtool操作 */
135     if (!dev->ethtool_ops)
136         dev->ethtool_ops = &default_ethtool_ops;
137
138     /* 初始化netfilter入口 */
139     nf_hook_ingress_init(dev);
140
141     return dev;
142
143 free_all:
144     free_netdev(dev);
145     return NULL;
146
147 free_pcpu:
148     free_percpu(dev->pcpu_refcnt);
149 free_dev:
150     netdev_freemem(dev);
151     return NULL;
152 }
 1 /**
 2  * ether_setup - setup Ethernet network device
 3  * @dev: network device
 4  *
 5  * Fill in the fields of the device structure with Ethernet-generic values.
 6  */
 7 void ether_setup(struct net_device *dev)
 8 {
 9     dev->header_ops        = &eth_header_ops;
10     dev->type        = ARPHRD_ETHER;
11     dev->hard_header_len     = ETH_HLEN;
12     dev->min_header_len    = ETH_HLEN;
13     dev->mtu        = ETH_DATA_LEN;
14     dev->min_mtu        = ETH_MIN_MTU;
15     dev->max_mtu        = ETH_DATA_LEN;
16     dev->addr_len        = ETH_ALEN;
17     dev->tx_queue_len    = DEFAULT_TX_QUEUE_LEN;
18     dev->flags        = IFF_BROADCAST|IFF_MULTICAST;
19     dev->priv_flags        |= IFF_TX_SKB_SHARING;
20
21     eth_broadcast_addr(dev->broadcast);
22
23 }
时间: 2024-10-04 09:01:56

网络设备之分配net_device结构的相关文章

net_device 结构体分析

/*  *    The DEVICE structure.  *    Actually, this whole structure is a big mistake.  It mixes I/O  *    data with strictly "high-level" data, and it has to know about  *    almost every data structure used in the INET module.  *  *    FIXME: c

线性表的动态内存分配顺序存储结构

1.线性表是最简单的一种数据结构,很容易实现其中单个元素的存取操作,但是对于插入和删除操作需要大量的移动.比较适用于相对稳定的线性表. 2.数据元素 struct SqList { ElemType * elem ; //存储空间基址 int length ; //当前长度 int listsize ; //当前分配的存储容量 }; 3.创建一个空的线性表 void InitList(SqList &L) { //构造一个空的顺序线性表L L.elem = (ElemType*)malloc(L

串的堆分配存储结构

串的堆分配存储,其具体实现方式是采用动态数组存储字符串. 通常,编程语言会将程序占有的内存空间分成多个不同的区域,程序包含的数据会被分们别类并存储到对应的区域.拿C语言来说,程序会将内存分为4个区域,分别为堆区.栈区.数据区和代码区.其中的堆分配 与其他区域不同,堆区的内存空间需要程序员手动使用malloc函数申请,并且在不用后要手动通过free函数将其释放 代码: #include <stdio.h>#include <stdlib.h>#include <string.h

struct net_device网络设备结构体详解

在linux中使用struct net_device结构体来描述每一个网络设备.同时这个用来刻画网络设备的struct net_device结构体包含的字段非常的多,以至于内核的开发者都觉得在现在的linux内核中,这个struct net_device是一个大的错误.    在本篇文章中,只介绍struct net_device中的一些字段,其他的字段在以后使用的时候再说.    #define IFNAMSIZ 32    struct net_device    {        //用于

《linux设备驱动开发详解》笔记——14 linux网络设备驱动

14.1 网络设备驱动结构 网络协议接口层:硬件无关,标准收发函数dev_queue_xmit()和netif_rx();  注意,netif_rx是将接收到的数据给上层,有时也在驱动收到数据以后调用. 网络设备接口层,net_device,统一接口名称,使上层独立于具体硬件. 设备驱动功能层,实现net_device的各成员 物理层 在整个以太网架构里,有两个数据结构非常重要,即sk_buff和net_device,后面两节有说明. 还有一些与内核交互的函数,需要掌握,如netif_start

网络设备

PCI设备 很多网络设备都是基于PCI接口的.因此尽管网络设备驱动比较特殊,但也要作为PCI驱动注册到内核中. PCI接口等定义.网络设备驱动相关定义涉及以下文件: include/linux/mod_devicetable.h 定义导出到用户控件的PCI设备信息 include/linux/pci.h 定义PCI接口驱动相关的结构.宏等 include/linux/netdevice.h 定义网络设备结构.宏等 include/linux/inetdevice.h 定义IPV4专用的网络设备相

Linux 网络设备驱动程序设计(4)

四.DM9000网卡驱动深度分析 1. DM9000的初始化 DM9000_init() { 1. 分配 net_device 结构 2. 从 platform_device 中获取地址中断号 3.  把获取的地址映射成虚拟地址 操作函数 io_remp() 4. 读取芯片类型 5. 设置操作函数集 6. 注册网卡驱动 Register } 2. DM9000_open() { 1. ifconfig eth0 up } 3. DM9000_xmit() { 1. 通知协议线,暂停向驱动传送数据

Linux 网络设备驱动程序设计(2)

二.回环网卡的程序设计 /*************************** *******回环网卡的驱动程序*** ***********吕晓宁*********** *********2015.12.26********* ***************************/ #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/module.h> #include <

由PPPOE看Linux网络协议栈的实现

http://www.cnblogs.com/zmkeil/archive/2013/05/01/3053545.html 这个标题起得比较纠结,之前熟知的PPPOE是作为PPP协议的底层载体,而实际上它也是一个完整的协议,不过它的实现比较简单,由它出发,可以很容易理清楚Linux网络栈的实现方式. 1.总述 Linux中用户空间的网络编程,是以socket为接口,一般创建一个sockfd = socket(family,type,protocol),之后以该sockfd为参数,进行各种系统调用