Linux内核分析 - 网络[十一]:ICMP模块
ip_append_data()函 数比较复杂,这里以两个例子来解释这个函数:发送50 Byte的echo报文,发送600 Byte的echo报文。56字节echo报文在IP层不 需要分片;600字节echo报文在IP层需要分片。ip_append_data()还可以多次调用来收集数据,而在ICMP模块中这点并不能体现 出来,在以后UDP或TCP时再以解释多次调用的情况。 example 1:50 Byte echo报文 [假设MTU=520] 如果 sk_write_queue为空,则证明是第一个分片,50字节的报文只需要一个分片。这里会设置exthdrlen,表示链路层额外的报头长 ,一般情况下是0,所以此时length和transhdrlen值仍是传入的值。而sk->sk_sndmsg_page和sk->sk_sndmsg_off与发散/ 聚合IO有关,这里先不考虑。 if (skb_queue_empty(&sk->sk_write_queue)) { …. sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; if ((exthdrlen = rt->u.dst.header_len) != 0) { length += exthdrlen; transhdrlen += exthdrlen; } … } 设置各种参数的值,hh_len表示以太网报头的长度,16字节对齐;fragheaderlen表示分片报头长度,即IP报头; maxfraglen表示最大分片长度。各参数值:hh_len = 16, fragheaderlen = 20, maxfraglen = 516,注意要求的节字对齐。 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; 此时sk- >sk_write_queue还为空,跳转至alloc_new_skb执行分配新的skb。 if ((skb = skb_peek_tail(&sk- >sk_write_queue)) == NULL) goto alloc_new_skb; fraggap在上一个skb没有8字节对齐时设置为多余的字节数,否则的话fraggap=0;datalen表示 IP报文长度(不包括IP报头),fraglen表示以太网帧报文长度(不包括以太网头),alloclen表示要分配的内容长度,下面代码省 略了一些内容。各参数值: fraggap=0, datalen=50, fraglen=70, alloclen=70。 fraggap = 0; datalen = length + fraggap; fraglen = datalen + fragheaderlen; alloclen = datalen + fragheaderlen; 分配报文skb空间,大小为alloclen+hh_len+15,alloclen + hh_len就是报文 的长度,15个字节为预留部分。 if (transhdrlen) { skb = sock_alloc_send_skb(sk, alloclen + hh_len + 15, (flags & MSG_DONTWAIT), &err); } (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |