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