Line data Source code
1 : /*
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 :
27 : typedef struct
28 : {
29 : u16 msg_id_base;
30 : vat_main_t *vat_main;
31 : } vlib_test_main_t;
32 : vlib_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 :
41 : static void
42 0 : vl_api_cli_reply_t_handler (vl_api_cli_reply_t *mp)
43 : {
44 0 : vat_main_t *vam = &vat_main;
45 0 : i32 retval = ntohl (mp->retval);
46 :
47 0 : vam->retval = retval;
48 0 : vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
49 0 : vam->result_ready = 1;
50 0 : }
51 :
52 : static void
53 0 : vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t *mp)
54 : {
55 0 : vat_main_t *vam = &vat_main;
56 0 : i32 retval = ntohl (mp->retval);
57 :
58 0 : vec_reset_length (vam->cmd_reply);
59 :
60 0 : vam->retval = retval;
61 0 : if (retval == 0)
62 0 : vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
63 0 : vam->result_ready = 1;
64 0 : }
65 :
66 : static void
67 0 : vl_api_get_node_index_reply_t_handler (vl_api_get_node_index_reply_t *mp)
68 : {
69 0 : vat_main_t *vam = &vat_main;
70 0 : i32 retval = ntohl (mp->retval);
71 0 : if (vam->async_mode)
72 : {
73 0 : vam->async_errors += (retval < 0);
74 : }
75 : else
76 : {
77 0 : vam->retval = retval;
78 0 : if (retval == 0)
79 0 : errmsg ("node index %d", ntohl (mp->node_index));
80 0 : vam->result_ready = 1;
81 : }
82 0 : }
83 :
84 : static void
85 0 : vl_api_get_next_index_reply_t_handler (vl_api_get_next_index_reply_t *mp)
86 : {
87 0 : vat_main_t *vam = &vat_main;
88 0 : i32 retval = ntohl (mp->retval);
89 0 : if (vam->async_mode)
90 : {
91 0 : vam->async_errors += (retval < 0);
92 : }
93 : else
94 : {
95 0 : vam->retval = retval;
96 0 : if (retval == 0)
97 0 : errmsg ("next node index %d", ntohl (mp->next_index));
98 0 : vam->result_ready = 1;
99 : }
100 0 : }
101 :
102 : static void
103 0 : vl_api_add_node_next_reply_t_handler (vl_api_add_node_next_reply_t *mp)
104 : {
105 0 : vat_main_t *vam = &vat_main;
106 0 : i32 retval = ntohl (mp->retval);
107 0 : if (vam->async_mode)
108 : {
109 0 : vam->async_errors += (retval < 0);
110 : }
111 : else
112 : {
113 0 : vam->retval = retval;
114 0 : if (retval == 0)
115 0 : errmsg ("next index %d", ntohl (mp->next_index));
116 0 : vam->result_ready = 1;
117 : }
118 0 : }
119 :
120 : static void
121 0 : vl_api_get_f64_endian_value_reply_t_handler (
122 : vl_api_get_f64_endian_value_reply_t *mp)
123 : {
124 : // not yet implemented
125 0 : }
126 :
127 : static void
128 0 : vl_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 0 : }
133 :
134 : static int
135 0 : api_get_f64_endian_value (vat_main_t *vam)
136 : {
137 : // not yet implemented
138 0 : return -1;
139 : }
140 :
141 : static int
142 0 : api_get_f64_increment_by_one (vat_main_t *vam)
143 : {
144 : // not yet implemented
145 0 : 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 : */
152 : static int
153 0 : exec_inband (vat_main_t *vam)
154 : {
155 : vl_api_cli_inband_t *mp;
156 0 : unformat_input_t *i = vam->input;
157 : int ret;
158 :
159 0 : if (vec_len (i->buffer) == 0)
160 0 : return -1;
161 :
162 0 : if (vam->exec_mode == 0 && unformat (i, "mode"))
163 : {
164 0 : vam->exec_mode = 1;
165 0 : return 0;
166 : }
167 0 : if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
168 : {
169 0 : vam->exec_mode = 0;
170 0 : 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 0 : M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
179 0 : vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
180 :
181 0 : S (mp);
182 0 : W (ret);
183 : /* json responses may or may not include a useful reply... */
184 0 : if (vec_len (vam->cmd_reply))
185 0 : print (vam->ofp, "%v", (char *) (vam->cmd_reply));
186 0 : return ret;
187 : }
188 : static int
189 0 : api_cli_inband (vat_main_t *vam)
190 : {
191 0 : return exec_inband (vam);
192 : }
193 :
194 : int
195 0 : exec (vat_main_t *vam)
196 : {
197 0 : return exec_inband (vam);
198 : }
199 :
200 : static int
201 0 : api_cli (vat_main_t *vam)
202 : {
203 0 : return exec_inband (vam);
204 : }
205 :
206 : static int
207 0 : api_get_node_index (vat_main_t *vam)
208 : {
209 0 : unformat_input_t *i = vam->input;
210 : vl_api_get_node_index_t *mp;
211 0 : u8 *name = 0;
212 : int ret;
213 :
214 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
215 : {
216 0 : if (unformat (i, "node %s", &name))
217 : ;
218 : else
219 0 : break;
220 : }
221 0 : if (name == 0)
222 : {
223 0 : errmsg ("node name required");
224 0 : return -99;
225 : }
226 0 : if (vec_len (name) >= ARRAY_LEN (mp->node_name))
227 : {
228 0 : errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
229 0 : return -99;
230 : }
231 :
232 0 : M (GET_NODE_INDEX, mp);
233 0 : clib_memcpy (mp->node_name, name, vec_len (name));
234 0 : vec_free (name);
235 :
236 0 : S (mp);
237 0 : W (ret);
238 0 : return ret;
239 : }
240 :
241 : static int
242 0 : api_get_next_index (vat_main_t *vam)
243 : {
244 0 : unformat_input_t *i = vam->input;
245 : vl_api_get_next_index_t *mp;
246 0 : u8 *node_name = 0, *next_node_name = 0;
247 : int ret;
248 :
249 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
250 : {
251 0 : if (unformat (i, "node-name %s", &node_name))
252 : ;
253 0 : else if (unformat (i, "next-node-name %s", &next_node_name))
254 0 : break;
255 : }
256 :
257 0 : if (node_name == 0)
258 : {
259 0 : errmsg ("node name required");
260 0 : return -99;
261 : }
262 0 : if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
263 : {
264 0 : errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
265 0 : return -99;
266 : }
267 :
268 0 : if (next_node_name == 0)
269 : {
270 0 : errmsg ("next node name required");
271 0 : return -99;
272 : }
273 0 : if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
274 : {
275 0 : errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
276 0 : return -99;
277 : }
278 :
279 0 : M (GET_NEXT_INDEX, mp);
280 0 : clib_memcpy (mp->node_name, node_name, vec_len (node_name));
281 0 : clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
282 0 : vec_free (node_name);
283 0 : vec_free (next_node_name);
284 :
285 0 : S (mp);
286 0 : W (ret);
287 0 : return ret;
288 : }
289 :
290 : static int
291 0 : api_add_node_next (vat_main_t *vam)
292 : {
293 0 : unformat_input_t *i = vam->input;
294 : vl_api_add_node_next_t *mp;
295 0 : u8 *name = 0;
296 0 : u8 *next = 0;
297 : int ret;
298 :
299 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
300 : {
301 0 : if (unformat (i, "node %s", &name))
302 : ;
303 0 : else if (unformat (i, "next %s", &next))
304 : ;
305 : else
306 0 : break;
307 : }
308 0 : if (name == 0)
309 : {
310 0 : errmsg ("node name required");
311 0 : return -99;
312 : }
313 0 : if (vec_len (name) >= ARRAY_LEN (mp->node_name))
314 : {
315 0 : errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
316 0 : return -99;
317 : }
318 0 : if (next == 0)
319 : {
320 0 : errmsg ("next node required");
321 0 : return -99;
322 : }
323 0 : if (vec_len (next) >= ARRAY_LEN (mp->next_name))
324 : {
325 0 : errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
326 0 : return -99;
327 : }
328 :
329 0 : M (ADD_NODE_NEXT, mp);
330 0 : clib_memcpy (mp->node_name, name, vec_len (name));
331 0 : clib_memcpy (mp->next_name, next, vec_len (next));
332 0 : vec_free (name);
333 0 : vec_free (next);
334 :
335 0 : S (mp);
336 0 : W (ret);
337 0 : return ret;
338 : }
339 :
340 : static void
341 0 : vl_api_show_threads_reply_t_handler (vl_api_show_threads_reply_t *mp)
342 : {
343 0 : vat_main_t *vam = &vat_main;
344 0 : i32 retval = ntohl (mp->retval);
345 0 : int i, count = 0;
346 :
347 0 : if (retval >= 0)
348 0 : count = ntohl (mp->count);
349 :
350 0 : for (i = 0; i < count; i++)
351 0 : print (vam->ofp, "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
352 0 : ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
353 0 : 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 0 : vam->retval = retval;
358 0 : vam->result_ready = 1;
359 0 : }
360 :
361 : static int
362 0 : api_show_threads (vat_main_t *vam)
363 : {
364 : vl_api_show_threads_t *mp;
365 : int ret;
366 :
367 0 : print (vam->ofp, "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s", "ID", "Name",
368 : "Type", "LWP", "cpu_id", "Core", "Socket");
369 :
370 0 : M (SHOW_THREADS, mp);
371 :
372 0 : S (mp);
373 0 : W (ret);
374 0 : return ret;
375 : }
376 :
377 : static void
378 0 : vl_api_get_node_graph_reply_t_handler (vl_api_get_node_graph_reply_t *mp)
379 : {
380 0 : vat_main_t *vam = &vat_main;
381 0 : i32 retval = ntohl (mp->retval);
382 : u8 *pvt_copy, *reply;
383 : void *oldheap;
384 : vlib_node_t *node;
385 : int i;
386 :
387 0 : if (vam->async_mode)
388 : {
389 0 : vam->async_errors += (retval < 0);
390 : }
391 : else
392 : {
393 0 : vam->retval = retval;
394 0 : vam->result_ready = 1;
395 : }
396 :
397 : /* "Should never happen..." */
398 0 : if (retval != 0)
399 0 : return;
400 :
401 0 : reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
402 0 : pvt_copy = vec_dup (reply);
403 :
404 : /* Toss the shared-memory original... */
405 0 : oldheap = vl_msg_push_heap ();
406 :
407 0 : vec_free (reply);
408 :
409 0 : vl_msg_pop_heap (oldheap);
410 :
411 0 : if (vam->graph_nodes)
412 : {
413 0 : hash_free (vam->graph_node_index_by_name);
414 :
415 0 : for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
416 : {
417 0 : node = vam->graph_nodes[0][i];
418 0 : vec_free (node->name);
419 0 : vec_free (node->next_nodes);
420 0 : vec_free (node);
421 : }
422 0 : vec_free (vam->graph_nodes[0]);
423 0 : vec_free (vam->graph_nodes);
424 : }
425 :
426 0 : vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
427 0 : vam->graph_nodes = vlib_node_unserialize (pvt_copy);
428 0 : vec_free (pvt_copy);
429 :
430 0 : for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
431 : {
432 0 : node = vam->graph_nodes[0][i];
433 0 : hash_set_mem (vam->graph_node_index_by_name, node->name, i);
434 : }
435 : }
436 :
437 : static int
438 0 : api_get_node_graph (vat_main_t *vam)
439 : {
440 : vl_api_get_node_graph_t *mp;
441 : int ret;
442 :
443 0 : M (GET_NODE_GRAPH, mp);
444 :
445 : /* send it... */
446 0 : S (mp);
447 : /* Wait for the reply */
448 0 : W (ret);
449 0 : return ret;
450 : }
451 :
452 : #define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table
453 : static void
454 559 : local_setup_message_id_table (vat_main_t *vam)
455 : {
456 : /* Add exec as an alias for cli_inband */
457 1118 : hash_set_mem (vam->function_by_name, "exec", api_cli_inband);
458 1118 : hash_set_mem (vam->help_by_name, "exec",
459 : "usage: exec <vpe-debug-CLI-command>");
460 559 : }
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 : */
|