天天看點

鄰居子系統

鄰居子系統

/*
 *  Neighbor Cache Entry States.
 */

#define NUD_INCOMPLETE  0x01 發包時建立條目
#define NUD_REACHABLE   0x02
#define NUD_STALE   0x04 收到ARP請求
#define NUD_DELAY   0x08
#define NUD_PROBE   0x10
#define NUD_FAILED  0x20

/* Dummy states */
#define NUD_NOARP   0x40
#define NUD_PERMANENT   0x80
#define NUD_NONE    0x00
           
net/ipv4/route.c
ipv4_neigh_lookup
    查找路由緩存
    ->__ipv4_neigh_lookup
        ->arp_hashfn
    ->neigh_create(&arp_tbl, pkey, dev)
        ->neigh_alloc
            ->nud_state = NUD_NONE
            ->setup_timer(&n->timer, neigh_timer_handler
        ->tbl->constructor/arp_constructor
        ->dev->netdev_ops->ndo_neigh_construct
        ->n->parms->neigh_setup
        ->neigh_hash_grow
        ->tbl->hash
           
ip_finish_output2
    發包
    ->dst_neigh_output
        ->nud_state & NUD_CONNECTED neigh_hh_output
        ->n->output/neigh_resolve_output
            ->neigh_event_send
                ->__neigh_event_send                
           
__neigh_event_send
    ->NUD_CONNECTED | NUD_DELAY | NUD_PROBE: 傳回,直接使用鄰居發包
    ->NUD_NONE: mcast_probes + neigh->parms->app_probes轉NUD_INCOMPLETE,探測、否則轉FALIED,丢skb
    ->NUD_STALE: 切NUD_DELAY
    ->NUD_INCOMPLETE: __skb_queue_tail(&neigh->arp_queue,緩存封包
    ->neigh_probe
        ->neigh->ops->solicit/arp_solicit
            ->arp_send
           
arp_rcv
    收到arp封包
    ->arp_process
        1. 丢棄目的位址是多點傳播或loopback的arp資料
        2. 對于源ip位址是0的arp請求,一般用于重複位址檢測,此時如果arp類型為request,且目的ip位址是本地位址,且可以進行arp應答時,則調用arp_send發送arp reply資料包
        3. 對于arp類型為request的資料包,且能找到到目的位址tip的路由
           1)如果路由緩存對應的ip位址類型為local,則調用neigh_event_ns,查找符合條件的鄰居項
              ->neigh_event_ns
            ->__neigh_lookup
            ->neigh_update(NUD_STALE, NEIGH_UPDATE_F_OVERRIDE)
                      a)如果找到符合條件的鄰居項,則調用arp_send發送對該arp request包的reply包,并傳回
                      b)直接傳回。
                   2)如果路由緩存對應的ip位址類型不是local,則進行arp proxy的處理,完成後直接傳回
        4. 調用__neigh_lookup,查找arp_tbl的neighbour hash bucket,查找sip對應的鄰居項
           對于非由arp請求的arp reply,且沒有相應的neighbour,則強制建立新的neighbour
        5. 查找到符合條件的neighbour    
           1)對于發給給本機的arp reply封包,則将鄰居項設定為reach狀态
               2)對于發給給本機的arp request封包,則将鄰居項狀态設定為stale狀态
           3)調用neigh_update,更新neighbour的狀态
           
neigh_add
    ->neigh_lookup
    ->neigh_event_send
    ->neigh_update(NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE)

           
neigh_periodic_work
    周期reachable_time,每300s重新随機生成
    NUD_PERMANENT | NUD_IN_TIMER(NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)不處理,僅處理NUD_STALE|NUD_FAILED
    ->NUD_FAILED狀态,引用計數為,删除;NUD_STALE狀态gc_staletime時間未使用,删除
    ->neigh_cleanup_and_release

neigh_timer_handler
    僅處理NUD_IN_TIMER(NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)狀态條目
    ->NUD_REACHABLE
        neigh->confirmed: 最近收到來自對應鄰居項的封包時間;neigh->used: 最近使用該鄰居項的時間
        ->confirm未逾時,不更改狀态,修改逾時時間reachable_time
        ->confirm逾時,used未逾時,狀态轉NUD_DELAY,修改逾時時間delay_probe_time,停fast path
        ->confirm逾時、used逾時,狀态轉NUD_STALE,停fast path
    ->NUD_DELAY(減少ARP包的數目,期望在定時時間内會收到對方的确認封包)
        ->收到對方封包,狀态轉NUD_REACHABLE,開fast path
        ->逾時,未收到對方封包,狀态轉NUD_PROBE
    ->NUD_PROBE|NUD_INCOMPLETE:
        ->超過最大probe次數轉NUD_FAILED,從arp_queue移除skb
    調整下次逾時時間
    ->NUD_INCOMPLETE | NUD_PROBE
        ->neigh_probe

           
struct neigh_table arp_tbl = {
    .family     = AF_INET,
    .key_len    = ,
    .hash       = arp_hash,
    .constructor    = arp_constructor,
    .proxy_redo = parp_redo(arp_process),
    .id     = "arp_cache",
    .parms      = {
        .tbl            = &arp_tbl,
        .base_reachable_time    =  * HZ,
        .retrans_time       =  * HZ,
        .gc_staletime       =  * HZ,
        .reachable_time     =  * HZ,
        .delay_probe_time   =  * HZ,
        .queue_len_bytes    = *,
        .ucast_probes       = ,
        .mcast_probes       = ,
        .anycast_delay      =  * HZ,
        .proxy_delay        = ( * HZ) / ,
        .proxy_qlen     = ,
        .locktime       =  * HZ,
    },
    .gc_interval    =  * HZ,
    .gc_thresh1 = ,
    .gc_thresh2 = ,
    .gc_thresh3 = ,
};
           
net/ipv4/arp.c
arp_init
    ->neigh_table_init(&arp_tbl)
        ->neigh_table_init_no_netlink
            ->neigh_rand_reach_time
            ->neigh_hash_alloc
            ->neigh_periodic_work
            ->schedule_delayed_work(&tbl->gc_work
            ->neigh_proxy_process
            ->skb_queue_head_init_class(&tbl->proxy_queue

           

繼續閱讀