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