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