docs: Improve new plugin doc & add govpp API doc 88/28688/4
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Fri, 4 Sep 2020 16:31:23 +0000 (18:31 +0200)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Wed, 9 Sep 2020 20:44:08 +0000 (20:44 +0000)
Type: docs

Change-Id: I5f20ac0232c5cdc3cf64015185b0d0fc5c4a3100
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
docs/gettingstarted/developers/VPPAPI.md [new symlink]
docs/gettingstarted/developers/add_plugin.rst
docs/gettingstarted/developers/add_plugin_goapi.rst [new file with mode: 0644]
docs/gettingstarted/developers/index.rst

diff --git a/docs/gettingstarted/developers/VPPAPI.md b/docs/gettingstarted/developers/VPPAPI.md
new file mode 120000 (symlink)
index 0000000..a5404c1
--- /dev/null
@@ -0,0 +1 @@
+../../../src/tools/vppapigen/VPPAPI.md
\ No newline at end of file
index 16952e8..19b935b 100644 (file)
@@ -7,7 +7,7 @@ Adding a plugin
 
 Overview
 ________
+
 This section shows how a VPP developer can create a new plugin, and
 add it to VPP. We assume that we are starting from the VPP <top-of-workspace>.
 
@@ -21,7 +21,7 @@ Create your new plugin
 Change directory to **./src/plugins**, and run the plugin generator:
 
 .. code-block:: console
-    
+
     $ cd ./src/plugins
     $ ../../extras/emacs/make-plugin.sh
     <snip>
@@ -36,7 +36,7 @@ Change directory to **./src/plugins**, and run the plugin generator:
     Plugin name: myplugin
     Dispatch type [dual or qs]: dual
     (Shell command succeeded with no output)
-    
+
     OK...
 
 The plugin generator script asks two questions: the name of the
@@ -65,9 +65,8 @@ Here are the generated files. We'll go through them in a moment.
 
     $ cd ./myplugin
     $ ls
-    CMakeLists.txt        myplugin.c           myplugin_periodic.c  setup.pg
-    myplugin_all_api_h.h  myplugin.h           myplugin_test.c
-    myplugin.api          myplugin_msg_enum.h  node.c
+    CMakeLists.txt  myplugin.api  myplugin.c  myplugin.h
+    myplugin_periodic.c  myplugin_test.c  node.c  setup.pg
 
 Due to recent build system improvements, you **don't** need to touch
 any other files to integrate your new plugin into the vpp build. Simply
@@ -92,7 +91,7 @@ As a quick sanity check, run vpp and make sure that
 "myplugin_plugin.so" and "myplugin_test_plugin.so" are loaded:
 
 .. code-block:: console
-    
+
     $ cd <top-of-workspace>
     $ make run
     <snip>
@@ -122,25 +121,21 @@ the copyright notice:
 
 The rest of the build recipe is pretty simple:
 
-.. code-block:: console
+.. code-block:: CMake
 
     add_vpp_plugin (myplugin
     SOURCES
-    myplugin.c 
-    node.c 
+    myplugin.c
+    node.c
     myplugin_periodic.c
     myplugin.h
-    
+
     MULTIARCH_SOURCES
-    node.c 
-    
+    node.c
+
     API_FILES
     myplugin.api
-    
-    INSTALL_HEADERS
-    myplugin_all_api_h.h
-    myplugin_msg_enum.h
-    
+
     API_TEST_SOURCES
     myplugin_test.c
     )
@@ -178,13 +173,13 @@ binary API message dispatcher, and to add its messages to vpp's global
 Vpp itself uses dlsym(...) to track down the vlib_plugin_registration_t
 generated by the VLIB_PLUGIN_REGISTER macro:
 
-.. code-block:: console
+.. code-block:: C
 
-    VLIB_PLUGIN_REGISTER () = 
+    VLIB_PLUGIN_REGISTER () =
       {
         .version = VPP_BUILD_VER,
         .description = "myplugin plugin description goes here",
-      };  
+      };
 
 Vpp only loads .so files from the plugin directory which contain an
 instance of this data structure.
@@ -193,7 +188,7 @@ You can enable or disable specific vpp plugins from the command
 line. By default, plugins are loaded. To change that behavior, set
 default_disabled in the macro VLIB_PLUGIN_REGISTER:
 
-.. code-block:: console
+.. code-block:: C
 
     VLIB_PLUGIN_REGISTER () =
       {
@@ -205,14 +200,14 @@ default_disabled in the macro VLIB_PLUGIN_REGISTER:
 The boilerplate generator places the graph node dispatch function
 onto the "device-input" feature arc. This may or may not be useful.
 
-.. code-block:: console
+.. code-block:: C
 
     VNET_FEATURE_INIT (myplugin, static) =
     {
       .arc_name = "device-input",
       .node_name = "myplugin",
       .runs_before = VNET_FEATURES ("ethernet-input"),
-    };  
+    };
 
 As given by the plugin generator, myplugin.c contains the binary API
 message handler for a generic "please enable my feature on such and
@@ -243,20 +238,53 @@ node.c
 This is the generated graph node dispatch function. You'll need to
 rewrite it to solve the problem at hand. It will save considerable
 time and aggravation to retain the **structure** of the node dispatch
-function. 
+function.
 
 Even for an expert, it's a waste of time to reinvent the *loop
 structure*, enqueue patterns, and so forth. Simply tear out and
 replace the specimen 1x, 2x, 4x packet processing code with code
 relevant to the problem you're trying to solve.
 
+myplugin.api
+------------
+
+This contains the API message definition. Here we only have defined
+a single one named ``myplugin_enable_disable`` and an implicit
+``myplugin_enable_disable_reply`` containing only a return value due
+to the ``autoreply`` keyword.
+
+The syntax reference for ``.api`` files can be found at VPP API Language
+
+Addressing the binary API with this message will run the handler defined
+in ``myplugin.c`` as ``vl_api_myplugin_enable_disable_t_handler``.
+It will receive a message pointer ``*mp`` which is the struct defined
+in ``myplugin.api`` and should return another message pointer ``*rmp``,
+of the reply type. That's what ``REPLY_MACRO`` does.
+
+To be noted, all API messages are in net-endian and vpp is host-endian,
+so you will need to use :
+
+* ``u32 value = ntohl(mp->value);``
+* ``rmp->value = htonl(value);``
+
+You can now use this API with :ref:`GoLang bindings <add_plugin_goapi>`
+
+myplugin_periodic.c
+-------------------
+
+This defines a VPP process, a routine that will run indefinitely and
+be woken up intermittently, here to process plugin events.
+
+To be noted, vlib_processes aren't thread-safe, and data structures
+should be locked when shared between workers.
+
 Plugin "Friends with Benefits"
 ------------------------------
 
 In vpp VLIB_INIT_FUNCTION functions, It's reasonably common to see a
 specific init function invoke other init functions:
 
-.. code-block:: console
+.. code-block:: C
 
     if ((error = vlib_call_init_function (vm, some_other_init_function))
        return error;
@@ -264,7 +292,7 @@ specific init function invoke other init functions:
 In the case where one plugin needs to call a init function in another
 plugin, use the vlib_call_plugin_init_function macro:
 
-.. code-block:: console
+.. code-block:: C
 
     if ((error = vlib_call_plugin_init_function (vm, "otherpluginname", some_init_function))
        return error;
@@ -274,7 +302,7 @@ This allows sequencing between plugin init functions.
 If you wish to obtain a pointer to a symbol in another plugin, use the
 vlib_plugin_get_symbol(...) API:
 
-.. code-block:: console
+.. code-block:: C
 
     void *p = vlib_get_plugin_symbol ("plugin_name", "symbol");
 
diff --git a/docs/gettingstarted/developers/add_plugin_goapi.rst b/docs/gettingstarted/developers/add_plugin_goapi.rst
new file mode 100644 (file)
index 0000000..dce35b8
--- /dev/null
@@ -0,0 +1,83 @@
+.. _add_plugin_goapi:
+
+Add a plugin's GO API
+=====================
+
+In order to use your plugin's API with GO, you will need to use
+a GO client and GO definitions of the API messages that you defined
+in ``myplugin.api`` (go bindings).
+
+These two things can be found in `govpp <https://github.com/FDio/govpp>`_
+
+* The API client lives in `./core`
+* The api-generator lives in `./binapigen`
+* A sample of its output (the go bindings) for VPP's latest version lives in `./binapi`
+
+To generate the go bindings for your plugin. Assuming :
+* ``/home/vpp`` is a VPP clone with your plugin in it.
+* ``/home/controlplane`` is a go controlplane repo
+
+.. code-block:: console
+
+    $ mkdir /home/controlplane/vpp-go-bindings
+    $ git clone https://github.com/FDio/govpp>
+    $ cd govpp
+    $ BINAPI_DIR=/home/controlplane/vpp-go-bindings VPP_DIR=/home/vpp make gen-binapi-from-code
+
+This will generate the go-bindings in ``/home/controlplane/vpp-go-bindings``
+For example ``vpp-go-bindings/myplugin/myplugin.ba.go`` will contain :
+
+.. code-block:: go
+
+    // MypluginEnableDisable defines message 'myplugin_enable_disable'.
+    type MypluginEnableDisable struct {
+           EnableDisable bool                           `binapi:"bool,name=enable_disable" json:"enable_disable,omitempty"`
+           SwIfIndex     interface_types.InterfaceIndex `binapi:"interface_index,name=sw_if_index" json:"sw_if_index,omitempty"`
+    }
+
+
+You can then use the generated go bindings in your go code like this :
+
+.. code-block:: go
+
+    package main
+
+    import (
+           "fmt"
+           "git.fd.io/govpp.git"
+           "git.fd.io/govpp.git/binapi/interfaces"
+           "git.fd.io/govpp.git/binapi/vpe"
+
+           "myplugin.io/controlplane/vpp-go-bindings/myplugin/myplugin"
+    )
+
+    func main() {
+           // Connect to VPP
+           conn, _ := govpp.Connect("/run/vpp/api.sock")
+           defer conn.Disconnect()
+
+           // Open channel
+           ch, _ := conn.NewAPIChannel()
+           defer ch.Close()
+
+           request := &vpe.MypluginEnableDisable{
+               EnableDisable: true,
+           }
+           reply := &vpe.MypluginEnableDisableReply{}
+
+           err := ch.SendRequest(request).ReceiveReply(reply)
+           if err != nil {
+                   fmt.Errorf("SendRequest: %w\n", err)
+           }
+    }
+
+As you will need to import (or ``go get "git.fd.io/govpp.git"``) to leverage the API
+client in your code, you might want to use the api-generator directly from the
+clone ``go build`` fetches for you. You can do this with :
+
+.. code-block:: console
+
+  $ export GOVPP_DIR=$(go list -f '{{.Dir}}' -m git.fd.io/govpp.git)
+  $ cd $GOVPP_DIR && go build -o /some/bin/dir ./cmd/binapi-generator
+  $ # instead of make gen-binapi-from-code you can rewrite the code to target
+  $ # your version ./binapi-generator
index 378b9fb..04d7043 100644 (file)
@@ -22,6 +22,7 @@ The Developers section covers the following areas:
    running_vpp
    gdb_examples
    add_plugin
+   add_plugin_goapi
    gitreview
    softwarearchitecture
    infrastructure
@@ -42,3 +43,4 @@ The Developers section covers the following areas:
    quic_plugin
    cross_compile_macos.rst
    cnat
+   VPPAPI.md