1 /* This is a small demo of DHCP Client for multiple interfaces for the high-performance NetX IP stack.
2
3 It is suggested that applications call interface specific API to do specific action on the specified
4 interface if DHCP is enabled on multiple interfaces at the same time.
5 Example of a device possibly with a secondary interfaces attached, and DHCP Client having only the secondary
6 interface enabled for DHCP:
7
8 #if (NX_MAX_PHYSICAL_INTERFACES >= 2) && (NX_DHCP_CLIENT_MAX_RECORDS >= 2)
9
10 Client configured for DHCP enabled on more than one interface. Use the interface specific service to
11 request Client IP on the secondary interface.
12
13 status = nx_dhcp_interface_request_client_ip(&dhcp_client, 1, NX_DHCP_CLIENT_IP_ADDRESS_1, SKIP_DISCOVER_MESSAGE);
14 #else
15 Client is configured for one interface to be enabled for DHCP. Use the non-interface specific service
16 to perform the request Client IP action on the interface index that the Client has set for DHCP.
17
18 Note: the application must first call nx_dhcp_set_interface_index() to set the secondary interface as the interface
19 to run DHCP on. Otherwise DHCP runs on the primary interface, by default.
20
21 status = nx_dhcp_request_client_ip(&dhcp_client, NX_DHCP_CLIENT_IP_ADDRESS_1, SKIP_DISCOVER_MESSAGE);
22 #endif
23
24 if (status)
25 error_counter++;
26
27 */
28
29 #include "tx_api.h"
30 #include "nx_api.h"
31 #include "nxd_dhcp_client.h"
32
33 #define DEMO_STACK_SIZE 4096
34 #define NX_PACKET_SIZE 1536
35 #define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8
36
37
38 /* If defined, the host requests a (previous) client IP address. */
39 /*
40 #define REQUEST_CLIENT_IP
41 */
42
43 #ifdef REQUEST_CLIENT_IP
44 /* Request a specific IP address using the DHCP client address option. */
45 #define NX_DHCP_CLIENT_IP_ADDRESS_0 IP_ADDRESS(192, 168, 0, 18)
46 #define NX_DHCP_CLIENT_IP_ADDRESS_1 IP_ADDRESS(10, 0, 0, 18)
47
48 /* If defined NX_TRUE, the client requests to jump to the boot state and skip the DISCOVER message. */
49 #define SKIP_DISCOVER_MESSAGE NX_TRUE
50 #endif /* REQUEST_CLIENT_IP */
51
52 /* Define the ThreadX and NetX object control blocks... */
53 TX_THREAD client_thread;
54 NX_PACKET_POOL client_pool;
55 NX_IP client_ip;
56 NX_DHCP dhcp_client;
57
58
59 /* Define the counters used in the demo application... */
60 ULONG client_thread_counter;
61 ULONG state_changes;
62 ULONG error_counter;
63 CHAR *pointer;
64
65
66 /* Define thread prototypes. */
67 void client_thread_entry(ULONG thread_input);
68 void dhcp_interface_state_change(NX_DHCP *dhcp_ptr, UINT iface_index, UCHAR new_state);
69
70 /******** Optionally substitute your Ethernet driver here. ***********/
71 void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
72
73 /* Define main entry point. */
74
main()75 int main()
76 {
77
78 /* Enter the ThreadX kernel. */
79 tx_kernel_enter();
80 return 0;
81 }
82
83
84 /* Define what the initial system looks like. */
tx_application_define(void * first_unused_memory)85 void tx_application_define(void *first_unused_memory)
86 {
87
88 UINT status;
89
90
91 /* Setup the working pointer. */
92 pointer = (CHAR *) first_unused_memory;
93
94 /* Create the client thread. */
95 tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
96 pointer, DEMO_STACK_SIZE,
97 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
98 pointer = pointer + DEMO_STACK_SIZE;
99
100 /* Initialize the NetX system. */
101 nx_system_initialize();
102
103 /* Create the client packet pool. */
104 status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
105 pointer = pointer + NX_PACKET_POOL_SIZE;
106
107 /* Check for pool creation error. */
108 if (status)
109 return;
110
111 /* Create an IP instance for the DHCP Client. */
112 status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver, pointer, 2048, 1);
113 pointer = pointer + 2048;
114
115 /* Check for IP create errors. */
116 if (status)
117 return;
118
119 /* Enable ARP and supply ARP cache memory for DHCP Client IP. */
120 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
121 pointer = pointer + 1024;
122
123 /* Check for ARP enable errors. */
124 if (status)
125 return;
126
127 /* Enable UDP traffic. */
128 status = nx_udp_enable(&client_ip);
129
130 /* Check for UDP enable errors. */
131 if (status)
132 return;
133
134 /* Enable TCP traffic. */
135 status = nx_tcp_enable(&client_ip);
136
137 /* Check for TCP enable errors. */
138 if (status)
139 return;
140
141 /* Enable ICMP. */
142 status = nx_icmp_enable(&client_ip);
143
144 /* Check for errors. */
145 if (status)
146 return;
147 }
148
149
150 /* Define the client thread. */
client_thread_entry(ULONG thread_input)151 void client_thread_entry(ULONG thread_input)
152 {
153
154 UINT status;
155 UINT actual_status;
156 ULONG server_address;
157
158 NX_PARAMETER_NOT_USED(thread_input);
159
160 /* Check if there are multiple network interfaces */
161
162 #if (NX_MAX_PHYSICAL_INTERFACES >= 2) && (NX_DHCP_CLIENT_MAX_RECORDS >= 2)
163 /* There are. Attach the second interface. */
164 status = nx_ip_interface_attach(&client_ip, "Second interface", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL,_nx_ram_network_driver);
165
166 /* Check status. */
167 if (status)
168 return;
169 #endif
170
171 /* Create the DHCP instance; this automatically enables DHCP on the primary interface. */
172 status = nx_dhcp_create(&dhcp_client, &client_ip, "dhcp_client");
173 if (status)
174 return;
175
176 /* Check if there are multiple network interfaces and if DHCP CLient is set up to run DHCP on multiple interfaces. */
177 #if (NX_MAX_PHYSICAL_INTERFACES >= 2) && (NX_DHCP_CLIENT_MAX_RECORDS >= 2)
178 /* Enable DHCP for specified interface(1:second interface). */
179 status = nx_dhcp_interface_enable(&dhcp_client, 1);
180 if (status)
181 return;
182 #else
183 /* for NX_MAX_PHYSICAL_INTERFACES >= 2, NX_DHCP_CLIENT_MAX_RECORDS == 1*/
184 status = nx_dhcp_set_interface_index(&dhcp_client, 1);
185 #endif
186
187 #ifdef REQUEST_CLIENT_IP
188
189 /* nx_dhcp_request_client_ip() requests a specific IP address for DHCP client address option on the first DHCP enabled (valid) interface it finds. */
190 /* Suggest using nx_dhcp_interface_request_client_ip() on a single interface if DHCP is enabled on multiple interfaces
191 status = nx_dhcp_interface_request_client_ip(&dhcp_client, 1, NX_DHCP_CLIENT_IP_ADDRESS_0, SKIP_DISCOVER_MESSAGE)
192 requests the IP address on the specified address (1:second interface)
193 */
194 status = nx_dhcp_request_client_ip(&dhcp_client, NX_DHCP_CLIENT_IP_ADDRESS_0, SKIP_DISCOVER_MESSAGE);
195 if (status)
196 error_counter++;
197
198 #endif /* REQUEST_CLIENT_IP */
199
200 /* Clear the broadcast flag. */
201 /* nx_dhcp_clear_broadcast_flag(&dhcp_client) clears the broadcast flag on all DHCP enabled interfaces.
202 Suggest using nx_dhcp_interface_clear_broadcast_flag() to clear the flag on one interface if DHCP is enabled on multiple interfaces
203 status = nx_dhcp_interface_clear_broadcast_flag(&dhcp_client, 1) clears the broadcast flag on the specified interface(1:second interface)
204 */
205 status = nx_dhcp_clear_broadcast_flag(&dhcp_client, NX_TRUE);
206 if (status)
207 error_counter++;
208
209
210 /* Register the interface state change callback. */
211 status = nx_dhcp_interface_state_change_notify(&dhcp_client, dhcp_interface_state_change);
212 if (status)
213 error_counter++;
214
215 /* Start the DHCP Client. */
216 /* nx_dhcp_start(&dhcp_client) start DHCP for all DHCP enabled interfaces.
217 Suggest using nx_dhcp_interface_start() to start DHCP on one interface if DHCP is enabled on multiple interfaces
218 status = nx_dhcp_interface_start(&dhcp_client, 1) starts DHCP on the specified interface (1:second interface)
219 */
220 status = nx_dhcp_start(&dhcp_client);
221
222 /* Loop to test DHCP. */
223 while (1)
224 {
225
226 /* Check the address resolution for primary interface. */
227 nx_ip_interface_status_check(&client_ip, 0, NX_IP_ADDRESS_RESOLVED, (ULONG *)&actual_status, NX_WAIT_FOREVER);
228
229 /* Check the address resolution for second interface. */
230 nx_ip_interface_status_check(&client_ip, 1, NX_IP_ADDRESS_RESOLVED, (ULONG *)&actual_status, NX_WAIT_FOREVER);
231
232 /* Use this API to get the Server address. */
233 /* nx_dhcp_server_address_get(&dhcp_client, &server_address) get the server address for the first DHCP enabled ("valid") interface.
234 Suggest using nx_dhcp_interface_server_address_get() to get the server address on a specific interface if DHCP is enabled on multiple interfaces
235 status = nx_dhcp_interface_server_address_get(&dhcp_client, 1, &server_address) returns the server address on specified interface(1:second interface)
236 */
237 status = nx_dhcp_server_address_get(&dhcp_client, &server_address);
238 if (status)
239 error_counter++;
240
241
242 /* Release the IP address the Client is bound to.
243
244 Use the nx_dhcp_release() API to release an IP address if the host is switching networks or running the host through DHCP cycles.
245 Note that it is not necessary to call nx_dhcp_reinitialize() or nx_dhcp_interface_reinitialize() after calling this
246 function. DHCP on this interface (or interfaces) is ready to be restarted. */
247
248 /* nx_dhcp_release(&dhcp_client) releases the DHCP generated IP address for all DHCP enabled interfaces.
249 Suggest using nx_dhcp_interface_release() to release the IP address on a specific interface if DHCP is enabled on multiple interfaces
250 status = nx_dhcp_interface_release(&dhcp_client, 1) releases the IP address for the specified interface(1:second interface)
251 */
252 status = nx_dhcp_release(&dhcp_client);
253 if (status)
254 error_counter++;
255
256 /* Stopping the DHCP client.
257
258 Use this API if the Client has not reached the BOUND state. This simply stops the DHCP
259 Client. It does not clear any network parameters or reset the Client state to NOT STARTED. To do clear network parameters,
260 and reset the state (e.g. before calling nx_dhcp_start() on the stopped interface(s), call nx_dhcp_reinitialize() or
261 nx_dhcp_interface_reinitialize() depending which interface(s) need to be reinitialized.
262 */
263
264 /* nx_dhcp_stop(&dhcp_client) stops DHCP on all DHCP enabled interfaces.
265 Suggest using nx_dhcp_interface_stop() to stop DHCP on a specific interface if DHCP is enabled on multiple interfaces
266 status = nx_dhcp_interface_stop(&dhcp_client, 1) stop DHCP on the specified interface(1:second interface)
267 */
268 status = nx_dhcp_stop(&dhcp_client);
269 if (status)
270 error_counter++;
271
272 /* Sleep one second. */
273 tx_thread_sleep(NX_IP_PERIODIC_RATE);
274
275 /* Reinitialize the Client for restarting DHCP.
276
277 Use this API to clear the network parameters and restart the client in the not started state. */
278
279 /* nx_dhcp_reinitialize(&dhcp_client) clears the network parameters on all DHCP enabled interfaces.
280 Suggest using nx_dhcp_interface_reinitialize() to reinitialize DHCP on a specific interface if DHCP is enabled on multiple interfaces
281 status = nx_dhcp_interface_reinitialize(&dhcp_client, 1) reinitializes DHCP on the specified interface(1:second interface)
282 */
283 status = nx_dhcp_reinitialize(&dhcp_client);
284 if (status)
285 error_counter++;
286
287 /* Resume the DHCP client thread. */
288 /* nx_dhcp_start(&dhcp_client) start DHCP for all DHCP enabled interfaces.
289 or nx_dhcp_interface_start(&dhcp_client, 1) to start DHCP for specified interface(1:second interface) */
290 status = nx_dhcp_start(&dhcp_client);
291 if (status)
292 error_counter++;
293 }
294
295 /* All done. Return resources to NetX and ThreadX. */
296 nx_dhcp_delete(&dhcp_client);
297
298 return;
299 }
300
301
dhcp_interface_state_change(NX_DHCP * dhcp_ptr,UINT iface_index,UCHAR new_state)302 void dhcp_interface_state_change(NX_DHCP *dhcp_ptr, UINT iface_index, UCHAR new_state)
303 {
304
305 NX_PARAMETER_NOT_USED(dhcp_ptr);
306 NX_PARAMETER_NOT_USED(iface_index);
307 NX_PARAMETER_NOT_USED(new_state);
308
309 /* Increment state changes counter. */
310 state_changes++;
311
312 return;
313 }
314
315