TCP协议发送SKB时ip_summed初始值为0
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                TCP协议发送SKB时ip_summed初始值为0
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
                                轉(zhuǎn)摘至http://www.2cto.com/kf/201301/183563.html?fw_key=B782188880BAA902
tcp_send_ack()函數(shù)是內(nèi)核用來發(fā)送ACK的函數(shù),該函數(shù)比較簡(jiǎn)單,就是先分配一個(gè)SKB包,然后簡(jiǎn)單的初始化(初始化操作中沒有設(shè)置ip_summed)后,調(diào)用tcp_transmit_skb()來將SKB包傳遞到IP層。tcp_transmit_skb中先做一些操作后(仔細(xì)看過,到計(jì)算校驗(yàn)和之前,沒有更改過ip_summed),會(huì)調(diào)用tcp_v4_send_check(語(yǔ)句是:icsk->icsk_af_ops->send_check(sk, skb->len, skb);)來計(jì)算校驗(yàn)和。
tcp_v4_send_check代碼如下: [cpp] ? /* This routine computes an IPv4 TCP checksum. */ ? void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) ? { ? struct inet_sock *inet = inet_sk(sk); ? struct tcphdr *th = tcp_hdr(skb); ? if (skb->ip_summed == CHECKSUM_PARTIAL) { ? th->check = ~tcp_v4_check(len, inet->saddr, ? inet->daddr, 0); ? skb->csum_start = skb_transport_header(skb) - skb->head; ? skb->csum_offset = offsetof(struct tcphdr, check); ? } else { ? th->check = tcp_v4_check(len, inet->saddr, inet->daddr, ? csum_partial(th, ? th->doff << 2, ? skb->csum)); ? } ? } ? 在這個(gè)函數(shù)中可以看到第7行中已經(jīng)開始使用skb->ip_summed來做比較,那也就是說skb->ip_summed肯定在之前已經(jīng)初始化過,反反復(fù)復(fù)地仔細(xì)閱讀tcp_send_ack和tcp_transmit_skb函數(shù)都沒有發(fā)現(xiàn)初始化的地方,真的是很奇怪。因?yàn)橹拔铱催^alloc_skb的實(shí)現(xiàn),而且又看了一次,沒看到在哪個(gè)地方“明顯地”初始化了ip_summed成員。 只能全文搜索ip_summed的所有設(shè)置的地方,看了半天還是沒有找到在tcp_send_ack到tcp_transmit_skb之間的地方有初始化ip_summed的操作,最后還是把目光鎖定在alloc_skb函數(shù)上。看了幾遍之后突然看到一句不起眼的代碼: [cpp] ? /*? * Only clear those fields we need to clear, not those that we will? * actually initialise below. Hence, don't put any more fields after? * the tail pointer in struct ? */ ? ? ? memset(skb, 0, offsetof(struct sk_buff, tail)); ? skb->truesize = size + sizeof(struct sk_buff); ? atomic_set(&skb->users, 1); ? 看到第6行代碼,才恍然大悟, 原來是在這個(gè)地方把skb從head成員到tail的所有成員都初始化為0,當(dāng)前ip_summed也在這個(gè)范圍內(nèi),也就是說ip_summed的值為0,對(duì)應(yīng)的就是CHECKSUM_NONE。 哎,只怪自己粗心大意,看的不夠仔細(xì)! tcp_v4_send_check中第7行if (skb->ip_summed == CHECKSUM_PARTIAL),判斷ip_summed是否等于CHECKSUM_PARTIAL,那在什么是否會(huì)將ip_summed置為CHECKSUM_PARTIAL呢?這個(gè)答案要在tcp_sendmsg中找,代碼片段如下: [cpp] ? /*? * Check whether we can use HW checksum.? */ ? if (sk->sk_route_caps & NETIF_F_ALL_CSUM) ? skb->ip_summed = CHECKSUM_PARTIAL; ? 也就是說如果目的路由網(wǎng)絡(luò)設(shè)備的特性支持NETIF_F_ALL_CSUM時(shí),才將ip_summed設(shè)置為CHECKSUM_PARTIAL。 當(dāng)然這里的討論只限于TCP協(xié)議發(fā)送SKB包,到計(jì)算校驗(yàn)和的過程中ip_summed成員的變化和值。總結(jié)
以上是生活随笔為你收集整理的TCP协议发送SKB时ip_summed初始值为0的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 读书笔记:《锻炼》
 - 下一篇: 添加VBA控件按钮及操作提示框