歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux實現的ARP緩存老化時間原理解析

Linux實現的ARP緩存老化時間原理解析

日期:2017/2/28 15:56:51   编辑:Linux教程

一.問題

眾所周知,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狀態而不是直接刪除,www.linuxidc.com 是為了保留neighbour結構體,優化內存以及CPU利用,實際上進入stale狀態的arp緩存表項時不可用的,要想使其可用,要麼在delay狀態定時器到期前本地給予了確認,比如tcp收到了一個包,要麼delay狀態到期進入probe狀態後arp請求得到了回應。否則還是會被刪除。
Copyright © Linux教程網 All Rights Reserved