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