mbuf: add timestamp dynamic field and flag (example)
[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 features require to store data inside the mbuf. As the room in
13  * 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 typical use case is when a specific offload feature requires to
26  * register a dedicated offload field in the mbuf structure, and adding
27  * a static field or flag is not justified.
28  *
29  * Example of use:
30  *
31  * - A rte_mbuf_dynfield structure is defined, containing the parameters
32  *   of the dynamic field to be registered:
33  *   const struct rte_mbuf_dynfield rte_dynfield_my_feature = { ... };
34  * - The application initializes the PMD, and asks for this feature
35  *   at port initialization by passing DEV_RX_OFFLOAD_MY_FEATURE in
36  *   rxconf. This will make the PMD to register the field by calling
37  *   rte_mbuf_dynfield_register(&rte_dynfield_my_feature). The PMD
38  *   stores the returned offset.
39  * - The application that uses the offload feature also registers
40  *   the field to retrieve the same offset.
41  * - When the PMD receives a packet, it can set the field:
42  *   *RTE_MBUF_DYNFIELD(m, offset, <type *>) = value;
43  * - In the main loop, the application can retrieve the value with
44  *   the same macro.
45  *
46  * To avoid wasting space, the dynamic fields or flags must only be
47  * reserved on demand, when an application asks for the related feature.
48  *
49  * The registration can be done at any moment, but it is not possible
50  * to unregister fields or flags for now.
51  *
52  * A dynamic field can be reserved and used by an application only.
53  * It can for instance be a packet mark.
54  */
55
56 #include <sys/types.h>
57 #include <stdint.h>
58 #include <stdbool.h>
59
60 /**
61  * Maximum length of the dynamic field or flag string.
62  */
63 #define RTE_MBUF_DYN_NAMESIZE 64
64
65 /**
66  * Structure describing the parameters of a mbuf dynamic field.
67  */
68 struct rte_mbuf_dynfield {
69         char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the field. */
70         size_t size;        /**< The number of bytes to reserve. */
71         size_t align;       /**< The alignment constraint (power of 2). */
72         unsigned int flags; /**< Reserved for future use, must be 0. */
73 };
74
75 /**
76  * Structure describing the parameters of a mbuf dynamic flag.
77  */
78 struct rte_mbuf_dynflag {
79         char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the dynamic flag. */
80         unsigned int flags; /**< Reserved for future use, must be 0. */
81 };
82
83 /**
84  * Register space for a dynamic field in the mbuf structure.
85  *
86  * If the field is already registered (same name and parameters), its
87  * offset is returned.
88  *
89  * @param params
90  *   A structure containing the requested parameters (name, size,
91  *   alignment constraint and flags).
92  * @return
93  *   The offset in the mbuf structure, or -1 on error.
94  *   Possible values for rte_errno:
95  *   - EINVAL: invalid parameters (size, align, or flags).
96  *   - EEXIST: this name is already register with different parameters.
97  *   - EPERM: called from a secondary process.
98  *   - ENOENT: not enough room in mbuf.
99  *   - ENOMEM: allocation failure.
100  *   - ENAMETOOLONG: name does not ends with \0.
101  */
102 __rte_experimental
103 int rte_mbuf_dynfield_register(const struct rte_mbuf_dynfield *params);
104
105 /**
106  * Lookup for a registered dynamic mbuf field.
107  *
108  * @param name
109  *   A string identifying the dynamic field.
110  * @param params
111  *   If not NULL, and if the lookup is successful, the structure is
112  *   filled with the parameters of the dynamic field.
113  * @return
114  *   The offset of this field in the mbuf structure, or -1 on error.
115  *   Possible values for rte_errno:
116  *   - ENOENT: no dynamic field matches this name.
117  */
118 __rte_experimental
119 int rte_mbuf_dynfield_lookup(const char *name,
120                         struct rte_mbuf_dynfield *params);
121
122 /**
123  * Register a dynamic flag in the mbuf structure.
124  *
125  * If the flag is already registered (same name and parameters), its
126  * offset is returned.
127  *
128  * @param params
129  *   A structure containing the requested parameters of the dynamic
130  *   flag (name and options).
131  * @return
132  *   The number of the reserved bit, or -1 on error.
133  *   Possible values for rte_errno:
134  *   - EINVAL: invalid parameters (size, align, or flags).
135  *   - EEXIST: this name is already register with different parameters.
136  *   - EPERM: called from a secondary process.
137  *   - ENOENT: no more flag available.
138  *   - ENOMEM: allocation failure.
139  *   - ENAMETOOLONG: name is longer than RTE_MBUF_DYN_NAMESIZE - 1.
140  */
141 __rte_experimental
142 int rte_mbuf_dynflag_register(const struct rte_mbuf_dynflag *params);
143
144 /**
145  * Lookup for a registered dynamic mbuf flag.
146  *
147  * @param name
148  *   A string identifying the dynamic flag.
149  * @param params
150  *   If not NULL, and if the lookup is successful, the structure is
151  *   filled with the parameters of the dynamic flag.
152  * @return
153  *   The offset of this flag in the mbuf structure, or -1 on error.
154  *   Possible values for rte_errno:
155  *   - ENOENT: no dynamic flag matches this name.
156  */
157 __rte_experimental
158 int rte_mbuf_dynflag_lookup(const char *name,
159                         struct rte_mbuf_dynflag *params);
160
161 /**
162  * Helper macro to access to a dynamic field.
163  */
164 #define RTE_MBUF_DYNFIELD(m, offset, type) ((type)((uintptr_t)(m) + (offset)))
165
166 /* Placeholder for dynamic fields and flags declarations. */
167 extern const struct rte_mbuf_dynfield rte_mbuf_dynfield_timestamp;
168 extern int rte_mbuf_dynfield_timestamp_offset;
169 extern const struct rte_mbuf_dynflag rte_mbuf_dynflag_timestamp;
170 extern int rte_mbuf_dynflag_timestamp_bitnum;
171
172 /**
173  * Register timestamp dynamic field and flag.
174  *
175  * @return
176  *   0 on success, or -1 on error (rte_errno is set, see
177  *   rte_mbuf_dynfield_register() and rte_mbuf_dynflag_register()
178  *   for details).
179  */
180 __rte_experimental
181 int rte_mbuf_dyn_timestamp_register(void);
182
183 /**
184  * Set timestamp dynamic field and flag in mbuf.
185  *
186  * rte_mbuf_dyn_timestamp_register() must have been called first.
187  */
188 __rte_experimental
189 static inline void rte_mbuf_dyn_timestamp_set(struct rte_mbuf *m,
190                                         uint64_t timestamp)
191 {
192         *RTE_MBUF_DYNFIELD(m, rte_mbuf_dynfield_timestamp_offset,
193                         uint64_t *) = timestamp;
194         m->ol_flags |= (1UL << rte_mbuf_dynflag_timestamp_bitnum);
195 }
196
197 /**
198  * Get timestamp dynamic field value in mbuf.
199  *
200  * rte_mbuf_dyn_timestamp_register() must have been called first.
201  */
202 __rte_experimental
203 static inline uint64_t rte_mbuf_dyn_timestamp_get(const struct rte_mbuf *m)
204 {
205         return *RTE_MBUF_DYNFIELD(m, rte_mbuf_dynfield_timestamp_offset,
206                                 uint64_t *);
207 }
208
209 /**
210  * Delete the timestamp dynamic flag in mbuf.
211  *
212  * rte_mbuf_dyn_timestamp_register() must have been called first.
213  */
214 __rte_experimental
215 static inline void rte_mbuf_dyn_timestamp_del(struct rte_mbuf *m)
216 {
217         m->ol_flags &= ~(1UL << rte_mbuf_dynflag_timestamp_bitnum);
218 }
219
220 /**
221  * Check timestamp dynamic flag value in mbuf.
222  *
223  * rte_mbuf_dyn_timestamp_register() must have been called first.
224  */
225 __rte_experimental
226 static inline bool rte_mbuf_dyn_timestamp_avail(const struct rte_mbuf *m)
227 {
228         return m->ol_flags & (1UL << rte_mbuf_dynflag_timestamp_bitnum);
229 }
230
231
232 #endif