加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[十一]:ICMP模块

发布时间:2016-10-16 06:06:59 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 ICMP模块比较简单,要注意的是icmp的速率限制策略,向IP层传输数据ip_append_data()和 ip_push_pending_frames()。 在net/ipv4/af_inet.c中的inet_init()注册icmp协议,从这里也可以看出,ICMP模块是绑 定在IP模块之上的。inet_

ip_push_pending_frames() 将待发送的报文传递给网络层

待发送的报文分片都在sk->sk_write_queue上,这 里要做的就是从sk_write_queue上取出所有分片,合并成一个报文,添加IP报头信息,使用ip_local_out()传递给网络层处理。

要注意的是这里的合并并不是真正的合并,只有第一个分片形成了skb,剩下的分片都放到了skb_shinfo(skb)- >frag_list上,虽然最后向下传递的只是一个skb,并实际上分片工作已经完成了,网络层并不需要再次分片,由网络的上层 完成分片是出于效率的考虑,虽然与协议标准有所出入。

首先从sk_write_queue上取出第一个分片,skb是最终向下传递的报 文,tail_skb指向skb的frag_list链表尾,即最后一个分片。

if ((skb = __skb_dequeue(&sk-

>sk_write_queue)) == NULL)     
 goto out;     
tail_skb = &(skb_shinfo(skb)->frag_list);

将skb->data指向ip报头的位置

if (skb->data 

< skb_network_header(skb))     
 __skb_pull(skb, skb_network_offset(skb));

tmp_skb表示现在要插入skb的分片,首先通过__skb_pull()除去这些 分片的IP报头,因为分片共用skb的IP报头。然后通过tail_skb处理将tmp_skb链入frag_list中;最后增加报文长度计数,以前 说明过,skb->len代表linear buffer + paged buffer,skb->data_len代表paged_buffer,这里插入的分片是增加了 paged buffer大小,所以对skb->len和skb->data_len都增加分片的长度。

while ((tmp_skb = __skb_dequeue

(&sk->sk_write_queue)) != NULL) {     
 __skb_pull(tmp_skb, skb_network_header_len(skb));     
 *tail_skb = tmp_skb;     
 tail_skb = &(tmp_skb->next);     
 skb->len += tmp_skb->len;     
 skb->data_len += tmp_skb->len;     
 skb->truesize += tmp_skb->truesize;     
 tmp_skb->destructor = NULL;     
 tmp_skb->sk = NULL;     
}

这里是生成skb的IP报头,设置其中的值

iph = (struct iphdr *)skb->data;     
iph->version = 4;     
…….     
skb->mark = sk->sk_mark;

最终通过ip_local_out()传递给IP层

err = ip_local_out(skb);

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读