]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: Change frrscript_call to call function instead
authorDonald Lee <dlqs@gmx.com>
Sun, 4 Jul 2021 15:08:18 +0000 (23:08 +0800)
committerDonald Lee <dlqs@gmx.com>
Sat, 17 Jul 2021 22:32:03 +0000 (06:32 +0800)
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 <dlqs@gmx.com>
lib/frrscript.c
lib/frrscript.h

index ed9043d8d21a2fafba567fe9c53a63dc5ba59c1e..8a93d36da1367d3fc347af21940f37f04dabb806 100644 (file)
@@ -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;
index df72bba4cd5a25a97416bf33f3d3bee28d2ac552..a0e1176ea7ce670effda322e106e22563b8ba210 100644 (file)
@@ -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;                                                                 \
+                         });                                                                  \
        })
 
 /*