blob: 820096ab80d9696a5bede73e27a616b21d389092 [file] [log] [blame]
Florin Coras248210c2021-09-14 18:54:45 -07001/*
2 *------------------------------------------------------------------
3 * Copyright (c) 2021 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
16 */
17
18#include <vat/vat.h>
19#include <vlibapi/api.h>
20#include <vlibmemory/api.h>
21#include <vppinfra/error.h>
22
23#include <vpp/api/types.h>
24#include <vnet/mpls/packet.h>
25#include <vnet/ip/ip_types_api.h>
26
27typedef struct
28{
29 u16 msg_id_base;
30 vat_main_t *vat_main;
31} vlib_test_main_t;
32vlib_test_main_t vlib_test_main;
33
34#define __plugin_msg_base vlib_test_main.msg_id_base
35#include <vlibapi/vat_helper_macros.h>
36
37/* Declare message IDs */
38#include <vlibmemory/vlib.api_enum.h>
39#include <vlibmemory/vlib.api_types.h>
40
41static void
42vl_api_cli_reply_t_handler (vl_api_cli_reply_t *mp)
43{
44 vat_main_t *vam = &vat_main;
45 i32 retval = ntohl (mp->retval);
46
47 vam->retval = retval;
48 vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
49 vam->result_ready = 1;
50}
51
52static void
53vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t *mp)
54{
55 vat_main_t *vam = &vat_main;
56 i32 retval = ntohl (mp->retval);
57
58 vec_reset_length (vam->cmd_reply);
59
60 vam->retval = retval;
61 if (retval == 0)
62 vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
63 vam->result_ready = 1;
64}
65
66static void
67vl_api_get_node_index_reply_t_handler (vl_api_get_node_index_reply_t *mp)
68{
69 vat_main_t *vam = &vat_main;
70 i32 retval = ntohl (mp->retval);
71 if (vam->async_mode)
72 {
73 vam->async_errors += (retval < 0);
74 }
75 else
76 {
77 vam->retval = retval;
78 if (retval == 0)
79 errmsg ("node index %d", ntohl (mp->node_index));
80 vam->result_ready = 1;
81 }
82}
83
84static void
85vl_api_get_next_index_reply_t_handler (vl_api_get_next_index_reply_t *mp)
86{
87 vat_main_t *vam = &vat_main;
88 i32 retval = ntohl (mp->retval);
89 if (vam->async_mode)
90 {
91 vam->async_errors += (retval < 0);
92 }
93 else
94 {
95 vam->retval = retval;
96 if (retval == 0)
97 errmsg ("next node index %d", ntohl (mp->next_index));
98 vam->result_ready = 1;
99 }
100}
101
102static void
103vl_api_add_node_next_reply_t_handler (vl_api_add_node_next_reply_t *mp)
104{
105 vat_main_t *vam = &vat_main;
106 i32 retval = ntohl (mp->retval);
107 if (vam->async_mode)
108 {
109 vam->async_errors += (retval < 0);
110 }
111 else
112 {
113 vam->retval = retval;
114 if (retval == 0)
115 errmsg ("next index %d", ntohl (mp->next_index));
116 vam->result_ready = 1;
117 }
118}
119
120static void
121vl_api_get_f64_endian_value_reply_t_handler (
122 vl_api_get_f64_endian_value_reply_t *mp)
123{
124 // not yet implemented
125}
126
127static void
128vl_api_get_f64_increment_by_one_reply_t_handler (
129 vl_api_get_f64_increment_by_one_reply_t *mp)
130{
131 // not yet implemented
132}
133
134static int
135api_get_f64_endian_value (vat_main_t *vam)
136{
137 // not yet implemented
138 return -1;
139}
140
141static int
142api_get_f64_increment_by_one (vat_main_t *vam)
143{
144 // not yet implemented
145 return -1;
146}
147
148/*
149 * Pass CLI buffers directly in the CLI_INBAND API message,
150 * instead of an additional shared memory area.
151 */
152static int
153exec_inband (vat_main_t *vam)
154{
155 vl_api_cli_inband_t *mp;
156 unformat_input_t *i = vam->input;
157 int ret;
158
159 if (vec_len (i->buffer) == 0)
160 return -1;
161
162 if (vam->exec_mode == 0 && unformat (i, "mode"))
163 {
164 vam->exec_mode = 1;
165 return 0;
166 }
167 if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
168 {
169 vam->exec_mode = 0;
170 return 0;
171 }
172
173 /*
174 * In order for the CLI command to work, it
175 * must be a vector ending in \n, not a C-string ending
176 * in \n\0.
177 */
178 M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
179 vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
180
181 S (mp);
182 W (ret);
183 /* json responses may or may not include a useful reply... */
184 if (vec_len (vam->cmd_reply))
185 print (vam->ofp, "%v", (char *) (vam->cmd_reply));
186 return ret;
187}
188static int
189api_cli_inband (vat_main_t *vam)
190{
191 return exec_inband (vam);
192}
193
194int
195exec (vat_main_t *vam)
196{
197 return exec_inband (vam);
198}
199
200static int
201api_cli (vat_main_t *vam)
202{
203 return exec (vam);
204}
205
206static int
207api_get_node_index (vat_main_t *vam)
208{
209 unformat_input_t *i = vam->input;
210 vl_api_get_node_index_t *mp;
211 u8 *name = 0;
212 int ret;
213
214 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
215 {
216 if (unformat (i, "node %s", &name))
217 ;
218 else
219 break;
220 }
221 if (name == 0)
222 {
223 errmsg ("node name required");
224 return -99;
225 }
226 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
227 {
228 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
229 return -99;
230 }
231
232 M (GET_NODE_INDEX, mp);
233 clib_memcpy (mp->node_name, name, vec_len (name));
234 vec_free (name);
235
236 S (mp);
237 W (ret);
238 return ret;
239}
240
241static int
242api_get_next_index (vat_main_t *vam)
243{
244 unformat_input_t *i = vam->input;
245 vl_api_get_next_index_t *mp;
246 u8 *node_name = 0, *next_node_name = 0;
247 int ret;
248
249 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
250 {
251 if (unformat (i, "node-name %s", &node_name))
252 ;
253 else if (unformat (i, "next-node-name %s", &next_node_name))
254 break;
255 }
256
257 if (node_name == 0)
258 {
259 errmsg ("node name required");
260 return -99;
261 }
262 if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
263 {
264 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
265 return -99;
266 }
267
268 if (next_node_name == 0)
269 {
270 errmsg ("next node name required");
271 return -99;
272 }
273 if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
274 {
275 errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
276 return -99;
277 }
278
279 M (GET_NEXT_INDEX, mp);
280 clib_memcpy (mp->node_name, node_name, vec_len (node_name));
281 clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
282 vec_free (node_name);
283 vec_free (next_node_name);
284
285 S (mp);
286 W (ret);
287 return ret;
288}
289
290static int
291api_add_node_next (vat_main_t *vam)
292{
293 unformat_input_t *i = vam->input;
294 vl_api_add_node_next_t *mp;
295 u8 *name = 0;
296 u8 *next = 0;
297 int ret;
298
299 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
300 {
301 if (unformat (i, "node %s", &name))
302 ;
303 else if (unformat (i, "next %s", &next))
304 ;
305 else
306 break;
307 }
308 if (name == 0)
309 {
310 errmsg ("node name required");
311 return -99;
312 }
313 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
314 {
315 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
316 return -99;
317 }
318 if (next == 0)
319 {
320 errmsg ("next node required");
321 return -99;
322 }
323 if (vec_len (next) >= ARRAY_LEN (mp->next_name))
324 {
325 errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
326 return -99;
327 }
328
329 M (ADD_NODE_NEXT, mp);
330 clib_memcpy (mp->node_name, name, vec_len (name));
331 clib_memcpy (mp->next_name, next, vec_len (next));
332 vec_free (name);
333 vec_free (next);
334
335 S (mp);
336 W (ret);
337 return ret;
338}
339
340static void
341vl_api_show_threads_reply_t_handler (vl_api_show_threads_reply_t *mp)
342{
343 vat_main_t *vam = &vat_main;
344 i32 retval = ntohl (mp->retval);
345 int i, count = 0;
346
347 if (retval >= 0)
348 count = ntohl (mp->count);
349
350 for (i = 0; i < count; i++)
351 print (vam->ofp, "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
352 ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
353 mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
354 ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
355 ntohl (mp->thread_data[i].cpu_socket));
356
357 vam->retval = retval;
358 vam->result_ready = 1;
359}
360
361static int
362api_show_threads (vat_main_t *vam)
363{
364 vl_api_show_threads_t *mp;
365 int ret;
366
367 print (vam->ofp, "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s", "ID", "Name",
368 "Type", "LWP", "cpu_id", "Core", "Socket");
369
370 M (SHOW_THREADS, mp);
371
372 S (mp);
373 W (ret);
374 return ret;
375}
376
377static void
378vl_api_get_node_graph_reply_t_handler (vl_api_get_node_graph_reply_t *mp)
379{
380 vat_main_t *vam = &vat_main;
381 i32 retval = ntohl (mp->retval);
382 u8 *pvt_copy, *reply;
383 void *oldheap;
384 vlib_node_t *node;
385 int i;
386
387 if (vam->async_mode)
388 {
389 vam->async_errors += (retval < 0);
390 }
391 else
392 {
393 vam->retval = retval;
394 vam->result_ready = 1;
395 }
396
397 /* "Should never happen..." */
398 if (retval != 0)
399 return;
400
401 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
402 pvt_copy = vec_dup (reply);
403
404 /* Toss the shared-memory original... */
405 oldheap = vl_msg_push_heap ();
406
407 vec_free (reply);
408
409 vl_msg_pop_heap (oldheap);
410
411 if (vam->graph_nodes)
412 {
413 hash_free (vam->graph_node_index_by_name);
414
415 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
416 {
417 node = vam->graph_nodes[0][i];
418 vec_free (node->name);
419 vec_free (node->next_nodes);
420 vec_free (node);
421 }
422 vec_free (vam->graph_nodes[0]);
423 vec_free (vam->graph_nodes);
424 }
425
426 vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
427 vam->graph_nodes = vlib_node_unserialize (pvt_copy);
428 vec_free (pvt_copy);
429
430 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
431 {
432 node = vam->graph_nodes[0][i];
433 hash_set_mem (vam->graph_node_index_by_name, node->name, i);
434 }
435}
436
437static int
438api_get_node_graph (vat_main_t *vam)
439{
440 vl_api_get_node_graph_t *mp;
441 int ret;
442
443 M (GET_NODE_GRAPH, mp);
444
445 /* send it... */
446 S (mp);
447 /* Wait for the reply */
448 W (ret);
449 return ret;
450}
451
Florin Coras248210c2021-09-14 18:54:45 -0700452#define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table
453static void
454local_setup_message_id_table (vat_main_t *vam)
455{
456 /* Add exec as an alias for cli_inband */
457 hash_set_mem (vam->function_by_name, "exec", api_cli_inband);
458 hash_set_mem (vam->help_by_name, "exec",
459 "usage: exec <vpe-debug-CLI-command>");
460}
461
462#include <vlibmemory/vlib.api_test.c>
463
464/*
465 * fd.io coding-style-patch-verification: ON
466 *
467 * Local Variables:
468 * eval: (c-set-style "gnu")
469 * End:
470 */