FD.io VPP  v16.12-rc0-308-g931be3a
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 #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 */
59  if (!(proc->flags & VLIB_PROCESS_IS_RUNNING) ||
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
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 */
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 *
91 {
92  static vnet_plugin_handoff_t _rv, *rv = &_rv;
93 
94  rv->vnet_main = vnet_get_main ();
96  return (void *) rv;
97 }
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  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... */
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 == 0
252  unix_physmem_init (vm, 0 /* fail_if_physical_memory_not_present */ );
253 #endif
255  return vlib_unix_main (argc, argv);
256  }
257  else
258  {
259  {
260  int rv __attribute__ ((unused)) =
261  write (2, "Main heap allocation failure!\r\n", 31);
262  }
263  return 1;
264  }
265 }
266 
267 static clib_error_t *
269 {
270  u32 junk;
271 
273  {
274  if (unformat (input, "%dm", &junk)
275  || unformat (input, "%dM", &junk)
276  || unformat (input, "%dg", &junk) || unformat (input, "%dG", &junk))
277  return 0;
278  else
279  return clib_error_return (0, "unknown input '%U'",
280  format_unformat_error, input);
281  }
282  return 0;
283 }
284 
286 
287 static clib_error_t *
289 {
290  u8 *junk;
291 
293  {
294  if (unformat (input, "%s", &junk))
295  {
296  vec_free (junk);
297  return 0;
298  }
299  else
300  return clib_error_return (0, "unknown input '%U'",
301  format_unformat_error, input);
302  }
303  return 0;
304 }
305 
307 
308 void vl_msg_api_post_mortem_dump (void);
309 
310 void
311 os_panic (void)
312 {
314  abort ();
315 }
316 
317 void vhost_user_unmap_all (void) __attribute__ ((weak));
318 void
320 {
321 }
322 
323 void
324 os_exit (int code)
325 {
326  static int recursion_block;
327 
328  if (code)
329  {
330  if (recursion_block)
331  abort ();
332 
333  recursion_block = 1;
334 
337  abort ();
338  }
339  exit (code);
340 }
341 
342 void
344 {
346 }
347 
348 void
350 {
352 }
353 
354 /* This application needs 1 thread stack for the stats pthread */
355 u32
357 {
358  return 1;
359 }
360 
361 /*
362  * Depending on the configuration selected above,
363  * it may be necessary to generate stub graph nodes.
364  * It is never OK to ignore "node 'x' refers to unknown node 'y'
365  * messages!
366  */
367 
368 #if CLIB_DEBUG > 0
369 
370 static clib_error_t *
372  unformat_input_t * input, vlib_cli_command_t * cmd)
373 {
374  u64 *p = (u64 *) 0xdefec8ed;
375 
376  *p = 0xdeadbeef;
377 
378  /* Not so much... */
379  return 0;
380 }
381 
382 /* *INDENT-OFF* */
383 VLIB_CLI_COMMAND (test_crash_command, static) = {
384  .path = "test crash",
385  .short_help = "crash the bus!",
386  .function = test_crash_command_fn,
387 };
388 /* *INDENT-ON* */
389 
390 #endif
391 
392 /*
393  * fd.io coding-style-patch-verification: ON
394  *
395  * Local Variables:
396  * eval: (c-set-style "gnu")
397  * End:
398  */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
char * vlib_plugin_path
Definition: main.c:87
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
void vl_msg_api_barrier_sync(void)
Definition: main.c:343
vlib_node_runtime_t node_runtime
Definition: node.h:494
int main(int argc, char *argv[])
Definition: main.c:100
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
int rte_delay_us_override(unsigned us)
Definition: main.c:34
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define NULL
Definition: clib.h:55
#define vlib_mark_init_function_complete(vm, x)
Definition: init.h:175
uword admin_up_down_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: device.c:1001
void vl_msg_api_set_first_available_msg_id(u16 first_avail)
Definition: api_shared.c:1261
ethernet_main_t * ethernet_main
Definition: plugin.h:27
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:432
ethernet_main_t ethernet_main
Definition: ethernet.h:279
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vlib_node_function_t * function
Definition: node.h:416
void vl_msg_api_barrier_release(void)
Definition: main.c:349
unsigned long u64
Definition: types.h:89
static void vpe_main_init(vlib_main_t *vm)
Definition: main.c:73
void vlib_set_get_handoff_structure_cb(void *cb)
Definition: plugin.c:25
void vl_msg_api_post_mortem_dump(void)
Definition: api_shared.c:1191
void os_panic(void)
Definition: main.c:311
void vlib_unix_cli_set_prompt(char *prompt)
Set the CLI prompt.
Definition: cli.c:2536
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
static clib_error_t * plugin_path_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:288
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:118
void vhost_user_unmap_all(void)
Definition: main.c:319
uword * init_functions_called
Definition: main.h:156
void * clib_mem_init(void *heap, uword size)
Definition: mem_mheap.c:60
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:397
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
vlib_main_t vlib_global_main
Definition: main.c:1536
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1182
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define hash_create(elts, value_bytes)
Definition: hash.h:658
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void os_exit(int code)
Definition: main.c:324
u32 size
Definition: vhost-user.h:76
u32 vlib_app_num_thread_stacks_needed(void)
Definition: main.c:356
u64 uword
Definition: types.h:112
void * vnet_get_handoff_structure(void)
Definition: main.c:90
unsigned short u16
Definition: types.h:57
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
clib_error_t * unix_physmem_init(vlib_main_t *vm, int physical_memory_required)
Definition: physmem.c:209
int vlib_unix_main(int argc, char *argv[])
Definition: main.c:492
vnet_main_t * vnet_main
Definition: plugin.h:26
u16 flags
Definition: node.h:507
static uword vlib_in_process_context(vlib_main_t *vm)
Definition: node_funcs.h:404
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1214
static clib_error_t * heapsize_config(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:268
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:918
static clib_error_t * test_crash_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:371
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:514