From patchwork Thu Jun 23 10:19:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Fischofer X-Patchwork-Id: 70754 Delivered-To: patch@linaro.org Received: by 10.140.28.4 with SMTP id 4csp354197qgy; Thu, 23 Jun 2016 03:21:35 -0700 (PDT) X-Received: by 10.233.232.148 with SMTP id a142mr41881935qkg.25.1466677295397; Thu, 23 Jun 2016 03:21:35 -0700 (PDT) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id 143si5093344qkg.152.2016.06.23.03.21.34; Thu, 23 Jun 2016 03:21:35 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 836AF62EB4; Thu, 23 Jun 2016 10:21:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 826C16679B; Thu, 23 Jun 2016 10:19:33 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 1EFDC63A16; Thu, 23 Jun 2016 10:19:25 +0000 (UTC) Received: from mail-wm0-f44.google.com (mail-wm0-f44.google.com [74.125.82.44]) by lists.linaro.org (Postfix) with ESMTPS id 9168C61D64 for ; Thu, 23 Jun 2016 10:19:22 +0000 (UTC) Received: by mail-wm0-f44.google.com with SMTP id r201so42858463wme.1 for ; Thu, 23 Jun 2016 03:19:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jrUjYtkCv+S6KuNG3fXRyLcbVUE+OuvuAT5SC9Vb8Fs=; b=XyrMpzoo0qUOffr0HoZnPTVQZJAmVJzdu/Wlh5I511WgoggRsIAjWH079HPe9UYa/v BBHZdCXTRGX7aoAUnOVXooIzsjemduM5S5EeVbBF5qqsd+hoYI1Oa2y+iZghYlHbZkpO VaY2DlaXODK5YUfJnGIjhJI5hwpoPaYsRgenb9n8zSJswj4bQDsqE9/Q89piBV4qtWwQ ZVksvgQLwXCVHZ4cKjNtmHBwbp5fTUcrOFNWUXHO5XgjsSromyFZRzo1WqDUop4Pnh/e tuCr5j2hvCFewnjmVmRaoUfCmTvIkWeZFuhfEC+wdagjn5OlpEcHTUATFnIPexoRUnvE zwHw== X-Gm-Message-State: ALyK8tI+yjpN/OkkPCPUenyWVdTkD8cn14ChF8w0aqRQjQUO8hshljQb0FbrCunL0E0d3IjTCT0= X-Received: by 10.194.235.4 with SMTP id ui4mr31117562wjc.23.1466677161493; Thu, 23 Jun 2016 03:19:21 -0700 (PDT) Received: from Ubuntu15.localdomain ([62.214.2.210]) by smtp.gmail.com with ESMTPSA id w81sm3124571wmg.20.2016.06.23.03.19.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 23 Jun 2016 03:19:20 -0700 (PDT) From: Bill Fischofer To: lng-odp@lists.linaro.org Date: Thu, 23 Jun 2016 12:19:14 +0200 Message-Id: <1466677154-15944-3-git-send-email-bill.fischofer@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1466677154-15944-1-git-send-email-bill.fischofer@linaro.org> References: <1466677154-15944-1-git-send-email-bill.fischofer@linaro.org> X-Topics: patch Subject: [lng-odp] [PATCH 3/3] doc: implguide: add sections on typedefs and abi coniderations X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" Signed-off-by: Bill Fischofer --- doc/implementers-guide/implementers-guide.adoc | 181 ++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 4 deletions(-) diff --git a/doc/implementers-guide/implementers-guide.adoc b/doc/implementers-guide/implementers-guide.adoc index 1abd884..4f49e8f 100644 --- a/doc/implementers-guide/implementers-guide.adoc +++ b/doc/implementers-guide/implementers-guide.adoc @@ -12,7 +12,68 @@ This document is intended to guide a new ODP implementation developer. Further details about ODP may be found at http://opendataplane.org[ODP homepage] :numbered: -== The include structure + +== Introduction and Overview +ODP consists of three distinct components: + +[[odp_components]] +.OpenDataPlane Components +image::odp_components.svg[align="center"] + +- An abstract API specification. This is the application's writer's view of +ODP and defines the syntax and semantics of all ODP routines at a functional +level. + +- An Implementation of the ODP API for a specific target platform. A +mapping of the ODP APIs to a specific target platform. This is the focus of +this document. + +- A Validation Test Suite. This is an independent set of routines that when +run against an ODP implmenetation verifies that it correctly implements all of +the defined ODP APIs at a functional level. The test suite is used by +implementers to self-certify their ODP implementation as well as by +third-parties to verify an implementation's claim to be ODP API compliant. + +The structure of these components, especially the API specification, is more +fully defined in the _ODP User's Guide_ + +=== Organization of this Document +This document is designed to serve two purposes. Its larger purpose is to +provide guidenace and practical advice for those wishing to implement ODP on +their platform. To help with this, as well as to provide deeper insight into +how to think about ODP from an implementer's standpoint, this document also +discusses in some depth the design and organization of a specific ODP +implementation: the odp-linux reference implementation distributed as part of +the main ODP git repository. By grounding theory in practice and discussing +a particular example implementation, it is hoped this will provide insight into +the tradeoffs implementers should consider in approaching how to best implement +ODP on their platforms. + +The section <> discusses the layout of the ODP include tree +from an implementer's perspective. Although implementers have wide lattitude +in how they organize their ODP implementations, it is recommended that this +layout be be observed by other implementations. Doing so both simplifies code +sharing with the odp-linux reference implementation and also ensure ease of +upgrading to future ODP API levels, as this is the basic layout that will be +observed by future revisions to the API. This layout also facilitates shared +library distribution. + +The section <> then discusses how validation tests are organized +and run to provide ODP API conformance testing for ODP implementations. This +is something ODP implementations need to consider from the outset. ODP uses +a self-certifying model for API compliance, however this self-certification is +performed by the ODP validation test suite (possibly augmented with a vendor's +own extensions to this suite). The important point is that because the +validation suite is itself free open source code, any potential user of a +given ODP implementation is free to do its own validation of a vendor's ODP +implementation using this suite. + +Following this basic material, each ODP API area is then reviewed and its +implementation considerations are discussed, illustrating these considerations +with discussion of how these are done in *odp-linux*. + +[[include_structure]] +== The Include Structure The implementers view of the include source tree allows the common interface definitions and documentation to be reused by all the platforms defined in the @@ -120,16 +181,23 @@ name of the libraries are `libodp-linux` and `libodp-dpdk` respectively. It is recommended that other implementations follow the same schema (*odp-*) to make the representation of the ODP implementations uniform in a distribution. -Additionally there is an ODP helper library to abstract OS differences. - -== The validation Suite +[[validation]] +== The Validation Suite ODP provides a comprehensive set of API validation tests that are intended to be used by implementers during development and by application developers to verify that a particular implementation meets their requirements. The list of these tests is expected to grow as ODP grows. +Note that validation tests are not typically written by implementers, however +their structure and operation needs to be understood so that implementations +can properly run them to validate that they conform to the ODP API +specification. The only exception to this is platform-specific tests, as +described in <>. These may be written by platforms to +leverage the CUnit framework for their own internal test needs or to extend +the platform-agnostic tests with platform-specific logic. + The list of test executables is run by the automake test harness, when running `make check`. Therefore, as required by this harness, each executable should return 0 on @@ -363,6 +431,7 @@ exit $res Note how the above script stores the return code of the test executable to return it properly to the automake test harness. +[[platform-specific-tests]] ==== Defining platform specific tests Sometimes, it may be necessary to call platform specific system calls to check @@ -528,4 +597,108 @@ Five older functions exist to tie and ODP thread to a specific implementation: The usage of these functions should not occur within ODP examples nor tests. The usage of these functions in other application is not recommended. +[[typedefs]] +== ODP Abstract Types and Implementation Typedefs +ODP APIs are defined to be abstract and operate on abstract types. For example, +ODP APIs that perform packet manipulation manipulate objects of type +`odp_packet_t`. Queues are represented by objects of type `odp_queue_t`, etc. + +Since the C compiler cannot compile code that has unresolved abstract types, +the first task of each ODP implementation is to decide how it wishes to +represent each of these abstract types and to supply appropriate `typedef` +definitions for them to make ODP applications compilable on this platform. + +It is recommended that however a platform wishes to represent ODP abstract +types, that it do so in a strongly typed manner. Using strong types means +that an application that tries to pass a variable of type `odp_packet_t` to +an API that expects an argument of type `odp_queue_t`, for example, will result +in a compililation error rather than some difficult to debug runtime failure. + +The *odp-linux* reference implementation defines all ODP abstract types strongly +using a set of utility macros contained in +`platform/linux-generic/include/odp/api/plat/strong_types.h`. These macros +can be used or modified as desired by other implementations to achieve strong +typing of their typedefs. + +=== Typedef approaches +ODP abstract types serve two distinct purposes that each implementation must +consider. First, they shield applications from implementation internals, thus +facilitating ODP application portability. Equally important, however, is that +implementations choose typdefs and representations that permit the +implementation to realize ODP APIs efficiently. This typically means that the +handles defined by typedefs are either a pointer to an implementation-defined +struct or else an index into an implementation-defined resource table. The two +LNG-provided ODP reference implemnetations illustrate both of these approaches. +The *odp-dpdk* implementation follows the former approach (pointers) as this +offers the highest performance. For example, in *odp-dpdk* an +`odp_packet_t` is a pointer to an `rte_mbuf` struct, which is how DPDK +represents packets. The *odp-linux* implementation, by contrast, uses indices +as this permits more robust validation support while still being highly +efficient. In general, software-based implemnetations will typically favor +pointers while hardware-based implementations will typically favor indices. + +=== ABI Considerations +An _Application Binary Interface_ is a specification of the _representation_ +of an API that guarantees that applications can move between implementations +of an API without recompilation. ABIs thus go beyond the basic source-code +portability guarantees provided by APIs to permit binary portability as well. + +It is important to note that ODP neither defines nor prohibits the specification +of ABIs. This is because ODP itself is an _Abstract API Specification_. As +noted earlier, abstract APIs cannot be compiled in the absense of completion +by an implementation that instantiates them, so the question of ABIs is +really a question of representation agreement between multiple ODP +implementations. If two or more ODP implementations agree on things like +typedefs, endianness, alignments, etc., then they are defining an ABI which +would permit ODP applications compiled to that common set of instantations +to interoperate at a binary as well as source level. + +==== Traditional ABI +ABIs can be defined at two levels. The simplest ABI is within a specific +Instruction Set Architecture (ISA). So, for example, an ABI might be defined +among ODP implementations for the AArch64 or x86 architectures. This +traditional approach is shown here: + +.Traditional ABI Structure +image::abi_traditional.svg[align="center"] + +In the traditional approach, multiple target platforms agree on a common set +of typedefs, etc. so that the resulting output from compilation is directly +executable on any platform that subscribes to that ABI. Adding a new platform +in this approach simply requires that platform to accept the existing ABI +specification. Note that since the output of compilation in a traditional ABI +is a ISA-specific binary that applications cannot offer binary compability +across platforms that use different ISAs. + +==== Bitcode based ABI +An ABI an also be defined at a higher level by moving to a more sophisticated +tool chain (such as is possible using LLVM) that implements a split +compilation model. In this model, the output from a compiler is not directly +executable. Rather it is a standardized intermediate representation called +_bitcode_ that must be further processed to result in an executable image as +shown here: + +.Bitcode ABI Structure +image::abi_llvm.svg[align="center"] + +The key to this model is that the platform linking and optimization that is +needed to create a platform executable is a system rather than a developer +responsibility. The developer's output is a universal bitcode binary. From +here, the library system creates a series of _managed binaries_ that result +from performing link-time optimization against a set of platform definitions. +When a universal application is to run on a specific target platform, the +library system selects the appropriate managed binary for that target platform +and loads and runs it. + +Adding a new platform in this approach involves adding the definition for that +platform to the libary system so that a managed binary for it can be created +and deployed as needed. This occurs without developer involvement since the +bitcode format that is input to this backend process is indepentent of the +specific target platform. Note also that since bitcode is not tied to any ISA, +applications using bitcode ABIs are binary portable between platforms that use +different ISAs. This occurs without loss of efficiency because the process of +creating a managed binary is itself a secondary compilation and optimization +step. The difference is that performing this step is a system rather than a +developer responsibility. + include::../glossary.adoc[]