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 /** Packet Pool Management (Packet) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_packet.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nx_packet_pool_create PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Yuxin Zhou, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function creates a pool of fixed-size packets within the */
44 /* specified memory area. */
45 /* */
46 /* INPUT */
47 /* */
48 /* pool_ptr Packet Pool control block */
49 /* name_ptr Packet Pool string pointer */
50 /* payload_size Size of packet payload */
51 /* pool_start Starting address of pool */
52 /* pool_size Number of bytes in pool */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Return status */
57 /* */
58 /* CALLS */
59 /* */
60 /* None */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* Application Code */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
71 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_nx_packet_pool_create(NX_PACKET_POOL * pool_ptr,CHAR * name_ptr,ULONG payload_size,VOID * pool_start,ULONG pool_size)75 UINT _nx_packet_pool_create(NX_PACKET_POOL *pool_ptr, CHAR *name_ptr, ULONG payload_size,
76 VOID *pool_start, ULONG pool_size)
77 {
78
79 TX_INTERRUPT_SAVE_AREA
80
81 NX_PACKET_POOL *tail_ptr; /* Working packet pool pointer */
82 ULONG packets; /* Number of packets in pool */
83 ULONG original_payload_size; /* Original payload size */
84 ULONG header_size; /* Rounded header size */
85 CHAR *packet_ptr; /* Working packet pointer */
86 CHAR *next_packet_ptr; /* Next packet pointer */
87 CHAR *end_of_pool; /* End of pool area */
88 CHAR *payload_address; /* Address of the first payload*/
89 VOID *rounded_pool_start; /* Rounded stating address */
90
91
92 /* Save the original payload size. */
93 original_payload_size = payload_size;
94
95 /* Align the starting address to four bytes. */
96 /*lint -e{923} suppress cast between ULONG and pointer. */
97 rounded_pool_start = (VOID *)((((ALIGN_TYPE)pool_start + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
98
99 /* Round the pool size down to something that is evenly divisible by alignment. */
100 /*lint -e{923} suppress cast between ULONG and pointer. */
101 pool_size = (ULONG)(((pool_size - ((ALIGN_TYPE)rounded_pool_start - (ALIGN_TYPE)pool_start)) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
102
103 /* Set the pool starting address. */
104 pool_start = rounded_pool_start;
105
106 /* Calculate the address of payload. */
107 /*lint -e{923} suppress cast between ULONG and pointer. */
108 payload_address = (CHAR *)((ALIGN_TYPE)rounded_pool_start + sizeof(NX_PACKET));
109
110 /* Align the address of payload. */
111 /*lint -e{923} suppress cast between ULONG and pointer. */
112 payload_address = (CHAR *)((((ALIGN_TYPE)payload_address + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
113
114 /* Calculate the header size. */
115 /*lint -e{923} suppress cast between ULONG and pointer. */
116 header_size = (ULONG)((ALIGN_TYPE)payload_address - (ALIGN_TYPE)rounded_pool_start);
117
118 /* Round the packet size up to something that helps guarantee proper alignment for header and payload. */
119 payload_size = (ULONG)(((header_size + payload_size + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT - header_size);
120
121 /* Clear pool fields. */
122 memset(pool_ptr, 0, sizeof(NX_PACKET_POOL));
123
124 /* Setup the basic packet pool fields. */
125 pool_ptr -> nx_packet_pool_name = name_ptr;
126 pool_ptr -> nx_packet_pool_suspension_list = TX_NULL;
127 pool_ptr -> nx_packet_pool_suspended_count = 0;
128 pool_ptr -> nx_packet_pool_start = (CHAR *)pool_start;
129 pool_ptr -> nx_packet_pool_size = pool_size;
130 pool_ptr -> nx_packet_pool_payload_size = original_payload_size;
131
132 /* Calculate the end of the pool's memory area. */
133 end_of_pool = ((CHAR *)pool_start) + pool_size;
134
135 /* Walk through the pool area, setting up the available packet list. */
136 packets = 0;
137 packet_ptr = (CHAR *)rounded_pool_start;
138 next_packet_ptr = packet_ptr + (payload_size + header_size);
139
140 /*lint -e{946} suppress pointer subtraction, since it is necessary. */
141 while (next_packet_ptr <= end_of_pool)
142 {
143
144 /* Yes, we have another packet. Increment the packet count. */
145 packets++;
146
147 /* Setup the link to the next packet. */
148 /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
149 ((NX_PACKET *)packet_ptr) -> nx_packet_queue_next = (NX_PACKET *)next_packet_ptr;
150
151 /* Remember that this packet pool is the owner. */
152 /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
153 ((NX_PACKET *)packet_ptr) -> nx_packet_pool_owner = pool_ptr;
154
155 #ifndef NX_DISABLE_PACKET_CHAIN
156 /* Clear the next packet pointer. */
157 /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
158 ((NX_PACKET *)packet_ptr) -> nx_packet_next = (NX_PACKET *)NX_NULL;
159 #endif /* NX_DISABLE_PACKET_CHAIN */
160
161 /* Mark the packet as free. */
162 /*lint -e{929} -e{923} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
163 ((NX_PACKET *)packet_ptr) -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_FREE;
164
165 /* Setup the packet data pointers. */
166 /*lint -e{929} -e{928} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
167 ((NX_PACKET *)packet_ptr) -> nx_packet_data_start = (UCHAR *)(packet_ptr + header_size);
168
169 /*lint -e{929} -e{928} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
170 ((NX_PACKET *)packet_ptr) -> nx_packet_data_end = (UCHAR *)(packet_ptr + header_size + original_payload_size);
171
172 /* Add debug information. */
173 NX_PACKET_DEBUG(__FILE__, __LINE__, (NX_PACKET *)packet_ptr);
174
175 /* Advance to the next packet. */
176 packet_ptr = next_packet_ptr;
177
178 /* Update the next packet pointer. */
179 next_packet_ptr = packet_ptr + (payload_size + header_size);
180 }
181
182 /* Backup to the last packet in the pool. */
183 packet_ptr = packet_ptr - (payload_size + header_size);
184
185 /* Set the last packet's forward pointer to NULL. */
186 /*lint -e{929} -e{740} -e{826} suppress cast of pointer to pointer, since it is necessary */
187 ((NX_PACKET *)packet_ptr) -> nx_packet_queue_next = NX_NULL;
188
189 /* Save the remaining information in the pool control packet. */
190 pool_ptr -> nx_packet_pool_available = packets;
191 pool_ptr -> nx_packet_pool_total = packets;
192
193 /* Set the packet pool available list. */
194 pool_ptr -> nx_packet_pool_available_list = (NX_PACKET *)pool_start;
195
196 /* If trace is enabled, register this object. */
197 NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_PACKET_POOL, pool_ptr, name_ptr, payload_size, packets);
198
199 /* If trace is enabled, insert this event into the trace buffer. */
200 NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_POOL_CREATE, pool_ptr, payload_size, pool_start, pool_size, NX_TRACE_PACKET_EVENTS, 0, 0);
201
202 /* Disable interrupts to place the packet pool on the created list. */
203 TX_DISABLE
204
205 /* Setup the packet pool ID to make it valid. */
206 pool_ptr -> nx_packet_pool_id = NX_PACKET_POOL_ID;
207
208 /* Place the packet pool on the list of created packet pools. First,
209 check for an empty list. */
210 if (_nx_packet_pool_created_ptr)
211 {
212
213 /* Pickup tail pointer. */
214 tail_ptr = _nx_packet_pool_created_ptr -> nx_packet_pool_created_previous;
215
216 /* Place the new packet pool in the list. */
217 _nx_packet_pool_created_ptr -> nx_packet_pool_created_previous = pool_ptr;
218 tail_ptr -> nx_packet_pool_created_next = pool_ptr;
219
220 /* Setup this packet pool's created links. */
221 pool_ptr -> nx_packet_pool_created_previous = tail_ptr;
222 pool_ptr -> nx_packet_pool_created_next = _nx_packet_pool_created_ptr;
223 }
224 else
225 {
226
227 /* The created packet pool list is empty. Add packet pool to empty list. */
228 _nx_packet_pool_created_ptr = pool_ptr;
229 pool_ptr -> nx_packet_pool_created_next = pool_ptr;
230 pool_ptr -> nx_packet_pool_created_previous = pool_ptr;
231 }
232
233 /* Increment the number of packet pools created. */
234 _nx_packet_pool_created_count++;
235
236 /* Restore interrupts. */
237 TX_RESTORE
238
239 /* Return NX_SUCCESS. */
240 return(NX_SUCCESS);
241 }
242
243