FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
builtin_http_server.c
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2015-2017 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 <vnet/vnet.h>
17 #include <vlibmemory/api.h>
20 
21 /* define message IDs */
22 #include <vpp/api/vpe_msg_enum.h>
23 
24 /* define message structures */
25 #define vl_typedefs
26 #include <vpp/api/vpe_all_api_h.h>
27 #undef vl_typedefs
28 
29 /* define generated endian-swappers */
30 #define vl_endianfun
31 #include <vpp/api/vpe_all_api_h.h>
32 #undef vl_endianfun
33 
34 /* instantiate all the print functions we know about */
35 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
36 #define vl_printfun
37 #include <vpp/api/vpe_all_api_h.h>
38 #undef vl_printfun
39 
40 typedef enum
41 {
44 
45 typedef struct
46 {
50 
52 
54 
55  /* Sever's event queue */
57 
58  /* API client handle */
60 
62 
63  /* process node index for evnt scheduling */
67 
69 
70 static void
72 {
76  vlib_node_t *n;
77  u32 node_index;
78  stream_session_t **save_s;
79 
80  node_index = (u64) (s->opaque[0]);
81  ASSERT (node_index != 0);
82 
83  n = vlib_get_node (vm, node_index);
86 
87  /* Reset session saved node index */
88  s->opaque[0] = 0;
89  /* Reset process session pointer */
90  *save_s = 0;
91 
92  /* Turn off the process node */
93  vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
94 
95  /* add node index to the freelist */
97 }
98 
99 static const char
100  *http_response = "HTTP/1.1 200 OK\r\n"
101  "Content-Type: text/html\r\n"
102  "Expires: Mon, 11 Jan 1970 10:10:10 GMT\r\n"
103  "Connection: close\r\n"
104  "Pragma: no-cache\r\n" "Content-Length: %d\r\n\r\n%s";
105 
106 static const char
107  *http_error_template = "HTTP/1.1 %s\r\n"
108  "Content-Type: text/html\r\n"
109  "Expires: Mon, 11 Jan 1970 10:10:10 GMT\r\n"
110  "Connection: close\r\n" "Pragma: no-cache\r\n" "Content-Length: 0\r\n\r\n";
111 
112 /* Header, including incantation to suppress favicon.ico requests */
113 static const char
114  *html_header_template = "<html><head><title>%v</title>"
115  "</head><link rel=\"icon\" href=\"data:,\"><body><pre>";
116 
117 static const char *html_footer = "</pre></body></html>\r\n";
118 
119 static void
120 http_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
121 {
122  u8 **output_vecp = (u8 **) arg;
123  u8 *output_vec;
124  u32 offset;
125 
126  output_vec = *output_vecp;
127 
128  offset = vec_len (output_vec);
129  vec_validate (output_vec, offset + buffer_bytes - 1);
130  clib_memcpy (output_vec + offset, buffer, buffer_bytes);
131 
132  *output_vecp = output_vec;
133 }
134 
135 void
137 {
138  session_fifo_event_t evt;
139  u32 offset, bytes_to_send;
140  f64 delay = 10e-3;
142  vlib_main_t *vm = hsm->vlib_main;
143  f64 last_sent_timer = vlib_time_now (vm);
144 
145  bytes_to_send = vec_len (data);
146  offset = 0;
147 
148  while (bytes_to_send > 0)
149  {
150  int actual_transfer;
151 
152  actual_transfer = svm_fifo_enqueue_nowait
153  (s->server_tx_fifo, bytes_to_send, data + offset);
154 
155  /* Made any progress? */
156  if (actual_transfer <= 0)
157  {
158  vlib_process_suspend (vm, delay);
159  /* 10s deadman timer */
160  if (vlib_time_now (vm) > last_sent_timer + 10.0)
161  {
162  /* $$$$ FC: reset transport session here? */
163  break;
164  }
165  /* Exponential backoff, within reason */
166  if (delay < 1.0)
167  delay = delay * 2.0;
168  }
169  else
170  {
171  last_sent_timer = vlib_time_now (vm);
172  offset += actual_transfer;
173  bytes_to_send -= actual_transfer;
174 
175  if (svm_fifo_set_event (s->server_tx_fifo))
176  {
177  /* Fabricate TX event, send to vpp */
178  evt.fifo = s->server_tx_fifo;
179  evt.event_type = FIFO_EVENT_APP_TX;
180  evt.event_id = 0;
181 
182  unix_shared_memory_queue_add (hsm->vpp_queue[s->thread_index],
183  (u8 *) & evt,
184  0 /* do wait for mutex */ );
185  }
186  delay = 10e-3;
187  }
188  }
189 }
190 
191 static void
192 send_error (stream_session_t * s, char *str)
193 {
194  u8 *data;
195 
196  data = format (0, http_error_template, str);
197  send_data (s, data);
198  vec_free (data);
199 }
200 
201 static uword
204 {
206  u8 *request = 0, *reply = 0;
207  stream_session_t **save_s;
208  stream_session_t *s;
209  unformat_input_t input;
210  int i;
211  u8 *http = 0, *html = 0;
212 
213  save_s = vlib_node_get_runtime_data (hsm->vlib_main, rt->node_index);
214  s = *save_s;
215 
216  request = (u8 *) (void *) (s->opaque[1]);
217  s->opaque[1] = 0;
218 
219  if (vec_len (request) < 7)
220  {
221  send_error (s, "400 Bad Request");
222  goto out;
223  }
224 
225  for (i = 0; i < vec_len (request) - 4; i++)
226  {
227  if (request[i] == 'G' &&
228  request[i + 1] == 'E' &&
229  request[i + 2] == 'T' && request[i + 3] == ' ')
230  goto found;
231  }
232 bad_request:
233  send_error (s, "400 Bad Request");
234  goto out;
235 
236 found:
237  /* Lose "GET " */
238  vec_delete (request, i + 5, 0);
239 
240  /* Replace slashes with spaces, stop at the end of the path */
241  i = 0;
242  while (1)
243  {
244  if (request[i] == '/')
245  request[i] = ' ';
246  else if (request[i] == ' ')
247  {
248  /* vlib_cli_input is vector-based, no need for a NULL */
249  _vec_len (request) = i;
250  break;
251  }
252  i++;
253  /* Should never happen */
254  if (i == vec_len (request))
255  goto bad_request;
256  }
257 
258  /* Generate the html header */
259  html = format (0, html_header_template, request /* title */ );
260 
261  /* Run the command */
262  unformat_init_vector (&input, request);
263  vlib_cli_input (vm, &input, http_cli_output, (uword) & reply);
264  unformat_free (&input);
265  request = 0;
266 
267  /* Generate the html page */
268  html = format (html, "%v", reply);
269  html = format (html, html_footer);
270  /* And the http reply */
271  http = format (0, http_response, vec_len (html), html);
272 
273  /* Send it */
274  send_data (s, http);
275 
276 out:
277  /* Cleanup */
278  vec_free (request);
279  vec_free (reply);
280  vec_free (html);
281  vec_free (http);
282 
283  free_http_process (s);
284  return (0);
285 }
286 
287 static void
289 {
290  char *name;
291  vlib_node_t *n;
293  vlib_main_t *vm = hsm->vlib_main;
295  stream_session_t **save_s;
296 
298  {
300 
301  vlib_node_set_state (vm, n->index, VLIB_NODE_STATE_POLLING);
302 
303  _vec_len (hsm->free_http_cli_process_node_indices) = l - 1;
304  }
305  else
306  {
307  static vlib_node_registration_t r = {
308  .function = http_cli_process,
309  .type = VLIB_NODE_TYPE_PROCESS,
310  .process_log2_n_stack_bytes = 16,
311  .runtime_data_bytes = sizeof (void *),
312  };
313 
314  name = (char *) format (0, "http-cli-%d", l);
315 
316  r.name = name;
317  vlib_register_node (vm, &r);
318  vec_free (name);
319 
320  n = vlib_get_node (vm, r.index);
321  }
322 
323  /* Save the node index in the stream_session_t. It won't be zero. */
324  s->opaque[0] = (u64) n->index;
325 
326  /* Save the stream_session_t (pointer) in the node runtime */
327  save_s = vlib_node_get_runtime_data (vm, n->index);
328  *save_s = s;
329 
331 }
332 
333 static int
335 {
337 
338  bsm->vpp_queue[s->thread_index] =
339  session_manager_get_vpp_event_queue (s->thread_index);
340  s->session_state = SESSION_STATE_READY;
341  bsm->byte_index = 0;
342  return 0;
343 }
344 
345 static void
347 {
349  vnet_disconnect_args_t _a, *a = &_a;
350 
351  a->handle = stream_session_handle (s);
352  a->app_index = bsm->app_index;
354 }
355 
356 static void
358 {
359  clib_warning ("called.. ");
360 
362 }
363 
364 
365 static int
367  stream_session_t * s, u8 is_fail)
368 {
369  clib_warning ("called...");
370  return -1;
371 }
372 
373 static int
375  const u8 * seg_name, u32 seg_size)
376 {
377  clib_warning ("called...");
378  return -1;
379 }
380 
381 static int
382 builtin_redirect_connect_callback (u32 client_index, void *mp)
383 {
384  clib_warning ("called...");
385  return -1;
386 }
387 
388 static void
390 {
391  stream_session_t *s = (stream_session_t *) s_arg;
392  alloc_http_process (s);
393 }
394 
395 static int
397 {
398  u32 max_dequeue;
399  int actual_transfer;
401  svm_fifo_t *rx_fifo;
402 
403  rx_fifo = s->server_rx_fifo;
404 
405  max_dequeue = svm_fifo_max_dequeue (rx_fifo);
406 
407  svm_fifo_unset_event (rx_fifo);
408 
409  if (PREDICT_FALSE (max_dequeue == 0))
410  return 0;
411 
412  vec_validate (hsm->rx_buf, max_dequeue - 1);
413  _vec_len (hsm->rx_buf) = max_dequeue;
414 
415  actual_transfer = svm_fifo_dequeue_nowait (rx_fifo, max_dequeue,
416  hsm->rx_buf);
417  ASSERT (actual_transfer > 0);
418 
419  _vec_len (hsm->rx_buf) = actual_transfer;
420 
421  /* send the command to a new/recycled vlib process */
422  s->opaque[1] = (u64) vec_dup (hsm->rx_buf);
423 
424  /* Send an RPC request via the thread-0 input node */
425  if (vlib_get_thread_index () != 0)
426  {
427  session_fifo_event_t evt;
428  evt.rpc_args.fp = alloc_http_process_callback;
429  evt.rpc_args.arg = s;
430  evt.event_type = FIFO_EVENT_RPC;
432  (session_manager_get_vpp_event_queue (0 /* main thread */ ),
433  (u8 *) & evt, 0 /* do wait for mutex */ );
434  }
435  else
436  alloc_http_process (s);
437  return 0;
438 }
439 
441  .session_accept_callback = builtin_session_accept_callback,
442  .session_disconnect_callback = builtin_session_disconnect_callback,
443  .session_connected_callback = builtin_session_connected_callback,
444  .add_segment_callback = builtin_add_segment_callback,
445  .redirect_connect_callback = builtin_redirect_connect_callback,
446  .builtin_server_rx_callback = http_server_rx_callback,
447  .session_reset_callback = builtin_session_reset_callback
448 };
449 
450 /* Abuse VPP's input queue */
451 static int
453 {
455  vl_api_memclnt_create_t _m, *mp = &_m;
457  api_main_t *am = &api_main;
459  uword *event_data = 0, event_type;
460  int resolved = 0;
461 
462  /*
463  * Create a "loopback" API client connection
464  * Don't do things like this unless you know what you're doing...
465  */
466 
467  shmem_hdr = am->shmem_hdr;
468  hsm->vl_input_queue = shmem_hdr->vl_input_queue;
469  memset (mp, 0, sizeof (*mp));
470  mp->_vl_msg_id = VL_API_MEMCLNT_CREATE;
471  mp->context = 0xFEEDFACE;
472  mp->input_queue = (u64) hsm->vl_input_queue;
473  strncpy ((char *) mp->name, "tcp_http_server", sizeof (mp->name) - 1);
474 
476 
477  /* Wait for reply */
480  event_type = vlib_process_get_events (vm, &event_data);
481  switch (event_type)
482  {
483  case 1:
484  resolved = 1;
485  break;
486  case ~0:
487  /* timed out */
488  break;
489  default:
490  clib_warning ("unknown event_type %d", event_type);
491  }
492  if (!resolved)
493  return -1;
494 
495  return 0;
496 }
497 
498 static int
500 {
502  u8 segment_name[128];
504  vnet_app_attach_args_t _a, *a = &_a;
505 
506  memset (a, 0, sizeof (*a));
507  memset (options, 0, sizeof (options));
508 
509  a->api_client_index = hsm->my_client_index;
510  a->session_cb_vft = &builtin_session_cb_vft;
511  a->options = options;
512  a->options[SESSION_OPTIONS_SEGMENT_SIZE] = 128 << 20;
513  a->options[SESSION_OPTIONS_RX_FIFO_SIZE] = 8 << 10;
514  a->options[SESSION_OPTIONS_TX_FIFO_SIZE] = 32 << 10;
515  a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_BUILTIN_APP;
516  a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16;
517  a->segment_name = segment_name;
518  a->segment_name_length = ARRAY_LEN (segment_name);
519 
520  if (vnet_application_attach (a))
521  {
522  clib_warning ("failed to attach server");
523  return -1;
524  }
525  hsm->app_index = a->app_index;
526  return 0;
527 }
528 
529 static int
531 {
533  vnet_bind_args_t _a, *a = &_a;
534  memset (a, 0, sizeof (*a));
535  a->app_index = hsm->app_index;
536  a->uri = "tcp://0.0.0.0/80";
537  return vnet_bind_uri (a);
538 }
539 
540 static int
542 {
544  u32 num_threads;
546 
547  if (hsm->my_client_index == (u32) ~ 0)
548  {
549  if (create_api_loopback (vm))
550  return -1;
551  }
552 
553  num_threads = 1 /* main thread */ + vtm->n_threads;
554  vec_validate (http_server_main.vpp_queue, num_threads - 1);
555 
556  if (server_attach ())
557  {
558  clib_warning ("failed to attach server");
559  return -1;
560  }
561  if (server_listen ())
562  {
563  clib_warning ("failed to start listening");
564  return -1;
565  }
566  return 0;
567 }
568 
569 /* Get our api client index */
570 static void
572 {
573  vlib_main_t *vm = vlib_get_main ();
575  hsm->my_client_index = mp->index;
576  vlib_process_signal_event (vm, hsm->node_index, 1 /* evt */ ,
577  0 /* data */ );
578 }
579 
580 #define foreach_tcp_http_server_api_msg \
581 _(MEMCLNT_CREATE_REPLY, memclnt_create_reply) \
582 
583 static clib_error_t *
585 {
586  vl_msg_api_msg_config_t _c, *c = &_c;
587 
588  /* Hook up client-side static APIs to our handlers */
589 #define _(N,n) do { \
590  c->id = VL_API_##N; \
591  c->name = #n; \
592  c->handler = vl_api_##n##_t_handler; \
593  c->cleanup = vl_noop_handler; \
594  c->endian = vl_api_##n##_t_endian; \
595  c->print = vl_api_##n##_t_print; \
596  c->size = sizeof(vl_api_##n##_t); \
597  c->traced = 1; /* trace, so these msgs print */ \
598  c->replay = 0; /* don't replay client create/delete msgs */ \
599  c->message_bounce = 0; /* don't bounce this message */ \
600  vl_msg_api_config(c);} while (0);
601 
603 #undef _
604 
605  return 0;
606 }
607 
608 static clib_error_t *
610  unformat_input_t * input, vlib_cli_command_t * cmd)
611 {
612  int rv;
613 
615  vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ );
616  rv = server_create (vm);
617  switch (rv)
618  {
619  case 0:
620  break;
621  default:
622  return clib_error_return (0, "server_create returned %d", rv);
623  }
624  return 0;
625 }
626 
627 /* *INDENT-OFF* */
628 VLIB_CLI_COMMAND (server_create_command, static) =
629 {
630  .path = "test http server",
631  .short_help = "test http server",
632  .function = server_create_command_fn,
633 };
634 /* *INDENT-ON* */
635 
636 static clib_error_t *
638 {
640  hsm->my_client_index = ~0;
641  hsm->vlib_main = vm;
642 
643  return 0;
644 }
645 
647 
648 /*
649 * fd.io coding-style-patch-verification: ON
650 *
651 * Local Variables:
652 * eval: (c-set-style "gnu")
653 * End:
654 */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
static void http_cli_output(uword arg, u8 *buffer, uword buffer_bytes)
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:699
vlib_node_runtime_t node_runtime
Definition: node.h:499
a
Definition: bitmap.h:516
void vlib_cli_input(vlib_main_t *vm, unformat_input_t *input, vlib_cli_output_function_t *function, uword function_arg)
Definition: cli.c:643
int vnet_bind_uri(vnet_bind_args_t *a)
void send_data(stream_session_t *s, u8 *data)
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:68
static const char * http_error_template
u32 index
Definition: node.h:238
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:192
static int http_server_rx_callback(stream_session_t *s)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
struct _vlib_node_registration vlib_node_registration_t
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void alloc_http_process(stream_session_t *s)
static int builtin_add_segment_callback(u32 client_index, const u8 *seg_name, u32 seg_size)
static const char * http_response
static int server_attach()
struct _stream_session_t stream_session_t
struct _svm_fifo svm_fifo_t
static clib_error_t * tcp_http_server_api_hookup(vlib_main_t *vm)
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:448
unix_shared_memory_queue_t ** vpp_queue
static clib_error_t * server_create_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void vl_api_memclnt_create_reply_t_handler(vl_api_memclnt_create_reply_t *mp)
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:542
struct _vnet_disconnect_args_t vnet_disconnect_args_t
static u32 svm_fifo_max_dequeue(svm_fifo_t *f)
Definition: svm_fifo.h:71
static int builtin_session_connected_callback(u32 app_index, u32 api_context, stream_session_t *s, u8 is_fail)
struct _stream_session_cb_vft session_cb_vft_t
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api_common.h:189
static int server_listen()
void stream_session_cleanup(stream_session_t *s)
Cleanup transport and session state.
Definition: session.c:1025
static const char * html_header_template
struct _vnet_app_attach_args_t vnet_app_attach_args_t
http_server_main_t http_server_main
vl_shmem_hdr_t * shmem_hdr
int unix_shared_memory_queue_add(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:946
vlib_main_t vlib_global_main
Definition: main.c:1653
struct _unformat_input_t unformat_input_t
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
static void * vlib_node_get_runtime_data(vlib_main_t *vm, u32 node_index)
Get node runtime private data by node index.
Definition: node_funcs.h:109
#define PREDICT_FALSE(x)
Definition: clib.h:97
static void svm_fifo_unset_event(svm_fifo_t *f)
Unsets fifo event flag.
Definition: svm_fifo.h:104
u32 node_index
Node index.
Definition: node.h:441
clib_error_t * vnet_session_enable_disable(vlib_main_t *vm, u8 is_en)
Definition: session.c:1179
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1031
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
Definition: svm_fifo.h:94
static unix_shared_memory_queue_t * session_manager_get_vpp_event_queue(u32 thread_index)
Definition: session.h:406
api_main_t api_main
Definition: api_shared.c:35
svmdb_client_t * c
u32 runtime_index
Definition: node.h:241
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:413
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:88
static void send_error(stream_session_t *s, char *str)
#define clib_memcpy(a, b, c)
Definition: string.h:69
int vnet_disconnect_session(vnet_disconnect_args_t *a)
#define ARRAY_LEN(x)
Definition: clib.h:59
int svm_fifo_enqueue_nowait(svm_fifo_t *f, u32 max_bytes, u8 *copy_from_here)
Definition: svm_fifo.c:441
static int builtin_session_accept_callback(stream_session_t *s)
static int builtin_redirect_connect_callback(u32 client_index, void *mp)
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1365
unix_shared_memory_queue_t * vl_input_queue
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
int vnet_application_attach(vnet_app_attach_args_t *a)
Attaches application.
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:498
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:146
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
static u64 stream_session_handle(stream_session_t *s)
Definition: session.h:299
void vl_api_memclnt_create_t_handler(vl_api_memclnt_create_t *mp)
Definition: memory_vlib.c:143
static clib_error_t * builtin_http_server_main_init(vlib_main_t *vm)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
static int create_api_loopback(vlib_main_t *vm)
static int server_create(vlib_main_t *vm)
static uword http_cli_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
struct clib_bihash_value offset
template key/value backing page structure
static const char * html_footer
vhost_user_req_t request
Definition: vhost-user.h:75
#define foreach_tcp_http_server_api_msg
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:58
http_process_event_t
int svm_fifo_dequeue_nowait(svm_fifo_t *f, u32 max_bytes, u8 *copy_here)
Definition: svm_fifo.c:593
struct _vnet_bind_args_t vnet_bind_args_t
static void builtin_session_disconnect_callback(stream_session_t *s)
static void free_http_process(stream_session_t *s)
static session_cb_vft_t builtin_session_cb_vft
static void alloc_http_process_callback(void *s_arg)
static void builtin_session_reset_callback(stream_session_t *s)
u32 * free_http_cli_process_node_indices
struct _unix_shared_memory_queue unix_shared_memory_queue_t