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