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