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