]> git.proxmox.com Git - mirror_frr.git/blame - lib/frrscript.h
Merge pull request #12694 from donaldsharp/zebra_rib_dead_code
[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>
263951c1
DL
27#include <nexthop.h>
28#include <nexthop_group.h>
5f98c815 29#include "frrlua.h"
6ffeb9f7 30#include "bgpd/bgp_script.h" // for peer and attr encoders/decoders
5f98c815
QY
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
263951c1
DL
36/* Forward declarations */
37extern struct zebra_dplane_ctx ctx;
38extern void lua_pushzebra_dplane_ctx(lua_State *L,
39 const struct zebra_dplane_ctx *ctx);
40extern void lua_decode_zebra_dplane_ctx(lua_State *L, int idx,
41 struct zebra_dplane_ctx *ctx);
42
a3ef7ae8
DL
43/*
44 * Script name hash
45 */
46PREDECL_HASH(frrscript_names);
47
48struct frrscript_names_entry {
49 /* Name of a Lua hook call */
50 char function_name[MAXPATHLEN];
51
52 /* Lua script in which to look for it */
53 char script_name[MAXPATHLEN];
54
55 struct frrscript_names_item item;
56};
57
58extern struct frrscript_names_head frrscript_names_hash;
59
60int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
61 const struct frrscript_names_entry *snhe2);
62uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe);
63
64DECLARE_HASH(frrscript_names, struct frrscript_names_entry, item,
65 frrscript_names_hash_cmp, frrscript_names_hash_key);
66
67int frrscript_names_add_function_name(const char *function_name);
68void frrscript_names_destroy(void);
69int frrscript_names_set_script_name(const char *function_name,
70 const char *script_name);
71char *frrscript_names_get_script_name(const char *function_name);
72
47dd8736 73typedef void (*encoder_func)(lua_State *, const void *);
f869ab17
QY
74typedef void *(*decoder_func)(lua_State *, int);
75
76struct frrscript_codec {
77 const char *typename;
78 encoder_func encoder;
79 decoder_func decoder;
80};
f944ec67 81
105ba9af
DL
82struct lua_function_state {
83 const char *name;
84 lua_State *L;
85};
86
5f98c815
QY
87struct frrscript {
88 /* Script name */
89 char *name;
90
105ba9af
DL
91 /* Hash of Lua function name to Lua function state */
92 struct hash *lua_function_hash;
5f98c815
QY
93};
94
105ba9af
DL
95
96/*
97 * Hash related functions for lua_function_hash
98 */
99
100void *lua_function_alloc(void *arg);
101
102unsigned int lua_function_hash_key(const void *data);
103
104bool lua_function_hash_cmp(const void *d1, const void *d2);
105
f869ab17
QY
106struct frrscript_env {
107 /* Value type */
108 const char *typename;
109
110 /* Binding name */
111 const char *name;
112
113 /* Value */
114 const void *val;
115};
5f98c815
QY
116
117/*
7472871e
DL
118 * Create new struct frrscript for a Lua script.
119 * This will hold the states for the Lua functions in this script.
120 *
121 * scriptname
122 * Name of the Lua script file, without the .lua
5f98c815 123 */
7472871e 124struct frrscript *frrscript_new(const char *scriptname);
f0cddf95
DL
125
126/*
127 * Load a function into frrscript, run callback if any
128 */
129int frrscript_load(struct frrscript *fs, const char *function_name,
130 int (*load_cb)(struct frrscript *));
5f98c815
QY
131
132/*
7472871e 133 * Delete Lua function states and frrscript
5f98c815 134 */
64d457d7 135void frrscript_delete(struct frrscript *fs);
5f98c815
QY
136
137/*
f869ab17 138 * Register a Lua codec for a type.
5f98c815
QY
139 *
140 * tname
141 * Name of type; e.g., "peer", "ospf_interface", etc. Chosen at will.
142 *
f869ab17
QY
143 * codec(s)
144 * Function pointer to codec struct. Encoder function should push a Lua
5f98c815 145 * table representing the passed argument - which will have the C type
f869ab17
QY
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.
149 *
150 * If using the plural function variant, pass a NULL-terminated array.
5f98c815
QY
151 *
152 */
f869ab17
QY
153void frrscript_register_type_codec(struct frrscript_codec *codec);
154void frrscript_register_type_codecs(struct frrscript_codec *codecs);
5f98c815
QY
155
156/*
157 * Initialize scripting subsystem. Call this before anything else.
e4e0229a
QY
158 *
159 * scriptdir
160 * Directory in which to look for scripts
5f98c815 161 */
e4e0229a 162void frrscript_init(const char *scriptdir);
5f98c815 163
ca28a0f6
DS
164/*
165 * On shutdown clean up memory associated with the scripting subsystem
166 */
167void frrscript_fini(void);
168
70d995ab
DL
169/*
170 * This macro is mapped to every (name, value) in frrscript_call,
171 * so this in turn maps them onto their encoders
172 */
b5e790ee 173#define ENCODE_ARGS(name, value) ENCODE_ARGS_WITH_STATE(lfs->L, (value))
43a5106d 174
70d995ab
DL
175/*
176 * This macro is also mapped to every (name, value) in frrscript_call, but
177 * not every value can be mapped to its decoder - only those that appear
178 * in the returned table will. To find out if they appear in the returned
179 * table, first pop the value and check if its nil. Only call the decoder
180 * if non-nil.
181 *
182 * At the end, the only thing left on the stack should be the
183 * returned table.
184 */
43a5106d
DL
185#define DECODE_ARGS(name, value) \
186 do { \
b5e790ee 187 lua_getfield(lfs->L, 1, (name)); \
24ff8520
DL
188 if (lua_isnil(lfs->L, 2)) { \
189 lua_pop(lfs->L, 1); \
190 } else { \
b5e790ee 191 DECODE_ARGS_WITH_STATE(lfs->L, (value)); \
24ff8520
DL
192 } \
193 assert(lua_gettop(lfs->L) == 1); \
43a5106d
DL
194 } while (0)
195
19eee398
DL
196/*
197 * Maps the type of value to its encoder/decoder.
198 * Add new mappings here.
199 *
200 * L
201 * Lua state
202 * scriptdir
203 * Directory in which to look for scripts
204 */
c2642aab
DL
205#define ENCODE_ARGS_WITH_STATE(L, value) \
206 _Generic((value), \
2ce634e2 207int : lua_pushinteger, \
c2642aab
DL
208long long * : lua_pushintegerp, \
209struct prefix * : lua_pushprefix, \
210struct interface * : lua_pushinterface, \
211struct in_addr * : lua_pushinaddr, \
212struct in6_addr * : lua_pushin6addr, \
213union sockunion * : lua_pushsockunion, \
214time_t * : lua_pushtimet, \
b7da61c1
DL
215char * : lua_pushstring_wrapper, \
216struct attr * : lua_pushattr, \
81fde499 217struct peer * : lua_pushpeer, \
263951c1
DL
218const struct prefix * : lua_pushprefix, \
219const struct ipaddr * : lua_pushipaddr, \
220const struct ethaddr * : lua_pushethaddr, \
221const struct nexthop_group * : lua_pushnexthop_group, \
222const struct nexthop * : lua_pushnexthop, \
223struct zebra_dplane_ctx * : lua_pushzebra_dplane_ctx \
b5e790ee 224)((L), (value))
43a5106d 225
3a3cfe47
DL
226#define DECODE_ARGS_WITH_STATE(L, value) \
227 _Generic((value), \
36cf58c7 228int : lua_decode_integer_noop, \
3a3cfe47
DL
229long long * : lua_decode_integerp, \
230struct prefix * : lua_decode_prefix, \
231struct interface * : lua_decode_interface, \
232struct in_addr * : lua_decode_inaddr, \
233struct in6_addr * : lua_decode_in6addr, \
234union sockunion * : lua_decode_sockunion, \
235time_t * : lua_decode_timet, \
b7da61c1 236char * : lua_decode_stringp, \
81fde499
DL
237struct attr * : lua_decode_attr, \
238struct peer * : lua_decode_noop, \
263951c1
DL
239const struct prefix * : lua_decode_noop, \
240const struct ipaddr * : lua_decode_noop, \
241const struct ethaddr * : lua_decode_noop, \
242const struct nexthop_group * : lua_decode_noop, \
243const struct nexthop * : lua_decode_noop, \
244struct zebra_dplane_ctx * : lua_decode_noop \
b5e790ee 245)((L), -1, (value))
5f98c815
QY
246
247/*
7472871e 248 * Call Lua function state (abstraction for a single Lua function)
3b002f19 249 *
7472871e 250 * lfs
2ce634e2 251 * The Lua function to call; this should have been loaded in by
08bf2b41 252 * frrscript_load(). nargs Number of arguments the function accepts
3b002f19 253 *
f869ab17
QY
254 * Returns:
255 * 0 if the script ran successfully, nonzero otherwise.
3b002f19 256 */
40d038d2 257int _frrscript_call_lua(struct lua_function_state *lfs, int nargs);
43a5106d 258
19eee398 259/*
2ed598ba
DL
260 * Wrapper for calling Lua function state.
261 *
262 * The Lua function name (f) to run should have already been checked by
263 * frrscript_load. So this wrapper will:
264 * 1) Find the Lua function state, which contains the Lua state
265 * 2) Clear the Lua state (there may be leftovers items from previous call)
266 * 3) Push the Lua function (f)
267 * 4) Map frrscript_call arguments onto their encoder and decoders, push those
268 * 5) Call _frrscript_call_lua (Lua execution takes place)
269 * 6) Write back to frrscript_call arguments using their decoders
270 *
271 * This wrapper can be called multiple times (after one frrscript_load).
19eee398
DL
272 *
273 * fs
7472871e
DL
274 * The struct frrscript in which the Lua fuction was loaded into
275 * f
276 * Name of the Lua function.
19eee398
DL
277 *
278 * Returns:
279 * 0 if the script ran successfully, nonzero otherwise.
280 */
2ce634e2
DL
281#define frrscript_call(fs, f, ...) \
282 ({ \
67b64027 283 struct lua_function_state lookup = {.name = (f)}; \
2ce634e2 284 struct lua_function_state *lfs; \
67b64027 285 lfs = hash_lookup((fs)->lua_function_hash, &lookup); \
2ce634e2
DL
286 lfs == NULL ? ({ \
287 zlog_err( \
288 "frrscript: '%s.lua': '%s': tried to call this function but it was not loaded", \
67b64027 289 (fs)->name, (f)); \
2ce634e2
DL
290 1; \
291 }) \
292 : ({ \
2ed598ba
DL
293 lua_settop(lfs->L, 0); \
294 lua_getglobal(lfs->L, f); \
2ce634e2
DL
295 MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
296 _frrscript_call_lua( \
297 lfs, PP_NARG(__VA_ARGS__)); \
298 }) != 0 \
299 ? ({ \
300 zlog_err( \
301 "frrscript: '%s.lua': '%s': this function called but returned non-zero exit code. No variables modified.", \
67b64027 302 (fs)->name, (f)); \
2ce634e2
DL
303 1; \
304 }) \
305 : ({ \
306 MAP_LISTS(DECODE_ARGS, \
307 ##__VA_ARGS__); \
308 0; \
309 }); \
43a5106d 310 })
3b002f19
QY
311
312/*
7472871e 313 * Get result from finished function
3b002f19 314 *
f869ab17
QY
315 * fs
316 * The script. This script must have been run already.
7472871e
DL
317 * function_name
318 * Name of the Lua function.
319 * name
320 * Name of the result.
321 * This will be used as a string key to retrieve from the table that the
322 * Lua function returns.
323 * The name here should *not* appear in frrscript_call.
324 * lua_to
325 * Function pointer to a lua_to decoder function.
326 * This function should allocate and decode a value from the Lua state.
3b002f19 327 *
f869ab17 328 * Returns:
7472871e
DL
329 * A pointer to the decoded value from the Lua state, or NULL if no such
330 * value.
3b002f19 331 */
06947dde
DL
332void *frrscript_get_result(struct frrscript *fs, const char *function_name,
333 const char *name,
334 void *(*lua_to)(lua_State *L, int idx));
3b002f19 335
5f98c815
QY
336#ifdef __cplusplus
337}
338#endif /* __cplusplus */
339
fa22080d
QY
340#endif /* HAVE_SCRIPTING */
341
5f98c815 342#endif /* __FRRSCRIPT_H__ */