1 /* This is a small demo of the NetX TCP/IP stack using the AUTO IP module.  */
2 
3 #include "nx_auto_ip.h"
4 #include "tx_api.h"
5 #include "nx_api.h"
6 
7 
8 #define     DEMO_STACK_SIZE         4096
9 
10 extern void    test_control_return(UINT status);
11 
12 #if !defined(NX_DISABLE_IPV4)
13 
14 /* Define the ThreadX and NetX object control blocks...  */
15 
16 static TX_THREAD               ntest_0;
17 static TX_THREAD               ntest_1;
18 static NX_PACKET_POOL          pool_0;
19 static NX_IP                   ip_0;
20 static NX_IP                   ip_1;
21 static NX_TCP_SOCKET           server_socket;
22 static NX_TCP_SOCKET           client_socket;
23 static TX_SEMAPHORE            sema_0;
24 static TX_SEMAPHORE            sema_1;
25 
26 
27 /* Define the AUTO IP structures for each IP instance.   */
28 
29 static NX_AUTO_IP              auto_ip_0;
30 static NX_AUTO_IP              auto_ip_1;
31 
32 
33 /* Define the counters used in the demo application...  */
34 static ULONG                   address_changes;
35 static ULONG                   error_counter;
36 static ULONG                   packet_counter;
37 static ULONG                   conn_ip_address;
38 
39 /* Define thread prototypes.  */
40 
41 static void    ntest_0_entry(ULONG thread_input);
42 static void    ntest_1_entry(ULONG thread_input);
43 static void    ntest_0_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
44 static void    ntest_0_disconnect_received(NX_TCP_SOCKET *server_socket);
45 static void    ip_address_changed(NX_IP *ip_ptr, VOID *auto_ip_address);
46 extern void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
47 extern void    test_control_return(UINT status);
48 
49 
50 /* Define what the initial system looks like.  */
51 #ifdef CTEST
test_application_define(void * first_unused_memory)52 VOID test_application_define(void *first_unused_memory)
53 #else
54 void    netx_auto_ip_basic_test_application_define(void *first_unused_memory)
55 #endif
56 {
57 
58 CHAR    *pointer;
59 UINT    status;
60 
61 
62     /* Setup the working pointer.  */
63     pointer =  (CHAR *) first_unused_memory;
64 
65     /* Initializes the variables. */
66     error_counter = 0;
67     packet_counter = 0;
68 
69     /* Create the main thread.  */
70     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
71                      pointer, DEMO_STACK_SIZE,
72                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
73     pointer =  pointer + DEMO_STACK_SIZE;
74 
75     /* Create the main thread.  */
76     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
77                      pointer, DEMO_STACK_SIZE,
78                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
79     pointer =  pointer + DEMO_STACK_SIZE;
80 
81     /* Initialize the NetX system.  */
82     nx_system_initialize();
83 
84     /* Create a packet pool.  */
85     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, pointer, 1536*16);
86     pointer = pointer + 1536*16;
87 
88     if (status)
89         error_counter++;
90 
91     /* Create an IP instance.  */
92     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
93                           pointer, 4096, 1);
94     pointer =  pointer + 4096;
95 
96     /* Create another IP instance.  */
97     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
98                            pointer, 4096, 1);
99     pointer =  pointer + 4096;
100 
101     if (status)
102         error_counter++;
103 
104     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
105     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
106     pointer = pointer + 1024;
107 
108     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
109     status +=  nx_arp_enable(&ip_1, (void *) pointer, 1024);
110     pointer = pointer + 1024;
111 
112     /* Check ARP enable status.  */
113     if (status)
114         error_counter++;
115 
116     /* Enable TCP processing for both IP instances.  */
117     status =  nx_tcp_enable(&ip_0);
118     status += nx_tcp_enable(&ip_1);
119 
120     /* Check UDP enable status.  */
121     if (status)
122         error_counter++;
123 
124     /* Create the AutoIP instance for each IP instance.   */
125     status =  nx_auto_ip_create(&auto_ip_0, "AutoIP 0", &ip_0, pointer, 4096, 2);
126     pointer = pointer + 4096;
127     status += nx_auto_ip_create(&auto_ip_1, "AutoIP 1", &ip_1, pointer, 4096, 2);
128     pointer = pointer + 4096;
129 
130     /* Check AutoIP create status.  */
131     if (status)
132         error_counter++;
133 
134     /* Start both AutoIP instances.  */
135     status =  nx_auto_ip_start(&auto_ip_0, 0 /*IP_ADDRESS(169,254,254,255)*/);
136     status += nx_auto_ip_start(&auto_ip_1, 0 /*IP_ADDRESS(169,254,254,255)*/);
137 
138     /* Check AutoIP start status.  */
139     if (status)
140         error_counter++;
141 
142     /* Register an IP address change function for each IP instance.  */
143     status =  nx_ip_address_change_notify(&ip_0, ip_address_changed, (void *) &auto_ip_0);
144     status += nx_ip_address_change_notify(&ip_1, ip_address_changed, (void *) &auto_ip_1);
145 
146     /* Check IP address change notify status.  */
147     if (status)
148         error_counter++;
149 
150     /* Create semaphores. */
151     status = tx_semaphore_create(&sema_0, "SEMA 0", 0);
152     status += tx_semaphore_create(&sema_1, "SEMA 1", 0);
153 
154     /* Check semaphore create status.  */
155     if (status)
156         error_counter++;
157 }
158 
159 
160 
161 /* Define the test threads.  */
162 
ntest_0_entry(ULONG thread_input)163 void    ntest_0_entry(ULONG thread_input)
164 {
165 
166 UINT         status;
167 ULONG        network_mask;
168 
169     printf("NetX Test:   Auto_IP Basic Processing Test.............................");
170 
171     status = tx_semaphore_get(&sema_0, (NX_AUTO_IP_PROBE_NUM * NX_AUTO_IP_PROBE_MAX + NX_AUTO_IP_ANNOUNCE_NUM * NX_AUTO_IP_ANNOUNCE_INTERVAL) * NX_IP_PERIODIC_RATE);
172 
173     /* Check status.  */
174     if(status)
175     {
176         printf("ERROR!\n");
177         test_control_return(1);
178     }
179 
180     /* Wakeup thread_1. */
181     tx_semaphore_put(&sema_1);
182 
183     /* Pickup the current IP address.  */
184 
185     nx_ip_address_get(&ip_0, &conn_ip_address, &network_mask);
186 
187     /* Check whether the AutoIP allocates addresses in the range of 169.254.1.0 through 169.254.254.255.*/
188     if((conn_ip_address & 0xFFFF0000UL) != IP_ADDRESS(169, 254, 0, 0) || (conn_ip_address < IP_ADDRESS(169, 254, 1, 0)) || (conn_ip_address > IP_ADDRESS(169, 254, 254, 255)))
189     {
190         printf("ERROR!\n");
191         test_control_return(1);
192     }
193 
194     /* Create a TCP socket.  */
195     status =  nx_tcp_socket_create(&ip_0, &server_socket, "Server Socket",
196                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
197                                    NX_NULL, ntest_0_disconnect_received);
198 
199     /* Check status.  */
200     if (status)
201         error_counter++;
202 
203         /* Setup this thread to listen.  */
204     status =  nx_tcp_server_socket_listen(&ip_0, 12, &server_socket, 5, ntest_0_connect_received);
205 
206     /* Check for error.  */
207     if (status)
208         error_counter++;
209 
210     /* Accept a client socket connection.  */
211     status =  nx_tcp_server_socket_accept(&server_socket, 5 * NX_IP_PERIODIC_RATE);
212 
213     /* Check for error.  */
214     if (status)
215         error_counter++;
216 
217     /* Server socket disconnect the connection.  */
218     status = nx_tcp_socket_disconnect(&server_socket, NX_IP_PERIODIC_RATE);
219 
220     /* Check for error.  */
221     if(status)
222         error_counter++;
223 
224     /* Unaccepted the server socket.  */
225     status = nx_tcp_server_socket_unaccept(&server_socket);
226 
227     /* Check for error.  */
228     if(status)
229         error_counter++;
230 
231     /* Unlisted on the server port.  */
232     status =  nx_tcp_server_socket_unlisten(&ip_0, 12);
233 
234     /* Check for error.  */
235     if (status)
236         error_counter++;
237 
238     /* Delete the socket.  */
239     status = nx_tcp_socket_delete(&server_socket);
240 
241     /* Check for error.  */
242     if(status)
243         error_counter++;
244 
245     /* Stop the AutoIP instance auto_ip_0.  */
246     status = nx_auto_ip_stop(&auto_ip_0);
247 
248     /* Check for error.  */
249     if(status)
250         error_counter++;
251 
252     /* Delete the AutoIP instance auto_ip_0.  */
253     status =  nx_auto_ip_delete(&auto_ip_0);
254 
255     /* Check for error.  */
256     if(status)
257         error_counter++;
258 
259 }
260 
261 
ntest_1_entry(ULONG thread_input)262 void    ntest_1_entry(ULONG thread_input)
263 {
264 
265 UINT         status;
266 ULONG        ip_address;
267 ULONG        network_mask;
268 
269     status = tx_semaphore_get(&sema_1, (NX_AUTO_IP_PROBE_NUM * NX_AUTO_IP_PROBE_MAX + NX_AUTO_IP_ANNOUNCE_NUM * NX_AUTO_IP_ANNOUNCE_INTERVAL) * NX_IP_PERIODIC_RATE);
270 
271     /* Check status.  */
272     if(status)
273     {
274         printf("ERROR!\n");
275         test_control_return(1);
276     }
277 
278     tx_semaphore_get(&sema_1, TX_WAIT_FOREVER);
279 
280     /* Pickup the current IP address.  */
281     nx_ip_address_get(&ip_1, &ip_address, &network_mask);
282 
283     /* Check whether the AutoIP allocates addresses in the range of 169.254.1.0 through 169.254.254.255.*/
284     if((ip_address & 0xFFFF0000UL) != IP_ADDRESS(169, 254, 0, 0) || (ip_address < IP_ADDRESS(169, 254, 1, 0)) || (ip_address > IP_ADDRESS(169, 254, 254, 255)))
285     {
286         printf("ERROR!\n");
287         test_control_return(1);
288     }
289 
290 
291        /* Create a socket.  */
292     status =  nx_tcp_socket_create(&ip_1, &client_socket, "Client Socket",
293                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
294                                    NX_NULL, NX_NULL);
295 
296     /* Check for error.  */
297     if (status)
298         error_counter++;
299 
300     /* Bind the socket.  */
301     status =  nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
302 
303     /* Check for error.  */
304     if (status)
305         error_counter++;
306 
307     /* Attempt to connect the socket.  */
308     status =  nx_tcp_client_socket_connect(&client_socket, conn_ip_address, 12, 5 * NX_IP_PERIODIC_RATE);
309 
310     /* Check for error.  */
311     if (status)
312         error_counter++;
313 
314     /* Disconnect this socket.  */
315     status =  nx_tcp_socket_disconnect(&client_socket, 5 * NX_IP_PERIODIC_RATE);
316 
317     /* Determine if the status is valid.  */
318     if (status)
319         error_counter++;
320 
321     /* Unbind the socket.  */
322     status =  nx_tcp_client_socket_unbind(&client_socket);
323 
324     /* Check for error.  */
325     if (status)
326         error_counter++;
327 
328     /* Delete the socket.  */
329     status =  nx_tcp_socket_delete(&client_socket);
330 
331     /* Check for error.  */
332     if (status)
333         error_counter++;
334 
335     /* Stop the AutoIP instance auto_ip_1.  */
336     status = nx_auto_ip_stop(&auto_ip_1);
337 
338     /* Check for error.  */
339     if(status)
340         error_counter++;
341 
342     /* Delete the AutoIP instance auto_ip_1.  */
343     status =  nx_auto_ip_delete(&auto_ip_1);
344 
345     /* Check for error.  */
346     if(status)
347         error_counter++;
348 
349     /* Determine if the test was successful.  */
350     if (error_counter)
351     {
352         printf("ERROR!\n");
353         test_control_return(1);
354     }
355     else
356     {
357         printf("SUCCESS!\n");
358         test_control_return(0);
359     }
360 }
361 
ip_address_changed(NX_IP * ip_ptr,VOID * auto_ip_address)362 void  ip_address_changed(NX_IP *ip_ptr, VOID *auto_ip_address)
363 {
364 
365 ULONG         ip_address;
366 ULONG         network_mask;
367 NX_AUTO_IP    *auto_ip_ptr;
368 
369 
370     /* Setup pointer to auto IP instance.  */
371     auto_ip_ptr =  (NX_AUTO_IP *) auto_ip_address;
372 
373     /* Pickup the current IP address.  */
374     nx_ip_address_get(ip_ptr, &ip_address, &network_mask);
375 
376     /* Determine if the IP address has changed back to zero. If so, make sure the
377        AutoIP instance is started.  */
378     if (ip_address == 0)
379     {
380 
381         /* Get the last AutoIP address for this node.  */
382         nx_auto_ip_get_address(auto_ip_ptr, &ip_address);
383 
384         /* Start this AutoIP instance.  */
385         nx_auto_ip_start(auto_ip_ptr, ip_address);
386     }
387 
388     /* Determine if the IP address has transitioned to a non local IP address.  */
389     else if ((ip_address & 0xFFFF0000UL) != IP_ADDRESS(169, 254, 0, 0))
390     {
391 
392         /* Stop the AutoIP processing.  */
393         nx_auto_ip_stop(auto_ip_ptr);
394 
395         /* Delete the AutoIP instance.  */
396         nx_auto_ip_delete(auto_ip_ptr);
397     }
398 
399     /* Increment a counter.  */
400     address_changes++;
401 
402     /* Wakeup test threads. */
403     if(ip_ptr == &ip_0)
404         tx_semaphore_put(&sema_0);
405     else
406         tx_semaphore_put(&sema_1);
407 }
408 
ntest_0_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)409 static void  ntest_0_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
410 {
411 
412     /* Check for the proper socket and port.  */
413     if ((socket_ptr != &server_socket) || (port != 12))
414         error_counter++;
415 }
416 
ntest_0_disconnect_received(NX_TCP_SOCKET * socket)417 static void  ntest_0_disconnect_received(NX_TCP_SOCKET *socket)
418 {
419 
420     /* Check for proper disconnected socket.  */
421     if (socket != &server_socket)
422         error_counter++;
423 }
424 #else
425 
426 #ifdef CTEST
test_application_define(void * first_unused_memory)427 VOID test_application_define(void *first_unused_memory)
428 #else
429 void    netx_auto_ip_basic_test_application_define(void *first_unused_memory)
430 #endif
431 {
432 
433     /* Print out test information banner.  */
434     printf("NetX Test:   Auto_IP Basic Processing Test.............................N/A\n");
435 
436     test_control_return(3);
437 }
438 #endif
439