441 lines
11 KiB
C
441 lines
11 KiB
C
//============================================================================
|
|
// Copyright (c) 1995, Microsoft Corporation
|
|
//
|
|
// File: forward.c
|
|
//
|
|
// History:
|
|
// V Raman June-25-1997 Created.
|
|
//
|
|
// Wrapper functions for callbacks into IP Router Manager.
|
|
//============================================================================
|
|
|
|
#include "pchmgm.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
VOID
|
|
GetMfeFromForwarder(
|
|
PGROUP_ENTRY pge,
|
|
PSOURCE_ENTRY pse
|
|
)
|
|
{
|
|
BOOL bFound;
|
|
|
|
DWORD dwErr = NO_ERROR, dwInd;
|
|
|
|
PLIST_ENTRY ple, pleHead;
|
|
|
|
POUT_IF_ENTRY poie = NULL;
|
|
|
|
PIPMCAST_MFE_STATS pimms = NULL;
|
|
|
|
|
|
TRACEFORWARD4(
|
|
FORWARD, "ENTERED GetMfeFromForwarder : Group : %x, %x : Source : "
|
|
"%x, %x : ", pge-> dwGroupAddr, pge-> dwGroupMask, pse-> dwSourceAddr,
|
|
pse-> dwSourceMask
|
|
);
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// if MFE is not in forwarder, do not get it
|
|
//
|
|
|
|
if ( !pse-> bInForwarder )
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate large enough buffer and set up query
|
|
//
|
|
|
|
pimms = MGM_ALLOC( SIZEOF_MFE_STATS( pse-> dwMfeIfCount ) );
|
|
|
|
if ( pimms == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
TRACE1(
|
|
ANY, "GetMfeFromForwarder : Failed to create MFE of size : %x",
|
|
SIZEOF_MFE_STATS( pse-> dwMfeIfCount )
|
|
);
|
|
|
|
LOGERR0( HEAP_ALLOC_FAILED, dwErr );
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( pimms, SIZEOF_MFE_STATS( pse-> dwMfeIfCount ) );
|
|
|
|
pimms-> dwGroup = pge-> dwGroupAddr;
|
|
|
|
pimms-> dwSource = pse-> dwSourceAddr;
|
|
|
|
pimms-> dwSrcMask = pse-> dwSourceMask;
|
|
|
|
pimms-> ulNumOutIf = pse-> dwMfeIfCount;
|
|
|
|
|
|
//
|
|
// Get MFE
|
|
//
|
|
|
|
dwErr = GET_MFE_CALLBACK()( pimms );
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
TRACE1(
|
|
ANY, "GetMfeFromForwarder : Failed to get MFE from forwarder"
|
|
": %x", dwErr
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Update base MFE statistics
|
|
//
|
|
|
|
RtlCopyMemory( &pse-> imsStatistics, pimms, SIZEOF_BASIC_MFE_STATS );
|
|
|
|
|
|
TRACEFORWARD4(
|
|
FORWARD, "Group : %x, Source : %x, In Interface : %x, #out if : %x",
|
|
pimms-> dwGroup, pimms-> dwSource, pimms-> dwInIfIndex, pimms-> ulNumOutIf
|
|
);
|
|
|
|
TRACEFORWARD4(
|
|
FORWARD, "In Packets : %d, In Bytes : %d, Diff i/f : %d, Q overflow : %d",
|
|
pimms-> ulInPkts, pimms-> ulInOctets, pimms-> ulPktsDifferentIf,
|
|
pimms-> ulQueueOverflow
|
|
);
|
|
|
|
|
|
//
|
|
// Update statistics for each outgoing interface
|
|
//
|
|
|
|
pleHead = &pse-> leMfeIfList;
|
|
|
|
|
|
//
|
|
// for each outgoing interface in the MFE present in the KMF
|
|
//
|
|
|
|
for ( dwInd = 0; dwInd < pimms-> ulNumOutIf; dwInd++ )
|
|
{
|
|
//
|
|
// find the outgoing interface in the MFE maintained
|
|
// by MGM and update the statistics based on what is
|
|
// retrieved by the kernel mode forwarder
|
|
//
|
|
|
|
bFound = FALSE;
|
|
|
|
ple = pleHead-> Flink;
|
|
|
|
|
|
while ( ple != pleHead )
|
|
{
|
|
poie = CONTAINING_RECORD( ple, OUT_IF_ENTRY, leIfList );
|
|
|
|
//
|
|
// Check if interface has a valid next hop address (non zero)
|
|
// - if it does then assume RAS client interface and do
|
|
// the interface matching based on (Interface index +
|
|
// Next Hop )
|
|
//
|
|
// - otherwise just do it based on the Interface Index
|
|
//
|
|
|
|
bFound = ( poie-> dwIfIndex ==
|
|
pimms-> rgiosOutStats[ dwInd ].dwOutIfIndex );
|
|
|
|
if ( poie-> dwIfNextHopAddr )
|
|
{
|
|
bFound = bFound &&
|
|
( poie-> dwIfNextHopAddr ==
|
|
pimms-> rgiosOutStats[ dwInd ].dwNextHopAddr );
|
|
}
|
|
|
|
|
|
if ( bFound )
|
|
{
|
|
//
|
|
// Outgoing Interface found in MFE in MGM
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
ple = ple-> Flink;
|
|
}
|
|
|
|
|
|
if ( bFound )
|
|
{
|
|
//
|
|
// Update outgoing interface statistics in MGM
|
|
//
|
|
|
|
poie-> imosIfStats.dwOutIfIndex =
|
|
pimms-> rgiosOutStats[ dwInd ].dwOutIfIndex;
|
|
|
|
poie-> imosIfStats.dwNextHopAddr =
|
|
pimms-> rgiosOutStats[ dwInd ].dwNextHopAddr;
|
|
|
|
|
|
poie-> imosIfStats.ulTtlTooLow =
|
|
pimms-> rgiosOutStats[ dwInd ].ulTtlTooLow;
|
|
|
|
poie-> imosIfStats.ulFragNeeded =
|
|
pimms-> rgiosOutStats[ dwInd ].ulFragNeeded;
|
|
|
|
poie-> imosIfStats.ulOutPackets =
|
|
pimms-> rgiosOutStats[ dwInd ].ulOutPackets;
|
|
|
|
poie-> imosIfStats.ulOutDiscards =
|
|
pimms-> rgiosOutStats[ dwInd ].ulOutDiscards;
|
|
|
|
TRACEFORWARD4(
|
|
FORWARD, "Out If : %d, Frag : %d, Out packets : %d, Out discards : %d",
|
|
pimms-> rgiosOutStats[ dwInd ].dwOutIfIndex,
|
|
pimms-> rgiosOutStats[ dwInd ].ulFragNeeded,
|
|
pimms-> rgiosOutStats[ dwInd ].ulOutPackets,
|
|
pimms-> rgiosOutStats[ dwInd ].ulOutDiscards
|
|
);
|
|
}
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
|
|
if ( pimms != NULL )
|
|
{
|
|
MGM_FREE( pimms );
|
|
}
|
|
|
|
|
|
TRACEFORWARD0( FORWARD, "LEAVING GetMfeFromForwarder" );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// AddMfeToForwarder
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
AddMfeToForwarder(
|
|
PGROUP_ENTRY pge,
|
|
PSOURCE_ENTRY pse,
|
|
DWORD dwTimeout
|
|
)
|
|
{
|
|
|
|
DWORD dwErr = NO_ERROR, dwInd = 0;
|
|
|
|
PIPMCAST_MFE pimm = NULL;
|
|
|
|
POUT_IF_ENTRY poie = NULL;
|
|
|
|
PLIST_ENTRY ple = NULL, pleHead = NULL;
|
|
|
|
|
|
|
|
TRACEFORWARD6(
|
|
FORWARD, "ENTERED AddMfeToForwarder : source : %x, %x : Group : "
|
|
"%x, %x : #(out if) : %d : Timeout : %x", pge-> dwGroupAddr,
|
|
pge-> dwGroupMask, pse-> dwSourceAddr, pse-> dwSourceMask,
|
|
pse-> dwMfeIfCount, dwTimeout
|
|
);
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// Allocate appropriate sized MFE.
|
|
//
|
|
|
|
pimm = MGM_ALLOC( SIZEOF_MFE( pse-> dwMfeIfCount ) );
|
|
|
|
if ( pimm == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
TRACE1(
|
|
ANY, "AddMfeToForwarder : Failed to create MFE of size : %x",
|
|
SIZEOF_MFE( pse-> dwMfeIfCount )
|
|
);
|
|
|
|
LOGERR0( HEAP_ALLOC_FAILED, dwErr );
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( pimm, SIZEOF_MFE( pse-> dwMfeIfCount ) );
|
|
|
|
|
|
//
|
|
// fill it up
|
|
//
|
|
|
|
pimm-> dwGroup = pge-> dwGroupAddr;
|
|
|
|
pimm-> dwSource = pse-> dwSourceAddr;
|
|
|
|
pimm-> dwSrcMask = pse-> dwSourceMask;
|
|
|
|
pimm-> dwInIfIndex = (pse-> dwMfeIfCount) ? pse-> dwInIfIndex : 0;
|
|
|
|
pimm-> ulNumOutIf = pse-> dwMfeIfCount;
|
|
|
|
pimm-> ulTimeOut = ( pse-> dwMfeIfCount ) ? 0 : dwTimeout;
|
|
|
|
|
|
//
|
|
// populate the outgoing interface list
|
|
//
|
|
|
|
pleHead = &pse-> leMfeIfList;
|
|
|
|
for ( ple = pleHead-> Flink ; ple != pleHead; ple = ple-> Flink )
|
|
{
|
|
poie = CONTAINING_RECORD( ple, OUT_IF_ENTRY, leIfList );
|
|
|
|
pimm-> rgioOutInfo[ dwInd ].dwOutIfIndex = poie-> dwIfIndex;
|
|
|
|
|
|
if ( poie-> dwIfNextHopAddr )
|
|
{
|
|
pimm-> rgioOutInfo[ dwInd ].dwNextHopAddr =
|
|
poie-> dwIfNextHopAddr;
|
|
}
|
|
|
|
else
|
|
{
|
|
pimm-> rgioOutInfo[ dwInd ].dwNextHopAddr = pimm-> dwGroup;
|
|
}
|
|
|
|
TRACEFORWARD2(
|
|
FORWARD, "AddMfeToForwarder : Out interface %x, next hop %x",
|
|
pimm-> rgioOutInfo[ dwInd ].dwOutIfIndex,
|
|
pimm-> rgioOutInfo[ dwInd ].dwNextHopAddr
|
|
);
|
|
|
|
pimm-> rgioOutInfo[ dwInd++ ].dwDialContext = 0;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// invoke callback into the IP router manager
|
|
//
|
|
|
|
if ( IS_ADD_MFE_CALLBACK() )
|
|
{
|
|
ADD_MFE_CALLBACK() ( pimm );
|
|
}
|
|
|
|
MGM_FREE( pimm );
|
|
|
|
} while ( FALSE );
|
|
|
|
|
|
TRACEFORWARD1( FORWARD, "LEAVING AddMfeToForwarder %x", dwErr );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// DeleteMfeFromForwarder
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteMfeFromForwarder(
|
|
PGROUP_ENTRY pge,
|
|
PSOURCE_ENTRY pse
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
PIPMCAST_DELETE_MFE pimdm = NULL;
|
|
|
|
|
|
|
|
TRACEFORWARD4(
|
|
FORWARD, "ENTERED DeleteMfeToForwarder : source : %x, %x : Group : "
|
|
"%x, %x : Timeout : %x", pge-> dwGroupAddr, pge-> dwGroupMask,
|
|
pse-> dwSourceAddr, pse-> dwSourceMask
|
|
);
|
|
|
|
do
|
|
{
|
|
|
|
//
|
|
// Allocate appropriate sized MFE.
|
|
//
|
|
|
|
pimdm = MGM_ALLOC( sizeof( IPMCAST_DELETE_MFE ) );
|
|
|
|
if ( pimdm == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
TRACE1(
|
|
ANY, "DeleteMfeFromForwarder : Failed to create MFE of size :"
|
|
" %x", sizeof( IPMCAST_DELETE_MFE )
|
|
);
|
|
|
|
LOGERR0( HEAP_ALLOC_FAILED, dwErr );
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( pimdm, sizeof( IPMCAST_DELETE_MFE ) );
|
|
|
|
|
|
//
|
|
// fill it up
|
|
//
|
|
|
|
pimdm-> dwGroup = pge-> dwGroupAddr;
|
|
|
|
pimdm-> dwSource = pse-> dwSourceAddr;
|
|
|
|
pimdm-> dwSrcMask = pse-> dwSourceMask;
|
|
|
|
|
|
//
|
|
// invoke callback into the IP router manager
|
|
//
|
|
|
|
if ( IS_DELETE_MFE_CALLBACK() )
|
|
{
|
|
DELETE_MFE_CALLBACK() ( pimdm );
|
|
}
|
|
|
|
MGM_FREE( pimdm );
|
|
|
|
|
|
} while ( FALSE );
|
|
|
|
|
|
TRACEFORWARD1( FORWARD, "LEAVING DeleteMfeToForwarder %x", dwErr );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|