Mon Jan 25 12:24:41 2016 UTC ()
include proplib.h if you're going to useuseitit


(pooka)
diff -r1.18 -r1.19 src/usr.sbin/npf/npftest/npftest.c

cvs diff -r1.18 -r1.19 src/usr.sbin/npf/npftest/npftest.c (switch to unified diff)

--- src/usr.sbin/npf/npftest/npftest.c 2015/06/16 23:04:14 1.18
+++ src/usr.sbin/npf/npftest/npftest.c 2016/01/25 12:24:41 1.19
@@ -1,334 +1,336 @@ @@ -1,334 +1,336 @@
1/* $NetBSD: npftest.c,v 1.18 2015/06/16 23:04:14 christos Exp $ */ 1/* $NetBSD: npftest.c,v 1.19 2016/01/25 12:24:41 pooka Exp $ */
2 2
3/* 3/*
4 * NPF testing framework. 4 * NPF testing framework.
5 * 5 *
6 * Public Domain. 6 * Public Domain.
7 */ 7 */
8 8
9#include <stdio.h> 9#include <stdio.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <stdbool.h> 11#include <stdbool.h>
12#include <string.h> 12#include <string.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <assert.h> 14#include <assert.h>
15#include <fcntl.h> 15#include <fcntl.h>
16#include <err.h> 16#include <err.h>
17 17
18#include <sys/mman.h> 18#include <sys/mman.h>
19#include <sys/ioctl.h> 19#include <sys/ioctl.h>
20#include <net/if.h> 20#include <net/if.h>
21#include <arpa/inet.h> 21#include <arpa/inet.h>
22 22
 23#include <prop/proplib.h>
 24
23#include <rump/rump.h> 25#include <rump/rump.h>
24#include <rump/rump_syscalls.h> 26#include <rump/rump_syscalls.h>
25 27
26#include <cdbw.h> 28#include <cdbw.h>
27 29
28#include "npftest.h" 30#include "npftest.h"
29 31
30static bool verbose, quiet; 32static bool verbose, quiet;
31 33
32__dead static void 34__dead static void
33usage(void) 35usage(void)
34{ 36{
35 printf("usage:\n" 37 printf("usage:\n"
36 " %s [ -q | -v ] [ -c <config> ] " 38 " %s [ -q | -v ] [ -c <config> ] "
37 "[ -i <interface> ] < -b | -t | -s file >\n" 39 "[ -i <interface> ] < -b | -t | -s file >\n"
38 " %s -T <testname> -c <config>\n" 40 " %s -T <testname> -c <config>\n"
39 " %s -L\n" 41 " %s -L\n"
40 "where:\n" 42 "where:\n"
41 "\t-b: benchmark\n" 43 "\t-b: benchmark\n"
42 "\t-t: regression test\n" 44 "\t-t: regression test\n"
43 "\t-T <testname>: specific test\n" 45 "\t-T <testname>: specific test\n"
44 "\t-s <file>: pcap stream\n" 46 "\t-s <file>: pcap stream\n"
45 "\t-c <config>: NPF configuration file\n" 47 "\t-c <config>: NPF configuration file\n"
46 "\t-i <interface>: primary interface\n" 48 "\t-i <interface>: primary interface\n"
47 "\t-L: list testnames and description for -T\n" 49 "\t-L: list testnames and description for -T\n"
48 "\t-q: quiet mode\n" 50 "\t-q: quiet mode\n"
49 "\t-v: verbose mode\n", 51 "\t-v: verbose mode\n",
50 getprogname(), getprogname(), getprogname()); 52 getprogname(), getprogname(), getprogname());
51 exit(EXIT_FAILURE); 53 exit(EXIT_FAILURE);
52} 54}
53 55
54__dead static void 56__dead static void
55describe_tests(void) 57describe_tests(void)
56{ 58{
57 printf( "nbuf\tbasic npf mbuf handling\n" 59 printf( "nbuf\tbasic npf mbuf handling\n"
58 "bpf\tBPF coprocessor\n" 60 "bpf\tBPF coprocessor\n"
59 "table\ttable handling\n" 61 "table\ttable handling\n"
60 "state\tstate handling and processing\n" 62 "state\tstate handling and processing\n"
61 "rule\trule processing\n" 63 "rule\trule processing\n"
62 "nat\tNAT rule processing\n"); 64 "nat\tNAT rule processing\n");
63 exit(EXIT_SUCCESS); 65 exit(EXIT_SUCCESS);
64} 66}
65 67
66static bool 68static bool
67result(const char *testcase, bool ok) 69result(const char *testcase, bool ok)
68{ 70{
69 if (!quiet) { 71 if (!quiet) {
70 printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail"); 72 printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail");
71 } 73 }
72 if (verbose) { 74 if (verbose) {
73 puts("-----"); 75 puts("-----");
74 } 76 }
75 return !ok; 77 return !ok;
76} 78}
77 79
78static void 80static void
79load_npf_config_ifs(prop_dictionary_t dbg_dict) 81load_npf_config_ifs(prop_dictionary_t dbg_dict)
80{ 82{
81 prop_array_t iflist = prop_dictionary_get(dbg_dict, "interfaces"); 83 prop_array_t iflist = prop_dictionary_get(dbg_dict, "interfaces");
82 prop_object_iterator_t it = prop_array_iterator(iflist); 84 prop_object_iterator_t it = prop_array_iterator(iflist);
83 prop_dictionary_t ifdict; 85 prop_dictionary_t ifdict;
84 86
85 while ((ifdict = prop_object_iterator_next(it)) != NULL) { 87 while ((ifdict = prop_object_iterator_next(it)) != NULL) {
86 const char *ifname = NULL; 88 const char *ifname = NULL;
87 89
88 prop_dictionary_get_cstring_nocopy(ifdict, "name", &ifname); 90 prop_dictionary_get_cstring_nocopy(ifdict, "name", &ifname);
89 (void)rumpns_npf_test_addif(ifname, true, verbose); 91 (void)rumpns_npf_test_addif(ifname, true, verbose);
90 } 92 }
91 prop_object_iterator_release(it); 93 prop_object_iterator_release(it);
92} 94}
93 95
94static void 96static void
95load_npf_config(const char *config) 97load_npf_config(const char *config)
96{ 98{
97 prop_dictionary_t npf_dict, dbg_dict; 99 prop_dictionary_t npf_dict, dbg_dict;
98 void *xml; 100 void *xml;
99 int error; 101 int error;
100 102
101 /* Read the configuration from the specified file. */ 103 /* Read the configuration from the specified file. */
102 npf_dict = prop_dictionary_internalize_from_file(config); 104 npf_dict = prop_dictionary_internalize_from_file(config);
103 if (!npf_dict) { 105 if (!npf_dict) {
104 err(EXIT_FAILURE, "prop_dictionary_internalize_from_file"); 106 err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
105 } 107 }
106 xml = prop_dictionary_externalize(npf_dict); 108 xml = prop_dictionary_externalize(npf_dict);
107 109
108 /* Inspect the debug data. Create the interfaces, if any. */ 110 /* Inspect the debug data. Create the interfaces, if any. */
109 dbg_dict = prop_dictionary_get(npf_dict, "debug"); 111 dbg_dict = prop_dictionary_get(npf_dict, "debug");
110 if (dbg_dict) { 112 if (dbg_dict) {
111 load_npf_config_ifs(dbg_dict); 113 load_npf_config_ifs(dbg_dict);
112 } 114 }
113 prop_object_release(npf_dict); 115 prop_object_release(npf_dict);
114 116
115 /* Pass the XML configuration for NPF kernel component to load. */ 117 /* Pass the XML configuration for NPF kernel component to load. */
116 error = rumpns_npf_test_load(xml); 118 error = rumpns_npf_test_load(xml);
117 if (error) { 119 if (error) {
118 errx(EXIT_FAILURE, "npf_test_load: %s", strerror(error)); 120 errx(EXIT_FAILURE, "npf_test_load: %s", strerror(error));
119 } 121 }
120 free(xml); 122 free(xml);
121 123
122 if (verbose) { 124 if (verbose) {
123 printf("Loaded NPF config at '%s'\n", config); 125 printf("Loaded NPF config at '%s'\n", config);
124 } 126 }
125} 127}
126 128
127static void * 129static void *
128generate_test_cdb(size_t *size) 130generate_test_cdb(size_t *size)
129{ 131{
130 in_addr_t addr; 132 in_addr_t addr;
131 struct cdbw *cdbw; 133 struct cdbw *cdbw;
132 struct stat sb; 134 struct stat sb;
133 char sfn[32]; 135 char sfn[32];
134 int alen, fd; 136 int alen, fd;
135 void *cdb; 137 void *cdb;
136 138
137 if ((cdbw = cdbw_open()) == NULL) { 139 if ((cdbw = cdbw_open()) == NULL) {
138 err(EXIT_FAILURE, "cdbw_open"); 140 err(EXIT_FAILURE, "cdbw_open");
139 } 141 }
140 strlcpy(sfn, "/tmp/npftest_cdb.XXXXXX", sizeof(sfn)); 142 strlcpy(sfn, "/tmp/npftest_cdb.XXXXXX", sizeof(sfn));
141 if ((fd = mkstemp(sfn)) == -1) { 143 if ((fd = mkstemp(sfn)) == -1) {
142 err(EXIT_FAILURE, "mkstemp"); 144 err(EXIT_FAILURE, "mkstemp");
143 } 145 }
144 unlink(sfn); 146 unlink(sfn);
145 147
146 addr = inet_addr("192.168.1.1"), alen = sizeof(struct in_addr); 148 addr = inet_addr("192.168.1.1"), alen = sizeof(struct in_addr);
147 if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1) 149 if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1)
148 err(EXIT_FAILURE, "cdbw_put"); 150 err(EXIT_FAILURE, "cdbw_put");
149 151
150 addr = inet_addr("10.0.0.2"), alen = sizeof(struct in_addr); 152 addr = inet_addr("10.0.0.2"), alen = sizeof(struct in_addr);
151 if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1) 153 if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1)
152 err(EXIT_FAILURE, "cdbw_put"); 154 err(EXIT_FAILURE, "cdbw_put");
153 155
154 if (cdbw_output(cdbw, fd, "npf-table-cdb", NULL) == -1) { 156 if (cdbw_output(cdbw, fd, "npf-table-cdb", NULL) == -1) {
155 err(EXIT_FAILURE, "cdbw_output"); 157 err(EXIT_FAILURE, "cdbw_output");
156 } 158 }
157 cdbw_close(cdbw); 159 cdbw_close(cdbw);
158 160
159 if (fstat(fd, &sb) == -1) { 161 if (fstat(fd, &sb) == -1) {
160 err(EXIT_FAILURE, "fstat"); 162 err(EXIT_FAILURE, "fstat");
161 } 163 }
162 if ((cdb = mmap(NULL, sb.st_size, PROT_READ, 164 if ((cdb = mmap(NULL, sb.st_size, PROT_READ,
163 MAP_FILE | MAP_PRIVATE, fd, 0)) == MAP_FAILED) { 165 MAP_FILE | MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
164 err(EXIT_FAILURE, "mmap"); 166 err(EXIT_FAILURE, "mmap");
165 } 167 }
166 close(fd); 168 close(fd);
167 169
168 *size = sb.st_size; 170 *size = sb.st_size;
169 return cdb; 171 return cdb;
170} 172}
171 173
172int 174int
173main(int argc, char **argv) 175main(int argc, char **argv)
174{ 176{
175 bool test, ok, fail, tname_matched; 177 bool test, ok, fail, tname_matched;
176 char *benchmark, *config, *interface, *stream, *testname; 178 char *benchmark, *config, *interface, *stream, *testname;
177 unsigned nthreads = 0; 179 unsigned nthreads = 0;
178 ifnet_t *ifp = NULL; 180 ifnet_t *ifp = NULL;
179 int ch; 181 int ch;
180 182
181 benchmark = NULL; 183 benchmark = NULL;
182 test = false; 184 test = false;
183 185
184 tname_matched = false; 186 tname_matched = false;
185 testname = NULL; 187 testname = NULL;
186 config = NULL; 188 config = NULL;
187 interface = NULL; 189 interface = NULL;
188 stream = NULL; 190 stream = NULL;
189 191
190 verbose = false; 192 verbose = false;
191 quiet = false; 193 quiet = false;
192 194
193 while ((ch = getopt(argc, argv, "b:qvc:i:s:tT:Lp:")) != -1) { 195 while ((ch = getopt(argc, argv, "b:qvc:i:s:tT:Lp:")) != -1) {
194 switch (ch) { 196 switch (ch) {
195 case 'b': 197 case 'b':
196 benchmark = optarg; 198 benchmark = optarg;
197 break; 199 break;
198 case 'q': 200 case 'q':
199 quiet = true; 201 quiet = true;
200 break; 202 break;
201 case 'v': 203 case 'v':
202 verbose = true; 204 verbose = true;
203 break; 205 break;
204 case 'c': 206 case 'c':
205 config = optarg; 207 config = optarg;
206 break; 208 break;
207 case 'i': 209 case 'i':
208 interface = optarg; 210 interface = optarg;
209 break; 211 break;
210 case 's': 212 case 's':
211 stream = optarg; 213 stream = optarg;
212 break; 214 break;
213 case 't': 215 case 't':
214 test = true; 216 test = true;
215 break; 217 break;
216 case 'T': 218 case 'T':
217 test = true; 219 test = true;
218 testname = optarg; 220 testname = optarg;
219 break; 221 break;
220 case 'L': 222 case 'L':
221 describe_tests(); 223 describe_tests();
222 break; 224 break;
223 case 'p': 225 case 'p':
224 /* Note: RUMP_NCPU must be high enough. */ 226 /* Note: RUMP_NCPU must be high enough. */
225 if ((nthreads = atoi(optarg)) > 0 && 227 if ((nthreads = atoi(optarg)) > 0 &&
226 getenv("RUMP_NCPU") == NULL) { 228 getenv("RUMP_NCPU") == NULL) {
227 char *val; 229 char *val;
228 asprintf(&val, "%u", nthreads + 1); 230 asprintf(&val, "%u", nthreads + 1);
229 setenv("RUMP_NCPU", val, 1); 231 setenv("RUMP_NCPU", val, 1);
230 free(val); 232 free(val);
231 } 233 }
232 break; 234 break;
233 default: 235 default:
234 usage(); 236 usage();
235 } 237 }
236 } 238 }
237 239
238 /* 240 /*
239 * Either benchmark or test. If stream analysis, then the 241 * Either benchmark or test. If stream analysis, then the
240 * interface should be specified. If benchmark, then the 242 * interface should be specified. If benchmark, then the
241 * config should be loaded. 243 * config should be loaded.
242 */ 244 */
243 if ((benchmark != NULL) == test && (stream && !interface)) { 245 if ((benchmark != NULL) == test && (stream && !interface)) {
244 usage(); 246 usage();
245 } 247 }
246 if (benchmark && (!config || !nthreads)) { 248 if (benchmark && (!config || !nthreads)) {
247 errx(EXIT_FAILURE, "missing config for the benchmark or " 249 errx(EXIT_FAILURE, "missing config for the benchmark or "
248 "invalid thread count"); 250 "invalid thread count");
249 } 251 }
250 252
251 /* XXX rn_init */ 253 /* XXX rn_init */
252 extern int rumpns_max_keylen; 254 extern int rumpns_max_keylen;
253 rumpns_max_keylen = 1; 255 rumpns_max_keylen = 1;
254 256
255 rump_init(); 257 rump_init();
256 rump_schedule(); 258 rump_schedule();
257 259
258 rumpns_npf_test_init(inet_pton, inet_ntop, random); 260 rumpns_npf_test_init(inet_pton, inet_ntop, random);
259 261
260 if (config) { 262 if (config) {
261 load_npf_config(config); 263 load_npf_config(config);
262 } 264 }
263 if (interface && (ifp = rumpns_npf_test_getif(interface)) == 0) { 265 if (interface && (ifp = rumpns_npf_test_getif(interface)) == 0) {
264 errx(EXIT_FAILURE, "failed to find the interface"); 266 errx(EXIT_FAILURE, "failed to find the interface");
265 } 267 }
266 268
267 srandom(1); 269 srandom(1);
268 fail = false; 270 fail = false;
269 271
270 if (test) { 272 if (test) {
271 if (!testname || strcmp("nbuf", testname) == 0) { 273 if (!testname || strcmp("nbuf", testname) == 0) {
272 ok = rumpns_npf_nbuf_test(verbose); 274 ok = rumpns_npf_nbuf_test(verbose);
273 fail |= result("nbuf", ok); 275 fail |= result("nbuf", ok);
274 tname_matched = true; 276 tname_matched = true;
275 } 277 }
276 278
277 if (!testname || strcmp("bpf", testname) == 0) { 279 if (!testname || strcmp("bpf", testname) == 0) {
278 ok = rumpns_npf_bpf_test(verbose); 280 ok = rumpns_npf_bpf_test(verbose);
279 fail |= result("bpf", ok); 281 fail |= result("bpf", ok);
280 tname_matched = true; 282 tname_matched = true;
281 } 283 }
282 284
283 if (!testname || strcmp("table", testname) == 0) { 285 if (!testname || strcmp("table", testname) == 0) {
284 void *cdb; 286 void *cdb;
285 size_t len; 287 size_t len;
286 288
287 cdb = generate_test_cdb(&len); 289 cdb = generate_test_cdb(&len);
288 ok = rumpns_npf_table_test(verbose, cdb, len); 290 ok = rumpns_npf_table_test(verbose, cdb, len);
289 fail |= result("table", ok); 291 fail |= result("table", ok);
290 tname_matched = true; 292 tname_matched = true;
291 munmap(cdb, len); 293 munmap(cdb, len);
292 } 294 }
293 295
294 if (!testname || strcmp("state", testname) == 0) { 296 if (!testname || strcmp("state", testname) == 0) {
295 ok = rumpns_npf_state_test(verbose); 297 ok = rumpns_npf_state_test(verbose);
296 fail |= result("state", ok); 298 fail |= result("state", ok);
297 tname_matched = true; 299 tname_matched = true;
298 } 300 }
299 } 301 }
300 302
301 if (test && config) { 303 if (test && config) {
302 if (!testname || strcmp("rule", testname) == 0) { 304 if (!testname || strcmp("rule", testname) == 0) {
303 ok = rumpns_npf_rule_test(verbose); 305 ok = rumpns_npf_rule_test(verbose);
304 fail |= result("rule", ok); 306 fail |= result("rule", ok);
305 tname_matched = true; 307 tname_matched = true;
306 } 308 }
307 309
308 if (!testname || strcmp("nat", testname) == 0) { 310 if (!testname || strcmp("nat", testname) == 0) {
309 ok = rumpns_npf_nat_test(verbose); 311 ok = rumpns_npf_nat_test(verbose);
310 fail |= result("nat", ok); 312 fail |= result("nat", ok);
311 tname_matched = true; 313 tname_matched = true;
312 } 314 }
313 } 315 }
314 316
315 if (stream) { 317 if (stream) {
316 process_stream(stream, NULL, ifp); 318 process_stream(stream, NULL, ifp);
317 } 319 }
318 320
319 if (benchmark) { 321 if (benchmark) {
320 if (strcmp("rule", benchmark) == 0) { 322 if (strcmp("rule", benchmark) == 0) {
321 rumpns_npf_test_conc(false, nthreads); 323 rumpns_npf_test_conc(false, nthreads);
322 } 324 }
323 if (strcmp("state", benchmark) == 0) { 325 if (strcmp("state", benchmark) == 0) {
324 rumpns_npf_test_conc(true, nthreads); 326 rumpns_npf_test_conc(true, nthreads);
325 } 327 }
326 } 328 }
327 329
328 rump_unschedule(); 330 rump_unschedule();
329 331
330 if (testname && !tname_matched) 332 if (testname && !tname_matched)
331 errx(EXIT_FAILURE, "test \"%s\" unknown", testname); 333 errx(EXIT_FAILURE, "test \"%s\" unknown", testname);
332 334
333 return fail ? EXIT_FAILURE : EXIT_SUCCESS; 335 return fail ? EXIT_FAILURE : EXIT_SUCCESS;
334} 336}