FD.io VPP  v20.09-rc2-28-g3c5414029
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/vnet/config.h>
28 #include <vpp/api/vpe_msg_enum.h>
29 #include <limits.h>
30 
31 /*
32  * Load plugins from /usr/lib/vpp_plugins by default
33  */
34 char *vlib_plugin_path = NULL;
35 char *vlib_plugin_app_version = VPP_BUILD_VER;
36 char *vat_plugin_path = NULL;
37 
38 static void
40 {
41  extern char *vat_plugin_path;
42  char *p, path[PATH_MAX];
43  int rv;
44  u8 *s;
45 
46  /* find executable path */
47  if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1)
48  return;
49 
50  /* readlink doesn't provide null termination */
51  path[rv] = 0;
52 
53  /* strip filename */
54  if ((p = strrchr (path, '/')) == 0)
55  return;
56  *p = 0;
57 
58  /* strip bin/ */
59  if ((p = strrchr (path, '/')) == 0)
60  return;
61  *p = 0;
62 
63  s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vpp_plugins:"
64  "%s/lib/vpp_plugins", path, path);
65  vec_add1 (s, 0);
66  vlib_plugin_path = (char *) s;
67 
68  s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vpp_api_test_plugins:"
69  "%s/lib/vpp_api_test_plugins", path, path);
70  vec_add1 (s, 0);
71  vat_plugin_path = (char *) s;
72 }
73 
74 static void
76 {
77 #if VPP_API_TEST_BUILTIN > 0
78  void vat_plugin_hash_create (void);
79 #endif
80 
81  if (CLIB_DEBUG > 0)
82  vlib_unix_cli_set_prompt ("DBGvpp# ");
83  else
84  vlib_unix_cli_set_prompt ("vpp# ");
85 
86  /* Turn off network stack components which we don't want */
88 
89  /*
90  * Create the binary api plugin hashes before loading plugins
91  */
92 #if VPP_API_TEST_BUILTIN > 0
94 #endif
95 
96  if (!vlib_plugin_path)
98 }
99 
100 /*
101  * Default path for runtime data
102  */
104 
105 int
106 main (int argc, char *argv[])
107 {
108  int i;
111  uword main_heap_size = (1ULL << 30);
112  u8 *sizep;
113  u32 size;
114  int main_core = 1;
115  cpu_set_t cpuset;
116  void *main_heap;
117 
118 #if __x86_64__
119  CLIB_UNUSED (const char *msg)
120  = "ERROR: This binary requires CPU with %s extensions.\n";
121 #define _(a,b) \
122  if (!clib_cpu_supports_ ## a ()) \
123  { \
124  fprintf(stderr, msg, b); \
125  exit(1); \
126  }
127 
128 #if __AVX2__
129  _(avx2, "AVX2")
130 #endif
131 #if __AVX__
132  _(avx, "AVX")
133 #endif
134 #if __SSE4_2__
135  _(sse42, "SSE4.2")
136 #endif
137 #if __SSE4_1__
138  _(sse41, "SSE4.1")
139 #endif
140 #if __SSSE3__
141  _(ssse3, "SSSE3")
142 #endif
143 #if __SSE3__
144  _(sse3, "SSE3")
145 #endif
146 #undef _
147 #endif
148  /*
149  * Load startup config from file.
150  * usage: vpp -c /etc/vpp/startup.conf
151  */
152  if ((argc == 3) && !strncmp (argv[1], "-c", 2))
153  {
154  FILE *fp;
155  char inbuf[4096];
156  int argc_ = 1;
157  char **argv_ = NULL;
158  char *arg = NULL;
159  char *p;
160 
161  fp = fopen (argv[2], "r");
162  if (fp == NULL)
163  {
164  fprintf (stderr, "open configuration file '%s' failed\n", argv[2]);
165  return 1;
166  }
167  argv_ = calloc (1, sizeof (char *));
168  if (argv_ == NULL)
169  {
170  fclose (fp);
171  return 1;
172  }
173  arg = strndup (argv[0], 1024);
174  if (arg == NULL)
175  {
176  fclose (fp);
177  free (argv_);
178  return 1;
179  }
180  argv_[0] = arg;
181 
182  while (1)
183  {
184  if (fgets (inbuf, 4096, fp) == 0)
185  break;
186  p = strtok (inbuf, " \t\n");
187  while (p != NULL)
188  {
189  if (*p == '#')
190  break;
191  argc_++;
192  char **tmp = realloc (argv_, argc_ * sizeof (char *));
193  if (tmp == NULL)
194  return 1;
195  argv_ = tmp;
196  arg = strndup (p, 1024);
197  if (arg == NULL)
198  return 1;
199  argv_[argc_ - 1] = arg;
200  p = strtok (NULL, " \t\n");
201  }
202  }
203 
204  fclose (fp);
205 
206  char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
207  if (tmp == NULL)
208  return 1;
209  argv_ = tmp;
210  argv_[argc_] = NULL;
211 
212  argc = argc_;
213  argv = argv_;
214  }
215 
216  /*
217  * Look for and parse the "heapsize" config parameter.
218  * Manual since none of the clib infra has been bootstrapped yet.
219  *
220  * Format: heapsize <nn>[mM][gG]
221  */
222 
223  for (i = 1; i < (argc - 1); i++)
224  {
225  if (!strncmp (argv[i], "plugin_path", 11))
226  {
227  if (i < (argc - 1))
228  vlib_plugin_path = argv[++i];
229  }
230  if (!strncmp (argv[i], "test_plugin_path", 16))
231  {
232  if (i < (argc - 1))
233  vat_plugin_path = argv[++i];
234  }
235  else if (!strncmp (argv[i], "heapsize", 8))
236  {
237  sizep = (u8 *) argv[i + 1];
238  size = 0;
239  while (*sizep >= '0' && *sizep <= '9')
240  {
241  size *= 10;
242  size += *sizep++ - '0';
243  }
244  if (size == 0)
245  {
246  fprintf
247  (stderr,
248  "warning: heapsize parse error '%s', use default %lld\n",
249  argv[i], (long long int) main_heap_size);
250  goto defaulted;
251  }
252 
253  main_heap_size = size;
254 
255  if (*sizep == 'g' || *sizep == 'G')
256  main_heap_size <<= 30;
257  else if (*sizep == 'm' || *sizep == 'M')
258  main_heap_size <<= 20;
259  }
260  else if (!strncmp (argv[i], "main-core", 9))
261  {
262  if (i < (argc - 1))
263  {
264  errno = 0;
265  unsigned long x = strtol (argv[++i], 0, 0);
266  if (errno == 0)
267  main_core = x;
268  }
269  }
270  }
271 
272 defaulted:
273 
274  /* set process affinity for main thread */
275  CPU_ZERO (&cpuset);
276  CPU_SET (main_core, &cpuset);
277  pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
278 
279  /* Set up the plugin message ID allocator right now... */
281 
282  /* Allocate main heap */
283  if ((main_heap = clib_mem_init_thread_safe (0, main_heap_size)))
284  {
286 
287  /* Figure out which numa runs the main thread */
288  vlib_get_thread_core_numa (&tmp, main_core);
289  __os_numa_index = tmp.numa_id;
290 
291  /* and use the main heap as that numa's numa heap */
292  clib_mem_set_per_numa_heap (main_heap);
293 
294  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
295  vpe_main_init (vm);
296  return vlib_unix_main (argc, argv);
297  }
298  else
299  {
300  {
301  int rv __attribute__ ((unused)) =
302  write (2, "Main heap allocation failure!\r\n", 31);
303  }
304  return 1;
305  }
306 }
307 
308 static clib_error_t *
310 {
311  u32 junk;
312 
314  {
315  if (unformat (input, "%dm", &junk)
316  || unformat (input, "%dM", &junk)
317  || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
318  return 0;
319  else
320  return clib_error_return (0, "unknown input '%U'",
321  format_unformat_error, input);
322  }
323  return 0;
324 }
325 
327 
328 static clib_error_t *
330 {
331  u8 *junk;
332 
334  {
335  if (unformat (input, "%s", &junk))
336  {
337  vec_free (junk);
338  return 0;
339  }
340  else
341  return clib_error_return (0, "unknown input '%U'",
342  format_unformat_error, input);
343  }
344  return 0;
345 }
346 
347 static clib_error_t *
349 {
350  return placeholder_path_config (vm, input);
351 }
352 
354 
355 static clib_error_t *
357 {
358  return placeholder_path_config (vm, input);
359 }
360 
361 VLIB_CONFIG_FUNCTION (test_plugin_path_config, "test_plugin_path");
362 
363 void vl_msg_api_post_mortem_dump (void);
364 void elog_post_mortem_dump (void);
365 
366 void
367 os_panic (void)
368 {
371  abort ();
372 }
373 
374 void vhost_user_unmap_all (void) __attribute__ ((weak));
375 void
377 {
378 }
379 
380 void
381 os_exit (int code)
382 {
383  static int recursion_block;
384 
385  if (code)
386  {
387  if (recursion_block)
388  abort ();
389 
390  recursion_block = 1;
391 
395  abort ();
396  }
397  exit (code);
398 }
399 
400 #ifdef BARRIER_TRACING
401 void
402 vl_msg_api_barrier_trace_context (const char *context)
403 {
405 }
406 #endif
407 
408 void
410 {
412 }
413 
414 void
416 {
418 }
419 
420 /* This application needs 1 thread stack for the stats pthread */
421 u32
423 {
424  return 1;
425 }
426 
427 /*
428  * Depending on the configuration selected above,
429  * it may be necessary to generate stub graph nodes.
430  * It is never OK to ignore "node 'x' refers to unknown node 'y'
431  * messages!
432  */
433 
434 #include <vppinfra/bihash_8_8.h>
435 
436 typedef struct
437 {
438  u8 *name;
441 } name_sort_t;
442 
443 static int
444 name_sort_cmp (void *a1, void *a2)
445 {
446  name_sort_t *n1 = a1;
447  name_sort_t *n2 = a2;
448 
449  return strcmp ((char *) n1->name, (char *) n2->name);
450 }
451 
452 static clib_error_t *
454  unformat_input_t * input, vlib_cli_command_t * cmd)
455 {
456  int i;
457  clib_bihash_8_8_t *h;
458  u64 total_actual_virt_size = 0;
459  u64 total_configured_virt_size = 0;
460  u64 actual_virt_size;
461  u64 configured_virt_size;
462  name_sort_t *names = 0;
463  name_sort_t *this;
464  int verbose = 0;
465 
466  if (unformat (input, "verbose"))
467  verbose = 1;
468 
469  for (i = 0; i < vec_len (clib_all_bihashes); i++)
470  {
471  h = (clib_bihash_8_8_t *) clib_all_bihashes[i];
472  if (alloc_arena (h) || verbose)
473  {
474  vec_add2 (names, this, 1);
475  this->name = format (0, "%s%c", h->name, 0);
476  configured_virt_size = h->memory_size;
477  actual_virt_size = alloc_arena (h) ? h->memory_size : 0ULL;
478  this->actual_virt_size = actual_virt_size;
479  this->configured_virt_size = configured_virt_size;
480  total_actual_virt_size += actual_virt_size;
481  total_configured_virt_size += configured_virt_size;
482  }
483  }
484 
486 
487  vlib_cli_output (vm, "%-30s %8s %s", "Name", "Actual", "Configured");
488 
489  for (i = 0; i < vec_len (names); i++)
490  {
491  vlib_cli_output (vm, "%-30s %8U %U", names[i].name,
493  names[i].actual_virt_size,
494  format_memory_size, names[i].configured_virt_size);
495  vec_free (names[i].name);
496  }
497 
498  vec_free (names);
499 
500  vlib_cli_output (vm, "%-30s %8U %U", "Total",
501  format_memory_size, total_actual_virt_size,
502  format_memory_size, total_configured_virt_size);
503  return 0;
504 }
505 
506 /* *INDENT-OFF* */
507 VLIB_CLI_COMMAND (show_bihash_command, static) =
508 {
509  .path = "show bihash",
510  .short_help = "show bihash",
511  .function = show_bihash_command_fn,
512 };
513 /* *INDENT-ON* */
514 
515 #ifdef CLIB_SANITIZE_ADDR
516 /* default options for Address Sanitizer */
517 const char *
518 __asan_default_options (void)
519 {
520  return VPP_SANITIZE_ADDR_OPTIONS;
521 }
522 #endif /* CLIB_SANITIZE_ADDR */
523 
524 /*
525  * fd.io coding-style-patch-verification: ON
526  *
527  * Local Variables:
528  * eval: (c-set-style "gnu")
529  * End:
530  */
int vlib_unix_main(int argc, char *argv[])
Definition: main.c:684
u32 vlib_app_num_thread_stacks_needed(void)
Definition: main.c:422
vlib_main_t vlib_global_main
Definition: main.c:1983
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:864
#define CLIB_UNUSED(x)
Definition: clib.h:87
void vlib_unix_cli_set_prompt(char *prompt)
Set the CLI prompt.
Definition: cli.c:3279
void vl_msg_api_barrier_sync(void)
Definition: main.c:409
static clib_error_t * plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:348
unsigned long u64
Definition: types.h:89
static clib_error_t * heapsize_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:309
#define vlib_mark_init_function_complete(vm, x)
Definition: init.h:284
void vhost_user_unmap_all(void)
Definition: main.c:376
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
vlib_main_t * vm
Definition: in2out_ed.c:1582
static clib_error_t * test_plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:356
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:191
char * vat_plugin_path
Definition: main.c:36
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:453
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:205
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:381
void vl_msg_api_post_mortem_dump(void)
Definition: api_shared.c:955
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:34
static int name_sort_cmp(void *a1, void *a2)
Definition: main.c:444
static clib_error_t * placeholder_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:329
const char * barrier_context
Definition: threads.h:108
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u32 size
Definition: vhost_user.h:106
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:737
uword * init_functions_called
Definition: main.h:246
#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:34
string name[64]
Definition: ip.api:44
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define hash_create(elts, value_bytes)
Definition: hash.h:696
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
void vat_plugin_hash_create(void)
Definition: api_main.c:65
void vl_msg_api_barrier_release(void)
Definition: main.c:415
static void vpe_main_init(vlib_main_t *vm)
Definition: main.c:75
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:593
#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:1055
static void vpp_find_plugin_path()
Definition: main.c:39
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:1554
int main(int argc, char *argv[])
Definition: main.c:106
u64 actual_virt_size
Definition: main.c:439
void ** clib_all_bihashes
char * vlib_plugin_app_version
Definition: main.c:35
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
Definition: mem_dlmalloc.c:234
u8 * name
Definition: macros.c:271
void os_panic(void)
Definition: main.c:367
u64 configured_virt_size
Definition: main.c:440
void vl_msg_api_set_first_available_msg_id(u16 first_avail)
Definition: api_shared.c:1025
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