f231b3665e70332a0c693d4812918b0f95e701eb
[dpdk.git] / doc / guides / contributing / versioning.rst
1 ..  SPDX-License-Identifier: BSD-3-Clause
2     Copyright 2018 The DPDK contributors
3
4 DPDK ABI/API policy
5 ===================
6
7 Description
8 -----------
9
10 This document details some methods for handling ABI management in the DPDK.
11
12 General Guidelines
13 ------------------
14
15 #. Whenever possible, ABI should be preserved
16 #. ABI/API may be changed with a deprecation process
17 #. The modification of symbols can generally be managed with versioning
18 #. Libraries or APIs marked in ``experimental`` state may change without constraint
19 #. New APIs will be marked as ``experimental`` for at least one release to allow
20    any issues found by users of the new API to be fixed quickly
21 #. The addition of symbols is generally not problematic
22 #. The removal of symbols generally is an ABI break and requires bumping of the
23    LIBABIVER macro
24 #. Updates to the minimum hardware requirements, which drop support for hardware which
25    was previously supported, should be treated as an ABI change.
26
27 What is an ABI
28 ~~~~~~~~~~~~~~
29
30 An ABI (Application Binary Interface) is the set of runtime interfaces exposed
31 by a library. It is similar to an API (Application Programming Interface) but
32 is the result of compilation.  It is also effectively cloned when applications
33 link to dynamic libraries.  That is to say when an application is compiled to
34 link against dynamic libraries, it is assumed that the ABI remains constant
35 between the time the application is compiled/linked, and the time that it runs.
36 Therefore, in the case of dynamic linking, it is critical that an ABI is
37 preserved, or (when modified), done in such a way that the application is unable
38 to behave improperly or in an unexpected fashion.
39
40
41 ABI/API Deprecation
42 -------------------
43
44 The DPDK ABI policy
45 ~~~~~~~~~~~~~~~~~~~
46
47 ABI versions are set at the time of major release labeling, and the ABI may
48 change multiple times, without warning, between the last release label and the
49 HEAD label of the git tree.
50
51 ABI versions, once released, are available until such time as their
52 deprecation has been noted in the Release Notes for at least one major release
53 cycle. For example consider the case where the ABI for DPDK 2.0 has been
54 shipped and then a decision is made to modify it during the development of
55 DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
56 release and the modification will be made available in the DPDK 2.2 release.
57
58 ABI versions may be deprecated in whole or in part as needed by a given
59 update.
60
61 Some ABI changes may be too significant to reasonably maintain multiple
62 versions. In those cases ABI's may be updated without backward compatibility
63 being provided. The requirements for doing so are:
64
65 #. At least 3 acknowledgments of the need to do so must be made on the
66    dpdk.org mailing list.
67
68    - The acknowledgment of the maintainer of the component is mandatory, or if
69      no maintainer is available for the component, the tree/sub-tree maintainer
70      for that component must acknowledge the ABI change instead.
71
72    - It is also recommended that acknowledgments from different "areas of
73      interest" be sought for each deprecation, for example: from NIC vendors,
74      CPU vendors, end-users, etc.
75
76 #. The changes (including an alternative map file) must be gated with
77    the ``RTE_NEXT_ABI`` option, and provided with a deprecation notice at the
78    same time.
79    It will become the default ABI in the next release.
80
81 #. A full deprecation cycle, as explained above, must be made to offer
82    downstream consumers sufficient warning of the change.
83
84 #. At the beginning of the next release cycle, every ``RTE_NEXT_ABI``
85    conditions will be removed, the ``LIBABIVER`` variable in the makefile(s)
86    where the ABI is changed will be incremented, and the map files will
87    be updated.
88
89 Note that the above process for ABI deprecation should not be undertaken
90 lightly. ABI stability is extremely important for downstream consumers of the
91 DPDK, especially when distributed in shared object form. Every effort should
92 be made to preserve the ABI whenever possible. The ABI should only be changed
93 for significant reasons, such as performance enhancements. ABI breakage due to
94 changes such as reorganizing public structure fields for aesthetic or
95 readability purposes should be avoided.
96
97 .. note::
98
99    Updates to the minimum hardware requirements, which drop support for hardware
100    which was previously supported, should be treated as an ABI change, and
101    follow the relevant deprecation policy procedures as above: 3 acks and
102    announcement at least one release in advance.
103
104 Examples of Deprecation Notices
105 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106
107 The following are some examples of ABI deprecation notices which would be
108 added to the Release Notes:
109
110 * The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
111   to be replaced with the inline function ``rte_foo()``.
112
113 * The function ``rte_mbuf_grok()`` has been updated to include a new parameter
114   in version 2.0. Backwards compatibility will be maintained for this function
115   until the release of version 2.1
116
117 * The members of ``struct rte_foo`` have been reorganized in release 2.0 for
118   performance reasons. Existing binary applications will have backwards
119   compatibility in release 2.0, while newly built binaries will need to
120   reference the new structure variant ``struct rte_foo2``. Compatibility will
121   be removed in release 2.2, and all applications will require updating and
122   rebuilding to the new structure at that time, which will be renamed to the
123   original ``struct rte_foo``.
124
125 * Significant ABI changes are planned for the ``librte_dostuff`` library. The
126   upcoming release 2.0 will not contain these changes, but release 2.1 will,
127   and no backwards compatibility is planned due to the extensive nature of
128   these changes. Binaries using this library built prior to version 2.1 will
129   require updating and recompilation.
130
131
132 Experimental APIs
133 -----------------
134
135 APIs marked as ``experimental`` are not considered part of the ABI and may
136 change without warning at any time.  Since changes to APIs are most likely
137 immediately after their introduction, as users begin to take advantage of
138 those new APIs and start finding issues with them, new DPDK APIs will be
139 automatically marked as ``experimental`` to allow for a period of stabilization
140 before they become part of a tracked ABI.
141
142 Note that marking an API as experimental is a multi step process.
143 To mark an API as experimental, the symbols which are desired to be exported
144 must be placed in an EXPERIMENTAL version block in the corresponding libraries'
145 version map script.
146 Secondly, the corresponding definitions of those exported functions, and
147 their forward declarations (in the development header files), must be marked
148 with the ``__rte_experimental`` tag (see ``rte_compat.h``).
149 The DPDK build makefiles perform a check to ensure that the map file and the
150 C code reflect the same list of symbols.
151 This check can be circumvented by defining ``ALLOW_EXPERIMENTAL_API``
152 during compilation in the corresponding library Makefile.
153
154 In addition to tagging the code with ``__rte_experimental``,
155 the doxygen markup must also contain the EXPERIMENTAL string,
156 and the MAINTAINERS file should note the EXPERIMENTAL libraries.
157
158 For removing the experimental tag associated with an API, deprecation notice
159 is not required. Though, an API should remain in experimental state for at least
160 one release. Thereafter, normal process of posting patch for review to mailing
161 list can be followed.
162
163
164 Library versioning
165 ------------------
166
167 Downstreams might want to provide different DPDK releases at the same time to
168 support multiple consumers of DPDK linked against older and newer sonames.
169
170 Also due to the interdependencies that DPDK libraries can have applications
171 might end up with an executable space in which multiple versions of a library
172 are mapped by ld.so.
173
174 Think of LibA that got an ABI bump and LibB that did not get an ABI bump but is
175 depending on LibA.
176
177 .. note::
178
179     Application
180     \-> LibA.old
181     \-> LibB.new -> LibA.new
182
183 That is a conflict which can be avoided by setting ``CONFIG_RTE_MAJOR_ABI``.
184 If set, the value of ``CONFIG_RTE_MAJOR_ABI`` overwrites all - otherwise per
185 library - versions defined in the libraries ``LIBABIVER``.
186 An example might be ``CONFIG_RTE_MAJOR_ABI=16.11`` which will make all libraries
187 ``librte<?>.so.16.11`` instead of ``librte<?>.so.<LIBABIVER>``.
188
189
190 ABI versioning
191 --------------
192
193 Versioning Macros
194 ~~~~~~~~~~~~~~~~~
195
196 When a symbol is exported from a library to provide an API, it also provides a
197 calling convention (ABI) that is embodied in its name, return type and
198 arguments. Occasionally that function may need to change to accommodate new
199 functionality or behavior. When that occurs, it is desirable to allow for
200 backward compatibility for a time with older binaries that are dynamically
201 linked to the DPDK.
202
203 To support backward compatibility the ``rte_compat.h``
204 header file provides macros to use when updating exported functions. These
205 macros are used in conjunction with the ``rte_<library>_version.map`` file for
206 a given library to allow multiple versions of a symbol to exist in a shared
207 library so that older binaries need not be immediately recompiled.
208
209 The macros exported are:
210
211 * ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
212   versioned symbol ``b@DPDK_n`` to the internal function ``b_e``.
213
214 * ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing
215   the linker to bind references to symbol ``b`` to the internal symbol
216   ``b_e``.
217
218 * ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the
219   fully qualified function ``p``, so that if a symbol becomes versioned, it
220   can still be mapped back to the public symbol name.
221
222 Examples of ABI Macro use
223 ^^^^^^^^^^^^^^^^^^^^^^^^^
224
225 Updating a public API
226 _____________________
227
228 Assume we have a function as follows
229
230 .. code-block:: c
231
232  /*
233   * Create an acl context object for apps to
234   * manipulate
235   */
236  struct rte_acl_ctx *
237  rte_acl_create(const struct rte_acl_param *param)
238  {
239         ...
240  }
241
242
243 Assume that struct rte_acl_ctx is a private structure, and that a developer
244 wishes to enhance the acl api so that a debugging flag can be enabled on a
245 per-context basis.  This requires an addition to the structure (which, being
246 private, is safe), but it also requires modifying the code as follows
247
248 .. code-block:: c
249
250  /*
251   * Create an acl context object for apps to
252   * manipulate
253   */
254  struct rte_acl_ctx *
255  rte_acl_create(const struct rte_acl_param *param, int debug)
256  {
257         ...
258  }
259
260
261 Note also that, being a public function, the header file prototype must also be
262 changed, as must all the call sites, to reflect the new ABI footprint.  We will
263 maintain previous ABI versions that are accessible only to previously compiled
264 binaries
265
266 The addition of a parameter to the function is ABI breaking as the function is
267 public, and existing application may use it in its current form.  However, the
268 compatibility macros in DPDK allow a developer to use symbol versioning so that
269 multiple functions can be mapped to the same public symbol based on when an
270 application was linked to it.  To see how this is done, we start with the
271 requisite libraries version map file.  Initially the version map file for the
272 acl library looks like this
273
274 .. code-block:: none
275
276    DPDK_2.0 {
277         global:
278
279         rte_acl_add_rules;
280         rte_acl_build;
281         rte_acl_classify;
282         rte_acl_classify_alg;
283         rte_acl_classify_scalar;
284         rte_acl_create;
285         rte_acl_dump;
286         rte_acl_find_existing;
287         rte_acl_free;
288         rte_acl_ipv4vlan_add_rules;
289         rte_acl_ipv4vlan_build;
290         rte_acl_list_dump;
291         rte_acl_reset;
292         rte_acl_reset_rules;
293         rte_acl_set_ctx_classify;
294
295         local: *;
296    };
297
298 This file needs to be modified as follows
299
300 .. code-block:: none
301
302    DPDK_2.0 {
303         global:
304
305         rte_acl_add_rules;
306         rte_acl_build;
307         rte_acl_classify;
308         rte_acl_classify_alg;
309         rte_acl_classify_scalar;
310         rte_acl_create;
311         rte_acl_dump;
312         rte_acl_find_existing;
313         rte_acl_free;
314         rte_acl_ipv4vlan_add_rules;
315         rte_acl_ipv4vlan_build;
316         rte_acl_list_dump;
317         rte_acl_reset;
318         rte_acl_reset_rules;
319         rte_acl_set_ctx_classify;
320
321         local: *;
322    };
323
324    DPDK_2.1 {
325         global:
326         rte_acl_create;
327
328    } DPDK_2.0;
329
330 The addition of the new block tells the linker that a new version node is
331 available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
332 symbols from the DPDK_2.0 node.  This list is directly translated into a list of
333 exported symbols when DPDK is compiled as a shared library
334
335 Next, we need to specify in the code which function map to the rte_acl_create
336 symbol at which versions.  First, at the site of the initial symbol definition,
337 we need to update the function so that it is uniquely named, and not in conflict
338 with the public symbol name
339
340 .. code-block:: c
341
342   struct rte_acl_ctx *
343  -rte_acl_create(const struct rte_acl_param *param)
344  +rte_acl_create_v20(const struct rte_acl_param *param)
345  {
346         size_t sz;
347         struct rte_acl_ctx *ctx;
348         ...
349
350 Note that the base name of the symbol was kept intact, as this is conducive to
351 the macros used for versioning symbols.  That is our next step, mapping this new
352 symbol name to the initial symbol name at version node 2.0.  Immediately after
353 the function, we add this line of code
354
355 .. code-block:: c
356
357    VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
358
359 Remembering to also add the rte_compat.h header to the requisite c file where
360 these changes are being made.  The above macro instructs the linker to create a
361 new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
362 builds, but now points to the above newly named function.  We have now mapped
363 the original rte_acl_create symbol to the original function (but with a new
364 name)
365
366 Next, we need to create the 2.1 version of the symbol.  We create a new function
367 name, with a different suffix, and  implement it appropriately
368
369 .. code-block:: c
370
371    struct rte_acl_ctx *
372    rte_acl_create_v21(const struct rte_acl_param *param, int debug);
373    {
374         struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
375
376         ctx->debug = debug;
377
378         return ctx;
379    }
380
381 This code serves as our new API call.  Its the same as our old call, but adds
382 the new parameter in place.  Next we need to map this function to the symbol
383 ``rte_acl_create@DPDK_2.1``.  To do this, we modify the public prototype of the call
384 in the header file, adding the macro there to inform all including applications,
385 that on re-link, the default rte_acl_create symbol should point to this
386 function.  Note that we could do this by simply naming the function above
387 rte_acl_create, and the linker would chose the most recent version tag to apply
388 in the version script, but we can also do this in the header file
389
390 .. code-block:: c
391
392    struct rte_acl_ctx *
393    -rte_acl_create(const struct rte_acl_param *param);
394    +rte_acl_create(const struct rte_acl_param *param, int debug);
395    +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
396
397 The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
398 header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
399 version node to it.  This method is more explicit and flexible than just
400 re-implementing the exact symbol name, and allows for other features (such as
401 linking to the old symbol version by default, when the new ABI is to be opt-in
402 for a period.
403
404 One last thing we need to do.  Note that we've taken what was a public symbol,
405 and duplicated it into two uniquely and differently named symbols.  We've then
406 mapped each of those back to the public symbol ``rte_acl_create`` with different
407 version tags.  This only applies to dynamic linking, as static linking has no
408 notion of versioning.  That leaves this code in a position of no longer having a
409 symbol simply named ``rte_acl_create`` and a static build will fail on that
410 missing symbol.
411
412 To correct this, we can simply map a function of our choosing back to the public
413 symbol in the static build with the ``MAP_STATIC_SYMBOL`` macro.  Generally the
414 assumption is that the most recent version of the symbol is the one you want to
415 map.  So, back in the C file where, immediately after ``rte_acl_create_v21`` is
416 defined, we add this
417
418 .. code-block:: c
419
420    struct rte_acl_ctx *
421    rte_acl_create_v21(const struct rte_acl_param *param, int debug)
422    {
423         ...
424    }
425    MAP_STATIC_SYMBOL(struct rte_acl_ctx *rte_acl_create(const struct rte_acl_param *param, int debug), rte_acl_create_v21);
426
427 That tells the compiler that, when building a static library, any calls to the
428 symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21``
429
430 That's it, on the next shared library rebuild, there will be two versions of
431 rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
432 and a new DPDK_2.1 version, used by future built applications.
433
434
435 Deprecating part of a public API
436 ________________________________
437
438 Lets assume that you've done the above update, and after a few releases have
439 passed you decide you would like to retire the old version of the function.
440 After having gone through the ABI deprecation announcement process, removal is
441 easy.  Start by removing the symbol from the requisite version map file:
442
443 .. code-block:: none
444
445    DPDK_2.0 {
446         global:
447
448         rte_acl_add_rules;
449         rte_acl_build;
450         rte_acl_classify;
451         rte_acl_classify_alg;
452         rte_acl_classify_scalar;
453         rte_acl_dump;
454  -      rte_acl_create
455         rte_acl_find_existing;
456         rte_acl_free;
457         rte_acl_ipv4vlan_add_rules;
458         rte_acl_ipv4vlan_build;
459         rte_acl_list_dump;
460         rte_acl_reset;
461         rte_acl_reset_rules;
462         rte_acl_set_ctx_classify;
463
464         local: *;
465    };
466
467    DPDK_2.1 {
468         global:
469         rte_acl_create;
470    } DPDK_2.0;
471
472
473 Next remove the corresponding versioned export.
474
475 .. code-block:: c
476
477  -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
478
479
480 Note that the internal function definition could also be removed, but its used
481 in our example by the newer version _v21, so we leave it in place.  This is a
482 coding style choice.
483
484 Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
485 indicate to applications doing dynamic linking that this is a later, and
486 possibly incompatible library version:
487
488 .. code-block:: c
489
490    -LIBABIVER := 1
491    +LIBABIVER := 2
492
493 Deprecating an entire ABI version
494 _________________________________
495
496 While removing a symbol from and ABI may be useful, it is often more practical
497 to remove an entire version node at once.  If a version node completely
498 specifies an API, then removing part of it, typically makes it incomplete.  In
499 those cases it is better to remove the entire node
500
501 To do this, start by modifying the version map file, such that all symbols from
502 the node to be removed are merged into the next node in the map
503
504 In the case of our map above, it would transform to look as follows
505
506 .. code-block:: none
507
508    DPDK_2.1 {
509         global:
510
511         rte_acl_add_rules;
512         rte_acl_build;
513         rte_acl_classify;
514         rte_acl_classify_alg;
515         rte_acl_classify_scalar;
516         rte_acl_dump;
517         rte_acl_create
518         rte_acl_find_existing;
519         rte_acl_free;
520         rte_acl_ipv4vlan_add_rules;
521         rte_acl_ipv4vlan_build;
522         rte_acl_list_dump;
523         rte_acl_reset;
524         rte_acl_reset_rules;
525         rte_acl_set_ctx_classify;
526
527         local: *;
528  };
529
530 Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node should be
531 updated to point to the new version node in any header files for all affected
532 symbols.
533
534 .. code-block:: c
535
536  -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
537  +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
538
539 Lastly, any VERSION_SYMBOL macros that point to the old version node should be
540 removed, taking care to keep, where need old code in place to support newer
541 versions of the symbol.
542
543
544 Running the ABI Validator
545 -------------------------
546
547 The ``devtools`` directory in the DPDK source tree contains a utility program,
548 ``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI
549 Compliance Checker
550 <http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
551
552 This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper``
553 utilities which can be installed via a package manager. For example::
554
555    sudo yum install abi-compliance-checker
556    sudo yum install abi-dumper
557
558 The syntax of the ``validate-abi.sh`` utility is::
559
560    ./devtools/validate-abi.sh <REV1> <REV2> <TARGET>
561
562 Where ``REV1`` and ``REV2`` are valid gitrevisions(7)
563 https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html
564 on the local repo and target is the usual DPDK compilation target.
565
566 For example::
567
568    # Check between the previous and latest commit:
569    ./devtools/validate-abi.sh HEAD~1 HEAD x86_64-native-linux-gcc
570
571    # Check between two tags:
572    ./devtools/validate-abi.sh v2.0.0 v2.1.0 x86_64-native-linux-gcc
573
574    # Check between git master and local topic-branch "vhost-hacking":
575    ./devtools/validate-abi.sh master vhost-hacking x86_64-native-linux-gcc
576
577 After the validation script completes (it can take a while since it need to
578 compile both tags) it will create compatibility reports in the
579 ``./compat_report`` directory. Listed incompatibilities can be found as
580 follows::
581
582   grep -lr Incompatible compat_reports/