TCP协议发送SKB时ip_summed成员的设置 http://blog.csdn.net/justlinux2010/article/details/8508455

 

TCP协议发送SKB时ip_summed成员的设置

分类: Linux内核   1457人阅读  评论(0)  收藏  举报
 tcp_send_ack()函数是内核用来发送ACK的函数,该函数比较简单,就是先分配一个SKB包,然后简单的初始化(初始化操作中没有设置ip_summed)后,调用tcp_transmit_skb()来将SKB包传递到IP层。tcp_transmit_skb中先做一些操作后(仔细看过,到计算校验和之前,没有更改过ip_summed),会调用tcp_v4_send_check(语句是:icsk->icsk_af_ops->send_check(sk, skb->len, skb);)来计算校验和。
 tcp_v4_send_check代码如下:
[cpp]  view plain copy
  1. /* This routine computes an IPv4 TCP checksum. */  
  2. void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)  
  3. {  
  4.     struct inet_sock *inet = inet_sk(sk);  
  5.     struct tcphdr *th = tcp_hdr(skb);  
  6.   
  7.     if (skb->ip_summed == CHECKSUM_PARTIAL) {  
  8.         th->check = ~tcp_v4_check(len, inet->saddr,  
  9.                      inet->daddr, 0);  
  10.         skb->csum_start = skb_transport_header(skb) - skb->head;  
  11.         skb->csum_offset = offsetof(struct tcphdr, check);  
  12.     } else {  
  13.         th->check = tcp_v4_check(len, inet->saddr, inet->daddr,  
  14.                      csum_partial(th,  
  15.                          th->doff << 2,  
  16.                          skb->csum));  
  17.     }  
  18. }  
在这个函数中可以看到第7行中已经开始使用skb->ip_summed来做比较,那也就是说skb->ip_summed肯定在之前已经初始化过,反反复复地仔细阅读tcp_send_ack和tcp_transmit_skb函数都没有发现初始化的地方,真的是很奇怪。因为之前我看过alloc_skb的实现,而且又看了一次,没看到在哪个地方“明显地”初始化了ip_summed成员。
  只能全文搜索ip_summed的所有设置的地方,看了半天还是没有找到在tcp_send_ack到tcp_transmit_skb之间的地方有初始化ip_summed的操作,最后还是把目光锁定在 alloc_skb函数上。看了几遍之后突然看到一句不起眼的代码:
[cpp]  view plain copy
  1. /* 
  2.      * Only clear those fields we need to clear, not those that we will 
  3.      * actually initialise below. Hence, don't put any more fields after 
  4.      * the tail pointer in struct  
  5.      */  
  6.     memset(skb, 0, offsetof(struct sk_buff, tail));  
  7.     skb->truesize = size + sizeof(struct sk_buff);  
  8.     atomic_set(&skb->users, 1);  
看到第6行代码,才恍然大悟,原来是在这个地方把skb从head成员到tail的所有成员都初始化为0,当前ip_summed也在这个范围内,也就是说ip_summed的值为0,对应的就是CHECKSUM_NONE。哎,只怪自己粗心大意,看的不够仔细!

  tcp_v4_send_check中第7行 if   ( skb - > ip_summed  = =  CHECKSUM_PARTIAL ), 判断ip_summed是否等于 CHECKSUM_PARTIAL, 那在什么是否会将ip_summed置为 CHECKSUM_PARTIAL 呢?这个答案要在tcp_sendmsg中找,代码片段如下:
[cpp]  view plain copy
  1. /* 
  2.                  * Check whether we can use HW checksum. 
  3.                  */  
  4.                 if (sk->sk_route_caps & NETIF_F_ALL_CSUM)  
  5.                     skb->ip_summed = CHECKSUM_PARTIAL;  

也就是说如果目的路由网络设备的特性支持NETIF_F_ALL_CSUM时,才将ip_summed设置为 CHECKSUM_PARTIAL。
当然这里的讨论只限于TCP协议发送SKB包,到计算校验和的过程中ip_summed成员的变化和值。


版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值