summaryrefslogtreecommitdiffstats
path: root/docs/gettingstarted/developers/add_plugin.rst
diff options
context:
space:
mode:
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>2020-09-04 18:31:23 +0200
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-09-09 20:44:08 +0000
commitc4781a32df89c6c29b5f4bbea5440cddbede19a0 (patch)
tree64c9ce6450b7754056cfe507a87595c77c00f5e4 /docs/gettingstarted/developers/add_plugin.rst
parentf681e9f736d34a6fdb7e596f63dfa1f51025a98c (diff)
docs: Improve new plugin doc & add govpp API doc
Type: docs Change-Id: I5f20ac0232c5cdc3cf64015185b0d0fc5c4a3100 Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
Diffstat (limited to 'docs/gettingstarted/developers/add_plugin.rst')
-rw-r--r--docs/gettingstarted/developers/add_plugin.rst84
1 files changed, 56 insertions, 28 deletions
diff --git a/docs/gettingstarted/developers/add_plugin.rst b/docs/gettingstarted/developers/add_plugin.rst
index 16952e8f036..19b935b746a 100644
--- a/docs/gettingstarted/developers/add_plugin.rst
+++ b/docs/gettingstarted/developers/add_plugin.rst
@@ -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");