1 /* This is a small demo of DHCP Client for the high-performance NetX IP stack. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #ifndef NX_DISABLE_IPV4
6 #include "nxd_dhcp_client.h"
7 #include "nxd_dhcp_server.h"
8
9 #define DEMO_STACK_SIZE 4096
10 #define NX_PACKET_SIZE 1536
11 #define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8
12
13 #define NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(10,0,0,1)
14 #define START_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,10)
15 #define END_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,19)
16
17 #define NX_DHCP_SUBNET_MASK_0 IP_ADDRESS(255,255,255,0)
18 #define NX_DHCP_DEFAULT_GATEWAY_0 IP_ADDRESS(10,0,0,1)
19 #define NX_DHCP_DNS_SERVER_0 IP_ADDRESS(10,0,0,1)
20
21 /* Define the interface index. */
22 #define NX_DHCP_INTERFACE_INDEX 0
23
24 /* If defined, the host requests a (previous) client IP address. */
25 /*
26 #define REQUEST_CLIENT_IP
27 */
28
29 #ifdef REQUEST_CLIENT_IP
30 /* Request a specific IP address using the DHCP client address option. */
31 #define NX_DHCP_CLIENT_IP_ADDRESS IP_ADDRESS(10,0,0,18)
32
33 /* If defined NX_TRUE, the client requests to jump to the boot state and skip the DISCOVER message. */
34 #define SKIP_DISCOVER_MESSAGE NX_TRUE
35 #endif
36
37
38
39 /* Define the ThreadX and NetX object control blocks... */
40 TX_THREAD client_thread;
41 NX_PACKET_POOL client_pool;
42 NX_IP client_ip;
43 NX_DHCP dhcp_client;
44
45 TX_THREAD server_thread;
46 NX_PACKET_POOL server_pool;
47 NX_IP server_ip;
48 NX_DHCP_SERVER dhcp_server;
49
50 /* Define the counters used in the demo application... */
51
52 ULONG client_thread_counter;
53 ULONG state_changes;
54 ULONG error_counter;
55 CHAR *pointer;
56
57 UCHAR message[50] = "My Ping Request!" ;
58
59
60 /* Define thread prototypes. */
61
62 void server_thread_entry(ULONG thread_input);
63 void client_thread_entry(ULONG thread_input);
64 void dhcp_state_change(NX_DHCP *dhcp_ptr, UCHAR new_state);
65
66 /******** Optionally substitute your Ethernet driver here. ***********/
67 void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
68
69 /* Define main entry point. */
70
main()71 int main()
72 {
73
74 /* Enter the ThreadX kernel. */
75 tx_kernel_enter();
76 return 0;
77 }
78
79
80 /* Define what the initial system looks like. */
81
tx_application_define(void * first_unused_memory)82 void tx_application_define(void *first_unused_memory)
83 {
84
85 UINT status;
86
87
88 /* Setup the working pointer. */
89 pointer = (CHAR *) first_unused_memory;
90
91 /* Create the client thread. */
92 tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
93 pointer, DEMO_STACK_SIZE,
94 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
95 pointer = pointer + DEMO_STACK_SIZE;
96
97 /* Create the server thread. */
98 tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,
99 pointer, DEMO_STACK_SIZE,
100 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
101 pointer = pointer + DEMO_STACK_SIZE;
102
103 /* Initialize the NetX system. */
104 nx_system_initialize();
105
106 /* Create the client packet pool. */
107 status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
108 pointer = pointer + NX_PACKET_POOL_SIZE;
109
110 /* Check for pool creation error. */
111 if (status)
112 return;
113
114 /* Create the server packet pool. */
115 status = nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
116 pointer = pointer + NX_PACKET_POOL_SIZE;
117
118 /* Check for pool creation error. */
119 if (status)
120 return;
121
122 /* Create an IP instance for the DHCP Client. */
123 status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver, pointer, 2048, 1);
124 pointer = pointer + 2048;
125
126 /* Check for IP create errors. */
127 if (status)
128 return;
129
130 /* Create an IP instance for the DHCP Server. */
131 status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver, pointer, 2048, 1);
132 pointer = pointer + 2048;
133
134 /* Check for IP create errors. */
135 if (status)
136 return;
137
138 /* Enable ARP and supply ARP cache memory for DHCP Client IP. */
139 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
140 pointer = pointer + 1024;
141
142 /* Enable ARP and supply ARP cache memory for DHCP Server IP. */
143 status += nx_arp_enable(&server_ip, (void *) pointer, 1024);
144 pointer = pointer + 1024;
145
146 /* Check for ARP enable errors. */
147 if (status)
148 return;
149
150 /* Enable UDP traffic. */
151 status = nx_udp_enable(&client_ip);
152 status += nx_udp_enable(&server_ip);
153
154 /* Check for UDP enable errors. */
155 if (status)
156 return;
157
158 /* Enable ICMP. */
159 status = nx_icmp_enable(&client_ip);
160 status += nx_icmp_enable(&server_ip);
161
162 /* Check for errors. */
163 if (status)
164 return;
165 }
166
167 /* Define the server thread. */
168
server_thread_entry(ULONG thread_input)169 void server_thread_entry(ULONG thread_input)
170 {
171
172 UINT status;
173 UINT addresses_added;
174
175 NX_PARAMETER_NOT_USED(thread_input);
176
177 /* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
178 status = nx_ip_interface_mtu_set(&server_ip, NX_DHCP_INTERFACE_INDEX, 1500);
179
180 /* Check for MTU set errors. */
181 if (status)
182 return;
183
184 /* Create the DHCP Server. */
185 status = nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE,
186 "DHCP Server", &server_pool);
187 pointer = pointer + DEMO_STACK_SIZE;
188
189 /* Check for errors creating the DHCP Server. */
190 if (status)
191 return;
192
193 /* Load the assignable DHCP IP addresses for the first interface. */
194 status = nx_dhcp_create_server_ip_address_list(&dhcp_server, NX_DHCP_INTERFACE_INDEX, START_IP_ADDRESS_LIST_0,
195 END_IP_ADDRESS_LIST_0, &addresses_added);
196
197 /* Check for errors creating the list. */
198 if (status)
199 return;
200
201 /* Verify all the addresses were added to the list. */
202 if (addresses_added != 10)
203 return;
204
205 /* Set the interface network parameters. */
206 status = nx_dhcp_set_interface_network_parameters(&dhcp_server, NX_DHCP_INTERFACE_INDEX, NX_DHCP_SUBNET_MASK_0,
207 NX_DHCP_DEFAULT_GATEWAY_0, NX_DHCP_DNS_SERVER_0);
208
209 /* Check for errors setting network parameters. */
210 if (status)
211 return;
212
213 /* Start DHCP Server task. */
214 status = nx_dhcp_server_start(&dhcp_server);
215
216 /* Check for errors starting up the DHCP server. */
217 if (status)
218 return;
219 }
220
221
222 /* Define the client thread. */
223
client_thread_entry(ULONG thread_input)224 void client_thread_entry(ULONG thread_input)
225 {
226
227 UINT status;
228 UINT actual_status;
229 UINT length;
230 UINT ping = NX_TRUE;
231 UINT run_dhcp_client = NX_TRUE;
232 NX_PACKET *my_packet;
233
234 NX_PARAMETER_NOT_USED(thread_input);
235
236 /* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
237 status = nx_ip_interface_mtu_set(&client_ip, NX_DHCP_INTERFACE_INDEX, 1500);
238
239 /* Check for MTU set errors. */
240 if (status)
241 return;
242
243 /* Create the DHCP instance. */
244 status = nx_dhcp_create(&dhcp_client, &client_ip, "DHCP-CLIENT");
245 if (status)
246 return;
247
248 #ifdef REQUEST_CLIENT_IP
249 /* Request a specific IP address using the DHCP client address option. */
250 status = nx_dhcp_request_client_ip(&dhcp_client, NX_DHCP_CLIENT_IP_ADDRESS, SKIP_DISCOVER_MESSAGE);
251 if (status)
252 error_counter++;
253 #endif
254
255 /* Register state change variable. */
256 status = nx_dhcp_state_change_notify(&dhcp_client, dhcp_state_change);
257 if (status)
258 error_counter++;
259
260 /* Start the DHCP Client. */
261 nx_dhcp_start(&dhcp_client);
262 while(run_dhcp_client)
263 {
264
265 /* Wait for DHCP to assign the IP address. */
266 do
267 {
268
269 /* Check for address resolution. */
270 status = nx_ip_status_check(&client_ip, NX_IP_ADDRESS_RESOLVED, (ULONG *) &actual_status, NX_IP_PERIODIC_RATE);
271
272 /* Check status. */
273 if (status)
274 {
275 /* wait a bit. */
276 tx_thread_sleep(NX_IP_PERIODIC_RATE);
277 }
278
279 } while (status != NX_SUCCESS);
280
281 length = sizeof(message);
282
283 while(ping)
284 {
285
286 /* Send pings to another host on the network... */
287 status = nx_icmp_ping(&client_ip, NX_DHCP_SERVER_IP_ADDRESS_0, (CHAR *)message, length, &my_packet, NX_IP_PERIODIC_RATE);
288 if (status)
289 error_counter++;
290 else
291 nx_packet_release(my_packet);
292
293 /* Increment counter. */
294 client_thread_counter++;
295
296 /* Sleep for a few ticks... */
297 tx_thread_sleep(NX_IP_PERIODIC_RATE);
298 }
299
300 /* Use this API to send a message to the server, e.g. a DECLINE if the IP address is owned by another host.
301 nx_dhcp_send_request(&dhcp_client, NX_DHCP_TYPE_DHCPDECLINE);
302 */
303
304 /* Use this API to release an IP address if the host is switching networks or running the host through DHCP cycles.
305 nx_dhcp_release(&dhcp_client);
306 */
307
308 /* Stopping the DHCP client. */
309 nx_dhcp_stop(&dhcp_client);
310
311 tx_thread_sleep(NX_IP_PERIODIC_RATE);
312
313 /* Use this API to clear the network parameters and restart the client in the INIT state. */
314 nx_dhcp_reinitialize(&dhcp_client);
315
316 /* Resume the DHCP client thread. */
317 nx_dhcp_start(&dhcp_client);
318
319 /* Ok to resume ping attempts. */
320 ping = NX_TRUE;
321 }
322
323 /* All done. Return resources to NetX and ThreadX. */
324 nx_dhcp_delete(&dhcp_client);
325
326 return;
327 }
328
329
dhcp_state_change(NX_DHCP * dhcp_ptr,UCHAR new_state)330 void dhcp_state_change(NX_DHCP *dhcp_ptr, UCHAR new_state)
331 {
332
333 NX_PARAMETER_NOT_USED(dhcp_ptr);
334 NX_PARAMETER_NOT_USED(new_state);
335
336 /* Increment state changes counter. */
337 state_changes++;
338
339 return;
340 }
341 #endif /* NX_DISABLE_IPV4 */
342