【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】

网卡驱动为每一个新的接口在一个全局的网络设备列表里插入一个数据结构.每一个接口由一个结构 net_device 项来描写叙述, 它在 <linux/netdevice.h> 里定义。该结构必须动态分配。

进行这样的分配的内核函数是 alloc_netdev, 它有下列原型:

struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *));

sizeof_priv 是驱动的的"私有数据"区的大小;name 是这个接口的名子;这个名子能够有一个 printf 风格的 %d 在里面. 内核用下一个可用的接口号来替换这个 %d。setup 是一个初始化函数的指针, 被调用来设置 net_device 结构的剩余部分。

网络子系统为各种接口提供了一些帮助函数, 包裹着 alloc_netdev。最通用的是 alloc_etherdev, 定义在 <linux/etherdevice.h>,还有其它网络设备接口,如alloc_fcdev ( 定义在 <linux/fcdevice.h> ) 为 fiber-channel 设备, alloc_fddidev (<linux/fddidevice.h>) 为 FDDI 设备, 或者 aloc_trdev (<linux/trdevice.h>) 为令牌环设备。

alloc_etherdev函数原型为:

struct net_device *alloc_etherdev(int sizeof_priv);

当中sizeof_priv 是驱动的的"私有数据"区的大小;这个函数分配一个网络设备使用 eth%d 作为參数 name. 它提供了自己的初始化函数 ( ether_setup )来设置几个 net_device 字段, 使用对以太网设备合适的值。 因此, 没有驱动提供的初始化函数给 alloc_etherdev;

他自己提供的初始化函数ether_setup为:

/**
* ether_setup - setup Ethernet network device
* @dev: network device
* Fill in the fields of the device structure with Ethernet-generic values.
*/
void ether_setup(struct net_device *dev)
{
dev->header_ops = ð_header_ops;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 1000; /* Ethernet wants good queues */
dev->flags = IFF_BROADCAST|IFF_MULTICAST; memset(dev->broadcast, 0xFF, ETH_ALEN); }

EXPORT_SYMBOL(ether_setup);

实际上该函数也是不过负责了一些以太网范围中的缺省值而已。一般alloc_netdev函数提供的setup函数也会调用该函数来设置这些缺省值。

事实上无论使用alloc_netdev函数还是alloc_etherdev函数都不只设置这些缺省值就够了。

既然是编写网络设备驱动,就要完毕网卡的基本功能:收发数据包,统计网卡数据等,所以一般还要设置该结构体里面的这些功能函数指针,而这些函数正是网络设备驱动须要实现的基本功能。所以假设使用函数alloc_netdev分配空间,那么setup函数一般实现为:

{
ether_setup(dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
dev->netdev_ops = &xxx_netdev_ops;
#else
dev->open = xxx_open;
dev->stop = xxx_stop;
dev->hard_start_xmit = xxx_tx;
dev->get_stats = xxx_stats;
// dev->change_mtu = xxx_change_mtu;
...
#endif
}

假设使用alloc_etherdev函数分配,那么在该函数之后还须要作例如以下设置:

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
dev->netdev_ops = &xxx_netdev_ops;
#else
dev->open = xxx_open;
dev->stop = xxx_stop;
dev->hard_start_xmit = xxx_tx;
dev->get_stats = xxx_stats;
// dev->change_mtu = xxx_change_mtu;
...
#endif

事实上二者的区别就是alloc_etherdev函数默认自己主动调用ether_setup函数而且自己主动分配一个网络设备使用 eth%d 作为參数 name,而函数alloc_netdev须要自己传入參数来设置这些项而已。

net_device 结构初始化之后, 传递这个结构给 register_netdev函数完毕注冊。

然后你必需要做的就是实现之前注冊的那些函数,收发函数的具体分析会在后面具体解说。

linux内核数据包转发流程(一):网络设备驱动的更多相关文章

  1. linux内核数据包转发流程(三)网卡帧接收分析

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu.邮箱:shallnew*163.com] 每一个cpu都有队列来处理接收到的帧,都有其数据结构来处理入口和出口流量,因此,不 ...

  2. linux内核数据包转发流程(二):中断

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu.邮箱:shallnew*163.com] 内核在处理2层数据包之前,必须先处理中断系统.设立中断系统,才有可能每秒处理成千的 ...

  3. Linux内核数据包的发送传输

    本文主要讲解了Linux内核数据包的传输流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式从内核高层面上梳理了二层数据包发送传输的流程,希望可以对大家有所帮助. ...

  4. [Docker]Docker与Linux ip_forward数据包转发

    背景 今天在一台新虚拟机上需要临时启动一个consul服务,安装Docker后使用docker启动,但是在执行启动命令后发现docker有一个警告: WARNING: IPv4 forwarding ...

  5. Linux内核二层数据包接收流程

    本文主要讲解了Linux内核二层数据包接收流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式从内核高层面上梳理了二层数据包接收的流程,希望可以对大家有所帮助.阅 ...

  6. LINUX下的远端主机登入 校园网络注册 网络数据包转发和捕获

    第一部分:LINUX 下的远端主机登入和校园网注册 校园网内目的主机远程管理登入程序 本程序为校园网内远程登入,管理功能,该程序分服务器端和客户端两部分:服务器端为remote_server_udp. ...

  7. Linux内核网络数据包处理流程

    Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...

  8. linux 内核网络数据包接收流程

    转:https://segmentfault.com/a/1190000008836467 本文将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的. 如果英文没有问题,强烈建议阅读后面 ...

  9. Linux内核网络报文简单流程

    转:http://blog.csdn.net/adamska0104/article/details/45397177 Linux内核网络报文简单流程2014-08-12 10:05:09 分类: L ...

随机推荐

  1. IntelliJ IDEA 显示行号

    设置方法如下:   File->Settings->Editor->Appearence->Show Line Number

  2. HTML/CSS权值继承

    <style type="text/css">p{color:red;}.first{color:green;}/*因为权值高显示为绿色*/ span{color:pi ...

  3. MemSQL Start[c]UP 2.0 - Round 1 E - Three strings 广义后缀自动机

    E - Three strings 将三个串加进去,看每个节点在三个串中分别出现了多少次. #include<bits/stdc++.h> #define LL long long #de ...

  4. thinkphp _complex 复合查询 where多个子组实现

    SELECT * FROM `user` WHERE ( `mobile` = '13824653465' OR `nickname` = 'evan' OR `openid` = '14545-fd ...

  5. 再议js的传递和深复制

    病理 基本类型的传递就是按值传递,比如说 var a = 1; var b = a; b = 3; console.log(a,b);//1,3 很明显,a的值并未因为b的值改变而变化,这是因为a只是 ...

  6. Python爬虫个人记录(四)利用Python在豆瓣上写一篇日记

    涉及关键词:requests库 requests.post方法 cookies登陆 version 1.5(附录):使用post方法登陆豆瓣,成功! 缺点:无法获得登陆成功后的cookie,要使用js ...

  7. Servlet的一点小结

    1.什么是servlet servlet是一个Java applet,一个帮助程序.用于帮助浏览器从服务器中获取资源.浏览器-servlet-服务器三者的关系如图所示. 2.servlet的生命周期 ...

  8. 深度学习基础系列(五)| 深入理解交叉熵函数及其在tensorflow和keras中的实现

    在统计学中,损失函数是一种衡量损失和错误(这种损失与“错误地”估计有关,如费用或者设备的损失)程度的函数.假设某样本的实际输出为a,而预计的输出为y,则y与a之间存在偏差,深度学习的目的即是通过不断地 ...

  9. 字符串hash与字典树

    title: 字符串hash与字典树 date: 2018-08-01 22:05:29 tags: acm 算法 字符串 概述 这篇主要是关于字符串里的 字符串hash 和 字符串字典树,,两个都是 ...

  10. mysql正则表达式,实现多个字段匹配多个like模糊查询

    现在有这么一个需求 一个questions表,字段有题目(TestSubject),选项(AnswerA,AnswerB,AnswerC,AnswerD,AnswerE) 要求字段不包含png,jpg ...