嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序
一、协议栈层次对比

设备无关层到驱动层的体系结构

1)、网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接受数据。这一层的存在使得上层协议独立于具体的设备。
2)、网络设备接口层向协议接口层提供统一的用于描述具体网络设备属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。实际上,网络设备接口层从宏观上规划了具体操作硬件的设备驱动功能层的结构。
3)、设备驱动功能层各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,他通过hard_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接受操作。
4)、网络设备与媒介层是完成数据包发送和接受的物理实体,包括网络适配器和具体的传输媒介,网络适配器被驱动功能层中的函数物理上驱动。对于Linux系统而言,网络设备和媒介都可以是虚拟的。
网络协议接口层:主要进行数据包的收发。
驱动程序代码:
/*************************************************************************
> File Name: s3c_virnet.c
> Author:
> Mail:
> Created Time: 2016年11月09日 星期三 13时27分51秒
************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.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/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/ip.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h> static struct net_device *vnet_dev; static void virnet_tx_packet(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *type;
struct iphdr *ih;
__be32 *saddr, *daddr, tmp;
unsigned char tmp_dev_addr[ETH_ALEN];
struct ethhdr *ethhdr; struct sk_buff *rx_skb; /* 对调MAC地址 */
ethhdr = (struct ethhdr *)skb->data;
memcpy(tmp_dev_addr,ethhdr->h_dest,ETH_ALEN);
memcpy(ethhdr->h_dest,ethhdr->h_source,ETH_ALEN);
memcpy(ethhdr->h_source,tmp_dev_addr,ETH_ALEN); /* */
ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
saddr = &ih->saddr;
daddr = &ih->daddr; tmp = *saddr;
*saddr = *daddr;
*daddr = tmp; type = skb->data + sizeof(struct ethhdr)+sizeof(struct iphdr); *type = ; ih->check = ;
ih->check = ip_fast_csum((unsigned char*)ih,ih->ihl); rx_skb = dev_alloc_skb(skb->len + );
skb_reserve(rx_skb,);
memcpy(skb_put(rx_skb,skb->len),skb->data,skb->len); rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
netif_rx(rx_skb); }
static int virnet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len; netif_stop_queue(dev); //停止该网卡的队列
/*把skb的数据写入网卡*/
//dev_kfree_skb(skb); //释放skb
netif_wake_queue(dev); //数据发送成功后唤醒队列
/* 构造出一个假的sk_buff */ virnet_tx_packet(skb,dev); return ;
} static int s3c_virnet_init(void)
{ /* 分配一个net_device结构体 */
vnet_dev = alloc_netdev(, "vnet%d", ether_setup); /* 设置 */
vnet_dev->hard_start_xmit = virnet_send_packet; /* MAC地址设置 */
vnet_dev->dev_addr[] = 0x07;
vnet_dev->dev_addr[] = 0x05;
vnet_dev->dev_addr[] = 0x06;
vnet_dev->dev_addr[] = 0x07;
vnet_dev->dev_addr[] = 0x08;
vnet_dev->dev_addr[] = 0x09; /* 添加下面的配置后才能ping通 */
vnet_dev->flags |= IFF_NOARP;
vnet_dev->features |= NETIF_F_NO_CSUM; /* 注册 */
register_netdev(vnet_dev); return ;
} static void s3c_virnet_exit(void)
{
unregister_netdev(vnet_dev); free_netdev(vnet_dev);
} module_init(s3c_virnet_init);
module_exit(s3c_virnet_exit);
MODULE_LICENSE("GPL");
sd
嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序的更多相关文章
- 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序
基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...
- 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序
Nor Flash和Nand Flash的不同: 类型 NOR Flash Nand Flash 接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...
- 嵌入式Linux驱动学习之路(二十二)用内存模拟磁盘
安装驱动后,可在/dev/目录下发现已经生成了相应的设备文件. 格式化设备:mkdosfs /dev/ramblock. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...
- 嵌入式Linux驱动学习之路(二十)USB设备驱动
USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...
- 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序
NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...
- 嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法
之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 struct file_operations 结构体对应. 而本节课讲的是如何在设备号相同的情况下,让不同的次设备号对 ...
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...
- 嵌入式Linux驱动学习之路(二)u-boot体验
u-boot工程简介 现在的u-boot支持PowerPC.ARM.X86.MIPS体系结构的上百种开发板,已经称为功能最多.灵活性最强,并且开发最积极的开源Bootloader.目前由DENX的Wo ...
- 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制
实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...
随机推荐
- Swift 必备开发库 (高级篇) (转)
1.CryptoSwift swift加密库, 支持md5,sha1,sha224,sha256... github地址: https://github.com/krzyzanowskim/Crypt ...
- ios 开发需要看的书籍
1.吴航写的<iOS应用逆向工程 第2版> 2.<iOS 应用安全攻防实战> 3.
- 单机静默安装GI软件并创建ASM实例和ASM磁盘组
环境:RHEL 6.4 + Oracle 11.2.0.4 需求:单机静默安装GI软件并创建ASM实例和ASM磁盘组,为后续迁移数据库文件到ASM做准备 1. 安装配置GI软件 2. 创建ASM实例 ...
- Apache Spark简单介绍、安装及使用
Apache Spark简介 Apache Spark是一个高速的通用型计算引擎,用来实现分布式的大规模数据的处理任务. 分布式的处理方式可以使以前单台计算机面对大规模数据时处理不了的情况成为可能. ...
- ThreadLocal<T>的是否有设计问题
一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...
- [占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合
[占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合 Datasets can often contain components of that require differe ...
- 在Ubuntu|CentOS上安装Shutter截图工具及快捷键设置
简介 Shutter前身叫GScrot,它是一款相当棒的截图软件. 通过Shutter,你可以截取包括选定区域.全屏幕.窗口.窗口内的控件甚至网页的图像.通过内置的强大插件机制,你可以在截图后,对图像 ...
- Entity Framework 教程——安装Entity Framework环境
安装Entity Framework环境 Entity Framework 5.0 API分布在两个地方,一个可在NuGet包管理器中找到,一个存在于.NET framework中..NET fram ...
- [Android下载]北京新版小学英语三年级上册点读手机软件
小学英语三年级上册点读软件.根据2014年北京教改版教材编写,发音标准.实现点读功能.点到哪里读到哪里.哪里不会点哪里!北京教育科学研究院编写,北京出版社出版.ISBN:9787200108781 ...
- Aix/Linux下自动备份oracle数据库
曾经有个同事,来回操作开发和生产的数据库,结果误删了生产的数据库,那种心情我想不是一般人能理解的,虽然说oracle可以有方法还原,但并不是彻底的. 所以,在工作中,不管是开发还是维护,备份数据库是非 ...