lwip ARP相關處理(2)


這里說一下find_entry這個函數,這個函數主要是查找ARP表和在ARP表中申請一個empty的表項
 
這里有必要先翻譯一下開頭的注釋:
函數有兩個參數,一個ip地址,一個flag
如果ip地址有效,就返回一個pending或者stable狀態的表項索引。
如果找不到,就創建一個新的,並把這個ip地址設置上去,狀態變為empty。狀態有上層調用函數去改變。
 
如果ip地址是空的。也返回一個empty的表項索引
 
上面的都不符合並且flasg標志為ETHARP_TRY_HARD,那么就嘗試從ARP表中刪除一個最早的表項,並返回之索引。
刪除會有一個優先級別。
在代碼搜索了一遍ARP表的時候,已經記錄了一下表項的狀態和生存時間
 
1.返回第一個empty狀態的表項,代碼中用empty表示
2.返回生存時間最長的stable表項。代碼中用old_stable表示
3.返回生存時間最長且沒有數據緩沖項的索引,代碼中用old_pending表示
4.返回生存時間最長而且有數據緩沖項的索引,代碼中用old_queue表示
 
下面給代碼,照例刪除一下調試用的代碼,減少篇幅

static s8_t find_entry ( struct ip_addr *ipaddr, u8_t flags )
{
    s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
    s8_t empty = ARP_TABLE_SIZE;
    u8_t i = 0, age_pending = 0, age_stable = 0;
#if ARP_QUEUEING
    /* oldest entry with packets on queue */
    s8_t old_queue = ARP_TABLE_SIZE;
    /* its age */
    u8_t age_queue = 0;
#endif
/*上面注意empty ,old_queue ,old_pending ,old_stable 這幾個變量*/
    if ( ipaddr )
    {
        /*etharp_cached_entry保存了上次返回的索引*/
        if ( arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE )
        {
            /*如果上次的還有效,並且是這個要找的ip,直接返回,這個技巧很快*/
            /* the cached entry is stable */
            if ( ip_addr_cmp ( ipaddr, &arp_table[etharp_cached_entry].ipaddr ) )
            {
                /* cached entry was the right one! */
                ETHARP_STATS_INC ( etharp.cachehit );
                return etharp_cached_entry;
            }
        }
    }

/*下面的for做搜索,並記錄一下表項的狀態和生存時間*/
    for ( i = 0; i < ARP_TABLE_SIZE; ++i )
    {
        /* no empty entry found yet and now we do find one? */
        if ( ( empty == ARP_TABLE_SIZE ) && ( arp_table[i].state == ETHARP_STATE_EMPTY ) )
        {
            /*empty == ARP_TABLE_SIZE
            這個第一次生效會生效,這里只進入一次,就是記錄第一個出現empty表項的位置*/
            /* remember first empty entry */
            empty = i;
        }
        /* pending entry? */
        else if ( arp_table[i].state == ETHARP_STATE_PENDING )
        {
            /**看ip是否匹配,匹配的話就直接返回索引更新etharp_cached_entry,*/
            /* if given, does IP address match IP address in ARP entry? */
            if ( ipaddr && ip_addr_cmp ( ipaddr, &arp_table[i].ipaddr ) )
            {
                /* found exact IP address match, simply bail out */
                etharp_cached_entry = i;
                return i;
#if ARP_QUEUEING
                /* pending with queued packets? */
            }
            else if ( arp_table[i].q != NULL )
            {
                        /*找生存時間最長的*/
                if ( arp_table[i].ctime >= age_queue )
                {
                    old_queue = i;
                    age_queue = arp_table[i].ctime;
                }
#endif
                /* pending without queued packets? */
            }
            else
            {
                        /*找生存時間最長的*/
                if ( arp_table[i].ctime >= age_pending )
                {
                    old_pending = i;
                    age_pending = arp_table[i].ctime;
                }
            }
        }
        /* stable entry? */
        else if ( arp_table[i].state == ETHARP_STATE_STABLE )
        {
            /* if given, does IP address match IP address in ARP entry? */
            if ( ipaddr && ip_addr_cmp ( ipaddr, &arp_table[i].ipaddr ) )
            {
                /*找到匹配的就直接返回了,就是它了!!*/
                etharp_cached_entry = i;
                return i;
                /* remember entry with oldest stable entry in oldest, its age in maxtime */
            }
            else if ( arp_table[i].ctime >= age_stable )
            {/*沒有就記錄一下它活了多久,一會會有判斷,如果活得太久了,就干掉它,返回一個empty的給上層*/
                old_stable = i;
                age_stable = arp_table[i].ctime;
            }
        }
    }
    /* { we have no match } => try to create a new entry */

    /* no empty entry found and not allowed to recycle? */
    if ( ( ( empty == ARP_TABLE_SIZE ) && ( ( flags & ETHARP_TRY_HARD ) == 0 ) )
            /* or don't create new entry, only search? */
            || ( ( flags & ETHARP_FIND_ONLY ) != 0 ) )
    {
/*找不到空位了,又不給殺人,只能返回錯誤了*/
        return ( s8_t ) ERR_MEM;
    }

    /* b) choose the least destructive entry to recycle:
     * 1) empty entry
     * 2) oldest stable entry
     * 3) oldest pending entry without queued packets
     * 4) oldest pending entry with queued packets
     *
     * { ETHARP_TRY_HARD is set at this point }
     */
下面找到最合適殺掉的那一個。上面是解釋,就不翻譯了
    /* 1) empty entry available? */
    if ( empty < ARP_TABLE_SIZE )
    {
        i = empty;
    }
    /* 2) found recyclable stable entry? */
    else if ( old_stable < ARP_TABLE_SIZE )
    {
        /* recycle oldest stable*/
        i = old_stable;
#if ARP_QUEUEING
        /* no queued packets should exist on stable entries */
        LWIP_ASSERT ( "arp_table[i].q == NULL", arp_table[i].q == NULL );
#endif
        /* 3) found recyclable pending entry without queued packets? */
    }
    else if ( old_pending < ARP_TABLE_SIZE )
    {
        /* recycle oldest pending */
        i = old_pending;
#if ARP_QUEUEING
        /* 4) found recyclable pending entry with queued packets? */
    }
    else if ( old_queue < ARP_TABLE_SIZE )
    {
        /* recycle oldest pending */
        i = old_queue;
        free_etharp_q ( arp_table[i].q );
        arp_table[i].q = NULL;
#endif
        /* no empty or recyclable entries found */
    }
    else
    {
        return ( s8_t ) ERR_MEM;
    }

    /* { empty or recyclable entry found } */
    LWIP_ASSERT ( "i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE );
/*殺人開始*/
/*從索引中刪除*/
    if ( arp_table[i].state != ETHARP_STATE_EMPTY )
    {
        snmp_delete_arpidx_tree ( arp_table[i].netif, &arp_table[i].ipaddr );
    }
    /* recycle entry (no-op for an already empty entry) */
    arp_table[i].state = ETHARP_STATE_EMPTY;

    /* IP address given? */
/*如果上面傳了個ip下來,就把這個ip寫進去*/
    if ( ipaddr != NULL )
    {
        /* set IP address */
        ip_addr_set ( &arp_table[i].ipaddr, ipaddr );
    }
    arp_table[i].ctime = 0;/*出生時間0*/
    etharp_cached_entry = i;
    return ( err_t ) i;
}




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com