]> git.proxmox.com Git - mirror_frr.git/blame - lib/frrscript.h
lib: Rename decode_int
[mirror_frr.git] / lib / frrscript.h
CommitLineData
5f98c815
QY
1/* Scripting foo
2 * Copyright (C) 2020 NVIDIA Corporation
3 * Quentin Young
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#ifndef __FRRSCRIPT_H__
20#define __FRRSCRIPT_H__
21
fa22080d
QY
22#include <zebra.h>
23
24#ifdef HAVE_SCRIPTING
25
9e47ee98 26#include <lua.h>
5f98c815 27#include "frrlua.h"
8878080b 28#include "bgpd/bgp_script.h"
5f98c815
QY
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
47dd8736 34typedef void (*encoder_func)(lua_State *, const void *);
f869ab17
QY
35typedef void *(*decoder_func)(lua_State *, int);
36
37struct frrscript_codec {
38 const char *typename;
39 encoder_func encoder;
40 decoder_func decoder;
41};
f944ec67 42
105ba9af
DL
43struct lua_function_state {
44 const char *name;
45 lua_State *L;
46};
47
5f98c815
QY
48struct frrscript {
49 /* Script name */
50 char *name;
51
105ba9af
DL
52 /* Hash of Lua function name to Lua function state */
53 struct hash *lua_function_hash;
5f98c815
QY
54};
55
105ba9af
DL
56
57/*
58 * Hash related functions for lua_function_hash
59 */
60
61void *lua_function_alloc(void *arg);
62
63unsigned int lua_function_hash_key(const void *data);
64
65bool lua_function_hash_cmp(const void *d1, const void *d2);
66
f869ab17
QY
67struct frrscript_env {
68 /* Value type */
69 const char *typename;
70
71 /* Binding name */
72 const char *name;
73
74 /* Value */
75 const void *val;
76};
5f98c815
QY
77
78/*
7472871e
DL
79 * Create new struct frrscript for a Lua script.
80 * This will hold the states for the Lua functions in this script.
81 *
82 * scriptname
83 * Name of the Lua script file, without the .lua
5f98c815 84 */
7472871e 85struct frrscript *frrscript_new(const char *scriptname);
f0cddf95
DL
86
87/*
88 * Load a function into frrscript, run callback if any
89 */
90int frrscript_load(struct frrscript *fs, const char *function_name,
91 int (*load_cb)(struct frrscript *));
5f98c815
QY
92
93/*
7472871e 94 * Delete Lua function states and frrscript
5f98c815 95 */
64d457d7 96void frrscript_delete(struct frrscript *fs);
5f98c815
QY
97
98/*
f869ab17 99 * Register a Lua codec for a type.
5f98c815
QY
100 *
101 * tname
102 * Name of type; e.g., "peer", "ospf_interface", etc. Chosen at will.
103 *
f869ab17
QY
104 * codec(s)
105 * Function pointer to codec struct. Encoder function should push a Lua
5f98c815 106 * table representing the passed argument - which will have the C type
f869ab17
QY
107 * associated with the chosen 'tname' to the provided stack. The decoder
108 * function should pop a value from the top of the stack and return a heap
109 * chunk containing that value. Allocations should be made with MTYPE_TMP.
110 *
111 * If using the plural function variant, pass a NULL-terminated array.
5f98c815
QY
112 *
113 */
f869ab17
QY
114void frrscript_register_type_codec(struct frrscript_codec *codec);
115void frrscript_register_type_codecs(struct frrscript_codec *codecs);
5f98c815
QY
116
117/*
118 * Initialize scripting subsystem. Call this before anything else.
e4e0229a
QY
119 *
120 * scriptdir
121 * Directory in which to look for scripts
5f98c815 122 */
e4e0229a 123void frrscript_init(const char *scriptdir);
5f98c815 124
70d995ab
DL
125/*
126 * This macro is mapped to every (name, value) in frrscript_call,
127 * so this in turn maps them onto their encoders
128 */
40d038d2 129#define ENCODE_ARGS(name, value) ENCODE_ARGS_WITH_STATE(lfs->L, value)
43a5106d 130
70d995ab
DL
131/*
132 * This macro is also mapped to every (name, value) in frrscript_call, but
133 * not every value can be mapped to its decoder - only those that appear
134 * in the returned table will. To find out if they appear in the returned
135 * table, first pop the value and check if its nil. Only call the decoder
136 * if non-nil.
137 *
138 * At the end, the only thing left on the stack should be the
139 * returned table.
140 */
43a5106d
DL
141#define DECODE_ARGS(name, value) \
142 do { \
40d038d2 143 lua_getfield(lfs->L, 1, name); \
24ff8520
DL
144 if (lua_isnil(lfs->L, 2)) { \
145 lua_pop(lfs->L, 1); \
146 } else { \
147 DECODE_ARGS_WITH_STATE(lfs->L, value); \
148 } \
149 assert(lua_gettop(lfs->L) == 1); \
43a5106d
DL
150 } while (0)
151
19eee398
DL
152/*
153 * Maps the type of value to its encoder/decoder.
154 * Add new mappings here.
155 *
156 * L
157 * Lua state
158 * scriptdir
159 * Directory in which to look for scripts
160 */
c2642aab
DL
161#define ENCODE_ARGS_WITH_STATE(L, value) \
162 _Generic((value), \
2ce634e2 163int : lua_pushinteger, \
c2642aab
DL
164long long * : lua_pushintegerp, \
165struct prefix * : lua_pushprefix, \
166struct interface * : lua_pushinterface, \
167struct in_addr * : lua_pushinaddr, \
168struct in6_addr * : lua_pushin6addr, \
169union sockunion * : lua_pushsockunion, \
170time_t * : lua_pushtimet, \
b7da61c1
DL
171char * : lua_pushstring_wrapper, \
172struct attr * : lua_pushattr, \
81fde499
DL
173struct peer * : lua_pushpeer, \
174const struct prefix * : lua_pushprefix \
c2642aab 175)(L, value)
43a5106d 176
3a3cfe47
DL
177#define DECODE_ARGS_WITH_STATE(L, value) \
178 _Generic((value), \
36cf58c7 179int : lua_decode_integer_noop, \
3a3cfe47
DL
180long long * : lua_decode_integerp, \
181struct prefix * : lua_decode_prefix, \
182struct interface * : lua_decode_interface, \
183struct in_addr * : lua_decode_inaddr, \
184struct in6_addr * : lua_decode_in6addr, \
185union sockunion * : lua_decode_sockunion, \
186time_t * : lua_decode_timet, \
b7da61c1 187char * : lua_decode_stringp, \
81fde499
DL
188struct attr * : lua_decode_attr, \
189struct peer * : lua_decode_noop, \
190const struct prefix * : lua_decode_noop \
3a3cfe47 191)(L, -1, value)
5f98c815
QY
192
193/*
7472871e 194 * Call Lua function state (abstraction for a single Lua function)
3b002f19 195 *
7472871e 196 * lfs
2ce634e2 197 * The Lua function to call; this should have been loaded in by
08bf2b41 198 * frrscript_load(). nargs Number of arguments the function accepts
3b002f19 199 *
f869ab17
QY
200 * Returns:
201 * 0 if the script ran successfully, nonzero otherwise.
3b002f19 202 */
40d038d2 203int _frrscript_call_lua(struct lua_function_state *lfs, int nargs);
43a5106d 204
19eee398 205/*
7472871e
DL
206 * Wrapper for calling Lua function state. Maps values passed in to their
207 * encoder and decoder types.
19eee398
DL
208 *
209 * fs
7472871e
DL
210 * The struct frrscript in which the Lua fuction was loaded into
211 * f
212 * Name of the Lua function.
19eee398
DL
213 *
214 * Returns:
215 * 0 if the script ran successfully, nonzero otherwise.
216 */
2ce634e2
DL
217#define frrscript_call(fs, f, ...) \
218 ({ \
67b64027 219 struct lua_function_state lookup = {.name = (f)}; \
2ce634e2 220 struct lua_function_state *lfs; \
67b64027 221 lfs = hash_lookup((fs)->lua_function_hash, &lookup); \
2ce634e2
DL
222 lfs == NULL ? ({ \
223 zlog_err( \
224 "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \
67b64027 225 (fs)->name, (f)); \
2ce634e2
DL
226 1; \
227 }) \
228 : ({ \
229 MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
230 _frrscript_call_lua( \
231 lfs, PP_NARG(__VA_ARGS__)); \
232 }) != 0 \
233 ? ({ \
234 zlog_err( \
235 "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \
67b64027 236 (fs)->name, (f)); \
2ce634e2
DL
237 1; \
238 }) \
239 : ({ \
240 MAP_LISTS(DECODE_ARGS, \
241 ##__VA_ARGS__); \
242 0; \
243 }); \
43a5106d 244 })
3b002f19
QY
245
246/*
7472871e 247 * Get result from finished function
3b002f19 248 *
f869ab17
QY
249 * fs
250 * The script. This script must have been run already.
7472871e
DL
251 * function_name
252 * Name of the Lua function.
253 * name
254 * Name of the result.
255 * This will be used as a string key to retrieve from the table that the
256 * Lua function returns.
257 * The name here should *not* appear in frrscript_call.
258 * lua_to
259 * Function pointer to a lua_to decoder function.
260 * This function should allocate and decode a value from the Lua state.
3b002f19 261 *
f869ab17 262 * Returns:
7472871e
DL
263 * A pointer to the decoded value from the Lua state, or NULL if no such
264 * value.
3b002f19 265 */
06947dde
DL
266void *frrscript_get_result(struct frrscript *fs, const char *function_name,
267 const char *name,
268 void *(*lua_to)(lua_State *L, int idx));
3b002f19 269
5f98c815
QY
270#ifdef __cplusplus
271}
272#endif /* __cplusplus */
273
fa22080d
QY
274#endif /* HAVE_SCRIPTING */
275
5f98c815 276#endif /* __FRRSCRIPT_H__ */