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

📄 lli.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// LLI.C
//
// IP Address Object
//
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "lli.h"

static LLI  *plliFirstExp  = 0;            // Points to first LLI in Exp list

//--------------------------------------------------------------------
// LLIMsg()
//
// Sevices Address Resolution
//--------------------------------------------------------------------
void LLIMsg( uint Msg )
{
    static HANDLE hTimer = 0;

    switch( Msg )
    {
    // System Initialization
    case MSG_EXEC_SYSTEM_INIT:
        // Create a 1 second timer
        hTimer = TimerNew( &LLIMsg, TIMER_TICKS_LLI, MSG_LLI_TIMER );
        break;

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

    // Low Resoruces
    case MSG_EXEC_LOW_RESOURCES:
        _LLITimeoutFlush();
        break;

    // One Second Timer
    case MSG_LLI_TIMER:
        _LLITimeoutCheck();
        break;
    }

    return;
}

//--------------------------------------------------------------------
// LLINew()
//
// Create
//--------------------------------------------------------------------
HANDLE LLINew( HANDLE hRt, HANDLE hLLA )
{
    LLI    *plli;

    // Route is required
    if( !hRt )
    {
        DbgPrintf(DBG_ERROR,"LLINew: No Route");
        return(0);
    }

    if( !(plli = mmAlloc(sizeof(LLI))) )
    {
        DbgPrintf(DBG_WARN,"LLINew: OOM");
        ExecLowResource();
        return(0);
    }

    // Most things are zero init
    mmZeroInit( plli, sizeof(LLI) );

    // Initialize type
    plli->Type = HTYPE_LLI;

    // Initialize non-zero parameters
    plli->hRt  = hRt;

    // Setup the LLI - Create LLA if needed
    if( !hLLA )
    {
        plli->Status = LLI_STATUS_IDLE;
        hLLA = LLANew();
    }
    else
    {
        plli->Status = LLI_STATUS_VALID;
        LLARef( hLLA );
    }
    plli->hLLA = hLLA;

    // Here we must have an LLA
    if( !plli->hLLA )
    {
        DbgPrintf(DBG_WARN,"LLINew: No LLA");
        LLIFree( plli );
        return(0);
    }

    return( (HANDLE)plli );
}

//--------------------------------------------------------------------
// LLIFree
//
// Destroy LLI
//--------------------------------------------------------------------
void LLIFree( HANDLE hLLI )
{
    LLI    *plli = (LLI *)hLLI;

#ifdef _STRONG_CHECKING
    if( plli->Type != HTYPE_LLI )
    {
        DbgPrintf(DBG_ERROR,"LLIFree: HTYPE %04x",plli->Type);
        return;
    }
#endif

    // Kill type for debug
    plli->Type = 0;

    // Remove from exp list
    _LLIExpListRemove( plli );

    // Free any attached packet
    if( plli->hPkt )
        PktFree( plli->hPkt );

    // Free any LLA
    if( plli->hLLA )
        LLADeRef( plli->hLLA );

    mmFree( plli );
}

//--------------------------------------------------------------------
// LLIGetValidTime() - Return the Valid Time of the LLI
//
// When an LLI is vailidated via ARP, it remains valid for a
// certain length of time. This function returns the expiration
// time of an LLI entry (0 for STATIC or invalid entries).
//--------------------------------------------------------------------
UINT32 LLIGetValidTime( HANDLE hLLI )
{
    LLI    *plli = (LLI *)hLLI;

#ifdef _STRONG_CHECKING
    if( plli->Type != HTYPE_LLI )
    {
        DbgPrintf(DBG_ERROR,"LLIGetValidTime: HTYPE %04x",plli->Type);
        return(0);
    }
#endif

    // Return NULL on an invalid LLI
    if( plli->Status != LLI_STATUS_VALID )
        return(0);

    // Return the valid time of the LLI
    return( plli->dwTimeout );
}

//--------------------------------------------------------------------
// LLIGetLLA() - Return the LLA (if valid) of the LLI
//
// Checks the status of the LLA and returns it if valid
//--------------------------------------------------------------------
HANDLE LLIGetLLA( HANDLE hLLI )
{
    LLI    *plli = (LLI *)hLLI;

#ifdef _STRONG_CHECKING
    if( plli->Type != HTYPE_LLI )
    {
        DbgPrintf(DBG_ERROR,"LLIGetValidTime: HTYPE %04x",plli->Type);
        return(0);
    }
#endif

    // Return NULL on an invalid LLI
    if( plli->Status != LLI_STATUS_VALID )
        return(0);

    // Return the LLA
    return( plli->hLLA );
}

//--------------------------------------------------------------------
// _LLIExpListInsert - Insert LLI into expiration list
//
//--------------------------------------------------------------------
void _LLIExpListInsert( LLI *plli, UINT32 dwExp )
{
    LLI *plliTmp;

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

        // Save the expiration
        plli->dwTimeout = dwExp;

        // Now add the entry to the list
        // Check the easy case - being first
        if( !plliFirstExp || plliFirstExp->dwTimeout >= dwExp )
        {
            // What we point to next
            plli->pNextExp = plliFirstExp;
            // Before us...pointing to us
            plliFirstExp = plli;
        }
        else
        {
            // Find an entry we expire AFTER
            plliTmp = plliFirstExp;
            while( plliTmp->pNextExp &&
                   plliTmp->pNextExp->dwTimeout < dwExp )
                plliTmp = plliTmp->pNextExp;

            // What we point to next
            plli->pNextExp = plliTmp->pNextExp;
            // Before us...pointing to us
            plliTmp->pNextExp = plli;
        }
    }
}

//--------------------------------------------------------------------
// _LLIExpListRemove - Remove LLI from expiration list
//
// Note: Normally, entries will be removed off the top of the list.
// However, if it is prematurely removed, it may be anywhere in the
// list.
//--------------------------------------------------------------------
void _LLIExpListRemove( LLI *plli )
{
    LLI *plliTmp;

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

    // Check to see if we're the head of the list
    if( plli == plliFirstExp )
        plliFirstExp = plli->pNextExp;
    else
    {
        // Look for us
        plliTmp = plliFirstExp;
        while( plliTmp && plliTmp->pNextExp != plli )
            plliTmp = plliTmp->pNextExp;

        // Patch entry which points to us
        if( plliTmp )
            plliTmp->pNextExp = plli->pNextExp;
    }
}

//--------------------------------------------------------------------
// LLITimeoutCheck - Check for Timed-out ARPs
//--------------------------------------------------------------------
void _LLITimeoutCheck()
{
    LLI     *plli;
    UINT32  dwTimeNow;
    HANDLE  hPkt;

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

    dwTimeNow = llTimerGetTime(0);

    do
    {
        // Get an expired entry off the list
        plli = plliFirstExp;
        if( plli && plli->dwTimeout <= dwTimeNow )
        {
            plliFirstExp = plli->pNextExp;
            // Make sure route does't go away when during check
            RtRef( plli->hRt );
        }
        else
            plli = 0;

        // Process an expired entry
        if( plli )
        {
            // Clear the expiration time
            plli->dwTimeout = 0;

            // Timeout ARP
            if( plli->Status == LLI_STATUS_ARP5 )
            {
                // ARP going down! Too many requests.

                // Back into timeout list
                _LLIExpListInsert( plli, dwTimeNow + LLI_ARP_DOWN_TIME );

                // Knock down the route
                plli->Status = LLI_STATUS_DOWN;
                RtSetFailure( plli->hRt, FLG_RTF_REPORT, RTC_HOSTUNREACH );

                // Return any waiting packet to IP
                // Use the forwarding flag since to gen ICMP error
                hPkt = plli->hPkt;
                plli->hPkt = 0;
                if( hPkt )
                    IPTxPacket( hPkt, FLG_IPTX_FORWARDING );
            }
            else if( plli->Status == LLI_STATUS_DOWN )
            {
                // Downed ARP coming up for air
                plli->Status = LLI_STATUS_IDLE;
                RtSetFailure( plli->hRt, FLG_RTF_REPORT, 0 );
            }

            // ARP Retry if not "down"
            if( plli->Status >= LLI_STATUS_ARP0 &&
                plli->Status < LLI_STATUS_ARP5 )
            {
                // When at first ARP doesn't succeed ...
                plli->Status++;

                // Insert into timeout list
                _LLIExpListInsert( plli, dwTimeNow + 1 );

                // Send ARP for this packet
                LLIGenArpPacket( RtGetIF(plli->hRt), RtGetIPAddr(plli->hRt) );
            }
            // Now we can DeRef the route
            RtDeRef( plli->hRt );
        }
    } while( plli );
}

//--------------------------------------------------------------------
// LLITimeoutFlush - Dump all LLI's in the timeout list
//--------------------------------------------------------------------
void _LLITimeoutFlush()
{
    LLI    *plli;

    // When a low resource condition or flush occurs, we'll free any
    // packet which is waiting at a pending LLI, and make the LLI "IDLE"

    while( plli = plliFirstExp )
    {
        // Get it out of the list
        plliFirstExp = plli->pNextExp;

        // Set status to IDLE
        plli->Status = LLI_STATUS_IDLE;

        // Free any waiting packet
        if( plli->hPkt )
        {
            PktFree( plli->hPkt );
            plli->hPkt = 0;
        }
    }
}

⌨️ 快捷键说明

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