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