Browse Source

Started adding structure to allow for separate protocol tests, with

individual options.

Created the embryonic beginnings of a cleanly separated driver and
protocol stack API.
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
5263a5abf4
1 changed files with 257 additions and 97 deletions
  1. 257
    97
      src/util/prototester.c

+ 257
- 97
src/util/prototester.c View File

@@ -9,6 +9,7 @@
9 9
 #include <net/if.h>
10 10
 #include <net/ethernet.h>
11 11
 #include <netinet/in.h>
12
+#include <arpa/inet.h>
12 13
 #include <getopt.h>
13 14
 
14 15
 typedef int irq_action_t;
@@ -29,6 +30,57 @@ struct nic_operations {
29 30
 	void ( *irq ) ( struct nic *, irq_action_t );
30 31
 };
31 32
 
33
+/*****************************************************************************
34
+ *
35
+ * Net device layer
36
+ *
37
+ */
38
+
39
+#include "../proto/uip/uip_arp.h"
40
+
41
+static unsigned char node_addr[ETH_ALEN];
42
+static unsigned char packet[ETH_FRAME_LEN];
43
+struct nic static_nic = {
44
+	.node_addr = node_addr,
45
+	.packet = packet,
46
+};
47
+
48
+/* Must be a macro because priv_data[] is of variable size */
49
+#define alloc_netdevice( priv_size ) ( {	\
50
+	static char priv_data[priv_size];	\
51
+	static_nic.priv_data = priv_data;	\
52
+	&static_nic; } )
53
+
54
+static int register_netdevice ( struct nic *nic ) {
55
+	struct uip_eth_addr hwaddr;
56
+
57
+	memcpy ( &hwaddr, nic->node_addr, sizeof ( hwaddr ) );
58
+	uip_setethaddr ( hwaddr );
59
+	return 0;
60
+}
61
+
62
+static inline void unregister_netdevice ( struct nic *nic ) {
63
+	/* Do nothing */
64
+}
65
+
66
+static inline void free_netdevice ( struct nic *nic ) {
67
+	/* Do nothing */
68
+}
69
+
70
+static int netdev_poll ( int retrieve, void **data, size_t *len ) {
71
+	int rc = static_nic.nic_op->poll ( &static_nic, retrieve );
72
+	*data = static_nic.packet;
73
+	*len = static_nic.packetlen;
74
+	return rc;
75
+}
76
+
77
+static void netdev_transmit ( const void *data, size_t len ) {
78
+	uint16_t type = ntohs ( *( ( uint16_t * ) ( data + 12 ) ) );
79
+	static_nic.nic_op->transmit ( &static_nic, data, type,
80
+				      len - ETH_HLEN,
81
+				      data + ETH_HLEN );
82
+}
83
+
32 84
 /*****************************************************************************
33 85
  *
34 86
  * Hijack device interface
@@ -43,8 +95,18 @@ struct hijack {
43 95
 
44 96
 struct hijack_device {
45 97
 	char *name;
98
+	void *priv;
46 99
 };
47 100
 
101
+static inline void hijack_set_drvdata ( struct hijack_device *hijack_dev,
102
+					void *data ) {
103
+	hijack_dev->priv = data;
104
+}
105
+
106
+static inline void * hijack_get_drvdata ( struct hijack_device *hijack_dev ) {
107
+	return hijack_dev->priv;
108
+}
109
+
48 110
 static int hijack_poll ( struct nic *nic, int retrieve ) {
49 111
 	struct hijack *hijack = nic->priv_data;
50 112
 	fd_set fdset;
@@ -118,16 +180,23 @@ static struct nic_operations hijack_operations = {
118 180
 	.irq		= hijack_irq,
119 181
 };
120 182
 
121
-static int hijack_probe ( struct nic *nic, struct hijack_device *hijack_dev ) {
122
-	static struct hijack hijack;
183
+int hijack_probe ( struct hijack_device *hijack_dev ) {
184
+	struct nic *nic;
185
+	struct hijack *hijack;
123 186
 	struct sockaddr_un sun;
124 187
 	int i;
125 188
 
126
-	memset ( &hijack, 0, sizeof ( hijack ) );
189
+	nic = alloc_netdevice ( sizeof ( *hijack ) );
190
+	if ( ! nic ) {
191
+		fprintf ( stderr, "alloc_netdevice() failed\n" );
192
+		goto err_alloc;
193
+	}
194
+	hijack = nic->priv_data;
195
+	memset ( hijack, 0, sizeof ( *hijack ) );
127 196
 
128 197
 	/* Create socket */
129
-	hijack.fd = socket ( PF_UNIX, SOCK_SEQPACKET, 0 );
130
-	if ( hijack.fd < 0 ) {
198
+	hijack->fd = socket ( PF_UNIX, SOCK_SEQPACKET, 0 );
199
+	if ( hijack->fd < 0 ) {
131 200
 		fprintf ( stderr, "socket() failed: %s\n",
132 201
 			  strerror ( errno ) );
133 202
 		goto err;
@@ -137,7 +206,7 @@ static int hijack_probe ( struct nic *nic, struct hijack_device *hijack_dev ) {
137 206
 	sun.sun_family = AF_UNIX;
138 207
 	snprintf ( sun.sun_path, sizeof ( sun.sun_path ), "/var/run/hijack-%s",
139 208
 		   hijack_dev->name );
140
-	if ( connect ( hijack.fd, ( struct sockaddr * ) &sun,
209
+	if ( connect ( hijack->fd, ( struct sockaddr * ) &sun,
141 210
 		       sizeof ( sun ) ) < 0 ) {
142 211
 		fprintf ( stderr, "could not connect to %s: %s\n",
143 212
 			  sun.sun_path, strerror ( errno ) );
@@ -152,23 +221,166 @@ static int hijack_probe ( struct nic *nic, struct hijack_device *hijack_dev ) {
152 221
 	nic->node_addr[0] &= 0xfe; /* clear multicast bit */
153 222
 	nic->node_addr[0] |= 0x02; /* set "locally-assigned" bit */
154 223
 
155
-	nic->priv_data = &hijack;
156 224
 	nic->nic_op = &hijack_operations;
225
+	if ( register_netdevice ( nic ) < 0 )
226
+		goto err;
227
+
228
+	hijack_set_drvdata ( hijack_dev, nic );
157 229
 	return 1;
158 230
 
159 231
  err:
160
-	if ( hijack.fd >= 0 )
161
-		close ( hijack.fd );
232
+	if ( hijack->fd >= 0 )
233
+		close ( hijack->fd );
234
+	free_netdevice ( nic );
235
+ err_alloc:
162 236
 	return 0;
163 237
 }
164 238
 
165
-static void hijack_disable ( struct nic *nic,
166
-			     struct hijack_device *hijack_dev ) {
239
+static void hijack_disable ( struct hijack_device *hijack_dev ) {
240
+	struct nic *nic = hijack_get_drvdata ( hijack_dev );
167 241
 	struct hijack *hijack = nic->priv_data;
168 242
 	
243
+	unregister_netdevice ( nic );
169 244
 	close ( hijack->fd );
170 245
 }
171 246
 
247
+/*****************************************************************************
248
+ *
249
+ * uIP wrapper layer
250
+ *
251
+ */
252
+
253
+#include "../proto/uip/uip.h"
254
+#include "../proto/uip/uip_arp.h"
255
+
256
+void UIP_APPCALL ( void ) {
257
+	printf ( "appcall\n" );
258
+}
259
+
260
+void udp_appcall ( void ) {
261
+}
262
+
263
+static void init_tcpip ( void ) {
264
+	uip_init();
265
+	uip_arp_init();
266
+}
267
+
268
+static void uip_transmit ( void ) {
269
+	uip_arp_out();
270
+	netdev_transmit ( uip_buf, uip_len );
271
+	uip_len = 0;
272
+}
273
+
274
+static int tcp_connect ( struct sockaddr_in *sin ) {
275
+	u16_t ipaddr[2];
276
+
277
+	* ( ( uint32_t * ) ipaddr ) = sin->sin_addr.s_addr;
278
+	return uip_connect ( ipaddr, sin->sin_port ) ? 1 : 0;
279
+}
280
+
281
+static void run_tcpip ( void ) {
282
+	void *data;
283
+	size_t len;
284
+	uint16_t type;
285
+	int i;
286
+	
287
+	if ( netdev_poll ( 1, &data, &len ) ) {
288
+		/* We have data */
289
+		memcpy ( uip_buf, data, len );
290
+		uip_len = len;
291
+		type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
292
+		if ( type == ETHERTYPE_ARP ) {
293
+			uip_arp_arpin();
294
+		} else {
295
+			uip_arp_ipin();
296
+			uip_input();
297
+		}
298
+		if ( uip_len > 0 )
299
+			uip_transmit();
300
+	} else {
301
+		for ( i = 0 ; i < UIP_CONNS ; i++ ) {
302
+			uip_periodic ( i );
303
+			if ( uip_len > 0 )
304
+				uip_transmit();
305
+		}
306
+	}
307
+}
308
+
309
+/*****************************************************************************
310
+ *
311
+ * HTTP protocol tester
312
+ *
313
+ */
314
+
315
+struct http_request {
316
+	struct sockaddr_in sin;
317
+	const char *filename;
318
+	void ( *callback ) ( struct http_request *http );
319
+	int complete;
320
+};
321
+
322
+static int http_get ( struct http_request *http ) {
323
+	return tcp_connect ( &http->sin );
324
+}
325
+
326
+static void test_http_callback ( struct http_request *http ) {
327
+	
328
+}
329
+
330
+static int test_http ( int argc, char **argv ) {
331
+	struct http_request http;
332
+
333
+	memset ( &http, 0, sizeof ( http ) );
334
+	http.filename = "/";
335
+	http.callback = test_http_callback;
336
+	inet_aton ( "192.168.0.1", &http.sin.sin_addr );
337
+	http.sin.sin_port = htons ( 80 );
338
+
339
+	http_get ( &http );
340
+	
341
+	while ( ! http.complete ) {
342
+		run_tcpip ();
343
+	}
344
+
345
+	return 0;
346
+}
347
+
348
+/*****************************************************************************
349
+ *
350
+ * Protocol tester
351
+ *
352
+ */
353
+
354
+struct protocol_test {
355
+	const char *name;
356
+	int ( *exec ) ( int argc, char **argv );
357
+};
358
+
359
+static struct protocol_test tests[] = {
360
+	{ "http", test_http },
361
+};
362
+
363
+#define NUM_TESTS ( sizeof ( tests ) / sizeof ( tests[0] ) )
364
+
365
+static void list_tests ( void ) {
366
+	int i;
367
+
368
+	for ( i = 0 ; i < NUM_TESTS ; i++ ) {
369
+		printf ( "%s\n", tests[i].name );
370
+	}
371
+}
372
+
373
+static struct protocol_test * get_test_from_name ( const char *name ) {
374
+	int i;
375
+
376
+	for ( i = 0 ; i < NUM_TESTS ; i++ ) {
377
+		if ( strcmp ( name, tests[i].name ) == 0 )
378
+			return &tests[i];
379
+	}
380
+
381
+	return NULL;
382
+}
383
+
172 384
 /*****************************************************************************
173 385
  *
174 386
  * Parse command-line options
@@ -181,18 +393,22 @@ struct tester_options {
181 393
 
182 394
 static void usage ( char **argv ) {
183 395
 	fprintf ( stderr,
184
-		  "Usage: %s [options]\n"
396
+		  "Usage: %s [global options] <test> [test-specific options]\n"
185 397
 		  "\n"
186
-		  "Options:\n"
398
+		  "Global options:\n"
187 399
 		  "  -h|--help              Print this help message\n"
188
-		  "  -i|--interface intf    Use specified network interface\n",
189
-		  argv[0] );
400
+		  "  -i|--interface intf    Use specified network interface\n"
401
+		  "  -l|--list              List available tests\n"
402
+		  "\n"
403
+		  "Use \"%s <test> -h\" to view test-specific options\n",
404
+		  argv[0], argv[0] );
190 405
 }
191 406
 
192 407
 static int parse_options ( int argc, char **argv,
193 408
 			   struct tester_options *options ) {
194 409
 	static struct option long_options[] = {
195 410
 		{ "interface", 1, NULL, 'i' },
411
+		{ "list", 0, NULL, 'l' },
196 412
 		{ "help", 0, NULL, 'h' },
197 413
 		{ },
198 414
 	};
@@ -206,7 +422,7 @@ static int parse_options ( int argc, char **argv,
206 422
 	while ( 1 ) {
207 423
 		int option_index = 0;
208 424
 		
209
-		c = getopt_long ( argc, argv, "i:h", long_options,
425
+		c = getopt_long ( argc, argv, "+i:hl", long_options,
210 426
 				  &option_index );
211 427
 		if ( c < 0 )
212 428
 			break;
@@ -216,8 +432,11 @@ static int parse_options ( int argc, char **argv,
216 432
 			strncpy ( options->interface, optarg,
217 433
 				  sizeof ( options->interface ) );
218 434
 			break;
435
+		case 'l':
436
+			list_tests ();
437
+			return -1;
219 438
 		case 'h':
220
-			usage( argv );
439
+			usage ( argv );
221 440
 			return -1;
222 441
 		case '?':
223 442
 			/* Unrecognised option */
@@ -228,79 +447,13 @@ static int parse_options ( int argc, char **argv,
228 447
 		}
229 448
 	}
230 449
 
231
-	/* Check there's nothing left over on the command line */
232
-	if ( optind != argc ) {
450
+	/* Check there is a test specified */
451
+	if ( optind == argc ) {
233 452
 		usage ( argv );
234 453
 		return -1;
235 454
 	}
236
-
237
-	return 0;
238
-}
239
-
240
-/*****************************************************************************
241
- *
242
- * uIP wrapper layer
243
- *
244
- */
245
-
246
-#include "../proto/uip/uip.h"
247
-#include "../proto/uip/uip_arp.h"
248
-
249
-static int done;
250
-
251
-void UIP_APPCALL ( void ) {
252
-	printf ( "appcall\n" );
253
-}
254
-
255
-void udp_appcall ( void ) {
256
-}
257
-
258
-static void uip_transmit ( struct nic *nic ) {
259
-	uip_arp_out();
260
-	nic->nic_op->transmit ( nic, ( char * ) uip_buf,
261
-				ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) ),
262
-				uip_len - ETH_HLEN,
263
-				( char * ) uip_buf + ETH_HLEN );
264
-	uip_len = 0;
265
-}
266
-
267
-static void run_stack ( struct nic *nic ) {
268
-	struct uip_eth_addr hwaddr;
269
-	u16_t ipaddr[2];
270
-	uint16_t type;
271
-	int i;
272
-
273
-	uip_init();
274
-	uip_arp_init();
275
-	memcpy ( &hwaddr, nic->node_addr, sizeof ( hwaddr ) );
276
-	uip_setethaddr ( hwaddr );
277
-
278
-	uip_ipaddr(ipaddr, 192,168,0,1);
279
-	uip_connect(ipaddr, HTONS(80));
280
-
281
-	done = 0;
282
-	while ( ! done ) {
283
-		if ( nic->nic_op->poll ( nic, 1 ) ) {
284
-			/* We have data */
285
-			memcpy ( uip_buf, nic->packet, nic->packetlen );
286
-			uip_len = nic->packetlen;
287
-			type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
288
-			if ( type == ETHERTYPE_ARP ) {
289
-				uip_arp_arpin();
290
-			} else {
291
-				uip_arp_ipin();
292
-				uip_input();
293
-			}
294
-			if ( uip_len > 0 )
295
-				uip_transmit ( nic );
296
-		} else {
297
-			for ( i = 0 ; i < UIP_CONNS ; i++ ) {
298
-				uip_periodic ( i );
299
-				if ( uip_len > 0 )
300
-					uip_transmit ( nic );
301
-			}
302
-		}
303
-	}
455
+	
456
+	return optind;
304 457
 }
305 458
 
306 459
 /*****************************************************************************
@@ -311,28 +464,35 @@ static void run_stack ( struct nic *nic ) {
311 464
 
312 465
 int main ( int argc, char **argv ) {
313 466
 	struct tester_options options;
467
+	struct protocol_test *test;
314 468
 	struct hijack_device hijack_dev;
315
-	static unsigned char node_addr[ETH_ALEN];
316
-	static unsigned char packet[ETH_FRAME_LEN];
317
-	struct nic nic = {
318
-		.node_addr = node_addr,
319
-		.packet = packet,
320
-	};
321 469
 
322 470
 	/* Parse command-line options */
323 471
 	if ( parse_options ( argc, argv, &options ) < 0 )
324 472
 		exit ( 1 );
325 473
 
474
+	/* Identify test */
475
+	test = get_test_from_name ( argv[optind] );
476
+	if ( ! test ) {
477
+		fprintf ( stderr, "Unrecognised test \"%s\"\n", argv[optind] );
478
+		return -1;
479
+	}
480
+	optind++;
481
+
482
+	/* Initialise the protocol stack */
483
+	init_tcpip();
484
+
326 485
 	/* Open the hijack device */
327 486
 	hijack_dev.name = options.interface;
328
-	if ( ! hijack_probe ( &nic, &hijack_dev ) )
487
+	if ( ! hijack_probe ( &hijack_dev ) )
329 488
 		exit ( 1 );
330 489
 
331
-	/* Run the stack to completion */
332
-	run_stack ( &nic );
490
+	/* Run the test */
491
+	if ( test->exec ( argc, argv ) < 0 )
492
+		exit ( 1 );
333 493
 
334 494
 	/* Close the hijack device */
335
-	hijack_disable ( &nic, &hijack_dev );
495
+	hijack_disable ( &hijack_dev );
336 496
 
337 497
 	return 0;
338 498
 }

Loading…
Cancel
Save