docs: convert plugins doc md->rst
[vpp.git] / docs / gettingstarted / developers / add_plugin.rst
1 .. _add_plugin:
2
3 Adding a plugin
4 ===============
5
6 .. toctree::
7
8 Strategic Choices
9 _________________
10
11 Plugins may implement lightly-used, experimental, or test
12 functionality. In such cases, please disable the plugin by default:
13
14 .. code-block:: console
15
16     /* *INDENT-OFF* */
17     VLIB_PLUGIN_REGISTER () =
18     {
19       .version = VPP_BUILD_VER,
20       .description = "Plugin Disabled by Default...",
21       .default_disabled = 1,
22     };
23     /* *INDENT-ON* */
24
25 Please do not create processes, or other dynamic data structures
26 unless the plugin is configured by API or debug CLI.
27
28 Specifically, please don't initialize bihash tables from
29 VLIB_INIT_FUNCTIONS, *especially* if the bihash template involved
30 doesn't #define BIHASH_LAZY_INSTANTIATE 1.
31
32 .. code-block:: console
33
34     static clib_error_t * sample_init (vlib_main_t * vm)
35     {
36       <snip>
37       /* DONT DO THIS! */
38       BV(clib_bihash_init (h, ...))
39       <snip>
40     }
41     VLIB_INIT_FUNCTION (sample_init);
42
43 Instead, please add a feature_init function:
44
45 .. code-block:: console
46
47     static void
48     feature_init (my_main_t * mm)
49     {
50       if (mm->feature_initialized == 0)
51         {
52           BV(clib_bihash_init)(mm->hash_table, ...)
53           /* Create Other Things, e.g a periodic process */
54           mm->feature_initialized = 1;
55         }
56     }
57
58 And call it from debug CLI and API message handlers any time the feature
59 is enabled.
60
61 How to create a new plugin
62 __________________________
63
64 This section shows how a VPP developer can create a new plugin, and
65 add it to VPP. We assume that we are starting from the VPP <top-of-workspace>.
66
67 As an example, we will use the **make-plugin.sh** tool found in
68 **./extras/emacs**. make-plugin.sh is a simple wrapper for a comprehensive
69 plugin generator constructed from a set of emacs-lisp skeletons.
70
71 Change directory to **./src/plugins**, and run the plugin generator:
72
73 .. code-block:: console
74
75     $ cd ./src/plugins
76     $ ../../extras/emacs/make-plugin.sh
77     <snip>
78     Loading /scratch/vpp-docs/extras/emacs/tunnel-c-skel.el (source)...
79     Loading /scratch/vpp-docs/extras/emacs/tunnel-decap-skel.el (source)...
80     Loading /scratch/vpp-docs/extras/emacs/tunnel-encap-skel.el (source)...
81     Loading /scratch/vpp-docs/extras/emacs/tunnel-h-skel.el (source)...
82     Loading /scratch/vpp-docs/extras/emacs/elog-4-int-skel.el (source)...
83     Loading /scratch/vpp-docs/extras/emacs/elog-4-int-track-skel.el (source)...
84     Loading /scratch/vpp-docs/extras/emacs/elog-enum-skel.el (source)...
85     Loading /scratch/vpp-docs/extras/emacs/elog-one-datum-skel.el (source)...
86     Plugin name: myplugin
87     Dispatch type [dual or qs]: dual
88     (Shell command succeeded with no output)
89
90     OK...
91
92 The plugin generator script asks two questions: the name of the
93 plugin, and which of two dispatch types to use. Since the plugin name
94 finds its way into quite a number of places - filenames, typedef
95 names, graph arc names - it pays to think for a moment.
96
97 The dispatch type refers to the coding pattern used to construct
98 **node.c**, the *pro forma* data-plane node. The **dual** option
99 constructs a dual-single loop pair with speculative enqueueing. This
100 is the traditional coding pattern for load-store intensive graph
101 nodes.
102
103 The **qs** option generates a quad-single loop pair which uses
104 vlib_get_buffers(...) and vlib_buffer_enqueue_to_next(...). These
105 operators make excellent use of available SIMD vector unit
106 operations. It's very simple to change a quad-single loop-pair to a
107 dual-single loop pair if you decide to do so later.
108
109 Generated Files
110 ---------------
111
112 Here are the generated files. We'll go through them in a moment.
113
114 .. code-block:: console
115
116     $ cd ./myplugin
117     $ ls
118     CMakeLists.txt  myplugin.api  myplugin.c  myplugin.h
119     myplugin_periodic.c  myplugin_test.c  node.c  setup.pg
120
121 Due to recent build system improvements, you **don't** need to touch
122 any other files to integrate your new plugin into the vpp build. Simply
123 rebuild your workspace from scratch, and the new plugin will appear.
124
125 Rebuild your workspace
126 ----------------------
127
128 This is the straightforward way to reconfigure and rebuild your workspace:
129
130 .. code-block:: console
131
132     $ cd <top-of-workspace>
133     $ make rebuild [or rebuild-release]
134
135 Thanks to ccache, this operation doesn't take an annoying amount of time.
136
137 Sanity check: run vpp
138 ---------------------
139
140 As a quick sanity check, run vpp and make sure that
141 "myplugin_plugin.so" and "myplugin_test_plugin.so" are loaded:
142
143 .. code-block:: console
144
145     $ cd <top-of-workspace>
146     $ make run
147     <snip>
148     load_one_plugin:189: Loaded plugin: myplugin_plugin.so (myplugin description goes here)
149     <snip>
150     load_one_vat_plugin:67: Loaded plugin: myplugin_test_plugin.so
151     <snip>
152     DBGvpp#
153
154 If this simple test fails, please seek assistance.
155
156 Generated Files in Detail
157 _________________________
158
159 This section discusses the generated files in some detail. It's fine to
160 skim this section, and return later for more detail.
161
162 CMakeLists.txt
163 --------------
164
165 This is the build system recipe for building your plugin. Please fix
166 the copyright notice:
167
168 .. code-block:: console
169
170     # Copyright (c) <current-year> <your-organization>
171
172 The rest of the build recipe is pretty simple:
173
174 .. code-block:: CMake
175
176     add_vpp_plugin (myplugin
177     SOURCES
178     myplugin.c
179     node.c
180     myplugin_periodic.c
181     myplugin.h
182
183     MULTIARCH_SOURCES
184     node.c
185
186     API_FILES
187     myplugin.api
188
189     API_TEST_SOURCES
190     myplugin_test.c
191     )
192
193 As you can see, the build recipe consists of several lists of
194 files. **SOURCES** is a list of C source files. **API_FILES** is a
195 list of the plugin's binary API definition files [one such file is
196 usually plenty], and so forth.
197
198 **MULTIARCH_SOURCES** lists data plane graph node dispatch function
199 source files considered to be performance-critical. Specific functions
200 in these files are compiled multiple times, so that they can leverage
201 CPU-specific features. More on this in a moment.
202
203 If you add source files, simply add them to the indicated list(s).
204
205 myplugin.h
206 ----------
207
208 This is the primary #include file for the new plugin. Among other
209 things, it defines the plugin's *main_t* data structure. This is the
210 right place to add problem-specific data structures. Please **resist
211 the temptation** to create a set of static or [worse yet] global
212 variables in your plugin. Refereeing name-collisions between plugins
213 is not anyone's idea of a good time.
214
215 myplugin.c
216 ----------
217
218 For want of a better way to describe it, myplugin.c is the vpp plugin
219 equivalent of "main.c". Its job is to hook the plugin into the vpp
220 binary API message dispatcher, and to add its messages to vpp's global
221 "message-name_crc" hash table. See "myplugin_init (...")"
222
223 Vpp itself uses dlsym(...) to track down the vlib_plugin_registration_t
224 generated by the VLIB_PLUGIN_REGISTER macro:
225
226 .. code-block:: C
227
228     VLIB_PLUGIN_REGISTER () =
229       {
230         .version = VPP_BUILD_VER,
231         .description = "myplugin plugin description goes here",
232       };
233
234 Vpp only loads .so files from the plugin directory which contain an
235 instance of this data structure.
236
237 You can enable or disable specific vpp plugins from the command
238 line. By default, plugins are loaded. To change that behavior, set
239 default_disabled in the macro VLIB_PLUGIN_REGISTER:
240
241 .. code-block:: C
242
243     VLIB_PLUGIN_REGISTER () =
244       {
245         .version = VPP_BUILD_VER,
246         .default_disabled = 1
247         .description = "myplugin plugin description goes here",
248       };
249
250 The boilerplate generator places the graph node dispatch function
251 onto the "device-input" feature arc. This may or may not be useful.
252
253 .. code-block:: C
254
255     VNET_FEATURE_INIT (myplugin, static) =
256     {
257       .arc_name = "device-input",
258       .node_name = "myplugin",
259       .runs_before = VNET_FEATURES ("ethernet-input"),
260     };
261
262 As given by the plugin generator, myplugin.c contains the binary API
263 message handler for a generic "please enable my feature on such and
264 such an interface" binary API message. As you'll see, setting up the
265 vpp message API tables is simple. Big fat warning: the scheme is
266 intolerant of minor mistakes. Example: forgetting to add
267 mainp->msg_id_base can lead to very confusing failures.
268
269 If you stick to modifying the generated boilerplate with care -
270 instead of trying to build code from first principles - you'll save
271 yourself a bunch of time and aggravation
272
273 myplugin_test.c
274 ---------------
275
276 This file contains binary API message **generation** code, which is
277 compiled into a separate .so file. The "vpp_api_test" program loads
278 these plugins, yielding immediate access to your plugin APIs for
279 external client binary API testing.
280
281 vpp itself loads test plugins, and makes the code available via the
282 "binary-api" debug CLI. This is a favorite way to unit-test binary
283 APIs prior to integration testing.
284
285 node.c
286 ------
287
288 This is the generated graph node dispatch function. You'll need to
289 rewrite it to solve the problem at hand. It will save considerable
290 time and aggravation to retain the **structure** of the node dispatch
291 function.
292
293 Even for an expert, it's a waste of time to reinvent the *loop
294 structure*, enqueue patterns, and so forth. Simply tear out and
295 replace the specimen 1x, 2x, 4x packet processing code with code
296 relevant to the problem you're trying to solve.
297
298 myplugin.api
299 ------------
300
301 This contains the API message definition. Here we only have defined
302 a single one named ``myplugin_enable_disable`` and an implicit
303 ``myplugin_enable_disable_reply`` containing only a return value due
304 to the ``autoreply`` keyword.
305
306 The syntax reference for ``.api`` files can be found at VPP API Language
307
308 Addressing the binary API with this message will run the handler defined
309 in ``myplugin.c`` as ``vl_api_myplugin_enable_disable_t_handler``.
310 It will receive a message pointer ``*mp`` which is the struct defined
311 in ``myplugin.api`` and should return another message pointer ``*rmp``,
312 of the reply type. That's what ``REPLY_MACRO`` does.
313
314 To be noted, all API messages are in net-endian and vpp is host-endian,
315 so you will need to use :
316
317 * ``u32 value = ntohl(mp->value);``
318 * ``rmp->value = htonl(value);``
319
320 You can now use this API with :ref:`GoLang bindings <add_plugin_goapi>`
321
322 myplugin_periodic.c
323 -------------------
324
325 This defines a VPP process, a routine that will run indefinitely and
326 be woken up intermittently, here to process plugin events.
327
328 To be noted, vlib_processes aren't thread-safe, and data structures
329 should be locked when shared between workers.
330
331 Plugin "Friends with Benefits"
332 ------------------------------
333
334 In vpp VLIB_INIT_FUNCTION functions, It's reasonably common to see a
335 specific init function invoke other init functions:
336
337 .. code-block:: C
338
339     if ((error = vlib_call_init_function (vm, some_other_init_function))
340        return error;
341
342 In the case where one plugin needs to call a init function in another
343 plugin, use the vlib_call_plugin_init_function macro:
344
345 .. code-block:: C
346
347     if ((error = vlib_call_plugin_init_function (vm, "otherpluginname", some_init_function))
348        return error;
349
350 This allows sequencing between plugin init functions.
351
352 If you wish to obtain a pointer to a symbol in another plugin, use the
353 vlib_plugin_get_symbol(...) API:
354
355 .. code-block:: C
356
357     void *p = vlib_get_plugin_symbol ("plugin_name", "symbol");
358
359 More Examples
360 -------------
361
362 For more information you can read many example plugins in the directory "./src/plugins".