歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux系統禁止路由cache

Linux系統禁止路由cache

日期:2017/2/28 14:46:39   编辑:Linux教程

Linux kernel 3.6正式去除了路由cache,原因正如作者所說,它並不適合作為路由表的一部分存在,它是和流量patterns高度相關的,應該作為一種優化在外部實現,比如基於Asic硬卡的轉發表中實現,況且,現有的路由cache在大多數情況下並不會帶來顯著的性能提升,如果你頻繁flush cache後帶來了性能下降的話,其中很多因素是flush操作本身以及lookup的read lock造成的。然而如果你使用的是低於3.6版本的內核,你將不得不面對路由cache,既然它給不了你太多的好處,那麼如果它反而給你帶來了壞處,你對它的態度就不僅僅是詛咒了!

面臨的一個路由cache帶來的危害

路由cache和基於mark的policy routing之間的不配合造成了產品的一個bug,讓我連續幾日陷入了煩惱!我們知道,mark目前只能靠Netfilter的鉤子來在標記,而PREROUTING處的標記在ROUTING之前,在Linux中,不管是iptables rule還是一條policy routing item,都是配置後立即生效的,兩個操作不能合並為一個單獨的原子操作,這就造成了問題:
1.現在需要一條rule為packet做mark,一條policy routing item基於該mark做路由,於是就有兩條Linux命令;
2.執行上述兩條命令前,有感興趣數據包持續通過BOX,造成了路由cache;
3.先執行了mark rule,此時在policy routing item還未執行時進來一個感興趣packet匹配到了mark,然而沒有匹配到policy routing;
4.如果你的policy routing table配置的是fall though,問題就來了,lookup進入main table,配置到原始的路由,被cache住;
5.如果一直有持續的感興趣流,那麼上述的mark-policy routing將永遠不會生效。
可能你會說,將mark rule和policy routing item的設置順序互換一下即可,然而即使那樣,如果你的實現是有狀態的,你還要面臨另外一個cache,即conntrack cache的問題。可能你還會說,fall though換成default unreachable去掉即可,但是那樣就會和實現的語義有很大的差別。因此禁用路由cache勢在必行!

如何禁用路由cache

又是一段艱難的旅程!/proc/sys/net/ipv4/route/下面的參數調了個遍也沒有成功,route -C -n還是顯示出了一大堆惡心的亂七八糟的東西。於是還是google以及看代碼,發現了以下的參數:
rt_cache_rebuild_count - INTEGER
The per net-namespace route cache emergency rebuild threshold.
Any net-namespace having its route cache rebuilt due to
a hash bucket chain being too long more than this many times
will have its route caching disabled
作為確認,在route.c中的IP的input/output中,查找cache之前有一個判斷:

if (!rt_caching(net))
goto skip_cache;

這樣就跳過了cache查找,而rt_caching的實現超級簡單:

static inline bool rt_caching(const struct net *net)
{
return net->ipv4.current_rt_cache_rebuild_count <=
net->ipv4.sysctl_rt_cache_rebuild_count;
}

加之sysctl_rt_cache_rebuild_count是int型的,只要保證上述函數永遠返回0即可,於是將sysctl_rt_cache_rebuild_count設置為-1,成功禁用了路由cache!

總結

不要天真地認為什麼cache都會提高效率,在Linux路由cache的例子中,查找路由表是hash/trie查表,查找cache也是一個hash表,另外如果你的路由表只有一條默認路由,cache項的數量要遠遠大於路由表項的數量,此時cache僅僅就是直接使用了dst_entry,而不用從result裡面把路由表項的字段摳出來設置進新申請的dst_entry中,浪費的查表時間得到這個一點收益...其實,只要路由表中有前綴小於32位的路由表項,都有可能出現上述情況,因此在cache查找機制和路由表查找機制沒有本質區別的情況下,路由cache並沒有達到預期的效果!相反,路由cache應該在PREROUTING的時候做,而不是到ROUTING的時候再做,在PREROUTING中,可以方便地使用Netfilter將cache實現在硬卡中。

在確定行為的情況下,cache會提高效率,在行為模式不固定的情況下,cache的作用就是浪費資源,擾亂視聽!老師罰你把“豬血”連續寫10遍,此時你就可以連續寫10個“豬”,再連續寫10個“血”,肯定比連續寫10個“豬血”要快一些,然而如果你是一位同聲傳譯員或者一位速記員,你千萬別把剛剛聽到的記在腦子裡...

Copyright © Linux教程網 All Rights Reserved