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