1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Internet Protocol (IP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_ip.h"
29
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_ip_interface_status_check PORTABLE C */
37 /* 6.2.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function polls the specified interface for the link state using*/
45 /* thread sleep for the necessary conditions n the IP instance. Where */
46 /* the requested status exists only at the IP instance, for example */
47 /* NX_IP_INITIALIZE_DONE this service supplies the IP setting for that */
48 /* status. */
49 /* */
50 /* INPUT */
51 /* */
52 /* ip_ptr Pointer to IP instance */
53 /* interface_index Index to the interface */
54 /* needed_status Status needed request */
55 /* actual_status Pointer to return status area */
56 /* wait_option Maximum suspension time */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* status Completion status */
61 /* */
62 /* CALLS */
63 /* */
64 /* (ip_link_driver) User supplied link driver */
65 /* tx_mutex_get Get protection mutex */
66 /* tx_mutex_put Put protection mutex */
67 /* tx_thread_sleep Sleep until events are */
68 /* satisfied */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application */
73 /* */
74 /* RELEASE HISTORY */
75 /* */
76 /* DATE NAME DESCRIPTION */
77 /* */
78 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
79 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
80 /* resulting in version 6.1 */
81 /* 03-08-2023 Yajun Xia Modified comment(s), */
82 /* added driver entry check, */
83 /* resulting in version 6.2.1 */
84 /* */
85 /**************************************************************************/
_nx_ip_interface_status_check(NX_IP * ip_ptr,UINT interface_index,ULONG needed_status,ULONG * actual_status,ULONG wait_option)86 UINT _nx_ip_interface_status_check(NX_IP *ip_ptr, UINT interface_index, ULONG needed_status,
87 ULONG *actual_status, ULONG wait_option)
88 {
89
90 ULONG current_status;
91 NX_IP_DRIVER driver_request;
92 ULONG return_value;
93
94 #ifdef TX_ENABLE_EVENT_TRACE
95 TX_TRACE_BUFFER_ENTRY *trace_event;
96 ULONG trace_timestamp;
97 #endif
98
99
100 /* If trace is enabled, insert this event into the trace buffer. */
101 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_STATUS_CHECK, ip_ptr, needed_status, 0, wait_option, NX_TRACE_IP_EVENTS, &trace_event, &trace_timestamp);
102
103 /* Loop to keep checking for the proper status bits. */
104 for (;;)
105 {
106
107 /* Clear the current status. */
108 current_status = 0;
109
110 /* Process according to the status option specified. */
111
112 if (needed_status & NX_IP_INITIALIZE_DONE)
113 {
114
115 /* Check for initialization complete. */
116 if (ip_ptr -> nx_ip_initialize_done)
117 {
118
119 /* Yes, set the appropriate bit in the current status. */
120 current_status = current_status | NX_IP_INITIALIZE_DONE;
121 }
122 }
123
124 #ifndef NX_DISABLE_IPV4
125 if (needed_status & NX_IP_ADDRESS_RESOLVED)
126 {
127
128 /* Check for a non-zero IP address. */
129 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
130 {
131
132 /* Yes, set the appropriate bit in the current status. */
133 current_status = current_status | NX_IP_ADDRESS_RESOLVED;
134 }
135 }
136
137 if (needed_status & NX_IP_ARP_ENABLED)
138 {
139
140 /* Check for ARP being enabled. */
141 if (ip_ptr -> nx_ip_arp_periodic_update)
142 {
143 /* Yes, set the appropriate bit in the current status. */
144 current_status = current_status | NX_IP_ARP_ENABLED;
145 }
146 }
147
148 if (needed_status & NX_IP_RARP_COMPLETE)
149 {
150
151 /* This is effectively the same as the IP address resolved... */
152
153 /* Check for a non-zero IP address. */
154 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
155 {
156
157 /* Yes, set the appropriate bit in the current status. */
158 current_status = current_status | NX_IP_RARP_COMPLETE;
159 }
160 }
161
162 if (needed_status & NX_IP_IGMP_ENABLED)
163 {
164
165 /* Check for IGMP being enabled. */
166 if (ip_ptr -> nx_ip_igmp_packet_receive)
167 {
168 /* Yes, set the appropriate bit in the current status. */
169 current_status = current_status | NX_IP_IGMP_ENABLED;
170 }
171 }
172 #endif /* !NX_DISABLE_IPV4 */
173
174 if (needed_status & NX_IP_LINK_ENABLED)
175 {
176
177 /* Get mutex protection. */
178 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
179
180 /* Build the driver request structure. */
181 driver_request.nx_ip_driver_ptr = ip_ptr;
182 driver_request.nx_ip_driver_command = NX_LINK_GET_STATUS;
183 driver_request.nx_ip_driver_return_ptr = &return_value;
184 driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[interface_index]);
185
186 /* If trace is enabled, insert this event into the trace buffer. */
187 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_GET_STATUS, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
188
189 /* Call link level driver. */
190 if(ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry == NX_NULL)
191 {
192
193 /* Release mutex protection. */
194 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
195
196 return(NX_NOT_SUCCESSFUL);
197 }
198 (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry)(&driver_request);
199
200 /* If the driver does not recognize this keyword, we fall back to reading the IP link status.*/
201 /*lint -e{644} suppress variable might not be initialized, since "nx_ip_driver_status" was initialized in nx_interface_link_driver_entry. */
202 if (driver_request.nx_ip_driver_status != NX_SUCCESS)
203 {
204 if (driver_request.nx_ip_driver_status == NX_UNHANDLED_COMMAND)
205 {
206 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_up)
207 {
208 current_status = current_status | NX_IP_LINK_ENABLED;
209 }
210 }
211 }
212 else
213 {
214
215 /* Check for a link up condition. */
216 /*lint -e{644} suppress variable might not be initialized, since "return_value" was initialized in nx_interface_link_driver_entry. */
217 if (return_value == NX_TRUE)
218 {
219
220 /* Yes, set the appropriate bit in the current status. */
221 current_status = current_status | NX_IP_LINK_ENABLED;
222 }
223 }
224
225 /* Release mutex protection. */
226 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
227 }
228
229 if (needed_status & NX_IP_UDP_ENABLED)
230 {
231
232 /* Check for UDP being enabled. */
233 if (ip_ptr -> nx_ip_udp_packet_receive)
234 {
235 /* Yes, set the appropriate bit in the current status. */
236 current_status = current_status | NX_IP_UDP_ENABLED;
237 }
238 }
239
240 if (needed_status & NX_IP_TCP_ENABLED)
241 {
242
243 /* Check for TCP being enabled. */
244 if (ip_ptr -> nx_ip_tcp_packet_receive)
245 {
246 /* Yes, set the appropriate bit in the current status. */
247 current_status = current_status | NX_IP_TCP_ENABLED;
248 }
249 }
250
251 if (needed_status & NX_IP_INTERFACE_LINK_ENABLED)
252 {
253
254 /* Get mutex protection. */
255 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
256
257 /* Build the driver request structure. */
258 driver_request.nx_ip_driver_ptr = ip_ptr;
259 driver_request.nx_ip_driver_command = NX_LINK_GET_STATUS;
260 driver_request.nx_ip_driver_return_ptr = &return_value;
261 driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[interface_index]);
262
263 /* If trace is enabled, insert this event into the trace buffer. */
264 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_GET_STATUS, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
265
266 /* Call link level driver. */
267 if(ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry == NX_NULL)
268 {
269
270 /* Release mutex protection. */
271 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
272
273 return(NX_NOT_SUCCESSFUL);
274 }
275 (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry)(&driver_request);
276
277 /* If the driver does not recognize this keyword, we fall back to reading the IP link status.*/
278 /*lint -e{644} suppress variable might not be initialized, since "nx_ip_driver_status" was initialized in nx_interface_link_driver_entry. */
279 if (driver_request.nx_ip_driver_status != NX_SUCCESS)
280 {
281 if (driver_request.nx_ip_driver_status == NX_UNHANDLED_COMMAND)
282 {
283 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_up)
284 {
285 current_status = current_status | NX_IP_INTERFACE_LINK_ENABLED;
286 }
287 }
288 }
289 else
290 {
291
292 /* Check for a link up condition. */
293 /*lint -e{644} suppress variable might not be initialized, since "return_value" was initialized in nx_interface_link_driver_entry. */
294 if (return_value == NX_TRUE)
295 {
296
297 /* Yes, set the appropriate bit in the current status. */
298 current_status = current_status | NX_IP_INTERFACE_LINK_ENABLED;
299 }
300 }
301
302 /* Release mutex protection. */
303 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
304 }
305
306 /* Determine if current status is the same. If so, break out
307 of this polling loop. */
308 if (current_status == needed_status)
309 {
310 break;
311 }
312
313 /* Check for suspension request. */
314 if (wait_option)
315 {
316
317 /* Decrease the wait time and sleep. */
318 if (wait_option > NX_IP_STATUS_CHECK_WAIT_TIME)
319 {
320 wait_option -= NX_IP_STATUS_CHECK_WAIT_TIME;
321 }
322 else
323 {
324 wait_option = 0;
325 }
326
327 /* Sleep for a tick and check again. */
328 tx_thread_sleep(NX_IP_STATUS_CHECK_WAIT_TIME);
329 }
330 else
331 {
332
333 /* Get out of the loop. */
334 break;
335 }
336 }
337
338 /* Place the current status in the return destination. */
339 *actual_status = current_status;
340
341 /* Update the trace event with the status. */
342 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_IP_STATUS_CHECK, 0, 0, current_status, 0);
343
344 /* Determine what status to return. */
345 if (needed_status == current_status)
346 {
347
348 /* Return a success. */
349 return(NX_SUCCESS);
350 }
351 else
352 {
353
354 /* Return an error. */
355 return(NX_NOT_SUCCESSFUL);
356 }
357 }
358
359