1 /* This NetX test concentrates on the basic TCP operation. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5
6 extern void test_control_return(UINT status);
7
8 #if !defined(NX_DISABLE_IPV4)
9
10 #define DEMO_STACK_SIZE 2048
11
12
13 /* Define the ThreadX and NetX object control blocks... */
14
15 static TX_THREAD thread_0;
16 static TX_THREAD thread_1;
17
18 static NX_PACKET_POOL pool_0;
19 #ifdef __PRODUCT_NETXDUO__
20 static NX_PACKET_POOL my_auxiliary_pool;
21 #endif
22 static NX_IP ip_0;
23 static NX_IP ip_1;
24 static NX_TCP_SOCKET client_socket;
25 static NX_TCP_SOCKET server_socket;
26
27
28
29 /* Define the counters used in the demo application... */
30
31 static ULONG thread_0_counter = 0;
32 static ULONG thread_1_counter = 0;
33 static ULONG error_counter = 0;
34 static ULONG connections = 0;
35 static ULONG disconnections = 0;
36 static ULONG client_receives = 0;
37 static ULONG server_receives = 0;
38 static UINT client_port;
39
40
41 /* Define thread prototypes. */
42
43 static void thread_0_entry(ULONG thread_input);
44 static void thread_1_entry(ULONG thread_input);
45 static void thread_1_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
46 static void thread_1_disconnect_received(NX_TCP_SOCKET *server_socket);
47 static void thread_0_receive_notify(NX_TCP_SOCKET *client_socket);
48 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
49 static void thread_0_establish_notify(NX_TCP_SOCKET *client_socket);
50 static void thread_0_disconnect_complete_notify(NX_TCP_SOCKET *client_socket);
51 #endif
52 static void thread_1_receive_notify(NX_TCP_SOCKET *server_socket);
53 #ifdef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
54 static void timed_wait_notify(NX_TCP_SOCKET *client_socket);
55 #endif
56 static void window_update_notify(NX_TCP_SOCKET *client_socket);
57 extern void _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
58
59
60 /* Define what the initial system looks like. */
61
62 #ifdef CTEST
test_application_define(void * first_unused_memory)63 VOID test_application_define(void *first_unused_memory)
64 #else
65 void netx_tcp_basic_processing_test_application_define(void *first_unused_memory)
66 #endif
67 {
68
69 CHAR *pointer;
70 UINT status;
71
72
73 /* Setup the working pointer. */
74 pointer = (CHAR *) first_unused_memory;
75
76 thread_0_counter = 0;
77 thread_1_counter = 0;
78 error_counter = 0;
79 connections = 0;
80 disconnections = 0;
81 client_receives = 0;
82 server_receives = 0;
83 client_port = 0;
84
85 /* Create the main thread. */
86 tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
87 pointer, DEMO_STACK_SIZE,
88 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
89
90 pointer = pointer + DEMO_STACK_SIZE;
91
92 /* Create the main thread. */
93 tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
94 pointer, DEMO_STACK_SIZE,
95 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
96
97 pointer = pointer + DEMO_STACK_SIZE;
98
99
100 /* Initialize the NetX system. */
101 nx_system_initialize();
102
103 /* Create a packet pool. */
104 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 8192);
105 pointer = pointer + 8192;
106
107 if (status)
108 error_counter++;
109
110 #ifdef __PRODUCT_NETXDUO__
111 /* Create a auxiliary packet pool. 128*10 = 1280 */
112 status = nx_packet_pool_create(&my_auxiliary_pool, "NetX Auxiliary Packet Pool", 128, pointer, 1280);
113 pointer = pointer + 1280;
114
115 if (status)
116 error_counter++;
117 #endif
118
119 /* Create an IP instance. */
120 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
121 pointer, 2048, 1);
122 pointer = pointer + 2048;
123
124 /* Create another IP instance. */
125 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
126 pointer, 2048, 1);
127 pointer = pointer + 2048;
128
129 if (status)
130 error_counter++;
131
132 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
133 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
134 pointer = pointer + 1024;
135
136 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
137 status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
138 pointer = pointer + 1024;
139
140 /* Check ARP enable status. */
141 if (status)
142 error_counter++;
143
144 /* Enable TCP processing for both IP instances. */
145 status = nx_tcp_enable(&ip_0);
146 status += nx_tcp_enable(&ip_1);
147
148 /* Check TCP enable status. */
149 if (status)
150 error_counter++;
151
152 #if defined(__PRODUCT_NETXDUO__)
153
154 /* Set the auxiliary packet pool for IP instance 0. */
155 status = nx_ip_auxiliary_packet_pool_set(&ip_0, &my_auxiliary_pool);
156
157 /* Check the status. */
158 #ifdef NX_ENABLE_DUAL_PACKET_POOL
159 if(status != NX_SUCCESS)
160 error_counter++;
161 #else
162 if(status != NX_NOT_SUPPORTED)
163 error_counter++;
164 #endif
165
166 /* Set the auxiliary packet pool for IP instance 1. */
167 status = nx_ip_auxiliary_packet_pool_set(&ip_1, &my_auxiliary_pool);
168
169 /* Check the status. */
170 #ifdef NX_ENABLE_DUAL_PACKET_POOL
171 if(status != NX_SUCCESS)
172 error_counter++;
173 #else
174 if(status != NX_NOT_SUPPORTED)
175 error_counter++;
176 #endif
177
178 #endif
179 }
180
181
182
183 /* Define the test threads. */
184
thread_0_entry(ULONG thread_input)185 static void thread_0_entry(ULONG thread_input)
186 {
187
188 UINT status;
189 NX_PACKET *my_packet;
190 UINT compare_port;
191 ULONG mss, peer_mss, peer_ip_address, peer_port, bytes_available;
192 ULONG tcp_packets_sent, tcp_bytes_sent, tcp_packets_received, tcp_bytes_received, tcp_invalid_packets, tcp_receive_packets_dropped, tcp_checksum_errors, tcp_connections, tcp_disconnections, tcp_connections_dropped, tcp_retransmit_packets;
193 ULONG packets_sent, bytes_sent, packets_received, bytes_received, retransmit_packets, packets_queued, checksum_errors, socket_state, transmit_queue_depth, transmit_window, receive_window;
194 ULONG window_size = 200;
195
196 /* Print out some test information banners. */
197 printf("NetX Test: TCP Basic Processing Test.................................");
198
199 /* Check for earlier error. */
200 if (error_counter)
201 {
202
203 printf("ERROR!\n");
204 test_control_return(1);
205 }
206
207 /* Get a free port for the client's use. */
208 status = nx_tcp_free_port_find(&ip_0, 1, &client_port);
209
210 /* Check for error. */
211 if (status)
212 {
213
214 printf("ERROR!\n");
215 test_control_return(1);
216 }
217
218 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
219 window_size = 0xFFFFFF;
220 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
221
222 /* Loop to establish 1000 connections, send one message, and disconnect. */
223 while ((thread_0_counter < 1000) && (error_counter == 0))
224 {
225
226 /* Increment thread 0's counter. */
227 thread_0_counter++;
228
229 /* Create a socket. */
230 status = nx_tcp_socket_create(&ip_0, &client_socket, "Client Socket",
231 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, window_size,
232 NX_NULL, NX_NULL);
233
234 /* Check for error. */
235 if (status)
236 error_counter++;
237
238 /* Setup a receive notify function. */
239 status = nx_tcp_socket_receive_notify(&client_socket, thread_0_receive_notify);
240
241 /* Check for error. */
242 if (status)
243 error_counter++;
244
245 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
246 status = nx_tcp_socket_establish_notify(&client_socket, thread_0_establish_notify);
247
248 /* Check for error. */
249 if (status)
250 error_counter++;
251
252 status = nx_tcp_socket_disconnect_complete_notify(&client_socket, thread_0_disconnect_complete_notify);
253
254 /* Check for error. */
255 if (status)
256 error_counter++;
257 #endif
258
259 #ifdef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
260 /* Setup a receive notify function. */
261 status = nx_tcp_socket_timed_wait_callback(&client_socket, timed_wait_notify);
262
263 /* Check for error. */
264 if (status)
265 error_counter++;
266 #endif
267
268 /* Setup a receive notify function. */
269 status = nx_tcp_socket_window_update_notify_set(&client_socket, window_update_notify);
270
271 /* Check for error. */
272 if (status)
273 error_counter++;
274
275 /* Bind the socket. */
276 status = nx_tcp_client_socket_bind(&client_socket, client_port, NX_WAIT_FOREVER);
277
278 /* Check for error. */
279 if (status)
280 error_counter++;
281
282 /* Pickup the port for the client socket. */
283 status = nx_tcp_client_socket_port_get(&client_socket, &compare_port);
284
285 /* Check for error. */
286 if ((status) || (client_port != compare_port))
287 {
288
289 printf("ERROR!\n");
290 test_control_return(1);
291 }
292
293 /* Get information about peer socket before connection. */
294 status = nx_tcp_socket_peer_info_get(&client_socket, &peer_ip_address, &peer_port);
295
296 /* The status should not be successful since the connection is not established. */
297 if (status == NX_SUCCESS)
298 {
299
300 printf("ERROR!\n");
301 test_control_return(1);
302 }
303
304
305 status = nx_tcp_socket_mss_set(&client_socket, 200);
306 if(status)
307 error_counter++;
308
309 /* Attempt to connect the socket. */
310 status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 5), 12, 5 * NX_IP_PERIODIC_RATE);
311
312 /* Check for error. */
313 if (status)
314 error_counter++;
315
316 /* Wait for established state. */
317 status = nx_tcp_socket_state_wait(&client_socket, NX_TCP_ESTABLISHED, 5 * NX_IP_PERIODIC_RATE);
318
319 /* Check for error. */
320 if (status)
321 error_counter++;
322
323 /* Get the socket mss. */
324 status = nx_tcp_socket_mss_get(&client_socket, &mss);
325
326 /* Check for error. */
327 if (status)
328 error_counter++;
329
330 /* Set the socket mss. */
331 status = nx_tcp_socket_mss_set(&client_socket, mss - 1);
332
333 /* Check for error. */
334 if (status == NX_SUCCESS)
335 error_counter++;
336
337 /* Get the peer socket mss. */
338 status = nx_tcp_socket_mss_peer_get(&client_socket, &peer_mss);
339
340 /* Check for error. */
341 if (status)
342 error_counter++;
343
344 /* Get the socket bytes available. */
345 status = nx_tcp_socket_bytes_available(&client_socket, &bytes_available);
346
347 /* Check for error. */
348 if (status)
349 error_counter++;
350
351 /* Get information about peer socket. */
352 status = nx_tcp_socket_peer_info_get(&client_socket, &peer_ip_address, &peer_port);
353
354 /* Check for errors. */
355 if ((status) || (peer_ip_address != IP_ADDRESS(1, 2, 3, 5)) || (peer_port != 12))
356 error_counter++;
357
358 /* Allocate a packet. */
359 status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
360
361 /* Check status. */
362 if (status != NX_SUCCESS)
363 break;
364
365 /* Write ABCs into the packet payload! */
366 memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 28);
367
368 /* Adjust the write pointer. */
369 my_packet -> nx_packet_length = 28;
370 my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + 28;
371
372 /* Send the packet out! */
373 status = nx_tcp_socket_send(&client_socket, my_packet, 5 * NX_IP_PERIODIC_RATE);
374
375 /* Determine if the status is valid. */
376 if (status)
377 {
378 error_counter++;
379 nx_packet_release(my_packet);
380 }
381
382 /* Disconnect this socket. */
383 status = nx_tcp_socket_disconnect(&client_socket, 5 * NX_IP_PERIODIC_RATE);
384
385 /* Determine if the status is valid. */
386 if (status)
387 error_counter++;
388
389 /* Unbind the socket. */
390 status = nx_tcp_client_socket_unbind(&client_socket);
391
392 /* Check for error. */
393 if (status)
394 error_counter++;
395
396 /* Get nothing from the socket. */
397 status = nx_tcp_socket_info_get(&client_socket, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL);
398
399 /* Check for error. */
400 if (status)
401 error_counter++;
402
403 /* Get information about this socket. */
404 status = nx_tcp_socket_info_get(&client_socket, &packets_sent, &bytes_sent,
405 &packets_received, &bytes_received,
406 &retransmit_packets, &packets_queued,
407 &checksum_errors, &socket_state,
408 &transmit_queue_depth, &transmit_window,
409 &receive_window);
410
411 #ifndef NX_DISABLE_TCP_INFO
412
413 if((packets_sent != 1) || (bytes_sent != 28))
414 error_counter++;
415 #endif
416
417 /* Check for errors. */
418 if ((error_counter) || (status) || (packets_received) || (bytes_received) ||
419 (retransmit_packets) || (packets_queued) || (checksum_errors) || (socket_state != NX_TCP_CLOSED) ||
420 (transmit_queue_depth) || (transmit_window != 100) || (receive_window != window_size))
421 {
422
423 printf("ERROR!\n");
424 test_control_return(1);
425 }
426
427 /* Delete the socket. */
428 status = nx_tcp_socket_delete(&client_socket);
429
430 /* Check for error. */
431 if (status)
432 error_counter++;
433 }
434
435 /* Get nothing from the overall TCP information. */
436 status = nx_tcp_info_get(&ip_0, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL);
437
438 /* Check for error. */
439 if (status)
440 error_counter++;
441
442 /* Get the overall TCP information. */
443 status = nx_tcp_info_get(&ip_0, &tcp_packets_sent, &tcp_bytes_sent, &tcp_packets_received, &tcp_bytes_received,
444 &tcp_invalid_packets, &tcp_receive_packets_dropped, &tcp_checksum_errors, &tcp_connections,
445 &tcp_disconnections, &tcp_connections_dropped, &tcp_retransmit_packets);
446
447 #ifndef NX_DISABLE_TCP_INFO
448 if((tcp_packets_sent != 1000) || (tcp_bytes_sent != 1000*28) || (tcp_connections != 1000) || (tcp_disconnections != 2000))
449 error_counter++;
450 #endif
451
452 /* Check status. */
453 if ((error_counter) || (status) || (thread_0_counter != 1000) || (thread_1_counter != 1000) || (connections != 1000) || (disconnections) ||
454 (tcp_packets_received) || (tcp_bytes_received) || (tcp_invalid_packets) ||(tcp_receive_packets_dropped) || (tcp_checksum_errors) ||
455 (tcp_connections_dropped) || (tcp_retransmit_packets))
456 {
457
458 printf("ERROR!\n");
459 test_control_return(1);
460 }
461 else
462 {
463
464 printf("SUCCESS!\n");
465 test_control_return(0);
466 }
467 }
468
469
thread_1_entry(ULONG thread_input)470 static void thread_1_entry(ULONG thread_input)
471 {
472
473 UINT status;
474 NX_PACKET *packet_ptr;
475 ULONG actual_status;
476
477
478 /* Ensure the IP instance has been initialized. */
479 status = nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
480
481 /* Check status... */
482 if (status != NX_SUCCESS)
483 {
484
485 error_counter++;
486 test_control_return(1);
487 }
488
489 /* Create a socket. */
490 status = nx_tcp_socket_create(&ip_1, &server_socket, "Server Socket",
491 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
492 NX_NULL, thread_1_disconnect_received);
493
494 /* Check for error. */
495 if (status)
496 error_counter++;
497
498 /* Setup a receive notify function. */
499 status = nx_tcp_socket_receive_notify(&server_socket, thread_1_receive_notify);
500
501 /* Check for error. */
502 if (status)
503 error_counter++;
504
505 /* Configure the socket further. */
506 status = nx_tcp_socket_transmit_configure(&server_socket, 10, 300, 10, 0);
507
508 /* Check for error. */
509 if (status)
510 error_counter++;
511
512 /* Setup this thread to listen. */
513 status = nx_tcp_server_socket_listen(&ip_1, 12, &server_socket, 5, thread_1_connect_received);
514
515 /* Check for error. */
516 if (status)
517 error_counter++;
518
519 /* Accept a client socket connection. */
520 status = nx_tcp_server_socket_accept(&server_socket, 0);
521
522 /* Disconnect the server socket. */
523 status = nx_tcp_socket_disconnect(&server_socket, 5 * NX_IP_PERIODIC_RATE);
524
525 /* Loop to create and establish server connections. */
526 while((thread_1_counter < 1000) && (error_counter == 0))
527 {
528
529 /* Increment thread 1's counter. */
530 thread_1_counter++;
531
532 /* Accept a client socket connection. */
533 status = nx_tcp_server_socket_accept(&server_socket, 5 * NX_IP_PERIODIC_RATE);
534
535 /* Check for error. */
536 if (status)
537 error_counter++;
538
539 /* Receive a TCP message from the socket. */
540 status = nx_tcp_socket_receive(&server_socket, &packet_ptr, 5 * NX_IP_PERIODIC_RATE);
541
542 /* Check for error. */
543 if (status)
544 error_counter++;
545 else
546 /* Release the packet. */
547 nx_packet_release(packet_ptr);
548
549 /* Disconnect the server socket. */
550 status = nx_tcp_socket_disconnect(&server_socket, 5 * NX_IP_PERIODIC_RATE);
551
552 /* Check for error. */
553 if (status)
554 error_counter++;
555
556 /* Unaccept the server socket. */
557 status = nx_tcp_server_socket_unaccept(&server_socket);
558
559 /* Check for error. */
560 if (status)
561 error_counter++;
562
563 /* Setup server socket for listening again. */
564 status = nx_tcp_server_socket_relisten(&ip_1, 12, &server_socket);
565
566 /* Check for error. */
567 if (status)
568 error_counter++;
569 }
570
571 /* Unlisten on the server port. */
572 status = nx_tcp_server_socket_unlisten(&ip_1, 12);
573
574 /* Check for error. */
575 if (status)
576 error_counter++;
577 }
578
579
thread_1_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)580 static void thread_1_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
581 {
582
583 /* Check for the proper socket and port. */
584 if ((socket_ptr != &server_socket) || (port != 12))
585 error_counter++;
586 else
587 connections++;
588 }
589
590
thread_1_disconnect_received(NX_TCP_SOCKET * socket)591 static void thread_1_disconnect_received(NX_TCP_SOCKET *socket)
592 {
593
594 /* Check for proper disconnected socket. */
595 if (socket != &server_socket)
596 error_counter++;
597 }
598
thread_0_receive_notify(NX_TCP_SOCKET * client_socket)599 static void thread_0_receive_notify(NX_TCP_SOCKET *client_socket)
600 {
601
602 client_receives++;
603 }
604
605 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
thread_0_establish_notify(NX_TCP_SOCKET * client_socket)606 static void thread_0_establish_notify(NX_TCP_SOCKET *client_socket)
607 {
608 ;
609 }
610
thread_0_disconnect_complete_notify(NX_TCP_SOCKET * client_socket)611 static void thread_0_disconnect_complete_notify(NX_TCP_SOCKET *client_socket)
612 {
613 ;
614 }
615 #endif
616
thread_1_receive_notify(NX_TCP_SOCKET * server_socket)617 static void thread_1_receive_notify(NX_TCP_SOCKET *server_socket)
618 {
619
620 server_receives++;
621 }
622
623 #ifdef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
timed_wait_notify(NX_TCP_SOCKET * client_socket)624 static void timed_wait_notify(NX_TCP_SOCKET *client_socket)
625 {
626 }
627 #endif
628
window_update_notify(NX_TCP_SOCKET * client_socket)629 static void window_update_notify(NX_TCP_SOCKET *client_socket)
630 {
631 }
632 #else
633
634 #ifdef CTEST
test_application_define(void * first_unused_memory)635 VOID test_application_define(void *first_unused_memory)
636 #else
637 void netx_tcp_basic_processing_test_application_define(void *first_unused_memory)
638 #endif
639 {
640
641 /* Print out test information banner. */
642 printf("NetX Test: TCP Basic Processing Test.................................N/A\n");
643
644 test_control_return(3);
645 }
646 #endif
647