IT技术互动交流平台

详解Linux系统网络技术之关键数据结构解析(二)

作者:visualfan  发布日期:2012-11-13 09:05:56

sk_buff结构中有一些通用字段,和特定内核功能无关:

ktime_t tstamp:对一个已接收的封包才有意义。这是一个时间戳,表示接收包的时间,或者有时用于表示封包预定的传输时间。这个丢按由netif_rx函数调用net_timestamp_check设置,而这个函数在接收每个包后由设备驱动程序调用。


struct net_device *dev:这个字段描述一个网络设备,由dev代表的设备角色依赖于这个封包是即将发出的数据包还是刚被接收的数据包。即若是即将发出的数据包,这个网络设备代表发送设备,否则就是接收设备。在3c59x系列的网卡驱动程序中。vortex_rx函数代码片段为:


 

有些网络功能允许一些设备按组集合起来代表一个虚拟的接口,有一个虚拟设备驱动程序提供接口服务。当该设备驱动程序被调用时,dev参数会指向此虚拟设备的net_device结构。但该驱动程序会从其组中选择一个特定的物理设备,然后将dev参数指向真实物理设备的net_device结构。因此,这种情况下,在包的处理期间传输设备的指针可能会变化。


sk_buff_data_t transport_header:
sk_buff_data_t network_header:
sk_buff_data_t mac_header:
    这些是指向TCP/IP协议栈的协议报头,其值是偏移地址还是指针取决于系统NET_SKBUFF_DATA_USES_OFFSET是否生效。这些字段分别代表传输层、网络层和链路层的报头位置。当接受一个数据包时,负责处理第n层报头的函数,会从第n-1层接收缓冲区,而该缓冲区的skb->data指向第n层报头的位置,同时将其对应层的指针进行初始化(如,网络层会将network_header字段指向网络层报头位置),因为当下一层进行处理时,skb->data会被设置指向其对应层报头的位置。


 

unsigned long _skb_refdst:这个字段由路由子系统使用。


char cb[48]:这是一个控制缓冲区(control buffer),也就是每层的私有存储空间。48个字节足以容纳每层所需的私有数据。在每一层都是通过宏进行访问的。如在tcp.h中,TCP使用这个空间来存储一个tcp_skb_cb数据结构:


struct tcp_skb_cb {
    union {
        struct inet_skb_parm    h4;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
        struct inet6_skb_parm    h6;
#endif
    } header;    /* For incoming frames        */
    __u32        seq;        /* Starting sequence number    */
    __u32        end_seq;    /* SEQ + FIN + SYN + datalen    */
    __u32        when;        /* used to compute rtt's    */
    __u8        flags;        /* TCP header flags.        */
    __u8        sacked;        /* State flags for SACK/FACK.    */
#define TCPCB_SACKED_ACKED    0x01    /* SKB ACK'd by a SACK block    */
#define TCPCB_SACKED_RETRANS    0x02    /* SKB retransmitted        */
#define TCPCB_LOST        0x04    /* SKB is lost            */
#define TCPCB_TAGBITS        0x07    /* All tag bits            */

#define TCPCB_EVER_RETRANS    0x80    /* Ever retransmitted frame    */
#define TCPCB_RETRANS        (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)

    __u32        ack_seq;    /* Sequence number ACK'd    */
};

#define TCP_SKB_CB(__skb)    ((struct tcp_skb_cb *)&((__skb)->cb[0]))

在TCP子系统的net/ipv4/tcp_ipv4.c文件中,tcp_v4_rcv函数对这个结构进行了填充:

 

th = tcp_hdr(skb);
iph = ip_hdr(skb);
     
TCP_SKB_CB(skb)->seq = ntohl(th->seq);
TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                 skb->len - th->doff * 4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
TCP_SKB_CB(skb)->when     = 0;
TCP_SKB_CB(skb)->flags     = iph->tos;
TCP_SKB_CB(skb)->sacked     = 0;

union {
  __wsum  csum;
  struct {
   __u16 csum_start;
   __u16 csum_offset;
  };
 };
__u8 ip_summed:2
这两个字段表示校验和(checksum)以及相关联的状态标志


__u8 cloned:1 这个字段置位,表示该结构是另一个sk_buff缓冲区的克隆


__u8 pkt_type:3 这个字段根据报文IP层的目的地址进行设置。可能的取值在include/linux/if_packet.h中。对于Ethernet设备而言,这个参数由eth_type_trans函数进行设置。
#define PACKET_HOST  0    到本机  /* To us  */
#define PACKET_BROADCAST 1    广播包 /* To all  */
#define PACKET_MULTICAST 2    本机是该接口已注册的多播地址之一 /* To group  */
#define PACKET_OTHERHOST 3     到其他主机,若本机转发功能被启用,将转发该包,否则丢弃 /* To someone else  */
#define PACKET_OUTGOING  4     这个数据包正在被发送 /* Outgoing of any type */
/* These ones are invisible by user level */
#define PACKET_LOOPBACK  5     传送给回环设备,由于此标志,当处理回环设备时,内核可以跳过一些真实设备所需的操作 /* MC/BRD frame looped back */
#define PACKET_FASTROUTE     6     由Fastroute功能路由封包。2.6内核不再支持Fastroute /* Fastrouted frame */


__u32 priority:这个字段表示正在被传输或转发的数据包QoS服务质量的等级。若包邮本地产生,将由套接字层定义优先级的值。若包在被转发将由ip_forward函数调用rt_tos2priority根据IP报头本身的ToS服务类型字段的值进行定义。 www.it165.net
skb->priority = rt_tos2priority(iph->tos);


__be16 protocol:从链路层来看,就是在下一个较高层使用的协议,如IP、IPv6和ARP等。每种协议都有自己的函数处理例程来处理输入数据包,因此驱动程序使用这个字段来通知上层该使用的处理例程。每个驱动程序都会调用netif_rx来启动上面的网络分层处理例程,所以在该函数调用之前protocol字段必须被初始化。


功能字段
Linux内核是模块化的,所以当内核编译时选择了某些功能,某些字段才会包含在sk_buff数据结构中:


__u8 nfctinfo:3
__u8 nf_trace:1
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 struct nf_conntrack *nfct;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info *nf_bridge;
#endif
这些参数都是Netfilter架构使用的,关于连接跟踪信息等


#ifdef CONFIG_XFRM
 struct sec_path *sp;
#endif
这个由IPsec协议组使用,以记录转换信息。


#ifdef CONFIG_NET_SCHED
 __u16   tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
 __u16   tc_verd; /* traffic control verdict */
#endif
#endif
这两个字段由流量控制功能使用


 
Tag标签: Linux系统   网络技术   关键数据结构  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规