1 /* This is a small demo of the high-performance NetX Duo TCP/IP stack.  This program demonstrates
2    ICMPv6 protocols Neighbor Discovery and Stateless Address Configuration for IPv6, ARP for IPv4, and
3    UDP packet sending and receiving with a simulated Ethernet driver.  */
4 
5 #include   "tx_api.h"
6 #include   "nx_api.h"
7 
8 #define     DEMO_STACK_SIZE 2048
9 #define     DEMO_DATA       "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
10 #define     PACKET_SIZE     1536
11 #define     POOL_SIZE       ((sizeof(NX_PACKET) + PACKET_SIZE) * 16)
12 
13 
14 /* Define the ThreadX and NetX object control blocks...  */
15 
16 TX_THREAD               thread_0;
17 TX_THREAD               thread_1;
18 
19 NX_PACKET_POOL          pool_0;
20 NX_IP                   ip_0;
21 NX_IP                   ip_1;
22 
23 
24 NX_UDP_SOCKET           socket_0;
25 NX_UDP_SOCKET           socket_1;
26 UCHAR                   pool_buffer[POOL_SIZE];
27 
28 
29 /* Define the counters used in the demo application...  */
30 
31 ULONG thread_0_counter;
32 ULONG thread_1_counter;
33 ULONG error_counter;
34 
35 /* Define thread prototypes.  */
36 
37 void thread_0_entry(ULONG thread_input);
38 void thread_1_entry(ULONG thread_input);
39 void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
40 
41 
42 /* Define main entry point.  */
43 
main()44 int main()
45 {
46 
47     /* Enter the ThreadX kernel.  */
48     tx_kernel_enter();
49 }
50 
51 
52 /* Define what the initial system looks like.  */
53 
tx_application_define(void * first_unused_memory)54 void    tx_application_define(void *first_unused_memory)
55 {
56 
57 CHAR *pointer;
58 UINT  status;
59 
60 #ifndef NX_DISABLE_IPV6
61 NXD_ADDRESS ip_address;
62 #endif
63     /* Setup the working pointer.  */
64     pointer =  (CHAR *)first_unused_memory;
65 
66     /* Create the main thread.  */
67     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
68                      pointer, DEMO_STACK_SIZE,
69                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
70     pointer =  pointer + DEMO_STACK_SIZE;
71 
72     /* .  */
73     tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
74                      pointer, DEMO_STACK_SIZE,
75                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
76     pointer =  pointer + DEMO_STACK_SIZE;
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", PACKET_SIZE, pool_buffer, POOL_SIZE);
83 
84     /* Check for pool creation error.  */
85     if (status)
86     {
87         error_counter++;
88     }
89 
90     /* Create an IP instance.  */
91     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver,
92                           pointer, 2048, 1);
93     pointer =  pointer + 2048;
94 
95     /* Create another IP instance.  */
96     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver,
97                            pointer, 2048, 1);
98     pointer =  pointer + 2048;
99 
100     /* Check for IP create errors.  */
101     if (status)
102     {
103         error_counter++;
104     }
105 
106 #ifndef NX_DISABLE_IPV4
107     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
108     status =  nx_arp_enable(&ip_0, (void *)pointer, 1024);
109     pointer = pointer + 1024;
110 
111     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
112     status +=  nx_arp_enable(&ip_1, (void *)pointer, 1024);
113     pointer = pointer + 1024;
114 
115     /* Check for ARP enable errors.  */
116     if (status)
117     {
118         error_counter++;
119     }
120 #endif /* NX_DISABLE_IPV4 */
121 
122 #ifndef NX_DISABLE_IPV6
123 
124     /* Enable IPv6 */
125     status = nxd_ipv6_enable(&ip_0);
126     if (status)
127     {
128         error_counter++;
129     }
130 
131     status = nxd_ipv6_enable(&ip_1);
132     if (status)
133     {
134         error_counter++;
135     }
136 #endif
137 
138     /* Enable ICMP */
139     status = nxd_icmp_enable(&ip_0);
140     if (status)
141     {
142         error_counter++;
143     }
144 
145     status = nxd_icmp_enable(&ip_1);
146     if (status)
147     {
148         error_counter++;
149     }
150 
151     /* Enable UDP traffic.  */
152     status =  nx_udp_enable(&ip_0);
153     status += nx_udp_enable(&ip_1);
154 
155     /* Check for UDP enable errors.  */
156     if (status)
157     {
158         error_counter++;
159     }
160 #ifndef NX_DISABLE_IPV6
161 
162     /* Set ip_0 global address address. */
163     ip_address.nxd_ip_version = NX_IP_VERSION_V6;
164     ip_address.nxd_ip_address.v6[0] = 0x20010000;
165     ip_address.nxd_ip_address.v6[1] = 0;
166     ip_address.nxd_ip_address.v6[2] = 0;
167     ip_address.nxd_ip_address.v6[3] = 1;
168     if (status)
169     {
170         error_counter++;
171     }
172 
173     status = nxd_ipv6_global_address_set(&ip_0, &ip_address, 64);
174 
175     /* Check for errors */
176     if (status)
177     {
178         error_counter++;
179     }
180 
181     /* Set ip_1 global address address. */
182     ip_address.nxd_ip_version = NX_IP_VERSION_V6;
183     ip_address.nxd_ip_address.v6[0] = 0x20010000;
184     ip_address.nxd_ip_address.v6[1] = 0;
185     ip_address.nxd_ip_address.v6[2] = 0;
186     ip_address.nxd_ip_address.v6[3] = 2;
187 
188     status = nxd_ipv6_global_address_set(&ip_1, &ip_address, 64);
189 
190     /* Check for errors */
191     if (status)
192     {
193         error_counter++;
194     }
195 
196     /* Note we are not setting the link local address. The ram driver
197        does not use physical addresses so it is unnecessary. Consult the
198        NetX Duo User Guide for setting the link local address. */
199 #endif
200 }
201 
202 
203 
204 /* Define the test threads.  */
205 
thread_0_entry(ULONG thread_input)206 void    thread_0_entry(ULONG thread_input)
207 {
208 
209 UINT       status;
210 NX_PACKET *my_packet;
211 
212 #ifndef NX_DISABLE_IPV4
213 NXD_ADDRESS ipv4_address;
214 #endif /* NX_DISABLE_IPV4 */
215 #ifndef NX_DISABLE_IPV6
216 NXD_ADDRESS ipv6_address;
217 #endif
218 
219     NX_PARAMETER_NOT_USED(thread_input);
220 
221     /* Let the IP threads and thread 1 execute.    */
222     tx_thread_sleep(NX_IP_PERIODIC_RATE);
223 
224 #ifndef NX_DISABLE_IPV6
225 
226     /* Wait for IPv6 stack to finish DAD process. */
227     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
228 #endif
229 
230 #ifndef NX_DISABLE_IPV4
231     ipv4_address.nxd_ip_version = NX_IP_VERSION_V4;
232     ipv4_address.nxd_ip_address.v4 = IP_ADDRESS(1, 2, 3, 5);
233 #endif /* NX_DISABLE_IPV4 */
234 
235 #ifndef NX_DISABLE_IPV6
236 
237     ipv6_address.nxd_ip_version = NX_IP_VERSION_V6;
238     ipv6_address.nxd_ip_address.v6[0] = 0x20010000;
239     ipv6_address.nxd_ip_address.v6[1] = 0;
240     ipv6_address.nxd_ip_address.v6[2] = 0;
241     ipv6_address.nxd_ip_address.v6[3] = 2;
242 #endif
243 
244     /* Create a UDP socket.  */
245     status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
246 
247     /* Check status.  */
248     if (status)
249     {
250         error_counter++;
251         return;
252     }
253 
254     /* Bind the UDP socket to the IP port.  */
255     status =  nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
256 
257     /* Check status.  */
258     if (status)
259     {
260         error_counter++;
261         return;
262     }
263 
264     /* Disable checksum logic for this socket.  */
265     nx_udp_socket_checksum_disable(&socket_0);
266 
267     /* Setup the ARP entry for the UDP send.  */
268     nx_arp_dynamic_entry_set(&ip_0, IP_ADDRESS(1, 2, 3, 5), 0, 0);
269 
270     while (1)
271     {
272 
273 
274         /* Allocate a packet.  */
275         status =  nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
276 
277         /* Check status.  */
278         if (status != NX_SUCCESS)
279         {
280             break;
281         }
282 
283         /* Write ABCs into the packet payload!  */
284         nx_packet_data_append(my_packet, DEMO_DATA, sizeof(DEMO_DATA), &pool_0, TX_WAIT_FOREVER);
285 
286         /* Send the UDP packet.  */
287 #ifndef NX_DISABLE_IPV6
288 
289 #ifndef NX_DISABLE_IPV4
290         /* In this demo, we alternate between IPv4 connections and IPv6 connections. */
291         if (thread_0_counter & 1)
292         {
293             status =  nxd_udp_socket_send(&socket_0, my_packet, &ipv4_address, 0x89);
294         }
295         else
296 #endif /* NX_DISABLE_IPV4 */
297         {
298             status =  nxd_udp_socket_send(&socket_0, my_packet, &ipv6_address, 0x89);
299         }
300 #else
301         status =  nxd_udp_socket_send(&socket_0, my_packet, &ipv4_address, 0x89);
302 #endif
303 
304         /* Check status.  */
305         if (status != NX_SUCCESS)
306         {
307             error_counter++;
308             break;
309         }
310 
311         /* Increment thread 0's counter.  */
312         thread_0_counter++;
313     }
314 }
315 
316 
thread_1_entry(ULONG thread_input)317 void    thread_1_entry(ULONG thread_input)
318 {
319 
320 UINT       status;
321 NX_PACKET *my_packet;
322 
323     NX_PARAMETER_NOT_USED(thread_input);
324 
325     tx_thread_sleep(NX_IP_PERIODIC_RATE);
326 #ifndef NX_DISABLE_IPV6
327     /* Wait 5 seconds for IPv6 stack to finish DAD process. */
328     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
329 #endif
330     /* Create a UDP socket.  */
331     status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
332 
333     /* Check status.  */
334     if (status)
335     {
336         error_counter++;
337         return;
338     }
339 
340     /* Bind the UDP socket to the IP port.  */
341     status =  nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
342 
343     /* Check status.  */
344     if (status)
345     {
346         error_counter++;
347         return;
348     }
349 
350     while (1)
351     {
352 
353 
354         /* Receive a UDP packet.  */
355         status =  nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
356 
357         /* Check status.  */
358         if (status != NX_SUCCESS)
359         {
360             break;
361         }
362 
363         /* Release the packet.  */
364         status =  nx_packet_release(my_packet);
365 
366         /* Check status.  */
367         if (status != NX_SUCCESS)
368         {
369             break;
370         }
371 
372         /* Increment thread 1's counter.  */
373         thread_1_counter++;
374     }
375 }
376 
377