|
|
/*++
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); }
|