您的位置:首页 > 理论基础 > 计算机网络

linux网络设备应用与驱动编程学习笔记(2)——网络驱动基础

2011-09-20 16:53 1016 查看
一、网络模型

OSI网络参考模型

应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

tcp/ip网络模型

应用层(数据段),传输层(数据包),网络互连层(数据帧),主机到网络层(比特)

以太网工作在主机到网络层。

IP层对应网络互连层,它是一个无连接,不可靠的协议。

无连接,报文走的数据通道不是固定的。

不可靠,发送数据的主机不保证数据能完全正确被接收。

网络设备不会在/dev下存在一个设备入口,它使用保留的内部设备名

网络设备的特点

1.网络设备异步的接收外来的数据包,有别于其他设备

2.网络设备主动的“请求”将硬件获得的数据包压入内核,而其他设备例如块设备被“

请求”向内核发送缓冲区

3.网络设备同时要执行大量的管理任务

设置地址

修改传输参数

维护流量和流量控制

错误统计和报告

4.网络子系统是完全与协议无关的,网络驱动程序与内核其余部分之间的每次交互处理的都是一个网络数据包

二、以太网(IEEE802.3)协议驱动相关帧结构

前导位PR 62bit

帧起始位SD 2bit

目的IP地址 48bit

源IP地址48bit

类型TYPE/长度16bit

数据DATA <=1500B

填充PAD可选

校验FCS32bit

网卡驱动不必关心所有内容,如前导序列,帧起始位,CRC校验由硬件自动添加/删除,与驱动软件无关。

以太网,不是具体的某个网络,而是一种技术标准。它对应于OSI网络模型中的数据链路层中的协议。数据链路层又细分为LLC和MAC两层。

以太,以前科学假设中,一种光传播的介质。后来证明根本不存在。网络传输中,用以太网命名一种技术标准,大概是象征使用这种技术数据传输速度快。

三、linux网络设备驱动程序概述

linux系统采用面向对象的设计方法,一个设备就是一个对象,它内部有自己的数据和方法

linux网络驱动程序的体系结构分为四层

网络协议接口,网络设备接口,设备驱动功能,网络设备和媒介层。

tcp/ip网络模型与linux网络驱动关系



设备驱动最主要的工作是完成设备驱动功能层。在linux中所有网络设备都抽象为一种数据结构对象(或称为接口)。网络设备在内核中的运行情况由数据结构struct net_device来表示。它提供了很多供系统访问和协议层调用的设备方法。

网络设备在linux里做专门的处理。linux网络系统主要是基于BSD unix的socket机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传输。

n 网络协议接口层

当上层ARP或IP需要发送数据包时,它将调用网络协议接口层dev_queue_xmit()函数发送数据包,同时需给该函数一个指向struct sk_buf数据结构的指针。

dev_queue_xmit(struct sk_buff *skb);

同样,上层对数据包的接收也通过向netif_rf()函数传递一个struct sk_buff结构指针来完成。

int netif_rx(struct sk_buff *skb);

u 套接字缓冲区(sk_buff)

当发送数据包时,linux内核的网络处理模块必须建立一个包含要传输的数据包的sk_buff,然后将sk_buff递交给下层,各层在sk_buff中添加不同的协议头直至交给网络设备发送。同样地,当网络设备从网络媒介上接收到数据包后,它必须将接收到的数据转换为sk_buff数据结构并传递给上层,各层剥去相应的协议头直至交给用户。

套接字缓冲区结构是linux内核网络子系统的核心内容。

hard_start_transmit将一个套接字缓存中数据放入外发队列

每个数据包属于更高网络层某个套接晏子,所有套接字输入和输出缓冲区都是sk_buff结构形成链表。

struct sk_buff的重要结构成员

-struct net_device *dev,缓冲区设备

-union{……} h;

-union{……} nh;

-union{……} mac;

指向数据包中各个层的数据包头。h指向传输层包头,nh指向网络层包头,mac指向链路层包头。

sk_buff_data_t transport_header;

sk_buff_data_t network_header;

sk_buff_data_t mac_header;

/* These elements must be at the end, see alloc_skb() for details. */

sk_buff_data_t tail;

sk_buff_data_t end;

unsigned char *head;

unsigned char *data;

用来寻址数据包中的数据指针。head指向已分配空间开头,data指向有效的octet开头.tail指向有效octel队尾。end指向tail可以到达的最大地址

unsigned long len;

unsigned char ip_summed;描述该数据包的校验和策略

unsigned char pkt_type;描述该数据包的类型

可取值:PACKET_HOST, PACKET_BROADCAST, PACKET_MULTICAST, PACKET_OTHERHOST

相关操作

分配sk_buff结构

struct sk_buff *alloc_skb(unsigned int len,gfp_t priority);

struct sk_buff *dev_alloc_skb(unsigned int len);

dev_alloc_skb()函数以GFP_ATOMIC优先级进行skb分配

释放

void kfree_skb(struct sk_buff *skb);

void dev_kfree_skb(struct sk_buff *skb);

void dev_kfree_skb_irq(struct sk_buff *skb);

void dev_kfree_skb_any(struct sk_buff *skb);

Linux内核使用kfree_skb(),dev_kfree_skb()函数用于非中断上下文,dev_kfree_skb_irq(),用于中断上下文。dev_kfree_skb_any()中断与非中断皆可用

变更

linux内核中用如下函数在缓冲区中尾部增加数据

unsigned char *skb_put(struct sk_buff *skb,insigned int len);

它会导致skb->tail后移len,skb->len 增加len;

linux内核中用如下函数在缓冲区总部增加数据

unsigned char *skb_push(struct sk_buff *skb,unsigned int len);

skb->data前移len,skb->len增加len;

unsigned char *skb_pull(struct sk_buff *skb,unsigned int len);

skb->data后移len,skb->len减小len;

static inline void skb_reserve(struct sk_buff *skb,int len);

skb->data和skb->len同时后移len;

n 网络设备接口层

net_device结构体在内核中指代一个网络设备。网络设备驱动程序只需通过填充net_device的具体成员并注册net_device即可实现硬件操作函数与内核的挂接。

ether_setup方法是用来填充设备net_device结构

net_device结构体

全局信息

char name[IFNAMESIZ];网络设备名称

硬件信息

unsigned long mem_end; /* shared mem end */

unsigned long mem_start; /* shared mem start */

unsigned long base_addr; /* device I/O address */

unsigned int irq; /* device IRQ number */

unsigned char if_port; /* Selectable AUI, TP,..*/

unsigned char dma; /* DMA channel */

接口信息

unsigned int flags; /* interface flags (a la BSD) */

flags网络接口标志,部分值由内核管理。可取的值

IFF_UP,当设备被激活并可以开始发送数据包时,内核设置该标志

IFF_AUTOMEDIA,设备可在多种媒介间切换

IFF_BROADCAST,允许广播

IFF_DEBUG,用于控制printk调用的详细程度

IFF_LOOPBACK,回环

IFF_MULTICAST,允许组播

IFF_NOARP,接口不能执行ARP

IFF_POINTOPOINT,接口连接到点到点链路

unsigned mtu; /* interface MTU value */

unsigned short type; /* interface hardware type */

unsigned short hard_header_len; /* hardware hdr length */

unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast

because most packets are unicast) */

unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */

dev_addr和broadcast分别用于存放硬件地址和广播地址。对于以太网而言,这两个地址长度都为6个字节。以太网广播地址为6个0xff,而MAC地址需由驱动程序从硬件读出填充到dev_addr中。

设备操作函数

int (*open)(struct net_device *dev);

int (*stop)(struct net_device *dev);

void (*tx_timeout) (struct net_device *dev);

int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);

struct net_device_stats*(*get_stats)(struct net_device *dev);

此函数用于获得网络设备的状态信息

int (*do_ioctl)(struct net_device *dev,struct ifreq *ifr,int cmd);

用于进行特定的I/O控制

int (*set_config)(struct net_device *dev,struct ifmap *map);

用于配置接口,可用于改变设备的I/O地址和中断号。

int (*set_mac_address)(struct net_device *dev,void *addr);

用于设置设备的mac地址。

const struct ethtool_ops *ethool_ops;

上述结构体中的一系列成员用于更改或报告网络设备的设置。

辅助成员

unsigned long trans_start;

记录数据包开始发送时的时间戳

unsigned long last_rx;

记录最后一次收到数据包的时间戳

void *priv

priv设备的私有信息指针。驱动程序应该通过netdev_priv()函数获得指针。

n 设备驱动功能层

这一部分是一个网络设备开发者的主要工作,主要是实现具体的net_device中的操作函数及一些成员的赋值

n 网络设备与媒介层

网络设备与媒介直接对应于塑壳的硬件设备。一般是对一些具体寄存器的读写。在具体的驱动程序中,可能直接和设备驱动功能层的程序混在一块儿。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: