📄 lli.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 + -