1 
2 /* This NetX test concentrates on the TCP operation. */
3 
4 #include   "tx_api.h"
5 #include   "nx_api.h"
6 #include   "nx_tcp.h"
7 
8 extern void    test_control_return(UINT status);
9 #if defined NX_NAT_ENABLE && defined __PRODUCT_NETXDUO__ && (NX_MAX_PHYSICAL_INTERFACES >= 2) && !defined(NX_DISABLE_IPV4)
10 #include   "nx_nat.h"
11 
12 #define     DEMO_STACK_SIZE         2048
13 
14 /* Define the ThreadX and NetX object control blocks...  */
15 
16 static TX_THREAD                    thread_0;
17 static TX_THREAD                    thread_1;
18 
19 /* Set up the NAT components. */
20 
21 /* Create a NAT instance, packet pool and translation table. */
22 
23 NX_PACKET_POOL                      nat_packet_pool;
24 NX_NAT_DEVICE                       nat_server;
25 NX_IP                               nat_ip;
26 NX_IP                               local_ip;
27 NX_IP                               external_ip;
28 NX_TCP_SOCKET                       local_socket;
29 NX_TCP_SOCKET                       nat_socket;
30 NX_TCP_SOCKET                       external_socket;
31 
32 
33 /* Configure the NAT network parameters. */
34 
35 /* Set NetX IP packet pool packet size. This should be less than the Maximum Transmit Unit (MTU) of
36    the driver (allow enough room for the Ethernet header plus padding bytes for frame alignment).  */
37 #define NX_NAT_PACKET_SIZE                          1536
38 
39 
40 /* Set the size of the NAT IP packet pool.  */
41 #define NX_NAT_PACKET_POOL_SIZE                     (NX_NAT_PACKET_SIZE * 10)
42 
43 /* Set NetX IP helper thread stack size. */
44 #define NX_NAT_IP_THREAD_STACK_SIZE                 2048
45 
46 /* Set the server IP thread priority */
47 #define NX_NAT_IP_THREAD_PRIORITY                   2
48 
49 /* Set ARP cache size of a NAT ip instance. */
50 #define NX_NAT_ARP_CACHE_SIZE                       1024
51 
52 /* Set NAT entries memory size. */
53 #define NX_NAT_ENTRY_CACHE_SIZE                     1024
54 
55 /* Define NAT IP addresses, local host private IP addresses and external host IP address. */
56 #define NX_NAT_LOCAL_IPADR              (IP_ADDRESS(192, 168, 2, 1))
57 #define NX_NAT_LOCAL_HOST1              (IP_ADDRESS(192, 168, 2, 3))
58 #define NX_NAT_LOCAL_HOST2              (IP_ADDRESS(192, 168, 2, 10))
59 #define NX_NAT_LOCAL_GATEWAY            (IP_ADDRESS(192, 168, 2, 1))
60 #define NX_NAT_LOCAL_NETMASK            (IP_ADDRESS(255, 255, 255, 0))
61 #define NX_NAT_EXTERNAL_IPADR           (IP_ADDRESS(192, 168, 0, 10))
62 #define NX_NAT_EXTERNAL_HOST            (IP_ADDRESS(192, 168, 0, 100))
63 #define NX_NAT_EXTERNAL_GATEWAY         (IP_ADDRESS(192, 168, 0, 1))
64 #define NX_NAT_EXTERNAL_NETMASK         (IP_ADDRESS(255, 255, 255, 0))
65 
66 /* Create NAT structures for preloading NAT tables with static
67    entries for local server hosts. */
68 NX_NAT_TRANSLATION_ENTRY            server_inbound_entry_tcp1;
69 NX_NAT_TRANSLATION_ENTRY            server_inbound_entry_tcp2;
70 
71 /* Set up generic network driver for demo program. */
72 extern void    _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
73 
74 
75 /* Define thread prototypes.  */
76 
77 static void    thread_0_entry(ULONG thread_input);
78 static void    thread_1_entry(ULONG thread_input);
79 
80 
81 /* Define what the initial system looks like.  */
82 #ifdef CTEST
test_application_define(void * first_unused_memory)83 VOID test_application_define(void *first_unused_memory)
84 #else
85 void    netx_nat_tcp_port_test_application_define(void *first_unused_memory)
86 #endif
87 {
88 
89 UINT     status;
90 UCHAR    *pointer;
91 UINT     error_counter = 0;
92 
93     /* Initialize the NetX system. */
94     nx_system_initialize();
95 
96     /* Setup the pointer to unallocated memory.  */
97     pointer =  (UCHAR *) first_unused_memory;
98 
99     /* Create the main thread.  */
100     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
101                      pointer, DEMO_STACK_SIZE,
102                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
103     pointer =  pointer + DEMO_STACK_SIZE;
104 
105     /* Create the main thread.  */
106     tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
107                      pointer, DEMO_STACK_SIZE,
108                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
109     pointer =  pointer + DEMO_STACK_SIZE;
110 
111     /* Create NAT packet pool. */
112     status =  nx_packet_pool_create(&nat_packet_pool, "NAT Packet Pool",
113                                     NX_NAT_PACKET_SIZE, pointer,
114                                     NX_NAT_PACKET_POOL_SIZE);
115 
116     /* Update pointer to unallocated (free) memory. */
117     pointer = pointer + NX_NAT_PACKET_POOL_SIZE;
118 
119     /* Check status.  */
120     if (status)
121         return;
122 
123     /* Create IP instances for NAT server (global network) */
124     status = nx_ip_create(&nat_ip, "NAT IP Instance", NX_NAT_EXTERNAL_IPADR, NX_NAT_EXTERNAL_NETMASK,
125                           &nat_packet_pool, _nx_ram_network_driver_1500, pointer,
126                           NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
127 
128     /* Update pointer to unallocated (free) memory. */
129     pointer =  pointer + NX_NAT_IP_THREAD_STACK_SIZE;
130 
131     /* Check status.  */
132     if (status)
133     {
134         error_counter++;
135         return;
136     }
137 
138     /* Set the private interface(private network).  */
139     status += nx_ip_interface_attach(&nat_ip, "Private Interface", NX_NAT_LOCAL_IPADR, NX_NAT_LOCAL_NETMASK, _nx_ram_network_driver_1500);
140 
141     /* Check status.  */
142     if (status)
143     {
144         error_counter++;
145         return;
146     }
147 
148     /* Create IP instances for Local network IP instance */
149     status = nx_ip_create(&local_ip, "Local IP Instance", NX_NAT_LOCAL_HOST1, NX_NAT_LOCAL_NETMASK,
150                           &nat_packet_pool, _nx_ram_network_driver_1500, pointer,
151                           NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
152 
153     /* Update pointer to unallocated (free) memory. */
154     pointer =  pointer + NX_NAT_IP_THREAD_STACK_SIZE;
155 
156     /* Check status.  */
157     if (status)
158     {
159         error_counter++;
160         return;
161     }
162 
163     /* Create IP instances for external network IP instance */
164     status = nx_ip_create(&external_ip, "External IP Instance", NX_NAT_EXTERNAL_HOST, NX_NAT_EXTERNAL_NETMASK,
165                           &nat_packet_pool, _nx_ram_network_driver_1500, pointer,
166                           NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
167 
168     /* Update pointer to unallocated (free) memory. */
169     pointer =  pointer + NX_NAT_IP_THREAD_STACK_SIZE;
170 
171     /* Check status.  */
172     if (status)
173     {
174         error_counter++;
175         return;
176     }
177 
178     /* Set the global network gateway for NAT IP instance.  */
179     status = nx_ip_gateway_address_set(&nat_ip, NX_NAT_EXTERNAL_GATEWAY);
180 
181     /* Check status.  */
182     if (status)
183     {
184         error_counter++;
185         return;
186     }
187 
188     /* Set the global network gateway for Local IP instance.  */
189     status = nx_ip_gateway_address_set(&local_ip, NX_NAT_LOCAL_GATEWAY);
190 
191     /* Check status.  */
192     if (status)
193     {
194         error_counter++;
195         return;
196     }
197 
198     /* Set the global network gateway for External IP instance.  */
199     status = nx_ip_gateway_address_set(&external_ip, NX_NAT_EXTERNAL_GATEWAY);
200 
201     /* Check status.  */
202     if (status)
203     {
204         error_counter++;
205         return;
206     }
207 
208 
209     /* Enable ARP and supply ARP cache memory for NAT IP isntance. */
210     status =  nx_arp_enable(&nat_ip, (void **) pointer,
211                             NX_NAT_ARP_CACHE_SIZE);
212 
213     /* Check status.  */
214     if (status)
215     {
216         error_counter++;
217         return;
218     }
219 
220     /* Update pointer to unallocated (free) memory. */
221     pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
222 
223     /* Enable ARP and supply ARP cache memory for Local IP isntance. */
224     status =  nx_arp_enable(&local_ip, (void **) pointer,
225                             NX_NAT_ARP_CACHE_SIZE);
226 
227     /* Check status.  */
228     if (status)
229     {
230         error_counter++;
231         return;
232     }
233 
234     /* Update pointer to unallocated (free) memory. */
235     pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
236 
237     /* Enable ARP and supply ARP cache memory for External IP isntance. */
238     status =  nx_arp_enable(&external_ip, (void **) pointer,
239                             NX_NAT_ARP_CACHE_SIZE);
240 
241     /* Check status.  */
242     if (status)
243     {
244         error_counter++;
245         return;
246     }
247 
248     /* Update pointer to unallocated (free) memory. */
249     pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
250 
251     /* Enable TCP traffic.  */
252     status += nx_tcp_enable(&local_ip);
253     status += nx_tcp_enable(&nat_ip);
254     status += nx_tcp_enable(&external_ip);
255 
256     /* Check status.  */
257     if (status)
258     {
259         error_counter++;
260         return;
261     }
262 
263     /* Create a NetX NAT server and cache with a global interface index.  */
264     status =  nx_nat_create(&nat_server, &nat_ip, 0, pointer, NX_NAT_ENTRY_CACHE_SIZE);
265 
266     /* Check status.  */
267     if (status)
268     {
269         error_counter++;
270         return;
271     }
272 
273     /* Update pointer to unallocated (free) memory. */
274     pointer = pointer + NX_NAT_ENTRY_CACHE_SIZE;
275 
276     /* Enable the NAT service.  */
277     nx_nat_enable(&nat_server);
278 }
279 
280 /* Define the test threads.  */
281 
thread_0_entry(ULONG thread_input)282 static void    thread_0_entry(ULONG thread_input)
283 {
284 
285 UINT        status;
286 NX_PACKET   *my_packet;
287 ULONG       packets_sent, bytes_sent, packets_received, bytes_received, retransmit_packets, packets_queued, checksum_errors, socket_state, transmit_queue_depth, transmit_window, receive_window;
288 
289 
290     /* Print out test information banner.  */
291     printf("NetX Test:   NAT TCP Port Processing Test..............................");
292 
293     /* Create a TCP socket for NAT IP instance.  */
294     status = nx_tcp_socket_create(&nat_ip, &nat_socket, "NAT Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200, NX_NULL, NX_NULL);
295 
296     /* Check status.  */
297     if (status)
298     {
299         printf("ERROR!\n");
300         test_control_return(1);
301     }
302 
303     /* Bind the socket to the IP port as NX_NAT_START_TCP_PORT.  */
304     status = nx_tcp_client_socket_bind(&nat_socket, NX_NAT_START_TCP_PORT, NX_WAIT_FOREVER);
305 
306     /* Check status.  */
307     if (status)
308     {
309 
310         printf("ERROR!\n");
311         test_control_return(1);
312     }
313 
314     /* Preload a NAT entry with same external TCP port of NAT socket.  */
315     status = nx_nat_inbound_entry_create(&nat_server, &server_inbound_entry_tcp1, NX_NAT_LOCAL_HOST1, NX_NAT_START_TCP_PORT, NX_NAT_START_TCP_PORT, NX_PROTOCOL_TCP);
316 
317     /* Check status.  */
318     if (status != NX_NAT_PORT_UNAVAILABLE)
319     {
320 
321         printf("ERROR!\n");
322         test_control_return(1);
323     }
324 
325     /* Preload a NAT entry with different external TCP port of NAT socket.  */
326     status = nx_nat_inbound_entry_create(&nat_server, &server_inbound_entry_tcp1, NX_NAT_LOCAL_HOST1, NX_NAT_START_TCP_PORT - 1, NX_NAT_START_TCP_PORT, NX_PROTOCOL_TCP);
327 
328     /* Check status.  */
329     if (status)
330     {
331 
332         printf("ERROR!\n");
333         test_control_return(1);
334     }
335 
336     /* Preload a NAT entry with same external TCP port of NAT entry.  */
337     status = nx_nat_inbound_entry_create(&nat_server, &server_inbound_entry_tcp2, NX_NAT_LOCAL_HOST1, NX_NAT_START_TCP_PORT - 1, NX_NAT_START_TCP_PORT, NX_PROTOCOL_TCP);
338 
339     /* Check status.  */
340     if (status != NX_NAT_PORT_UNAVAILABLE)
341     {
342 
343         printf("ERROR!\n");
344         test_control_return(1);
345     }
346 
347     /* Delete the inbound entry.  */
348     status = nx_nat_inbound_entry_delete(&nat_server, &server_inbound_entry_tcp1);
349 
350     /* Check status.  */
351     if (status)
352     {
353 
354         printf("ERROR!\n");
355         test_control_return(1);
356     }
357 
358     /* Create a TCP local socket.  */
359     status = nx_tcp_socket_create(&local_ip, &local_socket, "Local Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200, NX_NULL, NX_NULL);
360 
361     /* Check status.  */
362     if (status)
363     {
364         printf("ERROR!\n");
365         test_control_return(1);
366     }
367 
368     /* Bind the socket to the IP port 0x88.  */
369     status =  nx_tcp_client_socket_bind(&local_socket, 0x88, NX_WAIT_FOREVER);
370 
371     /* Check status.  */
372     if (status)
373     {
374 
375         printf("ERROR!\n");
376         test_control_return(1);
377     }
378 
379     /***********************************************************************/
380     /*         Local Socket sends tcp packet to External Socket            */
381     /***********************************************************************/
382 
383     /* Let other threads run again.  */
384     tx_thread_relinquish();
385 
386     /* Attempt to connect the socket.  */
387     status =  nx_tcp_client_socket_connect(&local_socket, NX_NAT_EXTERNAL_HOST, 0x89, 5 * NX_IP_PERIODIC_RATE);
388 
389     /* Check status.  */
390     if (status)
391     {
392         printf("ERROR!\n");
393         test_control_return(1);
394     }
395 
396     /* Wait for established state.  */
397     status =  nx_tcp_socket_state_wait(&local_socket, NX_TCP_ESTABLISHED, 5 * NX_IP_PERIODIC_RATE);
398 
399     /* Check status.  */
400     if (status)
401     {
402         printf("ERROR!\n");
403         test_control_return(1);
404     }
405 
406     /* Allocate a packet.  */
407     status =  nx_packet_allocate(&nat_packet_pool, &my_packet, NX_TCP_PACKET, TX_WAIT_FOREVER);
408 
409     /* Check status.  */
410     if (status != NX_SUCCESS)
411     {
412         printf("ERROR!\n");
413         test_control_return(1);
414     }
415 
416     /* Write ABCs into the packet payload!  */
417     memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
418 
419     /* Adjust the write pointer.  */
420     my_packet -> nx_packet_length =  28;
421     my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
422 
423     /* Send the TCP packet.  */
424     status =  nx_tcp_socket_send(&local_socket, my_packet, 5 * NX_IP_PERIODIC_RATE);
425 
426     /* Check status.  */
427     if (status)
428     {
429 
430         printf("ERROR!\n");
431         test_control_return(1);
432     }
433 
434     /* Check status.  */
435     if (status)
436     {
437 
438         printf("ERROR!\n");
439         test_control_return(1);
440     }
441 
442     /* Let other threads run again.  */
443     tx_thread_relinquish();
444 
445     /* Disconnect this socket.  */
446     status =  nx_tcp_socket_disconnect(&local_socket, 5 * NX_IP_PERIODIC_RATE);
447 
448     /* Determine if the status is valid.  */
449     if (status)
450     {
451         printf("ERROR!\n");
452         test_control_return(1);
453     }
454 
455     /* Unbind the socket.  */
456     status =  nx_tcp_client_socket_unbind(&local_socket);
457 
458     /* Check for error.  */
459     if (status)
460     {
461         printf("ERROR!\n");
462         test_control_return(1);
463     }
464 
465     /* Get information about this socket.  */
466     status =  nx_tcp_socket_info_get(&local_socket, &packets_sent, &bytes_sent,
467                                      &packets_received, &bytes_received,
468                                      &retransmit_packets, &packets_queued,
469                                      &checksum_errors, &socket_state,
470                                      &transmit_queue_depth, &transmit_window,
471                                      &receive_window);
472 
473 #ifndef NX_DISABLE_TCP_INFO
474 
475     if((packets_sent != 1) || (bytes_sent != 28))
476     {
477         printf("ERROR!\n");
478         test_control_return(1);
479     }
480 #endif
481 
482     /* Check for errors.  */
483     if ((status) || (packets_received) || (bytes_received) ||
484         (retransmit_packets) || (packets_queued) || (checksum_errors) || (socket_state != NX_TCP_CLOSED) ||
485         (transmit_queue_depth) || (transmit_window != 100) || (receive_window != 200))
486     {
487         printf("ERROR!\n");
488         test_control_return(1);
489     }
490 
491     /* Delete the socket.  */
492     status =  nx_tcp_socket_delete(&local_socket);
493 
494     /* Check for error.  */
495     if (status)
496     {
497         printf("ERROR!\n");
498         test_control_return(1);
499     }
500 
501     /* Check the NAT forwarded count.  */
502 #ifndef NX_DISABLE_NAT_INFO
503     if ((nat_server.forwarded_packets_received != 8) || (nat_server.forwarded_packets_sent != 8) ||(nat_server.forwarded_packets_dropped != 0))
504     {
505         printf("ERROR!\n");
506         test_control_return(1);
507     }
508 #endif
509 
510     /* Output success.  */
511     printf("SUCCESS!\n");
512     test_control_return(0);
513 }
514 
515 
thread_1_entry(ULONG thread_input)516 static void    thread_1_entry(ULONG thread_input)
517 {
518 
519 UINT        status;
520 NX_PACKET   *my_packet;
521 ULONG       peer_ip_address;
522 ULONG       peer_port;
523 
524 
525     /* Create a socket.  */
526     status =  nx_tcp_socket_create(&external_ip, &external_socket, "External Server Socket",
527                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
528                                    NX_NULL, NX_NULL);
529 
530     /* Check for error.  */
531     if (status)
532     {
533         printf("ERROR!\n");
534         test_control_return(1);
535     }
536 
537     /***********************************************************************/
538     /*         External Socket receives the udp packet from Local Socket   */
539     /***********************************************************************/
540 
541     /* Setup this thread to listen.  */
542     status =  nx_tcp_server_socket_listen(&external_ip, 0x89, &external_socket, 5, NX_NULL);
543 
544     /* Check for error.  */
545     if (status)
546     {
547         printf("ERROR!\n");
548         test_control_return(1);
549     }
550 
551     /* Accept a client socket connection.  */
552     status =  nx_tcp_server_socket_accept(&external_socket, NX_WAIT_FOREVER);
553 
554     /* Check for error.  */
555     if (status)
556     {
557         printf("ERROR!\n");
558         test_control_return(1);
559     }
560 
561     /* Check the peer socket port.  */
562     status = nx_tcp_socket_peer_info_get(&external_socket, &peer_ip_address, &peer_port);
563 
564     /* Check status.  */
565     if ((status) || (peer_ip_address != NX_NAT_EXTERNAL_IPADR) || (peer_port != NX_NAT_START_TCP_PORT + 1))
566     {
567         printf("ERROR!\n");
568         test_control_return(1);
569     }
570 
571     /* Receive a TCP message from the socket.  */
572     status =  nx_tcp_socket_receive(&external_socket, &my_packet, 5 * NX_IP_PERIODIC_RATE);
573 
574     /* Check for error.  */
575     if (status)
576     {
577         printf("ERROR!\n");
578         test_control_return(1);
579     }
580     else
581     {
582 
583         /* Release the packet.  */
584         nx_packet_release(my_packet);
585     }
586 
587     /* Disconnect the server socket.  */
588     status =  nx_tcp_socket_disconnect(&external_socket, 5 * NX_IP_PERIODIC_RATE);
589 
590     /* Check for error.  */
591     if (status)
592     {
593         printf("ERROR!\n");
594         test_control_return(1);
595     }
596 
597     /* Unaccept the server socket.  */
598     status =  nx_tcp_server_socket_unaccept(&external_socket);
599 
600     /* Check for error.  */
601     if (status)
602     {
603         printf("ERROR!\n");
604         test_control_return(1);
605     }
606 
607     /* Unlisten on the server port.  */
608     status =  nx_tcp_server_socket_unlisten(&external_ip, 0x89);
609 
610     /* Check for error.  */
611     if (status)
612     {
613         printf("ERROR!\n");
614         test_control_return(1);
615     }
616 
617     /* Delete the socket.  */
618     status =  nx_tcp_socket_delete(&external_socket);
619 
620     /* Check for error.  */
621     if (status)
622     {
623         printf("ERROR!\n");
624         test_control_return(1);
625     }
626 }
627 
628 #else
629 
630 #ifdef CTEST
test_application_define(void * first_unused_memory)631 VOID test_application_define(void *first_unused_memory)
632 #else
633 void    netx_nat_tcp_port_test_application_define(void *first_unused_memory)
634 #endif
635 {
636     printf("NetX Test:   NAT TCP Port Processing Test..............................N/A\n");
637     test_control_return(3);
638 }
639 #endif
640