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