Line data Source code
1 : #include "vat.h"
2 : #include <dlfcn.h>
3 : #include <vat/plugin.h>
4 :
5 : vat_main_t vat_main;
6 :
7 : void __clib_no_tail_calls
8 785365 : vat_suspend (vlib_main_t *vm, f64 interval)
9 : {
10 785365 : vlib_process_suspend (vm, interval);
11 785365 : }
12 :
13 : static u8 *
14 16 : format_api_error (u8 * s, va_list * args)
15 : {
16 16 : vat_main_t *vam = va_arg (*args, vat_main_t *);
17 16 : i32 error = va_arg (*args, u32);
18 : uword *p;
19 :
20 16 : p = hash_get (vam->error_string_by_error_number, -error);
21 :
22 16 : if (p)
23 16 : s = format (s, "%s", p[0]);
24 : else
25 0 : s = format (s, "%d", error);
26 16 : return s;
27 : }
28 :
29 :
30 : static void
31 575 : init_error_string_table (vat_main_t * vam)
32 : {
33 :
34 575 : vam->error_string_by_error_number = hash_create (0, sizeof (uword));
35 :
36 : #define _(n,v,s) hash_set (vam->error_string_by_error_number, -v, s);
37 575 : foreach_vnet_api_error;
38 : #undef _
39 :
40 575 : hash_set (vam->error_string_by_error_number, 99, "Misc");
41 575 : }
42 :
43 : #if VPP_API_TEST_BUILTIN > 0
44 : static void
45 575 : load_features (void)
46 : {
47 : vat_registered_features_t *f;
48 575 : vat_main_t *vam = &vat_main;
49 : clib_error_t *error;
50 :
51 575 : f = vam->feature_function_registrations;
52 :
53 575 : while (f)
54 : {
55 0 : error = f->function (vam);
56 0 : if (error)
57 : {
58 0 : clib_warning ("INIT FAILED");
59 : }
60 0 : f = f->next;
61 : }
62 575 : }
63 :
64 : clib_error_t *
65 575 : vat_builtin_main_init (vlib_main_t * vm)
66 : {
67 575 : vat_main_t *vam = &vat_main;
68 : int rv;
69 : int vat_plugin_init (vat_main_t * vam);
70 :
71 575 : vam->vlib_main = vm;
72 575 : vam->my_client_index = (u32) ~ 0;
73 : /* Ensure that vam->inbuf is never NULL */
74 575 : vec_validate (vam->inbuf, 0);
75 575 : vec_validate (vam->cmd_reply, 0);
76 575 : vec_reset_length (vam->cmd_reply);
77 575 : init_error_string_table (vam);
78 575 : rv = vat_plugin_init (vam);
79 575 : if (rv)
80 0 : clib_warning ("vat_plugin_init returned %d", rv);
81 :
82 575 : load_features ();
83 :
84 575 : return 0;
85 : }
86 : #endif
87 :
88 : void
89 575 : vat_plugin_hash_create (void)
90 : {
91 575 : vat_main_t *vam = &vat_main;
92 :
93 575 : vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
94 575 : vam->function_by_name = hash_create_string (0, sizeof (uword));
95 575 : vam->help_by_name = hash_create_string (0, sizeof (uword));
96 575 : }
97 :
98 : static void
99 2 : vat_register_interface_dump (vat_main_t *vam)
100 : {
101 : void *handle;
102 : plugin_info_t *pi;
103 :
104 24 : vec_foreach (pi, vat_plugin_main.plugin_info)
105 : {
106 24 : handle = dlsym (pi->handle, "api_sw_interface_dump");
107 24 : if (handle)
108 : {
109 2 : vam->api_sw_interface_dump = handle;
110 2 : break;
111 : }
112 : }
113 :
114 2 : if (!vam->api_sw_interface_dump)
115 : {
116 0 : fformat (stderr,
117 : "sw_interface_dump not found in interface_test plugin!\n");
118 0 : exit (1);
119 : }
120 2 : }
121 :
122 : static void
123 16 : maybe_register_api_client (vat_main_t * vam)
124 : {
125 : vl_api_registration_t **regpp;
126 : vl_api_registration_t *regp;
127 : void *oldheap;
128 16 : api_main_t *am = vlibapi_get_main ();
129 :
130 16 : if (vam->my_client_index != ~0)
131 14 : return;
132 :
133 2 : pool_get (am->vl_clients, regpp);
134 :
135 2 : oldheap = vl_msg_push_heap ();
136 :
137 2 : *regpp = clib_mem_alloc (sizeof (vl_api_registration_t));
138 :
139 2 : regp = *regpp;
140 2 : clib_memset (regp, 0, sizeof (*regp));
141 2 : regp->registration_type = REGISTRATION_TYPE_SHMEM;
142 2 : regp->vl_api_registration_pool_index = regpp - am->vl_clients;
143 2 : regp->vlib_rp = am->vlib_rp;
144 2 : regp->shmem_hdr = am->shmem_hdr;
145 :
146 : /* Loopback connection */
147 2 : regp->vl_input_queue = am->shmem_hdr->vl_input_queue;
148 :
149 2 : regp->name = format (0, "%s", "vpp-internal");
150 2 : vec_add1 (regp->name, 0);
151 :
152 2 : vl_msg_pop_heap (oldheap);
153 :
154 4 : vam->my_client_index = vl_msg_api_handle_from_index_and_epoch
155 : (regp->vl_api_registration_pool_index,
156 2 : am->shmem_hdr->application_restarts);
157 :
158 2 : vam->vl_input_queue = am->shmem_hdr->vl_input_queue;
159 2 : vat_register_interface_dump (vam);
160 2 : vam->api_sw_interface_dump (vam);
161 : }
162 :
163 : static clib_error_t *
164 16 : api_command_fn (vlib_main_t * vm,
165 : unformat_input_t * input, vlib_cli_command_t * cmd)
166 : {
167 16 : vat_main_t *vam = &vat_main;
168 : unformat_input_t _input;
169 : uword c;
170 : u8 *cmdp, *argsp, *this_cmd;
171 : uword *p;
172 : u32 arg_len;
173 : int rv;
174 : int (*fp) (vat_main_t *);
175 :
176 16 : maybe_register_api_client (vam);
177 :
178 : /* vec_validated in the init routine */
179 16 : vec_set_len (vam->inbuf, 0);
180 :
181 16 : vam->input = &_input;
182 :
183 1068 : while (((c = unformat_get_input (input)) != '\n') &&
184 : (c != UNFORMAT_END_OF_INPUT))
185 1052 : vec_add1 (vam->inbuf, c);
186 :
187 : /* Null-terminate the command */
188 16 : vec_add1 (vam->inbuf, 0);
189 :
190 : /* In case no args given */
191 16 : vec_add1 (vam->inbuf, 0);
192 :
193 : /* Split input into cmd + args */
194 16 : this_cmd = cmdp = vam->inbuf;
195 :
196 : /* Skip leading whitespace */
197 16 : while (cmdp < (this_cmd + vec_len (this_cmd)))
198 : {
199 16 : if (*cmdp == ' ' || *cmdp == '\t' || *cmdp == '\n')
200 : {
201 0 : cmdp++;
202 : }
203 : else
204 : break;
205 : }
206 :
207 16 : argsp = cmdp;
208 :
209 : /* Advance past the command */
210 369 : while (argsp < (this_cmd + vec_len (this_cmd)))
211 : {
212 369 : if (*argsp != ' ' && *argsp != '\t' && *argsp != '\n' && *argsp != 0)
213 : {
214 353 : argsp++;
215 : }
216 : else
217 : break;
218 : }
219 : /* NULL terminate the command */
220 16 : *argsp++ = 0;
221 :
222 : /* No arguments? Ensure that argsp points to a proper (empty) string */
223 16 : if (argsp == (this_cmd + vec_len (this_cmd) - 1))
224 0 : argsp[0] = 0;
225 : else
226 16 : while (argsp < (this_cmd + vec_len (this_cmd)))
227 : {
228 16 : if (*argsp == ' ' || *argsp == '\t' || *argsp == '\n')
229 : {
230 0 : argsp++;
231 : }
232 : else
233 : break;
234 : }
235 :
236 : /* Blank input line? */
237 16 : if (*cmdp == 0)
238 0 : return 0;
239 :
240 16 : p = hash_get_mem (vam->function_by_name, cmdp);
241 16 : if (p == 0)
242 : {
243 0 : return clib_error_return (0, "'%s': function not found\n", cmdp);
244 : }
245 :
246 16 : arg_len = strlen ((char *) argsp);
247 :
248 16 : unformat_init_string (vam->input, (char *) argsp, arg_len);
249 16 : fp = (void *) p[0];
250 :
251 16 : rv = (*fp) (vam);
252 :
253 16 : if (rv < 0)
254 : {
255 16 : unformat_free (vam->input);
256 16 : return clib_error_return (0,
257 : "%s error: %U\n", cmdp,
258 : format_api_error, vam, rv);
259 :
260 : }
261 0 : if (vam->regenerate_interface_table)
262 : {
263 0 : vam->regenerate_interface_table = 0;
264 0 : vam->api_sw_interface_dump (vam);
265 : }
266 0 : unformat_free (vam->input);
267 0 : return 0;
268 : }
269 :
270 : /* *INDENT-OFF* */
271 285289 : VLIB_CLI_COMMAND (api_command, static) =
272 : {
273 : .path = "binary-api",
274 : .short_help = "binary-api [help] <name> [<args>]",
275 : .function = api_command_fn,
276 : .is_mp_safe = 1,
277 : };
278 : /* *INDENT-ON* */
279 :
280 : void
281 0 : api_cli_output (void *notused, const char *fmt, ...)
282 : {
283 : va_list va;
284 0 : vat_main_t *vam = &vat_main;
285 0 : vlib_main_t *vm = vam->vlib_main;
286 0 : vlib_process_t *cp = vlib_get_current_process (vm);
287 : u8 *s;
288 :
289 0 : va_start (va, fmt);
290 0 : s = va_format (0, fmt, &va);
291 0 : va_end (va);
292 :
293 : /* Terminate with \n if not present. */
294 0 : if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n')
295 0 : vec_add1 (s, '\n');
296 :
297 0 : if ((!cp) || (!cp->output_function))
298 0 : fformat (stdout, "%v", s);
299 : else
300 0 : cp->output_function (cp->output_function_arg, s, vec_len (s));
301 :
302 0 : vec_free (s);
303 0 : }
304 :
305 : u16
306 31050 : vl_client_get_first_plugin_msg_id (const char *plugin_name)
307 : {
308 31050 : api_main_t *am = vlibapi_get_main ();
309 : vl_api_msg_range_t *rp;
310 : uword *p;
311 :
312 31050 : p = hash_get_mem (am->msg_range_by_name, plugin_name);
313 31050 : if (p == 0)
314 1725 : return ~0;
315 :
316 29325 : rp = vec_elt_at_index (am->msg_ranges, p[0]);
317 :
318 29325 : return (rp->first_msg_id);
319 : }
320 :
321 : uword
322 9 : unformat_sw_if_index (unformat_input_t * input, va_list * args)
323 : {
324 9 : void *vam_unused = va_arg (*args, void *);
325 : (void) (vam_unused);
326 9 : u32 *result = va_arg (*args, u32 *);
327 9 : vnet_main_t *vnm = vnet_get_main ();
328 9 : u32 sw_if_index = ~0;
329 :
330 9 : if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
331 : {
332 4 : *result = sw_if_index;
333 4 : return 1;
334 : }
335 5 : return 0;
336 : }
337 :
338 : /*
339 : * fd.io coding-style-patch-verification: ON
340 : *
341 : * Local Variables:
342 : * eval: (c-set-style "gnu")
343 : * End:
344 : */
|