婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Linux實現ARP緩存老化時間原理問題深入解析

Linux實現ARP緩存老化時間原理問題深入解析

熱門標簽:佛山外呼系統平臺 成都移動外呼系統 南昌語音外呼系統代理 南寧智能外呼系統線路商 聯客智能語音外呼系統賬號格式 長春外呼系統價格 電銷機器人的效果 美圖手機 長沙智能外呼系統中心
一.問題
眾所周知,ARP是一個鏈路層的地址解析協議,它以IP地址為鍵值,查詢保有該IP地址主機的MAC地址。協議的詳情就不詳述了,你可以看RFC,也可以看教科書。這里寫這么一篇文章,主要是為了做一點記錄,同時也為同學們提供一點思路。具體呢,我遇到過兩個問題:
1.使用keepalived進行熱備份的系統需要一個虛擬的IP地址,然而該虛擬IP地址到底屬于哪臺機器是根據熱備群的主備來決定的,因此主機器在獲得該虛擬IP的時候,必須要廣播一個免費的arp,起初人們認為這沒有必要,理由是不這么做,熱備群也工作的很好,然而事實證明,這是必須的;
2.ARP緩存表項都有一個老化時間,然而在linux系統中卻沒有給出具體如何來設置這個老化時間。那么到底怎么設置這個老化時間呢?

二.解答問題前的說明
ARP協議的規范只是闡述了地址解析的細節,然而并沒有規定協議棧的實現如何去維護ARP緩存。ARP緩存需要有一個到期時間,這是必要的,因為ARP緩存并不維護映射的狀態,也不進行認證,因此協議本身不能保證這種映射永遠都是正確的,它只能保證該映射在得到arp應答之后的一定時間內是有效的。這也給了ARP欺騙以可乘之機,不過本文不討論這種欺騙。
像Cisco或者基于VRP的華為設備都有明確的配置來配置arp緩存的到期時間,然而Linux系統中卻沒有這樣的配置,起碼可以說沒有這樣的直接配置。Linux用戶都知道如果需要配置什么系統行為,那么使用sysctl工具配置procfs下的sys接口是一個方法,然而當我們google了好久,終于發現關于ARP的配置處在/proc/sys/net/ipv4/neigh/ethX的時候,我們最終又迷茫于該目錄下的N多文件,即使去查詢Linux內核的Documents也不能清晰的明了這些文件的具體含義。對于Linux這樣的成熟系統,一定有辦法來配置ARP緩存的到期時間,但是具體到操作上,到底怎么配置呢?這還得從Linux實現的ARP狀態機說起。
如果你看過《Understading Linux Networking Internals》并且真的做到深入理解的話,那么本文講的基本就是廢話,但是很多人是沒有看過那本書的,因此本文的內容還是有一定價值的。
Linux協議棧實現為ARP緩存維護了一個狀態機,在理解具體的行為之前,先看一下下面的圖(該圖基于《Understading Linux Networking Internals》里面的圖26-13修改,在第二十六章):

在上圖中,我們看到只有arp緩存項的reachable狀態對于外發包是可用的,對于stale狀態的arp緩存項而言,它實際上是不可用的。如果此時有人要發包,那么需要進行重新解析,對于常規的理解,重新解析意味著要重新發送arp請求,然后事實上卻不一定這樣,因為Linux為arp增加了一個“事件點”來“不用發送arp請求”而對arp協議生成的緩存維護的優化措施,事實上,這種措施十分有效。這就是arp的“確認”機制,也就是說,如果說從一個鄰居主動發來一個數據包到本機,那么就可以確認該包的“上一跳”這個鄰居是有效的,然而為何只有到達本機的包才能確認“上一跳”這個鄰居的有效性呢?因為Linux并不想為IP層的處理增加負擔,也即不想改變IP層的原始語義。
Linux維護一個stale狀態其實就是為了保留一個neighbour結構體,在其狀態改變時只是個別字段得到修改或者填充。如果按照簡單的實現,只保存一個reachable狀態即可,其到期則刪除arp緩存表項。Linux的做法只是做了很多的優化,但是如果你為這些優化而絞盡腦汁,那就悲劇了...

三.Linux如何來維護這個stale狀態
在Linux實現的ARP狀態機中,最復雜的就是stale狀態了,在此狀態中的arp緩存表項面臨著生死抉擇,抉擇者就是本地發出的包,如果本地發出的包使用了這個stale狀態的arp緩存表項,那么就將狀態機推進到delay狀態,如果在“垃圾收集”定時器到期后還沒有人使用該鄰居,那么就有可能刪除這個表項了,到底刪除嗎?這樣看看有木有其它路徑使用它,關鍵是看路由緩存,路由緩存雖然是一個第三層的概念,然而卻保留了該路由的下一條的ARP緩存表項,這個意義上,Linux的路由緩存實則一個轉發表而不是一個路由表。
如果有外發包使用了這個表項,那么該表項的ARP狀態機將進入delay狀態,在delay狀態中,只要有“本地”確認的到來(本地接收包的上一跳來自該鄰居),linux還是不會發送ARP請求的,但是如果一直都沒有本地確認,那么Linux就將發送真正的ARP請求了,進入probe狀態。因此可以看到,從stale狀態開始,所有的狀態只是為一種優化措施而存在的,stale狀態的ARP緩存表項就是一個緩存的緩存,如果Linux只是將過期的reachable狀態的arp緩存表項刪除,語義是一樣的,但是實現看起來以及理解起來會簡單得多!
再次強調,reachable過期進入stale狀態而不是直接刪除,是為了保留neighbour結構體,優化內存以及CPU利用,實際上進入stale狀態的arp緩存表項時不可用的,要想使其可用,要么在delay狀態定時器到期前本地給予了確認,比如tcp收到了一個包,要么delay狀態到期進入probe狀態后arp請求得到了回應。否則還是會被刪除。

四.Linux的ARP緩存實現要點
在blog中分析源碼是兒時的記憶了,現在不再浪費版面了。只要知道Linux在實現arp時維護的幾個定時器的要點即可。
1.Reachable狀態定時器
每當有arp回應到達或者其它能證明該ARP表項表示的鄰居真的可達時,啟動該定時器。到期時根據配置的時間將對應的ARP緩存表項轉換到下一個狀態。
2.垃圾回收定時器
定時啟動該定時器,具體下一次什么到期,是根據配置的base_reachable_time來決定的,具體見下面的代碼:

復制代碼
代碼如下:

static void neigh_periodic_timer(unsigned long arg)
{
...
if (time_after(now, tbl->last_rand + 300 * HZ)) { //內核每5分鐘重新進行一次配置
struct neigh_parms *p;
tbl->last_rand = now;
for (p = tbl->parms; p; p = p->next)
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
}
...
/* Cycle through all hash buckets every base_reachable_time/2 ticks.
* ARP entry timeouts range from 1/2 base_reachable_time to 3/2
* base_reachable_time.
*/
expire = tbl->parms.base_reachable_time >> 1;
expire /= (tbl->hash_mask + 1);
if (!expire)
expire = 1;
//下次何時到期完全基于base_reachable_time);
mod_timer(tbl->gc_timer, now + expire);
...
}
static void neigh_periodic_timer(unsigned long arg)
{
...
if (time_after(now, tbl->last_rand + 300 * HZ)) { //內核每5分鐘重新進行一次配置
struct neigh_parms *p;
tbl->last_rand = now;
for (p = tbl->parms; p; p = p->next)
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
}
...
/* Cycle through all hash buckets every base_reachable_time/2 ticks.
* ARP entry timeouts range from 1/2 base_reachable_time to 3/2
* base_reachable_time.
*/
expire = tbl->parms.base_reachable_time >> 1;
expire /= (tbl->hash_mask + 1);
if (!expire)
expire = 1;
//下次何時到期完全基于base_reachable_time);
mod_timer(tbl->gc_timer, now + expire);
...
}

一旦這個定時器到期,將執行neigh_periodic_timer回調函數,里面有以下的邏輯,也即上面的...省略的部分:

復制代碼
代碼如下:

if (atomic_read(n->refcnt) == 1 //n->used可能會因為“本地確認”機制而向前推進
(state == NUD_FAILED ||time_after(now, n->used + n->parms->gc_staletime))) {
*np = n->next;
n->dead = 1;
write_unlock(n->lock);
neigh_release(n);
continue;
}
if (atomic_read(n->refcnt) == 1 //n->used可能會因為“本地確認”機制而向前推進
(state == NUD_FAILED ||time_after(now, n->used + n->parms->gc_staletime))) {
*np = n->next;
n->dead = 1;
write_unlock(n->lock);
neigh_release(n);
continue;
}

如果在實驗中,你的處于stale狀態的表項沒有被及時刪除,那么試著執行一下下面的命令:
[plain] view plaincopyprint?ip route flush cache
ip route flush cache然后再看看ip neigh ls all的結果,注意,不要指望馬上會被刪除,因為此時垃圾回收定時器還沒有到期呢...但是我敢保證,不長的時間之后,該緩存表項將被刪除。

五.第一個問題的解決
在啟用keepalived進行基于vrrp熱備份的群組上,很多同學認為根本不需要在進入master狀態時重新綁定自己的MAC地址和虛擬IP地址,然而這是根本錯誤的,如果說沒有出現什么問題,那也是僥幸,因為各個路由器上默認配置的arp超時時間一般很短,然而我們不能依賴這種配置。請看下面的圖示:

如果發生了切換,假設路由器上的arp緩存超時時間為1小時,那么在將近一小時內,單向數據將無法通信(假設群組中的主機不會發送數據通過路由器,排出“本地確認”,畢竟我不知道路由器是不是在運行Linux),路由器上的數據將持續不斷的法往原來的master,然而原始的matser已經不再持有虛擬IP地址。
因此,為了使得數據行為不再依賴路由器的配置,必須在vrrp協議下切換到master時手動綁定虛擬IP地址和自己的MAC地址,在Linux上使用方便的arping則是:
[plain] view plaincopyprint?arping -i ethX -S 1.1.1.1 -B -c 1
arping -i ethX -S 1.1.1.1 -B -c 1這樣一來,獲得1.1.1.1這個IP地址的master主機將IP地址為255.255.255.255的ARP請求廣播到全網,假設路由器運行Linux,則路由器接收到該ARP請求后將根據來源IP地址更新其本地的ARP緩存表項(如果有的話),然而問題是,該表項更新的結果狀態卻是stale,這只是ARP的規定,具體在代碼中體現是這樣的,在arp_process函數的最后:

復制代碼
代碼如下:

if (arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST)
state = NUD_STALE;
neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0);
if (arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST)
state = NUD_STALE;
neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0);

由此可見,只有實際的外發包的下一跳是1.1.1.1時,才會通過“本地確認”機制或者實際發送ARP請求的方式將對應的MAC地址映射reachable狀態。
更正:在看了keepalived的源碼之后,發現這個擔心是多余的,畢竟keepalived已經很成熟了,不應該犯“如此低級的錯誤”,keepalived在某主機切換到master之后,會主動發送免費arp,在keepalived中有代碼如是:

復制代碼
代碼如下:

vrrp_send_update(vrrp_rt * vrrp, ip_address * ipaddress, int idx)
{
char *msg;
char addr_str[41];
if (!IP_IS6(ipaddress)) {
msg = "gratuitous ARPs";
inet_ntop(AF_INET, ipaddress->u.sin.sin_addr, addr_str, 41);
send_gratuitous_arp(ipaddress);
} else {
msg = "Unsolicited Neighbour Adverts";
inet_ntop(AF_INET6, ipaddress->u.sin6_addr, addr_str, 41);
ndisc_send_unsolicited_na(ipaddress);
}
if (0 == idx debug 32) {
log_message(LOG_INFO, "VRRP_Instance(%s) Sending %s on %s for %s",
vrrp->iname, msg, IF_NAME(ipaddress->ifp), addr_str);
}
}
vrrp_send_update(vrrp_rt * vrrp, ip_address * ipaddress, int idx)
{
char *msg;
char addr_str[41];
if (!IP_IS6(ipaddress)) {
msg = "gratuitous ARPs";
inet_ntop(AF_INET, ipaddress->u.sin.sin_addr, addr_str, 41);
send_gratuitous_arp(ipaddress);
} else {
msg = "Unsolicited Neighbour Adverts";
inet_ntop(AF_INET6, ipaddress->u.sin6_addr, addr_str, 41);
ndisc_send_unsolicited_na(ipaddress);
}
if (0 == idx debug 32) {
log_message(LOG_INFO, "VRRP_Instance(%s) Sending %s on %s for %s",
vrrp->iname, msg, IF_NAME(ipaddress->ifp), addr_str);
}
}

六.第二個問題的解決
扯了這么多,在Linux上到底怎么設置ARP緩存的老化時間呢?
我們看到/proc/sys/net/ipv4/neigh/ethX目錄下面有多個文件,到底哪個是ARP緩存的老化時間呢?實際上,直接點說,就是base_reachable_time這個文件。其它的都只是優化行為的措施。比如gc_stale_time這個文件記錄的是“ARP緩存表項的緩存”的存活時間,該時間只是一個緩存的緩存的存活時間,在該時間內,如果需要用到該鄰居,那么直接使用表項記錄的數據作為ARP請求的內容即可,或者得到“本地確認”后直接將其置為reachable狀態,而不用再通過路由查找,ARP查找,ARP鄰居創建,ARP鄰居解析這種慢速的方式。
默認情況下,reachable狀態的超時時間是30秒,超過30秒,ARP緩存表項將改為stale狀態,此時,你可以認為該表項已經老化到期了,只是Linux的實現中并沒有將其刪除罷了,再過了gc_stale_time時間,表項才被刪除。在ARP緩存表項成為非reachable之后,垃圾回收器負責執行“再過了gc_stale_time時間,表項才被刪除”這件事,這個定時器的下次到期時間是根據base_reachable_time計算出來的,具體就是在neigh_periodic_timer中:

復制代碼
代碼如下:

if (time_after(now, tbl->last_rand + 300 * HZ)) {
struct neigh_parms *p;
tbl->last_rand = now;
for (p = tbl->parms; p; p = p->next)
//隨計化很重要,防止“共振行為”引發的ARP解析風暴
p->reachable_time = neigh_rand_reach_time(p->base_reachable_time);
}
...
expire = tbl->parms.base_reachable_time >> 1;
expire /= (tbl->hash_mask + 1);
if (!expire)
expire = 1;
mod_timer(tbl->gc_timer, now + expire);
if (time_after(now, tbl->last_rand + 300 * HZ)) {
struct neigh_parms *p;
tbl->last_rand = now;
for (p = tbl->parms; p; p = p->next)
//隨計化很重要,防止“共振行為”引發的ARP解析風暴
p->reachable_time = neigh_rand_reach_time(p->base_reachable_time);
}
...
expire = tbl->parms.base_reachable_time >> 1;
expire /= (tbl->hash_mask + 1);
if (!expire)
expire = 1;
mod_timer(tbl->gc_timer, now + expire);

可見一斑啊!適當地,我們可以通過看代碼注釋來理解這一點,好心人都會寫上注釋的。為了實驗的條理清晰,我們設計以下兩個場景:
1.使用iptables禁止一切本地接收,從而屏蔽arp本地確認,使用sysctl將base_reachable_time設置為5秒,將gc_stale_time為5秒。
2.關閉iptables的禁止策略,使用TCP下載外部網絡一個超大文件或者進行持續短連接,使用sysctl將base_reachable_time設置為5秒,將gc_stale_time為5秒。
在兩個場景下都使用ping命令來ping本地局域網的默認網關,然后迅速Ctrl-C掉這個ping,用ip neigh show all可以看到默認網關的arp表項,然而在場景1下,大約5秒之內,arp表項將變為stale之后不再改變,再ping的話,表項先變為delay再變為probe,然后為reachable,5秒之內再次成為stale,而在場景2下,arp表項持續為reachable以及dealy,這說明了Linux中的ARP狀態機。那么為何場景1中,當表項成為stale之后很久都不會被刪除呢?其實這是因為還有路由緩存項在使用它,此時你刪除路由緩存之后,arp表項很快被刪除。

七.總結
1.在Linux上如果你想設置你的ARP緩存老化時間,那么執行sysctl -w net.ipv4.neigh.ethX=Y即可,如果設置別的,只是影響了性能,在Linux中,ARP緩存老化以其變為stale狀態為準,而不是以其表項被刪除為準,stale狀態只是對緩存又進行了緩存;
2.永遠記住,在將一個IP地址更換到另一臺本網段設備時,盡可能快地廣播免費ARP,在Linux上可以使用arping來玩小技巧。

標簽:云浮 沈陽 新鄉 邵陽 東營 法律服務 慶陽 阜陽

巨人網絡通訊聲明:本文標題《Linux實現ARP緩存老化時間原理問題深入解析》,本文關鍵詞  Linux,實現,ARP,緩存,老化,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Linux實現ARP緩存老化時間原理問題深入解析》相關的同類信息!
  • 本頁收集關于Linux實現ARP緩存老化時間原理問題深入解析的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产精品色呦呦| 亚洲欧洲日韩女同| 性感美女极品91精品| 欧美群妇大交群中文字幕| 亚洲综合免费观看高清完整版| 丁香一区二区三区| 亚洲欧美国产毛片在线| 欧美精品电影在线播放| 国产一区二区三区日韩| 国产清纯美女被跳蛋高潮一区二区久久w| 成人av综合在线| 一区二区高清在线| 欧美电影免费观看高清完整版 | 日韩美女啊v在线免费观看| 99久久精品99国产精品| 一区二区三区.www| wwwwxxxxx欧美| 91网站在线播放| 久久国产免费看| 亚洲欧美偷拍另类a∨色屁股| 欧美日韩在线三区| 国产乱码字幕精品高清av| 一区二区三区鲁丝不卡| 日韩欧美一区二区久久婷婷| 成人美女视频在线观看18| 一区二区三区在线免费播放| 精品国产精品网麻豆系列| 成人精品免费网站| 日韩精品色哟哟| 欧美一级生活片| 欧美视频精品在线| 美女免费视频一区| 欧美午夜精品久久久久久孕妇| 日本aⅴ亚洲精品中文乱码| 亚洲电影激情视频网站| 国产视频一区在线观看| 99久久精品国产网站| 自拍偷在线精品自拍偷无码专区| 欧美一区二区大片| 成人亚洲精品久久久久软件| 婷婷中文字幕一区三区| 久久影音资源网| 91免费版在线| 国产成人丝袜美腿| 亚洲 欧美综合在线网络| 久久蜜桃av一区二区天堂| 欧美色手机在线观看| 国产一区二区三区在线观看精品| 亚洲欧美日韩中文播放| 久久久影院官网| 91豆麻精品91久久久久久| 亚洲国产成人va在线观看天堂| 久久久久久久性| 欧美日韩高清一区二区三区| 天天色综合天天| 中文av一区二区| 91精品国产日韩91久久久久久| 日本久久一区二区| 国产精品一级二级三级| 欧美刺激脚交jootjob| 欧美性感一类影片在线播放| 国产精品一二一区| 琪琪一区二区三区| 婷婷夜色潮精品综合在线| 亚洲视频小说图片| 国产亚洲综合色| 久久午夜色播影院免费高清| 欧美精品在线观看一区二区| 国产一区二区三区国产| 丝袜亚洲另类欧美综合| 亚洲视频一二三区| 亚洲精品成人a在线观看| 国产亚洲综合在线| 亚洲精品一线二线三线| 国产亚洲成年网址在线观看| 日韩免费看的电影| 久久在线观看免费| 久久网站最新地址| 日韩欧美在线影院| 精品国产露脸精彩对白 | 国产精品77777| 青草国产精品久久久久久| 亚洲精品国产无天堂网2021| 一区二区三区在线免费播放| 久久久久国产一区二区三区四区 | 欧美日韩高清不卡| 国产在线播放一区三区四| 国产精品久久777777| 69p69国产精品| 精品国产免费一区二区三区香蕉| 琪琪久久久久日韩精品| 亚洲在线观看免费| 亚洲激情欧美激情| 中文字幕一区三区| 日韩一区二区免费电影| 欧美一区三区二区| 7777精品久久久大香线蕉| 日韩欧美一二三| 日韩欧美国产一区在线观看| 欧美一区二区三区白人| 久久一区二区三区四区| 不卡av电影在线播放| 国产成人精品综合在线观看 | 91麻豆精品国产91久久久久| 欧美日韩精品一区二区三区四区| 成人中文字幕电影| 在线日韩av片| 欧美日韩视频专区在线播放| 日韩免费视频一区| 久久久精品欧美丰满| 中文av一区特黄| 日韩不卡一二三区| 另类综合日韩欧美亚洲| 久久久亚洲高清| 中文字幕欧美国产| 中文字幕一区二区三区在线观看| 另类调教123区| 91浏览器入口在线观看| 日本精品免费观看高清观看| 欧美性猛交xxxx乱大交退制版| 欧美日韩在线三级| 日韩欧美国产麻豆| 亚洲欧美另类小说视频| 亚洲一区二区三区在线| 亚洲精品网站在线观看| 婷婷六月综合亚洲| 国产91精品一区二区麻豆亚洲| 91福利资源站| 欧美大片一区二区三区| 91麻豆精品国产91久久久久| 国产欧美视频在线观看| 亚洲欧美色图小说| 国产老肥熟一区二区三区| www.av亚洲| 欧美美女网站色| 国产精品嫩草影院com| 亚洲高清视频中文字幕| 视频一区二区三区中文字幕| 99在线精品免费| 日韩视频中午一区| 亚洲成人激情社区| 99re66热这里只有精品3直播 | 亚洲精品视频在线看| 国产一区亚洲一区| 色94色欧美sute亚洲线路一久| 欧美丝袜丝交足nylons| 综合激情成人伊人| 久久99精品国产麻豆婷婷 | 国产在线观看免费一区| 色域天天综合网| 91亚洲国产成人精品一区二三| 欧美日韩国产综合一区二区三区| 久久这里只有精品6| 亚洲精品国产一区二区精华液| 青草国产精品久久久久久| 不卡视频在线观看| 久久精品网站免费观看| 亚洲狠狠爱一区二区三区| 91美女在线视频| 日韩一二三区不卡| 一区二区在线看| 97精品久久久午夜一区二区三区| 日韩欧美电影一二三| 日本在线不卡一区| 在线免费观看日韩欧美| 日本一区二区在线不卡| 成人小视频在线| 中文字幕 久热精品 视频在线 | 亚洲人123区| 国产成a人亚洲精| 日韩亚洲欧美在线观看| 日韩成人午夜电影| 色综合咪咪久久| 欧美国产精品v| 国产成人亚洲综合a∨婷婷| 欧美精品亚洲一区二区在线播放| 亚洲一二三四久久| eeuss鲁片一区二区三区在线观看| 欧美做爰猛烈大尺度电影无法无天| 国产婷婷一区二区| 国产一区不卡精品| 国产午夜精品福利| 国产尤物一区二区| 中文字幕免费一区| 国产成人午夜精品影院观看视频| 国产拍揄自揄精品视频麻豆| 韩国一区二区三区| 亚洲精品一区二区精华| 国产成人在线色| 国产欧美日韩久久| 色婷婷香蕉在线一区二区| 国产精品大尺度| 91同城在线观看| 亚洲欧美偷拍另类a∨色屁股| 成人精品视频.| 亚洲一区二区三区四区五区中文| 欧美三级蜜桃2在线观看| 日本在线不卡一区| 在线观看成人免费视频| 丝袜a∨在线一区二区三区不卡|