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