2008年7月24日星期四

学习kernel网络体系结构(2)

尽管,看过了,但是还是不能深刻的记忆和理解,我感觉只有一步一步的实践了之后,你才会正真的理解其中的奥秘。我再次,重新看。Linux网络实现的灵活性和高效性的一个主要因素是缓冲体系结构,它管理了网络报文——所谓的套接字缓存(socket buffer) ,skb。
一个套接字缓存由俩部分组成:报文数据和管理数据。

看了这个图,我们将分析他们中的一些具体的参数。
我们要明白其中的指针指向的位置。

其实,内容很多,我们还是简单的了解一些,而后多读源代码,现在把一些代码粘贴,看看,那些和图里面是如何对应的。
自 2.6.22 版的核心開始,sk_buff 結構變更

struct sk_buff_head {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
__u32 qlen;
spinlock_t lock;
};
但是,下面的和以前一些版本有些变化。
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;
};
struct sec_path *sp;

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;
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
__u16 queue_mapping;
#endif
#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
/* 14 bit hole */

#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;

#endif

__u32 mark;

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,
*data;
unsigned int truesize;
atomic_t users;
};
套接字缓存是用来定位和管理一个报文在内核中被处理的整个周期的。
以上的代码都是在include/linux/skbuff.h 里面,有空在好好的看看其他的。
struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用。
这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变。 L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部。添加头部比在不同层之间拷贝数据的效率更高。由于在缓冲区的头部 添加数据意味着要修改指向缓冲区的指针,这是个复杂的操作,所以内核提供了一个函数skb_reserve来完成这个功能。协议栈中的每一层在往下一层传 递缓冲区前,第一件事就是调用skb_reserve在缓冲区的头部给协议头预留一定的空间。
skb_reserve同样被设备驱动使用来对齐接收到包的包头。如果缓冲区向上层协议传递,旧的协议层的头部信息就没什么用了。例如,L2的头部只有在 网络驱动处理L2的协议时有用,L3是不会关心它的信息的。但是,内核并没有把L2的头部从缓冲区中删除,而是把有效荷载的指针指向L3的头部,这样做, 可以节省CPU时间。
http://hi.baidu.com/zkheartboy/blog/item/2dd5207a28eb2fee2f73b355.html不错哦!
Linux内核为我们提供了很多函数来操作套接字缓存,如:1.创建,释放和复制套接字缓存 2.操作sk_buff结构里的参数和指针 3.管理套接字缓存队列
而这些函数一般在net/core/skbuff.c 和include/linux/skbuff.h函数中。

time