Linux网络设备驱动结构概述

欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入

  网络设备驱动相比字符型设备的驱动要复杂一些,除了总体上驱动的框架有一些相似外,有很多地方都是不同,但网络设备驱动有一个很大的特点就是有固定的框架可以遵循,具体的框架会在后边详细的叙述,这里主要分析网络设备驱动的结构,和整个tcp/ip网络结构一样,整个网络设备驱动也是一个分层的结构。具体如下:

  1.网络协议接口层

  在网络协议接口层,只提供了两个抽象函数dev_queue_xmit()与 netif_rx(),之所以称之为抽象函数,是因为这两个函数抽象了很多底层的操作,不管是那个芯片它在网络协议结构的操作函数都是这两个函数,采用这样的抽象后,给上层带来了很多的方便,给上层协议提供统一的数据包收发接口,无论上层是ARP协议还是IP协议,都通过dev_queue_xmit() 函数发送数据,通过netif_rx()函数接收数据。此层使上层协议独立于具体的设备。

  相关数据结构sk_buff:

  sk_buff 称为“套接字缓冲区”,用于在Linux网络子系统中各层之间传递数据。是Linux网络子系统数据传递的“中枢神经”。sk_buff定义位置为:include/linux/skbuff.h,这个数据结构定义了很多用于网络操作的函数,更多的设计整个协议的实现,包括各层报文的头信息,以及报文的帧格式,下边这个这个结构体是有关报文header信息的,下边的代码摘自kernel2.6.29/include/linux /skbuff.h

  struct sk_buff {

  /* These two members must be first. */

  struct sk_buff *next;

  struct sk_buff *prev;

  struct sock *sk;

  ktime_t tstamp;

  struct net_device *dev;

  union {

  struct dst_entry *dst;

  struct rtable *rtable;

  };

  #ifdef CONFIG_XFRM

  struct sec_path *sp;

  #endif

  /*

  * This is the control buffer. It is free to use for every

  * layer. Please put your private variables there. If you

  * want to keep them across layers you have to do a skb_clone()

  * first. This is owned by whoever has the skb queued ATM.

  */

  char cb[48];

  unsigned int len,

  data_len;

  __u16 mac_len,

  hdr_len;

  union {

  __wsum csum;

  struct {

  __u16 csum_start;

  __u16 csum_offset;

  };

  };

  __u32 priority;

  __u8 local_df:1,

  cloned:1,

  ip_summed:2,

  nohdr:1,

  nfctinfo:3;

  __u8 pkt_type:3,

  fclone:2,

  ipvs_property:1,

  peeked:1,

  nf_trace:1;

  __be16 protocol;

  void (*destructor)(struct sk_buff *skb);

  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)

  struct nf_conntrack *nfct;

  struct sk_buff *nfct_reasm;

  #endif

  #ifdef CONFIG_BRIDGE_NETFILTER

  struct nf_bridge_info *nf_bridge;

  #endif

  int iif;

  __u16 queue_mapping;

  #ifdef CONFIG_NET_SCHED

  __u16 tc_index; /* traffic control index */

  #ifdef CONFIG_NET_CLS_ACT

  __u16 tc_verd; /* traffic control verdict */

  #endif

  #endif

  #ifdef CONFIG_IPV6_NDISC_NODETYPE

  __u8 ndisc_nodetype:2;

  #endif

  #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)

  __u8 do_not_encrypt:1;

  __u8 requeue:1;

  #endif

  /* 0/13/14 bit hole */

  #ifdef CONFIG_NET_DMA

  dma_cookie_t dma_cookie;

  #endif

  #ifdef CONFIG_NETWORK_SECMARK

  __u32 secmark;

  #endif

  __u32 mark;

  __u16 vlan_tci;

  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;//下边的tail、end、head、data是与缓冲区相关

  sk_buff_data_t end;

  unsigned char *head,*data;

  unsigned int truesize;

  atomic_t users;

  };

  sk_buff中的数据缓冲区的指针

  Linux必须分配用于容纳数据包的缓冲区,sk_buff中定义了4个指向这片缓冲区的不同位置的指针head、data、tail、end。

  head:指针指向内存中已分配的用于存储网路数据的缓冲区起始地址,sk_buff和相关数据块在分配后,该指针的值就固定了。

  data:指针指向对应当前协议层有效数据的起始地址。每个协议的有效数据含义不同。

  tail:指向对应当前协议层有效数据负载的结尾地址,与data对应。

  end:指向内存分配的数据缓冲区的结尾地址,与head指针对应。和head一样,sk_buff和相关数据块被分配后,end指针也就固定了。

[1][2]

人生最好的旅行,就是你在一个陌生的地方,

Linux网络设备驱动结构概述

相关文章:

你感兴趣的文章:

标签云: