程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> TCP協議發送SKB時ip_summed成員的設置

TCP協議發送SKB時ip_summed成員的設置

編輯:C++入門知識

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]   /* 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));       }   }   在這個函數中可以看到第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]   /*       * 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行代碼,才恍然大悟,原來是在這個地方把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]   /*                   * Check whether we can use HW checksum.                   */                   if (sk->sk_route_caps & NETIF_F_ALL_CSUM)                       skb->ip_summed = CHECKSUM_PARTIAL;     也就是說如果目的路由網絡設備的特性支持NETIF_F_ALL_CSUM時,才將ip_summed設置為CHECKSUM_PARTIAL。 當然這裡的討論只限於TCP協議發送SKB包,到計算校驗和的過程中ip_summed成員的變化和值。  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved