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 RTE_ETH_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 PMD 66 * - any name that does not start with "rte_" in an application 67 */ 68 69 #include <stdio.h> 70 #include <stdint.h> 71 72 73 #ifdef __cplusplus 74 extern "C" { 75 #endif 76 77 /** 78 * Maximum length of the dynamic field or flag string. 79 */ 80 #define RTE_MBUF_DYN_NAMESIZE 64 81 82 /** 83 * Structure describing the parameters of a mbuf dynamic field. 84 */ 85 struct rte_mbuf_dynfield { 86 char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the field. */ 87 size_t size; /**< The number of bytes to reserve. */ 88 size_t align; /**< The alignment constraint (power of 2). */ 89 unsigned int flags; /**< Reserved for future use, must be 0. */ 90 }; 91 92 /** 93 * Structure describing the parameters of a mbuf dynamic flag. 94 */ 95 struct rte_mbuf_dynflag { 96 char name[RTE_MBUF_DYN_NAMESIZE]; /**< Name of the dynamic flag. */ 97 unsigned int flags; /**< Reserved for future use, must be 0. */ 98 }; 99 100 /** 101 * Register space for a dynamic field in the mbuf structure. 102 * 103 * If the field is already registered (same name and parameters), its 104 * offset is returned. 105 * 106 * @param params 107 * A structure containing the requested parameters (name, size, 108 * alignment constraint and flags). 109 * @return 110 * The offset in the mbuf structure, or -1 on error. 111 * Possible values for rte_errno: 112 * - EINVAL: invalid parameters (size, align, or flags). 113 * - EEXIST: this name is already register with different parameters. 114 * - EPERM: called from a secondary process. 115 * - ENOENT: not enough room in mbuf. 116 * - ENOMEM: allocation failure. 117 * - ENAMETOOLONG: name does not ends with \0. 118 */ 119 int rte_mbuf_dynfield_register(const struct rte_mbuf_dynfield *params); 120 121 /** 122 * Register space for a dynamic field in the mbuf structure at offset. 123 * 124 * If the field is already registered (same name, parameters and offset), 125 * the offset is returned. 126 * 127 * @param params 128 * A structure containing the requested parameters (name, size, 129 * alignment constraint and flags). 130 * @param offset 131 * The requested offset. Ignored if SIZE_MAX is passed. 132 * @return 133 * The offset in the mbuf structure, or -1 on error. 134 * Possible values for rte_errno: 135 * - EINVAL: invalid parameters (size, align, flags, or offset). 136 * - EEXIST: this name is already register with different parameters. 137 * - EBUSY: the requested offset cannot be used. 138 * - EPERM: called from a secondary process. 139 * - ENOENT: not enough room in mbuf. 140 * - ENOMEM: allocation failure. 141 * - ENAMETOOLONG: name does not ends with \0. 142 */ 143 int rte_mbuf_dynfield_register_offset(const struct rte_mbuf_dynfield *params, 144 size_t offset); 145 146 /** 147 * Lookup for a registered dynamic mbuf field. 148 * 149 * @param name 150 * A string identifying the dynamic field. 151 * @param params 152 * If not NULL, and if the lookup is successful, the structure is 153 * filled with the parameters of the dynamic field. 154 * @return 155 * The offset of this field in the mbuf structure, or -1 on error. 156 * Possible values for rte_errno: 157 * - ENOENT: no dynamic field matches this name. 158 */ 159 int rte_mbuf_dynfield_lookup(const char *name, 160 struct rte_mbuf_dynfield *params); 161 162 /** 163 * Register a dynamic flag in the mbuf structure. 164 * 165 * If the flag is already registered (same name and parameters), its 166 * bitnum is returned. 167 * 168 * @param params 169 * A structure containing the requested parameters of the dynamic 170 * flag (name and options). 171 * @return 172 * The number of the reserved bit, or -1 on error. 173 * Possible values for rte_errno: 174 * - EINVAL: invalid parameters (size, align, or flags). 175 * - EEXIST: this name is already register with different parameters. 176 * - EPERM: called from a secondary process. 177 * - ENOENT: no more flag available. 178 * - ENOMEM: allocation failure. 179 * - ENAMETOOLONG: name is longer than RTE_MBUF_DYN_NAMESIZE - 1. 180 */ 181 int rte_mbuf_dynflag_register(const struct rte_mbuf_dynflag *params); 182 183 /** 184 * Register a dynamic flag in the mbuf structure specifying bitnum. 185 * 186 * If the flag is already registered (same name, parameters and bitnum), 187 * the bitnum is returned. 188 * 189 * @param params 190 * A structure containing the requested parameters of the dynamic 191 * flag (name and options). 192 * @param bitnum 193 * The requested bitnum. Ignored if UINT_MAX is passed. 194 * @return 195 * The number of the reserved bit, or -1 on error. 196 * Possible values for rte_errno: 197 * - EINVAL: invalid parameters (size, align, or flags). 198 * - EEXIST: this name is already register with different parameters. 199 * - EBUSY: the requested bitnum cannot be used. 200 * - EPERM: called from a secondary process. 201 * - ENOENT: no more flag available. 202 * - ENOMEM: allocation failure. 203 * - ENAMETOOLONG: name is longer than RTE_MBUF_DYN_NAMESIZE - 1. 204 */ 205 int rte_mbuf_dynflag_register_bitnum(const struct rte_mbuf_dynflag *params, 206 unsigned int bitnum); 207 208 /** 209 * Lookup for a registered dynamic mbuf flag. 210 * 211 * @param name 212 * A string identifying the dynamic flag. 213 * @param params 214 * If not NULL, and if the lookup is successful, the structure is 215 * filled with the parameters of the dynamic flag. 216 * @return 217 * The offset of this flag in the mbuf structure, or -1 on error. 218 * Possible values for rte_errno: 219 * - ENOENT: no dynamic flag matches this name. 220 */ 221 int rte_mbuf_dynflag_lookup(const char *name, 222 struct rte_mbuf_dynflag *params); 223 224 /** 225 * Helper macro to access to a dynamic field. 226 */ 227 #define RTE_MBUF_DYNFIELD(m, offset, type) ((type)((uintptr_t)(m) + (offset))) 228 229 /** 230 * Dump the status of dynamic fields and flags. 231 * 232 * @param out 233 * The stream where the status is displayed. 234 */ 235 void rte_mbuf_dyn_dump(FILE *out); 236 237 /* 238 * Placeholder for dynamic fields and flags declarations. 239 * This is centralizing point to gather all field names 240 * and parameters together. 241 */ 242 243 /* 244 * The metadata dynamic field provides some extra packet information 245 * to interact with RTE Flow engine. The metadata in sent mbufs can be 246 * used to match on some Flows. The metadata in received mbufs can 247 * provide some feedback from the Flows. The metadata flag tells 248 * whether the field contains actual value to send, or received one. 249 */ 250 #define RTE_MBUF_DYNFIELD_METADATA_NAME "rte_flow_dynfield_metadata" 251 #define RTE_MBUF_DYNFLAG_METADATA_NAME "rte_flow_dynflag_metadata" 252 253 /** 254 * The timestamp dynamic field provides some timing information, the 255 * units and time references (initial phase) are not explicitly defined 256 * but are maintained always the same for a given port. Some devices allow 257 * to query rte_eth_read_clock() that will return the current device 258 * timestamp. The dynamic Tx timestamp flag tells whether the field contains 259 * actual timestamp value for the packets being sent, this value can be 260 * used by PMD to schedule packet sending. 261 */ 262 #define RTE_MBUF_DYNFIELD_TIMESTAMP_NAME "rte_dynfield_timestamp" 263 typedef uint64_t rte_mbuf_timestamp_t; 264 265 /** 266 * Indicate that the timestamp field in the mbuf was filled by the driver. 267 */ 268 #define RTE_MBUF_DYNFLAG_RX_TIMESTAMP_NAME "rte_dynflag_rx_timestamp" 269 270 /** 271 * Register dynamic mbuf field and flag for Rx timestamp. 272 * 273 * @param field_offset 274 * Pointer to the offset of the registered mbuf field, can be NULL. 275 * The same field is shared for Rx and Tx timestamp. 276 * @param rx_flag 277 * Pointer to the mask of the registered offload flag, can be NULL. 278 * @return 279 * 0 on success, -1 otherwise. 280 * Possible values for rte_errno: 281 * - EEXIST: already registered with different parameters. 282 * - EPERM: called from a secondary process. 283 * - ENOENT: no more field or flag available. 284 * - ENOMEM: allocation failure. 285 */ 286 int rte_mbuf_dyn_rx_timestamp_register(int *field_offset, uint64_t *rx_flag); 287 288 /** 289 * When PMD sees the RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME flag set on the 290 * packet being sent it tries to synchronize the time of packet appearing 291 * on the wire with the specified packet timestamp. If the specified one 292 * is in the past it should be ignored, if one is in the distant future 293 * it should be capped with some reasonable value (in range of seconds). 294 * 295 * There is no any packet reordering according to timestamps is supposed, 296 * neither for packet within the burst, nor for the whole bursts, it is 297 * an entirely application responsibility to generate packets and its 298 * timestamps in desired order. The timestamps might be put only in 299 * the first packet in the burst providing the entire burst scheduling. 300 */ 301 #define RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME "rte_dynflag_tx_timestamp" 302 303 /** 304 * Register dynamic mbuf field and flag for Tx timestamp. 305 * 306 * @param field_offset 307 * Pointer to the offset of the registered mbuf field, can be NULL. 308 * The same field is shared for Rx and Tx timestamp. 309 * @param tx_flag 310 * Pointer to the mask of the registered offload flag, can be NULL. 311 * @return 312 * 0 on success, -1 otherwise. 313 * Possible values for rte_errno: 314 * - EEXIST: already registered with different parameters. 315 * - EPERM: called from a secondary process. 316 * - ENOENT: no more field or flag available. 317 * - ENOMEM: allocation failure. 318 */ 319 int rte_mbuf_dyn_tx_timestamp_register(int *field_offset, uint64_t *tx_flag); 320 321 /** 322 * For the PMDs which support IP reassembly of packets, PMD will update the 323 * packet with RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME to denote that 324 * IP reassembly is incomplete and application can retrieve the packets back 325 * using RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME. 326 */ 327 #define RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME "rte_dynfield_ip_reassembly" 328 #define RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME "rte_dynflag_ip_reassembly_incomplete" 329 330 #ifdef __cplusplus 331 } 332 #endif 333 334 #endif /* _RTE_MBUF_DYN_H_ */ 335