⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtable.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// RTable.C
//
// Routines related to Route Table
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "route.h"

static RT   *prtFirstExp  = 0;    // First route in Exp list
static uint _RtNoTimer    = 0;    // Set to disable timer

static UINT32 dwTestChecked = 0;
static UINT32 dwTestAttempt = 0;
static UINT32 dwTestRevived = 0;

static void  RtTimeoutCheck();
static void  RtFlush();

//--------------------------------------------------------------------
// RouteMsg()
//
// Sevices initialization, resource and timer messages
//--------------------------------------------------------------------
void RouteMsg( uint Msg )
{
    static HANDLE hTimer;

    switch( Msg )
    {
    // System Initialization
    case MSG_EXEC_SYSTEM_INIT:
        // The odd timer period helps stagger it from the LLI timer
        hTimer = TimerNew( &RouteMsg, TIMER_TICKS_ROUTE, MSG_ROUTE_TIMER );
        NodeTreeNew();
        break;

    // System Shutdown
    case MSG_EXEC_SYSTEM_SHUTDOWN:
        RtFlush();
        NodeTreeFree();
        if( hTimer )
            TimerFree( hTimer );
        break;

    // Ten Second Timer
    case MSG_ROUTE_TIMER:
        RtTimeoutCheck();
        break;
    }
}

//--------------------------------------------------------------------
// RtTimeoutCheck - Check for Timed-out Route
//--------------------------------------------------------------------
static void RtTimeoutCheck()
{
    RT     *prt;
    UINT32 dwTimeNow;
    UINT32 dwTimeTmp;

    // The timeout list is pre-sorted by time. Continue timing out
    // routes until we done ONE that isn't ready.

    if( _RtNoTimer )
        return;

    dwTimeNow = llTimerGetTime(0);

dwTestChecked++;
    do
    {
        // Get expired entry off list
        prt = prtFirstExp;
        if( prt && prt->dwTimeout <= dwTimeNow )
            prtFirstExp = prt->pNextExp;
        else
            prt = 0;

        if( prt )
        {
dwTestAttempt++;
            // Clear the expiration time
            prt->dwTimeout = 0;

            // If this is of type "KEEPALIVE", call the LLI to
            // get the KEEPALIVE time and defer timeout.
            if( (prt->Flags & FLG_RTE_KEEPALIVE) &&
                    (dwTimeTmp = LLIGetValidTime( prt->hLLI )) &&
                    (dwTimeTmp > dwTimeNow) )
            {
dwTestRevived++;
                _RtExpListInsert( prt, dwTimeTmp );
            }
            else
            {
                // Timeout Entry
                prt->Flags |= FLG_RTE_EXPIRED;

                // Remove it from the node chain
                _RtNodeRemove( prt );

                // Next, post a report
                RTCReport(MSG_RTC_EXPIRED, prt->dwIPAddr, prt->dwIPMask);

                // Notify all who cache routes
                IPRtChange( (HANDLE)prt );
                SockPcbRtChange( (HANDLE)prt );

                // DeRef the expired node (was ref'd when timeout set)
                RtDeRef( prt );
            }
        }
    } while( prt );
}

//--------------------------------------------------------------------
// RtFlush - Flush the Route Tree
//--------------------------------------------------------------------
static void RtFlush()
{
    uint wKilled;
    RT     *prt;

    // Kill Everything in the Timeout List
    prt = prtFirstExp;
    while( prt )
    {
        // Timeout Entry
        prt->Flags |= FLG_RTE_EXPIRED;

        // Get it out of the list
        prtFirstExp = prt->pNextExp;

        // Clear the expiration time
        prt->dwTimeout = 0;

        // Remove it from the node chain
        _RtNodeRemove( prt );

        // DeRef the expired node (was ref'd when timeout set)
        RtDeRef( prt );

        // Go to next entry
        prt = prtFirstExp;
    }

    //
    // Kill all STATIC routes
    //
    do
    {
        // Start Walking
        prt = RtWalkBegin();
        wKilled = 0;
        while( prt && !wKilled )
        {
            // Look for ANY static route
            if( prt->Flags & FLG_RTE_STATIC )
            {
                // Found a static route

                // Make it non-static
                prt->Flags &= ~FLG_RTE_STATIC;

                // Remove it from the node chain
                _RtNodeRemove( prt );

                // DeRef it
                RtDeRef( prt );

                // Flag that we killed a route
                wKilled = 1;
            }
            else
                prt = RtWalkNext(prt);
        }
        // We killed a route or ran out of routes. Either way
        // we need to end the walk (and potentially start over).
        RtWalkEnd( prt );
    } while( wKilled );
}


//--------------------------------------------------------------------
// _RtNodeInsert - Insert a route into the Node tree
//
// Returns 1 on Success
//         0 on Error
//--------------------------------------------------------------------
uint _RtNodeInsert( RT *prt )
{
    RT *prtFirst,*prtPrev,*prtNext;

    // Check for idiots
    if( prt->hNode )
        return(1);

    // Get the node that is or will be associated with this route
    if( !(prt->hNode = NodeAdd(prt->dwIPAddr,prt->dwIPMask,prt->MaskBits)) )
        return(0);

    // Get the first route for this node
    prtFirst = (RT *)NodeGetRt( prt->hNode );

    if( !prtFirst )
    {
        // This is the easy case. We're the first and only!
        prtFirst = prt;
    }
    else
    {
        // We need to find:
        // 1. Who's first     (prtFirst)
        // 2. Who's BEFORE us (prtPrev)
        // 3. Who's AFTER us  (prtNext)
        // We always sort by MOST specific MASK first. In the case of
        // a MASK tie, the higher IP address wins. In case an address tie,
        // the higher flags value wins (GATEWAY found before HOST, etc.).

        // i.e. THIS FUNCTION IS NOT USED TO MODIFY EXISTING ROUTES!

        prtPrev = 0;
        prtNext = prtFirst;
        while( prtNext )
        {
            // Most Specific Mask Wins
            if( prt->MaskBits > prtNext->MaskBits )
                break;

            // In case of a tie ...
            if( prt->MaskBits == prtNext->MaskBits )
            {
                // Higher IP address breaks ties
                if( prt->dwIPAddr > prtNext->dwIPAddr )
                    break;

                // Incase of a tie...
                if( prt->dwIPAddr == prtNext->dwIPAddr )
                {
                    if( prt->Flags > prtNext->Flags )
                        break;
                }
            }

            // Otherwise, get the next Rt in the chain
            prtPrev = prtNext;
            prtNext = prtNext->pNext;
        }

        // Now prtNext holds the entry we go BEFORE, and prtPrev holds
        // the entry we go AFTER.
        if( !prtPrev )
        {
            // Here, we're still first, but we need to chain the old
            // routes to us.
            prtFirst = prt;
            prt->pNext = prtNext;
        }
        else
        {
            // Here, there is someone before us, and potentially after us.
            prtPrev->pNext = prt;
            prt->pNext = prtNext;
        }
    }

    // prtFirst holds the new route chain head
    NodeSetRt( prt->hNode, prtFirst );
    return(1);
}

//--------------------------------------------------------------------
// _RtNodeRemove - Remove route from node tree
//
//--------------------------------------------------------------------
void _RtNodeRemove( RT *prt )
{
    RT *prtFirst,*prtNext,*prtPrev;

    if( prt->hNode )
    {
        // Remove us from the node
        prtFirst = (RT *)NodeGetRt( prt->hNode );
        prtNext  = prtFirst;

        // Look for our entry (we may not be there)
        while( prtNext != prt && prtNext->pNext )
        {
            prtPrev = prtNext;
            prtNext = prtNext->pNext;
        }

        // Check to see if we're in the list
        if( prtNext == prt )
        {
            // Remove ourselves from the chain

            // If we're first, set the node Rt to our "next"
            // otherwise, set the PREV rt to point our "next".
            if( prt == prtFirst )
                NodeSetRt( prt->hNode, prt->pNext );
            else
                prtPrev->pNext = prt->pNext;
        }
        NodeDeRef( prt->hNode );
        prt->hNode = 0;
    }
}

//--------------------------------------------------------------------
// _RtExpListInsert - Insert route into expiration list
//
//--------------------------------------------------------------------
void _RtExpListInsert( RT *prt, UINT32 dwExp )
{
    RT *prtTmp;

    if( !dwExp )
        _RtExpListRemove( prt );
    else
    {
        // Remove the entry if its already in the list
        if( prt->dwTimeout )
            _RtExpListRemove( prt );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -