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_allocate PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function allocates a packet from the specified packet pool. */
46 /* */
47 /* INPUT */
48 /* */
49 /* pool_ptr Pool to allocate packet from */
50 /* packet_ptr Pointer to place allocated */
51 /* packet pointer */
52 /* packet_type Type of packet to allocate */
53 /* wait_option Suspension option */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* status Completion status */
58 /* */
59 /* CALLS */
60 /* */
61 /* _tx_thread_system_suspend Suspend thread */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Application Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
72 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* */
75 /**************************************************************************/
_nx_packet_allocate(NX_PACKET_POOL * pool_ptr,NX_PACKET ** packet_ptr,ULONG packet_type,ULONG wait_option)76 UINT _nx_packet_allocate(NX_PACKET_POOL *pool_ptr, NX_PACKET **packet_ptr,
77 ULONG packet_type, ULONG wait_option)
78 {
79 TX_INTERRUPT_SAVE_AREA
80
81 UINT status; /* Return status */
82 TX_THREAD *thread_ptr; /* Working thread pointer */
83 NX_PACKET *work_ptr; /* Working packet pointer */
84
85 #ifdef TX_ENABLE_EVENT_TRACE
86 TX_TRACE_BUFFER_ENTRY *trace_event;
87 ULONG trace_timestamp;
88 #endif
89
90 /* Make sure the packet_type does not go beyond nx_packet_data_end. */
91 if (pool_ptr -> nx_packet_pool_payload_size < packet_type)
92 {
93 return(NX_INVALID_PARAMETERS);
94 }
95
96 /* Set the return pointer to NULL initially. */
97 *packet_ptr = NX_NULL;
98
99 /* If trace is enabled, insert this event into the trace buffer. */
100 NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_ALLOCATE, pool_ptr, 0, packet_type, pool_ptr -> nx_packet_pool_available, NX_TRACE_PACKET_EVENTS, &trace_event, &trace_timestamp);
101
102 /* Disable interrupts to get a packet from the pool. */
103 TX_DISABLE
104
105 /* Determine if there is an available packet. */
106 if (pool_ptr -> nx_packet_pool_available)
107 {
108
109 /* Yes, a packet is available. Decrement the available count. */
110 pool_ptr -> nx_packet_pool_available--;
111
112 /* Pickup the current packet pointer. */
113 work_ptr = pool_ptr -> nx_packet_pool_available_list;
114
115 /* Modify the available list to point at the next packet in the pool. */
116 pool_ptr -> nx_packet_pool_available_list = work_ptr -> nx_packet_queue_next;
117
118 /* Setup various fields for this packet. */
119 work_ptr -> nx_packet_queue_next = NX_NULL;
120 #ifndef NX_DISABLE_PACKET_CHAIN
121 work_ptr -> nx_packet_next = NX_NULL;
122 work_ptr -> nx_packet_last = NX_NULL;
123 #endif /* NX_DISABLE_PACKET_CHAIN */
124 work_ptr -> nx_packet_length = 0;
125 work_ptr -> nx_packet_prepend_ptr = work_ptr -> nx_packet_data_start + packet_type;
126 work_ptr -> nx_packet_append_ptr = work_ptr -> nx_packet_prepend_ptr;
127 work_ptr -> nx_packet_address.nx_packet_interface_ptr = NX_NULL;
128 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
129 work_ptr -> nx_packet_interface_capability_flag = 0;
130 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
131 /* Set the TCP queue to the value that indicates it has been allocated. */
132 /*lint -e{923} suppress cast of ULONG to pointer. */
133 work_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_ALLOCATED;
134
135 #ifdef FEATURE_NX_IPV6
136
137 /* Clear the option state. */
138 work_ptr -> nx_packet_option_state = 0;
139 #endif /* FEATURE_NX_IPV6 */
140
141 #ifdef NX_IPSEC_ENABLE
142
143 /* Clear the ipsec state. */
144 work_ptr -> nx_packet_ipsec_state = 0;
145 work_ptr -> nx_packet_ipsec_sa_ptr = NX_NULL;
146 #endif /* NX_IPSEC_ENABLE */
147
148 #ifndef NX_DISABLE_IPV4
149 /* Initialize the IP version field */
150 work_ptr -> nx_packet_ip_version = NX_IP_VERSION_V4;
151 #endif /* !NX_DISABLE_IPV4 */
152
153 /* Initialize the IP identification flag. */
154 work_ptr -> nx_packet_identical_copy = NX_FALSE;
155
156 /* Initialize the IP header length. */
157 work_ptr -> nx_packet_ip_header_length = 0;
158
159 #ifdef NX_ENABLE_THREAD
160 work_ptr -> nx_packet_type = 0;
161 #endif /* NX_ENABLE_THREAD */
162
163 /* Place the new packet pointer in the return destination. */
164 *packet_ptr = work_ptr;
165
166 /* Set status to success. */
167 status = NX_SUCCESS;
168
169 /* Add debug information. */
170 NX_PACKET_DEBUG(__FILE__, __LINE__, work_ptr);
171 }
172 else
173 {
174
175 #ifndef NX_DISABLE_PACKET_INFO
176 /* Increment the packet pool empty request count. */
177 pool_ptr -> nx_packet_pool_empty_requests++;
178 #endif
179
180 /* Determine if the request specifies suspension. */
181 if (wait_option)
182 {
183
184 /* Prepare for suspension of this thread. */
185
186 #ifndef NX_DISABLE_PACKET_INFO
187 /* Increment the packet pool empty request suspension count. */
188 pool_ptr -> nx_packet_pool_empty_suspensions++;
189 #endif
190
191 /* Pickup thread pointer. */
192 thread_ptr = _tx_thread_current_ptr;
193
194 /* Setup cleanup routine pointer. */
195 thread_ptr -> tx_thread_suspend_cleanup = _nx_packet_pool_cleanup;
196
197 /* Setup cleanup information, i.e. this pool control
198 block. */
199 thread_ptr -> tx_thread_suspend_control_block = (void *)pool_ptr;
200
201 /* Save the return packet pointer address as well. */
202 thread_ptr -> tx_thread_additional_suspend_info = (void *)packet_ptr;
203
204 /* Save the packet type (or prepend offset) so this can be added
205 after a new packet becomes available. */
206 thread_ptr -> tx_thread_suspend_info = packet_type;
207
208 /* Setup suspension list. */
209 if (pool_ptr -> nx_packet_pool_suspension_list)
210 {
211
212 /* This list is not NULL, add current thread to the end. */
213 thread_ptr -> tx_thread_suspended_next =
214 pool_ptr -> nx_packet_pool_suspension_list;
215 thread_ptr -> tx_thread_suspended_previous =
216 (pool_ptr -> nx_packet_pool_suspension_list) -> tx_thread_suspended_previous;
217 ((pool_ptr -> nx_packet_pool_suspension_list) -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
218 thread_ptr;
219 (pool_ptr -> nx_packet_pool_suspension_list) -> tx_thread_suspended_previous = thread_ptr;
220 }
221 else
222 {
223
224 /* No other threads are suspended. Setup the head pointer and
225 just setup this threads pointers to itself. */
226 pool_ptr -> nx_packet_pool_suspension_list = thread_ptr;
227 thread_ptr -> tx_thread_suspended_next = thread_ptr;
228 thread_ptr -> tx_thread_suspended_previous = thread_ptr;
229 }
230
231 /* Increment the suspended thread count. */
232 pool_ptr -> nx_packet_pool_suspended_count++;
233
234 /* Set the state to suspended. */
235 thread_ptr -> tx_thread_state = TX_TCP_IP;
236
237 /* Set the suspending flag. */
238 thread_ptr -> tx_thread_suspending = TX_TRUE;
239
240 /* Temporarily disable preemption. */
241 _tx_thread_preempt_disable++;
242
243 /* Save the timeout value. */
244 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
245
246 /* Restore interrupts. */
247 TX_RESTORE
248
249 /* Call actual thread suspension routine. */
250 _tx_thread_system_suspend(thread_ptr);
251
252 /* Update the trace event with the status. */
253 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_PACKET_ALLOCATE, 0, *packet_ptr, 0, 0);
254
255 #ifdef NX_ENABLE_PACKET_DEBUG_INFO
256 if (thread_ptr -> tx_thread_suspend_status == NX_SUCCESS)
257 {
258
259 /* Add debug information. */
260 NX_PACKET_DEBUG(__FILE__, __LINE__, *packet_ptr);
261 }
262 #endif /* NX_ENABLE_PACKET_DEBUG_INFO */
263
264 /* Return the completion status. */
265 return(thread_ptr -> tx_thread_suspend_status);
266 }
267 else
268 {
269
270 /* Immediate return, return error completion. */
271 status = NX_NO_PACKET;
272 }
273 }
274
275 /* Restore interrupts. */
276 TX_RESTORE
277
278 /* Update the trace event with the status. */
279 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_PACKET_ALLOCATE, 0, *packet_ptr, 0, 0);
280
281 /* Return completion status. */
282 return(status);
283 }
284
285