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 "nx_packet.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_packet_data_append PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function copies the specified data to the end of the specified */
45 /* packet. Additional packets are allocated from the specified pool */
46 /* if needed. */
47 /* */
48 /* INPUT */
49 /* */
50 /* packet_ptr Pointer to packet to append to*/
51 /* data_start Pointer to start of the data */
52 /* data_size Number of bytes to append */
53 /* pool_ptr Pool to allocate packet from */
54 /* wait_option Suspension option */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* status Completion status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _nx_packet_allocate Allocate data packet */
63 /* _nx_packet_release Release data packet */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
74 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
75 /* verified memcpy use cases, */
76 /* resulting in version 6.1 */
77 /* */
78 /**************************************************************************/
_nx_packet_data_append(NX_PACKET * packet_ptr,VOID * data_start,ULONG data_size,NX_PACKET_POOL * pool_ptr,ULONG wait_option)79 UINT _nx_packet_data_append(NX_PACKET *packet_ptr, VOID *data_start, ULONG data_size,
80 NX_PACKET_POOL *pool_ptr, ULONG wait_option)
81 {
82
83 #ifndef NX_DISABLE_PACKET_CHAIN
84 UINT status; /* Return status */
85 NX_PACKET *new_list_ptr; /* Head of new list pointer */
86 NX_PACKET *last_packet = NX_NULL; /* Last supplied packet */
87 #endif /* NX_DISABLE_PACKET_CHAIN */
88 ULONG available_bytes; /* Number of available bytes */
89 ULONG copy_size; /* Size for each memory copy */
90 UCHAR *source_ptr; /* Buffer source pointer */
91 NX_PACKET *work_ptr; /* Working packet pointer */
92
93
94 /* If trace is enabled, insert this event into the trace buffer. */
95 NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_DATA_APPEND, packet_ptr, data_start, data_size, pool_ptr, NX_TRACE_PACKET_EVENTS, 0, 0);
96
97 #ifndef NX_DISABLE_PACKET_CHAIN
98 /* Calculate the number of bytes available at the end of the supplied packet. */
99 if (packet_ptr -> nx_packet_last)
100 {
101
102 /* More than one packet. Walk the packet chain starting at the last packet
103 to calculate the remaining bytes. */
104 available_bytes = 0;
105 work_ptr = packet_ptr -> nx_packet_last;
106 do
107 {
108
109 /* Calculate the available bytes in this packet. */
110 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
111 /*lint -e{737} suppress loss of sign, since nx_packet_data_end is assumed to be larger than nx_packet_append_ptr. */
112 available_bytes = available_bytes +
113 (ULONG)(work_ptr -> nx_packet_data_end - work_ptr -> nx_packet_append_ptr);
114
115 /* Remember the last packet. */
116 last_packet = work_ptr;
117
118 /* Move to the next packet. There typically won't be another packet, but just in
119 case the logic is here for it! */
120 work_ptr = work_ptr -> nx_packet_next;
121 } while (work_ptr);
122 }
123 else
124 #endif /* NX_DISABLE_PACKET_CHAIN */
125 {
126
127 /* Just calculate the number of bytes available in the first packet. */
128 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
129 available_bytes = (ULONG)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
130 }
131
132 /* Determine if any new packets are required to satisfy this request. */
133 if (available_bytes < data_size)
134 {
135
136 #ifndef NX_DISABLE_PACKET_CHAIN
137 /* Setup a temporary head pointer. */
138 new_list_ptr = NX_NULL;
139
140 /* Loop to pickup enough packets to complete the append request. */
141 while (available_bytes < data_size)
142 {
143
144 /* Allocate a new packet. */
145 status = _nx_packet_allocate(pool_ptr, &work_ptr, 0, wait_option);
146
147 /* Determine if an error is present. */
148 if (status)
149 {
150
151 /* Yes, an error is present. */
152
153 /* First release any packets that have been allocated so far. */
154 if (new_list_ptr)
155 {
156 _nx_packet_release(new_list_ptr);
157 }
158
159 /* Return the error status to the caller of this service. */
160 return(status);
161 }
162
163 /* Add debug information. */
164 NX_PACKET_DEBUG(__FILE__, __LINE__, work_ptr);
165
166 /* No error is present. Link the new packet to the temporary list being built. */
167 if (new_list_ptr)
168 {
169
170 /* Determine if there is already more than one packet on the list. */
171 if (new_list_ptr -> nx_packet_last)
172 {
173
174 /* Yes, link up the last packet to the new packet and update the
175 last pointer. */
176 /*lint -e{644} suppress variable might not be initialized, since "work_ptr" was initialized in _nx_packet_allocate. */
177 (new_list_ptr -> nx_packet_last) -> nx_packet_next = work_ptr;
178 new_list_ptr -> nx_packet_last = work_ptr;
179 }
180 else
181 {
182
183 /* Second packet allocated. Just setup the last and next in the
184 head pointer. */
185 new_list_ptr -> nx_packet_last = work_ptr;
186 new_list_ptr -> nx_packet_next = work_ptr;
187 }
188 }
189 else
190 {
191
192 /* Just setup the temporary list head. */
193 new_list_ptr = work_ptr;
194 }
195
196 /* Adjust the number of available bytes according to how much space
197 is in the new packet. */
198 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
199 /*lint -e{737} suppress loss of sign, since nx_packet_data_end is assumed to be larger than nx_packet_append_ptr. */
200 /*lint -e{613} suppress possible use of null pointer, since "work_ptr" was set in _nx_packet_allocate. */
201 available_bytes = available_bytes +
202 (ULONG)(work_ptr -> nx_packet_data_end - work_ptr -> nx_packet_append_ptr);
203 }
204
205 /* At this point, all the necessary packets have been allocated and are present
206 on the temporary list. We need to link this new list to the end of the supplied
207 packet. */
208 if (last_packet)
209 {
210
211 /* Already more than one packet. Add the new packet list to the end. */
212 last_packet -> nx_packet_next = new_list_ptr;
213 }
214 else
215 {
216
217 /* Link the new packet list to the head packet. */
218 packet_ptr -> nx_packet_next = new_list_ptr;
219 }
220
221 /* Clear the last packet that was used to maintain the new list. */
222 /*lint -e{613} suppress possible use of null pointer, since "new_list_ptr" was set in previous loop. */
223 new_list_ptr -> nx_packet_last = NX_NULL;
224 #else
225 NX_PARAMETER_NOT_USED(pool_ptr);
226 NX_PARAMETER_NOT_USED(wait_option);
227
228 return(NX_SIZE_ERROR);
229 #endif /* NX_DISABLE_PACKET_CHAIN */
230 }
231
232 /* Setup the new data length in the packet. */
233 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + data_size;
234
235 /* Now copy the supplied data buffer at the end of the packet. */
236 source_ptr = (UCHAR *)data_start;
237 #ifndef NX_DISABLE_PACKET_CHAIN
238 if (packet_ptr -> nx_packet_last)
239 {
240 work_ptr = packet_ptr -> nx_packet_last;
241 }
242 else
243 {
244 #endif /* NX_DISABLE_PACKET_CHAIN */
245 work_ptr = packet_ptr;
246 #ifndef NX_DISABLE_PACKET_CHAIN
247 }
248 while (data_size)
249 {
250
251 /* Determine the amount of memory to copy. */
252 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
253 if (data_size < (ULONG)(work_ptr -> nx_packet_data_end - work_ptr -> nx_packet_append_ptr))
254 {
255 copy_size = data_size;
256 }
257 else
258 {
259
260 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
261 copy_size = (ULONG)(work_ptr -> nx_packet_data_end - work_ptr -> nx_packet_append_ptr);
262 }
263 #else
264 copy_size = data_size;
265 #endif /* NX_DISABLE_PACKET_CHAIN */
266
267 /* Copy the data into the current packet buffer. */
268 memcpy(work_ptr -> nx_packet_append_ptr, source_ptr, copy_size); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
269
270 /* Adjust the remaining data size. */
271 data_size = data_size - copy_size;
272
273 /* Update this packets append pointer. */
274 work_ptr -> nx_packet_append_ptr = work_ptr -> nx_packet_append_ptr + copy_size;
275
276 #ifndef NX_DISABLE_PACKET_CHAIN
277 /* Any more data left to append? */
278 if (data_size)
279 {
280
281 /* Yes, there is more to move. Update the source pointer, move the work pointer
282 to the next packet in the chain and update the last packet pointer. */
283 source_ptr = source_ptr + copy_size;
284 work_ptr = work_ptr -> nx_packet_next;
285 packet_ptr -> nx_packet_last = work_ptr;
286 }
287 }
288 #endif /* NX_DISABLE_PACKET_CHAIN */
289
290 /* Add debug information. */
291 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
292
293 /* Return successful status. */
294 return(NX_SUCCESS);
295 }
296
297