1 /* This NetX test concentrates on the raw packet IP send/receive operation.  */
2 
3 #include   "tx_api.h"
4 #include   "nx_api.h"
5 #include   "nx_tcp.h"
6 #include   "nx_udp.h"
7 
8 extern void    test_control_return(UINT status);
9 
10 #if !defined(NX_DISABLE_IPV4)
11 
12 #define     DEMO_STACK_SIZE         2048
13 
14 
15 /* Define the ThreadX and NetX object control blocks...  */
16 
17 static TX_THREAD               ntest_0;
18 
19 static NX_PACKET_POOL          pool_0;
20 static NX_IP                   ip_0;
21 static NX_IP                   ip_1;
22 
23 
24 /* Define the counters used in the test application...  */
25 
26 static ULONG                   error_counter;
27 static CHAR                   *ip_0_memory_ptr;
28 static CHAR                   *ip_1_memory_ptr;
29 static CHAR                   *arp_0_memory_ptr;
30 static CHAR                   *arp_1_memory_ptr;
31 static NX_TCP_SOCKET           tcp_server_socket;
32 static NX_TCP_SOCKET           tcp_client_socket;
33 static NX_UDP_SOCKET           udp_server_socket;
34 static NX_UDP_SOCKET           udp_client_socket;
35 
36 
37 /* Define thread prototypes.  */
38 
39 static void    ntest_0_entry(ULONG thread_input);
40 extern void    _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
41 
42 
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_ip_raw_packet_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     ip_0_memory_ptr =  NX_NULL;
61     ip_1_memory_ptr =  NX_NULL;
62     arp_0_memory_ptr =  NX_NULL;
63     arp_1_memory_ptr =  NX_NULL;
64 
65     /* Create the main thread.  */
66     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
67             pointer, DEMO_STACK_SIZE,
68             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
69     pointer =  pointer + DEMO_STACK_SIZE;
70 
71     /* Initialize the NetX system.  */
72     nx_system_initialize();
73 
74     /* Create a packet pool.  */
75     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 512, pointer, 8192);
76     pointer = pointer + 8192;
77 
78     if (status)
79         error_counter++;
80 
81     /* Create IP instances.  */
82     ip_0_memory_ptr =  pointer;
83     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 9), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
84                     pointer, 2048, 1);
85     pointer =  pointer + 2048;
86     ip_1_memory_ptr =  pointer;
87     status = nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 10), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
88                     pointer, 2048, 1);
89     pointer =  pointer + 2048;
90 
91     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
92     arp_0_memory_ptr =  pointer;
93     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
94     pointer = pointer + 1024;
95     arp_1_memory_ptr =  pointer;
96     status +=  nx_arp_enable(&ip_1, (void *) pointer, 1024);
97     pointer = pointer + 1024;
98     if (status)
99         error_counter++;
100 }
101 
102 
103 #ifndef NX_DISABLE_FRAGMENTATION
104 static UCHAR buff[256];
105 #endif /* NX_DISABLE_FRAGMENTATION */
106 
107 /* Define the test threads.  */
108 
ntest_0_entry(ULONG thread_input)109 static void    ntest_0_entry(ULONG thread_input)
110 {
111 
112 UINT        status;
113 ULONG       ip_address;
114 ULONG       mask;
115 ULONG       value;
116 ULONG       ip_total_packets_sent;
117 ULONG       ip_total_bytes_sent;
118 ULONG       ip_total_packets_received;
119 ULONG       ip_total_bytes_received;
120 ULONG       ip_invalid_packets;
121 ULONG       ip_receive_packets_dropped;
122 ULONG       ip_receive_checksum_errors;
123 ULONG       ip_send_packets_dropped;
124 ULONG       ip_total_fragments_sent;
125 ULONG       ip_total_fragments_received;
126 NX_PACKET   *my_packet;
127 
128 
129     /* Print out test information banner.  */
130     printf("NetX Test:   IP Raw Packet Test........................................");
131 
132     /* Check for earlier error.  */
133     if (error_counter)
134     {
135 
136         printf("ERROR!\n");
137         test_control_return(1);
138     }
139 
140     /* Pickup the IP address.  */
141     status =  nx_ip_address_get(&ip_0, &ip_address, &mask);
142 
143     /* Check for an error.  */
144     if ((status) || (ip_address != IP_ADDRESS(1, 2, 3, 9)))
145     {
146 
147         printf("ERROR!\n");
148         test_control_return(1);
149     }
150 
151     /* Set the IP address.  */
152     status =  nx_ip_address_set(&ip_0, IP_ADDRESS(1, 2, 3, 13), 0xFFFFFF00UL);
153     status += nx_ip_address_get(&ip_0, &ip_address, &mask);
154 
155     /* Check for an error.  */
156     if ((status) || (ip_address != IP_ADDRESS(1, 2, 3, 13)))
157     {
158 
159         printf("ERROR!\n");
160         test_control_return(1);
161     }
162 
163     /* Delete both IP instances.  */
164     status =  nx_ip_delete(&ip_0);
165     status += nx_ip_delete(&ip_1);
166 
167     /* Check for an error.  */
168     if (status)
169     {
170 
171         printf("ERROR!\n");
172         test_control_return(1);
173     }
174 
175     /* Create IP instances.  */
176     status =  nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
177                     ip_0_memory_ptr, 2048, 1);
178     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
179                     ip_1_memory_ptr, 2048, 1);
180     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
181     status +=  nx_arp_enable(&ip_0, (void *) arp_0_memory_ptr, 1024);
182     status +=  nx_arp_enable(&ip_1, (void *) arp_1_memory_ptr, 1024);
183 
184     /* Enable TCP for IP instances. */
185     status += nx_tcp_enable(&ip_0);
186     status += nx_tcp_enable(&ip_1);
187 
188     /* Enable UDP for IP instances. */
189     status += nx_udp_enable(&ip_0);
190     status += nx_udp_enable(&ip_1);
191 
192     /* Check the status of the IP instances.  */
193     status +=  nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &value, NX_IP_PERIODIC_RATE);
194 
195     /* Check for an error.  */
196     if ((status) || (value != NX_IP_INITIALIZE_DONE))
197     {
198 
199         printf("ERROR!\n");
200         test_control_return(1);
201     }
202 
203     /* Call driver directly.  */
204     status =  nx_ip_driver_direct_command(&ip_0, NX_LINK_GET_STATUS, &value);
205 
206     /* Check for an error.  */
207     if (status)
208     {
209 
210         printf("ERROR!\n");
211         test_control_return(1);
212     }
213 
214     /* Enable and disable forwarding.  */
215     status =  nx_ip_forwarding_enable(&ip_0);
216     status += nx_ip_forwarding_disable(&ip_0);
217 
218     /* Check for an error.  */
219     if (status)
220     {
221 
222         printf("ERROR!\n");
223         test_control_return(1);
224     }
225 
226 #ifndef NX_DISABLE_FRAGMENTATION
227     /* Enable and disable fragmenting.  */
228     status =  nx_ip_fragment_enable(&ip_0);
229     status += nx_ip_fragment_disable(&ip_0);
230     status +=  nx_ip_fragment_enable(&ip_0);
231     status += nx_ip_fragment_enable(&ip_1);
232     status += nx_ip_fragment_disable(&ip_1);
233     status += nx_ip_fragment_enable(&ip_1);
234 
235     /* Check for an error.  */
236     if (status)
237     {
238 
239         printf("ERROR!\n");
240         test_control_return(1);
241     }
242 #endif
243 
244     /* Set the gateway address.  */
245     status =  nx_ip_gateway_address_set(&ip_0, IP_ADDRESS(1, 2, 3, 87));
246 
247     /* Check for an error.  */
248     if (status)
249     {
250 
251         printf("ERROR!\n");
252         test_control_return(1);
253     }
254 
255     /* Get IP info.  */
256     status =  nx_ip_info_get(&ip_0, &ip_total_packets_sent,
257                                     &ip_total_bytes_sent,
258                                     &ip_total_packets_received,
259                                     &ip_total_bytes_received,
260                                     &ip_invalid_packets,
261                                     &ip_receive_packets_dropped,
262                                     &ip_receive_checksum_errors,
263                                     &ip_send_packets_dropped,
264                                     &ip_total_fragments_sent,
265                                     &ip_total_fragments_received);
266 
267     /* Check status.  */
268     if ((status) || (ip_total_packets_sent) || (ip_total_bytes_sent) || (ip_total_packets_received) ||
269         (ip_total_bytes_received) || (ip_invalid_packets) || (ip_receive_packets_dropped) || (ip_receive_checksum_errors) ||
270         (ip_send_packets_dropped) || (ip_total_fragments_sent) || (ip_total_fragments_received))
271     {
272 
273         printf("ERROR!\n");
274         test_control_return(1);
275     }
276 
277     /* Enable raw IP packet sending and receiving. This can only be done between two NetX nodes.  */
278     status =  nx_ip_raw_packet_enable(&ip_0);
279     status += nx_ip_raw_packet_enable(&ip_1);
280 
281 #ifndef NX_DISABLE_FRAGMENTATION
282     /* Allocate a packet.  */
283     status +=  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
284 
285     /* Write ABCs into the packet payload!  */
286     status += nx_packet_data_append(my_packet, buff, sizeof(buff), &pool_0, NX_WAIT_FOREVER);
287 
288     /* Check status.  */
289     if (status != NX_SUCCESS)
290     {
291 
292         printf("ERROR!\n");
293         test_control_return(1);
294     }
295 
296     /* Send the raw IP packet.  */
297     status =  nx_ip_raw_packet_send(&ip_0, my_packet, IP_ADDRESS(1, 2, 3, 5), NX_IP_NORMAL);
298 
299     /* Check status.  */
300     if (status != NX_SUCCESS)
301     {
302 
303         printf("ERROR!\n");
304         test_control_return(1);
305     }
306 #endif /* NX_DISABLE_FRAGMENTATION */
307 
308     /* Allocate another packet.  */
309     status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
310 
311     /* Check status.  */
312     if (status != NX_SUCCESS)
313     {
314 
315         printf("ERROR!\n");
316         test_control_return(1);
317     }
318 
319     /* Write ABCs into the packet payload!  */
320     memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
321 
322     /* Adjust the write pointer.  */
323     my_packet -> nx_packet_length =  28;
324     my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
325 
326 #ifdef __PRODUCT_NETXDUO__
327     /* Send the second raw IP packet.  */
328     status =  nx_ip_raw_packet_source_send(&ip_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0, NX_IP_NORMAL);
329 #else
330     status =  nx_ip_raw_packet_send(&ip_0, my_packet, IP_ADDRESS(1, 2, 3, 5), NX_IP_NORMAL);
331 #endif /* __PRODUCT_NETXDUO__ */
332 
333     /* Check status.  */
334     if (status != NX_SUCCESS)
335     {
336 
337         printf("ERROR!\n");
338         test_control_return(1);
339     }
340 
341     /* Allocate another packet.  */
342     status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
343 
344     /* Check status.  */
345     if (status != NX_SUCCESS)
346     {
347 
348         printf("ERROR!\n");
349         test_control_return(1);
350     }
351 
352     /* Write ABCs into the packet payload!  */
353     memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
354 
355     /* Adjust the write pointer.  */
356     my_packet -> nx_packet_length =  28;
357     my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
358 
359     /* Send the third raw IP packet.  */
360     status =  nx_ip_raw_packet_send(&ip_0, my_packet, IP_ADDRESS(1, 2, 3, 5), NX_IP_NORMAL);
361 
362     /* Check status.  */
363     if (status != NX_SUCCESS)
364     {
365 
366         printf("ERROR!\n");
367         test_control_return(1);
368     }
369 
370 #ifndef NX_DISABLE_FRAGMENTATION
371     /* Now, pickup the three raw packets that should be queued on the other IP instance.  */
372     status =  nx_ip_raw_packet_receive(&ip_1, &my_packet, NX_IP_PERIODIC_RATE);
373     status += nx_packet_release(my_packet);
374     /* Check status.  */
375     if (status != NX_SUCCESS)
376     {
377 
378         printf("ERROR!\n");
379         test_control_return(1);
380     }
381 #endif /* NX_DISABLE_FRAGMENTATION */
382 
383     /* Receive the second packet.  */
384     status =  nx_ip_raw_packet_receive(&ip_1, &my_packet, NX_IP_PERIODIC_RATE);
385     status += nx_packet_release(my_packet);
386     /* Check status.  */
387     if (status != NX_SUCCESS)
388     {
389 
390         printf("ERROR!\n");
391         test_control_return(1);
392     }
393 
394     /* Receive the third packet.  */
395     status =  nx_ip_raw_packet_receive(&ip_1, &my_packet, NX_IP_PERIODIC_RATE);
396     status += nx_packet_release(my_packet);
397     /* Check status.  */
398     if (status != NX_SUCCESS)
399     {
400 
401         printf("ERROR!\n");
402         test_control_return(1);
403     }
404 
405     /* Attempt to receive a packet on an empty queue.... should be an error.  */
406     status =  nx_ip_raw_packet_receive(&ip_1, &my_packet, NX_NO_WAIT);
407 
408     /* Check status.  */
409     if (status != NX_NO_PACKET)
410     {
411 
412         printf("ERROR!\n");
413         test_control_return(1);
414     }
415 
416     /* Check TCP connection when raw packet is enabled. */
417     /* Create a server socket.  */
418     status = nx_tcp_socket_create(&ip_1, &tcp_server_socket, "Server Socket",
419                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
420                                   NX_NULL, NX_NULL);
421 
422     /* Setup this thread to listen.  */
423     status += nx_tcp_server_socket_listen(&ip_1, 12, &tcp_server_socket, 5, NX_NULL);
424 
425     /* Create a client socket.  */
426     status += nx_tcp_socket_create(&ip_0, &tcp_client_socket, "Client Socket",
427                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 300,
428                                    NX_NULL, NX_NULL);
429 
430     /* Bind the socket.  */
431     status += nx_tcp_client_socket_bind(&tcp_client_socket, 12, NX_WAIT_FOREVER);
432 
433     /* Connect to server. */
434     nx_tcp_client_socket_connect(&tcp_client_socket, IP_ADDRESS(1, 2, 3, 5), 12, NX_NO_WAIT);
435 
436     /* If accept return successfully, then it handles an illegal option length for MSS.  */
437     status += nx_tcp_server_socket_accept(&tcp_server_socket, NX_IP_PERIODIC_RATE);
438 
439     /* Check if client is in establish state. */
440     status += nx_tcp_socket_state_wait(&tcp_client_socket, NX_TCP_ESTABLISHED, NX_NO_WAIT);
441 
442     /* Check status.  */
443     if (status)
444     {
445 
446         printf("ERROR!\n");
447         test_control_return(1);
448     }
449 
450     /* Allocate a packet.  */
451     status =  nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, 5 * NX_IP_PERIODIC_RATE);
452 
453     /* Append data. */
454     status += nx_packet_data_append(my_packet, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28, &pool_0, NX_NO_WAIT);
455 
456     /* Send a packet from server to client. */
457     status += nx_tcp_socket_send(&tcp_server_socket, my_packet, NX_NO_WAIT);
458 
459     /* Receive packet from server. */
460     status += nx_tcp_socket_receive(&tcp_client_socket, &my_packet, 5 * NX_IP_PERIODIC_RATE);
461 
462     /* Check status and received data. */
463     if(status || memcmp(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28))
464         status++;
465 
466     /* Release packet. */
467     status += nx_packet_release(my_packet);
468 
469     /* Disconnect. */
470     nx_tcp_socket_disconnect(&tcp_server_socket, NX_NO_WAIT);
471     nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT);
472     nx_tcp_server_socket_unaccept(&tcp_server_socket);
473 
474     /* Check if both sockets are closed. */
475     status += nx_tcp_socket_state_wait(&tcp_client_socket, NX_TCP_CLOSED, NX_NO_WAIT);
476     status += nx_tcp_socket_state_wait(&tcp_client_socket, NX_TCP_CLOSED, NX_NO_WAIT);
477 
478     /* Check status.  */
479     if (status)
480     {
481 
482         printf("ERROR!\n");
483         test_control_return(1);
484     }
485 
486     /* Check UDP connection when raw packet is enabled. */
487     /* Create two UDP sockets.  */
488     status = nx_udp_socket_create(&ip_0, &udp_client_socket, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
489     status += nx_udp_socket_create(&ip_1, &udp_server_socket, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
490 
491     /* Bind the UDP socket to the IP port.  */
492     status +=  nx_udp_socket_bind(&udp_client_socket, 0x89, NX_NO_WAIT);
493     status +=  nx_udp_socket_bind(&udp_server_socket, 0x89, NX_NO_WAIT);
494 
495     /* Allocate a packet.  */
496     status +=  nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, 5 * NX_IP_PERIODIC_RATE);
497 
498     /* Append data. */
499     status += nx_packet_data_append(my_packet, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28, &pool_0, NX_NO_WAIT);
500 
501     /* Send the UDP packet.  */
502     status +=  nx_udp_socket_send(&udp_client_socket, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
503 
504     /* Receive a UDP packet.  */
505     status +=  nx_udp_socket_receive(&udp_server_socket, &my_packet, 5 * NX_IP_PERIODIC_RATE);
506 
507     /* Check status and received data. */
508     if(status || memcmp(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28))
509         status++;
510 
511     /* Unbind the UDP socket.  */
512     status +=  nx_udp_socket_unbind(&udp_client_socket);
513     status +=  nx_udp_socket_unbind(&udp_server_socket);
514 
515     /* Check status.  */
516     if (status)
517     {
518 
519         printf("ERROR!\n");
520         test_control_return(1);
521     }
522 
523 
524     /* Disable the raw IP capability on both IP instances.  */
525     status =  nx_ip_raw_packet_disable(&ip_0);
526     status += nx_ip_raw_packet_disable(&ip_1);
527 
528     /* Check status.  */
529     if (status)
530     {
531 
532         printf("ERROR!\n");
533         test_control_return(1);
534     }
535     else
536     {
537 
538         printf("SUCCESS!\n");
539         test_control_return(0);
540     }
541 }
542 #else
543 
544 #ifdef CTEST
test_application_define(void * first_unused_memory)545 VOID test_application_define(void *first_unused_memory)
546 #else
547 void    netx_ip_raw_packet_test_application_define(void *first_unused_memory)
548 #endif
549 {
550 
551     /* Print out test information banner.  */
552     printf("NetX Test:   IP Raw Packet Test........................................N/A\n");
553 
554     test_control_return(3);
555 }
556 #endif
557 
558