[dpdk-dev,PATCHv4,4/5] dpdk: add __experimental tag to appropriate api calls

Message ID 20171213151728.16747-5-nhorman@tuxdriver.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Neil Horman Dec. 13, 2017, 3:17 p.m. UTC
  Append the __experimental tag to api calls appearing in the EXPERIMENTAL
section of their libraries version map

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Monjalon <thomas@monjalon.net>
CC: "Mcnamara, John" <john.mcnamara@intel.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_eal/common/eal_common_dev.c             |  6 ++-
 lib/librte_eal/common/eal_common_devargs.c         |  7 +--
 lib/librte_eal/common/include/rte_dev.h            |  6 ++-
 lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
 lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
 .../common/include/rte_service_component.h         | 14 +++---
 lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
 lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
 lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
 lib/librte_ether/rte_mtr.h                         | 26 +++++------
 lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
 lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
 lib/librte_security/rte_security.c                 | 16 +++----
 lib/librte_security/rte_security.h                 | 23 +++++-----
 14 files changed, 139 insertions(+), 116 deletions(-)
  

Comments

Ferruh Yigit Jan. 11, 2018, 8:06 p.m. UTC | #1
On 12/13/2017 3:17 PM, Neil Horman wrote:
> Append the __experimental tag to api calls appearing in the EXPERIMENTAL
> section of their libraries version map
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: Thomas Monjalon <thomas@monjalon.net>
> CC: "Mcnamara, John" <john.mcnamara@intel.com>
> CC: Bruce Richardson <bruce.richardson@intel.com>
> ---
>  lib/librte_eal/common/eal_common_dev.c             |  6 ++-
>  lib/librte_eal/common/eal_common_devargs.c         |  7 +--
>  lib/librte_eal/common/include/rte_dev.h            |  6 ++-
>  lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
>  lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
>  .../common/include/rte_service_component.h         | 14 +++---
>  lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
>  lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
>  lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
>  lib/librte_ether/rte_mtr.h                         | 26 +++++------
>  lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
>  lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
>  lib/librte_security/rte_security.c                 | 16 +++----
>  lib/librte_security/rte_security.h                 | 23 +++++-----

It may not be the responsibility of this patchset, but there are more
experimental APIs in DPDK.

Using EXPERIMENTAL tag in linker script is relatively new approach and this was
not a requirement, so many experimental APIs are documented in API documentation
(header file doxygen comment).
Sample: librte_member

It is required to scan all header files and update their linker scripts for the
experimental APIs.

>  14 files changed, 139 insertions(+), 116 deletions(-)

<...>
  
Neil Horman Jan. 11, 2018, 9:24 p.m. UTC | #2
On Thu, Jan 11, 2018 at 08:06:33PM +0000, Ferruh Yigit wrote:
> On 12/13/2017 3:17 PM, Neil Horman wrote:
> > Append the __experimental tag to api calls appearing in the EXPERIMENTAL
> > section of their libraries version map
> > 
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > CC: Thomas Monjalon <thomas@monjalon.net>
> > CC: "Mcnamara, John" <john.mcnamara@intel.com>
> > CC: Bruce Richardson <bruce.richardson@intel.com>
> > ---
> >  lib/librte_eal/common/eal_common_dev.c             |  6 ++-
> >  lib/librte_eal/common/eal_common_devargs.c         |  7 +--
> >  lib/librte_eal/common/include/rte_dev.h            |  6 ++-
> >  lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
> >  lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
> >  .../common/include/rte_service_component.h         | 14 +++---
> >  lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
> >  lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
> >  lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
> >  lib/librte_ether/rte_mtr.h                         | 26 +++++------
> >  lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
> >  lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
> >  lib/librte_security/rte_security.c                 | 16 +++----
> >  lib/librte_security/rte_security.h                 | 23 +++++-----
> 
> It may not be the responsibility of this patchset, but there are more
> experimental APIs in DPDK.
> 
Thats an interesting statement to make.  This patchset creates a build time
check that compares symbols located in the EXPERIMENTAL version section of a
libraries' version map file to the symbols that are marked with this new tag,
throwing an error if they don't match.  I believe what you say in that there may
be additional APIs that are experimental, but given that, I would have to
conclude one of the following:

1) The missing API's are macros or static inline functions that are not exported
from libraries directly

2) The documentation for experimental API's are out of sync, in that they have
legitimately moved to be supported API's and the documentation needs to be
updated

3) There are API's which are experimental that have been incorrectly placed in a
versioned tag.

I made a pretty good effort to scan comments for the word EXPERIMENTAL so that I
could catch item (1).  And while I may not have caught them all, I'd like to
think I got a good chunk of them.  That leaves cleanup of (2) and (3), which I
think this patchset can help us idenfity.

> Using EXPERIMENTAL tag in linker script is relatively new approach and this was
> not a requirement, so many experimental APIs are documented in API documentation
> (header file doxygen comment).
> Sample: librte_member
> 
That sounds like case (3) above.

Thats a bit odd.  I understand that the use of the EXPERIMENTAL version tag is
new, but once it was introduced it should have been made a requirement.  There
would have been no penalty for moving the version number (as doing so would not
have violated ABI guarantees, given that those API's were appropriately
documented as experimental).  If they have not been, then the use of the
EXPERIMENTAL tag isn't overly useful, as it doesn't provide any segregation of
the stable ABI from the unstable ABI.

> It is required to scan all header files and update their linker scripts for the
> experimental APIs.
> 
Yes and no.  If a given library is not marked as experimental in its version
map, this change won't flag it as a problem, but if its intended to be
experimental (i.e. if its likely to have its ABI fluctuate), then yes, we should
take the appropriate steps to flag it as such properly.

If a given library is intended to be experimental, I would say yes,
the author should make the appropriate chage to the version map, and then the
corresponding change to the headers  and c files with this new tag.
Alternatively, they might choose to simply update the documentation to reflect
the fact that the ABI for that library is now stable.

The thing that should definately not hapen though, is a half measure.  We
shouldn't allow libraries to call themselves experimental, and then excuse them
from any rules we have regarding their in-code representation.  If we have an
EXPERIMENTAL version in the map, we should require its use, and by extension
require this tag when its merged for the reasons previously outlined

Neil


> >  14 files changed, 139 insertions(+), 116 deletions(-)
> 
> <...>
> 
>
  
Ferruh Yigit Jan. 12, 2018, 11:50 a.m. UTC | #3
On 1/11/2018 9:24 PM, Neil Horman wrote:
> On Thu, Jan 11, 2018 at 08:06:33PM +0000, Ferruh Yigit wrote:
>> On 12/13/2017 3:17 PM, Neil Horman wrote:
>>> Append the __experimental tag to api calls appearing in the EXPERIMENTAL
>>> section of their libraries version map
>>>
>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>> CC: Thomas Monjalon <thomas@monjalon.net>
>>> CC: "Mcnamara, John" <john.mcnamara@intel.com>
>>> CC: Bruce Richardson <bruce.richardson@intel.com>
>>> ---
>>>  lib/librte_eal/common/eal_common_dev.c             |  6 ++-
>>>  lib/librte_eal/common/eal_common_devargs.c         |  7 +--
>>>  lib/librte_eal/common/include/rte_dev.h            |  6 ++-
>>>  lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
>>>  lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
>>>  .../common/include/rte_service_component.h         | 14 +++---
>>>  lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
>>>  lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
>>>  lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
>>>  lib/librte_ether/rte_mtr.h                         | 26 +++++------
>>>  lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
>>>  lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
>>>  lib/librte_security/rte_security.c                 | 16 +++----
>>>  lib/librte_security/rte_security.h                 | 23 +++++-----
>>
>> It may not be the responsibility of this patchset, but there are more
>> experimental APIs in DPDK.
>>
> Thats an interesting statement to make.  This patchset creates a build time
> check that compares symbols located in the EXPERIMENTAL version section of a
> libraries' version map file to the symbols that are marked with this new tag,
> throwing an error if they don't match.  I believe what you say in that there may
> be additional APIs that are experimental, but given that, I would have to
> conclude one of the following:
> 
> 1) The missing API's are macros or static inline functions that are not exported
> from libraries directly
> 
> 2) The documentation for experimental API's are out of sync, in that they have
> legitimately moved to be supported API's and the documentation needs to be
> updated
> 
> 3) There are API's which are experimental that have been incorrectly placed in a
> versioned tag.
> 
> I made a pretty good effort to scan comments for the word EXPERIMENTAL so that I
> could catch item (1).  And while I may not have caught them all, I'd like to
> think I got a good chunk of them.  That leaves cleanup of (2) and (3), which I
> think this patchset can help us idenfity.
> 
>> Using EXPERIMENTAL tag in linker script is relatively new approach and this was
>> not a requirement, so many experimental APIs are documented in API documentation
>> (header file doxygen comment).
>> Sample: librte_member
>>
> That sounds like case (3) above.
> 
> Thats a bit odd.  I understand that the use of the EXPERIMENTAL version tag is
> new, but once it was introduced it should have been made a requirement.  There
> would have been no penalty for moving the version number (as doing so would not
> have violated ABI guarantees, given that those API's were appropriately
> documented as experimental).  If they have not been, then the use of the
> EXPERIMENTAL tag isn't overly useful, as it doesn't provide any segregation of
> the stable ABI from the unstable ABI.
> 
>> It is required to scan all header files and update their linker scripts for the
>> experimental APIs.
>>
> Yes and no.  If a given library is not marked as experimental in its version
> map, this change won't flag it as a problem, but if its intended to be
> experimental (i.e. if its likely to have its ABI fluctuate), then yes, we should
> take the appropriate steps to flag it as such properly.
> 
> If a given library is intended to be experimental, I would say yes,
> the author should make the appropriate chage to the version map, and then the
> corresponding change to the headers  and c files with this new tag.
> Alternatively, they might choose to simply update the documentation to reflect
> the fact that the ABI for that library is now stable.
> 
> The thing that should definately not hapen though, is a half measure.  We
> shouldn't allow libraries to call themselves experimental, and then excuse them
> from any rules we have regarding their in-code representation.  If we have an
> EXPERIMENTAL version in the map, we should require its use, and by extension
> require this tag when its merged for the reasons previously outlined

My comment is for your item (3), but it is not fair to say "incorrectly placed"
because if I don't miss anything this has never been documented as correct way
to do, and lots of the existing usage is _before_ we start using EXPERIMENTAL
tag in the linker script, so they were doing right thing for that time.

Question is, is this patchset should fix them, since now this patchset defines
using EXPERIMENTAL tag in linker script as way to do it, or should we wait
maintainers to fix it after this has been documented. Waiting for maintainer may
take time because not all maintainers are following the mail list closely to
capture all expectations.

> 
> Neil
> 
> 
>>>  14 files changed, 139 insertions(+), 116 deletions(-)
>>
>> <...>
>>
>>
  
Neil Horman Jan. 12, 2018, 2:25 p.m. UTC | #4
On Fri, Jan 12, 2018 at 11:50:01AM +0000, Ferruh Yigit wrote:
> On 1/11/2018 9:24 PM, Neil Horman wrote:
> > On Thu, Jan 11, 2018 at 08:06:33PM +0000, Ferruh Yigit wrote:
> >> On 12/13/2017 3:17 PM, Neil Horman wrote:
> >>> Append the __experimental tag to api calls appearing in the EXPERIMENTAL
> >>> section of their libraries version map
> >>>
> >>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> >>> CC: Thomas Monjalon <thomas@monjalon.net>
> >>> CC: "Mcnamara, John" <john.mcnamara@intel.com>
> >>> CC: Bruce Richardson <bruce.richardson@intel.com>
> >>> ---
> >>>  lib/librte_eal/common/eal_common_dev.c             |  6 ++-
> >>>  lib/librte_eal/common/eal_common_devargs.c         |  7 +--
> >>>  lib/librte_eal/common/include/rte_dev.h            |  6 ++-
> >>>  lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
> >>>  lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
> >>>  .../common/include/rte_service_component.h         | 14 +++---
> >>>  lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
> >>>  lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
> >>>  lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
> >>>  lib/librte_ether/rte_mtr.h                         | 26 +++++------
> >>>  lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
> >>>  lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
> >>>  lib/librte_security/rte_security.c                 | 16 +++----
> >>>  lib/librte_security/rte_security.h                 | 23 +++++-----
> >>
> >> It may not be the responsibility of this patchset, but there are more
> >> experimental APIs in DPDK.
> >>
> > Thats an interesting statement to make.  This patchset creates a build time
> > check that compares symbols located in the EXPERIMENTAL version section of a
> > libraries' version map file to the symbols that are marked with this new tag,
> > throwing an error if they don't match.  I believe what you say in that there may
> > be additional APIs that are experimental, but given that, I would have to
> > conclude one of the following:
> > 
> > 1) The missing API's are macros or static inline functions that are not exported
> > from libraries directly
> > 
> > 2) The documentation for experimental API's are out of sync, in that they have
> > legitimately moved to be supported API's and the documentation needs to be
> > updated
> > 
> > 3) There are API's which are experimental that have been incorrectly placed in a
> > versioned tag.
> > 
> > I made a pretty good effort to scan comments for the word EXPERIMENTAL so that I
> > could catch item (1).  And while I may not have caught them all, I'd like to
> > think I got a good chunk of them.  That leaves cleanup of (2) and (3), which I
> > think this patchset can help us idenfity.
> > 
> >> Using EXPERIMENTAL tag in linker script is relatively new approach and this was
> >> not a requirement, so many experimental APIs are documented in API documentation
> >> (header file doxygen comment).
> >> Sample: librte_member
> >>
> > That sounds like case (3) above.
> > 
> > Thats a bit odd.  I understand that the use of the EXPERIMENTAL version tag is
> > new, but once it was introduced it should have been made a requirement.  There
> > would have been no penalty for moving the version number (as doing so would not
> > have violated ABI guarantees, given that those API's were appropriately
> > documented as experimental).  If they have not been, then the use of the
> > EXPERIMENTAL tag isn't overly useful, as it doesn't provide any segregation of
> > the stable ABI from the unstable ABI.
> > 
> >> It is required to scan all header files and update their linker scripts for the
> >> experimental APIs.
> >>
> > Yes and no.  If a given library is not marked as experimental in its version
> > map, this change won't flag it as a problem, but if its intended to be
> > experimental (i.e. if its likely to have its ABI fluctuate), then yes, we should
> > take the appropriate steps to flag it as such properly.
> > 
> > If a given library is intended to be experimental, I would say yes,
> > the author should make the appropriate chage to the version map, and then the
> > corresponding change to the headers  and c files with this new tag.
> > Alternatively, they might choose to simply update the documentation to reflect
> > the fact that the ABI for that library is now stable.
> > 
> > The thing that should definately not hapen though, is a half measure.  We
> > shouldn't allow libraries to call themselves experimental, and then excuse them
> > from any rules we have regarding their in-code representation.  If we have an
> > EXPERIMENTAL version in the map, we should require its use, and by extension
> > require this tag when its merged for the reasons previously outlined
> 
> My comment is for your item (3), but it is not fair to say "incorrectly placed"
> because if I don't miss anything this has never been documented as correct way
> to do, and lots of the existing usage is _before_ we start using EXPERIMENTAL
> tag in the linker script, so they were doing right thing for that time.
> 
Ok, Apologies, perhaps incorrectly placed isn't a fair term to use.  Perhaps it
would be better to say the experimental specification was insufficiently
documented?  The point however remains.  Defining an API category that conveys a
freedom of modification of ABI needs to follow rules for identification, and
providing a mechanism to tag said ABIs in the code without a requirement to use
it creates an confusing situation to say the least (i.e. some APIS will be
listed as belonging to the EXPERIMENTAL version, others won't, but will be
documented as such, creating an ambiguous status).

> Question is, is this patchset should fix them, since now this patchset defines
> using EXPERIMENTAL tag in linker script as way to do it, or should we wait
> maintainers to fix it after this has been documented. Waiting for maintainer may
> take time because not all maintainers are following the mail list closely to
> capture all expectations.
> 

In answer, I think waiting for maintainers to correct their experimental
use isn't going to get anything done.  As you said, not all maintainers monitor
all conversations closely enough to pick up on the need, and as we move forward
this effort will likely get de-prioitized, as the status quo will just continue
to exist.  I would propose that we accept this patch, and then I subsequently
preform an audit on the documentation to find other APIs which are documented as
EXPERIMENTAL, but not tagged as such in their version files.  I can submit
subsequent patches to reconcile those APIs that I find, which should get on the
respective maintainers radars.  Does that sound reasonable?

Neil

> > 
> > Neil
> > 
> > 
> >>>  14 files changed, 139 insertions(+), 116 deletions(-)
> >>
> >> <...>
> >>
> >>
> 
>
  
Ferruh Yigit Jan. 12, 2018, 3:53 p.m. UTC | #5
On 1/12/2018 2:25 PM, Neil Horman wrote:
> On Fri, Jan 12, 2018 at 11:50:01AM +0000, Ferruh Yigit wrote:
>> On 1/11/2018 9:24 PM, Neil Horman wrote:
>>> On Thu, Jan 11, 2018 at 08:06:33PM +0000, Ferruh Yigit wrote:
>>>> On 12/13/2017 3:17 PM, Neil Horman wrote:
>>>>> Append the __experimental tag to api calls appearing in the EXPERIMENTAL
>>>>> section of their libraries version map
>>>>>
>>>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>>>> CC: Thomas Monjalon <thomas@monjalon.net>
>>>>> CC: "Mcnamara, John" <john.mcnamara@intel.com>
>>>>> CC: Bruce Richardson <bruce.richardson@intel.com>
>>>>> ---
>>>>>  lib/librte_eal/common/eal_common_dev.c             |  6 ++-
>>>>>  lib/librte_eal/common/eal_common_devargs.c         |  7 +--
>>>>>  lib/librte_eal/common/include/rte_dev.h            |  6 ++-
>>>>>  lib/librte_eal/common/include/rte_devargs.h        |  8 ++--
>>>>>  lib/librte_eal/common/include/rte_service.h        | 47 ++++++++++---------
>>>>>  .../common/include/rte_service_component.h         | 14 +++---
>>>>>  lib/librte_eal/common/rte_service.c                | 52 ++++++++++++----------
>>>>>  lib/librte_eal/linuxapp/eal/eal.c                  |  1 +
>>>>>  lib/librte_ether/rte_mtr.c                         | 25 ++++++-----
>>>>>  lib/librte_ether/rte_mtr.h                         | 26 +++++------
>>>>>  lib/librte_flow_classify/rte_flow_classify.c       | 13 +++---
>>>>>  lib/librte_flow_classify/rte_flow_classify.h       | 11 ++---
>>>>>  lib/librte_security/rte_security.c                 | 16 +++----
>>>>>  lib/librte_security/rte_security.h                 | 23 +++++-----
>>>>
>>>> It may not be the responsibility of this patchset, but there are more
>>>> experimental APIs in DPDK.
>>>>
>>> Thats an interesting statement to make.  This patchset creates a build time
>>> check that compares symbols located in the EXPERIMENTAL version section of a
>>> libraries' version map file to the symbols that are marked with this new tag,
>>> throwing an error if they don't match.  I believe what you say in that there may
>>> be additional APIs that are experimental, but given that, I would have to
>>> conclude one of the following:
>>>
>>> 1) The missing API's are macros or static inline functions that are not exported
>>> from libraries directly
>>>
>>> 2) The documentation for experimental API's are out of sync, in that they have
>>> legitimately moved to be supported API's and the documentation needs to be
>>> updated
>>>
>>> 3) There are API's which are experimental that have been incorrectly placed in a
>>> versioned tag.
>>>
>>> I made a pretty good effort to scan comments for the word EXPERIMENTAL so that I
>>> could catch item (1).  And while I may not have caught them all, I'd like to
>>> think I got a good chunk of them.  That leaves cleanup of (2) and (3), which I
>>> think this patchset can help us idenfity.
>>>
>>>> Using EXPERIMENTAL tag in linker script is relatively new approach and this was
>>>> not a requirement, so many experimental APIs are documented in API documentation
>>>> (header file doxygen comment).
>>>> Sample: librte_member
>>>>
>>> That sounds like case (3) above.
>>>
>>> Thats a bit odd.  I understand that the use of the EXPERIMENTAL version tag is
>>> new, but once it was introduced it should have been made a requirement.  There
>>> would have been no penalty for moving the version number (as doing so would not
>>> have violated ABI guarantees, given that those API's were appropriately
>>> documented as experimental).  If they have not been, then the use of the
>>> EXPERIMENTAL tag isn't overly useful, as it doesn't provide any segregation of
>>> the stable ABI from the unstable ABI.
>>>
>>>> It is required to scan all header files and update their linker scripts for the
>>>> experimental APIs.
>>>>
>>> Yes and no.  If a given library is not marked as experimental in its version
>>> map, this change won't flag it as a problem, but if its intended to be
>>> experimental (i.e. if its likely to have its ABI fluctuate), then yes, we should
>>> take the appropriate steps to flag it as such properly.
>>>
>>> If a given library is intended to be experimental, I would say yes,
>>> the author should make the appropriate chage to the version map, and then the
>>> corresponding change to the headers  and c files with this new tag.
>>> Alternatively, they might choose to simply update the documentation to reflect
>>> the fact that the ABI for that library is now stable.
>>>
>>> The thing that should definately not hapen though, is a half measure.  We
>>> shouldn't allow libraries to call themselves experimental, and then excuse them
>>> from any rules we have regarding their in-code representation.  If we have an
>>> EXPERIMENTAL version in the map, we should require its use, and by extension
>>> require this tag when its merged for the reasons previously outlined
>>
>> My comment is for your item (3), but it is not fair to say "incorrectly placed"
>> because if I don't miss anything this has never been documented as correct way
>> to do, and lots of the existing usage is _before_ we start using EXPERIMENTAL
>> tag in the linker script, so they were doing right thing for that time.
>>
> Ok, Apologies, perhaps incorrectly placed isn't a fair term to use.  Perhaps it
> would be better to say the experimental specification was insufficiently
> documented?  The point however remains.  Defining an API category that conveys a
> freedom of modification of ABI needs to follow rules for identification, and
> providing a mechanism to tag said ABIs in the code without a requirement to use
> it creates an confusing situation to say the least (i.e. some APIS will be
> listed as belonging to the EXPERIMENTAL version, others won't, but will be
> documented as such, creating an ambiguous status).
> 
>> Question is, is this patchset should fix them, since now this patchset defines
>> using EXPERIMENTAL tag in linker script as way to do it, or should we wait
>> maintainers to fix it after this has been documented. Waiting for maintainer may
>> take time because not all maintainers are following the mail list closely to
>> capture all expectations.
>>
> 
> In answer, I think waiting for maintainers to correct their experimental
> use isn't going to get anything done.  As you said, not all maintainers monitor
> all conversations closely enough to pick up on the need, and as we move forward
> this effort will likely get de-prioitized, as the status quo will just continue
> to exist.  I would propose that we accept this patch, and then I subsequently
> preform an audit on the documentation to find other APIs which are documented as
> EXPERIMENTAL, but not tagged as such in their version files.  I can submit
> subsequent patches to reconcile those APIs that I find, which should get on the
> respective maintainers radars.  Does that sound reasonable?

Sounds good to me, hence

Series
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>

> 
> Neil
> 
>>>
>>> Neil
>>>
>>>
>>>>>  14 files changed, 139 insertions(+), 116 deletions(-)
>>>>
>>>> <...>
>>>>
>>>>
>>
>>
  

Patch

diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index dda8f5835..ee866ddd2 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -37,6 +37,7 @@ 
 #include <inttypes.h>
 #include <sys/queue.h>
 
+#include <rte_compat.h>
 #include <rte_bus.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -133,7 +134,7 @@  full_dev_name(const char *bus, const char *dev, const char *args)
 	return name;
 }
 
-int rte_eal_hotplug_add(const char *busname, const char *devname,
+int __experimental rte_eal_hotplug_add(const char *busname, const char *devname,
 			const char *devargs)
 {
 	struct rte_bus *bus;
@@ -203,7 +204,8 @@  int rte_eal_hotplug_add(const char *busname, const char *devname,
 	return ret;
 }
 
-int rte_eal_hotplug_remove(const char *busname, const char *devname)
+int __experimental
+rte_eal_hotplug_remove(const char *busname, const char *devname)
 {
 	struct rte_bus *bus;
 	struct rte_device *dev;
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index 6ac88d6ab..8e46d54bd 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -40,6 +40,7 @@ 
 #include <stdio.h>
 #include <string.h>
 
+#include <rte_compat.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include <rte_tailq.h>
@@ -85,7 +86,7 @@  bus_name_cmp(const struct rte_bus *bus, const void *name)
 	return strncmp(bus->name, name, strlen(bus->name));
 }
 
-int
+int __experimental
 rte_eal_devargs_parse(const char *dev, struct rte_devargs *da)
 {
 	struct rte_bus *bus = NULL;
@@ -139,7 +140,7 @@  rte_eal_devargs_parse(const char *dev, struct rte_devargs *da)
 	return 0;
 }
 
-int
+int __experimental
 rte_eal_devargs_insert(struct rte_devargs *da)
 {
 	int ret;
@@ -188,7 +189,7 @@  rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
 	return -1;
 }
 
-int
+int __experimental
 rte_eal_devargs_remove(const char *busname, const char *devname)
 {
 	struct rte_devargs *d;
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 9342e0cbd..ddb0a09a7 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -49,6 +49,7 @@  extern "C" {
 #include <stdio.h>
 #include <sys/queue.h>
 
+#include <rte_compat.h>
 #include <rte_log.h>
 
 __attribute__((format(printf, 2, 0)))
@@ -209,7 +210,7 @@  int rte_eal_dev_detach(struct rte_device *dev);
  * @return
  *   0 on success, negative on error.
  */
-int rte_eal_hotplug_add(const char *busname, const char *devname,
+int __experimental rte_eal_hotplug_add(const char *busname, const char *devname,
 			const char *devargs);
 
 /**
@@ -225,7 +226,8 @@  int rte_eal_hotplug_add(const char *busname, const char *devname,
  * @return
  *   0 on success, negative on error.
  */
-int rte_eal_hotplug_remove(const char *busname, const char *devname);
+int __experimental rte_eal_hotplug_remove(const char *busname,
+					  const char *devname);
 
 /**
  * Device comparison function.
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 58d585df6..e4c10b6c5 100644
--- a/lib/librte_eal/common/include/rte_devargs.h
+++ b/lib/librte_eal/common/include/rte_devargs.h
@@ -50,6 +50,7 @@  extern "C" {
 
 #include <stdio.h>
 #include <sys/queue.h>
+#include <rte_compat.h>
 #include <rte_bus.h>
 
 /**
@@ -136,7 +137,7 @@  int rte_eal_parse_devargs_str(const char *devargs_str,
  *   - 0 on success.
  *   - Negative errno on error.
  */
-int
+int __experimental
 rte_eal_devargs_parse(const char *dev,
 		      struct rte_devargs *da);
 
@@ -150,7 +151,7 @@  rte_eal_devargs_parse(const char *dev,
  *   - 0 on success
  *   - Negative on error.
  */
-int
+int __experimental
 rte_eal_devargs_insert(struct rte_devargs *da);
 
 /**
@@ -193,7 +194,8 @@  int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str);
  *   <0 on error.
  *   >0 if the devargs was not within the user device list.
  */
-int rte_eal_devargs_remove(const char *busname, const char *devname);
+int __experimental rte_eal_devargs_remove(const char *busname,
+					  const char *devname);
 
 /**
  * Count the number of user devices of a specified type
diff --git a/lib/librte_eal/common/include/rte_service.h b/lib/librte_eal/common/include/rte_service.h
index 927244065..da10d17ea 100644
--- a/lib/librte_eal/common/include/rte_service.h
+++ b/lib/librte_eal/common/include/rte_service.h
@@ -84,7 +84,7 @@  extern "C" {
  *
  * @return The number of services registered.
  */
-uint32_t rte_service_get_count(void);
+uint32_t __experimental rte_service_get_count(void);
 
 /**
  * @warning
@@ -111,7 +111,8 @@  uint32_t rte_service_get_count(void);
  * @retval -EINVAL Null *service_id* pointer provided
  * @retval -ENODEV No such service registered
  */
-int32_t rte_service_get_by_name(const char *name, uint32_t *service_id);
+int32_t __experimental rte_service_get_by_name(const char *name,
+					       uint32_t *service_id);
 
 /**
  * @warning
@@ -122,7 +123,7 @@  int32_t rte_service_get_by_name(const char *name, uint32_t *service_id);
  * @return A pointer to the name of the service. The returned pointer remains
  *         in ownership of the service, and the application must not free it.
  */
-const char *rte_service_get_name(uint32_t id);
+const char __experimental *rte_service_get_name(uint32_t id);
 
 /**
  * @warning
@@ -135,7 +136,8 @@  const char *rte_service_get_name(uint32_t id);
  * @retval 1 Capability supported by this service instance
  * @retval 0 Capability not supported by this service instance
  */
-int32_t rte_service_probe_capability(uint32_t id, uint32_t capability);
+int32_t __experimental rte_service_probe_capability(uint32_t id,
+						    uint32_t capability);
 
 /**
  * @warning
@@ -159,8 +161,8 @@  int32_t rte_service_probe_capability(uint32_t id, uint32_t capability);
  * @retval 0 lcore map updated successfully
  * @retval -EINVAL An invalid service or lcore was provided.
  */
-int32_t rte_service_map_lcore_set(uint32_t service_id, uint32_t lcore,
-				  uint32_t enable);
+int32_t __experimental rte_service_map_lcore_set(uint32_t service_id,
+				  uint32_t lcore, uint32_t enable);
 
 /**
  * @warning
@@ -175,7 +177,8 @@  int32_t rte_service_map_lcore_set(uint32_t service_id, uint32_t lcore,
  * @retval 0 lcore is not mapped to service
  * @retval -EINVAL An invalid service or lcore was provided.
  */
-int32_t rte_service_map_lcore_get(uint32_t service_id, uint32_t lcore);
+int32_t __experimental rte_service_map_lcore_get(uint32_t service_id,
+						 uint32_t lcore);
 
 /**
  * @warning
@@ -192,7 +195,7 @@  int32_t rte_service_map_lcore_get(uint32_t service_id, uint32_t lcore);
  * @retval 0 The service was successfully started
  * @retval -EINVAL Invalid service id
  */
-int32_t rte_service_runstate_set(uint32_t id, uint32_t runstate);
+int32_t __experimental rte_service_runstate_set(uint32_t id, uint32_t runstate);
 
 /**
  * @warning
@@ -210,7 +213,7 @@  int32_t rte_service_runstate_set(uint32_t id, uint32_t runstate);
  * @retval 0 Service is stopped
  * @retval -EINVAL Invalid service id
  */
-int32_t rte_service_runstate_get(uint32_t id);
+int32_t __experimental rte_service_runstate_get(uint32_t id);
 
 /**
  * @warning
@@ -226,7 +229,8 @@  int32_t rte_service_runstate_get(uint32_t id);
  * @retval 0 Success
  * @retval -EINVAL Invalid service ID
  */
-int32_t rte_service_set_runstate_mapped_check(uint32_t id, int32_t enable);
+int32_t __experimental rte_service_set_runstate_mapped_check(uint32_t id,
+							     int32_t enable);
 
 /**
  * @warning
@@ -264,7 +268,7 @@  int32_t rte_service_set_runstate_mapped_check(uint32_t id, int32_t enable);
  * @retval -ENOEXEC Service is not in a run-able state
  * @retval -EINVAL Invalid service id
  */
-int32_t rte_service_run_iter_on_app_lcore(uint32_t id,
+int32_t __experimental rte_service_run_iter_on_app_lcore(uint32_t id,
 		uint32_t serialize_multithread_unsafe);
 
 /**
@@ -280,7 +284,7 @@  int32_t rte_service_run_iter_on_app_lcore(uint32_t id,
  * @retval -EINVAL Failed to start core. The *lcore_id* passed in is not
  *          currently assigned to be a service core.
  */
-int32_t rte_service_lcore_start(uint32_t lcore_id);
+int32_t __experimental rte_service_lcore_start(uint32_t lcore_id);
 
 /**
  * @warning
@@ -299,7 +303,7 @@  int32_t rte_service_lcore_start(uint32_t lcore_id);
  *          The application must stop the service first, and then stop the
  *          lcore.
  */
-int32_t rte_service_lcore_stop(uint32_t lcore_id);
+int32_t __experimental rte_service_lcore_stop(uint32_t lcore_id);
 
 /**
  * @warning
@@ -315,7 +319,7 @@  int32_t rte_service_lcore_stop(uint32_t lcore_id);
  * @retval -EALREADY lcore is already added to the service core list
  * @retval -EINVAL Invalid lcore provided
  */
-int32_t rte_service_lcore_add(uint32_t lcore);
+int32_t __experimental rte_service_lcore_add(uint32_t lcore);
 
 /**
  * @warning
@@ -329,7 +333,7 @@  int32_t rte_service_lcore_add(uint32_t lcore);
  * @retval -EBUSY Lcore is not stopped, stop service core before removing.
  * @retval -EINVAL failed to add lcore to service core mask.
  */
-int32_t rte_service_lcore_del(uint32_t lcore);
+int32_t __experimental rte_service_lcore_del(uint32_t lcore);
 
 /**
  * @warning
@@ -346,7 +350,7 @@  int32_t rte_service_lcore_del(uint32_t lcore);
  *
  * @return The number of service cores currently configured.
  */
-int32_t rte_service_lcore_count(void);
+int32_t __experimental rte_service_lcore_count(void);
 
 /**
  * @warning
@@ -358,7 +362,7 @@  int32_t rte_service_lcore_count(void);
  *
  * @retval 0 Success
  */
-int32_t rte_service_lcore_reset_all(void);
+int32_t __experimental rte_service_lcore_reset_all(void);
 
 /**
  * @warning
@@ -372,7 +376,8 @@  int32_t rte_service_lcore_reset_all(void);
  * @retval 0 Success
  * @retval -EINVAL Invalid service pointer passed
  */
-int32_t rte_service_set_stats_enable(uint32_t id, int32_t enable);
+int32_t __experimental rte_service_set_stats_enable(uint32_t id,
+						    int32_t enable);
 
 /**
  * @warning
@@ -393,7 +398,7 @@  int32_t rte_service_set_stats_enable(uint32_t id, int32_t enable);
  *          service core list. No items have been populated, call this function
  *          with a size of at least *rte_service_core_count* items.
  */
-int32_t rte_service_lcore_list(uint32_t array[], uint32_t n);
+int32_t __experimental rte_service_lcore_list(uint32_t array[], uint32_t n);
 
 /**
  * @warning
@@ -406,7 +411,7 @@  int32_t rte_service_lcore_list(uint32_t array[], uint32_t n);
  * @retval -EINVAL Invalid lcore provided
  * @retval -ENOTSUP The provided lcore is not a service core.
  */
-int32_t rte_service_lcore_count_services(uint32_t lcore);
+int32_t __experimental rte_service_lcore_count_services(uint32_t lcore);
 
 /**
  * @warning
@@ -418,7 +423,7 @@  int32_t rte_service_lcore_count_services(uint32_t lcore);
  * @retval 0 Statistics have been successfully dumped
  * @retval -EINVAL Invalid service id provided
  */
-int32_t rte_service_dump(FILE *f, uint32_t id);
+int32_t __experimental rte_service_dump(FILE *f, uint32_t id);
 
 #ifdef __cplusplus
 }
diff --git a/lib/librte_eal/common/include/rte_service_component.h b/lib/librte_eal/common/include/rte_service_component.h
index ac965cb48..a129258eb 100644
--- a/lib/librte_eal/common/include/rte_service_component.h
+++ b/lib/librte_eal/common/include/rte_service_component.h
@@ -37,7 +37,7 @@ 
  * Include this file if you are writing a component that requires CPU cycles to
  * operate, and you wish to run the component using service cores
  */
-
+#include <rte_compat.h>
 #include <rte_service.h>
 
 /**
@@ -101,8 +101,9 @@  struct rte_service_spec {
  *         -EINVAL Attempted to register an invalid service (eg, no callback
  *         set)
  */
-int32_t rte_service_component_register(const struct rte_service_spec *spec,
-				       uint32_t *service_id);
+int32_t __experimental
+rte_service_component_register(const struct rte_service_spec *spec,
+			       uint32_t *service_id);
 
 /**
  * @warning
@@ -116,7 +117,7 @@  int32_t rte_service_component_register(const struct rte_service_spec *spec,
  * @retval -EBUSY The service is currently running, stop the service before
  *          calling unregister. No action has been taken.
  */
-int32_t rte_service_component_unregister(uint32_t id);
+int32_t __experimental rte_service_component_unregister(uint32_t id);
 
 /**
  * @warning
@@ -134,7 +135,7 @@  int32_t rte_service_component_unregister(uint32_t id);
  * @retval -ENODEV Error in enabling service lcore on a service
  * @retval -ENOEXEC Error when starting services
  */
-int32_t rte_service_start_with_defaults(void);
+int32_t __experimental rte_service_start_with_defaults(void);
 
 /**
  * @warning
@@ -151,7 +152,8 @@  int32_t rte_service_start_with_defaults(void);
  *
  * @retval 0 Success
  */
-int32_t rte_service_component_runstate_set(uint32_t id, uint32_t runstate);
+int32_t __experimental rte_service_component_runstate_set(uint32_t id,
+							  uint32_t runstate);
 
 /**
  * @warning
diff --git a/lib/librte_eal/common/rte_service.c b/lib/librte_eal/common/rte_service.c
index ae97e6b7f..178354323 100644
--- a/lib/librte_eal/common/rte_service.c
+++ b/lib/librte_eal/common/rte_service.c
@@ -38,6 +38,7 @@ 
 #include <string.h>
 #include <dirent.h>
 
+#include <rte_compat.h>
 #include <rte_service.h>
 #include "include/rte_service_component.h"
 
@@ -168,7 +169,8 @@  service_mt_safe(struct rte_service_spec_impl *s)
 	return !!(s->spec.capabilities & RTE_SERVICE_CAP_MT_SAFE);
 }
 
-int32_t rte_service_set_stats_enable(uint32_t id, int32_t enabled)
+int32_t __experimental
+rte_service_set_stats_enable(uint32_t id, int32_t enabled)
 {
 	struct rte_service_spec_impl *s;
 	SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
@@ -181,7 +183,8 @@  int32_t rte_service_set_stats_enable(uint32_t id, int32_t enabled)
 	return 0;
 }
 
-int32_t rte_service_set_runstate_mapped_check(uint32_t id, int32_t enabled)
+int32_t __experimental
+rte_service_set_runstate_mapped_check(uint32_t id, int32_t enabled)
 {
 	struct rte_service_spec_impl *s;
 	SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
@@ -194,13 +197,14 @@  int32_t rte_service_set_runstate_mapped_check(uint32_t id, int32_t enabled)
 	return 0;
 }
 
-uint32_t
+uint32_t __experimental
 rte_service_get_count(void)
 {
 	return rte_service_count;
 }
 
-int32_t rte_service_get_by_name(const char *name, uint32_t *service_id)
+int32_t __experimental
+rte_service_get_by_name(const char *name, uint32_t *service_id)
 {
 	if (!service_id)
 		return -EINVAL;
@@ -217,7 +221,7 @@  int32_t rte_service_get_by_name(const char *name, uint32_t *service_id)
 	return -ENODEV;
 }
 
-const char *
+const char * __experimental
 rte_service_get_name(uint32_t id)
 {
 	struct rte_service_spec_impl *s;
@@ -225,7 +229,7 @@  rte_service_get_name(uint32_t id)
 	return s->spec.name;
 }
 
-int32_t
+int32_t __experimental
 rte_service_probe_capability(uint32_t id, uint32_t capability)
 {
 	struct rte_service_spec_impl *s;
@@ -233,7 +237,7 @@  rte_service_probe_capability(uint32_t id, uint32_t capability)
 	return !!(s->spec.capabilities & capability);
 }
 
-int32_t
+int32_t __experimental
 rte_service_component_register(const struct rte_service_spec *spec,
 			       uint32_t *id_ptr)
 {
@@ -266,7 +270,7 @@  rte_service_component_register(const struct rte_service_spec *spec,
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_component_unregister(uint32_t id)
 {
 	uint32_t i;
@@ -287,7 +291,7 @@  rte_service_component_unregister(uint32_t id)
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_component_runstate_set(uint32_t id, uint32_t runstate)
 {
 	struct rte_service_spec_impl *s;
@@ -302,7 +306,7 @@  rte_service_component_runstate_set(uint32_t id, uint32_t runstate)
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_runstate_set(uint32_t id, uint32_t runstate)
 {
 	struct rte_service_spec_impl *s;
@@ -317,7 +321,7 @@  rte_service_runstate_set(uint32_t id, uint32_t runstate)
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_runstate_get(uint32_t id)
 {
 	struct rte_service_spec_impl *s;
@@ -378,7 +382,7 @@  service_run(uint32_t i, struct core_state *cs, uint64_t service_mask)
 	return 0;
 }
 
-int32_t rte_service_run_iter_on_app_lcore(uint32_t id,
+int32_t __experimental rte_service_run_iter_on_app_lcore(uint32_t id,
 		uint32_t serialize_mt_unsafe)
 {
 	/* run service on calling core, using all-ones as the service mask */
@@ -434,7 +438,7 @@  rte_service_runner_func(void *arg)
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_count(void)
 {
 	int32_t count = 0;
@@ -444,7 +448,7 @@  rte_service_lcore_count(void)
 	return count;
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_list(uint32_t array[], uint32_t n)
 {
 	uint32_t count = rte_service_lcore_count();
@@ -467,7 +471,7 @@  rte_service_lcore_list(uint32_t array[], uint32_t n)
 	return count;
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_count_services(uint32_t lcore)
 {
 	if (lcore >= RTE_MAX_LCORE)
@@ -480,7 +484,7 @@  rte_service_lcore_count_services(uint32_t lcore)
 	return __builtin_popcountll(cs->service_mask);
 }
 
-int32_t
+int32_t __experimental
 rte_service_start_with_defaults(void)
 {
 	/* create a default mapping from cores to services, then start the
@@ -562,7 +566,7 @@  service_update(struct rte_service_spec *service, uint32_t lcore,
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_map_lcore_set(uint32_t id, uint32_t lcore, uint32_t enabled)
 {
 	struct rte_service_spec_impl *s;
@@ -571,7 +575,7 @@  rte_service_map_lcore_set(uint32_t id, uint32_t lcore, uint32_t enabled)
 	return service_update(&s->spec, lcore, &on, 0);
 }
 
-int32_t
+int32_t __experimental
 rte_service_map_lcore_get(uint32_t id, uint32_t lcore)
 {
 	struct rte_service_spec_impl *s;
@@ -583,7 +587,7 @@  rte_service_map_lcore_get(uint32_t id, uint32_t lcore)
 	return ret;
 }
 
-int32_t rte_service_lcore_reset_all(void)
+int32_t __experimental rte_service_lcore_reset_all(void)
 {
 	/* loop over cores, reset all to mask 0 */
 	uint32_t i;
@@ -614,7 +618,7 @@  set_lcore_state(uint32_t lcore, int32_t state)
 	lcore_states[lcore].is_service_core = (state == ROLE_SERVICE);
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_add(uint32_t lcore)
 {
 	if (lcore >= RTE_MAX_LCORE)
@@ -633,7 +637,7 @@  rte_service_lcore_add(uint32_t lcore)
 	return rte_eal_wait_lcore(lcore);
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_del(uint32_t lcore)
 {
 	if (lcore >= RTE_MAX_LCORE)
@@ -652,7 +656,7 @@  rte_service_lcore_del(uint32_t lcore)
 	return 0;
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_start(uint32_t lcore)
 {
 	if (lcore >= RTE_MAX_LCORE)
@@ -675,7 +679,7 @@  rte_service_lcore_start(uint32_t lcore)
 	return ret;
 }
 
-int32_t
+int32_t __experimental
 rte_service_lcore_stop(uint32_t lcore)
 {
 	if (lcore >= RTE_MAX_LCORE)
@@ -745,7 +749,7 @@  service_dump_calls_per_lcore(FILE *f, uint32_t lcore, uint32_t reset)
 	fprintf(f, "\n");
 }
 
-int32_t rte_service_dump(FILE *f, uint32_t id)
+int32_t __experimental rte_service_dump(FILE *f, uint32_t id)
 {
 	uint32_t i;
 	int print_one = (id != UINT32_MAX);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9f1..73a0da22c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -53,6 +53,7 @@ 
 #include <sys/io.h>
 #endif
 
+#include <rte_compat.h>
 #include <rte_common.h>
 #include <rte_debug.h>
 #include <rte_memory.h>
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
index 4f56f8714..2cbe0bb5a 100644
--- a/lib/librte_ether/rte_mtr.c
+++ b/lib/librte_ether/rte_mtr.c
@@ -34,6 +34,7 @@ 
 #include <stdint.h>
 
 #include <rte_errno.h>
+#include "rte_compat.h"
 #include "rte_ethdev.h"
 #include "rte_mtr_driver.h"
 #include "rte_mtr.h"
@@ -86,7 +87,7 @@  rte_mtr_ops_get(uint16_t port_id, struct rte_mtr_error *error)
 })
 
 /* MTR capabilities get */
-int
+int __experimental
 rte_mtr_capabilities_get(uint16_t port_id,
 	struct rte_mtr_capabilities *cap,
 	struct rte_mtr_error *error)
@@ -97,7 +98,7 @@  rte_mtr_capabilities_get(uint16_t port_id,
 }
 
 /* MTR meter profile add */
-int
+int __experimental
 rte_mtr_meter_profile_add(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_meter_profile *profile,
@@ -109,7 +110,7 @@  rte_mtr_meter_profile_add(uint16_t port_id,
 }
 
 /** MTR meter profile delete */
-int
+int __experimental
 rte_mtr_meter_profile_delete(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_error *error)
@@ -120,7 +121,7 @@  rte_mtr_meter_profile_delete(uint16_t port_id,
 }
 
 /** MTR object create */
-int
+int __experimental
 rte_mtr_create(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -133,7 +134,7 @@  rte_mtr_create(uint16_t port_id,
 }
 
 /** MTR object destroy */
-int
+int __experimental
 rte_mtr_destroy(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error)
@@ -144,7 +145,7 @@  rte_mtr_destroy(uint16_t port_id,
 }
 
 /** MTR object meter enable */
-int
+int __experimental
 rte_mtr_meter_enable(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error)
@@ -155,7 +156,7 @@  rte_mtr_meter_enable(uint16_t port_id,
 }
 
 /** MTR object meter disable */
-int
+int __experimental
 rte_mtr_meter_disable(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error)
@@ -166,7 +167,7 @@  rte_mtr_meter_disable(uint16_t port_id,
 }
 
 /** MTR object meter profile update */
-int
+int __experimental
 rte_mtr_meter_profile_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint32_t meter_profile_id,
@@ -178,7 +179,7 @@  rte_mtr_meter_profile_update(uint16_t port_id,
 }
 
 /** MTR object meter DSCP table update */
-int
+int __experimental
 rte_mtr_meter_dscp_table_update(uint16_t port_id,
 	uint32_t mtr_id,
 	enum rte_mtr_color *dscp_table,
@@ -190,7 +191,7 @@  rte_mtr_meter_dscp_table_update(uint16_t port_id,
 }
 
 /** MTR object policer action update */
-int
+int __experimental
 rte_mtr_policer_actions_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint32_t action_mask,
@@ -203,7 +204,7 @@  rte_mtr_policer_actions_update(uint16_t port_id,
 }
 
 /** MTR object enabled stats update */
-int
+int __experimental
 rte_mtr_stats_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint64_t stats_mask,
@@ -215,7 +216,7 @@  rte_mtr_stats_update(uint16_t port_id,
 }
 
 /** MTR object stats read */
-int
+int __experimental
 rte_mtr_stats_read(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_stats *stats,
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
index f6b6ef3b6..fd8361998 100644
--- a/lib/librte_ether/rte_mtr.h
+++ b/lib/librte_ether/rte_mtr.h
@@ -74,7 +74,7 @@ 
  * @b EXPERIMENTAL: this API may change without prior notice
  */
 #include <stdint.h>
-
+#include <rte_compat.h>
 #include <rte_common.h>
 
 #ifdef __cplusplus
@@ -447,7 +447,7 @@  struct rte_mtr_error {
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_capabilities_get(uint16_t port_id,
 	struct rte_mtr_capabilities *cap,
 	struct rte_mtr_error *error);
@@ -470,7 +470,7 @@  rte_mtr_capabilities_get(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_profile_add(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_meter_profile *profile,
@@ -491,7 +491,7 @@  rte_mtr_meter_profile_add(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_profile_delete(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_error *error);
@@ -519,7 +519,7 @@  rte_mtr_meter_profile_delete(uint16_t port_id,
  *
  * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
  */
-int
+int __experimental
 rte_mtr_create(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -542,7 +542,7 @@  rte_mtr_create(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_destroy(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error);
@@ -569,7 +569,7 @@  rte_mtr_destroy(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_disable(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error);
@@ -590,7 +590,7 @@  rte_mtr_meter_disable(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_enable(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_error *error);
@@ -609,7 +609,7 @@  rte_mtr_meter_enable(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_profile_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint32_t meter_profile_id,
@@ -633,7 +633,7 @@  rte_mtr_meter_profile_update(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_meter_dscp_table_update(uint16_t port_id,
 	uint32_t mtr_id,
 	enum rte_mtr_color *dscp_table,
@@ -659,7 +659,7 @@  rte_mtr_meter_dscp_table_update(uint16_t port_id,
  * @return
  *   0 on success, non-zero error code otherwise.
  */
-int
+int __experimental
 rte_mtr_policer_actions_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint32_t action_mask,
@@ -684,7 +684,7 @@  rte_mtr_policer_actions_update(uint16_t port_id,
  *
  * @see enum rte_mtr_stats_type
  */
-int
+int __experimental
 rte_mtr_stats_update(uint16_t port_id,
 	uint32_t mtr_id,
 	uint64_t stats_mask,
@@ -715,7 +715,7 @@  rte_mtr_stats_update(uint16_t port_id,
  *
  * @see enum rte_mtr_stats_type
  */
-int
+int __experimental
 rte_mtr_stats_read(uint16_t port_id,
 	uint32_t mtr_id,
 	struct rte_mtr_stats *stats,
diff --git a/lib/librte_flow_classify/rte_flow_classify.c b/lib/librte_flow_classify/rte_flow_classify.c
index e6f448643..6716672fc 100644
--- a/lib/librte_flow_classify/rte_flow_classify.c
+++ b/lib/librte_flow_classify/rte_flow_classify.c
@@ -31,6 +31,7 @@ 
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <rte_compat.h>
 #include <rte_flow_classify.h>
 #include "rte_flow_classify_parse.h"
 #include <rte_flow_driver.h>
@@ -245,7 +246,7 @@  rte_flow_classifier_check_params(struct rte_flow_classifier_params *params)
 	return 0;
 }
 
-struct rte_flow_classifier *
+struct rte_flow_classifier * __experimental
 rte_flow_classifier_create(struct rte_flow_classifier_params *params)
 {
 	struct rte_flow_classifier *cls;
@@ -291,7 +292,7 @@  rte_flow_classify_table_free(struct rte_table *table)
 		table->ops.f_free(table->h_table);
 }
 
-int
+int __experimental
 rte_flow_classifier_free(struct rte_flow_classifier *cls)
 {
 	uint32_t i;
@@ -369,7 +370,7 @@  rte_table_check_params(struct rte_flow_classifier *cls,
 	return 0;
 }
 
-int
+int __experimental
 rte_flow_classify_table_create(struct rte_flow_classifier *cls,
 	struct rte_flow_classify_table_params *params,
 	uint32_t *table_id)
@@ -483,7 +484,7 @@  allocate_acl_ipv4_5tuple_rule(void)
 	return rule;
 }
 
-struct rte_flow_classify_rule *
+struct rte_flow_classify_rule * __experimental
 rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
 		uint32_t table_id,
 		int *key_found,
@@ -582,7 +583,7 @@  rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
 	return rule;
 }
 
-int
+int __experimental
 rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
 		uint32_t table_id,
 		struct rte_flow_classify_rule *rule)
@@ -659,7 +660,7 @@  action_apply(struct rte_flow_classifier *cls,
 	return ret;
 }
 
-int
+int __experimental
 rte_flow_classifier_query(struct rte_flow_classifier *cls,
 		uint32_t table_id,
 		struct rte_mbuf **pkts,
diff --git a/lib/librte_flow_classify/rte_flow_classify.h b/lib/librte_flow_classify/rte_flow_classify.h
index 1211873a1..cd9516f9e 100644
--- a/lib/librte_flow_classify/rte_flow_classify.h
+++ b/lib/librte_flow_classify/rte_flow_classify.h
@@ -70,6 +70,7 @@ 
  *    with rte_flow_classifier_free()
  */
 
+#include <rte_compat.h>
 #include <rte_ethdev.h>
 #include <rte_ether.h>
 #include <rte_flow.h>
@@ -176,7 +177,7 @@  struct rte_flow_classify_ipv4_5tuple_stats {
  * @return
  *   Handle to flow classifier instance on success or NULL otherwise
  */
-struct rte_flow_classifier *
+struct rte_flow_classifier * __experimental
 rte_flow_classifier_create(struct rte_flow_classifier_params *params);
 
 /**
@@ -187,7 +188,7 @@  rte_flow_classifier_create(struct rte_flow_classifier_params *params);
  * @return
  *   0 on success, error code otherwise
  */
-int
+int __experimental
 rte_flow_classifier_free(struct rte_flow_classifier *cls);
 
 /**
@@ -203,7 +204,7 @@  rte_flow_classifier_free(struct rte_flow_classifier *cls);
  * @return
  *   0 on success, error code otherwise
  */
-int
+int __experimental
 rte_flow_classify_table_create(struct rte_flow_classifier *cls,
 		struct rte_flow_classify_table_params *params,
 		uint32_t *table_id);
@@ -250,7 +251,7 @@  rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
  * @return
  *   0 on success, error code otherwise.
  */
-int
+int __experimental
 rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
 		uint32_t table_id,
 		struct rte_flow_classify_rule *rule);
@@ -274,7 +275,7 @@  rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
  * @return
  *   0 on success, error code otherwise.
  */
-int
+int __experimental
 rte_flow_classifier_query(struct rte_flow_classifier *cls,
 		uint32_t table_id,
 		struct rte_mbuf **pkts,
diff --git a/lib/librte_security/rte_security.c b/lib/librte_security/rte_security.c
index 1227fca8a..958b7273e 100644
--- a/lib/librte_security/rte_security.c
+++ b/lib/librte_security/rte_security.c
@@ -33,12 +33,12 @@ 
 
 #include <rte_malloc.h>
 #include <rte_dev.h>
-
+#include "rte_compat.h"
 #include "rte_security.h"
 #include "rte_security_driver.h"
 
 struct rte_security_session *
-rte_security_session_create(struct rte_security_ctx *instance,
+__experimental rte_security_session_create(struct rte_security_ctx *instance,
 			    struct rte_security_session_conf *conf,
 			    struct rte_mempool *mp)
 {
@@ -61,7 +61,7 @@  rte_security_session_create(struct rte_security_ctx *instance,
 	return sess;
 }
 
-int
+int __experimental
 rte_security_session_update(struct rte_security_ctx *instance,
 			    struct rte_security_session *sess,
 			    struct rte_security_session_conf *conf)
@@ -70,7 +70,7 @@  rte_security_session_update(struct rte_security_ctx *instance,
 	return instance->ops->session_update(instance->device, sess, conf);
 }
 
-int
+int __experimental
 rte_security_session_stats_get(struct rte_security_ctx *instance,
 			       struct rte_security_session *sess,
 			       struct rte_security_stats *stats)
@@ -79,7 +79,7 @@  rte_security_session_stats_get(struct rte_security_ctx *instance,
 	return instance->ops->session_stats_get(instance->device, sess, stats);
 }
 
-int
+int __experimental
 rte_security_session_destroy(struct rte_security_ctx *instance,
 			     struct rte_security_session *sess)
 {
@@ -98,7 +98,7 @@  rte_security_session_destroy(struct rte_security_ctx *instance,
 	return ret;
 }
 
-int
+int __experimental
 rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
 			      struct rte_security_session *sess,
 			      struct rte_mbuf *m, void *params)
@@ -108,14 +108,14 @@  rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
 					       sess, m, params);
 }
 
-const struct rte_security_capability *
+const struct rte_security_capability * __experimental
 rte_security_capabilities_get(struct rte_security_ctx *instance)
 {
 	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->capabilities_get, NULL);
 	return instance->ops->capabilities_get(instance->device);
 }
 
-const struct rte_security_capability *
+const struct rte_security_capability * __experimental
 rte_security_capability_get(struct rte_security_ctx *instance,
 			    struct rte_security_capability_idx *idx)
 {
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 653929b99..176378e78 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -52,6 +52,7 @@  extern "C" {
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
 
+#include <rte_compat.h>
 #include <rte_common.h>
 #include <rte_crypto.h>
 #include <rte_mbuf.h>
@@ -291,7 +292,7 @@  struct rte_security_session {
  *  - On success, pointer to session
  *  - On failure, NULL
  */
-struct rte_security_session *
+struct rte_security_session * __experimental
 rte_security_session_create(struct rte_security_ctx *instance,
 			    struct rte_security_session_conf *conf,
 			    struct rte_mempool *mp);
@@ -306,7 +307,7 @@  rte_security_session_create(struct rte_security_ctx *instance,
  *  - On success returns 0
  *  - On failure return errno
  */
-int
+int __experimental
 rte_security_session_update(struct rte_security_ctx *instance,
 			    struct rte_security_session *sess,
 			    struct rte_security_session_conf *conf);
@@ -323,7 +324,7 @@  rte_security_session_update(struct rte_security_ctx *instance,
  *  - -EINVAL if session is NULL.
  *  - -EBUSY if not all device private data has been freed.
  */
-int
+int __experimental
 rte_security_session_destroy(struct rte_security_ctx *instance,
 			     struct rte_security_session *sess);
 
@@ -340,7 +341,7 @@  rte_security_session_destroy(struct rte_security_ctx *instance,
  *  - On success, zero.
  *  - On failure, a negative value.
  */
-int
+int __experimental
 rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
 			      struct rte_security_session *sess,
 			      struct rte_mbuf *mb, void *params);
@@ -351,7 +352,7 @@  rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
  * @param	sym_op	crypto operation
  * @param	sess	security session
  */
-static inline int
+static inline int __experimental
 __rte_security_attach_session(struct rte_crypto_sym_op *sym_op,
 			      struct rte_security_session *sess)
 {
@@ -360,13 +361,13 @@  __rte_security_attach_session(struct rte_crypto_sym_op *sym_op,
 	return 0;
 }
 
-static inline void *
+static inline void * __experimental
 get_sec_session_private_data(const struct rte_security_session *sess)
 {
 	return sess->sess_private_data;
 }
 
-static inline void
+static inline void __experimental
 set_sec_session_private_data(struct rte_security_session *sess,
 			     void *private_data)
 {
@@ -382,7 +383,7 @@  set_sec_session_private_data(struct rte_security_session *sess,
  * @param	op	crypto operation
  * @param	sess	security session
  */
-static inline int
+static inline int __experimental
 rte_security_attach_session(struct rte_crypto_op *op,
 			    struct rte_security_session *sess)
 {
@@ -424,7 +425,7 @@  struct rte_security_stats {
  *  - On success return 0
  *  - On failure errno
  */
-int
+int __experimental
 rte_security_session_stats_get(struct rte_security_ctx *instance,
 			       struct rte_security_session *sess,
 			       struct rte_security_stats *stats);
@@ -507,7 +508,7 @@  struct rte_security_capability_idx {
  *   - Returns array of security capabilities.
  *   - Return NULL if no capabilities available.
  */
-const struct rte_security_capability *
+const struct rte_security_capability * __experimental
 rte_security_capabilities_get(struct rte_security_ctx *instance);
 
 /**
@@ -521,7 +522,7 @@  rte_security_capabilities_get(struct rte_security_ctx *instance);
  *     index criteria.
  *   - Return NULL if the capability not matched on security instance.
  */
-const struct rte_security_capability *
+const struct rte_security_capability * __experimental
 rte_security_capability_get(struct rte_security_ctx *instance,
 			    struct rte_security_capability_idx *idx);