zoukankan      html  css  js  c++  java
  • 回环网卡驱动设计

      回环网卡是一个虚拟网卡,当上层协议栈发出包后,包又会被发回给上层协议栈。下面来编程实现回环网卡驱动。

      所需头文件

    #include <linux/kernel.h>
    #include <linux/jiffies.h>
    #include <linux/module.h>
    #include <linux/interrupt.h>
    #include <linux/fs.h>
    #include <linux/types.h>
    #include <linux/string.h>
    #include <linux/socket.h>
    #include <linux/errno.h>
    #include <linux/fcntl.h>
    #include <linux/in.h>
    #include <linux/init.h>
    
    #include <asm/system.h>
    #include <asm/uaccess.h>
    #include <asm/io.h>
    
    #include <linux/inet.h>
    #include <linux/netdevice.h>
    #include <linux/etherdevice.h>
    #include <linux/skbuff.h>
    #include <linux/ethtool.h>
    #include <net/sock.h>
    #include <net/checksum.h>
    #include <linux/if_ether.h>    /* For the statistics structure. */
    #include <linux/if_arp.h>    /* For ARPHRD_ETHER */
    #include <linux/ip.h>
    #include <linux/tcp.h>
    #include <linux/percpu.h>
    #include <net/net_namespace.h>

      全局变量

    unsigned long bites = 0;    //记录数据量
    unsigned long packets = 0;   //记录数据包的数量
    
    struct net_device *dev;     //定义一个网卡驱动

      从上篇网卡驱动架构分析中可知,首先要进行网卡的初始化

    static __net_init int loopback_net_init(struct net *net)
    {
        dev = alloc_netdev(0,"lo%d",lo_setup);  //给网卡驱动分配空间    
        register_netdev(dev);            //注册网卡驱动
        net->loopback_dev = dev;          
    
        return 0;
    }

      这里没有用alloc_etherdev函数,因为alloc_etherdev只能为以太网卡分配空间。我们这里使用alloc_netdev函数,linux中函数定义为

    define alloc_netdev(sizeof_priv, name, setup),其中第一个参数表示net_device结构中一个成员priv占用空间的大小,我们这里不使用,所以填0。第二个参数表示回环网卡的名称,第三个参数是一个函数指针,分配完空间后会自动调用setup函数来进行网卡的初始化,所以我们将初始化的操作移至setup函数中。分配好空间之后将网卡驱动注册到linux内核中。最后告诉linux内核回环网卡驱动为dev。

      接下来是lo_setup函数的实现

    static void __init lo_setup(struct net_device *dev)
    {
        dev->netdev_ops = &lo_ops;        //网卡操作函数集
        dev->mtu = (16*1024) + 20 + 20 + 12;  //最大能接收数据包的大小 
        dev->flags = IFF_LOOPBACK;        //网卡驱动的标志
        dev->header_ops = &eth_header_ops;   //构造头的函数集
    
    }

      lo_setup函数进行网卡的初始化。上篇文章提到初始化中断号、I/O基地址、MAC地址都是针对物理的网卡,我们今天的回环网卡是一个虚拟网卡,所以不需要对他们进行初始化。这里初始化的有这几项:

        1、网卡操作函数集

        2、最大能接收数据包的大小

        3、网卡驱动的标志,指明是一个回环网卡

        4、构造头的函数集

      网卡操作函数集实现两个函数:数据的接收和查询网卡状态

    struct net_device_ops lo_ops = 
    {
        .ndo_start_xmit = lo_xmit,
        .ndo_get_stats = lo_get_stats,
    };

      首先看发送数据函数的实现:

      

    static int lo_xmit(struct sk_buff *skb, struct net_device *dev)
    {
        /*标明以太网协议*/
        skb->protocol = eth_type_trans(skb,dev);
    
        /*统计信息*/
        bites += skb->len;
        packets ++;
    
        netif_rx(skb);
    
        return 0;
    }

      由于回环网卡在发送数据之后立刻就将数据接收回来,所以不必让上层协议暂停发送数据。再者回环网卡是虚拟网卡,也不需要将数据写入寄存器中发送。在这个函数中我们只简单的统计数据长度和包数量的信息,然后将数据包发回给上层协议栈即可。

      然后是查看状态函数

    static struct net_device_stats *lo_get_stats(struct net_device *dev)
    {
        struct net_device_stats *stats = &dev->stats;
        stats->rx_packets = packets;
        stats->tx_packets = packets;
        stats->rx_bytes = bites;
        stats->tx_bytes = bites;
    
        return stats;
    }

      这样回环网卡的驱动程序大致就设计完了。由于回环网卡是虚拟网卡,不牵扯中断、寄存器等硬件信息,所以驱动程序十分简单。

      如果有疑问或错误,欢迎指出。

      

  • 相关阅读:
    银行存钱取钱余额的图形程序
    centos7 的httpd的问题
    idea创建springboot项目初始化失败解决方案
    Spring Boot之yaml配置注入基本使用
    idea修改Java注释的颜色
    IDEA常用快捷键及修改快捷键
    WordPress Markdown编辑器插件:WP Githuber MD
    Docker安装solo博客部署到云服务器教程
    Spring Boot 定制个性 banner
    Java类型转换
  • 原文地址:https://www.cnblogs.com/51qianrushi/p/4337935.html
Copyright © 2011-2022 走看看