1 /* This NetX test concentrates on the basic UDP operation.  */
2 
3 
4 #include   "tx_api.h"
5 #include   "nx_api.h"
6 #include   "nx_ip.h"
7 #include   "nx_udp.h"
8 
9 extern void  test_control_return(UINT status);
10 
11 #if !defined(NX_DISABLE_IPV4)
12 
13 #define     DEMO_STACK_SIZE         2048
14 
15 
16 /* Define the ThreadX and NetX object control blocks...  */
17 
18 static TX_THREAD               thread_0;
19 static TX_THREAD               thread_1;
20 
21 static NX_PACKET_POOL          pool_0;
22 static NX_IP                   ip_0;
23 static NX_IP                   ip_1;
24 
25 
26 static NX_UDP_SOCKET           socket_0;
27 static NX_UDP_SOCKET           socket_1;
28 
29 #ifdef FEATURE_NX_IPV6
30 static NXD_ADDRESS             address_0;
31 static NXD_ADDRESS             address_1;
32 #endif /* FEATURE_NX_IPV6 */
33 
34 
35 /* Define the counters used in the demo application...  */
36 
37 static ULONG                   thread_0_counter;
38 static ULONG                   thread_1_counter;
39 static ULONG                   error_counter;
40 static ULONG                   notify_calls =  0;
41 static ULONG                   total_packets = 2000;
42 static ULONG                   modify_packets = 0;
43 static ULONG                   invalid_packets;
44 
45 /* Define thread prototypes.  */
46 
47 static void    thread_0_entry(ULONG thread_input);
48 static void    thread_1_entry(ULONG thread_input);
49 extern void    _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
50 static void    receive_packet_function(NX_UDP_SOCKET *socket_ptr);
51 extern UINT    (*packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
52 #ifdef FEATURE_NX_IPV6
53 static UINT    my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
54 #endif /* FEATURE_NX_IPV6 */
55 static VOID    udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
56 /* Define what the initial system looks like.  */
57 
58 #ifdef CTEST
test_application_define(void * first_unused_memory)59 VOID test_application_define(void *first_unused_memory)
60 #else
61 void    netx_udp_basic_processing_test_application_define(void *first_unused_memory)
62 #endif
63 {
64 
65 CHAR    *pointer;
66 UINT    status;
67 
68 
69     /* Setup the working pointer.  */
70     pointer =  (CHAR *) first_unused_memory;
71 
72     thread_0_counter =  0;
73     thread_1_counter =  0;
74     error_counter =  0;
75     notify_calls =  0;
76     invalid_packets = 0;
77 
78     /* Create the main thread.  */
79     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
80             pointer, DEMO_STACK_SIZE,
81             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
82     pointer =  pointer + DEMO_STACK_SIZE;
83 
84     /* .  */
85     tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
86             pointer, DEMO_STACK_SIZE,
87             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
88     pointer =  pointer + DEMO_STACK_SIZE;
89 
90     /* Initialize the NetX system.  */
91     nx_system_initialize();
92 
93     /* Create a packet pool.  */
94     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 2048);
95     pointer = pointer + 2048;
96 
97     /* Check for pool creation error.  */
98     if (status)
99         error_counter++;
100 
101     /* Create an IP instance.  */
102     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver_256,
103                     pointer, 2048, 1);
104     pointer =  pointer + 2048;
105 
106     /* Create another IP instance.  */
107     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver_256,
108                     pointer, 2048, 1);
109     pointer =  pointer + 2048;
110 
111     /* Check for IP create errors.  */
112     if (status)
113         error_counter++;
114 
115     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
116     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
117     pointer = pointer + 1024;
118 
119     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
120     status +=  nx_arp_enable(&ip_1, (void *) pointer, 1024);
121     pointer = pointer + 1024;
122 
123     /* Check for ARP enable errors.  */
124     if (status)
125         error_counter++;
126 
127     /* Enable UDP traffic.  */
128     status =  nx_udp_enable(&ip_0);
129     status += nx_udp_enable(&ip_1);
130 
131 #ifdef FEATURE_NX_IPV6
132     /* Enable IPv6 traffic.  */
133     status += nxd_ipv6_enable(&ip_0);
134     status += nxd_ipv6_enable(&ip_1);
135 
136     /* Enable ICMP processing for both IP instances.  */
137     status +=  nxd_icmp_enable(&ip_0);
138     status += nxd_icmp_enable(&ip_1);
139 
140     /* Check enable status.  */
141     if (status)
142         error_counter++;
143 
144     /* Set source and destination address with global address. */
145     address_0.nxd_ip_version = NX_IP_VERSION_V6;
146     address_0.nxd_ip_address.v6[0] = 0x20010DB8;
147     address_0.nxd_ip_address.v6[1] = 0x00010001;
148     address_0.nxd_ip_address.v6[2] = 0x021122FF;
149     address_0.nxd_ip_address.v6[3] = 0xFE334456;
150 
151     address_1.nxd_ip_version = NX_IP_VERSION_V6;
152     address_1.nxd_ip_address.v6[0] = 0x20010DB8;
153     address_1.nxd_ip_address.v6[1] = 0x00010001;
154     address_1.nxd_ip_address.v6[2] = 0x021122FF;
155     address_1.nxd_ip_address.v6[3] = 0xFE334499;
156 
157     status = nxd_ipv6_address_set(&ip_0, 0, &address_0, 64, NX_NULL);
158     status = nxd_ipv6_address_set(&ip_1, 0, &address_1, 64, NX_NULL);
159 
160     total_packets = 4000;
161     packet_process_callback = NX_NULL;
162 #endif /* FEATURE_NX_IPV6 */
163 
164     /* Check for UDP enable errors.  */
165     if (status)
166         error_counter++;
167 }
168 
169 
170 
171 /* Define the test threads.  */
172 
thread_0_entry(ULONG thread_input)173 static void    thread_0_entry(ULONG thread_input)
174 {
175 
176 UINT        status;
177 NX_PACKET   *my_packet;
178 UINT        free_port;
179 ULONG       packets_sent, bytes_sent, packets_received, bytes_received, packets_queued, receive_packets_dropped, checksum_errors;
180 
181 
182     /* Print out some test information banners.  */
183     printf("NetX Test:   UDP Basic Processing Test.................................");
184 
185     /* Check for earlier error.  */
186     if (error_counter)
187     {
188 
189         printf("ERROR!\n");
190         test_control_return(1);
191     }
192 
193 #ifdef FEATURE_NX_IPV6
194     /* Sleep 5 seconds to finish DAD.  */
195     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
196 #endif /* FEATURE_NX_IPV6 */
197 
198     /* Filter UDP packet. */
199     ip_1.nx_ip_udp_packet_receive = udp_packet_receive;
200 
201     /* Let the IP threads and thread 1 execute.    */
202     tx_thread_relinquish();
203 
204     /* Create a UDP socket.  */
205     status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
206 
207     /* Check status.  */
208     if (status)
209     {
210         error_counter++;
211         test_control_return(1);
212     }
213 
214     /* Pickup the first free port for 0x88.  */
215     status =  nx_udp_free_port_find(&ip_0, 0x88, &free_port);
216 
217     /* Check status.  */
218     if ((status) || (free_port != 0x88))
219     {
220 
221         printf("ERROR!\n");
222         test_control_return(1);
223     }
224 
225     /* Bind the UDP socket to the IP port.  */
226     status =  nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
227 
228     /* Check status.  */
229     if (status)
230     {
231 
232         printf("ERROR!\n");
233         test_control_return(1);
234     }
235 
236     /* Get the port that is actually bound to this socket.  */
237     status =  nx_udp_socket_port_get(&socket_0, &free_port);
238 
239     /* Check status.  */
240     if ((status) || (free_port != 0x88))
241     {
242 
243         printf("ERROR!\n");
244         test_control_return(31);
245     }
246 
247     /* Disable checksum logic for this socket.  */
248     status =  nx_udp_socket_checksum_disable(&socket_0);
249 
250     /* Check status.  */
251     if (status)
252     {
253 
254         printf("ERROR!\n");
255         test_control_return(1);
256     }
257 
258     /* Setup the ARP entry for the UDP send.  */
259     nx_arp_dynamic_entry_set(&ip_0, IP_ADDRESS(1, 2, 3, 5), 0, 0);
260 
261     /* Let other threads run again.  */
262     tx_thread_relinquish();
263 
264     /* Send 1000 ipv4 packets without checksum.  */
265     thread_0_counter =  0;
266     while ((thread_0_counter < 1000) && (error_counter == 0))
267     {
268 
269         /* Allocate a packet.  */
270         status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
271 
272         /* Check status.  */
273         if (status != NX_SUCCESS)
274             break;
275 
276         /* Write ABCs into the packet payload!  */
277         memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
278 
279         /* Adjust the write pointer.  */
280         my_packet -> nx_packet_length =  28;
281         my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
282 
283         /* Send the UDP packet.  */
284         status =  nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
285 
286         /* Check status.  */
287         if (status)
288         {
289 
290             printf("ERROR!\n");
291             test_control_return(1);
292         }
293 
294         /* Increment thread 0's counter.  */
295         thread_0_counter++;
296 
297         /* Relinquish to thread 1 so it can pickup the message.  */
298         tx_thread_relinquish();
299     }
300 
301     /* Now, enable the checksum.  */
302     status =  nx_udp_socket_checksum_enable(&socket_0);
303 
304     /* Check status.  */
305     if (status)
306     {
307 
308         printf("ERROR!\n");
309         test_control_return(1);
310     }
311 
312     /* Send another 1000 ipv4 packets with checksum enabled.  */
313     while ((thread_0_counter < 2000) && (error_counter == 0))
314     {
315 
316         /* Allocate a packet.  */
317         status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
318 
319         /* Check status.  */
320         if (status != NX_SUCCESS)
321             break;
322 
323         /* Write ABCs into the packet payload!  */
324         memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
325 
326         /* Adjust the write pointer.  */
327         my_packet -> nx_packet_length =  28;
328         my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
329 
330         /* Send the UDP packet.  */
331         status =  nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
332 
333         /* Check status.  */
334         if (status)
335         {
336 
337             printf("ERROR!\n");
338             test_control_return(1);
339         }
340 
341         /* Increment thread 0's counter.  */
342         thread_0_counter++;
343 
344         /* Relinquish to thread 1 so it can pickup the message.  */
345         tx_thread_relinquish();
346     }
347 
348     /* Now, disable the checksum.  */
349     status =  nx_udp_socket_checksum_disable(&socket_0);
350 
351     /* Check status.  */
352     if (status)
353     {
354 
355         printf("ERROR!\n");
356         test_control_return(1);
357     }
358 
359 #ifdef FEATURE_NX_IPV6
360     packet_process_callback = my_packet_process;
361 
362     /* Send another 1000 ipv6 packets without checksum enabled.  */
363     while ((thread_0_counter < 3000) && (error_counter == 0))
364     {
365 
366         /* Allocate a packet.  */
367         status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
368 
369         /* Check status.  */
370         if (status != NX_SUCCESS)
371             break;
372 
373         /* Write ABCs into the packet payload!  */
374         memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
375 
376         /* Adjust the write pointer.  */
377         my_packet -> nx_packet_length =  28;
378         my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
379 
380         /* Send the UDP packet.  */
381         status =  nxd_udp_socket_send(&socket_0, my_packet, &address_1, 0x89);
382 
383         /* Check status.  */
384         if (status)
385         {
386 
387             printf("ERROR!\n");
388             test_control_return(1);
389         }
390 
391         /* Increment thread 0's counter.  */
392         thread_0_counter++;
393 
394         /* Relinquish to thread 1 so it can pickup the message.  */
395         tx_thread_relinquish();
396     }
397 
398     /* Now, enable the checksum.  */
399     status =  nx_udp_socket_checksum_enable(&socket_0);
400 
401     /* Check status.  */
402     if (status)
403     {
404 
405         printf("ERROR!\n");
406         test_control_return(1);
407     }
408 
409     /* Send another 1000 ipv6 packets with checksum enabled.  */
410     while ((thread_0_counter < 4000) && (error_counter == 0))
411     {
412 
413         /* Allocate a packet.  */
414         status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
415 
416         /* Check status.  */
417         if (status != NX_SUCCESS)
418             break;
419 
420         /* Write ABCs into the packet payload!  */
421         memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
422 
423         /* Adjust the write pointer.  */
424         my_packet -> nx_packet_length =  28;
425         my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
426 
427         /* Send the UDP packet.  */
428         status =  nxd_udp_socket_send(&socket_0, my_packet, &address_1, 0x89);
429 
430         /* Check status.  */
431         if (status)
432         {
433 
434             printf("ERROR!\n");
435             test_control_return(1);
436         }
437 
438         /* Increment thread 0's counter.  */
439         thread_0_counter++;
440 
441         /* Relinquish to thread 1 so it can pickup the message.  */
442         tx_thread_relinquish();
443     }
444 #endif /* FEATURE_NX_IPV6 */
445 
446     /* Get nothing from UDP socket.  */
447     status =  nx_udp_socket_info_get(&socket_0, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL);
448 
449     /* Check status.  */
450     if (status)
451     {
452 
453         printf("ERROR!\n");
454         test_control_return(1);
455     }
456 
457     /* Get UDP socket information.  */
458     status =  nx_udp_socket_info_get(&socket_0, &packets_sent, &bytes_sent, &packets_received, &bytes_received,
459                                                 &packets_queued, &receive_packets_dropped, &checksum_errors);
460 
461 #ifndef NX_DISABLE_UDP_INFO
462 
463     if ((packets_sent != total_packets) || (bytes_sent != total_packets*28))
464     {
465         error_counter++;
466     }
467 #endif
468 
469 #if defined(NX_DISABLE_UDP_RX_CHECKSUM)
470     /* Modified packets are processed as normal packets. */
471     modify_packets = 0;
472 #elif defined(NX_ENABLE_INTERFACE_CAPABILITY)
473     /* Packets with checksum error are dropped by driver directly. */
474     if(ip_0.nx_ip_interface[0].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM)
475         notify_calls += modify_packets;
476 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
477 
478     /* Check status.  */
479     if ((error_counter) || (status) || (thread_0_counter != total_packets) || (thread_1_counter != total_packets - modify_packets) ||
480         (packets_received) || (bytes_received) || (packets_queued) || (receive_packets_dropped) || (checksum_errors) || (notify_calls != total_packets))
481     {
482 
483         printf("ERROR!\n");
484         test_control_return(1);
485     }
486 
487 #ifndef NX_DISABLE_IP_INFO
488     if (invalid_packets != ip_0.nx_ip_invalid_transmit_packets)
489     {
490 
491         printf("ERROR!\n");
492         test_control_return(1);
493     }
494 #endif /* NX_DISABLE_IP_INFO */
495 
496     /* Unbind the UDP socket.  */
497     status =  nx_udp_socket_unbind(&socket_0);
498 
499     /* Check status.  */
500     if (status)
501     {
502 
503         printf("ERROR!\n");
504         test_control_return(1);
505     }
506 
507     /* Delete the UDP socket.  */
508     status =  nx_udp_socket_delete(&socket_0);
509 
510     /* Check status.  */
511     if (status)
512     {
513 
514         printf("ERROR!\n");
515         test_control_return(1);
516     }
517 
518     printf("SUCCESS!\n");
519     test_control_return(0);
520 }
521 
522 
thread_1_entry(ULONG thread_input)523 static void    thread_1_entry(ULONG thread_input)
524 {
525 
526 UINT        status;
527 NX_PACKET   *my_packet;
528 
529 
530     /* Create a UDP socket.  */
531     status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
532 
533     /* Check status.  */
534     if (status)
535     {
536         error_counter++;
537         test_control_return(1);
538     }
539 
540     /* Register the receive notify function.  */
541     status =  nx_udp_socket_receive_notify(&socket_1, receive_packet_function);
542 
543     /* Check status.  */
544     if (status)
545     {
546         error_counter++;
547         test_control_return(1);
548     }
549 
550     /* Bind the UDP socket to the IP port.  */
551     status =  nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
552 
553     /* Check status.  */
554     if (status)
555     {
556         error_counter++;
557         test_control_return(1);
558     }
559 
560     /* Get 4000 packets.  */
561     thread_1_counter =  0;
562     while (1)
563     {
564 
565         /* Receive a UDP packet.  */
566         status =  nx_udp_socket_receive(&socket_1, &my_packet, 10 * NX_IP_PERIODIC_RATE);
567 
568         /* Check status.  */
569         if (status != NX_SUCCESS)
570             break;
571 
572         /* Release the packet.  */
573         status =  nx_packet_release(my_packet);
574 
575         /* Check status.  */
576         if (status != NX_SUCCESS)
577             break;
578 
579         /* Increment thread 1's counter.  */
580         thread_1_counter++;
581     }
582 
583     /* Unbind the UDP socket.  */
584     status =  nx_udp_socket_unbind(&socket_1);
585 
586     /* Check status.  */
587     if (status)
588     {
589 
590         printf("ERROR!\n");
591         test_control_return(1);
592     }
593 
594     /* Delete the UDP socket.  */
595     status =  nx_udp_socket_delete(&socket_1);
596 
597     /* Check status.  */
598     if (status)
599     {
600 
601         printf("ERROR!\n");
602         test_control_return(1);
603     }
604 }
605 
receive_packet_function(NX_UDP_SOCKET * socket_ptr)606 static void    receive_packet_function(NX_UDP_SOCKET *socket_ptr)
607 {
608 
609     if (socket_ptr == &socket_1)
610         notify_calls++;
611 }
612 
613 
614 #ifdef FEATURE_NX_IPV6
my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)615 static UINT    my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)
616 {
617 
618     /* Check if it is a UDP packet with IPv6 header.  */
619     if ((packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
620         (*(packet_ptr -> nx_packet_prepend_ptr + 6) == NX_PROTOCOL_UDP))
621     {
622 
623         /* Yes it is a UDP packet with IPv6 header.  */
624 #ifndef NX_DISABLE_UDP_RX_CHECKSUM
625         /* Check if checksum field is 0.  */
626         if ((*(packet_ptr -> nx_packet_prepend_ptr + 46) == 0) &&
627             (*(packet_ptr -> nx_packet_prepend_ptr + 47) == 0))
628         {
629 
630             /* The checksum field is 0.  */
631             error_counter++;
632         }
633         else
634 #endif /* NX_DISABLE_UDP_RX_CHECKSUM */
635         {
636 
637             /* Modify first 1000 packets. Set checksum field to 0.  */
638             if (modify_packets < 1000)
639             {
640                 *(packet_ptr -> nx_packet_prepend_ptr + 46) = 0;
641                 *(packet_ptr -> nx_packet_prepend_ptr + 47) = 0;
642                 modify_packets++;
643             }
644         }
645     }
646 
647     return NX_TRUE;
648 }
649 #endif /* FEATURE_NX_IPV6 */
650 
651 
udp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)652 static VOID    udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
653 {
654 NX_PACKET *invalid_pkt_ptr;
655 
656     /* Send a UDP packet with no interface. */
657     if (nx_packet_copy(packet_ptr, &invalid_pkt_ptr, &pool_0, NX_NO_WAIT))
658     {
659         error_counter++;
660     }
661     else
662     {
663 
664         /* Set interface to NULL. */
665 #ifdef __PRODUCT_NETXDUO__
666         invalid_pkt_ptr -> nx_packet_address.nx_packet_interface_ptr = NX_NULL;
667         invalid_packets++;
668 
669         /* Send the packet. */
670         _nx_ip_packet_send(&ip_0, invalid_pkt_ptr, IP_ADDRESS(1, 2, 3, 5), NX_IP_NORMAL,
671                            0x80, NX_IP_UDP, NX_FRAGMENT_OKAY, IP_ADDRESS(1, 2, 3, 5));
672 #else
673         invalid_pkt_ptr -> nx_packet_ip_interface = NX_NULL;
674         invalid_packets++;
675 
676         /* Send the packet. */
677         _nx_ip_packet_send(&ip_0, invalid_pkt_ptr, IP_ADDRESS(1, 2, 3, 5), NX_IP_NORMAL,
678                            0x80, NX_IP_UDP, NX_FRAGMENT_OKAY);
679 #endif
680     }
681 
682     /* Process this packet. */
683     _nx_udp_packet_receive(ip_ptr, packet_ptr);
684 }
685 #else
686 
687 #ifdef CTEST
test_application_define(void * first_unused_memory)688 VOID test_application_define(void *first_unused_memory)
689 #else
690 void    netx_udp_basic_processing_test_application_define(void *first_unused_memory)
691 #endif
692 {
693 
694     /* Print out test information banner.  */
695     printf("NetX Test:   UDP Basic Processing Test.................................N/A\n");
696 
697     test_control_return(3);
698 }
699 #endif
700