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 "tx_thread.h"
30 #include "nx_ip.h"
31 #include "nx_icmp.h"
32 #include "nx_arp.h"
33 #ifdef FEATURE_NX_IPV6
34 #include "nx_nd_cache.h"
35 #endif /* FEATURE_NX_IPV6 */
36
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _nx_ip_delete PORTABLE C */
43 /* 6.1 */
44 /* AUTHOR */
45 /* */
46 /* Yuxin Zhou, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function deletes an Internet Protocol instance, including */
51 /* calling the associated driver with a link disable request. */
52 /* */
53 /* INPUT */
54 /* */
55 /* ip_ptr Pointer to IP control block */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* status Completion status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _nx_ip_delete_queue_clear Clear a packet queue */
64 /* _nx_ip_raw_packet_cleanup Cleanup raw packet suspension */
65 /* _nx_icmp_cleanup Cleanup for ICMP packets */
66 /* _nx_ip_fragment_disable Disable fragment processing */
67 /* tx_mutex_delete Delete IP protection mutex */
68 /* tx_mutex_get Get protection mutex */
69 /* tx_mutex_put Put protection mutex */
70 /* tx_thread_terminate Terminate IP helper thread */
71 /* tx_event_flags_delete Delete IP event flags */
72 /* tx_thread_delete Delete IP helper thread */
73 /* _tx_thread_system_preempt_check Check for preemption */
74 /* tx_timer_deactivate Deactivate IP-ARP timer */
75 /* tx_timer_delete Delete IP-ARP timer */
76 /* (ip_link_driver) User supplied link driver */
77 /* */
78 /* CALLED BY */
79 /* */
80 /* Application */
81 /* */
82 /* RELEASE HISTORY */
83 /* */
84 /* DATE NAME DESCRIPTION */
85 /* */
86 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
87 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
88 /* resulting in version 6.1 */
89 /* */
90 /**************************************************************************/
_nx_ip_delete(NX_IP * ip_ptr)91 UINT _nx_ip_delete(NX_IP *ip_ptr)
92 {
93
94 TX_INTERRUPT_SAVE_AREA
95
96 UINT i;
97 NX_IP_DRIVER driver_request;
98 NX_PACKET *raw_packet_head;
99 NX_PACKET *deferred_head;
100 NX_PACKET *icmp_queue_head;
101 NX_PACKET *tcp_queue_head;
102 #ifndef NX_DISABLE_IPV4
103 NX_PACKET *arp_queue_head;
104 NX_PACKET *rarp_queue_head;
105 NX_PACKET *igmp_queue_head;
106 #endif /* !NX_DISABLE_IPV4 */
107
108 /* If trace is enabled, insert this event into the trace buffer. */
109 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_DELETE, ip_ptr, 0, 0, 0, NX_TRACE_IP_EVENTS, 0, 0);
110
111 /* Get mutex protection. */
112 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
113
114 /* Determine if the IP instance has any sockets bound to it. */
115 if ((ip_ptr -> nx_ip_udp_created_sockets_count) || (ip_ptr -> nx_ip_tcp_created_sockets_count))
116 {
117
118 /* Still sockets bound to this IP instance. They must all be deleted prior
119 to deleting the IP instance. Release the mutex and return
120 an error code. */
121 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
122
123 return(NX_SOCKETS_BOUND);
124 }
125
126 /* Call through every link driver to disable the link. */
127 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
128 {
129
130 /* Skip the invalid entries. */
131 if (!(ip_ptr -> nx_ip_interface[i].nx_interface_valid))
132 {
133 continue;
134 }
135
136 driver_request.nx_ip_driver_ptr = ip_ptr;
137 driver_request.nx_ip_driver_command = NX_LINK_DISABLE;
138 driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]);
139
140 /* If trace is enabled, insert this event into the trace buffer. */
141 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_LINK_DISABLE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
142
143 /* Send the driver LINK DISABLE request. */
144 (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
145
146 /* Call the link driver to uninitialize. */
147 driver_request.nx_ip_driver_ptr = ip_ptr;
148 driver_request.nx_ip_driver_command = NX_LINK_UNINITIALIZE;
149
150 /* If trace is enabled, insert this event into the trace buffer. */
151 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_UNINITIALIZE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
152
153 /* Send the driver UNITIALIZE request. */
154 (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
155 }
156
157 /* Disable interrupts. */
158 TX_DISABLE
159
160 /* Remove the IP instance from the created list. */
161
162 /* See if the IP instance is the only one on the list. */
163 if (ip_ptr == ip_ptr -> nx_ip_created_next)
164 {
165
166 /* Only created IP instance, just set the created list to NULL. */
167 _nx_ip_created_ptr = TX_NULL;
168 }
169 else
170 {
171
172 /* Otherwise, not the only created IP, link-up the neighbors. */
173 (ip_ptr -> nx_ip_created_next) -> nx_ip_created_previous =
174 ip_ptr -> nx_ip_created_previous;
175 (ip_ptr -> nx_ip_created_previous) -> nx_ip_created_next =
176 ip_ptr -> nx_ip_created_next;
177
178 /* See if we have to update the created list head pointer. */
179 if (_nx_ip_created_ptr == ip_ptr)
180 {
181
182 /* Yes, move the head pointer to the next link. */
183 _nx_ip_created_ptr = ip_ptr -> nx_ip_created_next;
184 }
185 }
186
187 /* Decrement the IP created counter. */
188 _nx_ip_created_count--;
189
190 /* Temporarily disable preemption. */
191 _tx_thread_preempt_disable++;
192
193 /* Release any raw packets queued up. */
194 raw_packet_head = ip_ptr -> nx_ip_raw_received_packet_head;
195 ip_ptr -> nx_ip_raw_received_packet_head = NX_NULL;
196 ip_ptr -> nx_ip_raw_received_packet_tail = NX_NULL;
197 ip_ptr -> nx_ip_raw_received_packet_count = 0;
198
199 /* Release all deferred IP packets. */
200 deferred_head = ip_ptr -> nx_ip_deferred_received_packet_head;
201 ip_ptr -> nx_ip_deferred_received_packet_head = NX_NULL;
202 ip_ptr -> nx_ip_deferred_received_packet_tail = NX_NULL;
203
204 /* Release all queued ICMP packets. */
205 icmp_queue_head = ip_ptr -> nx_ip_icmp_queue_head;
206 ip_ptr -> nx_ip_icmp_queue_head = NX_NULL;
207
208 #ifndef NX_DISABLE_IPV4
209 /* Release all queued IGMP packets. */
210 igmp_queue_head = ip_ptr -> nx_ip_igmp_queue_head;
211 ip_ptr -> nx_ip_igmp_queue_head = NX_NULL;
212
213 /* Release all queued ARP packets. */
214 arp_queue_head = ip_ptr -> nx_ip_arp_deferred_received_packet_head;
215 ip_ptr -> nx_ip_arp_deferred_received_packet_head = NX_NULL;
216 ip_ptr -> nx_ip_arp_deferred_received_packet_tail = NX_NULL;
217
218 /* Release all queued RARP packets. */
219 rarp_queue_head = ip_ptr -> nx_ip_rarp_deferred_received_packet_head;
220 ip_ptr -> nx_ip_rarp_deferred_received_packet_head = NX_NULL;
221 ip_ptr -> nx_ip_rarp_deferred_received_packet_tail = NX_NULL;
222 #endif /* !NX_DISABLE_IPV4 */
223
224 /* Release all queued TCP packets. */
225 tcp_queue_head = ip_ptr -> nx_ip_tcp_queue_head;
226 ip_ptr -> nx_ip_tcp_queue_head = NX_NULL;
227 ip_ptr -> nx_ip_tcp_queue_tail = NX_NULL;
228
229 /* Restore interrupts. */
230 TX_RESTORE
231
232 /* Release mutex protection. */
233 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
234
235 /* Deactivate and delete the IP periodic timer. */
236 tx_timer_deactivate(&(ip_ptr -> nx_ip_periodic_timer));
237 tx_timer_delete(&(ip_ptr -> nx_ip_periodic_timer));
238
239 /* Determine if the fast timer has been created. */
240 if (ip_ptr -> nx_ip_fast_periodic_timer_created)
241 {
242
243 /* Yes. Deactivate and delete the IP fast periodic timer. */
244 tx_timer_deactivate(&(ip_ptr -> nx_ip_fast_periodic_timer));
245 tx_timer_delete(&(ip_ptr -> nx_ip_fast_periodic_timer));
246 ip_ptr -> nx_ip_fast_periodic_timer_created = 0;
247 }
248
249 /* Terminate the internal IP thread. */
250 tx_thread_terminate(&(ip_ptr -> nx_ip_thread));
251
252 /* Delete the internal IP protection mutex. */
253 tx_mutex_delete(&(ip_ptr -> nx_ip_protection));
254
255 /* Delete the internal IP event flag object. */
256 tx_event_flags_delete(&(ip_ptr -> nx_ip_events));
257
258 /* Delete the internal IP thread for handling more processing intensive
259 duties. */
260 tx_thread_delete(&(ip_ptr -> nx_ip_thread));
261
262 /* Release any raw packets queued up. */
263 if (raw_packet_head)
264 {
265 _nx_ip_delete_queue_clear(raw_packet_head);
266 }
267
268 /* Release any deferred IP packets. */
269 if (deferred_head)
270 {
271 _nx_ip_delete_queue_clear(deferred_head);
272 }
273
274 /* Release any queued ICMP packets. */
275 if (icmp_queue_head)
276 {
277 _nx_ip_delete_queue_clear(icmp_queue_head);
278 }
279
280 /* Release any queued TCP packets. */
281 if (tcp_queue_head)
282 {
283 _nx_ip_delete_queue_clear(tcp_queue_head);
284 }
285
286 #ifndef NX_DISABLE_IPV4
287 /* Release any queued ARP packets. */
288 if (arp_queue_head)
289 {
290 _nx_ip_delete_queue_clear(arp_queue_head);
291 }
292
293 /* Release any queued RARP packets. */
294 if (rarp_queue_head)
295 {
296 _nx_ip_delete_queue_clear(rarp_queue_head);
297 }
298
299 /* Release any queued IGMP packets. */
300 if (igmp_queue_head)
301 {
302 _nx_ip_delete_queue_clear(igmp_queue_head);
303 }
304 #endif /* !NX_DISABLE_IPV4 */
305
306 /* Lift any suspension on RAW IP packet receives. */
307 while (ip_ptr -> nx_ip_raw_packet_suspension_list)
308 {
309
310 /* Release the suspended thread. */
311 _nx_ip_raw_packet_cleanup(ip_ptr -> nx_ip_raw_packet_suspension_list NX_CLEANUP_ARGUMENT);
312 }
313
314 /* Lift any suspension on ICMP ping requests. */
315 while (ip_ptr -> nx_ip_icmp_ping_suspension_list)
316 {
317
318 /* Release the suspended thread. */
319 _nx_icmp_cleanup(ip_ptr -> nx_ip_icmp_ping_suspension_list NX_CLEANUP_ARGUMENT);
320 }
321
322 /* Determine if fragment processing was enabled. */
323 if (ip_ptr -> nx_ip_fragment_processing)
324 {
325
326 /* Yes, disable fragment processing, which will release all outstanding
327 fragmented packets. */
328 _nx_ip_fragment_disable(ip_ptr);
329 }
330
331 #ifndef NX_DISABLE_IPV4
332 /* Invalidate dynamic ARP entries. */
333 _nx_arp_dynamic_entries_invalidate(ip_ptr);
334 #endif /* !NX_DISABLE_IPV4 */
335
336 #ifdef FEATURE_NX_IPV6
337 /* Invalidate ND cache. */
338 _nxd_nd_cache_invalidate(ip_ptr);
339 #endif /* FEATURE_NX_IPV6 */
340
341 /* Clear the IP ID to make it invalid. */
342 ip_ptr -> nx_ip_id = 0;
343
344 /* Disable interrupts. */
345 TX_DISABLE
346
347 /* Restore preemption. */
348 _tx_thread_preempt_disable--;
349
350 /* Restore interrupts. */
351 TX_RESTORE
352
353 /* Check for preemption. */
354 _tx_thread_system_preempt_check();
355
356 /* Return success to the caller. */
357 return(NX_SUCCESS);
358 }
359
360