diff options
Diffstat (limited to 'docs/gettingstarted/developers/add_plugin.rst')
-rw-r--r-- | docs/gettingstarted/developers/add_plugin.rst | 84 |
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"); |