]> git.proxmox.com Git - mirror_frr.git/blob - doc/developer/scripting.rst
pimd, doc: remove dead import check references
[mirror_frr.git] / doc / developer / scripting.rst
1 .. _scripting:
2
3 Scripting
4 =========
5
6 .. seealso:: User docs for scripting
7
8 Overview
9 --------
10
11 FRR has the ability to call Lua scripts to perform calculations, make
12 decisions, or otherwise extend builtin behavior with arbitrary user code. This
13 is implemented using the standard Lua C bindings. The supported version of Lua
14 is 5.3.
15
16 C objects may be passed into Lua and Lua objects may be retrieved by C code via
17 a encoding/decoding system. In this way, arbitrary data from FRR may be passed to
18 scripts.
19
20 The Lua environment is isolated from the C environment; user scripts cannot
21 access FRR's address space unless explicitly allowed by FRR.
22
23 For general information on how Lua is used to extend C, refer to Part IV of
24 "Programming in Lua".
25
26 https://www.lua.org/pil/contents.html#24
27
28
29 Design
30 ------
31
32 Why Lua
33 ^^^^^^^
34
35 Lua is designed to be embedded in C applications. It is very small; the
36 standard library is 220K. It is relatively fast. It has a simple, minimal
37 syntax that is relatively easy to learn and can be understood by someone with
38 little to no programming experience. Moreover it is widely used to add
39 scripting capabilities to applications. In short it is designed for this task.
40
41 Reasons against supporting multiple scripting languages:
42
43 - Each language would require different FFI methods, and specifically
44 different object encoders; a lot of code
45 - Languages have different capabilities that would have to be brought to
46 parity with each other; a lot of work
47 - Languages have vastly different performance characteristics; this would
48 create alot of basically unfixable issues, and result in a single de facto
49 standard scripting language (the fastest)
50 - Each language would need a dedicated maintainer for the above reasons;
51 this is pragmatically difficult
52 - Supporting multiple languages fractures the community and limits the audience
53 with which a given script can be shared
54
55 General
56 -------
57
58 FRR's scripting functionality is provided in the form of Lua functions in Lua
59 scripts (``.lua`` files). One Lua script may contain many Lua functions. These
60 are respectively encapsulated in the following structures:
61
62 .. code-block:: c
63
64 struct frrscript {
65 /* Lua file name */
66 char *name;
67
68 /* hash of lua_function_states */
69 struct hash *lua_function_hash;
70 };
71
72 struct lua_function_state {
73 /* Lua function name */
74 char *name;
75
76 lua_State *L;
77 };
78
79
80 `struct frrscript`: Since all Lua functions are contained within scripts, the
81 following APIs manipulates this structure. ``name`` contains the
82 Lua script name and a hash of Lua functions to their function names.
83
84 `struct lua_function_state` is an internal structure, but it essentially contains
85 the name of the Lua function and its state (a stack), which is run using Lua
86 library functions.
87
88 In general, to run a Lua function, these steps must take place:
89
90 - Initialization
91 - Load
92 - Call
93 - Delete
94
95 Initialization
96 ^^^^^^^^^^^^^^
97
98 The ``frrscript`` object encapsulates the Lua function state(s) from
99 one Lua script file. To create, use ``frrscript_new()`` which takes the
100 name of the Lua script.
101 The string ".lua" is appended to the script name, and the resultant filename
102 will be used to look for the script when we want to load a Lua function from it.
103
104 For example, to create ``frrscript`` for ``/etc/frr/scripts/bingus.lua``:
105
106 .. code-block:: c
107
108 struct frrscript *fs = frrscript_new("bingus");
109
110
111 The script is *not* read at this stage.
112 This function cannot be used to test for a script's presence.
113
114 Load
115 ^^^^
116
117 The function to be called must first be loaded. Use ``frrscript_load()``
118 which takes a ``frrscript`` object, the name of the Lua function
119 and a callback function.
120 The script file will be read to load and compile the function.
121
122 For example, to load the Lua function ``on_foo``
123 in ``/etc/frr/scripts/bingus.lua``:
124
125 .. code-block:: c
126
127 int ret = frrscript_load(fs, "on_foo", NULL);
128
129
130 This function returns 0 if and only if the Lua function was successfully loaded.
131 A non-zero return could indicate either a missing Lua script, a missing
132 Lua function, or an error when loading the function.
133
134 During loading the script is validated for syntax and its environment
135 is set up. By default this does not include the Lua standard library; there are
136 security issues to consider, though for practical purposes untrusted users
137 should not be able to write the scripts directory anyway.
138
139 Call
140 ^^^^
141
142 After loading, a Lua function can be called any number of times.
143
144 Input
145 """""
146
147 Inputs to the Lua script should be given by providing a list of parenthesized
148 pairs,
149 where the first and second field identify the name of the variable and the
150 value it is bound to, respectively.
151 The types of the values must have registered encoders (more below); the compiler
152 will warn you otherwise.
153
154 These variables are first encoded in-order, then provided as arguments
155 to the Lua function. In the example, note that ``c`` is passed in as a value
156 while ``a`` and ``b`` are passed in as pointers.
157
158 .. code-block:: c
159
160 int a = 100, b = 200, c = 300;
161 frrscript_call(fs, "on_foo", ("a", &a), ("b", &b), ("c", c));
162
163
164 .. code-block:: lua
165
166 function on_foo(a, b, c)
167 -- a is 100, b is 200, c is 300
168 ...
169
170
171 Output
172 """"""
173
174 .. code-block:: c
175
176 int a = 100, b = 200, c = 300;
177 frrscript_call(fs, "on_foo", ("a", &a), ("b", &b), ("c", c));
178 // a is 500, b is 200, c is 300
179
180 int* d = frrscript_get_result(fs, "on_foo", "d", lua_tointegerp);
181 // d is 800
182
183
184 .. code-block:: lua
185
186 function on_foo(a, b, c)
187 b = 600
188 return { ["a"] = 500, ["c"] = 700, ["d"] = 800 }
189 end
190
191
192 **Lua functions being called must return a single table of string names to
193 values.**
194 (Lua functions should return an empty table if there is no output.)
195 The keys of the table are mapped back to names of variables in C. Note that
196 the values in the table can also be tables. Since tables are Lua's primary
197 data structure, this design lets us return any Lua value.
198
199 After the Lua function returns, the names of variables to ``frrscript_call()``
200 are matched against keys of the returned table, and then decoded. The types
201 being decoded must have registered decoders (more below); the compiler will
202 warn you otherwise.
203
204 In the example, since ``a`` was in the returned table and ``b`` was not,
205 ``a`` was decoded and its value modified, while ``b`` was not decoded.
206 ``c`` was decoded as well, but its decoder is a noop.
207 What modifications happen given a variable depends whether its name was
208 in the returned table and the decoder's implementation.
209
210 .. warning::
211 Always keep in mind that non const-qualified pointers in
212 ``frrscript_call()`` may be modified - this may be a source of bugs.
213 On the other hand, const-qualified pointers and other values cannot
214 be modified.
215
216
217 .. tip::
218 You can make a copy of a data structure and pass that in instead,
219 so that modifications only happen to that copy.
220
221 ``frrscript_call()`` returns 0 if and only if the Lua function was successfully
222 called. A non-zero return could indicate either a missing Lua script, a missing
223 Lua function, or an error from the Lua interpreter.
224
225 In the above example, ``d`` was not an input to ``frrscript_call()``, so its
226 value must be explicitly retrieved with ``frrscript_get_result``.
227
228 ``frrscript_get_result()`` takes a
229 decoder and string name which is used as a key to search the returned table.
230 Returns the pointer to the decoded value, or NULL if it was not found.
231 In the example, ``d`` is a "new" value in C space,
232 so memory allocation might take place. Hence the caller is
233 responsible for memory deallocation.
234
235 ``frrscript_call()`` may be called multiple times without re-loading with
236 ``frrscript_load()``. Results are not preserved between consecutive calls.
237
238 .. code-block:: c
239
240 frrscript_load(fs, "on_foo");
241
242 frrscript_call(fs, "on_foo");
243 frrscript_get_result(fs, "on_foo", ...);
244 frrscript_call(fs, "on_foo");
245 frrscript_get_result(fs, "on_foo", ...);
246
247
248 Delete
249 ^^^^^^
250
251 To delete a script and the all Lua states associated with it:
252
253 .. code-block:: c
254
255 frrscript_delete(fs);
256
257
258 A complete example
259 """"""""""""""""""
260
261 So, a typical execution call, with error checking, looks something like this:
262
263 .. code-block:: c
264
265 struct frrscript *fs = frrscript_new("my_script"); // name *without* .lua
266
267 int ret = frrscript_load(fs, "on_foo", NULL);
268 if (ret != 0)
269 goto DONE; // Lua script or function might have not been found
270
271 int a = 100, b = 200, c = 300;
272 ret = frrscript_call(fs, "on_foo", ("a", &a), ("b", &b), ("c", c));
273 if (ret != 0)
274 goto DONE; // Lua function might have not successfully run
275
276 // a and b might be modified
277 assert(a == 500);
278 assert(b == 200);
279
280 // c could not have been modified
281 assert(c == 300);
282
283 // d is new
284 int* d = frrscript_get_result(fs, "on_foo", "d", lua_tointegerp);
285
286 if (!d)
287 goto DONE; // "d" might not have been in returned table
288
289 assert(*d == 800);
290 XFREE(MTYPE_SCRIPT_RES, d); // caller responsible for free
291
292 DONE:
293 frrscript_delete(fs);
294
295
296 .. code-block:: lua
297
298 function on_foo(a, b, c)
299 b = 600
300 return { a = 500, c = 700, d = 800 }
301 end
302
303
304 Note that ``{ a = ...`` is same as ``{ ["a"] = ...``; it is Lua shorthand to
305 use the variable name as the key in a table.
306
307 Encoding and Decoding
308 ^^^^^^^^^^^^^^^^^^^^^
309
310 Earlier sections glossed over the types of values that can be passed into
311 ``frrscript_call()`` and how data is passed between C and Lua. Lua, as a
312 dynamically typed, garbage collected language, cannot directly use C values
313 without some kind of encoding / decoding system to
314 translate types between the two runtimes.
315
316 Lua communicates with C code using a stack. C code wishing to provide data to
317 Lua scripts must provide a function that encodes the C data into a Lua
318 representation and pushes it on the stack. C code wishing to retrieve data from
319 Lua must provide a corresponding decoder function that retrieves a Lua
320 value from the stack and converts it to the corresponding C type.
321
322 Encoders and decoders are provided for common data types.
323 Developers wishing to pass their own data structures between C and Lua need to
324 create encoders and decoders for that data type.
325
326 We try to keep them named consistently.
327 There are three kinds of encoders and decoders:
328
329 1. lua_push*: encodes a value onto the Lua stack.
330 Required for ``frrscript_call``.
331
332 2. lua_decode*: decodes a value from the Lua stack.
333 Required for ``frrscript_call``.
334 Only non const-qualified pointers may be actually decoded (more below).
335
336 3. lua_to*: allocates memory and decodes a value from the Lua stack.
337 Required for ``frrscript_get_result``.
338
339 This design allows us to combine typesafe *modification* of C values as well as
340 *allocation* of new C values.
341
342 In the following sections, we will use the encoders/decoders for ``struct prefix`` as an example.
343
344 Encoding
345 """"""""
346
347 An encoder function takes a ``lua_State *``, a C type and pushes that value onto
348 the Lua state (a stack).
349 For C structs, the usual case,
350 this will typically be encoded to a Lua table, then pushed onto the Lua stack.
351
352 Here is the encoder function for ``struct prefix``:
353
354 .. code-block:: c
355
356 void lua_pushprefix(lua_State *L, struct prefix *prefix)
357 {
358 char buffer[PREFIX_STRLEN];
359
360 lua_newtable(L);
361 lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
362 lua_setfield(L, -2, "network");
363 lua_pushinteger(L, prefix->prefixlen);
364 lua_setfield(L, -2, "length");
365 lua_pushinteger(L, prefix->family);
366 lua_setfield(L, -2, "family");
367 }
368
369 This function pushes a single value, a table, onto the Lua stack, whose
370 equivalent in Lua is:
371
372 .. code-block:: c
373
374 { ["network"] = "1.2.3.4/24", ["prefixlen"] = 24, ["family"] = 2 }
375
376
377 Decoding
378 """"""""
379
380 Decoders are a bit more involved. They do the reverse; a decoder function takes
381 a ``lua_State *``, pops a value off the Lua stack and converts it back into its
382 C type.
383
384 There are two: ``lua_decode*`` and ``lua_to*``. The former does no mememory
385 allocation and is needed for ``frrscript_call``.
386 The latter performs allocation and is optional.
387
388 A ``lua_decode_*`` function takes a ``lua_State*``, an index, and a pointer
389 to a C data structure, and directly modifies the structure with values from the
390 Lua stack. Note that only non const-qualified pointers may be modified;
391 ``lua_decode_*`` for other types will be noops.
392
393 Again, for ``struct prefix *``:
394
395 .. code-block:: c
396
397 void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
398 {
399 lua_getfield(L, idx, "network");
400 (void)str2prefix(lua_tostring(L, -1), prefix);
401 /* pop the network string */
402 lua_pop(L, 1);
403 /* pop the prefix table */
404 lua_pop(L, 1);
405 }
406
407
408 Note:
409 - Before ``lua_decode*`` is run, the "prefix" table is already on the top of
410 the stack. ``frrscript_call`` does this for us.
411 - However, at the end of ``lua_decode*``, the "prefix" table should be popped.
412 - The other two fields in the "network" table are disregarded, meaning that any
413 modification to them is discarded in C space. In this case, this is desired
414 behavior.
415
416 .. warning::
417
418 ``lua_decode*`` functions should pop all values that ``lua_to*`` pushed onto
419 the Lua stack.
420 For encoders that pushed a table, its decoder should pop the table at the end.
421 The above is an example.
422
423
424
425 ``int`` is not a non const-qualified pointer, so for ``int``:
426
427 .. code-block:: c
428
429 void lua_decode_int_noop(lua_State *L, int idx, int i)
430 { //noop
431 }
432
433
434 A ``lua_to*`` function provides identical functionality except that it first
435 allocates memory for the new C type before decoding the value from the Lua stack,
436 then returns a pointer to the newly allocated C type. You only need to implement
437 this function to use with ``frrscript_get_result`` to retrieve a result of
438 this type.
439
440 This function can and should be implemented using ``lua_decode_*``:
441
442 .. code-block:: c
443
444 void *lua_toprefix(lua_State *L, int idx)
445 {
446 struct prefix *p = XCALLOC(MTYPE_SCRIPT_RES, sizeof(struct prefix));
447
448 lua_decode_prefix(L, idx, p);
449 return p;
450 }
451
452
453 The returned data must always be copied off the stack and the copy must be
454 allocated with ``MTYPE_SCRIPT_RES``. This way it is possible to unload the script
455 (destroy the state) without invalidating any references to values stored in it.
456 Note that it is the caller's responsibility to free the data.
457
458
459 Registering encoders and decoders for frrscript_call
460 """"""""""""""""""""""""""""""""""""""""""""""""""""
461
462 To register a new type with its ``lua_push*`` and ``lua_decode*`` functions,
463 add the mapping in the following macros in ``frrscript.h``:
464
465 .. code-block:: diff
466
467 #define ENCODE_ARGS_WITH_STATE(L, value) \
468 _Generic((value), \
469 ...
470 - struct peer * : lua_pushpeer \
471 + struct peer * : lua_pushpeer, \
472 + struct prefix * : lua_pushprefix \
473 )((L), (value))
474
475 #define DECODE_ARGS_WITH_STATE(L, value) \
476 _Generic((value), \
477 ...
478 - struct peer * : lua_decode_peer \
479 + struct peer * : lua_decode_peer, \
480 + struct prefix * : lua_decode_prefix \
481 )((L), -1, (value))
482
483
484 At compile time, the compiler will search for encoders/decoders for the type of
485 each value passed in via ``frrscript_call``. If a encoder/decoder cannot be
486 found, it will appear as a compile warning. Note that the types must
487 match *exactly*.
488 In the above example, we defined encoders/decoders for a value of
489 ``struct prefix *``, but not ``struct prefix`` or ``const struct prefix *``.
490
491 ``const`` values are a special case. We want to use them in our Lua scripts
492 but not modify them, so creating a decoder for them would be meaningless.
493 But we still need a decoder for the type of value so that the compiler will be
494 satisfied.
495 For that, use ``lua_decode_noop``:
496
497 .. code-block:: diff
498
499 #define DECODE_ARGS_WITH_STATE(L, value) \
500 _Generic((value), \
501 ...
502 + const struct prefix * : lua_decode_noop \
503 )(L, -1, value)
504
505
506 .. note::
507
508 Encodable/decodable types are not restricted to simple values like integers,
509 strings and tables.
510 It is possible to encode a type such that the resultant object in Lua
511 is an actual object-oriented object, complete with methods that call
512 back into defined C functions. See the Lua manual for how to do this;
513 for a code example, look at how zlog is exported into the script environment.
514
515
516 Script Environment
517 ------------------
518
519 Logging
520 ^^^^^^^
521
522 For convenience, script environments are populated by default with a ``log``
523 object which contains methods corresponding to each of the ``zlog`` levels:
524
525 .. code-block:: lua
526
527 log.info("info")
528 log.warn("warn")
529 log.error("error")
530 log.notice("notice")
531 log.debug("debug")
532
533 The log messages will show up in the daemon's log output.
534
535
536 Examples
537 --------
538
539 For a complete code example involving passing custom types, retrieving results,
540 and doing complex calculations in Lua, look at the implementation of the
541 ``match script SCRIPT`` command for BGP routemaps. This example calls into a
542 script with a function named ``route_match``,
543 provides route prefix and attributes received from a peer and expects the
544 function to return a match / no match / match and update result.
545
546 An example script to use with this follows. This function matches, does not match
547 or updates a route depending on how many BGP UPDATE messages the peer has
548 received when the script is called, simply as a demonstration of what can be
549 accomplished with scripting.
550
551 .. code-block:: lua
552
553
554 -- Example route map matching
555 -- author: qlyoung
556 --
557 -- The following variables are available in the global environment:
558 -- log
559 -- logging library, with the usual functions
560 --
561 -- route_match arguments:
562 -- table prefix
563 -- the route under consideration
564 -- table attributes
565 -- the route's attributes
566 -- table peer
567 -- the peer which received this route
568 -- integer RM_FAILURE
569 -- status code in case of failure
570 -- integer RM_NOMATCH
571 -- status code for no match
572 -- integer RM_MATCH
573 -- status code for match
574 -- integer RM_MATCH_AND_CHANGE
575 -- status code for match-and-set
576 --
577 -- route_match returns table with following keys:
578 -- integer action, required
579 -- resultant status code. Should be one of RM_*
580 -- table attributes, optional
581 -- updated route attributes
582 --
583
584 function route_match(prefix, attributes, peer,
585 RM_FAILURE, RM_NOMATCH, RM_MATCH, RM_MATCH_AND_CHANGE)
586
587 log.info("Evaluating route " .. prefix.network .. " from peer " .. peer.remote_id.string)
588
589 function on_match (prefix, attributes)
590 log.info("Match")
591 return {
592 attributes = RM_MATCH
593 }
594 end
595
596 function on_nomatch (prefix, attributes)
597 log.info("No match")
598 return {
599 action = RM_NOMATCH
600 }
601 end
602
603 function on_match_and_change (prefix, attributes)
604 log.info("Match and change")
605 attributes["metric"] = attributes["metric"] + 7
606 return {
607 action = RM_MATCH_AND_CHANGE,
608 attributes = attributes
609 }
610 end
611
612 special_routes = {
613 ["172.16.10.4/24"] = on_match,
614 ["172.16.13.1/8"] = on_nomatch,
615 ["192.168.0.24/8"] = on_match_and_change,
616 }
617
618
619 if special_routes[prefix.network] then
620 return special_routes[prefix.network](prefix, attributes)
621 elseif peer.stats.update_in % 3 == 0 then
622 return on_match(prefix, attributes)
623 elseif peer.stats.update_in % 2 == 0 then
624 return on_nomatch(prefix, attributes)
625 else
626 return on_match_and_change(prefix, attributes)
627 end
628 end