misc: move part of vpe apis to vlibmemory
[vpp.git] / src / vlibmemory / vlibapi_test.c
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 vl_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
52 static void
53 vl_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
66 static void
67 vl_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
84 static void
85 vl_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
102 static void
103 vl_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
120 static void
121 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 }
126
127 static void
128 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 }
133
134 static int
135 api_get_f64_endian_value (vat_main_t *vam)
136 {
137   // not yet implemented
138   return -1;
139 }
140
141 static int
142 api_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  */
152 static int
153 exec_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 }
188 static int
189 api_cli_inband (vat_main_t *vam)
190 {
191   return exec_inband (vam);
192 }
193
194 int
195 exec (vat_main_t *vam)
196 {
197   return exec_inband (vam);
198 }
199
200 static int
201 api_cli (vat_main_t *vam)
202 {
203   return exec (vam);
204 }
205
206 static int
207 api_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
241 static int
242 api_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
290 static int
291 api_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
340 static void
341 vl_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
361 static int
362 api_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
377 static void
378 vl_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
437 static int
438 api_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
452 #define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table
453 static void
454 local_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  */