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