1 /* This NetX test concentrates on the basic BSD UDP non-blocking operation.  */
2 
3 
4 #include   "tx_api.h"
5 #include   "nx_api.h"
6 #if defined(NX_BSD_ENABLE) && !defined(NX_DISABLE_IPV4)
7 #include   "nx_icmpv6.h"
8 #include   "nxd_bsd.h"
9 #define     DEMO_STACK_SIZE         4096
10 
11 
12 /* Define the ThreadX and NetX object control blocks...  */
13 
14 static TX_THREAD               ntest_0;
15 static TX_THREAD               ntest_1;
16 
17 static NX_PACKET_POOL          pool_0;
18 static NX_IP                   ip_0;
19 static NX_IP                   ip_1;
20 static NX_UDP_SOCKET           server_socket;
21 static ULONG                   bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
22 #define BSD_THREAD_PRIORITY    2
23 #define NUM_CLIENTS            20
24 /* Define the counters used in the test application...  */
25 
26 static ULONG                   error_counter;
27 
28 
29 /* Define thread prototypes.  */
30 
31 static void    ntest_0_entry(ULONG thread_input);
32 static void    ntest_1_entry(ULONG thread_input);
33 extern void    test_control_return(UINT status);
34 extern void    _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
35 static void    validate_bsd_structure(void);
36 #ifdef FEATURE_NX_IPV6
37 static NXD_ADDRESS ipv6_address_ip0;
38 static NXD_ADDRESS ipv6_address_ip1;
39 #endif /* FEATURE_NX_IPV6 */
40 static char *requests[4] = {"Request1", "Request2", "Request3", "Request4"};
41 static char *response[4] = {"Response1", "Response2", "Response3", "Response4"};
42 static void validate_bsd_structure(void);
43 /* Define what the initial system looks like.  */
44 
45 #ifdef CTEST
test_application_define(void * first_unused_memory)46 VOID test_application_define(void *first_unused_memory)
47 #else
48 void    netx_bsd_udp_basic_blocking_test_application_define(void *first_unused_memory)
49 #endif
50 {
51 
52 CHAR    *pointer;
53 UINT    status;
54 
55 
56     /* Setup the working pointer.  */
57     pointer =  (CHAR *) first_unused_memory;
58 
59     error_counter =  0;
60 
61     /* Create the main thread.  */
62     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
63                      pointer, DEMO_STACK_SIZE,
64                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
65 
66     pointer =  pointer + DEMO_STACK_SIZE;
67 
68     /* Create the main thread.  */
69     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
70                      pointer, DEMO_STACK_SIZE,
71                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
72 
73     pointer =  pointer + DEMO_STACK_SIZE;
74 
75 
76     /* Initialize the NetX system.  */
77     nx_system_initialize();
78 
79     /* Create a packet pool.  */
80     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2);
81     pointer = pointer + (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2;
82 
83     if (status)
84         error_counter++;
85 
86     /* Create an IP instance.  */
87     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
88                     pointer, 2048, 1);
89     pointer =  pointer + 2048;
90 
91     /* Create another IP instance.  */
92     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
93                     pointer, 2048, 2);
94     pointer =  pointer + 2048;
95     if (status)
96         error_counter++;
97 
98     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
99     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
100     pointer = pointer + 1024;
101     if (status)
102         error_counter++;
103 
104     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
105     status  =  nx_arp_enable(&ip_1, (void *) pointer, 1024);
106     pointer = pointer + 1024;
107     if (status)
108         error_counter++;
109 
110     /* Enable UDP processing for both IP instances.  */
111     status =  nx_udp_enable(&ip_0);
112     status += nx_udp_enable(&ip_1);
113 
114     /* Enable BSD */
115     status += bsd_initialize(&ip_0, &pool_0, (CHAR*)&bsd_thread_area[0], sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
116 
117     /* Check UDP enable and BSD init status.  */
118     if (status)
119         error_counter++;
120 }
121 
122 #ifdef FEATURE_NX_IPV6
test_udp_server6(void)123 static void test_udp_server6(void)
124 {
125 int                 sockfd;
126 struct sockaddr_in6 remote_addr, local_addr;
127 int                 ret;
128 char                buf[30];
129 int                 addrlen;
130 
131 
132     sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
133     if(sockfd < 0)
134         error_counter++;
135     memset(&local_addr, 0, sizeof(local_addr));
136     local_addr.sin6_family = AF_INET6;
137     local_addr.sin6_port = htons(12345);
138 
139 
140     ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
141     if(ret < 0)
142         error_counter++;
143 
144     /* Receive data from the client. */
145     addrlen = sizeof(remote_addr);
146     ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&remote_addr, &addrlen);
147     if(ret <= 0)
148         error_counter++;
149 
150     if(addrlen != sizeof(struct sockaddr_in6))
151         error_counter++;
152 
153     if((remote_addr.sin6_family != AF_INET6) ||
154        (remote_addr.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip1.nxd_ip_address.v6[0])) ||
155        (remote_addr.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip1.nxd_ip_address.v6[1])) ||
156        (remote_addr.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip1.nxd_ip_address.v6[2])) ||
157        (remote_addr.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip1.nxd_ip_address.v6[3])) ||
158        (remote_addr.sin6_port != htons(54321)))
159         error_counter++;
160 
161     /* Validate the data. */
162     if((ret != (INT)strlen(requests[1])) || strncmp(buf, requests[1], ret))
163         error_counter++;
164 
165     /* Send a response back. */
166     ret = sendto(sockfd, response[1], strlen(response[1]), 0, (struct sockaddr*)&remote_addr, addrlen);
167     if(ret != (INT)strlen(response[1]))
168         error_counter++;
169 
170 
171     /* Close downt he socket. */
172     ret = soc_close(sockfd);
173     if(ret < 0)
174         error_counter++;
175 
176 }
177 #endif /* FEATURE_NX_IPV6 */
178 
test_udp_server4(void)179 static void test_udp_server4(void)
180 {
181 int                sockfd;
182 struct sockaddr_in remote_addr, local_addr;
183 int                ret;
184 char               buf[30];
185 int                addrlen;
186 
187 
188     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
189     if(sockfd < 0)
190         error_counter++;
191 
192     local_addr.sin_family = AF_INET;
193     local_addr.sin_port = htons(12345);
194     local_addr.sin_addr.s_addr = INADDR_ANY;
195 
196     ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
197     if(ret < 0)
198         error_counter++;
199 
200     /* Receive data from the client. */
201     addrlen = sizeof(remote_addr);
202     ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&remote_addr, &addrlen);
203     if(ret <= 0)
204         error_counter++;
205 
206     if(addrlen != sizeof(struct sockaddr_in))
207         error_counter++;
208 
209     if((remote_addr.sin_family != AF_INET) ||
210        (remote_addr.sin_addr.s_addr != htonl(IP_ADDRESS(1,2,3,5))) ||
211        (remote_addr.sin_port != htons(54321)))
212         error_counter++;
213 
214     /* Validate the data. */
215     if((ret != (int)strlen(requests[0])) || strncmp(buf, requests[0], ret))
216         error_counter++;
217 
218     /* Send a response back. */
219     ret = sendto(sockfd, response[0], strlen(response[0]), 0, (struct sockaddr*)&remote_addr, addrlen);
220     if(ret != (int)strlen(response[0]))
221         error_counter++;
222 
223 
224     /* Close downt he socket. */
225     ret = soc_close(sockfd);
226     if(ret < 0)
227         error_counter++;
228 
229 }
230 
231 
232 
233 /* Define the test threads.  */
ntest_0_entry(ULONG thread_input)234 static void    ntest_0_entry(ULONG thread_input)
235 {
236 #ifdef FEATURE_NX_IPV6
237 char mac_ip0[6];
238 char mac_ip1[6];
239 UINT status;
240 #endif
241 
242 
243     printf("NetX Test:   Basic BSD UDP Blocking Test...................");
244 
245     /* Check for earlier error.  */
246     if (error_counter)
247     {
248 
249         printf("ERROR!\n");
250         test_control_return(1);
251     }
252 
253 #ifdef FEATURE_NX_IPV6
254     /* First set up IPv6 addresses. */
255     ipv6_address_ip0.nxd_ip_version = NX_IP_VERSION_V6;
256     ipv6_address_ip0.nxd_ip_address.v6[0] = 0xfe800000;
257     ipv6_address_ip0.nxd_ip_address.v6[1] = 0x00000000;
258     ipv6_address_ip0.nxd_ip_address.v6[2] = 0x021122ff;
259     ipv6_address_ip0.nxd_ip_address.v6[3] = 0xfe334456;
260 
261     ipv6_address_ip1.nxd_ip_version = NX_IP_VERSION_V6;
262     ipv6_address_ip1.nxd_ip_address.v6[0] = 0xfe800000;
263     ipv6_address_ip1.nxd_ip_address.v6[1] = 0x00000000;
264     ipv6_address_ip1.nxd_ip_address.v6[2] = 0x021122ff;
265     ipv6_address_ip1.nxd_ip_address.v6[3] = 0xfe334457;
266 
267     status = nxd_ipv6_address_set(&ip_0, 0, &ipv6_address_ip0, 64, NX_NULL);
268     status += nxd_ipv6_address_set(&ip_1, 0, &ipv6_address_ip1, 64, NX_NULL);
269 
270     status += nxd_ipv6_enable(&ip_0);
271     status += nxd_ipv6_enable(&ip_1);
272 
273     mac_ip0[0] = (char)(ip_0.nx_ip_interface[0].nx_interface_physical_address_msw >> 8);
274     mac_ip0[1] = ip_0.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
275     mac_ip0[2] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
276     mac_ip0[3] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
277     mac_ip0[4] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
278     mac_ip0[5] = ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
279 
280     mac_ip1[0] = (char)(ip_1.nx_ip_interface[0].nx_interface_physical_address_msw >> 8);
281     mac_ip1[1] = ip_1.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
282     mac_ip1[2] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
283     mac_ip1[3] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
284     mac_ip1[4] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
285     mac_ip1[5] = ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
286 
287     status += nxd_nd_cache_entry_set(&ip_0, ipv6_address_ip1.nxd_ip_address.v6, 0,  mac_ip1);
288     status += nxd_nd_cache_entry_set(&ip_1, ipv6_address_ip0.nxd_ip_address.v6, 0,  mac_ip0);
289 
290     if(status)
291         error_counter++;
292 #endif
293     test_udp_server4();
294 
295     tx_thread_sleep(3);
296 
297 #ifdef FEATURE_NX_IPV6
298     test_udp_server6();
299 #endif
300 
301 
302     tx_thread_sleep(1);
303 
304     validate_bsd_structure();
305 
306     if(error_counter)
307         printf("ERROR!\n");
308     else
309         printf("SUCCESS!\n");
310 
311     if(error_counter)
312         test_control_return(1);
313 
314     test_control_return(0);
315 }
316 
ntest_1_entry(ULONG thread_input)317 static void    ntest_1_entry(ULONG thread_input)
318 {
319 
320 UINT            status;
321 NX_PACKET       *packet_ptr;
322 ULONG           actual_status;
323 
324 
325 
326     /* Ensure the IP instance has been initialized.  */
327     status =  nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, 1 * NX_IP_PERIODIC_RATE);
328 
329     /* Check status...  */
330     if (status != NX_SUCCESS)
331     {
332 
333         printf("ERROR!\n");
334         test_control_return(3);
335     }
336 
337     /* Create a socket.  */
338     status =  nx_udp_socket_create(&ip_1, &server_socket, "Server Socket",
339                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 10);
340 
341     /* Check for error.  */
342     if (status)
343         error_counter++;
344 
345     /* Allocate a packet. */
346     status = nx_packet_allocate(&pool_0, &packet_ptr, NX_UDP_PACKET, NX_WAIT_FOREVER);
347     if (status)
348         error_counter++;
349 
350     /* Fill in the packet with data */
351     memcpy(packet_ptr -> nx_packet_prepend_ptr, requests[0], strlen(requests[0]));
352 
353     packet_ptr -> nx_packet_length = strlen(requests[0]);
354     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
355 
356     /* Bind to a UDP port. */
357     status = nx_udp_socket_bind(&server_socket, 54321, NX_WAIT_FOREVER);
358     if(status)
359         error_counter++;
360 
361     /* Send a UDP packet */
362     status =  nx_udp_socket_send(&server_socket, packet_ptr, IP_ADDRESS(1,2,3,4), 12345);
363     if(status)
364         error_counter++;
365 
366     /* Ready to reaceive a message */
367     status = nx_udp_socket_receive(&server_socket, &packet_ptr, NX_WAIT_FOREVER);
368     if(status)
369         error_counter++;
370 
371     /* Validate the content. */
372     if(packet_ptr -> nx_packet_length != strlen(response[0]))
373         error_counter++;
374     else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[0], strlen(response[0])))
375         error_counter++;
376 
377 
378     status = nx_udp_socket_unbind(&server_socket);
379     if(status)
380         error_counter++;
381 
382     status = nx_udp_socket_delete(&server_socket);
383     if(status)
384         error_counter++;
385 
386 #ifdef FEATURE_NX_IPV6
387     tx_thread_sleep(3);
388 
389 
390     /* Create a socket.  */
391     status =  nx_udp_socket_create(&ip_1, &server_socket, "Server Socket",
392                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 10);
393 
394     /* Check for error.  */
395     if (status)
396         error_counter++;
397 
398     /* Allocate a packet. */
399     status = nx_packet_allocate(&pool_0, &packet_ptr, NX_UDP_PACKET, NX_WAIT_FOREVER);
400     if (status)
401         error_counter++;
402 
403     /* Fill in the packet with data */
404     memcpy(packet_ptr -> nx_packet_prepend_ptr, requests[1], strlen(requests[1]));
405 
406     packet_ptr -> nx_packet_length = strlen(requests[1]);
407     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
408 
409     /* Bind to a UDP port. */
410     status = nx_udp_socket_bind(&server_socket, 54321, NX_WAIT_FOREVER);
411     if(status)
412         error_counter++;
413 
414     /* Send a UDP packet */
415     status =  nxd_udp_socket_send(&server_socket, packet_ptr, &ipv6_address_ip0, 12345);
416     if(status)
417         error_counter++;
418 
419     error_counter++;
420     /* Ready to reaceive a message */
421     status = nx_udp_socket_receive(&server_socket, &packet_ptr, NX_WAIT_FOREVER);
422     if(status)
423         error_counter++;
424 
425     /* Validate the content. */
426     if(packet_ptr -> nx_packet_length != strlen(response[1]))
427         error_counter++;
428     else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[1], strlen(response[1])))
429         error_counter++;
430     else
431         error_counter--;
432 
433     status = nx_udp_socket_unbind(&server_socket);
434     if(status)
435         error_counter++;
436 
437     status = nx_udp_socket_delete(&server_socket);
438     if(status)
439         error_counter++;
440 
441 #endif
442 
443 }
444 
445 extern NX_BSD_SOCKET  nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
446 extern TX_BLOCK_POOL nx_bsd_socket_block_pool;
validate_bsd_structure(void)447 static void validate_bsd_structure(void)
448 {
449 int i;
450     /* Make sure every BSD socket should be free by now. */
451 
452     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
453     {
454         if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)
455         {
456             error_counter++;
457         }
458 
459         if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket ||
460            nx_bsd_socket_array[i].nx_bsd_socket_udp_socket)
461         {
462             error_counter++;
463         }
464     }
465 
466     /* Make sure all the NX SOCKET control blocks are released. */
467     if(nx_bsd_socket_block_pool.tx_block_pool_available !=
468        nx_bsd_socket_block_pool.tx_block_pool_total)
469     {
470         error_counter++;
471     }
472 
473     /* Make sure all the sockets are released */
474     if(ip_0.nx_ip_tcp_created_sockets_ptr ||
475        ip_0.nx_ip_udp_created_sockets_ptr)
476     {
477         error_counter++;
478         return;
479     }
480 }
481 
482 #else
483 extern void       test_control_return(UINT status);
484 
485 #ifdef CTEST
test_application_define(void * first_unused_memory)486 VOID test_application_define(void *first_unused_memory)
487 #else
488 void    netx_bsd_udp_basic_blocking_test_application_define(void *first_unused_memory)
489 #endif
490 {
491 
492     /* Print out test information banner.  */
493     printf("NetX Test:   Basic BSD UDP Blocking Test...................N/A\n");
494 
495     test_control_return(3);
496 }
497 #endif
498