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