X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ftcp%2Fbuiltin_http_server.c;h=5510f8ad34c9b874030dab17609efaaabf872e11;hb=b384b543313b6b47a277c903e9d4fcd4343054fa;hp=f307880bcfd06bd0c5f20d82bb4632734548392a;hpb=3cbc04bea02fc60471dfe0c671ede3ca42c118c3;p=vpp.git diff --git a/src/vnet/tcp/builtin_http_server.c b/src/vnet/tcp/builtin_http_server.c index f307880bcfd..5510f8ad34c 100644 --- a/src/vnet/tcp/builtin_http_server.c +++ b/src/vnet/tcp/builtin_http_server.c @@ -31,8 +31,8 @@ typedef struct typedef struct { - u8 *rx_buf; - unix_shared_memory_queue_t **vpp_queue; + u8 **rx_buf; + svm_queue_t **vpp_queue; u64 byte_index; uword *handler_by_get_request; @@ -40,7 +40,7 @@ typedef struct u32 *free_http_cli_process_node_indices; /* Sever's event queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* API client handle */ u32 my_client_index; @@ -49,6 +49,10 @@ typedef struct /* process node index for evnt scheduling */ u32 node_index; + + u32 prealloc_fifos; + u32 private_segment_size; + u32 fifo_size; vlib_main_t *vlib_main; } http_server_main_t; @@ -102,6 +106,13 @@ static const char static const char *html_footer = "\r\n"; +static const char + *html_header_static = "static reply" + "
hello
" + "\r\n"; + +static u8 *static_http; + static void http_cli_output (uword arg, u8 * buffer, uword buffer_bytes) { @@ -119,7 +130,7 @@ http_cli_output (uword arg, u8 * buffer, uword buffer_bytes) } void -send_data (builtin_http_server_args * args, u8 * data) +send_data (stream_session_t * s, u8 * data) { session_fifo_event_t evt; u32 offset, bytes_to_send; @@ -127,10 +138,7 @@ send_data (builtin_http_server_args * args, u8 * data) http_server_main_t *hsm = &http_server_main; vlib_main_t *vm = hsm->vlib_main; f64 last_sent_timer = vlib_time_now (vm); - stream_session_t *s; - s = session_get_from_handle (args->session_handle); - ASSERT (s); bytes_to_send = vec_len (data); offset = 0; @@ -167,9 +175,8 @@ send_data (builtin_http_server_args * args, u8 * data) evt.fifo = s->server_tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - unix_shared_memory_queue_add (hsm->vpp_queue[s->thread_index], - (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (hsm->vpp_queue[s->thread_index], + (u8 *) & evt, 0 /* do wait for mutex */ ); } delay = 10e-3; } @@ -177,12 +184,12 @@ send_data (builtin_http_server_args * args, u8 * data) } static void -send_error (builtin_http_server_args * args, char *str) +send_error (stream_session_t * s, char *str) { u8 *data; data = format (0, http_error_template, str); - send_data (args, data); + send_data (s, data); vec_free (data); } @@ -194,17 +201,20 @@ http_cli_process (vlib_main_t * vm, u8 *request = 0, *reply = 0; builtin_http_server_args **save_args; builtin_http_server_args *args; + stream_session_t *s; unformat_input_t input; int i; u8 *http = 0, *html = 0; save_args = vlib_node_get_runtime_data (hsm->vlib_main, rt->node_index); args = *save_args; + s = session_get_from_handle (args->session_handle); + ASSERT (s); request = (u8 *) (void *) (args->data); if (vec_len (request) < 7) { - send_error (args, "400 Bad Request"); + send_error (s, "400 Bad Request"); goto out; } @@ -216,7 +226,7 @@ http_cli_process (vlib_main_t * vm, goto found; } bad_request: - send_error (args, "400 Bad Request"); + send_error (s, "400 Bad Request"); goto out; found: @@ -257,7 +267,7 @@ found: http = format (0, http_response, vec_len (html), html); /* Send it */ - send_data (args, http); + send_data (s, http); out: /* Cleanup */ @@ -320,31 +330,43 @@ alloc_http_process_callback (void *cb_args) } static int -http_server_rx_callback (stream_session_t * s) +session_rx_request (stream_session_t * s) { - u32 max_dequeue; - int actual_transfer; http_server_main_t *hsm = &http_server_main; svm_fifo_t *rx_fifo; - builtin_http_server_args *args; + u32 max_dequeue; + int actual_transfer; rx_fifo = s->server_rx_fifo; max_dequeue = svm_fifo_max_dequeue (rx_fifo); svm_fifo_unset_event (rx_fifo); if (PREDICT_FALSE (max_dequeue == 0)) - return 0; + return -1; - vec_validate (hsm->rx_buf, max_dequeue - 1); - _vec_len (hsm->rx_buf) = max_dequeue; + vec_validate (hsm->rx_buf[s->thread_index], max_dequeue - 1); + _vec_len (hsm->rx_buf[s->thread_index]) = max_dequeue; actual_transfer = svm_fifo_dequeue_nowait (rx_fifo, max_dequeue, - hsm->rx_buf); + hsm->rx_buf[s->thread_index]); ASSERT (actual_transfer > 0); - _vec_len (hsm->rx_buf) = actual_transfer; + _vec_len (hsm->rx_buf[s->thread_index]) = actual_transfer; + return 0; +} + +static int +http_server_rx_callback (stream_session_t * s) +{ + http_server_main_t *hsm = &http_server_main; + builtin_http_server_args *args; + int rv; + + rv = session_rx_request (s); + if (rv) + return rv; /* send the command to a new/recycled vlib process */ args = clib_mem_alloc (sizeof (*args)); - args->data = vec_dup (hsm->rx_buf); + args->data = vec_dup (hsm->rx_buf[s->thread_index]); args->session_handle = session_handle (s); /* Send an RPC request via the thread-0 input node */ @@ -354,7 +376,7 @@ http_server_rx_callback (stream_session_t * s) evt.rpc_args.fp = alloc_http_process_callback; evt.rpc_args.arg = args; evt.event_type = FIFO_EVENT_RPC; - unix_shared_memory_queue_add + svm_queue_add (session_manager_get_vpp_event_queue (0 /* main thread */ ), (u8 *) & evt, 0 /* do wait for mutex */ ); } @@ -363,6 +385,47 @@ http_server_rx_callback (stream_session_t * s) return 0; } +static int +http_server_rx_callback_static (stream_session_t * s) +{ + http_server_main_t *hsm = &http_server_main; + u8 *request = 0; + int i; + int rv; + + rv = session_rx_request (s); + if (rv) + return rv; + + request = hsm->rx_buf[s->thread_index]; + if (vec_len (request) < 7) + { + send_error (s, "400 Bad Request"); + goto out; + } + + for (i = 0; i < vec_len (request) - 4; i++) + { + if (request[i] == 'G' && + request[i + 1] == 'E' && + request[i + 2] == 'T' && request[i + 3] == ' ') + goto found; + } + send_error (s, "400 Bad Request"); + goto out; + +found: + + /* Send it */ + send_data (s, static_http); + +out: + /* Cleanup */ + vec_free (request); + hsm->rx_buf[s->thread_index] = request; + return 0; +} + static int builtin_session_accept_callback (stream_session_t * s) { @@ -403,8 +466,7 @@ builtin_session_connected_callback (u32 app_index, u32 api_context, } static int -builtin_add_segment_callback (u32 client_index, - const u8 * seg_name, u32 seg_size) +builtin_add_segment_callback (u32 client_index, const ssvm_private_t * sp) { clib_warning ("called..."); return -1; @@ -438,7 +500,7 @@ create_api_loopback (vlib_main_t * vm) shmem_hdr = am->shmem_hdr; hsm->vl_input_queue = shmem_hdr->vl_input_queue; hsm->my_client_index = - vl_api_memclnt_create_internal ("tcp_test_client", hsm->vl_input_queue); + vl_api_memclnt_create_internal ("test_http_server", hsm->vl_input_queue); return 0; } @@ -446,23 +508,26 @@ static int server_attach () { http_server_main_t *hsm = &http_server_main; - u8 segment_name[128]; - u64 options[SESSION_OPTIONS_N_OPTIONS]; + u64 options[APP_OPTIONS_N_OPTIONS]; vnet_app_attach_args_t _a, *a = &_a; + u32 segment_size = 128 << 20; memset (a, 0, sizeof (*a)); memset (options, 0, sizeof (options)); + if (hsm->private_segment_size) + segment_size = hsm->private_segment_size; + a->api_client_index = hsm->my_client_index; a->session_cb_vft = &builtin_session_cb_vft; a->options = options; - a->options[SESSION_OPTIONS_SEGMENT_SIZE] = 128 << 20; - a->options[SESSION_OPTIONS_RX_FIFO_SIZE] = 8 << 10; - a->options[SESSION_OPTIONS_TX_FIFO_SIZE] = 32 << 10; - a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_BUILTIN_APP; - a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16; - a->segment_name = segment_name; - a->segment_name_length = ARRAY_LEN (segment_name); + a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size; + a->options[APP_OPTIONS_RX_FIFO_SIZE] = + hsm->fifo_size ? hsm->fifo_size : 8 << 10; + a->options[APP_OPTIONS_TX_FIFO_SIZE] = + hsm->fifo_size ? hsm->fifo_size : 32 << 10; + a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN; + a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = hsm->prealloc_fifos; if (vnet_application_attach (a)) { @@ -516,12 +581,48 @@ server_create_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { http_server_main_t *hsm = &http_server_main; - int rv; - + int rv, is_static = 0; + u64 seg_size; + u8 *html; + + hsm->prealloc_fifos = 0; + hsm->private_segment_size = 0; + hsm->fifo_size = 0; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "static")) + is_static = 1; + else if (unformat (input, "prealloc-fifos %d", &hsm->prealloc_fifos)) + ; + else if (unformat (input, "private-segment-size %U", + unformat_memory_size, &seg_size)) + { + if (seg_size >= 0x100000000ULL) + { + vlib_cli_output (vm, "private segment size %llu, too large", + seg_size); + return 0; + } + hsm->private_segment_size = seg_size; + } + else if (unformat (input, "fifo-size %d", &hsm->fifo_size)) + hsm->fifo_size <<= 10; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } if (hsm->my_client_index != (u32) ~ 0) return clib_error_return (0, "test http server is already running"); vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); + + if (is_static) + { + builtin_session_cb_vft.builtin_server_rx_callback = + http_server_rx_callback_static; + html = format (0, html_header_static); + static_http = format (0, http_response, vec_len (html), html); + } rv = server_create (vm); switch (rv) { @@ -546,9 +647,13 @@ static clib_error_t * builtin_http_server_main_init (vlib_main_t * vm) { http_server_main_t *hsm = &http_server_main; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + u32 num_threads; + hsm->my_client_index = ~0; hsm->vlib_main = vm; - + num_threads = 1 /* main thread */ + vtm->n_threads; + vec_validate (hsm->rx_buf, num_threads - 1); return 0; }