windows-nt/Source/XPSP1/NT/net/rras/rtmv2/lkuptst.c
2020-09-26 16:20:57 +08:00

829 lines
17 KiB
C

/*++
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
lkuptst.c
Abstract:
Contains routines for testing an implementation
for the generalized best matching prefix lookup
interface.
Author:
Chaitanya Kodeboyina (chaitk) 30-Jun-1998
Revision History:
--*/
#include "lkuptst.h"
//
// Main
//
#if LOOKUP_TESTING
__cdecl
main (
IN UINT argc,
IN CHAR *argv[]
)
{
CHAR RouteDatabase[MAX_FNAME_LEN];
FILE *FilePtr;
UINT NumRoutes;
Route InputRoutes[MAXROUTES];
UINT i;
DWORD Status;
// Initialize input arguments
RouteDatabase[0] = '\0';
for ( i = 1; i < argc - 1; i++ )
{
if ( ( argv[i][0] == '-' ) || ( argv[i][0] == '/' ) )
{
if (argv[i][2])
{
Usage();
}
switch (toupper(argv[i][1]))
{
case 'D':
strcpy(RouteDatabase, argv[++i]);
continue;
default:
Usage();
}
}
else
{
Usage();
}
}
if (RouteDatabase[0] == '\0')
{
Usage();
}
if ((FilePtr = fopen(RouteDatabase, "r")) == NULL)
{
Fatal("Failed open route database with status = %08x\n",
ERROR_OPENING_DATABASE);
}
// Print("InputRoutes = %p\n", InputRoutes);
NumRoutes = ReadRoutesFromFile(FilePtr, MAXROUTES, InputRoutes);
// Print("InputRoutes = %p\n", InputRoutes);
fclose(FilePtr);
Status = WorkOnLookup(InputRoutes,
NumRoutes);
return 0;
}
#endif
DWORD
WorkOnLookup (
IN Route *InputRoutes,
IN UINT NumRoutes
)
{
Route *OutputRoute;
HANDLE Table;
UINT Status;
UINT i, j;
PLOOKUP_LINKAGE linkage;
#if PROF
HANDLE Thread;
UINT Priority;
PROFVARS;
Thread = GetCurrentThread();
Priority = GetThreadPriority(Thread);
SetThreadPriority(Thread, THREAD_PRIORITY_TIME_CRITICAL);
#endif
// Create and Initialize a new lookup table
#if PROF
INITPROF;
STARTPROF;
#endif
Status = CreateTable(NUMBYTES, &Table);
#if PROF
STOPPROF;
ADDPROF;
PRINTPROF;
Print("Time for an Initialize Table : %.3f ns\n\n", duration);
#endif
if (!SUCCESS(Status))
{
Fatal("Initialize Failed With Status: %08x\n", Status);
}
CheckTable(Table);
// Compute the total time for inserting all routes
#if PROF
INITPROF;
STARTPROF;
#endif
// Add each route one by one to the table
for (i = 0; i < NumRoutes ; i++)
{
// Print("Inserting Route %6d\n", i + 1);
Status = InsertIntoTable(Table,
LEN(&InputRoutes[i]),
(PUCHAR) &DEST(&InputRoutes[i]),
NULL,
&InputRoutes[i].backptr);
// CheckTable(Table);
if (!SUCCESS(Status))
{
Print("Inserting item %08x/%08x, but got an error",
DEST(&InputRoutes[i]),
MASK(&InputRoutes[i]));
Fatal("Insert Failed With Status: %08x\n", Status);
}
}
#if PROF
STOPPROF;
ADDPROF;
#endif
// Subtract from above the for - loop overhead
#if PROF
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++) { ; }
#if PROF
STOPPROF;
SUBPROF;
Print("Avg Time for an Insert Table : %.3f ns for %d routes\n\n",
duration/i, i);
#endif
CheckTable(Table);
#ifdef _DBG_
DumpTable(Table, VERBOSE);
#endif
#ifdef _DBG_
EnumerateAllRoutes(Table);
#endif
#ifdef _DBG_
ReadAddrAndGetRoute(Table);
#endif
// Compute the total time for searching all routes
#if PROF
INITPROF;
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++)
{
Status = SearchInTable(Table,
LEN(&InputRoutes[i]),
(PUCHAR) &DEST(&InputRoutes[i]),
NULL,
&linkage);
if (!SUCCESS(Status))
{
Print("Searching for %08x/%08x, but got an error\n",
DEST(&InputRoutes[i]),
MASK(&InputRoutes[i]));
Fatal("Search Failed With Status: %08x\n", Status);
}
OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
if (OutputRoute != &InputRoutes[i])
{
if ((DEST(OutputRoute) != DEST(&InputRoutes[i])) ||
(MASK(OutputRoute) != MASK(&InputRoutes[i])))
{
Print("Searching for %08x/%08x, but got %08x/%08x\n",
DEST(&InputRoutes[i]),
MASK(&InputRoutes[i]),
DEST(OutputRoute),
MASK(OutputRoute));
}
else
{
// Print("Possible Duplicate Insertion @S\n");
}
}
}
#if PROF
STOPPROF;
ADDPROF;
#endif
// Subtract from above the for - loop overhead
#if PROF
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++) { ; }
#if PROF
STOPPROF;
SUBPROF;
Print("Avg Time for a Search Table : %.3f ns for %d routes\n\n",
duration/i, i);
#endif
// Compute the total time for searching all prefixes
#if PROF
INITPROF;
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++)
{
Status = BestMatchInTable(Table,
(PUCHAR) &DEST(&InputRoutes[i]),
&linkage);
OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
if (!SUCCESS(Status))
{
Print("Searching for %08x, but got an error\n",
DEST(&InputRoutes[i]));
Fatal("Search Failed With Status: %08x\n", Status);
}
if (OutputRoute != &InputRoutes[i])
{
if (DEST(OutputRoute) != DEST(&InputRoutes[i]))
{
Print("Searching for %08x, but got %08x/%08x\n",
DEST(&InputRoutes[i]),
DEST(OutputRoute),
MASK(OutputRoute));
}
else
{
// Print("Possible Duplicate Insertion @S\n");
}
}
}
#if PROF
STOPPROF;
ADDPROF;
#endif
// Subtract from above the for - loop overhead
#if PROF
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++) { ; }
#if PROF
STOPPROF;
SUBPROF;
Print("Avg Time for Prefix in Table : %.3f ns for %d routes\n\n",
duration/i, i);
#endif
// Compute the total time for deleting all routes
#if PROF
INITPROF;
STARTPROF;
#endif
// Del each route one by one to the table
for (i = 0; i < NumRoutes ; i++)
{
// Print("Deleting Route %6d\n", i + 1);
j = NumRoutes - 1 - i;
Status = DeleteFromTable(Table,
LEN(&InputRoutes[j]),
(PUCHAR) &DEST(&InputRoutes[j]),
NULL,
&linkage);
OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
// CheckTable(Table);
if (!SUCCESS(Status))
{
/*
Print("Deleting route %08x/%08x, but got an error\n",
DEST(&InputRoutes[j]),
MASK(&InputRoutes[j]));
Error("Delete Failed With Status: %08x\n", Status);
*/
}
else
if (OutputRoute != &InputRoutes[j])
{
if ((DEST(OutputRoute) != DEST(&InputRoutes[j])) ||
(MASK(OutputRoute) != MASK(&InputRoutes[j])))
{
Print("Deleting route %08x/%08x, but got %08x/%08x\n",
DEST(&InputRoutes[j]),
MASK(&InputRoutes[j]),
DEST(OutputRoute),
MASK(OutputRoute));
}
else
{
// Print("Possible Duplicate Insertion @D\n");
}
}
}
#if PROF
STOPPROF;
ADDPROF;
#endif
// Subtract from above the for - loop overhead
#if PROF
STARTPROF;
#endif
for (i = 0; i < NumRoutes ; i++) { j = NumRoutes - 1 - i; }
#if PROF
STOPPROF;
SUBPROF;
Print("Avg Time for a Delete Table : %.3f ns for %d routes\n\n",
duration/i, i);
#endif
CheckTable(Table);
#ifdef _DBG_
DumpTable(Table, VERBOSE);
#endif
#ifdef _DBG_
EnumerateAllRoutes(Table);
#endif
#ifdef _DBG_
ReadAddrAndGetRoute(Table);
#endif
// Destory the lookup table
#if PROF
INITPROF;
STARTPROF;
#endif
Status = DestroyTable(Table);
#if PROF
STOPPROF;
ADDPROF;
PRINTPROF;
Print("Time for a Destroy Table : %.3f ns\n\n", duration);
#endif
if (!SUCCESS(Status))
{
Fatal("Destroy Failed With Status: %08x\n", Status);
}
#if PROF
SetThreadPriority(Thread, Priority);
#endif
return 0;
}
// Search Testing
VOID
ReadAddrAndGetRoute (
IN PVOID Table
)
{
LOOKUP_CONTEXT Context;
FILE *FilePtr;
Route *BestRoute;
UINT Status;
ULONG Addr;
PLOOKUP_LINKAGE linkage;
FilePtr = fopen("con", "r");
do
{
Print("Enter the IP Addr to search for: ");
ReadIPAddr(FilePtr, &Addr);
Print("Searching route table for Addr = ");
PrintIPAddr(&Addr);
Print("\n");
Status = SearchInTable(Table,
ADDRSIZE,
(PUCHAR) &Addr,
&Context,
&linkage);
BestRoute = CONTAINING_RECORD(linkage, Route, backptr);
if (!SUCCESS(Status))
{
Fatal("Search Failed With Status: %08x\n", Status);
}
Print("The BMP for this addr: \n");
PrintRoute(BestRoute);
}
while (Addr != 0);
fclose(FilePtr);
}
// Enumerate Testing
VOID
EnumerateAllRoutes (
IN PVOID Table
)
{
LOOKUP_CONTEXT Context;
USHORT NumBits;
UCHAR KeyBits[NUMBYTES];
UINT Status;
PLOOKUP_LINKAGE Linkage;
UINT NumDests = 1;
PVOID DestItems[1];
Print("\n---------------- ENUMERATION BEGIN ---------------------\n");
ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
ZeroMemory(&KeyBits, NUMBYTES);
NumBits = 0;
do
{
Status = EnumOverTable(Table,
&NumBits,
KeyBits,
&Context,
0,
NULL,
&NumDests,
&Linkage);
DestItems[0] = CONTAINING_RECORD(Linkage, Route, backptr);
if (SUCCESS(Status))
{
PrintRoute((Route *)DestItems[0]);
}
}
while (SUCCESS(Status));
// If it is just an EOF, print last route
if (Status == ERROR_NO_MORE_ITEMS)
{
PrintRoute((Route *)DestItems[0]);
}
Print("---------------- ENUMERATION END ---------------------\n\n");
}
UINT ReadRoutesFromFile(
IN FILE *FilePtr,
IN UINT NumRoutes,
OUT Route *RouteTable
)
{
UINT i;
for (i = 0; (!feof(FilePtr)) && (i < NumRoutes) ; )
{
// Print("RouteTable = %p\n", RouteTable);
if (ReadRoute(FilePtr, &RouteTable[i]) != EOF)
{
if (RouteTable[i].len)
{
;
}
else
{
;
}
i++;
}
// Print("RouteTable = %p\n", RouteTable);
}
if (i >= NumRoutes)
{
Error("Number of routes in file exceeds the limit\n",
ERROR_MAX_NUM_ROUTES);
}
Print("Total number of routes = %lu\n\n", i);
return i;
}
INT
ReadRoute (
IN FILE *FilePtr,
OUT Route *route
)
{
UCHAR currLine[MAX_LINE_LEN];
UCHAR *addrBytes;
UCHAR *maskBytes;
UINT byteRead;
UINT byteTemp;
INT numConv;
UINT i;
// Zero the input addr, mask, and len
ClearMemory(route, sizeof(Route));
// Input format: A1.A2..An/M1.M2..Mn!
// Read destination IP address
addrBytes = (UCHAR *) &DEST(route);
// Read the address A1.A2..An
for (i = 0; i < NUMBYTES; i++)
{
numConv = fscanf(FilePtr, "%d.", &byteRead);
// Last Line in file
if (numConv == EOF)
{
return EOF;
}
// End of Address
if (numConv == 0)
{
break;
}
addrBytes[i] = (UCHAR) byteRead;
}
// Read the '/' seperator
fscanf(FilePtr, "%c", &byteRead);
// Read destination IP mask
maskBytes = (UCHAR *) &MASK(route);
// Read the mask M1.M2..Mn
for (i = 0; i < NUMBYTES; i++)
{
numConv = fscanf(FilePtr, "%d.", &byteRead);
// Incomplete line
if (numConv == EOF)
{
return EOF;
}
// End of Mask
if (numConv == 0)
{
break;
}
maskBytes[i] = (UCHAR) byteRead;
// Assume route mask is contiguous
byteTemp = byteRead;
while (byteTemp)
{
byteTemp &= byteTemp - 1;
LEN(route)++;
}
}
// Read the ',' seperator
fscanf(FilePtr, "%c", &byteRead);
// Read next hop information
addrBytes = (UCHAR *) &NHOP(route);
// Read the next hop N1.N2..Nn
for (i = 0; i < NUMBYTES; i++)
{
numConv = fscanf(FilePtr, "%d.", &byteRead);
// Incomplete line
if (numConv == EOF)
{
return EOF;
}
// End of Address
if (numConv == 0)
{
break;
}
addrBytes[i] = (UCHAR) byteRead;
}
// Read the ',' seperator
fscanf(FilePtr, "%c", &byteRead);
// Read interface addr/index
addrBytes = (UCHAR *) &IF(route);
// Read the interface I1.I2..In
for (i = 0; i < NUMBYTES; i++)
{
numConv = fscanf(FilePtr, "%d.", &byteRead);
// Incomplete line
if (numConv == EOF)
{
return EOF;
}
// End of Address
if (numConv == 0)
{
break;
}
addrBytes[i] = (UCHAR) byteRead;
}
// Read the ',' seperator
fscanf(FilePtr, "%c", &byteRead);
// Read the route's metric
fscanf(FilePtr, "%lu", &METRIC(route));
// Read the rest of the line
fscanf(FilePtr, "%s\n", currLine);
#ifdef _DBG_
PrintRoute(route);
#endif
return TRUE;
}
VOID
PrintRoute (
IN Route *route
)
{
if (NULL_ROUTE(route))
{
Print("NULL route\n");
}
else
{
Print("Route: Len = %2d", LEN(route));
Print(", Addr = ");
PrintIPAddr(&DEST(route));
Print(", NHop = ");
PrintIPAddr(&NHOP(route));
Print(", IF = %08x", PtrToInt(IF(route)));
Print(", Metric = %3lu\n", METRIC(route));
}
}
INT
ReadIPAddr (
IN FILE *FilePtr,
OUT ULONG *addr
)
{
UCHAR *addrBytes;
UINT byteRead;
INT numConv;
UINT i;
// Initialize the addr variable to 0
*addr = 0;
// Cast it for easy byte access
addrBytes = (UCHAR *)addr;
// Read the address A1.A2..An
for (i = 0; i < NUMBYTES; i++)
{
numConv = fscanf(FilePtr, "%d.", &byteRead);
// Last Line in file
if (numConv == EOF)
{
return EOF;
}
// End of Address
if (numConv == 0)
{
break;
}
addrBytes[i] = (UCHAR) byteRead;
}
return 0;
}
VOID
PrintIPAddr (
IN ULONG *addr
)
{
UCHAR *addrBytes = (UCHAR *) addr;
UINT i;
if (addrBytes)
{
for (i = 0; i < NUMBYTES; i++)
{
Print("%3d.", addrBytes[i]);
}
Print(" ");
}
else
{
Print("NULL Addr ");
}
}
VOID
Usage (
VOID
)
{
Fatal("Failed Operation with status = %08x"
"\n"
"Tests and measures the IP route lookup mechanism \n"
"\n"
"Usage: \n"
"\t lkuptst \t [ -d routing_database ] \n"
"\n"
"Options:\n"
" -d routing_database \t Name of the route database\n"
"\n",
ERROR_WRONG_CMDUSAGE);
}