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