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 /**   Packet Pool Management (Packet)                                     */
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_packet.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _nx_packet_release                                  PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Yuxin Zhou, Microsoft Corporation                                   */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function releases the packet chain back to the appropriate     */
46 /*    packet pools.                                                       */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    packet_ptr                            Pointer of packet to release  */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    status                                Completion status             */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _tx_thread_system_resume              Resume suspended thread       */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    Application Code                                                    */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
69 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*                                                                        */
72 /**************************************************************************/
_nx_packet_release(NX_PACKET * packet_ptr)73 UINT  _nx_packet_release(NX_PACKET *packet_ptr)
74 {
75 
76 TX_INTERRUPT_SAVE_AREA
77 
78 NX_PACKET_POOL *pool_ptr;       /* Pool pointer            */
79 TX_THREAD      *thread_ptr;     /* Working thread pointer  */
80 #ifndef NX_DISABLE_PACKET_CHAIN
81 NX_PACKET      *next_packet;    /* Working block pointer   */
82 #endif /* NX_DISABLE_PACKET_CHAIN */
83 
84 
85     /* If trace is enabled, insert this event into the trace buffer.  */
86     NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_RELEASE, packet_ptr, packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next, (packet_ptr -> nx_packet_pool_owner) -> nx_packet_pool_available, 0, NX_TRACE_PACKET_EVENTS, 0, 0);
87 
88 #ifndef NX_DISABLE_PACKET_CHAIN
89     /* Loop to free all packets chained together, not assuming they are
90        from the same pool.  */
91     while (packet_ptr)
92     {
93 #endif /* NX_DISABLE_PACKET_CHAIN */
94 
95         /* Check to see if the packet is releasable.  */
96         /*lint -e{923} suppress cast of ULONG to pointer.  */
97         if (packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next != ((NX_PACKET *)NX_PACKET_ALLOCATED))
98         {
99 
100 #ifndef NX_DISABLE_PACKET_INFO
101             /* Pickup the pool pointer.  */
102             pool_ptr =  packet_ptr -> nx_packet_pool_owner;
103 
104             /* Check for a good pool pointer...  error must be the packet!  */
105             if ((pool_ptr) && (pool_ptr -> nx_packet_pool_id == NX_PACKET_POOL_ID))
106             {
107 
108                 /* Increment the packet pool invalid release error count.  */
109                 pool_ptr -> nx_packet_pool_invalid_releases++;
110             }
111 #endif
112 
113             /* Return an error indicating the packet could not be released.  */
114             return(NX_PTR_ERROR);
115         }
116         /* End of packet check.  */
117 
118 #ifndef NX_DISABLE_PACKET_CHAIN
119         /* Pickup the next packet. */
120         next_packet =  packet_ptr -> nx_packet_next;
121 #endif /* NX_DISABLE_PACKET_CHAIN */
122 
123         /* Add debug information. */
124         NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
125 
126         /* Disable interrupts to put this packet back in the packet pool.  */
127         TX_DISABLE
128 
129         /* Pickup the pool pointer.  */
130         pool_ptr =  packet_ptr -> nx_packet_pool_owner;
131 
132         /* Determine if there are any threads suspended on the block pool.  */
133         thread_ptr =  pool_ptr -> nx_packet_pool_suspension_list;
134         if (thread_ptr)
135         {
136 
137             /* Remove the suspended thread from the list.  */
138 
139             /* See if this is the only suspended thread on the list.  */
140             if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
141             {
142 
143                 /* Yes, the only suspended thread.  */
144 
145                 /* Update the head pointer.  */
146                 pool_ptr -> nx_packet_pool_suspension_list =  NX_NULL;
147             }
148             else
149             {
150 
151                 /* At least one more thread is on the same expiration list.  */
152 
153                 /* Update the list head pointer.  */
154                 pool_ptr -> nx_packet_pool_suspension_list =  thread_ptr -> tx_thread_suspended_next;
155 
156                 /* Update the links of the adjacent threads.  */
157                 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous =
158                     thread_ptr -> tx_thread_suspended_previous;
159                 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
160                     thread_ptr -> tx_thread_suspended_next;
161             }
162 
163             /* Decrement the suspension count.  */
164             pool_ptr -> nx_packet_pool_suspended_count--;
165 
166             /* Prepare for resumption of the first thread.  */
167 
168             /* Clear cleanup routine to avoid timeout.  */
169             thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
170 
171             /* Temporarily disable preemption.  */
172             _tx_thread_preempt_disable++;
173 
174             /* Restore interrupts.  */
175             TX_RESTORE
176 
177             /* Adjust this packet to look just like a new packet.  */
178             packet_ptr -> nx_packet_queue_next  =  NX_NULL;
179 #ifndef NX_DISABLE_PACKET_CHAIN
180             packet_ptr -> nx_packet_next        =  NX_NULL;
181             packet_ptr -> nx_packet_last        =  NX_NULL;
182 #endif /* NX_DISABLE_PACKET_CHAIN */
183             packet_ptr -> nx_packet_length      =  0;
184             packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_data_start + (thread_ptr -> tx_thread_suspend_info);
185             packet_ptr -> nx_packet_append_ptr  =  packet_ptr -> nx_packet_prepend_ptr;
186             packet_ptr -> nx_packet_address.nx_packet_interface_ptr = NX_NULL;
187 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
188             packet_ptr -> nx_packet_interface_capability_flag = 0;
189 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
190             /* Set the TCP queue to the value that indicates it has been allocated.  */
191             /*lint -e{923} suppress cast of ULONG to pointer.  */
192             packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next =  (NX_PACKET *)NX_PACKET_ALLOCATED;
193 
194 #ifdef FEATURE_NX_IPV6
195 
196             /* Clear the option state. */
197             packet_ptr -> nx_packet_option_state = 0;
198 #endif /* FEATURE_NX_IPV6 */
199 
200 #ifdef NX_IPSEC_ENABLE
201 
202             /* Clear the ipsec state. */
203             packet_ptr -> nx_packet_ipsec_state = 0;
204 #endif /* NX_IPSEC_ENABLE */
205 
206             /* Clear the IP version.  */
207             packet_ptr -> nx_packet_ip_version  =  0;
208 
209             /* Clear the IP identification flag.  */
210             packet_ptr -> nx_packet_identical_copy = NX_FALSE;
211 
212             /* Initialize the IP header length. */
213             packet_ptr -> nx_packet_ip_header_length = 0;
214 
215             /* Return this block pointer to the suspended thread waiting for
216                a block.  */
217             *((NX_PACKET **)thread_ptr -> tx_thread_additional_suspend_info) =  packet_ptr;
218 
219             /* Put return status into the thread control block.  */
220             thread_ptr -> tx_thread_suspend_status =  NX_SUCCESS;
221 
222             /* Resume thread.  */
223             _tx_thread_system_resume(thread_ptr);
224         }
225         else
226         {
227 
228             /* No thread is suspended for a memory block.  */
229 
230             /* Mark the packet as free.  */
231             /*lint -e{923} suppress cast of ULONG to pointer.  */
232             packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next =  (NX_PACKET *)NX_PACKET_FREE;
233 
234             /* Put the packet back in the available list.  */
235             packet_ptr -> nx_packet_queue_next =  pool_ptr -> nx_packet_pool_available_list;
236 
237             /* Adjust the head pointer.  */
238             pool_ptr -> nx_packet_pool_available_list =  packet_ptr;
239 
240             /* Increment the count of available blocks.  */
241             pool_ptr -> nx_packet_pool_available++;
242 
243             /* Restore interrupts.  */
244             TX_RESTORE
245         }
246 
247 #ifndef NX_DISABLE_PACKET_CHAIN
248         /* Move to the next packet in the list.  */
249         packet_ptr =  next_packet;
250     }
251 #endif /* NX_DISABLE_PACKET_CHAIN */
252 
253     /* Return completion status.  */
254     return(NX_SUCCESS);
255 }
256 
257