ping On 11 March 2015 at 14:43, Bill Fischofer <[email protected]> wrote:
> > > On Wed, Mar 11, 2015 at 1:24 PM, Mike Holmes <[email protected]> > wrote: > >> This documentation was moved from the architecture doc to this API doc. >> >> Signed-off-by: Mike Holmes <[email protected]> >> > > Reviewed-by: Bill Fischofer <[email protected]> > > >> --- >> doc/api_guide_lines.dox | 178 >> ++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 178 insertions(+) >> create mode 100644 doc/api_guide_lines.dox >> >> diff --git a/doc/api_guide_lines.dox b/doc/api_guide_lines.dox >> new file mode 100644 >> index 0000000..4cfe088 >> --- /dev/null >> +++ b/doc/api_guide_lines.dox >> @@ -0,0 +1,178 @@ >> +/* Copyright (c) 2014, Linaro Limited >> + >> + * All rights reserved >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +/** >> + >> +@page api_guide_lines API Guide Lines >> + >> +@tableofcontents >> + >> +@section introduction Introduction >> +ODP APIs are implemented as callable C functions that often return a >> typed value. >> +This document describes the approach to handling return values and error >> indications expected of conforming ODP implementations. >> +As such it should be regarded as providing guidelines for how to create >> new ODP APIs. >> + >> +@section functional Functional Definition >> +This section defines the use of data types, calling conventions, and >> return codes used by ODP APIs. >> +All ODP APIs MUST follow these conventions as part of their design. >> + >> +@subsection naming Naming Conventions >> +All ODP APIs begin with the prefix odp_ and those that describe an >> action to be performed on an object follow the naming convention of object >> followed by action. >> +The advantage of this approach is that an alphabetical list of APIs for >> an object all sort together since they all have names of the form >> odp_object_action(). >> + >> +So for example the API call to allocate a buffer is named >> odp_buffer_alloc() rather than odp_alloc_buffer(). >> + >> +@subsection data_types Data Types and Use of typedef >> +ODP is designed to allow broad variability in how APIs are implemented >> on various platforms. >> +To support this, most APIs operate on abstract data types that are >> defined via typedef on a per-implementation basis. >> +These abstract types follow the naming convention of odp_object_t. >> + >> +Typedefs that encapsulate C structs follow the convention: >> + >> +@code >> +typedef struct odp_<descriptive_name>_s { >> +... >> +} odp_<descriptive_name>_t; >> +@endcode >> + >> +The use of typedef allows implementations to choose underlying data >> representations that map efficiently to platform capabilities while >> providing accessor functions to provide structured access to implementation >> information in a portable manner >> +Similarly, the use of enum is RECOMMENDED to provide value abstraction >> for API parameters while enabling the implementation to choose code points >> that map well to platform native values. >> + >> +Several native C types are used conventionally within ODP and SHOULD be >> employed in API design: >> + >> +type | Correct use >> + |---| :--------- >> +void | SHOULD be used for APIs that do not return a value >> +void*| SHOULD be used for APIs that return a pointer intended to be used >> by the caller. For example, a routine that returns the address of an >> application context area SHOULD use a void * return type >> +odp_bool_t | SHOULD be used for APIs that return a @ref boolean value. >> +int | SHOULD be used for success and failure indications, with 0 >> indicating a success. Errno may be set >> + >> +@subsection parameters Parameter Structure and Validation >> +ODP is a framework for use in the data plane. >> +Data plane applications typically have extreme performance requirements >> mandating very strict attention to path length considerations in the design >> of all ODP APIs, with the exception of those designed to be used >> infrequently such as only during initialization or termination processing. >> + >> +Minimizing pathlength in API design involves several considerations: >> + - The number of parameters passed to a call. >> + In general, ODP APIs designed for frequent use SHOULD have few >> parameters. >> + Limiting parameter count to one or two well-chosen parameters SHOULD >> be the goal for APIs designed for frequent use. >> + If a call requires more complex parameter data then it is RECOMMENDED >> that instead of multiple parameters a single pointer to a struct that can >> be statically templated and modified by the caller be used. >> + - The use of macros and inlining. >> + ODP APIs MAY be implemented as preprocessor macros and/or inline >> functions. >> + This is especially true for accessor functions that are designed to >> provide getters/setters for object meta data. >> + - Limiting parameter validation and error-checking processing. >> + While useful for development and debugging, providing “bullet-proof” >> APIs that perform extensive parameter validation and error checking is >> often inappropriate. >> + While validations that can be performed statically at compile time or >> at little to no runtime cost SHOULD be considered, APIs MAY choose to leave >> behavior as undefined when presented with invalid parameters in the >> interest of runtime efficiency. >> + >> +One of the reasons for using abstract types is to avoid having >> implementation knowledge “bleed through” the API, leading to possible >> parameter errors. >> +When one API returns an opaque token to an application it is reasonable >> to expect that the application can pass that token to subsequent APIs >> without needing expensive runtime validation. >> + >> +ODP provides the helper APIs ODP_STATIC_ASSERT(cond,msg) and >> ODP_ASSERT(cond,msg) that SHOULD be used in implementations for performing >> appropriate validation. >> +The former is a compile-time assertion and hence adds no additional path >> length. >> +The latter is controlled by the ODP_NO_DEBUG compile-time switch and so >> is suitable for use in development/debug builds that can be compiled out >> for production use. >> +Other mechanisms available to the implementer are: >> + - ODP_ABORT() is provided for situations where further execution of the >> code must not occur and a level of tracing information should be left in >> the log. >> + - ODP_DEPRECATED() is used to signify that a call is planned for >> obsolescence. >> + - ODP_LOG() is used to direct implementation messages to the >> application. >> + >> + >> +@subsection function_name Function Names >> +Functions must attempt to be so clear in their intent that referencing >> the documentation is not necessary, the guidelines below should be followed >> unless a strong case is made for an exception. >> + >> +@subsection getters Getting information >> + >> +@subsubsection is_has Is / Has >> +An api with "is" or "has" are both considered @ref boolean questions. >> They can only return true or false and it reflects the current state of >> something. >> + >> +An example might be a packet interface, you might want to know if it is >> in promiscuous mode. >> +@code odp_bool_t state = odp_pktio_is_promiscuous(pktio handle) @endcode >> + >> +In addtion you might want to know if it has the ability to be in >> promiscuous mode. >> +@code odp_bool_t state = odp_pktio_has_promiscuous(pktio handle) @endcode >> + >> +Another case might be if a packet has a vlan flag set >> +@code odp_bool_t state = odp_packet_has_vlan(packet handle) @endcode >> + >> +@subsubsection get Get >> +Where possible returned information should be an enum if it reflects a >> finite list of information. >> +In general get apis drop the actual tag "get" in the function name. >> + >> +@subsection function_calls Function Calls >> +ODP APIs typically have prototypes of the form: >> + >> +@code >> +odp_return_type_t odp_api(p1_type p1, p2_type p2, …); >> +@endcode >> +Where: >> + >> +type | Description >> + |--------- | :--------- >> +odp_return_type_t | Is the return value produced by the API call. As >> noted above, the native types void, void *, and int are also used. Other >> APIs return abstract types defined via typedef >> +p1_type | Is the data type of the first parameter >> +p2_type | Is the data type of the second parameter, etc. >> + >> +For ODP APIs that return void, results are undefined if the input >> parameters are invalid. >> +For those that return void *, the value ODP_NULL or ODP_INVALID MAY be >> used to indicate call failure. >> +For non-boolean APIs returning int, a return value of 0 indicates >> success while non-zero indicates failure see @ref success. >> + >> +@subsection errno Use of errno >> +ODP APIs SHOULD make use of the thread-local variable errno, defined in >> the standard library include file errno.h, to indicate a reason for an API >> call failure when appropriate. >> +This convention allows callers to easily determine success/failure of a >> call with a single test and then decode the failure as desired from the >> extended reason provided by errno. >> +So, for example, an attempt to allocate a buffer from a buffer pool >> might return ODP_BUFFER_INVALID if the call was unsuccessful and errno >> could then be set to an appropriate reason (no storage available (ENOMEM, >> ENOBUFS), pool not recognized (EINVAL), etc.). >> + >> +In general APIs are free to define their own errno usage conventions and >> values or reuse standard errno values when appropriate. >> +When “standard” codes exist, implementations SHOULD make use of them so >> that standard utility functions like perror() can decode them intelligently. >> +There are, however, a small set of standard codes that are commonly used. >> +One errno value that MUST be present for all APIs is >> ODP_FUNCTION_NOT_AVAILABLE. >> +This special reason code is used to indicate that the underlying >> implementation does not support the requested API, and SHOULD be equated to >> ENOSYS. >> +This may be because the requested API is specifically designated as >> OPTIONAL or that the caller is using a pre-release version of an API that >> does not have all functionality implemented yet. >> + >> +Another standard errno is ODP_IMPLEMENTATION_LIMIT. >> +This code SHOULD be used if a API call is made that exceeds a permitted >> limit of the underlying implementation, and SHOULD be equated to ERANGE. >> +For example, many APIs MAY mandate certain minimum functionality but >> provide latitude on maximums. >> +An example of this might be the number of queues that an application can >> create. >> +An attempt to allocate more queues than the underlying implementation >> supports would result in this failure code being returned via errno. >> + >> +@subsection boolean Boolean >> +For odp all booleans are integers. To aid application readability they >> are defined as the type odp_bool_t. >> +The values !0 = true, 0 = false are used for this purpose. >> + >> +@subsection success Success and Failure >> +Pass indications are integers (int) and SHOULD also be used for APIs >> that return a simple success/failure indication to the caller. >> +In this case the return value 0 indicates success while non-zero >> (typically -1) indicates failure and errno is set to a reason code that >> indicates the nature of the failure. >> + >> +@subsection odp_internal Internal APIs >> +When an interface is defined in a header file and is intended to to be >> reused internally it will follow these rules:- >> +- Be prefixed with an underscore "_". >> +- All the required definitions for the API are to use an underscore, >> this includes MACROS, typedefs, enums and function names. >> + >> +@section implementation Implementation Considerations >> +To support application portability and preserve implementation >> flexibility, ODP APIs MUST be designed with several guiding principles in >> mind. >> + >> +@subsection application_view Application View vs. Implementation View >> +ODP APIs MUST present an application view of a problem in their >> externals. >> +That is, the API should allow the application to specify what it wants >> to do while the underlying implementation of that API controls how the >> requested function is realized. >> +As a result, ODP APIs SHOULD NOT be designed with a specific >> implementation in mind. >> +This is the reason, for example, that packet I/O in ODP follows a queued >> model. >> +It is an implementation responsibility to determine how packets are >> physically read and written, and whatever internal structures are needed to >> perform this most efficiently are an implementation rather than an >> application concern. >> +In some platforms this may involve the use of receive rings and buffer >> bursting, while in others this may be a simple memory-mapped register >> operation to interface with a hardware packet scheduler/distributor. >> +The ODP application does not care how packets arrive for processing only >> that a packet is available for it to work on. >> + >> +Similarly, ODP applications reference packets data fields in terms of >> the information that is needed, rather than focusing on how that >> information is obtained. >> +The assumption is that the underlying implementation has pre-parsed the >> packet to extract the most relevant data as packet meta data that is >> immediately available to the application without requiring the application >> to do this work itself. >> +Over time, as network speeds increase, more and higher level networking >> functions are expected to migrate directly into hardware and ODP APIs MUST >> be mindful of this evolution in their design. >> + >> +@subsection essential_functions Essential functions vs. Extensions >> +At the same time, APIs SHOULD reflect essential needs of data plane >> application programming and SHOULD NOT strive to offer comprehensive >> solutions to every possible contingency. >> +How to draw this line is a judgement call based on experience but API >> designers MUST take implementation practicalities into consideration when >> designing APIs to ensure that APIs and features can be implemented >> efficiently on a wide variety of underlying platforms. >> +This is one of the reasons why some features MAY be defined as OPTIONAL. >> +While allowed, the proliferation of OPTIONAL features SHOULD be avoided >> to enable broad application portability across many implementations. >> +At the same time, a “least common denominator” approach MUST NOT be >> taken as that defeats the purpose of providing higher-level abstractions in >> APIs. >> + >> +@section defaults Default behaviours >> +When an API has a default behaviour it must be possible for the >> application to explicitly call for that behaviour, this guards against the >> default changing and breaking the application. >> + >> +*/ >> -- >> 2.1.0 >> >> >> _______________________________________________ >> lng-odp mailing list >> [email protected] >> http://lists.linaro.org/mailman/listinfo/lng-odp >> > > -- Mike Holmes Technical Manager - Linaro Networking Group Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
_______________________________________________ lng-odp mailing list [email protected] http://lists.linaro.org/mailman/listinfo/lng-odp
