2 * Copyright (C) 2020 NVIDIA Corporation
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)
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
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
19 #ifndef __FRRSCRIPT_H__
20 #define __FRRSCRIPT_H__
28 #include <nexthop_group.h>
30 #include "bgpd/bgp_script.h" // for peer and attr encoders/decoders
36 /* Forward declarations */
37 extern struct zebra_dplane_ctx ctx
;
38 extern void lua_pushzebra_dplane_ctx(lua_State
*L
,
39 const struct zebra_dplane_ctx
*ctx
);
40 extern void lua_decode_zebra_dplane_ctx(lua_State
*L
, int idx
,
41 struct zebra_dplane_ctx
*ctx
);
46 PREDECL_HASH(frrscript_names
);
48 struct frrscript_names_entry
{
49 /* Name of a Lua hook call */
50 char function_name
[MAXPATHLEN
];
52 /* Lua script in which to look for it */
53 char script_name
[MAXPATHLEN
];
55 struct frrscript_names_item item
;
58 extern struct frrscript_names_head frrscript_names_hash
;
60 int frrscript_names_hash_cmp(const struct frrscript_names_entry
*snhe1
,
61 const struct frrscript_names_entry
*snhe2
);
62 uint32_t frrscript_names_hash_key(const struct frrscript_names_entry
*snhe
);
64 DECLARE_HASH(frrscript_names
, struct frrscript_names_entry
, item
,
65 frrscript_names_hash_cmp
, frrscript_names_hash_key
);
67 int frrscript_names_add_function_name(const char *function_name
);
68 void frrscript_names_destroy(void);
69 int frrscript_names_set_script_name(const char *function_name
,
70 const char *script_name
);
71 char *frrscript_names_get_script_name(const char *function_name
);
73 typedef void (*encoder_func
)(lua_State
*, const void *);
74 typedef void *(*decoder_func
)(lua_State
*, int);
76 struct frrscript_codec
{
82 struct lua_function_state
{
91 /* Hash of Lua function name to Lua function state */
92 struct hash
*lua_function_hash
;
97 * Hash related functions for lua_function_hash
100 void *lua_function_alloc(void *arg
);
102 unsigned int lua_function_hash_key(const void *data
);
104 bool lua_function_hash_cmp(const void *d1
, const void *d2
);
106 struct frrscript_env
{
108 const char *typename
;
118 * Create new struct frrscript for a Lua script.
119 * This will hold the states for the Lua functions in this script.
122 * Name of the Lua script file, without the .lua
124 struct frrscript
*frrscript_new(const char *scriptname
);
127 * Load a function into frrscript, run callback if any
129 int frrscript_load(struct frrscript
*fs
, const char *function_name
,
130 int (*load_cb
)(struct frrscript
*));
133 * Delete Lua function states and frrscript
135 void frrscript_delete(struct frrscript
*fs
);
138 * Register a Lua codec for a type.
141 * Name of type; e.g., "peer", "ospf_interface", etc. Chosen at will.
144 * Function pointer to codec struct. Encoder function should push a Lua
145 * table representing the passed argument - which will have the C type
146 * associated with the chosen 'tname' to the provided stack. The decoder
147 * function should pop a value from the top of the stack and return a heap
148 * chunk containing that value. Allocations should be made with MTYPE_TMP.
150 * If using the plural function variant, pass a NULL-terminated array.
153 void frrscript_register_type_codec(struct frrscript_codec
*codec
);
154 void frrscript_register_type_codecs(struct frrscript_codec
*codecs
);
157 * Initialize scripting subsystem. Call this before anything else.
160 * Directory in which to look for scripts
162 void frrscript_init(const char *scriptdir
);
165 * This macro is mapped to every (name, value) in frrscript_call,
166 * so this in turn maps them onto their encoders
168 #define ENCODE_ARGS(name, value) ENCODE_ARGS_WITH_STATE(lfs->L, (value))
171 * This macro is also mapped to every (name, value) in frrscript_call, but
172 * not every value can be mapped to its decoder - only those that appear
173 * in the returned table will. To find out if they appear in the returned
174 * table, first pop the value and check if its nil. Only call the decoder
177 * At the end, the only thing left on the stack should be the
180 #define DECODE_ARGS(name, value) \
182 lua_getfield(lfs->L, 1, (name)); \
183 if (lua_isnil(lfs->L, 2)) { \
184 lua_pop(lfs->L, 1); \
186 DECODE_ARGS_WITH_STATE(lfs->L, (value)); \
188 assert(lua_gettop(lfs->L) == 1); \
192 * Maps the type of value to its encoder/decoder.
193 * Add new mappings here.
198 * Directory in which to look for scripts
200 #define ENCODE_ARGS_WITH_STATE(L, value) \
202 int : lua_pushinteger, \
203 long long * : lua_pushintegerp, \
204 struct prefix * : lua_pushprefix, \
205 struct interface * : lua_pushinterface, \
206 struct in_addr * : lua_pushinaddr, \
207 struct in6_addr * : lua_pushin6addr, \
208 union sockunion * : lua_pushsockunion, \
209 time_t * : lua_pushtimet, \
210 char * : lua_pushstring_wrapper, \
211 struct attr * : lua_pushattr, \
212 struct peer * : lua_pushpeer, \
213 const struct prefix * : lua_pushprefix, \
214 const struct ipaddr * : lua_pushipaddr, \
215 const struct ethaddr * : lua_pushethaddr, \
216 const struct nexthop_group * : lua_pushnexthop_group, \
217 const struct nexthop * : lua_pushnexthop, \
218 struct zebra_dplane_ctx * : lua_pushzebra_dplane_ctx \
221 #define DECODE_ARGS_WITH_STATE(L, value) \
223 int : lua_decode_integer_noop, \
224 long long * : lua_decode_integerp, \
225 struct prefix * : lua_decode_prefix, \
226 struct interface * : lua_decode_interface, \
227 struct in_addr * : lua_decode_inaddr, \
228 struct in6_addr * : lua_decode_in6addr, \
229 union sockunion * : lua_decode_sockunion, \
230 time_t * : lua_decode_timet, \
231 char * : lua_decode_stringp, \
232 struct attr * : lua_decode_attr, \
233 struct peer * : lua_decode_noop, \
234 const struct prefix * : lua_decode_noop, \
235 const struct ipaddr * : lua_decode_noop, \
236 const struct ethaddr * : lua_decode_noop, \
237 const struct nexthop_group * : lua_decode_noop, \
238 const struct nexthop * : lua_decode_noop, \
239 struct zebra_dplane_ctx * : lua_decode_noop \
243 * Call Lua function state (abstraction for a single Lua function)
246 * The Lua function to call; this should have been loaded in by
247 * frrscript_load(). nargs Number of arguments the function accepts
250 * 0 if the script ran successfully, nonzero otherwise.
252 int _frrscript_call_lua(struct lua_function_state
*lfs
, int nargs
);
255 * Wrapper for calling Lua function state.
257 * The Lua function name (f) to run should have already been checked by
258 * frrscript_load. So this wrapper will:
259 * 1) Find the Lua function state, which contains the Lua state
260 * 2) Clear the Lua state (there may be leftovers items from previous call)
261 * 3) Push the Lua function (f)
262 * 4) Map frrscript_call arguments onto their encoder and decoders, push those
263 * 5) Call _frrscript_call_lua (Lua execution takes place)
264 * 6) Write back to frrscript_call arguments using their decoders
266 * This wrapper can be called multiple times (after one frrscript_load).
269 * The struct frrscript in which the Lua fuction was loaded into
271 * Name of the Lua function.
274 * 0 if the script ran successfully, nonzero otherwise.
276 #define frrscript_call(fs, f, ...) \
278 struct lua_function_state lookup = {.name = (f)}; \
279 struct lua_function_state *lfs; \
280 lfs = hash_lookup((fs)->lua_function_hash, &lookup); \
283 "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \
288 lua_settop(lfs->L, 0); \
289 lua_getglobal(lfs->L, f); \
290 MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
291 _frrscript_call_lua( \
292 lfs, PP_NARG(__VA_ARGS__)); \
296 "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \
301 MAP_LISTS(DECODE_ARGS, \
308 * Get result from finished function
311 * The script. This script must have been run already.
313 * Name of the Lua function.
315 * Name of the result.
316 * This will be used as a string key to retrieve from the table that the
317 * Lua function returns.
318 * The name here should *not* appear in frrscript_call.
320 * Function pointer to a lua_to decoder function.
321 * This function should allocate and decode a value from the Lua state.
324 * A pointer to the decoded value from the Lua state, or NULL if no such
327 void *frrscript_get_result(struct frrscript
*fs
, const char *function_name
,
329 void *(*lua_to
)(lua_State
*L
, int idx
));
333 #endif /* __cplusplus */
335 #endif /* HAVE_SCRIPTING */
337 #endif /* __FRRSCRIPT_H__ */