829 lines
17 KiB
C
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);
|
|
}
|