From 105ba9af8f0bd9a116f2571625b2ea39c49c20c1 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sun, 4 Jul 2021 22:58:21 +0800 Subject: lib: Change frrscript to hold many Lua states Instead of 1 frrscript : 1 lua state, it is changed to 1 : N. The states are hashed with their function names. Signed-off-by: Donald Lee --- lib/frrscript.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 1a9f3639dd..d86e6acb12 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -102,6 +102,40 @@ static void codec_free(struct codec *c) } #endif + +unsigned int lua_function_hash_key(const void *data) +{ + const struct lua_function_state *lfs = data; + + return string_hash_make(lfs->name); +} + +bool lua_function_hash_cmp(const void *d1, const void *d2) +{ + const struct lua_function_state *lfs1 = d1; + const struct lua_function_state *lfs2 = d2; + + return strmatch(lfs1->name, lfs2->name); +} + +void *lua_function_alloc(void *arg) +{ + struct lua_function_state *tmp = arg; + + struct lua_function_state *lfs = + XCALLOC(MTYPE_SCRIPT, sizeof(struct lua_function_state)); + lfs->name = tmp->name; + lfs->L = tmp->L; + return lfs; +} + +static void lua_function_free(struct lua_function_state *lfs) +{ + XFREE(MTYPE_TMP, lfs->name); + lua_close(lfs->L); + XFREE(MTYPE_TMP, lfs); +} + /* Generic script APIs */ int _frrscript_call(struct frrscript *fs) -- cgit v1.2.3 From f0cddf950f928b6f9a8d56c688235cea728fda41 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sun, 4 Jul 2021 23:05:37 +0800 Subject: lib: create new frrscript_new frrscript_new now creates a new frrscript frrscript_load now loads a function (by allocating a new lua stack) Signed-off-by: Donald Lee --- lib/frrscript.c | 48 ++++++++++++++++++++++++++++++++++-------------- lib/frrscript.h | 9 +++++++-- 2 files changed, 41 insertions(+), 16 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index d86e6acb12..ed9043d8d2 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -217,56 +217,76 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs) frrscript_register_type_codec(&codecs[i]); } -struct frrscript *frrscript_load(const char *name, - int (*load_cb)(struct frrscript *)) +struct frrscript *frrscript_new(const char *name) { struct frrscript *fs = XCALLOC(MTYPE_SCRIPT, sizeof(struct frrscript)); fs->name = XSTRDUP(MTYPE_SCRIPT, name); - fs->L = luaL_newstate(); - frrlua_export_logging(fs->L); + fs->lua_function_hash = + hash_create(lua_function_hash_key, lua_function_hash_cmp, + "Lua function state hash"); + return fs; +} + +int frrscript_load(struct frrscript *fs, const char *function_name, + int (*load_cb)(struct frrscript *)) +{ + + /* Set up the Lua script */ + lua_State *L = luaL_newstate(); + frrlua_export_logging(L); char fname[MAXPATHLEN * 2]; - snprintf(fname, sizeof(fname), "%s/%s.lua", scriptdir, fs->name); - int ret = luaL_loadfile(fs->L, fname); + snprintf(fname, sizeof(fname), "%s/%s.lua", scriptdir, fs->name); + int ret = luaL_dofile(L, fname); switch (ret) { case LUA_OK: break; case LUA_ERRSYNTAX: zlog_err("Failed loading script '%s': syntax error: %s", fname, - lua_tostring(fs->L, -1)); + lua_tostring(L, -1)); break; case LUA_ERRMEM: zlog_err("Failed loading script '%s': out-of-memory error: %s", - fname, lua_tostring(fs->L, -1)); + fname, lua_tostring(L, -1)); break; case LUA_ERRGCMM: zlog_err( "Failed loading script '%s': garbage collector error: %s", - fname, lua_tostring(fs->L, -1)); + fname, lua_tostring(L, -1)); break; case LUA_ERRFILE: zlog_err("Failed loading script '%s': file read error: %s", - fname, lua_tostring(fs->L, -1)); + fname, lua_tostring(L, -1)); break; default: zlog_err("Failed loading script '%s': unknown error: %s", fname, - lua_tostring(fs->L, -1)); + lua_tostring(L, -1)); break; } if (ret != LUA_OK) goto fail; + /* Push the Lua function we want */ + lua_getglobal(L, function_name); + if (lua_isfunction(L, lua_gettop(L)) == 0) + goto fail; + if (load_cb && (*load_cb)(fs) != 0) goto fail; - return fs; + /* Add the Lua function state to frrscript */ + struct lua_function_state key = {.name = function_name, .L = L}; + + hash_get(fs->lua_function_hash, &key, lua_function_alloc); + + return 0; fail: - frrscript_unload(fs); - return NULL; + lua_close(L); + return 1; } void frrscript_unload(struct frrscript *fs) diff --git a/lib/frrscript.h b/lib/frrscript.h index 97e543eb00..df72bba4cd 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -79,8 +79,13 @@ struct frrscript_env { /* * Create new FRR script. */ -struct frrscript *frrscript_load(const char *name, - int (*load_cb)(struct frrscript *)); +struct frrscript *frrscript_new(const char *name); + +/* + * Load a function into frrscript, run callback if any + */ +int frrscript_load(struct frrscript *fs, const char *function_name, + int (*load_cb)(struct frrscript *)); /* * Destroy FRR script. -- cgit v1.2.3 From 40d038d2a1c8329c408c4fffd88e674413dfd427 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sun, 4 Jul 2021 23:08:18 +0800 Subject: lib: Change frrscript_call to call function instead There is some rather heavy error checking logic in frrscript_call. Normally I'd put this in the _frrscript_call function, but the error checking needs to happen before the encoders/decoders in the macro are called. The error checking looks messy but its really just nested ternary expressions insite a larger statement expression. Signed-off-by: Donald Lee --- lib/frrscript.c | 42 +++++++++++++++++++++++++++++------------- lib/frrscript.h | 47 ++++++++++++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 30 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index ed9043d8d2..8a93d36da1 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -138,41 +138,57 @@ static void lua_function_free(struct lua_function_state *lfs) /* Generic script APIs */ -int _frrscript_call(struct frrscript *fs) +int _frrscript_call_lua(struct lua_function_state *lfs, int nargs) { - int ret = lua_pcall(fs->L, 0, 0, 0); + int ret; + ret = lua_pcall(lfs->L, nargs, 1, 0); switch (ret) { case LUA_OK: break; case LUA_ERRRUN: - zlog_err("Script '%s' runtime error: %s", fs->name, - lua_tostring(fs->L, -1)); + zlog_err("Lua hook call '%s' : runtime error: %s", lfs->name, + lua_tostring(lfs->L, -1)); break; case LUA_ERRMEM: - zlog_err("Script '%s' memory error: %s", fs->name, - lua_tostring(fs->L, -1)); + zlog_err("Lua hook call '%s' : memory error: %s", lfs->name, + lua_tostring(lfs->L, -1)); break; case LUA_ERRERR: - zlog_err("Script '%s' error handler error: %s", fs->name, - lua_tostring(fs->L, -1)); + zlog_err("Lua hook call '%s' : error handler error: %s", + lfs->name, lua_tostring(lfs->L, -1)); break; case LUA_ERRGCMM: - zlog_err("Script '%s' garbage collector error: %s", fs->name, - lua_tostring(fs->L, -1)); + zlog_err("Lua hook call '%s' : garbage collector error: %s", + lfs->name, lua_tostring(lfs->L, -1)); break; default: - zlog_err("Script '%s' unknown error: %s", fs->name, - lua_tostring(fs->L, -1)); + zlog_err("Lua hook call '%s' : unknown error: %s", lfs->name, + lua_tostring(lfs->L, -1)); break; } if (ret != LUA_OK) { - lua_pop(fs->L, 1); + lua_pop(lfs->L, 1); goto done; } + if (lua_gettop(lfs->L) != 1) { + zlog_err( + "Lua hook call '%s': Lua function should return only 1 result", + lfs->name); + ret = 1; + goto done; + } + + if (lua_istable(lfs->L, 1) != 1) { + zlog_err( + "Lua hook call '%s': Lua function should return a Lua table", + lfs->name); + ret = 1; + } + done: /* LUA_OK is 0, so we can just return lua_pcall's result directly */ return ret; diff --git a/lib/frrscript.h b/lib/frrscript.h index df72bba4cd..a0e1176ea7 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -119,16 +119,12 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs); */ void frrscript_init(const char *scriptdir); -#define ENCODE_ARGS(name, value) \ - do { \ - ENCODE_ARGS_WITH_STATE(L, value); \ - lua_setglobal(L, name); \ - } while (0) +#define ENCODE_ARGS(name, value) ENCODE_ARGS_WITH_STATE(lfs->L, value) #define DECODE_ARGS(name, value) \ do { \ - lua_getglobal(L, name); \ - DECODE_ARGS_WITH_STATE(L, value); \ + lua_getfield(lfs->L, 1, name); \ + DECODE_ARGS_WITH_STATE(lfs->L, value); \ } while (0) /* @@ -179,7 +175,7 @@ const struct prefix * : lua_decode_noop \ * Returns: * 0 if the script ran successfully, nonzero otherwise. */ -int _frrscript_call(struct frrscript *fs); +int _frrscript_call_lua(struct lua_function_state *lfs, int nargs); /* * Wrapper for call script. Maps values passed in to their encoder @@ -191,15 +187,32 @@ int _frrscript_call(struct frrscript *fs); * Returns: * 0 if the script ran successfully, nonzero otherwise. */ -#define frrscript_call(fs, ...) \ - ({ \ - lua_State *L = fs->L; \ - MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ - int ret = _frrscript_call(fs); \ - if (ret == 0) { \ - MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ - } \ - ret; \ + +#define frrscript_call(fs, f, ...) \ + ({ \ + struct lua_function_state lookup = {.name = f}; \ + struct lua_function_state *lfs; \ + lfs = hash_lookup(fs->lua_function_hash, &lookup); \ + lfs == NULL ? ({ \ + zlog_err( \ + "Lua script call: tried to call '%s' in '%s' which was not loaded", \ + f, fs->name); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ + _frrscript_call_lua(lfs, PP_NARG(__VA_ARGS__)); \ + }) != 0 \ + ? ({ \ + zlog_err( \ + "Lua script call: '%s' in '%s' returned non-zero exit code", \ + f, fs->name); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ + 0; \ + }); \ }) /* -- cgit v1.2.3 From cb5de2314056e81854715c1835612445736e0a03 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Mon, 5 Jul 2021 05:11:24 +0800 Subject: lib: update frrscript unload Signed-off-by: Donald Lee --- lib/frrscript.c | 4 ---- lib/frrscript.h | 1 - 2 files changed, 5 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 8a93d36da1..1d4fe58dd1 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -208,9 +208,6 @@ void *frrscript_get_result(struct frrscript *fs, return NULL; } - lua_getglobal(fs->L, result->name); - r = codec->decoder(fs->L, -1); - lua_pop(fs->L, 1); return r; } @@ -307,7 +304,6 @@ fail: void frrscript_unload(struct frrscript *fs) { - lua_close(fs->L); XFREE(MTYPE_SCRIPT, fs->name); XFREE(MTYPE_SCRIPT, fs); } diff --git a/lib/frrscript.h b/lib/frrscript.h index a0e1176ea7..0d5568d342 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -45,7 +45,6 @@ struct lua_function_state { lua_State *L; }; - struct frrscript { /* Script name */ char *name; -- cgit v1.2.3 From 06947ddeac654c76940c09d38cb0e5f435e28495 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Wed, 7 Jul 2021 21:53:38 +0800 Subject: lib: Add frrscript_get_result Signed-off-by: Donald Lee --- lib/frrscript.c | 27 ++++++++++++++++++--------- lib/frrscript.h | 5 +++-- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 1d4fe58dd1..5352c6470d 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -194,22 +194,31 @@ done: return ret; } -void *frrscript_get_result(struct frrscript *fs, - const struct frrscript_env *result) +void *frrscript_get_result(struct frrscript *fs, const char *function_name, + const char *name, + void *(*lua_to)(lua_State *L, int idx)) { - void *r; - struct frrscript_codec c = {.typename = result->typename}; + void *p; + struct lua_function_state *lfs; + struct lua_function_state lookup = {.name = function_name}; - struct frrscript_codec *codec = hash_lookup(codec_hash, &c); - assert(codec && "No encoder for type"); + lfs = hash_lookup(fs->lua_function_hash, &lookup); - if (!codec->decoder) { - zlog_err("No script decoder for type '%s'", result->typename); + if (lfs == NULL) { return NULL; } + /* results table is idx 1 on the stack, getfield pushes our item to idx + * 2*/ + lua_getfield(lfs->L, 1, name); + if (lua_isnil(lfs->L, -1)) { + lua_pop(lfs->L, 1); + zlog_err("No result in results table with that name %s", name); + return NULL; + } + p = lua_to(lfs->L, 2); - return r; + return p; } void frrscript_register_type_codec(struct frrscript_codec *codec) diff --git a/lib/frrscript.h b/lib/frrscript.h index 1e35e2ee41..d2791a5a8b 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -233,8 +233,9 @@ int _frrscript_call_lua(struct lua_function_state *lfs, int nargs); * Returns: * The script result of the specified name and type, or NULL. */ -void *frrscript_get_result(struct frrscript *fs, - const struct frrscript_env *result); +void *frrscript_get_result(struct frrscript *fs, const char *function_name, + const char *name, + void *(*lua_to)(lua_State *L, int idx)); #ifdef __cplusplus } -- cgit v1.2.3 From fae19fa56d110b27bc4f507221573b432cdfc9a8 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Thu, 8 Jul 2021 01:31:43 +0800 Subject: lib: frrscript unload deallocates Lua function Signed-off-by: Donald Lee --- lib/frrscript.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 5352c6470d..9b497a431d 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -102,6 +102,7 @@ static void codec_free(struct codec *c) } #endif +/* Lua function hash utils */ unsigned int lua_function_hash_key(const void *data) { @@ -129,11 +130,11 @@ void *lua_function_alloc(void *arg) return lfs; } -static void lua_function_free(struct lua_function_state *lfs) +static void lua_function_free(struct hash_bucket *b, void *data) { - XFREE(MTYPE_TMP, lfs->name); + struct lua_function_state *lfs = (struct lua_function_state *)b->data; lua_close(lfs->L); - XFREE(MTYPE_TMP, lfs); + XFREE(MTYPE_SCRIPT, lfs); } /* Generic script APIs */ @@ -313,6 +314,7 @@ fail: void frrscript_unload(struct frrscript *fs) { + hash_iterate(fs->lua_function_hash, lua_function_free, NULL); XFREE(MTYPE_SCRIPT, fs->name); XFREE(MTYPE_SCRIPT, fs); } -- cgit v1.2.3 From b664092990bddc95562626847396e067d50fae85 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Thu, 8 Jul 2021 02:40:18 +0800 Subject: lib: standardize zlog error messages Signed-off-by: Donald Lee --- lib/frrscript.c | 37 ++++++++++++++++++++++--------------- lib/frrscript.h | 52 +++++++++++++++++++++++++--------------------------- 2 files changed, 47 insertions(+), 42 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 9b497a431d..8252455fd9 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -137,7 +137,7 @@ static void lua_function_free(struct hash_bucket *b, void *data) XFREE(MTYPE_SCRIPT, lfs); } -/* Generic script APIs */ +/* internal frrscript APIs */ int _frrscript_call_lua(struct lua_function_state *lfs, int nargs) { @@ -214,7 +214,9 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, lua_getfield(lfs->L, 1, name); if (lua_isnil(lfs->L, -1)) { lua_pop(lfs->L, 1); - zlog_err("No result in results table with that name %s", name); + zlog_warn( + "frrscript: '%s.lua': '%s': tried to decode '%s' as result but failed", + fs->name, function_name, name); return NULL; } p = lua_to(lfs->L, 2); @@ -259,34 +261,39 @@ int frrscript_load(struct frrscript *fs, const char *function_name, lua_State *L = luaL_newstate(); frrlua_export_logging(L); - char fname[MAXPATHLEN * 2]; + char script_name[MAXPATHLEN * 2]; - snprintf(fname, sizeof(fname), "%s/%s.lua", scriptdir, fs->name); - int ret = luaL_dofile(L, fname); + snprintf(script_name, sizeof(script_name), "%s/%s.lua", scriptdir, + fs->name); + int ret = luaL_dofile(L, script_name); switch (ret) { case LUA_OK: break; case LUA_ERRSYNTAX: - zlog_err("Failed loading script '%s': syntax error: %s", fname, - lua_tostring(L, -1)); + zlog_err( + "frrscript: failed loading script '%s.lua': syntax error: %s", + script_name, lua_tostring(L, -1)); break; case LUA_ERRMEM: - zlog_err("Failed loading script '%s': out-of-memory error: %s", - fname, lua_tostring(L, -1)); + zlog_err( + "frrscript: failed loading script '%s.lua': out-of-memory error: %s", + script_name, lua_tostring(L, -1)); break; case LUA_ERRGCMM: zlog_err( - "Failed loading script '%s': garbage collector error: %s", - fname, lua_tostring(L, -1)); + "frrscript: failed loading script '%s.lua': garbage collector error: %s", + script_name, lua_tostring(L, -1)); break; case LUA_ERRFILE: - zlog_err("Failed loading script '%s': file read error: %s", - fname, lua_tostring(L, -1)); + zlog_err( + "frrscript: failed loading script '%s.lua': file read error: %s", + script_name, lua_tostring(L, -1)); break; default: - zlog_err("Failed loading script '%s': unknown error: %s", fname, - lua_tostring(L, -1)); + zlog_err( + "frrscript: failed loading script '%s.lua': unknown error: %s", + script_name, lua_tostring(L, -1)); break; } diff --git a/lib/frrscript.h b/lib/frrscript.h index 85e7b15cd3..1f234a38a9 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -192,33 +192,31 @@ int _frrscript_call_lua(struct lua_function_state *lfs, int nargs); * 0 if the script ran successfully, nonzero otherwise. */ -#define frrscript_call(fs, f, ...) \ - ({ \ - struct lua_function_state lookup = {.name = f}; \ - struct lua_function_state *lfs; \ - lfs = hash_lookup(fs->lua_function_hash, &lookup); \ - lfs == NULL ? ({ \ - zlog_err( \ - "Lua script call: tried to call '%s' in '%s' which was not loaded", \ - f, fs->name); \ - 1; \ - }) \ - : ({ \ - MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ - _frrscript_call_lua( \ - lfs, PP_NARG(__VA_ARGS__)); \ - }) != 0 \ - ? ({ \ - zlog_err( \ - "Lua script call: '%s' in '%s' returned non-zero exit code", \ - f, fs->name); \ - 1; \ - }) \ - : ({ \ - MAP_LISTS(DECODE_ARGS, \ - ##__VA_ARGS__); \ - 0; \ - }); \ +#define frrscript_call(fs, f, ...) \ + ({ \ + struct lua_function_state lookup = {.name = f}; \ + struct lua_function_state *lfs; \ + lfs = hash_lookup(fs->lua_function_hash, &lookup); \ + lfs == NULL ? ({ \ + zlog_err( \ + "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \ + fs->name, f); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ + _frrscript_call_lua(lfs, PP_NARG(__VA_ARGS__)); \ + }) != 0 \ + ? ({ \ + zlog_err( \ + "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \ + fs->name, f); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ + 0; \ + }); \ }) /* -- cgit v1.2.3 From 64d457d7ac22d643afb5638bacb0b9713274689e Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Thu, 8 Jul 2021 17:51:14 +0800 Subject: lib: Rename frrscript_unload to delete frrscript_load now loads a function instead of a file, so frrscript_unload should be renamed since it does not unload a function. Signed-off-by: Donald Lee --- bgpd/bgp_routemap.c | 2 +- lib/command.c | 2 +- lib/frrscript.c | 2 +- lib/frrscript.h | 2 +- tests/lib/test_frrscript.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/frrscript.c') diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 0b22caaee7..c2062a5f60 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -434,7 +434,7 @@ route_match_script(void *rule, const struct prefix *prefix, void *object) break; } - frrscript_unload(fs); + frrscript_delete(fs); return status; } diff --git a/lib/command.c b/lib/command.c index 7808f57594..ceea186a9d 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2443,7 +2443,7 @@ DEFUN(script, vty_out(vty, "p: %s\n", buf); vty_out(vty, "Script result: %d\n", ret); - frrscript_unload(fs); + frrscript_delete(fs); return CMD_SUCCESS; } diff --git a/lib/frrscript.c b/lib/frrscript.c index 8252455fd9..b3f8a9f6f5 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -319,7 +319,7 @@ fail: return 1; } -void frrscript_unload(struct frrscript *fs) +void frrscript_delete(struct frrscript *fs) { hash_iterate(fs->lua_function_hash, lua_function_free, NULL); XFREE(MTYPE_SCRIPT, fs->name); diff --git a/lib/frrscript.h b/lib/frrscript.h index 1f234a38a9..14a922a741 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -89,7 +89,7 @@ int frrscript_load(struct frrscript *fs, const char *function_name, /* * Destroy FRR script. */ -void frrscript_unload(struct frrscript *fs); +void frrscript_delete(struct frrscript *fs); /* * Register a Lua codec for a type. diff --git a/tests/lib/test_frrscript.c b/tests/lib/test_frrscript.c index e01807f193..2d5746b587 100644 --- a/tests/lib/test_frrscript.c +++ b/tests/lib/test_frrscript.c @@ -98,7 +98,7 @@ int main(int argc, char **argv) result = frrscript_call(fs, "bad_return4"); assert(result == 1); - frrscript_unload(fs); + frrscript_delete(fs); return 0; } -- cgit v1.2.3 From 2ce634e2ad6cdfddb79e00cda01f21280d521279 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sun, 18 Jul 2021 06:25:54 +0800 Subject: lib: formatting Signed-off-by: Donald Lee --- bgpd/bgp_routemap.c | 3 ++- lib/frrscript.c | 7 ++++--- lib/frrscript.h | 59 +++++++++++++++++++++++++++-------------------------- 3 files changed, 36 insertions(+), 33 deletions(-) (limited to 'lib/frrscript.c') diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 9146e90fbf..5bdc37c9ad 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -396,7 +396,8 @@ route_match_script(void *rule, const struct prefix *prefix, void *object) return RMAP_NOMATCH; } - long long* action = frrscript_get_result(fs, routematch_function, "action", lua_tointegerp); + long long *action = frrscript_get_result(fs, routematch_function, + "action", lua_tointegerp); int status = RMAP_NOMATCH; diff --git a/lib/frrscript.c b/lib/frrscript.c index b3f8a9f6f5..b385ad7eaa 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -205,12 +205,12 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, lfs = hash_lookup(fs->lua_function_hash, &lookup); - if (lfs == NULL) { + if (lfs == NULL) return NULL; - } /* results table is idx 1 on the stack, getfield pushes our item to idx - * 2*/ + * 2 + */ lua_getfield(lfs->L, 1, name); if (lua_isnil(lfs->L, -1)) { lua_pop(lfs->L, 1); @@ -259,6 +259,7 @@ int frrscript_load(struct frrscript *fs, const char *function_name, /* Set up the Lua script */ lua_State *L = luaL_newstate(); + frrlua_export_logging(L); char script_name[MAXPATHLEN * 2]; diff --git a/lib/frrscript.h b/lib/frrscript.h index d756b49533..e76d14c1f4 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -146,7 +146,7 @@ void frrscript_init(const char *scriptdir); */ #define ENCODE_ARGS_WITH_STATE(L, value) \ _Generic((value), \ -int: lua_pushinteger, \ +int : lua_pushinteger, \ long long * : lua_pushintegerp, \ struct prefix * : lua_pushprefix, \ struct interface * : lua_pushinterface, \ @@ -180,9 +180,8 @@ const struct prefix * : lua_decode_noop \ * Call Lua function state (abstraction for a single Lua function) * * lfs - * The Lua function to call; this should have been loaded in by frrscript_load(). - * nargs - * Number of arguments the function accepts + * The Lua function to call; this should have been loaded in by + * frrscript_load(). nargs Number of arguments the function accepts * * Returns: * 0 if the script ran successfully, nonzero otherwise. @@ -201,31 +200,33 @@ int _frrscript_call_lua(struct lua_function_state *lfs, int nargs); * Returns: * 0 if the script ran successfully, nonzero otherwise. */ -#define frrscript_call(fs, f, ...) \ - ({ \ - struct lua_function_state lookup = {.name = f}; \ - struct lua_function_state *lfs; \ - lfs = hash_lookup(fs->lua_function_hash, &lookup); \ - lfs == NULL ? ({ \ - zlog_err( \ - "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \ - fs->name, f); \ - 1; \ - }) \ - : ({ \ - MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ - _frrscript_call_lua(lfs, PP_NARG(__VA_ARGS__)); \ - }) != 0 \ - ? ({ \ - zlog_err( \ - "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \ - fs->name, f); \ - 1; \ - }) \ - : ({ \ - MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ - 0; \ - }); \ +#define frrscript_call(fs, f, ...) \ + ({ \ + struct lua_function_state lookup = {.name = f}; \ + struct lua_function_state *lfs; \ + lfs = hash_lookup(fs->lua_function_hash, &lookup); \ + lfs == NULL ? ({ \ + zlog_err( \ + "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \ + fs->name, f); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ + _frrscript_call_lua( \ + lfs, PP_NARG(__VA_ARGS__)); \ + }) != 0 \ + ? ({ \ + zlog_err( \ + "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \ + fs->name, f); \ + 1; \ + }) \ + : ({ \ + MAP_LISTS(DECODE_ARGS, \ + ##__VA_ARGS__); \ + 0; \ + }); \ }) /* -- cgit v1.2.3 From 1763ed26559eda64663f1224a07b46001084d985 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Fri, 23 Jul 2021 23:25:20 +0800 Subject: lib: Cap script_name length Signed-off-by: Donald Lee --- lib/frrscript.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index b385ad7eaa..3f2544f4a0 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -262,10 +262,15 @@ int frrscript_load(struct frrscript *fs, const char *function_name, frrlua_export_logging(L); - char script_name[MAXPATHLEN * 2]; + char script_name[MAXPATHLEN]; - snprintf(script_name, sizeof(script_name), "%s/%s.lua", scriptdir, - fs->name); + if (snprintf(script_name, sizeof(script_name), "%s/%s.lua", scriptdir, + fs->name) + < 0) { + zlog_err("frrscript: path to script %s/%s.lua is too long", + scriptdir, fs->name); + goto fail; + } int ret = luaL_dofile(L, script_name); switch (ret) { -- cgit v1.2.3 From 1da9c4bdbb5ffdaf83af482af031fa97ed47eb15 Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sat, 24 Jul 2021 00:17:33 +0800 Subject: lib: Use negative indices and add comments Signed-off-by: Donald Lee --- lib/frrscript.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 3f2544f4a0..8fe8a93f05 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -208,10 +208,14 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, if (lfs == NULL) return NULL; - /* results table is idx 1 on the stack, getfield pushes our item to idx - * 2 + /* At this point, the Lua state should have only the returned table. + * We will then search the table for the key/value we're interested in. + * Then if the value is present (i.e. non-nil), call the lua_to* + * decoder. */ - lua_getfield(lfs->L, 1, name); + assert(lua_gettop(lfs->L) == 1); + assert(lua_istable(lfs->L, -1) == 1); + lua_getfield(lfs->L, -1, name); if (lua_isnil(lfs->L, -1)) { lua_pop(lfs->L, 1); zlog_warn( @@ -221,6 +225,11 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, } p = lua_to(lfs->L, 2); + /* At the end, the Lua state should be same as it was at the start + * i.e. containing soley the returned table. */ + assert(lua_gettop(lfs->L) == 1); + assert(lua_istable(lfs->L, -1) == 1); + return p; } -- cgit v1.2.3 From 4093300ee891bd7559b93e2b7c94fb6fc68b5ddc Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Sat, 24 Jul 2021 03:34:28 +0800 Subject: lib: zlog err in error cases during lua loading Signed-off-by: Donald Lee --- lib/frrscript.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 8fe8a93f05..59fce36c7a 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -317,11 +317,18 @@ int frrscript_load(struct frrscript *fs, const char *function_name, /* Push the Lua function we want */ lua_getglobal(L, function_name); - if (lua_isfunction(L, lua_gettop(L)) == 0) + 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; + } - if (load_cb && (*load_cb)(fs) != 0) + if (load_cb && (*load_cb)(fs) != 0) { + zlog_err( + "frrscript: '%s.lua': %s: loaded but callback returned non-zero exit code", + script_name, function_name); goto fail; + } /* Add the Lua function state to frrscript */ struct lua_function_state key = {.name = function_name, .L = L}; -- cgit v1.2.3 From 84c92002d25b7a498f9210356874dbe45a306e8a Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Mon, 26 Jul 2021 23:35:17 +0800 Subject: lib: formatting Signed-off-by: Donald Lee --- doc/developer/scripting.rst | 14 +++++++------- lib/frrscript.c | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'lib/frrscript.c') diff --git a/doc/developer/scripting.rst b/doc/developer/scripting.rst index fa1c521fc6..7251bafb05 100644 --- a/doc/developer/scripting.rst +++ b/doc/developer/scripting.rst @@ -62,18 +62,18 @@ are respectively encapsulated in the following structures: .. code-block:: c struct frrscript { - /* Lua file name */ - char *name; + /* Lua file name */ + char *name; - /* hash of lua_function_states */ - struct hash *lua_function_hash; + /* hash of lua_function_states */ + struct hash *lua_function_hash; }; struct lua_function_state { - /* Lua function name */ - char *name; + /* Lua function name */ + char *name; - lua_State *L; + lua_State *L; }; diff --git a/lib/frrscript.c b/lib/frrscript.c index 59fce36c7a..3e1e184bc6 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -226,7 +226,8 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, p = lua_to(lfs->L, 2); /* At the end, the Lua state should be same as it was at the start - * i.e. containing soley the returned table. */ + * i.e. containing soley the returned table. + */ assert(lua_gettop(lfs->L) == 1); assert(lua_istable(lfs->L, -1) == 1); -- cgit v1.2.3 From 9e3a277b0442861482a2dae9070fb5a1dd887aeb Mon Sep 17 00:00:00 2001 From: Donald Lee Date: Thu, 29 Jul 2021 05:41:09 +0800 Subject: lib: Fix condition for snprintf Signed-off-by: Donald Lee --- lib/frrscript.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/frrscript.c') diff --git a/lib/frrscript.c b/lib/frrscript.c index 3e1e184bc6..d00b84ccbb 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -276,7 +276,7 @@ int frrscript_load(struct frrscript *fs, const char *function_name, if (snprintf(script_name, sizeof(script_name), "%s/%s.lua", scriptdir, fs->name) - < 0) { + >= (int)sizeof(script_name)) { zlog_err("frrscript: path to script %s/%s.lua is too long", scriptdir, fs->name); goto fail; -- cgit v1.2.3