Make VPP runtime directory configurable
[vpp.git] / src / vpp / vnet / main.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vppinfra/cpu.h>
17 #include <vlib/vlib.h>
18 #include <vlib/unix/unix.h>
19 #include <vnet/plugin/plugin.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vpp/app/version.h>
22 #include <vpp/api/vpe_msg_enum.h>
23
24
25 static void
26 vpe_main_init (vlib_main_t * vm)
27 {
28   void vat_plugin_hash_create (void);
29
30   if (CLIB_DEBUG > 0)
31     vlib_unix_cli_set_prompt ("DBGvpp# ");
32   else
33     vlib_unix_cli_set_prompt ("vpp# ");
34
35   /* Turn off network stack components which we don't want */
36   vlib_mark_init_function_complete (vm, srp_init);
37
38   /*
39    * Create the binary api plugin hashes before loading plugins
40    */
41   vat_plugin_hash_create ();
42 }
43
44 /*
45  * Default path for runtime data
46  */
47 char *vlib_default_runtime_dir = "/run/vpp";
48
49 /*
50  * Load plugins from /usr/lib/vpp_plugins by default
51  */
52 char *vlib_plugin_path = "/usr/lib/vpp_plugins";
53 char *vlib_plugin_app_version = VPP_BUILD_VER;
54
55 int
56 main (int argc, char *argv[])
57 {
58   int i;
59   vlib_main_t *vm = &vlib_global_main;
60   void vl_msg_api_set_first_available_msg_id (u16);
61   uword main_heap_size = (1ULL << 30);
62   u8 *sizep;
63   u32 size;
64
65 #if __x86_64__
66   CLIB_UNUSED (const char *msg)
67     = "ERROR: This binary requires CPU with %s extensions.\n";
68 #define _(a,b)                                  \
69     if (!clib_cpu_supports_ ## a ())            \
70       {                                         \
71         fprintf(stderr, msg, b);                \
72         exit(1);                                \
73       }
74
75 #if __AVX2__
76   _(avx2, "AVX2")
77 #endif
78 #if __AVX__
79     _(avx, "AVX")
80 #endif
81 #if __SSE4_2__
82     _(sse42, "SSE4.2")
83 #endif
84 #if __SSE4_1__
85     _(sse41, "SSE4.1")
86 #endif
87 #if __SSSE3__
88     _(ssse3, "SSSE3")
89 #endif
90 #if __SSE3__
91     _(sse3, "SSE3")
92 #endif
93 #undef _
94 #endif
95     /*
96      * Load startup config from file.
97      * usage: vpp -c /etc/vpp/startup.conf
98      */
99     if ((argc == 3) && !strncmp (argv[1], "-c", 2))
100     {
101       FILE *fp;
102       char inbuf[4096];
103       int argc_ = 1;
104       char **argv_ = NULL;
105       char *arg = NULL;
106       char *p;
107
108       fp = fopen (argv[2], "r");
109       if (fp == NULL)
110         {
111           fprintf (stderr, "open configuration file '%s' failed\n", argv[2]);
112           return 1;
113         }
114       argv_ = calloc (1, sizeof (char *));
115       if (argv_ == NULL)
116         return 1;
117       arg = strndup (argv[0], 1024);
118       if (arg == NULL)
119         return 1;
120       argv_[0] = arg;
121
122       while (1)
123         {
124           if (fgets (inbuf, 4096, fp) == 0)
125             break;
126           p = strtok (inbuf, " \t\n");
127           while (p != NULL)
128             {
129               if (*p == '#')
130                 break;
131               argc_++;
132               char **tmp = realloc (argv_, argc_ * sizeof (char *));
133               if (tmp == NULL)
134                 return 1;
135               argv_ = tmp;
136               arg = strndup (p, 1024);
137               if (arg == NULL)
138                 return 1;
139               argv_[argc_ - 1] = arg;
140               p = strtok (NULL, " \t\n");
141             }
142         }
143
144       fclose (fp);
145
146       char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
147       if (tmp == NULL)
148         return 1;
149       argv_ = tmp;
150       argv_[argc_] = NULL;
151
152       argc = argc_;
153       argv = argv_;
154     }
155
156   /*
157    * Look for and parse the "heapsize" config parameter.
158    * Manual since none of the clib infra has been bootstrapped yet.
159    *
160    * Format: heapsize <nn>[mM][gG]
161    */
162
163   for (i = 1; i < (argc - 1); i++)
164     {
165       if (!strncmp (argv[i], "plugin_path", 11))
166         {
167           if (i < (argc - 1))
168             vlib_plugin_path = argv[++i];
169         }
170       else if (!strncmp (argv[i], "heapsize", 8))
171         {
172           sizep = (u8 *) argv[i + 1];
173           size = 0;
174           while (*sizep >= '0' && *sizep <= '9')
175             {
176               size *= 10;
177               size += *sizep++ - '0';
178             }
179           if (size == 0)
180             {
181               fprintf
182                 (stderr,
183                  "warning: heapsize parse error '%s', use default %lld\n",
184                  argv[i], (long long int) main_heap_size);
185               goto defaulted;
186             }
187
188           main_heap_size = size;
189
190           if (*sizep == 'g' || *sizep == 'G')
191             main_heap_size <<= 30;
192           else if (*sizep == 'm' || *sizep == 'M')
193             main_heap_size <<= 20;
194         }
195     }
196
197 defaulted:
198
199   /* Set up the plugin message ID allocator right now... */
200   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
201
202   /* Allocate main heap */
203   if (clib_mem_init (0, main_heap_size))
204     {
205       vm->init_functions_called = hash_create (0, /* value bytes */ 0);
206       vpe_main_init (vm);
207       return vlib_unix_main (argc, argv);
208     }
209   else
210     {
211       {
212         int rv __attribute__ ((unused)) =
213           write (2, "Main heap allocation failure!\r\n", 31);
214       }
215       return 1;
216     }
217 }
218
219 static clib_error_t *
220 heapsize_config (vlib_main_t * vm, unformat_input_t * input)
221 {
222   u32 junk;
223
224   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
225     {
226       if (unformat (input, "%dm", &junk)
227           || unformat (input, "%dM", &junk)
228           || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
229         return 0;
230       else
231         return clib_error_return (0, "unknown input '%U'",
232                                   format_unformat_error, input);
233     }
234   return 0;
235 }
236
237 VLIB_CONFIG_FUNCTION (heapsize_config, "heapsize");
238
239 static clib_error_t *
240 plugin_path_config (vlib_main_t * vm, unformat_input_t * input)
241 {
242   u8 *junk;
243
244   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
245     {
246       if (unformat (input, "%s", &junk))
247         {
248           vec_free (junk);
249           return 0;
250         }
251       else
252         return clib_error_return (0, "unknown input '%U'",
253                                   format_unformat_error, input);
254     }
255   return 0;
256 }
257
258 VLIB_CONFIG_FUNCTION (plugin_path_config, "plugin_path");
259
260 void vl_msg_api_post_mortem_dump (void);
261 void elog_post_mortem_dump (void);
262
263 void
264 os_panic (void)
265 {
266   vl_msg_api_post_mortem_dump ();
267   elog_post_mortem_dump ();
268   abort ();
269 }
270
271 void vhost_user_unmap_all (void) __attribute__ ((weak));
272 void
273 vhost_user_unmap_all (void)
274 {
275 }
276
277 void
278 os_exit (int code)
279 {
280   static int recursion_block;
281
282   if (code)
283     {
284       if (recursion_block)
285         abort ();
286
287       recursion_block = 1;
288
289       vl_msg_api_post_mortem_dump ();
290       elog_post_mortem_dump ();
291       vhost_user_unmap_all ();
292       abort ();
293     }
294   exit (code);
295 }
296
297 void
298 vl_msg_api_barrier_sync (void)
299 {
300   vlib_worker_thread_barrier_sync (vlib_get_main ());
301 }
302
303 void
304 vl_msg_api_barrier_release (void)
305 {
306   vlib_worker_thread_barrier_release (vlib_get_main ());
307 }
308
309 /* This application needs 1 thread stack for the stats pthread */
310 u32
311 vlib_app_num_thread_stacks_needed (void)
312 {
313   return 1;
314 }
315
316 /*
317  * Depending on the configuration selected above,
318  * it may be necessary to generate stub graph nodes.
319  * It is never OK to ignore "node 'x' refers to unknown node 'y'
320  * messages!
321  */
322
323 #if CLIB_DEBUG > 0
324
325 static clib_error_t *
326 test_crash_command_fn (vlib_main_t * vm,
327                        unformat_input_t * input, vlib_cli_command_t * cmd)
328 {
329   u64 *p = (u64 *) 0xdefec8ed;
330
331   ELOG_TYPE_DECLARE (e) =
332   {
333   .format = "deliberate crash: touching %x",.format_args = "i4",};
334
335   elog (&vm->elog_main, &e, 0xdefec8ed);
336
337   *p = 0xdeadbeef;
338
339   /* Not so much... */
340   return 0;
341 }
342
343 /* *INDENT-OFF* */
344 VLIB_CLI_COMMAND (test_crash_command, static) = {
345   .path = "test crash",
346   .short_help = "crash the bus!",
347   .function = test_crash_command_fn,
348 };
349 /* *INDENT-ON* */
350
351 #endif
352
353 /*
354  * fd.io coding-style-patch-verification: ON
355  *
356  * Local Variables:
357  * eval: (c-set-style "gnu")
358  * End:
359  */