📄 rtable.c
字号:
//--------------------------------------------------------------------------
// 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 + -