zoukankan      html  css  js  c++  java
  • 虚拟网卡驱动

    alloc_netdev

    #define alloc_netdev(sizeof_priv, name, setup) 
    	alloc_netdev_mq(sizeof_priv, name, setup, 1)
    
    /**
     *	alloc_netdev_mq - allocate network device
     *	@sizeof_priv:	size of private data to allocate space for
     *	@name:		device name format string
     *	@setup:		callback to initialize device
     *	@queue_count:	the number of subqueues to allocate
     *
     *	Allocates a struct net_device with private data area for driver use
     *	and performs basic initialization.  Also allocates subquue structs
     *	for each queue on the device at the end of the netdevice.
     */
    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));
    
    	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.
    ");
    		return NULL;
    	}
    
    	tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
    	if (!tx) {
    		printk(KERN_ERR "alloc_netdev: Unable to allocate "
    		       "tx qdiscs.
    ");
    		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);
    
    	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;
    	setup(dev);
    	strcpy(dev->name, name);
    	return dev;
    
    free_tx:
    	kfree(tx);
    
    free_p:
    	kfree(p);
    	return NULL;
    }
    EXPORT_SYMBOL(alloc_netdev_mq);
    

    sizeof_priv:私有数据大小
    name:设备名
    setup:net_device部分成员初始化

    alloc_etherdev

    #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
    
    struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
    {
    	return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count);
    }
    

    alloc_etherdev相比alloc_netdev更常用

    网络接口的打开与关闭

    static inline void netif_start_queue(struct net_device *dev)
    static inline void netif_stop_queue(struct net_device *dev)
    

    netdev_priv

    #define netdev_priv(dev) (dev->priv)
    

    存取私有数据指针

    dev_hold
    设备的引用计数器加1

    dev_put
    设备的引用计数器减1

    dev_get_by_name
    取得设备指针
    记得dev_put取消设备引用

    /**
     *	dev_get_by_name		- find a device by its name
     *	@net: the applicable net namespace
     *	@name: name to find
     *
     *	Find an interface by name. This can be called from any
     *	context and does its own locking. The returned handle has
     *	the usage count incremented and the caller must use dev_put() to
     *	release it when it is no longer needed. %NULL is returned if no
     *	matching device is found.
     */
    
    struct net_device *dev_get_by_name(struct net *net, const char *name)
    {
    	struct net_device *dev;
    
    	read_lock(&dev_base_lock);
    	dev = __dev_get_by_name(net, name);
    	if (dev)
    		dev_hold(dev);
    	read_unlock(&dev_base_lock);
    	return dev;
    }
    

    举例

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/netdevice.h>
    #include <linux/etherdevice.h>
    #include <linux/skbuff.h>
    #include <linux/ethtool.h>
    
    static struct net_device *dev = NULL;
    
    static int net_open(struct net_device *dev)
    {
    	netif_start_queue(dev);
    	
    	return 0;
    }
    
    static int net_start_xmit(struct sk_buf *skb, struct net_device *dev)
    {
    	netif_start_queue(dev);
    
    	dev->stats.tx_packets++;
    	dev->stats.tx_bytes += skb->len;
    	
    	/* this is normally done in the interrupt when tx finishes */
    //	netif_wake_queue(dev);	
    
    	netif_stop_queue(dev);
    	
    	return 0;
    }
    
    static int net_close(struct net_device *dev)
    {
    	netif_stop_queue(dev);
    	
    	return 0;
    }
    
    static int __init net_init(void)
    {
    	dev = alloc_etherdev(0);
    	
    	dev->open = net_open;
    	dev->hard_start_xmit = &net_start_xmit;
    	dev->stop = net_close;
    	dev->tx_timeout = net_tx_timeout;
    	
    	ether_setup(dev);
    	
    	//注册网卡设备
    	register_netdev(dev);
    	
    	return 0;
    }
    
    //出口函数
    static void __exit net_exit(void)
    {
    	unregister_netdev(dev);
    	free_netdev(dev);
    	
    	return;
    }
    
    module_init(net_init);
    module_exit(net_exit);
    

    启动网卡

    # ifconfig "eth%d" 192.168.1.1 up
    
  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709805.html
Copyright © 2011-2022 走看看