Home | History | Annotate | Line # | Download | only in npftest
npftest.c revision 1.1.2.3
      1  1.1.2.3  yamt /*	$NetBSD: npftest.c,v 1.1.2.3 2012/10/30 19:00:46 yamt Exp $	*/
      2  1.1.2.2  yamt 
      3  1.1.2.2  yamt /*
      4  1.1.2.2  yamt  * NPF testing framework.
      5  1.1.2.2  yamt  *
      6  1.1.2.2  yamt  * Public Domain.
      7  1.1.2.2  yamt  */
      8  1.1.2.2  yamt 
      9  1.1.2.2  yamt #include <stdio.h>
     10  1.1.2.2  yamt #include <stdlib.h>
     11  1.1.2.2  yamt #include <stdbool.h>
     12  1.1.2.3  yamt #include <string.h>
     13  1.1.2.2  yamt #include <unistd.h>
     14  1.1.2.2  yamt #include <assert.h>
     15  1.1.2.3  yamt #include <fcntl.h>
     16  1.1.2.3  yamt #include <err.h>
     17  1.1.2.3  yamt 
     18  1.1.2.3  yamt #include <sys/ioctl.h>
     19  1.1.2.3  yamt #include <net/if.h>
     20  1.1.2.3  yamt #include <arpa/inet.h>
     21  1.1.2.2  yamt 
     22  1.1.2.2  yamt #include <rump/rump.h>
     23  1.1.2.3  yamt #include <rump/rump_syscalls.h>
     24  1.1.2.2  yamt 
     25  1.1.2.2  yamt #include "npftest.h"
     26  1.1.2.2  yamt 
     27  1.1.2.3  yamt static bool verbose, quiet;
     28  1.1.2.2  yamt 
     29  1.1.2.3  yamt __dead static void
     30  1.1.2.2  yamt usage(void)
     31  1.1.2.2  yamt {
     32  1.1.2.3  yamt 	printf("usage:\n"
     33  1.1.2.3  yamt 	    "  %s [ -q | -v ] [ -c <config> ] "
     34  1.1.2.3  yamt 	        "[ -i <interface> ] < -b | -t | -s file >\n"
     35  1.1.2.3  yamt 	    "  %s -T <testname> -c <config>\n"
     36  1.1.2.3  yamt 	    "  %s -L\n"
     37  1.1.2.3  yamt 	    "where:\n"
     38  1.1.2.3  yamt 	    "\t-b: benchmark\n"
     39  1.1.2.3  yamt 	    "\t-t: regression test\n"
     40  1.1.2.3  yamt 	    "\t-T <testname>: specific test\n"
     41  1.1.2.3  yamt 	    "\t-s <file>: pcap stream\n"
     42  1.1.2.3  yamt 	    "\t-c <config>: NPF configuration file\n"
     43  1.1.2.3  yamt 	    "\t-i <interface>: primary interface\n"
     44  1.1.2.3  yamt 	    "\t-L: list testnames and description for -T\n"
     45  1.1.2.3  yamt 	    "\t-q: quiet mode\n"
     46  1.1.2.3  yamt 	    "\t-v: verbose mode\n",
     47  1.1.2.3  yamt 	    getprogname(), getprogname(), getprogname());
     48  1.1.2.3  yamt 	exit(EXIT_FAILURE);
     49  1.1.2.3  yamt }
     50  1.1.2.3  yamt 
     51  1.1.2.3  yamt __dead static void
     52  1.1.2.3  yamt describe_tests(void)
     53  1.1.2.3  yamt {
     54  1.1.2.3  yamt 	printf(	"nbuf\tbasic npf mbuf handling\n"
     55  1.1.2.3  yamt 		"processor\tncode processing\n"
     56  1.1.2.3  yamt 		"table\ttable handling\n"
     57  1.1.2.3  yamt 		"state\tstate handling and processing\n"
     58  1.1.2.3  yamt 		"rule\trule processing\n"
     59  1.1.2.3  yamt 		"nat\tNAT rule processing\n");
     60  1.1.2.2  yamt 	exit(EXIT_SUCCESS);
     61  1.1.2.2  yamt }
     62  1.1.2.2  yamt 
     63  1.1.2.3  yamt static bool
     64  1.1.2.3  yamt result(const char *testcase, bool ok)
     65  1.1.2.2  yamt {
     66  1.1.2.2  yamt 	if (!quiet) {
     67  1.1.2.3  yamt 		printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail");
     68  1.1.2.2  yamt 	}
     69  1.1.2.2  yamt 	if (verbose) {
     70  1.1.2.2  yamt 		puts("-----");
     71  1.1.2.2  yamt 	}
     72  1.1.2.3  yamt 	return !ok;
     73  1.1.2.3  yamt }
     74  1.1.2.3  yamt 
     75  1.1.2.3  yamt static void
     76  1.1.2.3  yamt load_npf_config_ifs(prop_dictionary_t dbg_dict)
     77  1.1.2.3  yamt {
     78  1.1.2.3  yamt 	prop_dictionary_t ifdict;
     79  1.1.2.3  yamt 	prop_object_iterator_t it;
     80  1.1.2.3  yamt 	prop_array_t iflist;
     81  1.1.2.3  yamt 
     82  1.1.2.3  yamt 	iflist = prop_dictionary_get(dbg_dict, "interfaces");
     83  1.1.2.3  yamt 	it = prop_array_iterator(iflist);
     84  1.1.2.3  yamt 	while ((ifdict = prop_object_iterator_next(it)) != NULL) {
     85  1.1.2.3  yamt 		const char *ifname;
     86  1.1.2.3  yamt 		unsigned if_idx;
     87  1.1.2.3  yamt 
     88  1.1.2.3  yamt 		prop_dictionary_get_cstring_nocopy(ifdict, "name", &ifname);
     89  1.1.2.3  yamt 		prop_dictionary_get_uint32(ifdict, "idx", &if_idx);
     90  1.1.2.3  yamt 		(void)rumpns_npf_test_addif(ifname, if_idx, verbose);
     91  1.1.2.3  yamt 	}
     92  1.1.2.3  yamt 	prop_object_iterator_release(it);
     93  1.1.2.3  yamt }
     94  1.1.2.3  yamt 
     95  1.1.2.3  yamt static void
     96  1.1.2.3  yamt load_npf_config(const char *config)
     97  1.1.2.3  yamt {
     98  1.1.2.3  yamt 	prop_dictionary_t npf_dict, dbg_dict;
     99  1.1.2.3  yamt 	void *xml;
    100  1.1.2.3  yamt 	int error;
    101  1.1.2.3  yamt 
    102  1.1.2.3  yamt 	/* Read the configuration from the specified file. */
    103  1.1.2.3  yamt 	npf_dict = prop_dictionary_internalize_from_file(config);
    104  1.1.2.3  yamt 	if (!npf_dict) {
    105  1.1.2.3  yamt 		err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
    106  1.1.2.3  yamt 	}
    107  1.1.2.3  yamt 	xml = prop_dictionary_externalize(npf_dict);
    108  1.1.2.3  yamt 
    109  1.1.2.3  yamt 	/* Inspect the debug data.  Create the interfaces, if any. */
    110  1.1.2.3  yamt 	dbg_dict = prop_dictionary_get(npf_dict, "debug");
    111  1.1.2.3  yamt 	if (dbg_dict) {
    112  1.1.2.3  yamt 		load_npf_config_ifs(dbg_dict);
    113  1.1.2.3  yamt 	}
    114  1.1.2.3  yamt 	prop_object_release(npf_dict);
    115  1.1.2.3  yamt 
    116  1.1.2.3  yamt 	/* Pass the XML configuration for NPF kernel component to load. */
    117  1.1.2.3  yamt 	error = rumpns_npf_test_load(xml);
    118  1.1.2.3  yamt 	if (error) {
    119  1.1.2.3  yamt 		errx(EXIT_FAILURE, "npf_test_load: %s\n", strerror(error));
    120  1.1.2.3  yamt 	}
    121  1.1.2.3  yamt 	free(xml);
    122  1.1.2.3  yamt 
    123  1.1.2.3  yamt 	if (verbose) {
    124  1.1.2.3  yamt 		printf("Loaded NPF config at '%s'\n", config);
    125  1.1.2.2  yamt 	}
    126  1.1.2.2  yamt }
    127  1.1.2.2  yamt 
    128  1.1.2.3  yamt /*
    129  1.1.2.3  yamt  * Need to override for cprng_fast32(), since RUMP uses arc4random() for it.
    130  1.1.2.3  yamt  */
    131  1.1.2.3  yamt uint32_t
    132  1.1.2.3  yamt arc4random(void)
    133  1.1.2.3  yamt {
    134  1.1.2.3  yamt 	return random();
    135  1.1.2.3  yamt }
    136  1.1.2.3  yamt 
    137  1.1.2.2  yamt int
    138  1.1.2.2  yamt main(int argc, char **argv)
    139  1.1.2.2  yamt {
    140  1.1.2.3  yamt 	bool benchmark, test, ok, fail, tname_matched;
    141  1.1.2.3  yamt 	char *config, *interface, *stream, *testname;
    142  1.1.2.3  yamt 	int idx = -1, ch;
    143  1.1.2.2  yamt 
    144  1.1.2.2  yamt 	benchmark = false;
    145  1.1.2.3  yamt 	test = false;
    146  1.1.2.3  yamt 
    147  1.1.2.3  yamt 	tname_matched = false;
    148  1.1.2.3  yamt 	testname = NULL;
    149  1.1.2.3  yamt 	config = NULL;
    150  1.1.2.3  yamt 	interface = NULL;
    151  1.1.2.3  yamt 	stream = NULL;
    152  1.1.2.3  yamt 
    153  1.1.2.2  yamt 	verbose = false;
    154  1.1.2.2  yamt 	quiet = false;
    155  1.1.2.2  yamt 
    156  1.1.2.3  yamt 	while ((ch = getopt(argc, argv, "bqvc:i:s:tT:L")) != -1) {
    157  1.1.2.2  yamt 		switch (ch) {
    158  1.1.2.2  yamt 		case 'b':
    159  1.1.2.2  yamt 			benchmark = true;
    160  1.1.2.2  yamt 			break;
    161  1.1.2.2  yamt 		case 'q':
    162  1.1.2.2  yamt 			quiet = true;
    163  1.1.2.2  yamt 			break;
    164  1.1.2.2  yamt 		case 'v':
    165  1.1.2.2  yamt 			verbose = true;
    166  1.1.2.2  yamt 			break;
    167  1.1.2.3  yamt 		case 'c':
    168  1.1.2.3  yamt 			config = optarg;
    169  1.1.2.3  yamt 			break;
    170  1.1.2.3  yamt 		case 'i':
    171  1.1.2.3  yamt 			interface = optarg;
    172  1.1.2.3  yamt 			break;
    173  1.1.2.3  yamt 		case 's':
    174  1.1.2.3  yamt 			stream = optarg;
    175  1.1.2.3  yamt 			break;
    176  1.1.2.3  yamt 		case 't':
    177  1.1.2.3  yamt 			test = true;
    178  1.1.2.3  yamt 			break;
    179  1.1.2.3  yamt 		case 'T':
    180  1.1.2.3  yamt 			test = true;
    181  1.1.2.3  yamt 			testname = optarg;
    182  1.1.2.3  yamt 			break;
    183  1.1.2.3  yamt 		case 'L':
    184  1.1.2.3  yamt 			describe_tests();
    185  1.1.2.2  yamt 		default:
    186  1.1.2.2  yamt 			usage();
    187  1.1.2.2  yamt 		}
    188  1.1.2.2  yamt 	}
    189  1.1.2.2  yamt 
    190  1.1.2.3  yamt 	/*
    191  1.1.2.3  yamt 	 * Either benchmark or test.  If stream analysis, then the interface
    192  1.1.2.3  yamt 	 * is needed as well.
    193  1.1.2.3  yamt 	 */
    194  1.1.2.3  yamt 	if (benchmark == test && (stream && !interface)) {
    195  1.1.2.3  yamt 		usage();
    196  1.1.2.3  yamt 	}
    197  1.1.2.3  yamt 
    198  1.1.2.2  yamt 	/* XXX rn_init */
    199  1.1.2.2  yamt 	extern int rumpns_max_keylen;
    200  1.1.2.2  yamt 	rumpns_max_keylen = 1;
    201  1.1.2.2  yamt 
    202  1.1.2.2  yamt 	rump_init();
    203  1.1.2.2  yamt 	rump_schedule();
    204  1.1.2.2  yamt 
    205  1.1.2.3  yamt 	rumpns_npf_test_init();
    206  1.1.2.3  yamt 
    207  1.1.2.3  yamt 	if (config) {
    208  1.1.2.3  yamt 		load_npf_config(config);
    209  1.1.2.3  yamt 	}
    210  1.1.2.3  yamt 	if (interface && (idx = rumpns_npf_test_getif(interface)) == 0) {
    211  1.1.2.3  yamt 		errx(EXIT_FAILURE, "failed to find the interface");
    212  1.1.2.3  yamt 	}
    213  1.1.2.2  yamt 
    214  1.1.2.3  yamt 	srandom(1);
    215  1.1.2.3  yamt 	fail = false;
    216  1.1.2.2  yamt 
    217  1.1.2.3  yamt 	if (test) {
    218  1.1.2.3  yamt 		if (!testname || strcmp("nbuf", testname) == 0) {
    219  1.1.2.3  yamt 			ok = rumpns_npf_nbuf_test(verbose);
    220  1.1.2.3  yamt 			fail |= result("nbuf", ok);
    221  1.1.2.3  yamt 			tname_matched = true;
    222  1.1.2.3  yamt 		}
    223  1.1.2.3  yamt 
    224  1.1.2.3  yamt 		if (!testname || strcmp("processor", testname) == 0) {
    225  1.1.2.3  yamt 			ok = rumpns_npf_processor_test(verbose);
    226  1.1.2.3  yamt 			fail |= result("processor", ok);
    227  1.1.2.3  yamt 			tname_matched = true;
    228  1.1.2.3  yamt 		}
    229  1.1.2.3  yamt 
    230  1.1.2.3  yamt 		if (!testname || strcmp("table", testname) == 0) {
    231  1.1.2.3  yamt 			ok = rumpns_npf_table_test(verbose);
    232  1.1.2.3  yamt 			fail |= result("table", ok);
    233  1.1.2.3  yamt 			tname_matched = true;
    234  1.1.2.3  yamt 		}
    235  1.1.2.3  yamt 
    236  1.1.2.3  yamt 		if (!testname || strcmp("state", testname) == 0) {
    237  1.1.2.3  yamt 			ok = rumpns_npf_state_test(verbose);
    238  1.1.2.3  yamt 			fail |= result("state", ok);
    239  1.1.2.3  yamt 			tname_matched = true;
    240  1.1.2.3  yamt 		}
    241  1.1.2.3  yamt 	}
    242  1.1.2.3  yamt 
    243  1.1.2.3  yamt 	if (test && config) {
    244  1.1.2.3  yamt 		if (!testname || strcmp("rule", testname) == 0) {
    245  1.1.2.3  yamt 			ok = rumpns_npf_rule_test(verbose);
    246  1.1.2.3  yamt 			fail |= result("rule", ok);
    247  1.1.2.3  yamt 			tname_matched = true;
    248  1.1.2.3  yamt 		}
    249  1.1.2.3  yamt 
    250  1.1.2.3  yamt 		if (!testname || strcmp("nat", testname) == 0) {
    251  1.1.2.3  yamt 			ok = rumpns_npf_nat_test(verbose);
    252  1.1.2.3  yamt 			fail |= result("nat", ok);
    253  1.1.2.3  yamt 			tname_matched = true;
    254  1.1.2.3  yamt 		}
    255  1.1.2.3  yamt 	}
    256  1.1.2.3  yamt 
    257  1.1.2.3  yamt 	if (stream) {
    258  1.1.2.3  yamt 		process_stream(stream, NULL, idx);
    259  1.1.2.3  yamt 	}
    260  1.1.2.2  yamt 
    261  1.1.2.2  yamt 	rump_unschedule();
    262  1.1.2.2  yamt 
    263  1.1.2.3  yamt 	if (testname && !tname_matched)
    264  1.1.2.3  yamt 		errx(EXIT_FAILURE, "test \"%s\" unknown", testname);
    265  1.1.2.3  yamt 
    266  1.1.2.3  yamt 	return fail ? EXIT_FAILURE : EXIT_SUCCESS;
    267  1.1.2.2  yamt }
    268