]>
Commit | Line | Data |
---|---|---|
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" |
b7da61c1 | 28 | #include "../bgpd/bgp_script.h" |
5f98c815 QY |
29 | |
30 | #ifdef __cplusplus | |
31 | extern "C" { | |
32 | #endif | |
33 | ||
47dd8736 | 34 | typedef void (*encoder_func)(lua_State *, const void *); |
f869ab17 QY |
35 | typedef void *(*decoder_func)(lua_State *, int); |
36 | ||
37 | struct frrscript_codec { | |
38 | const char *typename; | |
39 | encoder_func encoder; | |
40 | decoder_func decoder; | |
41 | }; | |
f944ec67 | 42 | |
105ba9af DL |
43 | struct lua_function_state { |
44 | const char *name; | |
45 | lua_State *L; | |
46 | }; | |
47 | ||
48 | ||
5f98c815 QY |
49 | struct frrscript { |
50 | /* Script name */ | |
51 | char *name; | |
52 | ||
105ba9af DL |
53 | /* Hash of Lua function name to Lua function state */ |
54 | struct hash *lua_function_hash; | |
5f98c815 QY |
55 | }; |
56 | ||
105ba9af DL |
57 | |
58 | /* | |
59 | * Hash related functions for lua_function_hash | |
60 | */ | |
61 | ||
62 | void *lua_function_alloc(void *arg); | |
63 | ||
64 | unsigned int lua_function_hash_key(const void *data); | |
65 | ||
66 | bool lua_function_hash_cmp(const void *d1, const void *d2); | |
67 | ||
f869ab17 QY |
68 | struct frrscript_env { |
69 | /* Value type */ | |
70 | const char *typename; | |
71 | ||
72 | /* Binding name */ | |
73 | const char *name; | |
74 | ||
75 | /* Value */ | |
76 | const void *val; | |
77 | }; | |
5f98c815 QY |
78 | |
79 | /* | |
80 | * Create new FRR script. | |
81 | */ | |
f0cddf95 DL |
82 | struct frrscript *frrscript_new(const char *name); |
83 | ||
84 | /* | |
85 | * Load a function into frrscript, run callback if any | |
86 | */ | |
87 | int frrscript_load(struct frrscript *fs, const char *function_name, | |
88 | int (*load_cb)(struct frrscript *)); | |
5f98c815 QY |
89 | |
90 | /* | |
91 | * Destroy FRR script. | |
92 | */ | |
93 | void frrscript_unload(struct frrscript *fs); | |
94 | ||
95 | /* | |
f869ab17 | 96 | * Register a Lua codec for a type. |
5f98c815 QY |
97 | * |
98 | * tname | |
99 | * Name of type; e.g., "peer", "ospf_interface", etc. Chosen at will. | |
100 | * | |
f869ab17 QY |
101 | * codec(s) |
102 | * Function pointer to codec struct. Encoder function should push a Lua | |
5f98c815 | 103 | * table representing the passed argument - which will have the C type |
f869ab17 QY |
104 | * associated with the chosen 'tname' to the provided stack. The decoder |
105 | * function should pop a value from the top of the stack and return a heap | |
106 | * chunk containing that value. Allocations should be made with MTYPE_TMP. | |
107 | * | |
108 | * If using the plural function variant, pass a NULL-terminated array. | |
5f98c815 QY |
109 | * |
110 | */ | |
f869ab17 QY |
111 | void frrscript_register_type_codec(struct frrscript_codec *codec); |
112 | void frrscript_register_type_codecs(struct frrscript_codec *codecs); | |
5f98c815 QY |
113 | |
114 | /* | |
115 | * Initialize scripting subsystem. Call this before anything else. | |
e4e0229a QY |
116 | * |
117 | * scriptdir | |
118 | * Directory in which to look for scripts | |
5f98c815 | 119 | */ |
e4e0229a | 120 | void frrscript_init(const char *scriptdir); |
5f98c815 | 121 | |
43a5106d DL |
122 | #define ENCODE_ARGS(name, value) \ |
123 | do { \ | |
c2642aab | 124 | ENCODE_ARGS_WITH_STATE(L, value); \ |
43a5106d DL |
125 | lua_setglobal(L, name); \ |
126 | } while (0) | |
127 | ||
128 | #define DECODE_ARGS(name, value) \ | |
129 | do { \ | |
130 | lua_getglobal(L, name); \ | |
3a3cfe47 | 131 | DECODE_ARGS_WITH_STATE(L, value); \ |
43a5106d DL |
132 | } while (0) |
133 | ||
19eee398 DL |
134 | /* |
135 | * Maps the type of value to its encoder/decoder. | |
136 | * Add new mappings here. | |
137 | * | |
138 | * L | |
139 | * Lua state | |
140 | * scriptdir | |
141 | * Directory in which to look for scripts | |
142 | */ | |
c2642aab DL |
143 | #define ENCODE_ARGS_WITH_STATE(L, value) \ |
144 | _Generic((value), \ | |
145 | long long * : lua_pushintegerp, \ | |
146 | struct prefix * : lua_pushprefix, \ | |
147 | struct interface * : lua_pushinterface, \ | |
148 | struct in_addr * : lua_pushinaddr, \ | |
149 | struct in6_addr * : lua_pushin6addr, \ | |
150 | union sockunion * : lua_pushsockunion, \ | |
151 | time_t * : lua_pushtimet, \ | |
b7da61c1 DL |
152 | char * : lua_pushstring_wrapper, \ |
153 | struct attr * : lua_pushattr, \ | |
81fde499 DL |
154 | struct peer * : lua_pushpeer, \ |
155 | const struct prefix * : lua_pushprefix \ | |
c2642aab | 156 | )(L, value) |
43a5106d | 157 | |
3a3cfe47 DL |
158 | #define DECODE_ARGS_WITH_STATE(L, value) \ |
159 | _Generic((value), \ | |
160 | long long * : lua_decode_integerp, \ | |
161 | struct prefix * : lua_decode_prefix, \ | |
162 | struct interface * : lua_decode_interface, \ | |
163 | struct in_addr * : lua_decode_inaddr, \ | |
164 | struct in6_addr * : lua_decode_in6addr, \ | |
165 | union sockunion * : lua_decode_sockunion, \ | |
166 | time_t * : lua_decode_timet, \ | |
b7da61c1 | 167 | char * : lua_decode_stringp, \ |
81fde499 DL |
168 | struct attr * : lua_decode_attr, \ |
169 | struct peer * : lua_decode_noop, \ | |
170 | const struct prefix * : lua_decode_noop \ | |
3a3cfe47 | 171 | )(L, -1, value) |
5f98c815 QY |
172 | |
173 | /* | |
f869ab17 | 174 | * Call script. |
3b002f19 | 175 | * |
f869ab17 QY |
176 | * fs |
177 | * The script to call; this is obtained from frrscript_load(). | |
3b002f19 | 178 | * |
f869ab17 QY |
179 | * Returns: |
180 | * 0 if the script ran successfully, nonzero otherwise. | |
3b002f19 | 181 | */ |
43a5106d DL |
182 | int _frrscript_call(struct frrscript *fs); |
183 | ||
19eee398 DL |
184 | /* |
185 | * Wrapper for call script. Maps values passed in to their encoder | |
186 | * and decoder types. | |
187 | * | |
188 | * fs | |
189 | * The script to call; this is obtained from frrscript_load(). | |
190 | * | |
191 | * Returns: | |
192 | * 0 if the script ran successfully, nonzero otherwise. | |
193 | */ | |
43a5106d DL |
194 | #define frrscript_call(fs, ...) \ |
195 | ({ \ | |
196 | lua_State *L = fs->L; \ | |
197 | MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ | |
198 | int ret = _frrscript_call(fs); \ | |
199 | if (ret == 0) { \ | |
200 | MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ | |
201 | } \ | |
202 | ret; \ | |
203 | }) | |
3b002f19 QY |
204 | |
205 | /* | |
f869ab17 | 206 | * Get result from finished script. |
3b002f19 | 207 | * |
f869ab17 QY |
208 | * fs |
209 | * The script. This script must have been run already. | |
3b002f19 | 210 | * |
f869ab17 QY |
211 | * result |
212 | * The result to extract from the script. | |
213 | * This reuses the frrscript_env type, but only the typename and name fields | |
214 | * need to be set. The value is returned directly. | |
3b002f19 | 215 | * |
f869ab17 QY |
216 | * Returns: |
217 | * The script result of the specified name and type, or NULL. | |
3b002f19 | 218 | */ |
f869ab17 QY |
219 | void *frrscript_get_result(struct frrscript *fs, |
220 | const struct frrscript_env *result); | |
3b002f19 | 221 | |
5f98c815 QY |
222 | #ifdef __cplusplus |
223 | } | |
224 | #endif /* __cplusplus */ | |
225 | ||
fa22080d QY |
226 | #endif /* HAVE_SCRIPTING */ |
227 | ||
5f98c815 | 228 | #endif /* __FRRSCRIPT_H__ */ |