Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1371740
  • 博文数量: 284
  • 博客积分: 3251
  • 博客等级: 中校
  • 技术积分: 3046
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-26 17:23
文章分类

全部博文(284)

文章存档

2019年(2)

2018年(5)

2015年(19)

2014年(13)

2013年(10)

2012年(235)

分类: LINUX

2012-12-21 16:25:07

    结构体struct sk_buff中共有三个联合体,分别是h, nh和mac,它们都是一些指针,指向协议栈各层协议的首部。从含有的首部类型来看,nh是h的子集,而mac是nh的子集。《Linux设备驱动程序》 第三版第522页这样介绍这三个联合体:h中包含有传输层的报文头,nh中包含有网络层的报文头,而mac中包含的是链路层的报文头。
    光靠这样的一个解释可能过于抽象,让我们来看一个UDP数据报是怎么样穿过数千公里长的网线来到我们的网卡,通过网卡的驱动程序层层向上来到协议栈的上层的。
    当网卡驱动程序收到一个UDP数据报后,它创建一个结构体struct sk_buff,确保data成员指向的空间足够存放收到的数据(对于数据报分片的情况,因为比较复杂,我们暂时忽略,我们假设一次收到的是一个完整的 UDP数据报)。把收到的数据全部拷贝到data指向的空间,然后,把skb->mac.raw指向data,此时,数据报的开始位置是一个以太网 头,所以skb->mac.raw指向链路层的以太网头。然后通过调用skb_pull剥掉以太网头,所谓剥掉以太网头,只是把data加上 sizeof(struct ethhdr),同时len减去这个值,这样,在逻辑上,skb已经不包含以太网头了,但通过skb->mac.raw还能找到它。这就是我们通常 所说的,IP数据报被收到后,在链路层被剥去以太网头。
    在继续往上层的过程中,一直到我们的my_inet域的函数myip_local_deliver_finish中,我们通过 __skb_pull剥去IP首部,同样,我们可以通过skb->nh.raw找到它。最后,skb->h.raw指向data,即udp首 部,udp首部其实到最后都没有被剥去,应用程序在调用recv接收数据时,直接从skb->data+sizeof(struc udphdr)的位置开始拷贝。   
    我们可以看到,从网卡驱动开始,通过协议栈层层往上传送数据报时,通过增加skb->data的值,来逐步剥离协议首部,但通过h,nh,mac这三个联合指针,我们可以访问到这些协议首部,从而利用其提供的有效信息。
    但必须指出的是,《Linux设备驱动程序》中的解释并不完全准确,mac中包含链路层报文头,这是毫无疑问的,nh中包含义网络层的报文头,也没有问 题,因为ARP协议也属于网络层协议,nh中包含IP首部或者ARP首部。当我们接收到一个icmp数据报时,在 myip_local_deliver_finish中剥去IP首部后,skb->h.raw指向的是icmp首部,但icmp显然不是传输层协 议,它是网络层的一个附属协议。igmp也是相同的情况,我想这也是为什么sk_buff的三个联合体不命名为th, nh, mac的原因,因为th(transprot header)不能准确反映它的内容。
    正确的理解应该是三个联合体是按TCP/IP数据报的协议首部的排列顺序来制定的。排在最前面的是以太网头,包含在mac中,第二是网络层协议首部,包括IP和ARP,包含在nh中,第三包括传输层协议头(TCP, UDP)、ICMP, IGMP。
    另外,再选择两个重要的数据成员作个简短介绍。
    pkt_type,数据报的类型。这个值在网卡驱动程序中由函数eth_type_trans通过判断目的以太网地址来确定。如果目的地址是 FF:FF:FF:FF:FF:FF,则为广播地址,pkt_type=PACKET_BROADCAST,如果最高位为1,则为组播地 址,pkt_type=PACKET_MULTICAST,如果目的mac地址跟本机mac地址不相等,则不是发给本机的数据 报,pkt_type=PACKET_OTHERHOST,否则就是缺省值PACKET_HOST。
    protocol, 它的值是以太网首部的第三个成员,即帧类型,对于IP数据来讲,就是ETH_P_IP(0x8000),对ARP数据报来讲,就是ETH_P_ARP(0x8086)。
    sk_buff还有一组操作函数,在理解sk_buff本身的基础上,理解这些函数并不困难,这里不再作分析。关于套接字缓冲区的分析就到这里结束。
阅读(848) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~