內核參數學習(一)

最近經常接觸到以下這2個參數,特此記錄下來:


conntrack_max:(最大跟蹤連接條目)理解爲內核內存中netfilter可以處理的"任務"

hashsize:存儲跟蹤連接條目的哈希表的大小


通常是8個跟蹤條目存於一個哈希表中,所以hashsize=conntrack_max/8


以下爲轉載內容:轉自http://blog.csdn.net/eroswang/article/details/3593515

英文原版爲http://www.360doc.com/content/12/1128/11/1073512_250716423.shtml


要訪問一個特定包的跟蹤連接條目,內核必須:
-針對一個包中的已經定義的一些字符計算哈西值。這是一個不間斷的計算。
  這個哈西值就會被當作哈西表的索引來使用,而跟蹤連接條目的列表就存儲在這裏。
-反覆的查看鏈接列表中的跟蹤連接條目以找到匹配的那一個。
  這是一個耗資源的操作,依賴於列表的大小(也依賴於列表中被操作的跟蹤連接條目的位置)


CONNTRACK_MAX和HASHSIZE的默認值
============================================

一般來說,CONNTRACK_MAX和HASHSIZE都會設置在“合理”使用的值上,依據可使用的RAM的大小來計算這個值。

CONNTRACK_MAX的默認值
------------------------------

在i386架構上,CONNTRACK_MAX = RAMSIZE (以bytes記) / 16384 =
RAMSIZE (以MegaBytes記) * 64,
因此,一個32位的帶512M內存的PC在默認情況下能夠處理512*1024^2/16384 = 512*64 = 32768個併發的netfilter連接。

但是真正的公式是:
CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32)
這裏x是指針的bit數,(例如,32或者64bit)

請注意:
-默認的CONNTRACK_MAX值不會低於128
-對於帶有超過1G內存的系統,CONNTRACK_MAX的默認值會被限制在65536(但是可以手工設置成更大的值)

HASHSIZE的默認值
-------------------------

通常,CONNTRACK_MAX = HASHSIZE * 8。這意味着每個鏈接的列表平均包含8個conntrack的條目(在優化的情況並且CONNTRACK_MAX達到的情況下),每個鏈接的列表就是一個哈西表條目(一個桶)。

在i386架構上,HASHSIZE = CONNTRACK_MAX / 8 =
RAMSIZE (以bytes記) / 131072 = RAMSIZE (以MegaBytes記) * 8。
舉例來說,一個32位、帶512M內存的PC可以存儲512*1024^2/128/1024 =
512*8 = 4096 個桶(鏈接表)

但是真正的公式是:
HASHSIZE = CONNTRACK_MAX / 8 = RAMSIZE (以bytes記) / 131072 / (x / 32)
這裏x是指針的bit數,(例如,32或者64bit)

請注意:
-默認HASHSIZE的值不會小於16
-對於帶有超過1G內存的系統,HASHSIZE的默認值會被限制在8192(但是可以手工設置成更大的值)

讀取CONNTRACK_MAX和HASHSIZE
==================================

現在通過/proc文件系統我們可以在運行時讀取CONNTRACK_MAX的值。

在Linux kernel 2.4.23版本前,使用:
# cat /proc/sys/net/ipv4/ip_conntrack_max

在Linux kernel 2.4.23版本後,使用:
# cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max
  (舊的 /proc/sys/net/ipv4/ip_conntrack_max是不建議使用的!)

當前的HASHSIZE總是可以在syslog信息中找到(對任何一個內核版本),桶(也就是HASHSIZE)的數目是在ip_conntrack初始化的時候顯示出來的。
對於linux內核2.4.24以後,當前的HASHSIZE值可以在運行時使用下面的命令讀取:
# cat /proc/sys/net/ipv4/netfilter/ip_conntrack_buckets


修改CONNTRACK_MAX和HASHSIZE
====================================

默認的CONNTRACK_MAX和HASHSIZE的值都會因主機的不同而不同,但你可以在只做防火牆的高負載的系統上增加他們。
因此CONNTRACK_MAX和HASHSIZE值如果需要的話可以手工更改。

讀取桶是一個連續性的操作(我們的興趣在於得到一個哈西列表),請記得內核需要不停的遍歷一個鏈接的列表去查找一個跟蹤連接條目。因此一個鏈接列表(CONNTRACK_MAX/HASHSIZE的值在優化的狀態下並且達到上限)的平均值不能設置太大。這個比值默認值是8(當值是自動計算的時候)。
在系統有足夠的內存並且性能真的很重要的時候,你可以試着使平均值是一個跟蹤連接條目配一個哈西桶,這意味着HASHSIZE = CONNTRACK_MAX。


設置CONNTRACK_MAX
---------------------

跟蹤連接的條目是存儲在鏈接的表中的,因此最大的跟蹤鏈接條目(CONNTRACK_MAX)可以很容易的動態調整。

linux內核2.4.23之前,使用:
# echo $CONNTRACK_MAX >; /proc/sys/net/ipv4/ip_conntrack_max

linux內核2.4.23之後,使用:
# echo $CONNTRACK_MAX >; /proc/sys/net/ipv4/netfilter/ip_conntrack_max

這裏$CONNTRACK_MAX是一個整數。

設置HASHSIZE
----------------

因爲數學上的原因,哈西表佔有固定的大小。因此HASHSIZE必須在哈西表被創建和開始填充之前就確定。

在linux內核2.4.21之前,必須使用素數作爲哈西表的大小,而且要保證這個哈西表能夠有效並通用。非素數的奇數或者其他的數值都是強烈不推薦使用的,因爲這樣哈西的分配不能達到最優化的狀態。

從linux內核2.4.21(還有2.6內核)跟蹤連接使用jenkins2b算法,這樣就可以使用所有的數值,但是使用2^n次方運作的最有效。


如果netfilter的跟蹤連接是被編譯進內核中的,哈西表的大小就可以在編譯的時候設置,或者(2.6內核之後)可以作爲一個啓動選項ip_conntrack.hashsize=$HASHSIZE。

如果netfilter的跟蹤連接是編譯成一個模塊,哈西表的大小可以在加載模塊的時候設置,使用下面的命令:
# modprobe ip_conntrack hashsize=$HASHSIZE

這裏$HASHSIZE是一個整數。

一個理想的例子:只做防火牆的機器
------------------------------------

在理想的例子中,你有一臺機器只做包過濾和NAT(也就是說,基本上沒有用戶空間的使用,至少不會有象代理這樣會不斷的耗費內存空間的東西......)

netfilter跟蹤連接使用的內核內存大小是:
size_of_mem_used_by_conntrack (以bytes記) =
        CONNTRACK_MAX * sizeof(struct ip_conntrack) +
        HASHSIZE * sizeof(struct list_head)
-這裏:sizeof(struct ip_conntrack)可以有很大的區別,依賴於機器的體系架構,內核版本和編譯時間的配置。要想知道它的大小,可以查看ip_conntrack初始化時候kenel的日誌信息。sizeof(struct ip_conntrack)在i386架構、2.6.5內核上大約是300bytes,但是在2.6.10的內核上,這個值可以在352至192bytes之間變化!
-sizeof(struct list_head) = 2 * size_of_a_pointer
  在i386上,size_of_a_pointer是4bytes。


因此在i386,2.6.5內核上,size_of_mem_used_by_conntrack大約是CONNTRACK_MAX * 300 + HASHSIZE * 8 (bytes)。

如果我們使HASHSIZE = CONNTRACK_MAX(如果我們將大部分的內存用來做防火牆的工作,參見“修改CONNTRACK_MAX和HASHSIZE”部分),在i386架構、2.6.5內核上,size_of_mem_used_by_conntrack大概是CONNTRACK_MAX * 308 bytes。

現在我們假定你使用512M的內存拿來做一個只做防火牆的機器,並且使用128MB以外的內存來做跟蹤連接,對於使用終端模式只做防火牆來說應該是足夠的大的,例如:
你可以同時設置CONNTRACK_MAX和HASHSIZE大致如下:
(512 - 128 ) * 1024^2 / 308 =~ 1307315 (instead of 32768 for CONNTRACK_MAX,
and 4096 for HASHSIZE by default)。
對於linux2.4.21(和linux2.6),哈西算法最好使用“2的次方”大小(之前是使用素數)。

因此在這裏我們可以將CONNTRACK_MAX和HASHSIZE設置成1048576(2^20)。


這樣,你可以存儲默認值32倍的跟蹤連接條目,而且可以得到更好的跟蹤連接性能。


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