admin管理员组

文章数量:1657732

说明:网卡驱动为网络硬件相关的驱动程序:

一、驱动框架

以drivers/net/ethernet/cirrus/cs89x0.c为例

1、分配一个结构体(内核驱动更多的是类似面向对象):

net_device

2、设置(网卡驱动与上层通信):

发包函数:ndo_start_xmit

收包函数:在中断函数里,用netif_rx

数据包格式:struct sk_buff

3、注册:

register_netdev

4、硬件相关操作:

二、最简单的虚拟网卡实现

新建virt_net/virt_net.c

#include <linux/module.h>
#include <linux/printk.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/atomic.h>

static struct net_device *vnet_dev;

// 有数据帧要发送时,内核会调用该函数
static int vnet_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 vnet_ops=
{
    // 发送数据帧
    .ndo_start_xmit=vnet_send_packet,
};

static int __init virt_net_init(void)
{
    printk(KERN_ERR "%s,%d\n",__FUNCTION__,__LINE__);
    
    //1、分配一个 net_device 结构体
    vnet_dev = alloc_netdev(0, "vnet%d", NET_NAME_UNKNOWN, ether_setup);//生成一个net_device结构体,对其成员赋值并返回该结构体的指针

    //2、设置
    //网络设备的操作集,这个参数一定要有!否则驱动无法加载
    vnet_dev->netdev_ops = &vnet_ops;

    //3、注册
    register_netdev(vnet_dev);

    //4、硬件操作

    return 0;
}

static __exit virt_net_exit(void)
{
    unregister_netdev(vnet_dev);
    free_netdev(vnet_dev);
}

module_init(virt_net_init);
module_exit(virt_net_exit);
MODULE_AUTHOR("zfeng");
MODULE_LICENSE("GPL");

三、测试

insmod virt_net.ko
ifconfig vnet0 1.1.1.1
ifconfig
eth0      Link encap:Ethernet  HWaddr 82:48:E9:AB:E7:76
          inet addr:10.117.197.11  Bcast:10.117.197.255  Mask:255.255.255.0
          inet6 addr: fe80::8048:e9ff:feab:e776/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2509 errors:0 dropped:62 overruns:0 frame:0
          TX packets:1160 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2233922 (2.1 MiB)  TX bytes:215180 (210.1 KiB)
          Interrupt:57

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

vnet0     Link encap:Ethernet  HWaddr 01:02:03:04:05:06
          inet addr:1.1.1.1  Bcast:1.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::302:3ff:fe04:506/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:578 (578.0 B)

ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: seq=0 ttl=64 time=0.148 ms
64 bytes from 1.1.1.1: seq=1 ttl=64 time=0.088 ms

本文标签: 内核网卡网卡驱动Linux