1. 程式人生 > >各種網路裝置分配建立net_device{}流程

各種網路裝置分配建立net_device{}流程

接下來分析alloc_netdev_mq()

 /*
@sizeof_priv 私有資料大小,驅動可以使用netdev_priv()得到該私有資料
@name:網路介面的名字
@setup:驅動程式負責實現此函式,實現的此函式用於初始化net_device中的一些成員
@queue_count:網路裝置的傳送佇列
net_device資料結構的記憶體空間+私有資料記憶體空間+裝置傳送佇列的記憶體空間+對齊位元組
*/
struct net_device *alloc_netdev_mq(int sizeof_priv, 
                                            const char *name,
		                                    void (*setup)(struct net_device *), 
		                                    unsigned int queue_count)
{
	struct netdev_queue *tx;
	struct net_device *dev;
	size_t alloc_size;
	struct net_device *p;

	//設定的網路介面名字不能太長
	BUG_ON(strlen(name) >= sizeof(dev->name));

	 /* 計算net_device結構大小 */
	alloc_size = sizeof(struct net_device);

	 /* 加上私有資料大小 */
	if (sizeof_priv) 
	{
		/* ensure 32-byte alignment of private area */
		alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
		alloc_size += sizeof_priv;
	}

	/* ensure 32-byte alignment of whole construct */
	/* 整個空間做對齊後的大小 */
	alloc_size += NETDEV_ALIGN - 1;

	p = kzalloc(alloc_size, GFP_KERNEL);
	if (!p) {
		printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
		return NULL;
	}

	//傳送佇列空間 在alloc_netdev()中queue_count為1
	tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
	if (!tx) 
	{
		printk(KERN_ERR "alloc_netdev: Unable to allocate tx qdiscs.\n");
		goto free_p;
	}

	/* 計算對齊的填充 */
	dev = PTR_ALIGN(p, NETDEV_ALIGN);

	//計算為了填充多增加了幾個位元組
	dev->padded = (char *)dev - (char *)p;

	/* 地址列表初始化 */
	if (dev_addr_init(dev))
		goto free_tx;

	//初始化單播地址列表
	dev_unicast_init(dev);
	
	/* 設定網路名稱空間net */
	dev_net_set(dev, &init_net);

	/* 設定傳送佇列數 */
	dev->_tx = tx;//關聯傳送佇列
	dev->num_tx_queues = queue_count;//傳送佇列數
	dev->real_num_tx_queues = queue_count;//活動的傳送佇列數

	dev->gso_max_size = GSO_MAX_SIZE;
    //初始化接收佇列
	netdev_init_queues(dev);
    
	INIT_LIST_HEAD(&dev->napi_list);
	
	dev->priv_flags = IFF_XMIT_DST_RELEASE;

	/* 給驅動程式一個機會來設定當前函式中未設定的net_dev物件成員 */
	setup(dev);
	
	//設定介面名
	strcpy(dev->name, name);
	return dev;

free_tx:
	kfree(tx);

free_p:
	kfree(p);
	return NULL;
}