天天看點

Linux網絡裝置驅動子產品——虛拟網卡virnet

環境

系統:Ubuntu16.04

kernel:4.10.0-28-generic

建立目錄和檔案

~$ mkdir virnet
~$ cd virnet
~/virnet$ touch virnet.c
~/virnet$ touch Makefile
           

添加以下内容到virnet.c檔案

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/netdevice.h>

MODULE_LICENSE("GPL");

// 網絡裝置對象
static struct net_device *sg_dev;

// 有資料幀要發送時,kernel會調用該函數
static int virnet_send_packet(struct sk_buff *skb,struct net_device *dev)
{
    // 統計已發送的資料包
    dev->stats.tx_packets++;
    // 統計已發送的位元組
    dev->stats.tx_bytes+=skb->len;
    // 釋放資料幀
    dev_kfree_skb(skb);
    return 0;
}

// 驅動程式支援的操作
static struct net_device_ops sg_ops=
{
    // 發送資料幀
    .ndo_start_xmit=virnet_send_packet,
};

// 驅動程式初始化
static int virnet_init(void)
{
    // 建立一個網絡裝置,名為“virnet%d",kernel會自動填寫%d為網卡編号
    //sg_dev=alloc_netdev(0,"virnet%d",ether_setup);
    // kernel 4.4.0-97上需要四個參數如下
    sg_dev=alloc_netdev(0,"virnet%d", NET_NAME_UNKNOWN, ether_setup);
    // 該網絡裝置的操作集
    sg_dev->netdev_ops=&sg_ops;
    // MAC位址是01:02:03:04:05:06
    memcpy(sg_dev->dev_addr,"\x01\x02\x03\x04\x05\x06",6);
    // 注冊網絡裝置
    register_netdev(sg_dev);
    return 0;
}

// 驅動程式銷毀
static void virnet_exit(void)
{
    // 登出網絡裝置
    unregister_netdev(sg_dev);
    // 釋放對象
    free_netdev(sg_dev);
}

module_init(virnet_init);
module_exit(virnet_exit);
           

添加以下内容到Makefile檔案

obj-m := virnet.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
	make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules
clean:
	rm *.o *.ko *.mod.c
.PHONY:clean
           

編譯和測試

~/virnet$ make
~/virnet$ sudo insmod virnet.ko
~/virnet$ ifconfig -a
~/virnet$ sudo rmmod virnet
           

參考

第一個Linux網絡裝置驅動——最簡虛拟網卡virnet

繼續閱讀