a252b84663a1b40a174c4de36f6e92b92707e7a2
[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
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
43 void *
44 vnet_get_handoff_structure (void)
45 {
46   static vnet_plugin_handoff_t _rv, *rv = &_rv;
47
48   rv->vnet_main = vnet_get_main ();
49   rv->ethernet_main = &ethernet_main;
50   return (void *) rv;
51 }
52
53 int
54 main (int argc, char *argv[])
55 {
56   int i;
57   vlib_main_t *vm = &vlib_global_main;
58   void vl_msg_api_set_first_available_msg_id (u16);
59   uword main_heap_size = (1ULL << 30);
60   u8 *sizep;
61   u32 size;
62   void vlib_set_get_handoff_structure_cb (void *cb);
63
64 #if __x86_64__
65   CLIB_UNUSED (const char *msg)
66     = "ERROR: This binary requires CPU with %s extensions.\n";
67 #define _(a,b)                                  \
68     if (!clib_cpu_supports_ ## a ())            \
69       {                                         \
70         fprintf(stderr, msg, b);                \
71         exit(1);                                \
72       }
73
74 #if __AVX2__
75   _(avx2, "AVX2")
76 #endif
77 #if __AVX__
78     _(avx, "AVX")
79 #endif
80 #if __SSE4_2__
81     _(sse42, "SSE4.2")
82 #endif
83 #if __SSE4_1__
84     _(sse41, "SSE4.1")
85 #endif
86 #if __SSSE3__
87     _(ssse3, "SSSE3")
88 #endif
89 #if __SSE3__
90     _(sse3, "SSE3")
91 #endif
92 #undef _
93 #endif
94     /*
95      * Load startup config from file.
96      * usage: vpp -c /etc/vpp/startup.conf
97      */
98     if ((argc == 3) && !strncmp (argv[1], "-c", 2))
99     {
100       FILE *fp;
101       char inbuf[4096];
102       int argc_ = 1;
103       char **argv_ = NULL;
104       char *arg = NULL;
105       char *p;
106
107       fp = fopen (argv[2], "r");
108       if (fp == NULL)
109         {
110           fprintf (stderr, "open configuration file '%s' failed\n", argv[2]);
111           return 1;
112         }
113       argv_ = calloc (1, sizeof (char *));
114       if (argv_ == NULL)
115         return 1;
116       arg = strndup (argv[0], 1024);
117       if (arg == NULL)
118         return 1;
119       argv_[0] = arg;
120
121       while (1)
122         {
123           if (fgets (inbuf, 4096, fp) == 0)
124             break;
125           p = strtok (inbuf, " \t\n");
126           while (p != NULL)
127             {
128               if (*p == '#')
129                 break;
130               argc_++;
131               char **tmp = realloc (argv_, argc_ * sizeof (char *));
132               if (tmp == NULL)
133                 return 1;
134               argv_ = tmp;
135               arg = strndup (p, 1024);
136               if (arg == NULL)
137                 return 1;
138               argv_[argc_ - 1] = arg;
139               p = strtok (NULL, " \t\n");
140             }
141         }
142
143       fclose (fp);
144
145       char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
146       if (tmp == NULL)
147         return 1;
148       argv_ = tmp;
149       argv_[argc_] = NULL;
150
151       argc = argc_;
152       argv = argv_;
153     }
154
155   /*
156    * Look for and parse the "heapsize" config parameter.
157    * Manual since none of the clib infra has been bootstrapped yet.
158    *
159    * Format: heapsize <nn>[mM][gG]
160    */
161
162   for (i = 1; i < (argc - 1); i++)
163     {
164       if (!strncmp (argv[i], "plugin_path", 11))
165         {
166           if (i < (argc - 1))
167             vlib_plugin_path = argv[++i];
168         }
169       else if (!strncmp (argv[i], "heapsize", 8))
170         {
171           sizep = (u8 *) argv[i + 1];
172           size = 0;
173           while (*sizep >= '0' && *sizep <= '9')
174             {
175               size *= 10;
176               size += *sizep++ - '0';
177             }
178           if (size == 0)
179             {
180               fprintf
181                 (stderr,
182                  "warning: heapsize parse error '%s', use default %lld\n",
183                  argv[i], (long long int) main_heap_size);
184               goto defaulted;
185             }
186
187           main_heap_size = size;
188
189           if (*sizep == 'g' || *sizep == 'G')
190             main_heap_size <<= 30;
191           else if (*sizep == 'm' || *sizep == 'M')
192             main_heap_size <<= 20;
193         }
194     }
195
196 defaulted:
197
198   /* Set up the plugin message ID allocator right now... */
199   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
200
201   /* Allocate main heap */
202   if (clib_mem_init (0, main_heap_size))
203     {
204       vm->init_functions_called = hash_create (0, /* value bytes */ 0);
205       vpe_main_init (vm);
206 #if DPDK == 0
207       unix_physmem_init (vm, 0 /* fail_if_physical_memory_not_present */ );
208 #endif
209       vlib_set_get_handoff_structure_cb (&vnet_get_handoff_structure);
210       return vlib_unix_main (argc, argv);
211     }
212   else
213     {
214       {
215         int rv __attribute__ ((unused)) =
216           write (2, "Main heap allocation failure!\r\n", 31);
217       }
218       return 1;
219     }
220 }
221
222 static clib_error_t *
223 heapsize_config (vlib_main_t * vm, unformat_input_t * input)
224 {
225   u32 junk;
226
227   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
228     {
229       if (unformat (input, "%dm", &junk)
230           || unformat (input, "%dM", &junk)
231           || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
232         return 0;
233       else
234         return clib_error_return (0, "unknown input '%U'",
235                                   format_unformat_error, input);
236     }
237   return 0;
238 }
239
240 VLIB_CONFIG_FUNCTION (heapsize_config, "heapsize");
241
242 static clib_error_t *
243 plugin_path_config (vlib_main_t * vm, unformat_input_t * input)
244 {
245   u8 *junk;
246
247   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
248     {
249       if (unformat (input, "%s", &junk))
250         {
251           vec_free (junk);
252           return 0;
253         }
254       else
255         return clib_error_return (0, "unknown input '%U'",
256                                   format_unformat_error, input);
257     }
258   return 0;
259 }
260
261 VLIB_CONFIG_FUNCTION (plugin_path_config, "plugin_path");
262
263 void vl_msg_api_post_mortem_dump (void);
264
265 void
266 os_panic (void)
267 {
268   vl_msg_api_post_mortem_dump ();
269   abort ();
270 }
271
272 void vhost_user_unmap_all (void) __attribute__ ((weak));
273 void
274 vhost_user_unmap_all (void)
275 {
276 }
277
278 void
279 os_exit (int code)
280 {
281   static int recursion_block;
282
283   if (code)
284     {
285       if (recursion_block)
286         abort ();
287
288       recursion_block = 1;
289
290       vl_msg_api_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   *p = 0xdeadbeef;
332
333   /* Not so much... */
334   return 0;
335 }
336
337 /* *INDENT-OFF* */
338 VLIB_CLI_COMMAND (test_crash_command, static) = {
339   .path = "test crash",
340   .short_help = "crash the bus!",
341   .function = test_crash_command_fn,
342 };
343 /* *INDENT-ON* */
344
345 #endif
346
347 /*
348  * fd.io coding-style-patch-verification: ON
349  *
350  * Local Variables:
351  * eval: (c-set-style "gnu")
352  * End:
353  */