summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/developer/scripting.rst17
-rw-r--r--lib/frrscript.c5
-rw-r--r--lib/frrscript.h16
-rw-r--r--tests/lib/test_frrscript.c8
4 files changed, 41 insertions, 5 deletions
diff --git a/doc/developer/scripting.rst b/doc/developer/scripting.rst
index d543ed3560..202f0036f8 100644
--- a/doc/developer/scripting.rst
+++ b/doc/developer/scripting.rst
@@ -117,6 +117,7 @@ Load
The function to be called must first be loaded. Use ``frrscript_load()``
which takes a ``frrscript`` object, the name of the Lua function
and a callback function.
+The script file will be read to load and compile the function.
For example, to load the Lua function ``on_foo``
in ``/etc/frr/scripts/bingus.lua``:
@@ -138,7 +139,7 @@ should not be able to write the scripts directory anyway.
Call
^^^^
-After loading, Lua functions may be called.
+After loading, a Lua function can be called any number of times.
Input
"""""
@@ -231,6 +232,18 @@ In the example, ``d`` is a "new" value in C space,
so memory allocation might take place. Hence the caller is
responsible for memory deallocation.
+``frrscript_call()`` may be called multiple times without re-loading with
+``frrscript_load()``. Results are not preserved between consecutive calls.
+
+.. code-block:: c
+
+ frrscript_load(fs, "on_foo");
+
+ frrscript_call(fs, "on_foo");
+ frrscript_get_result(fs, "on_foo", ...);
+ frrscript_call(fs, "on_foo");
+ frrscript_get_result(fs, "on_foo", ...);
+
Delete
^^^^^^
@@ -385,7 +398,7 @@ Again, for ``struct prefix *``:
{
lua_getfield(L, idx, "network");
(void)str2prefix(lua_tostring(L, -1), prefix);
- /* pop the netork string */
+ /* pop the network string */
lua_pop(L, 1);
/* pop the prefix table */
lua_pop(L, 1);
diff --git a/lib/frrscript.c b/lib/frrscript.c
index c9fc938997..0e0d3c030c 100644
--- a/lib/frrscript.c
+++ b/lib/frrscript.c
@@ -288,13 +288,16 @@ int frrscript_load(struct frrscript *fs, const char *function_name,
goto fail;
}
- /* Push the Lua function we want */
+ /* To check the Lua function, we get it from the global table */
lua_getglobal(L, function_name);
if (lua_isfunction(L, lua_gettop(L)) == 0) {
zlog_err("frrscript: loaded script '%s.lua' but %s not found",
script_name, function_name);
goto fail;
}
+ /* Then pop the function (frrscript_call will push it when it needs it)
+ */
+ lua_pop(L, 1);
if (load_cb && (*load_cb)(fs) != 0) {
zlog_err(
diff --git a/lib/frrscript.h b/lib/frrscript.h
index 540676c099..c089df61fc 100644
--- a/lib/frrscript.h
+++ b/lib/frrscript.h
@@ -203,8 +203,18 @@ const struct prefix * : lua_decode_noop \
int _frrscript_call_lua(struct lua_function_state *lfs, int nargs);
/*
- * Wrapper for calling Lua function state. Maps values passed in to their
- * encoder and decoder types.
+ * Wrapper for calling Lua function state.
+ *
+ * The Lua function name (f) to run should have already been checked by
+ * frrscript_load. So this wrapper will:
+ * 1) Find the Lua function state, which contains the Lua state
+ * 2) Clear the Lua state (there may be leftovers items from previous call)
+ * 3) Push the Lua function (f)
+ * 4) Map frrscript_call arguments onto their encoder and decoders, push those
+ * 5) Call _frrscript_call_lua (Lua execution takes place)
+ * 6) Write back to frrscript_call arguments using their decoders
+ *
+ * This wrapper can be called multiple times (after one frrscript_load).
*
* fs
* The struct frrscript in which the Lua fuction was loaded into
@@ -226,6 +236,8 @@ int _frrscript_call_lua(struct lua_function_state *lfs, int nargs);
1; \
}) \
: ({ \
+ lua_settop(lfs->L, 0); \
+ lua_getglobal(lfs->L, f); \
MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
_frrscript_call_lua( \
lfs, PP_NARG(__VA_ARGS__)); \
diff --git a/tests/lib/test_frrscript.c b/tests/lib/test_frrscript.c
index 7b23045978..4c5d8d2928 100644
--- a/tests/lib/test_frrscript.c
+++ b/tests/lib/test_frrscript.c
@@ -62,6 +62,14 @@ int main(int argc, char **argv)
long long *ansptr =
frrscript_get_result(fs, "fact", "ans", lua_tointegerp);
assert(*ansptr == 120);
+
+ /* check consecutive call + get_result without re-loading */
+ n = 4;
+ result = frrscript_call(fs, "fact", ("n", &n));
+ assert(result == 0);
+ ansptr = frrscript_get_result(fs, "fact", "ans", lua_tointegerp);
+ assert(*ansptr == 24);
+
XFREE(MTYPE_SCRIPT_RES, ansptr);
/* Negative testing */