1 /* This is a small demo of the NetX TCP/IP stack using the AUTO IP module. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #ifndef NX_DISABLE_IPV4
6 #include "nx_auto_ip.h"
7
8
9 #define DEMO_STACK_SIZE 4096
10 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
11
12
13 /* Define the ThreadX and NetX object control blocks... */
14
15 TX_THREAD thread_0;
16 TX_THREAD thread_1;
17 NX_PACKET_POOL pool_0;
18 NX_IP ip_0;
19 NX_IP ip_1;
20 NX_UDP_SOCKET socket_0;
21 NX_UDP_SOCKET socket_1;
22
23
24 /* Define the AUTO IP structures for each IP instance. */
25
26 NX_AUTO_IP auto_ip_0;
27 NX_AUTO_IP auto_ip_1;
28
29
30 /* Define the counters used in the demo application... */
31
32 ULONG thread_0_counter;
33 ULONG thread_1_counter;
34 ULONG address_changes;
35 ULONG error_counter;
36
37
38 /* Define thread prototypes. */
39
40 void thread_0_entry(ULONG thread_input);
41 void thread_1_entry(ULONG thread_input);
42 void ip_address_changed(NX_IP *ip_ptr, VOID *auto_ip_address);
43
44 void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
45
46
47 /* Define main entry point. */
48
main()49 int main()
50 {
51
52 /* Enter the ThreadX kernel. */
53 tx_kernel_enter();
54 }
55
56
57 /* Define what the initial system looks like. */
58
tx_application_define(void * first_unused_memory)59 void tx_application_define(void *first_unused_memory)
60 {
61
62 CHAR *pointer;
63 UINT status;
64
65
66 /* Setup the working pointer. */
67 pointer = (CHAR *) first_unused_memory;
68
69 /* Create the main thread. */
70 tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
71 pointer, DEMO_STACK_SIZE,
72 16, 16, 1, TX_AUTO_START);
73
74 pointer = pointer + DEMO_STACK_SIZE;
75
76 /* Create the main thread. */
77 tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
78 pointer, DEMO_STACK_SIZE,
79 16, 16, 1, TX_AUTO_START);
80 pointer = pointer + DEMO_STACK_SIZE;
81
82 /* Initialize the NetX system. */
83 nx_system_initialize();
84
85 /* Create a packet pool. */
86 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 4096);
87 pointer = pointer + 4096;
88
89 if (status)
90 error_counter++;
91
92 /* Create an IP instance. */
93 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
94 pointer, 4096, 1);
95 pointer = pointer + 4096;
96
97 /* Create another IP instance. */
98 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
99 pointer, 4096, 1);
100 pointer = pointer + 4096;
101
102 if (status)
103 error_counter++;
104
105 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
106 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
107 pointer = pointer + 1024;
108
109 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
110 status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
111 pointer = pointer + 1024;
112
113 /* Check ARP enable status. */
114 if (status)
115 error_counter++;
116
117 /* Enable UDP processing for both IP instances. */
118 status = nx_udp_enable(&ip_0);
119 status += nx_udp_enable(&ip_1);
120
121 /* Check UDP enable status. */
122 if (status)
123 error_counter++;
124
125 /* Create the AutoIP instance for each IP instance. */
126 status = nx_auto_ip_create(&auto_ip_0, "AutoIP 0", &ip_0, pointer, 4096, 1);
127 pointer = pointer + 4096;
128 status += nx_auto_ip_create(&auto_ip_1, "AutoIP 1", &ip_1, pointer, 4096, 1);
129 pointer = pointer + 4096;
130
131 /* Check AutoIP create status. */
132 if (status)
133 error_counter++;
134
135 /* Start both AutoIP instances. */
136 status = nx_auto_ip_start(&auto_ip_0, 0 /*IP_ADDRESS(169,254,254,255)*/);
137 status += nx_auto_ip_start(&auto_ip_1, 0 /*IP_ADDRESS(169,254,254,255)*/);
138
139 /* Check AutoIP start status. */
140 if (status)
141 error_counter++;
142
143 /* Register an IP address change function for each IP instance. */
144 status = nx_ip_address_change_notify(&ip_0, ip_address_changed, (void *) &auto_ip_0);
145 status += nx_ip_address_change_notify(&ip_1, ip_address_changed, (void *) &auto_ip_1);
146
147 /* Check IP address change notify status. */
148 if (status)
149 error_counter++;
150 }
151
152
153
154 /* Define the test threads. */
155
thread_0_entry(ULONG thread_input)156 void thread_0_entry(ULONG thread_input)
157 {
158
159 UINT status;
160 ULONG actual_status;
161 NX_PACKET *my_packet;
162
163 NX_PARAMETER_NOT_USED(thread_input);
164
165 /* Wait for IP address to be resolved. */
166 do
167 {
168
169 /* Call IP status check routine. */
170 status = nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, 10 * NX_IP_PERIODIC_RATE);
171
172 } while (status != NX_SUCCESS);
173
174 /* Create a UDP socket. */
175 status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
176
177 /* Check status. */
178 if (status)
179 {
180 error_counter++;
181 return;
182 }
183
184 /* Bind the UDP socket to the IP port. */
185 status = nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
186
187 /* Check status. */
188 if (status)
189 {
190 error_counter++;
191 return;
192 }
193
194 /* Disable checksum logic for this socket. */
195 nx_udp_socket_checksum_disable(&socket_0);
196
197 /* Let other threads run again. */
198 tx_thread_relinquish();
199
200 while(1)
201 {
202
203
204 /* Allocate a packet. */
205 status = nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
206
207 /* Check status. */
208 if (status != NX_SUCCESS)
209 break;
210
211 /* Write ABCs into the packet payload! */
212 memcpy(my_packet -> nx_packet_prepend_ptr, DEMO_DATA, sizeof(DEMO_DATA)); /* Use case of memcpy is verified. */
213
214 /* Adjust the write pointer. */
215 my_packet -> nx_packet_length = sizeof(DEMO_DATA);
216 my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + sizeof(DEMO_DATA);
217
218 /* Send the UDP packet. */
219 status = nx_udp_socket_send(&socket_0, my_packet, ip_1.nx_ip_address, 0x89);
220
221 /* Check status. */
222 if (status != NX_SUCCESS)
223 {
224 error_counter++;
225 break;
226 }
227
228 /* Increment thread 0's counter. */
229 thread_0_counter++;
230
231 /* Relinquish to thread 1. */
232 tx_thread_relinquish();
233 }
234 }
235
236
thread_1_entry(ULONG thread_input)237 void thread_1_entry(ULONG thread_input)
238 {
239
240 UINT status;
241 ULONG actual_status;
242 NX_PACKET *my_packet;
243
244 NX_PARAMETER_NOT_USED(thread_input);
245
246 /* Wait for IP address to be resolved. */
247 do
248 {
249
250 /* Call IP status check routine. */
251 status = nx_ip_status_check(&ip_1, NX_IP_ADDRESS_RESOLVED, &actual_status, 10 * NX_IP_PERIODIC_RATE);
252
253 } while (status != NX_SUCCESS);
254
255 /* Create a UDP socket. */
256 status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
257
258 /* Check status. */
259 if (status)
260 {
261 error_counter++;
262 return;
263 }
264
265 /* Bind the UDP socket to the IP port. */
266 status = nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
267
268 /* Check status. */
269 if (status)
270 {
271 error_counter++;
272 return;
273 }
274
275 while(1)
276 {
277
278
279 /* Receive a UDP packet. */
280 status = nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
281
282 /* Check status. */
283 if (status != NX_SUCCESS)
284 break;
285
286 /* Release the packet. */
287 status = nx_packet_release(my_packet);
288
289 /* Check status. */
290 if (status != NX_SUCCESS)
291 break;
292
293 /* Increment thread 1's counter. */
294 thread_1_counter++;
295 }
296 }
297
ip_address_changed(NX_IP * ip_ptr,VOID * auto_ip_address)298 void ip_address_changed(NX_IP *ip_ptr, VOID *auto_ip_address)
299 {
300
301 ULONG ip_address;
302 ULONG network_mask;
303 NX_AUTO_IP *auto_ip_ptr;
304
305
306 /* Setup pointer to auto IP instance. */
307 auto_ip_ptr = (NX_AUTO_IP *) auto_ip_address;
308
309 /* Pickup the current IP address. */
310 nx_ip_address_get(ip_ptr, &ip_address, &network_mask);
311
312 /* Determine if the IP address has changed back to zero. If so, make sure the
313 AutoIP instance is started. */
314 if (ip_address == 0)
315 {
316
317 /* Get the last AutoIP address for this node. */
318 nx_auto_ip_get_address(auto_ip_ptr, &ip_address);
319
320 /* Start this AutoIP instance. */
321 nx_auto_ip_start(auto_ip_ptr, ip_address);
322 }
323
324 /* Determine if the IP address has transitioned to a non local IP address. */
325 else if ((ip_address & 0xFFFF0000UL) != IP_ADDRESS(169, 254, 0, 0))
326 {
327
328 /* Stop the AutoIP processing. */
329 nx_auto_ip_stop(auto_ip_ptr);
330 }
331
332 /* Increment a counter. */
333 address_changes++;
334 }
335 #endif /* NX_DISABLE_IPV4 */
336