FD.io VPP  v20.05-21-gb1500e9ff
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 <vlib/threads.h>
24 #include <vnet/plugin/plugin.h>
25 #include <vnet/ethernet/ethernet.h>
26 #include <vpp/app/version.h>
27 #include <vpp/api/vpe_msg_enum.h>
28 #include <limits.h>
29 
30 /*
31  * Load plugins from /usr/lib/vpp_plugins by default
32  */
33 char *vlib_plugin_path = NULL;
34 char *vlib_plugin_app_version = VPP_BUILD_VER;
35 char *vat_plugin_path = NULL;
36 
37 static void
39 {
40  extern char *vat_plugin_path;
41  char *p, path[PATH_MAX];
42  int rv;
43  u8 *s;
44 
45  /* find executable path */
46  if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1)
47  return;
48 
49  /* readlink doesn't provide null termination */
50  path[rv] = 0;
51 
52  /* strip filename */
53  if ((p = strrchr (path, '/')) == 0)
54  return;
55  *p = 0;
56 
57  /* strip bin/ */
58  if ((p = strrchr (path, '/')) == 0)
59  return;
60  *p = 0;
61 
62  s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vpp_plugins:"
63  "%s/lib/vpp_plugins", path, path);
64  vec_add1 (s, 0);
65  vlib_plugin_path = (char *) s;
66 
67  s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vpp_api_test_plugins:"
68  "%s/lib/vpp_api_test_plugins", path, path);
69  vec_add1 (s, 0);
70  vat_plugin_path = (char *) s;
71 }
72 
73 static void
75 {
76  void vat_plugin_hash_create (void);
77 
78  if (CLIB_DEBUG > 0)
79  vlib_unix_cli_set_prompt ("DBGvpp# ");
80  else
81  vlib_unix_cli_set_prompt ("vpp# ");
82 
83  /* Turn off network stack components which we don't want */
85 
86  /*
87  * Create the binary api plugin hashes before loading plugins
88  */
90 
91  if (!vlib_plugin_path)
93 }
94 
95 /*
96  * Default path for runtime data
97  */
99 
100 int
101 main (int argc, char *argv[])
102 {
103  int i;
106  uword main_heap_size = (1ULL << 30);
107  u8 *sizep;
108  u32 size;
109  int main_core = 1;
110  cpu_set_t cpuset;
111  void *main_heap;
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  {
165  fclose (fp);
166  return 1;
167  }
168  arg = strndup (argv[0], 1024);
169  if (arg == NULL)
170  {
171  fclose (fp);
172  free (argv_);
173  return 1;
174  }
175  argv_[0] = arg;
176 
177  while (1)
178  {
179  if (fgets (inbuf, 4096, fp) == 0)
180  break;
181  p = strtok (inbuf, " \t\n");
182  while (p != NULL)
183  {
184  if (*p == '#')
185  break;
186  argc_++;
187  char **tmp = realloc (argv_, argc_ * sizeof (char *));
188  if (tmp == NULL)
189  return 1;
190  argv_ = tmp;
191  arg = strndup (p, 1024);
192  if (arg == NULL)
193  return 1;
194  argv_[argc_ - 1] = arg;
195  p = strtok (NULL, " \t\n");
196  }
197  }
198 
199  fclose (fp);
200 
201  char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
202  if (tmp == NULL)
203  return 1;
204  argv_ = tmp;
205  argv_[argc_] = NULL;
206 
207  argc = argc_;
208  argv = argv_;
209  }
210 
211  /*
212  * Look for and parse the "heapsize" config parameter.
213  * Manual since none of the clib infra has been bootstrapped yet.
214  *
215  * Format: heapsize <nn>[mM][gG]
216  */
217 
218  for (i = 1; i < (argc - 1); i++)
219  {
220  if (!strncmp (argv[i], "plugin_path", 11))
221  {
222  if (i < (argc - 1))
223  vlib_plugin_path = argv[++i];
224  }
225  if (!strncmp (argv[i], "test_plugin_path", 16))
226  {
227  if (i < (argc - 1))
228  vat_plugin_path = argv[++i];
229  }
230  else if (!strncmp (argv[i], "heapsize", 8))
231  {
232  sizep = (u8 *) argv[i + 1];
233  size = 0;
234  while (*sizep >= '0' && *sizep <= '9')
235  {
236  size *= 10;
237  size += *sizep++ - '0';
238  }
239  if (size == 0)
240  {
241  fprintf
242  (stderr,
243  "warning: heapsize parse error '%s', use default %lld\n",
244  argv[i], (long long int) main_heap_size);
245  goto defaulted;
246  }
247 
248  main_heap_size = size;
249 
250  if (*sizep == 'g' || *sizep == 'G')
251  main_heap_size <<= 30;
252  else if (*sizep == 'm' || *sizep == 'M')
253  main_heap_size <<= 20;
254  }
255  else if (!strncmp (argv[i], "main-core", 9))
256  {
257  if (i < (argc - 1))
258  {
259  errno = 0;
260  unsigned long x = strtol (argv[++i], 0, 0);
261  if (errno == 0)
262  main_core = x;
263  }
264  }
265  }
266 
267 defaulted:
268 
269  /* set process affinity for main thread */
270  CPU_ZERO (&cpuset);
271  CPU_SET (main_core, &cpuset);
272  pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
273 
274  /* Set up the plugin message ID allocator right now... */
276 
277  /* Allocate main heap */
278  if ((main_heap = clib_mem_init_thread_safe (0, main_heap_size)))
279  {
281 
282  /* Figure out which numa runs the main thread */
283  vlib_get_thread_core_numa (&tmp, main_core);
284  __os_numa_index = tmp.numa_id;
285 
286  /* and use the main heap as that numa's numa heap */
287  clib_mem_set_per_numa_heap (main_heap);
288 
289  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
290  vpe_main_init (vm);
291  return vlib_unix_main (argc, argv);
292  }
293  else
294  {
295  {
296  int rv __attribute__ ((unused)) =
297  write (2, "Main heap allocation failure!\r\n", 31);
298  }
299  return 1;
300  }
301 }
302 
303 static clib_error_t *
305 {
306  u32 junk;
307 
309  {
310  if (unformat (input, "%dm", &junk)
311  || unformat (input, "%dM", &junk)
312  || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
313  return 0;
314  else
315  return clib_error_return (0, "unknown input '%U'",
316  format_unformat_error, input);
317  }
318  return 0;
319 }
320 
322 
323 static clib_error_t *
325 {
326  u8 *junk;
327 
329  {
330  if (unformat (input, "%s", &junk))
331  {
332  vec_free (junk);
333  return 0;
334  }
335  else
336  return clib_error_return (0, "unknown input '%U'",
337  format_unformat_error, input);
338  }
339  return 0;
340 }
341 
342 static clib_error_t *
344 {
345  return dummy_path_config (vm, input);
346 }
347 
349 
350 static clib_error_t *
352 {
353  return dummy_path_config (vm, input);
354 }
355 
356 VLIB_CONFIG_FUNCTION (test_plugin_path_config, "test_plugin_path");
357 
358 void vl_msg_api_post_mortem_dump (void);
359 void elog_post_mortem_dump (void);
360 
361 void
362 os_panic (void)
363 {
366  abort ();
367 }
368 
369 void vhost_user_unmap_all (void) __attribute__ ((weak));
370 void
372 {
373 }
374 
375 void
376 os_exit (int code)
377 {
378  static int recursion_block;
379 
380  if (code)
381  {
382  if (recursion_block)
383  abort ();
384 
385  recursion_block = 1;
386 
390  abort ();
391  }
392  exit (code);
393 }
394 
395 #ifdef BARRIER_TRACING
396 void
397 vl_msg_api_barrier_trace_context (const char *context)
398 {
400 }
401 #endif
402 
403 void
405 {
407 }
408 
409 void
411 {
413 }
414 
415 /* This application needs 1 thread stack for the stats pthread */
416 u32
418 {
419  return 1;
420 }
421 
422 /*
423  * Depending on the configuration selected above,
424  * it may be necessary to generate stub graph nodes.
425  * It is never OK to ignore "node 'x' refers to unknown node 'y'
426  * messages!
427  */
428 
429 #include <vppinfra/bihash_8_8.h>
430 
431 typedef struct
432 {
436 } name_sort_t;
437 
438 static int
439 name_sort_cmp (void *a1, void *a2)
440 {
441  name_sort_t *n1 = a1;
442  name_sort_t *n2 = a2;
443 
444  return strcmp ((char *) n1->name, (char *) n2->name);
445 }
446 
447 static clib_error_t *
449  unformat_input_t * input, vlib_cli_command_t * cmd)
450 {
451  int i;
452  clib_bihash_8_8_t *h;
453  u64 total_actual_virt_size = 0;
454  u64 total_configured_virt_size = 0;
455  u64 actual_virt_size;
456  u64 configured_virt_size;
457  name_sort_t *names = 0;
458  name_sort_t *this;
459  int verbose = 0;
460 
461  if (unformat (input, "verbose"))
462  verbose = 1;
463 
464  for (i = 0; i < vec_len (clib_all_bihashes); i++)
465  {
466  h = (clib_bihash_8_8_t *) clib_all_bihashes[i];
467  if (alloc_arena (h) || verbose)
468  {
469  vec_add2 (names, this, 1);
470  this->name = format (0, "%s%c", h->name, 0);
471  configured_virt_size = h->memory_size;
472  actual_virt_size = alloc_arena (h) ? h->memory_size : 0ULL;
473  this->actual_virt_size = actual_virt_size;
474  this->configured_virt_size = configured_virt_size;
475  total_actual_virt_size += actual_virt_size;
476  total_configured_virt_size += configured_virt_size;
477  }
478  }
479 
481 
482  vlib_cli_output (vm, "%-30s %8s %s", "Name", "Actual", "Configured");
483 
484  for (i = 0; i < vec_len (names); i++)
485  {
486  vlib_cli_output (vm, "%-30s %8U %U", names[i].name,
488  names[i].actual_virt_size,
489  format_memory_size, names[i].configured_virt_size);
490  vec_free (names[i].name);
491  }
492 
493  vec_free (names);
494 
495  vlib_cli_output (vm, "%-30s %8U %U", "Total",
496  format_memory_size, total_actual_virt_size,
497  format_memory_size, total_configured_virt_size);
498  return 0;
499 }
500 
501 /* *INDENT-OFF* */
502 VLIB_CLI_COMMAND (show_bihash_command, static) =
503 {
504  .path = "show bihash",
505  .short_help = "show bihash",
506  .function = show_bihash_command_fn,
507 };
508 /* *INDENT-ON* */
509 
510 #ifdef CLIB_SANITIZE_ADDR
511 /* default options for Address Sanitizer */
512 const char *
513 __asan_default_options (void)
514 {
515  return
516  "unmap_shadow_on_exit=1:disable_coredump=0:abort_on_error=1:detect_leaks=0";
517 }
518 #endif /* CLIB_SANITIZE_ADDR */
519 
520 /*
521  * fd.io coding-style-patch-verification: ON
522  *
523  * Local Variables:
524  * eval: (c-set-style "gnu")
525  * End:
526  */
int vlib_unix_main(int argc, char *argv[])
Definition: main.c:682
u32 vlib_app_num_thread_stacks_needed(void)
Definition: main.c:417
vlib_main_t vlib_global_main
Definition: main.c:1999
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:864
#define CLIB_UNUSED(x)
Definition: clib.h:86
void vlib_unix_cli_set_prompt(char *prompt)
Set the CLI prompt.
Definition: cli.c:3231
void vl_msg_api_barrier_sync(void)
Definition: main.c:404
static clib_error_t * plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:343
unsigned long u64
Definition: types.h:89
static clib_error_t * heapsize_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:304
#define vlib_mark_init_function_complete(vm, x)
Definition: init.h:284
void vhost_user_unmap_all(void)
Definition: main.c:371
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
static clib_error_t * test_plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:351
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vl_api_fib_path_t path
Definition: mfib_types.api:34
#define vl_msg_api_barrier_trace_context(X)
Definition: api_common.h:190
char * vat_plugin_path
Definition: main.c:35
unsigned char u8
Definition: types.h:56
static clib_error_t * show_bihash_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:448
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:204
char * vlib_default_runtime_dir
Definition: main.c:59
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:209
#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:376
void vl_msg_api_post_mortem_dump(void)
Definition: api_shared.c:923
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:34
static int name_sort_cmp(void *a1, void *a2)
Definition: main.c:439
const char * barrier_context
Definition: threads.h:107
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u64 size
Definition: vhost_user.h:150
vec_header_t h
Definition: buffer.c:322
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:182
void elog_post_mortem_dump(void)
Definition: main.c:777
uword * init_functions_called
Definition: main.h:215
vlib_main_t * vm
Definition: in2out_ed.c:1599
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
char * vlib_plugin_path
Definition: main.c:33
static clib_error_t * dummy_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:324
string name[64]
Definition: ip.api:44
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
#define hash_create(elts, value_bytes)
Definition: hash.h:696
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
void vat_plugin_hash_create(void)
Definition: api_main.c:65
void vl_msg_api_barrier_release(void)
Definition: main.c:410
static void vpe_main_init(vlib_main_t *vm)
Definition: main.c:74
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
void vlib_get_thread_core_numa(vlib_worker_thread_t *w, unsigned cpu_id)
Definition: threads.c:592
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1053
static void vpp_find_plugin_path()
Definition: main.c:38
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:1540
int main(int argc, char *argv[])
Definition: main.c:101
u64 actual_virt_size
Definition: main.c:434
void ** clib_all_bihashes
char * vlib_plugin_app_version
Definition: main.c:34
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
Definition: mem_dlmalloc.c:235
void os_panic(void)
Definition: main.c:362
u8 * name
Definition: main.c:433
u64 configured_virt_size
Definition: main.c:435
void vl_msg_api_set_first_available_msg_id(u16 first_avail)
Definition: api_shared.c:993
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static void * clib_mem_set_per_numa_heap(u8 *new_heap)
Definition: mem.h:88
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171