mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 12:44:55 +00:00
doc: add scripting docs
Signed-off-by: Quentin Young <qlyoung@nvidia.com>
This commit is contained in:
parent
b068d61304
commit
0833300a7a
@ -15,6 +15,6 @@ Library Facilities (libfrr)
|
|||||||
hooks
|
hooks
|
||||||
cli
|
cli
|
||||||
modules
|
modules
|
||||||
lua
|
scripting
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
.. _lua:
|
|
||||||
|
|
||||||
Lua
|
|
||||||
===
|
|
||||||
|
|
||||||
Lua is currently experimental within FRR and has very limited
|
|
||||||
support. If you would like to compile FRR with Lua you must
|
|
||||||
follow these steps:
|
|
||||||
|
|
||||||
1. Installation of Relevant Libraries
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
apt-get install lua5.3 liblua5-3 liblua5.3-dev
|
|
||||||
|
|
||||||
These are the Debian libraries that are needed. There should
|
|
||||||
be equivalent RPM's that can be found
|
|
||||||
|
|
||||||
2. Compilation
|
|
||||||
|
|
||||||
Configure needs these options
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
./configure --enable-dev-build --enable-lua <all other interesting options>
|
|
||||||
|
|
||||||
Typically you just include the two new enable lines to build with it.
|
|
||||||
|
|
||||||
3. Using Lua
|
|
||||||
|
|
||||||
* Copy tools/lua.scr into /etc/frr
|
|
||||||
|
|
||||||
* Create a route-map match command
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
!
|
|
||||||
router bgp 55
|
|
||||||
neighbor 10.50.11.116 remote-as external
|
|
||||||
address-family ipv4 unicast
|
|
||||||
neighbor 10.50.11.116 route-map TEST in
|
|
||||||
exit-address-family
|
|
||||||
!
|
|
||||||
route-map TEST permit 10
|
|
||||||
match command mooey
|
|
||||||
!
|
|
||||||
|
|
||||||
* In the lua.scr file make sure that you have a function named 'mooey'
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
function mooey ()
|
|
||||||
zlog_debug(string.format("afi: %d: %s %d ifdx: %d aspath: %s localpref: %d",
|
|
||||||
prefix.family, prefix.route, nexthop.metric,
|
|
||||||
nexthop.ifindex, nexthop.aspath, nexthop.localpref))
|
|
||||||
|
|
||||||
nexthop.metric = 33
|
|
||||||
nexthop.localpref = 13
|
|
||||||
return 3
|
|
||||||
end
|
|
||||||
|
|
||||||
4. General Comments
|
|
||||||
|
|
||||||
Please be aware that this is extremely experimental and needs a ton of work
|
|
||||||
to get this up into a state that is usable.
|
|
433
doc/developer/scripting.rst
Normal file
433
doc/developer/scripting.rst
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
.. _scripting:
|
||||||
|
|
||||||
|
Scripting
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. seealso:: User docs for scripting
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
FRR has the ability to call Lua scripts to perform calculations, make
|
||||||
|
decisions, or otherwise extend builtin behavior with arbitrary user code. This
|
||||||
|
is implemented using the standard Lua C bindings. The supported version of Lua
|
||||||
|
is 5.3.
|
||||||
|
|
||||||
|
C objects may be passed into Lua and Lua objects may be retrieved by C code via
|
||||||
|
a marshalling system. In this way, arbitrary data from FRR may be passed to
|
||||||
|
scripts. It is possible to pass C functions as well.
|
||||||
|
|
||||||
|
The Lua environment is isolated from the C environment; user scripts cannot
|
||||||
|
access FRR's address space unless explicitly allowed by FRR.
|
||||||
|
|
||||||
|
For general information on how Lua is used to extend C, refer to Part IV of
|
||||||
|
"Programming in Lua".
|
||||||
|
|
||||||
|
https://www.lua.org/pil/contents.html#24
|
||||||
|
|
||||||
|
|
||||||
|
Design
|
||||||
|
------
|
||||||
|
|
||||||
|
Why Lua
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
Lua is designed to be embedded in C applications. It is very small; the
|
||||||
|
standard library is 220K. It is relatively fast. It has a simple, minimal
|
||||||
|
syntax that is relatively easy to learn and can be understood by someone with
|
||||||
|
little to no programming experience. Moreover it is widely used to add
|
||||||
|
scripting capabilities to applications. In short it is designed for this task.
|
||||||
|
|
||||||
|
Reasons against supporting multiple scripting languages:
|
||||||
|
|
||||||
|
- Each language would require different FFI methods, and specifically
|
||||||
|
different object encoders; a lot of code
|
||||||
|
- Languages have different capabilities that would have to be brought to
|
||||||
|
parity with each other; a lot of work
|
||||||
|
- Languages have vastly different performance characteristics; this would
|
||||||
|
create alot of basically unfixable issues, and result in a single de facto
|
||||||
|
standard scripting language (the fastest)
|
||||||
|
- Each language would need a dedicated maintainer for the above reasons;
|
||||||
|
this is pragmatically difficult
|
||||||
|
- Supporting multiple languages fractures the community and limits the audience
|
||||||
|
with which a given script can be shared
|
||||||
|
|
||||||
|
General
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
FRR's concept of a script is somewhat abstracted away from the fact that it is
|
||||||
|
Lua underneath. A script in has two things:
|
||||||
|
|
||||||
|
- name
|
||||||
|
- state
|
||||||
|
|
||||||
|
In code:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct frrscript {
|
||||||
|
/* Script name */
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* Lua state */
|
||||||
|
struct lua_State *L;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
``name`` is simply a string. Everything else is in ``state``, which is itself a
|
||||||
|
Lua library object (``lua_State``). This is an opaque struct that is
|
||||||
|
manipulated using ``lua_*`` functions. The basic ones are imported from
|
||||||
|
``lua.h`` and the rest are implemented within FRR to fill our use cases. The
|
||||||
|
thing to remember is that all operations beyond the initial loading the script
|
||||||
|
take place on this opaque state object.
|
||||||
|
|
||||||
|
There are four basic actions that can be done on a script:
|
||||||
|
|
||||||
|
- load
|
||||||
|
- execute
|
||||||
|
- query state
|
||||||
|
- unload
|
||||||
|
|
||||||
|
They are typically done in this order.
|
||||||
|
|
||||||
|
|
||||||
|
Loading
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
A snippet of Lua code is referred to as a "chunk". These are simply text. FRR
|
||||||
|
presently assumes chunks are located in individual files specific to one task.
|
||||||
|
These files are stored in the scripts directory and must end in ``.lua``.
|
||||||
|
|
||||||
|
A script object is created by loading a script. This is done with
|
||||||
|
``frrscript_load()``. This function takes the name of the script and an
|
||||||
|
optional callback function. The string ".lua" is appended to the script name,
|
||||||
|
and the resultant filename is looked for in the scripts directory.
|
||||||
|
|
||||||
|
For example, to load ``/etc/frr/scripts/bingus.lua``:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct frrscript *fs = frrscript_load("bingus", NULL);
|
||||||
|
|
||||||
|
During loading the script is validated for syntax and its initial environment
|
||||||
|
is setup. By default this does not include the Lua standard library; there are
|
||||||
|
security issues to consider, though for practical purposes untrusted users
|
||||||
|
should not be able to write the scripts directory anyway. If desired the Lua
|
||||||
|
standard library may be added to the script environment using
|
||||||
|
``luaL_openlibs(fs->L)`` after loading the script. Further information on
|
||||||
|
setting up the script environment is in the Lua manual.
|
||||||
|
|
||||||
|
|
||||||
|
Executing
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
After loading, scripts may be executed. A script may take input in the form of
|
||||||
|
variable bindings set in its environment prior to being run, and may provide
|
||||||
|
results by setting the value of variables. Arbitrary C values may be
|
||||||
|
transferred into the script environment, including functions.
|
||||||
|
|
||||||
|
A typical execution call looks something like this:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct frrscript *fs = frrscript_load(...);
|
||||||
|
|
||||||
|
int status_ok = 0, status_fail = 1;
|
||||||
|
struct prefix p = ...;
|
||||||
|
|
||||||
|
struct frrscript_env env[] = {
|
||||||
|
{"integer", "STATUS_FAIL", &status_fail},
|
||||||
|
{"integer", "STATUS_OK", &status_ok},
|
||||||
|
{"prefix", "myprefix", &p},
|
||||||
|
{}};
|
||||||
|
|
||||||
|
int result = frrscript_call(fs, env);
|
||||||
|
|
||||||
|
|
||||||
|
To execute a loaded script, we need to define the inputs. These inputs are
|
||||||
|
passed by binding values to variable names that will be accessible within the
|
||||||
|
Lua environment. Basically, all communication with the script takes place via
|
||||||
|
global variables within the script, and to provide inputs we predefine globals
|
||||||
|
before the script runs. This is done by passing ``frrscript_call()`` an array
|
||||||
|
of ``struct frrscript_env``. Each struct has three fields. The first identifies
|
||||||
|
the type of the value being passed; more on this later. The second defines the
|
||||||
|
name of the global variable within the script environment to bind the third
|
||||||
|
argument (the value) to.
|
||||||
|
|
||||||
|
The script is then executed and returns a general status code. In the success
|
||||||
|
case this will be 0, otherwise it will be nonzero. The script itself does not
|
||||||
|
determine this code, it is provided by the Lua interpreter.
|
||||||
|
|
||||||
|
|
||||||
|
Querying State
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When a chunk is executed, its state at exit is preserved and can be inspected.
|
||||||
|
|
||||||
|
After running a script, results may be retrieved by querying the script's
|
||||||
|
state. Again this is done by retrieving the values of global variables, which
|
||||||
|
are known to the script author to be "output" variables.
|
||||||
|
|
||||||
|
A result is retrieved like so:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct frrscript_env myresult = {"string", "myresult"};
|
||||||
|
|
||||||
|
char *myresult = frrscript_get_result(fs, &myresult);
|
||||||
|
|
||||||
|
... do something ...
|
||||||
|
|
||||||
|
XFREE(MTYPE_TMP, myresult);
|
||||||
|
|
||||||
|
|
||||||
|
As with arguments, results are retrieved by providing a ``struct
|
||||||
|
frrscript_env`` specifying a type and a global name. No value is necessary, nor
|
||||||
|
is it modified by ``frrscript_get_result()``. That function simply extracts the
|
||||||
|
requested value from the script state and returns it.
|
||||||
|
|
||||||
|
In most cases the returned value will be allocated with ``MTYPE_TMP`` and will
|
||||||
|
need to be freed after use.
|
||||||
|
|
||||||
|
|
||||||
|
Unloading
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
To destroy a script and its associated state:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
frrscript_unload(fs);
|
||||||
|
|
||||||
|
Values returned by ``frrscript_get_result`` are still valid after the script
|
||||||
|
they were retrieved from is unloaded.
|
||||||
|
|
||||||
|
Note that you must unload and then load the script if you want to reset its
|
||||||
|
state, for example to run it again with different inputs. Otherwise the state
|
||||||
|
from the previous run carries over into subsequent runs.
|
||||||
|
|
||||||
|
|
||||||
|
.. _marshalling:
|
||||||
|
|
||||||
|
Marshalling
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Earlier sections glossed over the meaning of the type name field in ``struct
|
||||||
|
frrscript_env`` and how data is passed between C and Lua. Lua, as a dynamically
|
||||||
|
typed, garbage collected language, cannot directly use C values without some
|
||||||
|
kind of marshalling / unmarshalling system to translate types between the two
|
||||||
|
runtimes.
|
||||||
|
|
||||||
|
Lua communicates with C code using a stack. C code wishing to provide data to
|
||||||
|
Lua scripts must provide a function that marshalls the C data into a Lua
|
||||||
|
representation and pushes it on the stack. C code wishing to retrieve data from
|
||||||
|
Lua must provide a corresponding unmarshalling function that retrieves a Lua
|
||||||
|
value from the stack and converts it to the corresponding C type. These two
|
||||||
|
functions, together with a chosen name of the type they operate on, are
|
||||||
|
referred to as ``codecs`` in FRR.
|
||||||
|
|
||||||
|
A codec is defined as:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
typedef void (*encoder_func)(lua_State *, const void *);
|
||||||
|
typedef void *(*decoder_func)(lua_State *, int);
|
||||||
|
|
||||||
|
struct frrscript_codec {
|
||||||
|
const char *typename;
|
||||||
|
encoder_func encoder;
|
||||||
|
decoder_func decoder;
|
||||||
|
};
|
||||||
|
|
||||||
|
A typename string and two function pointers.
|
||||||
|
|
||||||
|
``typename`` can be anything you want. For example, for the combined types of
|
||||||
|
``struct prefix`` and its equivalent in Lua I have chosen the name ``prefix``.
|
||||||
|
There is no restriction on naming here, it is just a human name used as a key
|
||||||
|
and specified when passing and retrieving values.
|
||||||
|
|
||||||
|
``encoder`` is a function that takes a ``lua_State *`` and a C type and pushes
|
||||||
|
onto the Lua stack a value representing the C type. For C structs, the usual
|
||||||
|
case, this will typically be a Lua table (tables are the only datastructure Lua
|
||||||
|
has). For example, here is the encoder function for ``struct prefix``:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
void lua_pushprefix(lua_State *L, const struct prefix *prefix)
|
||||||
|
{
|
||||||
|
char buffer[PREFIX_STRLEN];
|
||||||
|
|
||||||
|
zlog_debug("frrlua: pushing prefix table");
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
|
||||||
|
lua_setfield(L, -2, "network");
|
||||||
|
lua_pushinteger(L, prefix->prefixlen);
|
||||||
|
lua_setfield(L, -2, "length");
|
||||||
|
lua_pushinteger(L, prefix->family);
|
||||||
|
lua_setfield(L, -2, "family");
|
||||||
|
}
|
||||||
|
|
||||||
|
This function pushes a single value onto the Lua stack. It is a table whose equivalent in Lua is:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
{ ["network"] = "1.2.3.4/24", ["prefixlen"] = 24, ["family"] = 2 }
|
||||||
|
|
||||||
|
|
||||||
|
``decoder`` does the reverse; it takes a ``lua_State *`` and an index into the
|
||||||
|
stack, and unmarshalls a Lua value there into the corresponding C type. Again
|
||||||
|
for ``struct prefix``:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
void *lua_toprefix(lua_State *L, int idx)
|
||||||
|
{
|
||||||
|
struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
|
||||||
|
|
||||||
|
lua_getfield(L, idx, "network");
|
||||||
|
str2prefix(lua_tostring(L, -1), p);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
By convention these functions should be called ``lua_to*``, as this is the
|
||||||
|
naming convention used by the Lua C library for the basic types e.g.
|
||||||
|
``lua_tointeger`` and ``lua_tostring``.
|
||||||
|
|
||||||
|
The returned data must always be copied off the stack and the copy must be
|
||||||
|
allocated with ``MTYPE_TMP``. This way it is possible to unload the script
|
||||||
|
(destroy the state) without invalidating any references to values stored in it.
|
||||||
|
|
||||||
|
To register a new type with its corresponding encoding functions:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct frrscript_codec frrscript_codecs_lib[] = {
|
||||||
|
{.typename = "prefix",
|
||||||
|
.encoder = (encoder_func)lua_pushprefix,
|
||||||
|
.decoder = lua_toprefix},
|
||||||
|
{.typename = "sockunion",
|
||||||
|
.encoder = (encoder_func)lua_pushsockunion,
|
||||||
|
.decoder = lua_tosockunion},
|
||||||
|
...
|
||||||
|
{}};
|
||||||
|
|
||||||
|
frrscript_register_type_codecs(frrscript_codecs_lib);
|
||||||
|
|
||||||
|
From this point on the type names are available to be used when calling any
|
||||||
|
script and getting its results.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Marshalled types are not restricted to simple values like integers, strings
|
||||||
|
and tables. It is possible to marshall a type such that the resultant object
|
||||||
|
in Lua is an actual object-oriented object, complete with methods that call
|
||||||
|
back into defined C functions. See the Lua manual for how to do this; for a
|
||||||
|
code example, look at how zlog is exported into the script environment.
|
||||||
|
|
||||||
|
|
||||||
|
Script Environment
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Logging
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
For convenience, script environments are populated by default with a ``log``
|
||||||
|
object which contains methods corresponding to each of the ``zlog`` levels:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
log.info("info")
|
||||||
|
log.warn("warn")
|
||||||
|
log.error("error")
|
||||||
|
log.notice("notice")
|
||||||
|
log.debug("debug")
|
||||||
|
|
||||||
|
The log messages will show up in the daemon's log output.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
For a complete code example involving passing custom types, retrieving results,
|
||||||
|
and doing complex calculations in Lua, look at the implementation of the
|
||||||
|
``match script SCRIPT`` command for BGP routemaps. This example calls into a
|
||||||
|
script with a route prefix and attributes received from a peer and expects the
|
||||||
|
script to return a match / no match / match and update result.
|
||||||
|
|
||||||
|
An example script to use with this follows. This script matches, does not match
|
||||||
|
or updates a route depending on how many BGP UPDATE messages the peer has
|
||||||
|
received when the script is called, simply as a demonstration of what can be
|
||||||
|
accomplished with scripting.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
|
||||||
|
-- Example route map matching
|
||||||
|
-- author: qlyoung
|
||||||
|
--
|
||||||
|
-- The following variables are available to us:
|
||||||
|
-- log
|
||||||
|
-- logging library, with the usual functions
|
||||||
|
-- prefix
|
||||||
|
-- the route under consideration
|
||||||
|
-- attributes
|
||||||
|
-- the route's attributes
|
||||||
|
-- peer
|
||||||
|
-- the peer which received this route
|
||||||
|
-- RM_FAILURE
|
||||||
|
-- status code in case of failure
|
||||||
|
-- RM_NOMATCH
|
||||||
|
-- status code for no match
|
||||||
|
-- RM_MATCH
|
||||||
|
-- status code for match
|
||||||
|
-- RM_MATCH_AND_CHANGE
|
||||||
|
-- status code for match-and-set
|
||||||
|
--
|
||||||
|
-- We need to set the following out values:
|
||||||
|
-- action
|
||||||
|
-- Set to the appropriate status code to indicate what we did
|
||||||
|
-- attributes
|
||||||
|
-- Setting fields on here will propagate them back up to the caller if
|
||||||
|
-- 'action' is set to RM_MATCH_AND_CHANGE.
|
||||||
|
|
||||||
|
|
||||||
|
log.info("Evaluating route " .. prefix.network .. " from peer " .. peer.remote_id.string)
|
||||||
|
|
||||||
|
function on_match (prefix, attrs)
|
||||||
|
log.info("Match")
|
||||||
|
action = RM_MATCH
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_nomatch (prefix, attrs)
|
||||||
|
log.info("No match")
|
||||||
|
action = RM_NOMATCH
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_match_and_change (prefix, attrs)
|
||||||
|
action = RM_MATCH_AND_CHANGE
|
||||||
|
log.info("Match and change")
|
||||||
|
attrs["metric"] = attrs["metric"] + 7
|
||||||
|
end
|
||||||
|
|
||||||
|
special_routes = {
|
||||||
|
["172.16.10.4/24"] = on_match,
|
||||||
|
["172.16.13.1/8"] = on_nomatch,
|
||||||
|
["192.168.0.24/8"] = on_match_and_change,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if special_routes[prefix.network] then
|
||||||
|
special_routes[prefix.network](prefix, attributes)
|
||||||
|
elseif peer.stats.update_in % 3 == 0 then
|
||||||
|
on_match(prefix, attributes)
|
||||||
|
elseif peer.stats.update_in % 2 == 0 then
|
||||||
|
on_nomatch(prefix, attributes)
|
||||||
|
else
|
||||||
|
on_match_and_change(prefix, attributes)
|
||||||
|
end
|
||||||
|
|
@ -35,7 +35,6 @@ dev_RSTFILES = \
|
|||||||
doc/developer/lists.rst \
|
doc/developer/lists.rst \
|
||||||
doc/developer/locking.rst \
|
doc/developer/locking.rst \
|
||||||
doc/developer/logging.rst \
|
doc/developer/logging.rst \
|
||||||
doc/developer/lua.rst \
|
|
||||||
doc/developer/memtypes.rst \
|
doc/developer/memtypes.rst \
|
||||||
doc/developer/modules.rst \
|
doc/developer/modules.rst \
|
||||||
doc/developer/next-hop-tracking.rst \
|
doc/developer/next-hop-tracking.rst \
|
||||||
@ -46,6 +45,7 @@ dev_RSTFILES = \
|
|||||||
doc/developer/packaging-redhat.rst \
|
doc/developer/packaging-redhat.rst \
|
||||||
doc/developer/packaging.rst \
|
doc/developer/packaging.rst \
|
||||||
doc/developer/rcu.rst \
|
doc/developer/rcu.rst \
|
||||||
|
doc/developer/scripting.rst \
|
||||||
doc/developer/static-linking.rst \
|
doc/developer/static-linking.rst \
|
||||||
doc/developer/testing.rst \
|
doc/developer/testing.rst \
|
||||||
doc/developer/topotests-snippets.rst \
|
doc/developer/topotests-snippets.rst \
|
||||||
|
@ -29,6 +29,7 @@ Basics
|
|||||||
ipv6
|
ipv6
|
||||||
kernel
|
kernel
|
||||||
snmp
|
snmp
|
||||||
|
scripting
|
||||||
.. modules
|
.. modules
|
||||||
|
|
||||||
#########
|
#########
|
||||||
|
@ -362,6 +362,10 @@ options from the list below.
|
|||||||
|
|
||||||
Set hardcoded rpaths in the executable [default=yes].
|
Set hardcoded rpaths in the executable [default=yes].
|
||||||
|
|
||||||
|
.. option:: --enable-scripting
|
||||||
|
|
||||||
|
Enable Lua scripting [default=no].
|
||||||
|
|
||||||
You may specify any combination of the above options to the configure
|
You may specify any combination of the above options to the configure
|
||||||
script. By default, the executables are placed in :file:`/usr/local/sbin`
|
script. By default, the executables are placed in :file:`/usr/local/sbin`
|
||||||
and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/`
|
and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/`
|
||||||
@ -382,6 +386,10 @@ options to the configuration script.
|
|||||||
Configure zebra to use `dir` for local state files, such as pid files and
|
Configure zebra to use `dir` for local state files, such as pid files and
|
||||||
unix sockets.
|
unix sockets.
|
||||||
|
|
||||||
|
.. option:: --with-scriptdir <dir>
|
||||||
|
|
||||||
|
Look for Lua scripts in ``dir`` [``prefix``/etc/frr/scripts].
|
||||||
|
|
||||||
.. option:: --with-yangmodelsdir <dir>
|
.. option:: --with-yangmodelsdir <dir>
|
||||||
|
|
||||||
Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR
|
Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR
|
||||||
|
28
doc/user/scripting.rst
Normal file
28
doc/user/scripting.rst
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.. _scripting:
|
||||||
|
|
||||||
|
*********
|
||||||
|
Scripting
|
||||||
|
*********
|
||||||
|
|
||||||
|
The behavior of FRR may be extended or customized using its built-in scripting
|
||||||
|
capabilities.
|
||||||
|
|
||||||
|
Some configuration commands accept the name of a Lua script to call to perform
|
||||||
|
some task or make some decision. These scripts have their environments
|
||||||
|
populated with some set of inputs, and are expected to populate some set of
|
||||||
|
output variables, which are read by FRR after the script completes. The names
|
||||||
|
and expected contents of these scripts are documented alongside the commands
|
||||||
|
that support them.
|
||||||
|
|
||||||
|
These scripts live in :file:`/etc/frr/scripts/` by default. This is
|
||||||
|
configurable at compile time via ``--with-scriptdir``. It may be
|
||||||
|
overriden at runtime with the ``--scriptdir`` daemon option.
|
||||||
|
|
||||||
|
In order to use scripting, FRR must be built with ``--enable-scripting``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Scripts are typically loaded just-in-time. This means you can change the
|
||||||
|
contents of a script that is in use without restarting FRR. Not all
|
||||||
|
scripting locations may behave this way; refer to the documentation for the
|
||||||
|
particular location.
|
@ -34,6 +34,7 @@ user_RSTFILES = \
|
|||||||
doc/user/routemap.rst \
|
doc/user/routemap.rst \
|
||||||
doc/user/routeserver.rst \
|
doc/user/routeserver.rst \
|
||||||
doc/user/rpki.rst \
|
doc/user/rpki.rst \
|
||||||
|
doc/user/scripting.rst \
|
||||||
doc/user/setup.rst \
|
doc/user/setup.rst \
|
||||||
doc/user/sharp.rst \
|
doc/user/sharp.rst \
|
||||||
doc/user/snmp.rst \
|
doc/user/snmp.rst \
|
||||||
|
Loading…
Reference in New Issue
Block a user