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