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