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