udp cksum

    目前碰到一個奇怪的現象,某臺機器(就叫hostA吧)上面tx-checksumming是開啓狀態下,所有本地發出去的UDP報文用tcpdump -vvv udp抓出來,凡是從這臺主機發出去的包所有包全部顯示bad udp cksum,收到的UDP包則沒有一個是bad udp cksum的。

    而在另外一臺機器(就叫hostB吧)上面,則沒有一個bad udp cksum的包,抓包不多,1000個左右,對比環境差異:

hostA的ethtool -i信息:

driver: bnx2
version: 1.6.9
firmware-version: 4.0.3 ipms 1.6.0
bus-info: 0000:04:00.0

hostB的ethtool -i信息:

driver: bnx2
version: 1.6.9
firmware-version: 1.9.6
bus-info: 0000:04:00.0

hostA uname -a:

Linux hostA 2.6.18-92.el5xen #1 SMP Tue Apr 29 13:31:30 EDT 2008 x86_64 x86_64 x86_64 GNU/Linux

hostB uname -a:

Linux hostB 2.6.18-92.el5xen #1 SMP Tue Apr 29 13:31:30 EDT 2008 x86_64 x86_64 x86_64 GNU/Linux

hostA and hostB tcpdump --version:

tcpdump version 3.9.4
libpcap version 0.9.4

下面驗證使用的kernel源碼版本爲:2.6.32.60


    物理上兩臺一樣的服務器,tcpdump版本一致,除了網卡固件有所差異外,沒別的區別,按照我的分析,會對udp send包 cksum有所影響的只應該有2個層面,一個是內核,也就是系統調用入sendto生產udp報文的時候udp層面的cksum計算,而另外一個就是網卡來計算cksum,二選一。

   這兩天和雷風討論了下,沒啥結果,現在應該說是昨天下午,和燕飛請教了下,讓我關掉tx-checksumming,他的理解是開啓這個功能相當於用網卡硬件來計算cksum,而關閉則由內核來計算cksum。


    燕飛推薦的《understanding_linux_network_internals》的85頁,引用下該圖:


    可以看到tcpdump 的原理是創建一個PF_PACKET類型套接字,直接插到網絡層和數據鏈路層中間的dev_queue_xmit函數中截取,按照燕飛的說法,開啓了tx-checksumming,內核就不會計算cksum,而是在這個包交給數據鏈路層後再計算cksum,所以tcpdump 的時候,抓回來的包,全是錯誤的cksum,而關閉該功能後,也就是說讓網絡層去做cksum的計算後抓回來的包是沒問題的,在hostA上我驗證與燕飛的猜想一致。

   但是,我在hostB上面,看到checksumming也是開啓的,實時抓取1000+ udp報文是沒有一個cksum錯誤的,這就是我疑惑的地方,難道說在網絡層已經完成了cksum計算?

    假設tcpdump拿到的包都是dev_queue_xmit處理完之後的包。這個以後驗證,以下邏輯建立在此之上:

    看dev_queue_xmit函數(1908~1916行):

    /* If packet is not checksummed and device does not support
     * checksumming for this protocol, complete checksumming here.
     */
    if (skb->ip_summed == CHECKSUM_PARTIAL) {
        skb_set_transport_header(skb, skb->csum_start -
                          skb_headroom(skb));
        if (!dev_can_checksum(dev, skb) && skb_checksum_help(skb))
            goto out_kfree_skb;
    }

    解釋的很清楚,只有當硬件不支持和包還未cksum的時候纔會計算cksum,調用的是skb_checksum_help函數來計算,具體cksum實現在該函數裏。

    如果硬件支持cksum,就不計算cksum直接發出去。

實驗數據:

  tx-checksumming on tx-checksumming off
hostA bad udp cksum normal
hostB normal normal

    顯然這裏面有臺機器是不正常的,個人更傾向於hostB不正常,因爲hostA可以用代碼來解釋爲什麼開啓了tx checksumming抓到的全是錯誤的cksum包。

    而對於hostB,暫時我無法理解該行爲!

    有點晚了,明天開啓tx checksumming 的情況下,驗證一下從hostA發一個UDP報文給hostB,分別在A和B上抓包看下cksum是否變化過。

    接上次的,28號驗證表明,在網卡開啓tx checksumming的情況下,hostA發出UDP報文,在hostA上抓取顯示UDPcksum是錯誤的,而在目標主機上抓取hostA發送的UDP報文,則沒問題,也就是說,開啓tx checksumming的情況下,是網卡來計算了cksum。

    最後一個疑問,目前還無法解釋hostB上的情況,無論起開或者關閉tx checksumming,hostB發生的UDP報文在hostB上抓取,UDP cksum均是沒問題的。



參考資料:

1、其他博主寫的dev_queue_xmit函數分析http://blog.csdn.net/peimichael/article/details/4699609.

2、《understanding_linux_network_internals》一書的第85頁.

3、《TCP/IP詳解卷2: 實現》的UDP部分615頁



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章