FD.io VPP  v18.11-rc0-18-g2a3fb1a
Vector Packet Processing
main.c
Go to the documentation of this file.
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 #define _GNU_SOURCE
17 #include <pthread.h>
18 #include <sched.h>
19 
20 #include <vppinfra/cpu.h>
21 #include <vlib/vlib.h>
22 #include <vlib/unix/unix.h>
23 #include <vnet/plugin/plugin.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vpp/app/version.h>
26 #include <vpp/api/vpe_msg_enum.h>
27 #include <limits.h>
28 
29 /*
30  * Load plugins from /usr/lib/vpp_plugins by default
31  */
32 char *vlib_plugin_path = "/usr/lib/vpp_plugins";
33 char *vlib_plugin_app_version = VPP_BUILD_VER;
34 
35 static void
37 {
38  extern char *vat_plugin_path;
39  char *p, path[PATH_MAX];
40  int rv;
41  u8 *s;
42 
43  /* find executable path */
44  if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1)
45  return;
46 
47  /* readlink doesn't provide null termination */
48  path[rv] = 0;
49 
50  /* strip filename */
51  if ((p = strrchr (path, '/')) == 0)
52  return;
53  *p = 0;
54 
55  /* strip bin/ */
56  if ((p = strrchr (path, '/')) == 0)
57  return;
58  *p = 0;
59 
60  s = format (0, "%s/lib/vpp_plugins", path);
61 #if uword_bits == 64
62  s = format (s, ":%s/lib64/vpp_plugins", path);
63 #endif
64  vec_add1 (s, 0);
65  vlib_plugin_path = (char *) s;
66 
67  s = format (0, "%s/lib/vpp_api_test_plugins", path);
68 #if uword_bits == 64
69  s = format (s, ":%s/lib64/vpp_api_test_plugins", path);
70 #endif
71  vec_add1 (s, 0);
72  vat_plugin_path = (char *) s;
73 }
74 
75 static void
77 {
78  void vat_plugin_hash_create (void);
79 
80  if (CLIB_DEBUG > 0)
81  vlib_unix_cli_set_prompt ("DBGvpp# ");
82  else
83  vlib_unix_cli_set_prompt ("vpp# ");
84 
85  /* Turn off network stack components which we don't want */
87 
88  /*
89  * Create the binary api plugin hashes before loading plugins
90  */
92 
94 }
95 
96 /*
97  * Default path for runtime data
98  */
100 
101 int
102 main (int argc, char *argv[])
103 {
104  int i;
107  uword main_heap_size = (1ULL << 30);
108  u8 *sizep;
109  u32 size;
110  int main_core = 1;
111  cpu_set_t cpuset;
112 
113 #if __x86_64__
114  CLIB_UNUSED (const char *msg)
115  = "ERROR: This binary requires CPU with %s extensions.\n";
116 #define _(a,b) \
117  if (!clib_cpu_supports_ ## a ()) \
118  { \
119  fprintf(stderr, msg, b); \
120  exit(1); \
121  }
122 
123 #if __AVX2__
124  _(avx2, "AVX2")
125 #endif
126 #if __AVX__
127  _(avx, "AVX")
128 #endif
129 #if __SSE4_2__
130  _(sse42, "SSE4.2")
131 #endif
132 #if __SSE4_1__
133  _(sse41, "SSE4.1")
134 #endif
135 #if __SSSE3__
136  _(ssse3, "SSSE3")
137 #endif
138 #if __SSE3__
139  _(sse3, "SSE3")
140 #endif
141 #undef _
142 #endif
143  /*
144  * Load startup config from file.
145  * usage: vpp -c /etc/vpp/startup.conf
146  */
147  if ((argc == 3) && !strncmp (argv[1], "-c", 2))
148  {
149  FILE *fp;
150  char inbuf[4096];
151  int argc_ = 1;
152  char **argv_ = NULL;
153  char *arg = NULL;
154  char *p;
155 
156  fp = fopen (argv[2], "r");
157  if (fp == NULL)
158  {
159  fprintf (stderr, "open configuration file '%s' failed\n", argv[2]);
160  return 1;
161  }
162  argv_ = calloc (1, sizeof (char *));
163  if (argv_ == NULL)
164  return 1;
165  arg = strndup (argv[0], 1024);
166  if (arg == NULL)
167  return 1;
168  argv_[0] = arg;
169 
170  while (1)
171  {
172  if (fgets (inbuf, 4096, fp) == 0)
173  break;
174  p = strtok (inbuf, " \t\n");
175  while (p != NULL)
176  {
177  if (*p == '#')
178  break;
179  argc_++;
180  char **tmp = realloc (argv_, argc_ * sizeof (char *));
181  if (tmp == NULL)
182  return 1;
183  argv_ = tmp;
184  arg = strndup (p, 1024);
185  if (arg == NULL)
186  return 1;
187  argv_[argc_ - 1] = arg;
188  p = strtok (NULL, " \t\n");
189  }
190  }
191 
192  fclose (fp);
193 
194  char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
195  if (tmp == NULL)
196  return 1;
197  argv_ = tmp;
198  argv_[argc_] = NULL;
199 
200  argc = argc_;
201  argv = argv_;
202  }
203 
204  /*
205  * Look for and parse the "heapsize" config parameter.
206  * Manual since none of the clib infra has been bootstrapped yet.
207  *
208  * Format: heapsize <nn>[mM][gG]
209  */
210 
211  for (i = 1; i < (argc - 1); i++)
212  {
213  if (!strncmp (argv[i], "plugin_path", 11))
214  {
215  if (i < (argc - 1))
216  vlib_plugin_path = argv[++i];
217  }
218  else if (!strncmp (argv[i], "heapsize", 8))
219  {
220  sizep = (u8 *) argv[i + 1];
221  size = 0;
222  while (*sizep >= '0' && *sizep <= '9')
223  {
224  size *= 10;
225  size += *sizep++ - '0';
226  }
227  if (size == 0)
228  {
229  fprintf
230  (stderr,
231  "warning: heapsize parse error '%s', use default %lld\n",
232  argv[i], (long long int) main_heap_size);
233  goto defaulted;
234  }
235 
236  main_heap_size = size;
237 
238  if (*sizep == 'g' || *sizep == 'G')
239  main_heap_size <<= 30;
240  else if (*sizep == 'm' || *sizep == 'M')
241  main_heap_size <<= 20;
242  }
243  else if (!strncmp (argv[i], "main-core", 9))
244  {
245  if (i < (argc - 1))
246  {
247  errno = 0;
248  unsigned long x = strtol (argv[++i], 0, 0);
249  if (errno == 0)
250  main_core = x;
251  }
252  }
253  }
254 
255 defaulted:
256 
257  /* set process affinity for main thread */
258  CPU_ZERO (&cpuset);
259  CPU_SET (main_core, &cpuset);
260  pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
261 
262  /* Set up the plugin message ID allocator right now... */
264 
265  /* Allocate main heap */
266  if (clib_mem_init (0, main_heap_size))
267  {
268  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
269  vpe_main_init (vm);
270  return vlib_unix_main (argc, argv);
271  }
272  else
273  {
274  {
275  int rv __attribute__ ((unused)) =
276  write (2, "Main heap allocation failure!\r\n", 31);
277  }
278  return 1;
279  }
280 }
281 
282 static clib_error_t *
284 {
285  u32 junk;
286 
288  {
289  if (unformat (input, "%dm", &junk)
290  || unformat (input, "%dM", &junk)
291  || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
292  return 0;
293  else
294  return clib_error_return (0, "unknown input '%U'",
295  format_unformat_error, input);
296  }
297  return 0;
298 }
299 
301 
302 static clib_error_t *
304 {
305  u8 *junk;
306 
308  {
309  if (unformat (input, "%s", &junk))
310  {
311  vec_free (junk);
312  return 0;
313  }
314  else
315  return clib_error_return (0, "unknown input '%U'",
316  format_unformat_error, input);
317  }
318  return 0;
319 }
320 
322 
323 void vl_msg_api_post_mortem_dump (void);
324 void elog_post_mortem_dump (void);
325 
326 void
327 os_panic (void)
328 {
331  abort ();
332 }
333 
334 void vhost_user_unmap_all (void) __attribute__ ((weak));
335 void
337 {
338 }
339 
340 void
341 os_exit (int code)
342 {
343  static int recursion_block;
344 
345  if (code)
346  {
347  if (recursion_block)
348  abort ();
349 
350  recursion_block = 1;
351 
355  abort ();
356  }
357  exit (code);
358 }
359 
360 #ifdef BARRIER_TRACING
361 void
362 vl_msg_api_barrier_trace_context (const char *context)
363 {
364  vlib_worker_threads[0].barrier_context = context;
365 }
366 #endif
367 
368 void
370 {
372 }
373 
374 void
376 {
378 }
379 
380 /* This application needs 1 thread stack for the stats pthread */
381 u32
383 {
384  return 1;
385 }
386 
387 /*
388  * Depending on the configuration selected above,
389  * it may be necessary to generate stub graph nodes.
390  * It is never OK to ignore "node 'x' refers to unknown node 'y'
391  * messages!
392  */
393 
394 #if CLIB_DEBUG > 0
395 
396 static clib_error_t *
398  unformat_input_t * input, vlib_cli_command_t * cmd)
399 {
400  u64 *p = (u64 *) 0xdefec8ed;
401 
402  ELOG_TYPE_DECLARE (e) =
403  {
404  .format = "deliberate crash: touching %x",.format_args = "i4",};
405 
406  elog (&vm->elog_main, &e, 0xdefec8ed);
407 
408  *p = 0xdeadbeef;
409 
410  /* Not so much... */
411  return 0;
412 }
413 
414 /* *INDENT-OFF* */
415 VLIB_CLI_COMMAND (test_crash_command, static) = {
416  .path = "test crash",
417  .short_help = "crash the bus!",
418  .function = test_crash_command_fn,
419 };
420 /* *INDENT-ON* */
421 
422 #endif
423 
424 /*
425  * fd.io coding-style-patch-verification: ON
426  *
427  * Local Variables:
428  * eval: (c-set-style "gnu")
429  * End:
430  */
int vlib_unix_main(int argc, char *argv[])
Definition: main.c:631
u32 vlib_app_num_thread_stacks_needed(void)
Definition: main.c:382
vlib_main_t vlib_global_main
Definition: main.c:1644
#define CLIB_UNUSED(x)
Definition: clib.h:79
void vl_msg_api_barrier_sync(void)
Definition: main.c:369
static clib_error_t * plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:303
unsigned long u64
Definition: types.h:89
#define NULL
Definition: clib.h:55
void vlib_unix_cli_set_prompt(char *prompt)
Set the CLI prompt.
Definition: cli.c:3054
static clib_error_t * heapsize_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:283
#define vlib_mark_init_function_complete(vm, x)
Definition: init.h:241
void vhost_user_unmap_all(void)
Definition: main.c:336
char * vat_plugin_path
Definition: plugin.c:183
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define vl_msg_api_barrier_trace_context(X)
Definition: api_common.h:167
unsigned char u8
Definition: types.h:56
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:212
char * vlib_default_runtime_dir
Definition: main.c:59
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
void os_exit(int code)
Definition: main.c:341
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:920
void vl_msg_api_post_mortem_dump(void)
Definition: api_shared.c:794
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
uword size
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:164
void elog_post_mortem_dump(void)
Definition: main.c:706
static void elog(elog_main_t *em, elog_event_type_t *type, u32 data)
Log a single-datum event.
Definition: elog.h:364
uword * init_functions_called
Definition: main.h:173
void * clib_mem_init(void *heap, uword size)
Definition: mem_mheap.c:60
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
char * vlib_plugin_path
Definition: main.c:32
static clib_error_t * test_crash_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:397
elog_main_t elog_main
Definition: main.h:158
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:439
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define hash_create(elts, value_bytes)
Definition: hash.h:696
void vat_plugin_hash_create(void)
Definition: api_main.c:65
void vl_msg_api_barrier_release(void)
Definition: main.c:375
static void vpe_main_init(vlib_main_t *vm)
Definition: main.c:76
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
static void vpp_find_plugin_path()
Definition: main.c:36
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1513
int main(int argc, char *argv[])
Definition: main.c:102
char * vlib_plugin_app_version
Definition: main.c:33
void os_panic(void)
Definition: main.c:327
void vl_msg_api_set_first_available_msg_id(u16 first_avail)
Definition: api_shared.c:864
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170