嵌入式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内没有按键 ...
随机推荐
- 从零开始编写自己的C#框架(17)——Web层后端首页
后端首页是管理员登陆后进入的第一个页面,主要是显示当前登陆用户信息.在线人数.菜单树列表.相关功能按键和系统介绍.让管理员能更方便的找到息想要的内容. 根据不同系统的需要,首页会显示不同的内容,比如显 ...
- ASP.NET MVC Html.BeginForm 设置 timeout
示例代码: @using (Html.BeginForm("PublishSubmit", "Blog", FormMethod.Post, new { id ...
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇三:Access远程连接数据库和窗体打包部署
篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...
- SolrNet高级用法(分页、Facet查询、任意分组)
前言 如果你在系统中用到了Solr的话,那么肯定会碰到从Solr中反推数据的需求,基于数据库数据生产索引后,那么Solr索引的数据相对准确,在电商需求中经常会碰到菜单.导航分类(比如电脑.PC的话会有 ...
- 【小型系统】简单的刷票系统(突破IP限制进行投票)
一.前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了 ...
- Linux内核配置、编译及Makefile简述
Hi,大家好!我是CrazyCatJack.最近在学习Linux内核的配置.编译及Makefile文件.今天总结一下学习成果,分享给大家^_^ 1.解压缩打补丁 首先是解压缩你获取到的Linux内核. ...
- 微服务(Microservices)—Martin Fowler【翻译】
本文转载自:http://www.cnblogs.com/liuning8023/p/4493156.html -------------------------------------------- ...
- agsXMPP
agsXMPP使用 agsXMPP中的例子已经有注册.登录.添加好友.接收好友添加请求.发送消息.接收消息等功能. 修改用户密码 登录后可用以下方法修改密码 IQ iq = new IQ(IqType ...
- MVC5+EF6+AutoMapper+Bootstrap打造在线博客(1.1)
DAL层的三个Model类: 字典表:CFDict 用户表:CFUser 用户爱好表:CFUserHobby(关联cfuser表和cfdict表) CFUser表和CFUserHobby表是一对多关系 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 7.外部接口的设计
目 录 第七章 外部接口的设计... 2 7.1 插件接口... 2 7.2 图形显示接口... 3 7.3 ...