zt:tcpdump抓包對性能的影響

 https://blog.csdn.net/dog250/article/details/52502623

一直以來,提到這個話題,你們更多的關注的是tcpdump抓包自己的性能,好比能不能應付幾十萬的pps,可否在萬兆網絡上自運自如...咱們如今知道,這些問題的答案都是否認的,即「不能」!所以你應該去關注netmap高性能抓包方案以及DPDK這樣的東西...linux

        但本文不談這些,本文談的是被抓取數據包之外的東西,即tcpdump對那些未被命中抓包規則的數據包性能的影響。程序員

接口和實現算法

不得不說,有的時候一些教誨是錯的。好比說關注接口而不關注實現。信奉此信條的,不知踩了多少坑。對於tcpdump而言,你可能只須要關注tcpdump能夠抓包就行了,而沒必要去關注tcpdump是怎麼抓包的。事實上,對於tcpdump是怎麼抓包的細節,我敢確定大多數人,包括一些老資格的高級工程師都是不知道的,大多數狀況下,不少人只是知道某個接口能夠完成某件事情,對於完成該事情的能力上限卻沒有任何認知。編程

        在編程中咱們也常常遇到這種事,好比Java中有HashMap,大多數人根本無論這個HashMap是怎麼實現的,只知道它是一個高效的查詢容器,Set了一個Value後,即可以經過其Key在任意時間Get出來,悲哀的是,即使在性能攸關的場景中,不少人還會無條件調用該接口,而後就出現了一個必須加班到深夜才能夠排除的故障。咱們知道,性能攸關的場景要求你對每個步驟都瞭如指掌,這就站在了「關注接口而不是關注實現」的反面!網絡

        然而,有人說「關注接口而不是關注實現」就必定正確嗎?沒有!這只是在軟件工程某個領域的某個細節上是正確的,能夠快速開發和迭代,對於訓練熟練工是好的,可是對於像我這樣的人,那顯然是不夠的。這也是我沒有掌握也沒興趣掌握各類「框架」的本質緣由吧。架構

        我來講一下我遇到過的事情。併發

        2011年,我遇到一個性能問題,最終的瓶頸是nf_conntrack,過濾的項目太多了,可是拋開這個具體場景不說,若是你的iptables規則設置太多了,也會影響性能,這須要你對iptables的執行機制有充分的理解。app

        2013年,再次遇到一個性能問題,CPU,eth0網卡滿載的狀況下,pps急劇降低,後來發現是eth1網卡瘋了致使,不斷的up/down,致使路由表不斷更新,我說這個eth1狀態更新有問題,然而別的程序員卻並不買帳,eth1怎麼可能影響eth0呢?想一想也是哦...後來「只關注接口」的程序員試圖默默重現該問題,寫了一個腳本不斷up/down這個eth1,而後觀察eth0的變化,結果沒有重現,我後來之處了問題所在:在模擬重現的過程當中,大家的路由項加的太少了,加入10萬條路由試試!問題的關鍵不在eth1的up/down,而是其up/down致使的路由表更新的鎖操做。排查該問題,須要你對路由查找的算法,路由表更新的鎖操做有充分的理解,只瞭解路由表的增刪改查接口以及網卡的up/down接口是沒有用的。框架

        近日,我被要求在10萬級pps(來自百萬級的IP地址)不衰減的狀況,同步執行tcpdump抓取特定數據包。預研階段我認爲瓶頸可能會在BPF Filter,由於幾年前我曾經研究過它的執行細節,按照線性過濾的執行規則,這明顯是一個O(n)算法,且還要受到CPU Cache抖動的影響....高速網絡中任意的O(n)操做都會指數級拉低性能!因而我考慮採用HiPAC多維樹匹配代替BPF,最終因爲耗時久,動做場面大討論沒經過而做罷。本着數聽說話的原則,仍是花了兩天時間來驗證tcpdump一會兒過濾幾千個IP地址是否是真的影響性能,結果是,和料想的同樣,真的影響性能。socket

感官的印象

我不想經過iperf,netperf,hping3之類的玩意兒來驗證,由於這些都是基於socket的,萬一在數據發送端遇到協議棧的瓶頸,就很悲哀,所以,我試圖經過一種繞開發送端協議棧的發包方案,這樣顯然能夠節省幾乎一半的排查工做量。感謝有pktgen!

        如下是發包腳本:

modprobe pktgen

echo rem_device_all >/proc/net/pktgen/kpktgend_0

echo max_before_softirq 1 >/proc/net/pktgen/kpktgend_0

echo clone_skb 1000 >/proc/net/pktgen/lo

echo add_device eth2 >/proc/net/pktgen/kpktgend_0

echo clone_skb 1000 >/proc/net/pktgen/eth2

echo pkt_size 550 >/proc/net/pktgen/eth2

echo src_mac 00:0C:29:B0:CE:CF >/proc/net/pktgen/eth2

echo flag IPSRC_RND >/proc/net/pktgen/eth2

echo src_min 10.0.0.2 >/proc/net/pktgen/eth2

echo src_max 10.0.0.255 >/proc/net/pktgen/eth2

echo dst 1.1.1.1 >/proc/net/pktgen/eth2

echo dst_mac  00:0C:29:A9:F3:DD >/proc/net/pktgen/eth2

echo count 0 >/proc/net/pktgen/eth2

echo pkt_size 100 >/proc/net/pktgen/eth2

echo start >/proc/net/pktgen/pgctrl 

以上腳本運行在機器A上,在與其直連的機器B上用sysstat來觀察:

sar -n DEV 1

而後在機器B上執行下面的腳本:

# 此例子中,我僅僅是啓2個tcpdump,每個過濾600個IP地址,而已!循環參數能夠任意調。

i=0

j=0

k=0

 

for ((k=1;k<2;k++)); do

        src='tcpdump -i any src '

 

        for ((i=1;i<30;i++)); do

                for ((j=20;j<50;j++)); do

                        temp=$src" 192.$k.$i.$j or src"

                        src=$temp

                done

        done

 

        src=$src" 192.168.11.11 -n"

 

 

        echo $src

        $src &

done

而後,sar的輸出結果變化了嗎?什麼緣由致使的呢?

 

PS:固然上面的pktgen發包方式是我默默作的,在實際中,我仍是要使用程序員承認的東西,好比iperf,netperf,hping3之類低效的東西。我並不否定iperf,netperf,hping是好東西,我只是以爲它們在這個測試場景中大材小用了。

 

tcpdump抓包的架構

上一節的測試我但願看到此文的人本身去測試,這樣感官印象更深入些,否則太多的結果貼圖,不免有湊篇幅之嫌了。

        本節,我給出目前tcpdump底層pcap的抓包原理,以下圖所示:

 

 

 

 

 

 

這是標準的libpcap/tcpdump的結構,一個串行的,同步的抓包結構,固然,也許你已經接觸過DPDK,netmap等,這些固然比libpcap/tcpdump更加優秀,可是面臨的問題是開發週期太長,以netmap爲例,若是你想用它最高效的模式,那就要犧牲對傳統協議棧的兼容,反之,若是你想不patch驅動,不編譯內核就能用,那你獲得的也僅僅是一個兼容PACKET套接字的libpcap/tcpdump的兼容方案。

 

        另外,上述流程圖中的不少細節我並無敘述,好比緩衝區的組織形式,是使用copy仍是mmap等等,可是這並不阻礙咱們對其的理解,在微秒,甚至毫秒級的BPF開銷下,內存操做開銷真的不算什麼了。

        總之,和以前遇到的iptables,路由表等問題同樣,抓包也是一個有其能力極限的機制,它是好東西,但不要期望它在哪裏都能幫你的忙-若是不是幫倒忙的話!

        咱們來看一下高性能網絡上的一些數據包分析的方案。好比在匯聚層,甚至核心層,我要是想對數據包進行審計,該怎麼辦?用tcpdump嗎?....能夠這麼說,這個層次上,同步的抓包幾乎是不可能的,通常都是使用端口鏡像的方式,而後在另外一臺機器上去處理,這臺專門處理數據包審計的機器通常都是衆核機器,超多的CPU,超高的並行併發處理能力,固然,這是須要花錢的,這也是一種負責人的作法,另一種不負責任的作法是什麼呢?是相似tcpdump的作法,徹底串行同步處理,這樣會慢,但慢不是問題,問題是必定不能漏,這種思惟實際上是錯誤的,特別是在基於統計的互聯網絡上,任何事情都不精確,任何事情都不絕對。

        在網絡上,80%就是所有!

--------------------- 

做者:dog250 

來源:CSDN 

原文:https://blog.csdn.net/dog250/article/details/52502623 

版權聲明:本文爲博主原創文章,轉載請附上博文連接!

 

------------------------------

tcpdump丟包分析

 

https://blog.csdn.net/blade2001/article/details/41543297

 

tcpdump丟包分析




  經過tcpdump抓包時,結束後tcpdump會給出以下統計信息:
  1552 packets captured
  1586 packets received by filter
  34 packets dropped by kernel
  
  其中「captured」的計數指的是應用層捕獲到的數據,「received by filter」和「dropped by kernel」的計數由內核維護,應用層經過getsockopt來獲取。收到一個包,「received by filter」會加1,若是sock的接收buffer被填滿時,則把這個數據包丟棄,將「dropped by kernel」加1。
  if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= (unsigned)sk->sk_rcvbuf){
   spin_lock(&sk->sk_receive_queue.lock);
   po->stats.tp_drops++;
   spin_unlock(&sk->sk_receive_queue.lock);
  }
  經過調節/proc/sys/net/core/rmem_default和/proc/sys/net/core/rmem_max可以改變sk_rcvbuf的大小。
  
  正常「captured」加上「dropped by kernel」應該等於「received by filter」的大小,有的時候出現不等的狀況應該是還有一些數據包在sk_rcvbuf中,尚未被應用層收到的緣由。


丟包緣由:
通過google以及分析,形成這種丟包的緣由是因爲libcap抓到包後,tcpdump上層沒有及時的取出,致使libcap緩衝區溢出,從而覆蓋了未處理包,此處即顯示爲dropped by kernel,注意,這裏的kernel並非說是被linux內核拋棄的,而是被tcpdump的內核,即libcap拋棄掉的


 解決方法:
 根據以上分析,能夠經過改善tcpdump上層的處理效率來減小丟包率,下面的幾步根據須要選用,每一步都能減小必定的丟包率
 1. 最小化抓取過濾範圍,即經過指定網卡,端口,包流向,包大小減小包數量
 2. 添加-n參數,禁止反向域名解析
 3. 添加-B參數,加大OS capture buffer size
 4. 指定-s參數, 最好小於1000
 5. 將數據包輸出到cap文件
 6. 用sysctl修改SO_REVBUF參數,增長libcap緩衝區長度:/proc/sys/net/core/rmem_default和/proc/sys/net/core/rmem_ma
 
-B buffer_size
Set the operating system capture buffer size to buffer_size, in units of KiB (1024 bytes).
-n
Don't convert addresses (i.e., host addresses, port numbers, etc.) to names.
-s snaplen
--snapshot-length=snaplen
Snarf snaplen bytes of data from each packet rather than the default of 65535 bytes. Packets truncated because of a limited snapshot are indicated in the output with ``[|proto]'', where proto is the name of the protocol level at which the truncation has occurred. Note that taking larger snapshots both increases the amount of time it takes to process packets and, effectively, decreases the amount of packet buffering. This may cause packets to be lost. You should limit snaplen to the smallest number that will capture the protocol information you're interested in. Setting snaplen to 0 sets it to the default of 65535, for backwards compatibility with recent older versions of tcpdump.


 
http://blog.tianya.cn/blogger/post_read.asp?BlogID=227219&PostID=16646525
http://blog.csdn.net/cszhouwei/article/details/17798271

https://blog.csdn.net/dog250/article/details/52502623

相關文章
相關標籤/搜索