mbuf: support dynamic fields and flags
[dpdk.git] / lib / librte_mbuf / rte_mbuf_dyn.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2019 6WIND S.A.
3  */
4
5 #ifndef _RTE_MBUF_DYN_H_
6 #define _RTE_MBUF_DYN_H_
7
8 /**
9  * @file
10  * RTE Mbuf dynamic fields and flags
11  *
12  * Many DPDK features require to store data inside the mbuf. As the room
13  * in mbuf structure is limited, it is not possible to have a field for
14  * each feature. Also, changing fields in the mbuf structure can break
15  * the API or ABI.
16  *
17  * This module addresses this issue, by enabling the dynamic
18  * registration of fields or flags:
19  *
20  * - a dynamic field is a named area in the rte_mbuf structure, with a
21  *   given size (>= 1 byte) and alignment constraint.
22  * - a dynamic flag is a named bit in the rte_mbuf structure, stored
23  *   in mbuf->ol_flags.
24  *
25  * The placement of the field or flag can be automatic, in this case the
26  * zones that have the smallest size and alignment constraint are
27  * selected in priority. Else, a specific field offset or flag bit
28  * number can be requested through the API.
29  *
30  * The typical use case is when a specific offload feature requires to
31  * register a dedicated offload field in the mbuf structure, and adding
32  * a static field or flag is not justified.
33  *
34  * Example of use:
35  *
36  * - A rte_mbuf_dynfield structure is defined, containing the parameters
37  *   of the dynamic field to be registered:
38  *   const struct rte_mbuf_dynfield rte_dynfield_my_feature = { ... };
39  * - The application initializes the PMD, and asks for this feature
40  *   at port initialization by passing DEV_RX_OFFLOAD_MY_FEATURE in
41  *   rxconf. This will make the PMD to register the field by calling
42  *   rte_mbuf_dynfield_register(&rte_dynfield_my_feature). The PMD
43  *   stores the returned offset.
44  * - The application that uses the offload feature also registers
45  *   the field to retrieve the same offset.
46  * - When the PMD receives a packet, it can set the field:
47  *   *RTE_MBUF_DYNFIELD(m, offset, <type *>) = value;
48  * - In the main loop, the application can retrieve the value with
49  *   the same macro.
50  *
51  * To avoid wasting space, the dynamic fields or flags must only be
52  * reserved on demand, when an application asks for the related feature.
53  *
54  * The registration can be done at any moment, but it is not possible
55  * to unregister fields or flags for now.
56  *
57  * A dynamic field can be reserved and used by an application only.
58  * It can for instance be a packet mark.
59  *
60  * To avoid namespace collisions, the dynamic mbuf field or flag names
61  * have to be chosen with care. It is advised to use the same
62  * conventions than function names in dpdk:
63  * - "rte_mbuf_dynfield_<name>" if defined in mbuf library
64  * - "rte_<libname>_dynfield_<name>" if defined in another library
65  * - "rte_net_<pmd>_dynfield_<name>" if defined in a in PMD
66  * - any name that does not start with "rte_" in an application
67  */
68
69 #include <sys/types.h>
70 /**
71  * Maximum length of the dynamic field or flag string.
72  */
73 #define RTE_MBUF_DYN_NAMESIZE 64
74
75 /**
76  * Structure describing the parameters of a mbuf dynamic field.
77  */
78 struct rte_mbuf_dynfield {
79         char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the field. */
80         size_t size;        /**< The number of bytes to reserve. */
81         size_t align;       /**< The alignment constraint (power of 2). */
82         unsigned int flags; /**< Reserved for future use, must be 0. */
83 };
84
85 /**
86  * Structure describing the parameters of a mbuf dynamic flag.
87  */
88 struct rte_mbuf_dynflag {
89         char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the dynamic flag. */
90         unsigned int flags; /**< Reserved for future use, must be 0. */
91 };
92
93 /**
94  * Register space for a dynamic field in the mbuf structure.
95  *
96  * If the field is already registered (same name and parameters), its
97  * offset is returned.
98  *
99  * @param params
100  *   A structure containing the requested parameters (name, size,
101  *   alignment constraint and flags).
102  * @return
103  *   The offset in the mbuf structure, or -1 on error.
104  *   Possible values for rte_errno:
105  *   - EINVAL: invalid parameters (size, align, or flags).
106  *   - EEXIST: this name is already register with different parameters.
107  *   - EPERM: called from a secondary process.
108  *   - ENOENT: not enough room in mbuf.
109  *   - ENOMEM: allocation failure.
110  *   - ENAMETOOLONG: name does not ends with \0.
111  */
112 __rte_experimental
113 int rte_mbuf_dynfield_register(const struct rte_mbuf_dynfield *params);
114
115 /**
116  * Register space for a dynamic field in the mbuf structure at offset.
117  *
118  * If the field is already registered (same name, parameters and offset),
119  * the offset is returned.
120  *
121  * @param params
122  *   A structure containing the requested parameters (name, size,
123  *   alignment constraint and flags).
124  * @param offset
125  *   The requested offset. Ignored if SIZE_MAX is passed.
126  * @return
127  *   The offset in the mbuf structure, or -1 on error.
128  *   Possible values for rte_errno:
129  *   - EINVAL: invalid parameters (size, align, flags, or offset).
130  *   - EEXIST: this name is already register with different parameters.
131  *   - EBUSY: the requested offset cannot be used.
132  *   - EPERM: called from a secondary process.
133  *   - ENOENT: not enough room in mbuf.
134  *   - ENOMEM: allocation failure.
135  *   - ENAMETOOLONG: name does not ends with \0.
136  */
137 __rte_experimental
138 int rte_mbuf_dynfield_register_offset(const struct rte_mbuf_dynfield *params,
139                                 size_t offset);
140
141 /**
142  * Lookup for a registered dynamic mbuf field.
143  *
144  * @param name
145  *   A string identifying the dynamic field.
146  * @param params
147  *   If not NULL, and if the lookup is successful, the structure is
148  *   filled with the parameters of the dynamic field.
149  * @return
150  *   The offset of this field in the mbuf structure, or -1 on error.
151  *   Possible values for rte_errno:
152  *   - ENOENT: no dynamic field matches this name.
153  */
154 __rte_experimental
155 int rte_mbuf_dynfield_lookup(const char *name,
156                         struct rte_mbuf_dynfield *params);
157
158 /**
159  * Register a dynamic flag in the mbuf structure.
160  *
161  * If the flag is already registered (same name and parameters), its
162  * bitnum is returned.
163  *
164  * @param params
165  *   A structure containing the requested parameters of the dynamic
166  *   flag (name and options).
167  * @return
168  *   The number of the reserved bit, or -1 on error.
169  *   Possible values for rte_errno:
170  *   - EINVAL: invalid parameters (size, align, or flags).
171  *   - EEXIST: this name is already register with different parameters.
172  *   - EPERM: called from a secondary process.
173  *   - ENOENT: no more flag available.
174  *   - ENOMEM: allocation failure.
175  *   - ENAMETOOLONG: name is longer than RTE_MBUF_DYN_NAMESIZE - 1.
176  */
177 __rte_experimental
178 int rte_mbuf_dynflag_register(const struct rte_mbuf_dynflag *params);
179
180 /**
181  * Register a dynamic flag in the mbuf structure specifying bitnum.
182  *
183  * If the flag is already registered (same name, parameters and bitnum),
184  * the bitnum is returned.
185  *
186  * @param params
187  *   A structure containing the requested parameters of the dynamic
188  *   flag (name and options).
189  * @param bitnum
190  *   The requested bitnum. Ignored if UINT_MAX is passed.
191  * @return
192  *   The number of the reserved bit, or -1 on error.
193  *   Possible values for rte_errno:
194  *   - EINVAL: invalid parameters (size, align, or flags).
195  *   - EEXIST: this name is already register with different parameters.
196  *   - EBUSY: the requested bitnum cannot be used.
197  *   - EPERM: called from a secondary process.
198  *   - ENOENT: no more flag available.
199  *   - ENOMEM: allocation failure.
200  *   - ENAMETOOLONG: name is longer than RTE_MBUF_DYN_NAMESIZE - 1.
201  */
202 __rte_experimental
203 int rte_mbuf_dynflag_register_bitnum(const struct rte_mbuf_dynflag *params,
204                                 unsigned int bitnum);
205
206 /**
207  * Lookup for a registered dynamic mbuf flag.
208  *
209  * @param name
210  *   A string identifying the dynamic flag.
211  * @param params
212  *   If not NULL, and if the lookup is successful, the structure is
213  *   filled with the parameters of the dynamic flag.
214  * @return
215  *   The offset of this flag in the mbuf structure, or -1 on error.
216  *   Possible values for rte_errno:
217  *   - ENOENT: no dynamic flag matches this name.
218  */
219 __rte_experimental
220 int rte_mbuf_dynflag_lookup(const char *name,
221                         struct rte_mbuf_dynflag *params);
222
223 /**
224  * Helper macro to access to a dynamic field.
225  */
226 #define RTE_MBUF_DYNFIELD(m, offset, type) ((type)((uintptr_t)(m) + (offset)))
227
228 /**
229  * Dump the status of dynamic fields and flags.
230  *
231  * @param out
232  *   The stream where the status is displayed.
233  */
234 __rte_experimental
235 void rte_mbuf_dyn_dump(FILE *out);
236
237 /* Placeholder for dynamic fields and flags declarations. */
238
239 #endif