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