aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/hs_apps/http_client.c362
-rw-r--r--src/vcl/ldp.c26
-rw-r--r--src/vnet/fib/ip4_fib.c5
-rw-r--r--src/vnet/pg/pg.h51
-rw-r--r--src/vpp-api/python/setup.py2
-rw-r--r--src/vpp-api/python/vpp_papi/__init__.py9
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_papi.py9
7 files changed, 296 insertions, 168 deletions
diff --git a/src/plugins/hs_apps/http_client.c b/src/plugins/hs_apps/http_client.c
index 05a87ec7de8..a86bf1f3db3 100644
--- a/src/plugins/hs_apps/http_client.c
+++ b/src/plugins/hs_apps/http_client.c
@@ -23,9 +23,19 @@ typedef struct
typedef struct
{
+ u64 request_count;
+ f64 start, end;
+ f64 elapsed_time;
+} hc_stats_t;
+
+typedef struct
+{
hc_session_t *sessions;
u32 thread_index;
vlib_main_t *vlib_main;
+ u8 *headers_buf;
+ http_header_t *req_headers;
+ http_msg_t msg;
} hc_worker_t;
typedef struct
@@ -36,7 +46,6 @@ typedef struct
u8 *uri;
session_endpoint_cfg_t connect_sep;
u8 *target;
- u8 *headers_buf;
u8 *data;
u64 data_offset;
hc_worker_t *wrk;
@@ -50,6 +59,9 @@ typedef struct
bool verbose;
f64 timeout;
http_req_method_t req_method;
+ u64 repeat_count;
+ f64 duration;
+ bool repeat;
} hc_main_t;
typedef enum
@@ -57,9 +69,12 @@ typedef enum
HC_CONNECT_FAILED = 1,
HC_TRANSPORT_CLOSED,
HC_REPLY_RECEIVED,
+ HC_GENERIC_ERR,
+ HC_REPEAT_DONE,
} hc_cli_signal_t;
static hc_main_t hc_main;
+static hc_stats_t hc_stats;
static inline hc_worker_t *
hc_worker_get (u32 thread_index)
@@ -95,39 +110,94 @@ hc_session_alloc (hc_worker_t *wrk)
}
static int
-hc_session_connected_callback (u32 app_index, u32 hc_session_index,
- session_t *s, session_error_t err)
+hc_request (session_t *s, session_error_t err)
{
hc_main_t *hcm = &hc_main;
- hc_session_t *hc_session, *new_hc_session;
- hc_worker_t *wrk;
- http_msg_t msg;
u64 to_send;
u32 n_enq;
u8 n_segs;
int rv;
- http_header_ht_t *header;
- http_header_t *req_headers = 0;
- u32 new_hc_index;
+ hc_worker_t *wrk = hc_worker_get (s->thread_index);
+
+ if (hcm->use_ptr)
+ {
+ uword target = pointer_to_uword (hcm->target);
+ uword headers = pointer_to_uword (wrk->headers_buf);
+ uword body = pointer_to_uword (hcm->data);
+ svm_fifo_seg_t segs[4] = {
+ { (u8 *) &wrk->msg, sizeof (wrk->msg) },
+ { (u8 *) &target, sizeof (target) },
+ { (u8 *) &headers, sizeof (headers) },
+ { (u8 *) &body, sizeof (body) },
+ };
+
+ n_segs = (hcm->req_method == HTTP_REQ_GET) ? 3 : 4;
+ rv = svm_fifo_enqueue_segments (s->tx_fifo, segs, n_segs,
+ 0 /* allow partial */);
+ if (hcm->req_method == HTTP_REQ_POST)
+ ASSERT (rv == (sizeof (wrk->msg) + sizeof (target) + sizeof (headers) +
+ sizeof (body)));
+ else
+ ASSERT (rv ==
+ (sizeof (wrk->msg) + sizeof (target) + sizeof (headers)));
+ goto done;
+ }
+
+ rv = svm_fifo_enqueue (s->tx_fifo, sizeof (wrk->msg), (u8 *) &wrk->msg);
+ ASSERT (rv == sizeof (wrk->msg));
+
+ rv = svm_fifo_enqueue (s->tx_fifo, vec_len (hcm->target), hcm->target);
+ ASSERT (rv == vec_len (hcm->target));
+
+ rv = svm_fifo_enqueue (s->tx_fifo, vec_len (wrk->headers_buf),
+ wrk->headers_buf);
+ ASSERT (rv == wrk->msg.data.headers_len);
+
+ if (hcm->req_method == HTTP_REQ_POST)
+ {
+ to_send = vec_len (hcm->data);
+ n_enq = clib_min (svm_fifo_size (s->tx_fifo), to_send);
+
+ rv = svm_fifo_enqueue (s->tx_fifo, n_enq, hcm->data);
+ if (rv < to_send)
+ {
+ hcm->data_offset = (rv > 0) ? rv : 0;
+ svm_fifo_add_want_deq_ntf (s->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
+ }
+ }
+
+done:
+ if (svm_fifo_set_event (s->tx_fifo))
+ {
+ session_program_tx_io_evt (s->handle, SESSION_IO_EVT_TX);
+ }
+ return 0;
+}
+static int
+hc_session_connected_callback (u32 app_index, u32 hc_session_index,
+ session_t *s, session_error_t err)
+{
+ hc_main_t *hcm = &hc_main;
+ hc_worker_t *wrk;
+ u32 new_hc_index;
+ http_header_ht_t *header;
HTTP_DBG (1, "ho hc_index: %d", hc_session_index);
if (err)
{
clib_warning ("hc_session_index[%d] connected error: %U",
hc_session_index, format_session_error, err);
- vlib_process_signal_event_mt (hcm->wrk->vlib_main, hcm->cli_node_index,
- HC_CONNECT_FAILED, 0);
+ vlib_process_signal_event_mt (vlib_get_main_by_index (s->thread_index),
+ hcm->cli_node_index, HC_CONNECT_FAILED, 0);
return -1;
}
- hc_session = hc_session_get (hc_session_index, 0);
wrk = hc_worker_get (s->thread_index);
- new_hc_session = hc_session_alloc (wrk);
+ hc_session_t *hc_session, *new_hc_session = hc_session_alloc (wrk);
+ hc_session = hc_session_get (hc_session_index, 0);
new_hc_index = new_hc_session->session_index;
clib_memcpy_fast (new_hc_session, hc_session, sizeof (*hc_session));
- hc_session->vpp_session_index = s->session_index;
-
new_hc_session->session_index = new_hc_index;
new_hc_session->thread_index = s->thread_index;
new_hc_session->vpp_session_index = s->session_index;
@@ -138,104 +208,64 @@ hc_session_connected_callback (u32 app_index, u32 hc_session_index,
{
if (hcm->is_file)
http_add_header (
- &req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ &wrk->req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
http_content_type_token (HTTP_CONTENT_APP_OCTET_STREAM));
else
http_add_header (
- &req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ &wrk->req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
http_content_type_token (HTTP_CONTENT_APP_X_WWW_FORM_URLENCODED));
}
vec_foreach (header, hcm->custom_header)
- http_add_header (&req_headers, (const char *) header->name,
+ http_add_header (&wrk->req_headers, (const char *) header->name,
vec_len (header->name), (const char *) header->value,
vec_len (header->value));
- hcm->headers_buf = http_serialize_headers (req_headers);
- vec_free (req_headers);
+ wrk->headers_buf = http_serialize_headers (wrk->req_headers);
+ vec_free (wrk->req_headers);
- msg.method_type = hcm->req_method;
+ wrk->msg.method_type = hcm->req_method;
if (hcm->req_method == HTTP_REQ_POST)
- msg.data.body_len = vec_len (hcm->data);
+ wrk->msg.data.body_len = vec_len (hcm->data);
else
- msg.data.body_len = 0;
+ wrk->msg.data.body_len = 0;
- msg.type = HTTP_MSG_REQUEST;
+ wrk->msg.type = HTTP_MSG_REQUEST;
/* request target */
- msg.data.target_form = HTTP_TARGET_ORIGIN_FORM;
- msg.data.target_path_len = vec_len (hcm->target);
+ wrk->msg.data.target_form = HTTP_TARGET_ORIGIN_FORM;
+ wrk->msg.data.target_path_len = vec_len (hcm->target);
/* custom headers */
- msg.data.headers_len = vec_len (hcm->headers_buf);
+ wrk->msg.data.headers_len = vec_len (wrk->headers_buf);
/* total length */
- msg.data.len =
- msg.data.target_path_len + msg.data.headers_len + msg.data.body_len;
+ wrk->msg.data.len = wrk->msg.data.target_path_len +
+ wrk->msg.data.headers_len + wrk->msg.data.body_len;
if (hcm->use_ptr)
{
- uword target = pointer_to_uword (hcm->target);
- uword headers = pointer_to_uword (hcm->headers_buf);
- uword body = pointer_to_uword (hcm->data);
- msg.data.type = HTTP_MSG_DATA_PTR;
- svm_fifo_seg_t segs[4] = {
- { (u8 *) &msg, sizeof (msg) },
- { (u8 *) &target, sizeof (target) },
- { (u8 *) &headers, sizeof (headers) },
- { (u8 *) &body, sizeof (body) },
- };
-
- n_segs = (hcm->req_method == HTTP_REQ_GET) ? 3 : 4;
- rv = svm_fifo_enqueue_segments (s->tx_fifo, segs, n_segs,
- 0 /* allow partial */);
- if (hcm->req_method == HTTP_REQ_POST)
- ASSERT (rv == (sizeof (msg) + sizeof (target) + sizeof (headers) +
- sizeof (body)));
- else
- ASSERT (rv == (sizeof (msg) + sizeof (target) + sizeof (headers)));
- goto done;
+ wrk->msg.data.type = HTTP_MSG_DATA_PTR;
}
-
- msg.data.type = HTTP_MSG_DATA_INLINE;
- msg.data.target_path_offset = 0;
- msg.data.headers_offset = msg.data.target_path_len;
- msg.data.body_offset = msg.data.headers_offset + msg.data.headers_len;
-
- rv = svm_fifo_enqueue (s->tx_fifo, sizeof (msg), (u8 *) &msg);
- ASSERT (rv == sizeof (msg));
-
- rv = svm_fifo_enqueue (s->tx_fifo, vec_len (hcm->target), hcm->target);
- ASSERT (rv == vec_len (hcm->target));
-
- rv = svm_fifo_enqueue (s->tx_fifo, vec_len (hcm->headers_buf),
- hcm->headers_buf);
- ASSERT (rv == msg.data.headers_len);
-
- if (hcm->req_method == HTTP_REQ_POST)
+ else
{
- to_send = vec_len (hcm->data);
- n_enq = clib_min (svm_fifo_size (s->tx_fifo), to_send);
-
- rv = svm_fifo_enqueue (s->tx_fifo, n_enq, hcm->data);
- if (rv < to_send)
- {
- hcm->data_offset = (rv > 0) ? rv : 0;
- svm_fifo_add_want_deq_ntf (s->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
- }
+ wrk->msg.data.type = HTTP_MSG_DATA_INLINE;
+ wrk->msg.data.target_path_offset = 0;
+ wrk->msg.data.headers_offset = wrk->msg.data.target_path_len;
+ wrk->msg.data.body_offset =
+ wrk->msg.data.headers_offset + wrk->msg.data.headers_len;
}
-done:
- if (svm_fifo_set_event (s->tx_fifo))
- session_program_tx_io_evt (s->handle, SESSION_IO_EVT_TX);
+ if (hcm->repeat)
+ hc_stats.start = vlib_time_now (vlib_get_main_by_index (s->thread_index));
- return 0;
+ return hc_request (s, err);
}
static void
hc_session_disconnect_callback (session_t *s)
{
hc_main_t *hcm = &hc_main;
+ HTTP_DBG (1, "disconnecting");
vnet_disconnect_args_t _a = { 0 }, *a = &_a;
int rv;
-
a->handle = session_handle (s);
a->app_index = hcm->app_index;
if ((rv = vnet_disconnect_session (a)))
@@ -252,10 +282,10 @@ hc_session_transport_closed_callback (session_t *s)
}
static void
-hc_ho_cleanup_callback (session_t *ts)
+hc_ho_cleanup_callback (session_t *s)
{
- HTTP_DBG (1, "ho hc_index: %d:", ts->opaque);
- hc_ho_session_free (ts->opaque);
+ HTTP_DBG (1, "ho hc_index: %d:", s->opaque);
+ hc_ho_session_free (s->opaque);
}
static void
@@ -280,9 +310,12 @@ static int
hc_rx_callback (session_t *s)
{
hc_main_t *hcm = &hc_main;
+ hc_worker_t *wrk = hc_worker_get (s->thread_index);
hc_session_t *hc_session;
http_msg_t msg;
int rv;
+ session_error_t session_err = 0;
+ int send_err = 0;
hc_session = hc_session_get (s->opaque, s->thread_index);
@@ -300,28 +333,35 @@ hc_rx_callback (session_t *s)
if (msg.type != HTTP_MSG_REPLY)
{
clib_warning ("unexpected msg type %d", msg.type);
+ vlib_process_signal_event_mt (wrk->vlib_main, hcm->cli_node_index,
+ HC_GENERIC_ERR, 0);
return -1;
}
if (msg.data.headers_len)
{
+ hcm->response_status =
+ format (0, "%U", format_http_status_code, msg.code);
+ svm_fifo_dequeue_drop (s->rx_fifo, msg.data.headers_offset);
+
http_header_table_t *ht;
vec_validate (hcm->resp_headers, msg.data.headers_len - 1);
- rv = svm_fifo_peek (s->rx_fifo, msg.data.headers_offset,
- msg.data.headers_len, hcm->resp_headers);
+ vec_set_len (hcm->resp_headers, msg.data.headers_len);
+ rv = svm_fifo_dequeue (s->rx_fifo, msg.data.headers_len,
+ hcm->resp_headers);
ASSERT (rv == msg.data.headers_len);
- HTTP_DBG (1, (char *) hcm->resp_headers);
-
+ HTTP_DBG (1, (char *) format (0, "%v", hcm->resp_headers));
if (http_parse_headers (hcm->resp_headers, &ht))
{
clib_warning ("invalid headers received");
+ vlib_process_signal_event_mt (
+ wrk->vlib_main, hcm->cli_node_index, HC_GENERIC_ERR, 0);
return -1;
}
http_free_header_table (ht);
-
- hcm->response_status =
- format (0, "%U", format_http_status_code, msg.code);
+ msg.data.body_offset -=
+ msg.data.headers_len + msg.data.headers_offset;
}
if (msg.data.body_len == 0)
@@ -342,13 +382,18 @@ hc_rx_callback (session_t *s)
}
u32 max_deq = svm_fifo_max_dequeue (s->rx_fifo);
-
+ if (!max_deq)
+ {
+ goto done;
+ }
u32 n_deq = clib_min (hc_session->to_recv, max_deq);
u32 curr = vec_len (hcm->http_response);
rv = svm_fifo_dequeue (s->rx_fifo, n_deq, hcm->http_response + curr);
if (rv < 0)
{
clib_warning ("app dequeue(n=%d) failed; rv = %d", n_deq, rv);
+ vlib_process_signal_event_mt (wrk->vlib_main, hcm->cli_node_index,
+ HC_GENERIC_ERR, 0);
return -1;
}
@@ -360,11 +405,33 @@ hc_rx_callback (session_t *s)
done:
if (hc_session->to_recv == 0)
{
- hc_session_disconnect_callback (s);
- vlib_process_signal_event_mt (hcm->wrk->vlib_main, hcm->cli_node_index,
- HC_REPLY_RECEIVED, 0);
- }
+ if (hcm->repeat)
+ {
+ hc_stats.request_count++;
+ hc_stats.end = vlib_time_now (wrk->vlib_main);
+ hc_stats.elapsed_time = hc_stats.end - hc_stats.start;
+ if (hc_stats.elapsed_time >= hcm->duration &&
+ hc_stats.request_count >= hcm->repeat_count)
+ {
+ vlib_process_signal_event_mt (
+ wrk->vlib_main, hcm->cli_node_index, HC_REPEAT_DONE, 0);
+ hc_session_disconnect_callback (s);
+ }
+ else
+ {
+ send_err = hc_request (s, session_err);
+ if (send_err)
+ clib_warning ("failed to send request, error %d", send_err);
+ }
+ }
+ else
+ {
+ vlib_process_signal_event_mt (wrk->vlib_main, hcm->cli_node_index,
+ HC_REPLY_RECEIVED, 0);
+ hc_session_disconnect_callback (s);
+ }
+ }
return 0;
}
@@ -455,6 +522,7 @@ hc_connect ()
vnet_connect_args_t *a = 0;
hc_worker_t *wrk;
hc_session_t *hc_session;
+ transport_endpt_ext_cfg_t *ext_cfg;
vec_validate (a, 0);
clib_memset (a, 0, sizeof (a[0]));
@@ -462,6 +530,10 @@ hc_connect ()
clib_memcpy (&a->sep_ext, &hcm->connect_sep, sizeof (hcm->connect_sep));
a->app_index = hcm->app_index;
+ ext_cfg = session_endpoint_add_ext_cfg (
+ &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_HTTP, sizeof (ext_cfg->opaque));
+ ext_cfg->opaque = hcm->timeout;
+
/* allocate http session on main thread */
wrk = hc_worker_get (0);
hc_session = hc_session_alloc (wrk);
@@ -472,29 +544,19 @@ hc_connect ()
}
static clib_error_t *
-hc_run (vlib_main_t *vm)
+hc_get_event (vlib_main_t *vm)
{
hc_main_t *hcm = &hc_main;
- vlib_thread_main_t *vtm = vlib_get_thread_main ();
- u32 num_threads;
- hc_worker_t *wrk;
uword event_type, *event_data = 0;
- clib_error_t *err;
+ clib_error_t *err = NULL;
FILE *file_ptr;
+ u64 event_timeout = 10;
- num_threads = 1 /* main thread */ + vtm->n_threads;
- vec_validate (hcm->wrk, num_threads - 1);
- vec_foreach (wrk, hcm->wrk)
- wrk->thread_index = wrk - hcm->wrk;
-
- if ((err = hc_attach ()))
- return clib_error_return (0, "http client attach: %U", format_clib_error,
- err);
-
- hc_connect ();
-
- vlib_process_wait_for_event_or_clock (vm, hcm->timeout);
+ if (event_timeout == hcm->timeout || event_timeout == hcm->duration)
+ event_timeout += 5;
+ vlib_process_wait_for_event_or_clock (vm, event_timeout);
event_type = vlib_process_get_events (vm, &event_data);
+
switch (event_type)
{
case ~0:
@@ -506,11 +568,14 @@ hc_run (vlib_main_t *vm)
case HC_TRANSPORT_CLOSED:
err = clib_error_return (0, "error: transport closed");
break;
+ case HC_GENERIC_ERR:
+ err = clib_error_return (0, "error: unknown");
+ break;
case HC_REPLY_RECEIVED:
if (hcm->filename)
{
file_ptr =
- fopen ((char *) format (0, "/tmp/%v", hcm->filename), "w");
+ fopen ((char *) format (0, "/tmp/%v", hcm->filename), "a");
if (file_ptr == NULL)
{
vlib_cli_output (vm, "couldn't open file %v", hcm->filename);
@@ -524,10 +589,17 @@ hc_run (vlib_main_t *vm)
}
}
if (hcm->verbose)
- vlib_cli_output (vm, "< %v\n< %v", hcm->response_status,
+ vlib_cli_output (vm, "< %v< %v", hcm->response_status,
hcm->resp_headers);
- vlib_cli_output (vm, "<\n%v", hcm->http_response);
-
+ vlib_cli_output (vm, "\n%v\n", hcm->http_response);
+ break;
+ case HC_REPEAT_DONE:
+ vlib_cli_output (vm,
+ "< %d request(s) in %.6fs\n< avg latency "
+ "%.4fms\n< %.2f req/sec",
+ hc_stats.request_count, hc_stats.elapsed_time,
+ (hc_stats.elapsed_time / hc_stats.request_count) * 1000,
+ hc_stats.request_count / hc_stats.elapsed_time);
break;
default:
err = clib_error_return (0, "error: unexpected event %d", event_type);
@@ -538,6 +610,29 @@ hc_run (vlib_main_t *vm)
return err;
}
+static clib_error_t *
+hc_run (vlib_main_t *vm)
+{
+ hc_main_t *hcm = &hc_main;
+ vlib_thread_main_t *vtm = vlib_get_thread_main ();
+ u32 num_threads;
+ hc_worker_t *wrk;
+ clib_error_t *err;
+
+ num_threads = 1 /* main thread */ + vtm->n_threads;
+ vec_validate (hcm->wrk, num_threads - 1);
+ vec_foreach (wrk, hcm->wrk)
+ wrk->thread_index = wrk - hcm->wrk;
+
+ if ((err = hc_attach ()))
+ return clib_error_return (0, "http client attach: %U", format_clib_error,
+ err);
+
+ hc_connect ();
+
+ return hc_get_event (vm);
+}
+
static int
hc_detach ()
{
@@ -560,12 +655,15 @@ hc_detach ()
static void
hcc_worker_cleanup (hc_worker_t *wrk)
{
+ HTTP_DBG (1, "worker cleanup");
+ vec_free (wrk->headers_buf);
pool_free (wrk->sessions);
}
static void
hc_cleanup ()
{
+ HTTP_DBG (1, "cleanup");
hc_main_t *hcm = &hc_main;
hc_worker_t *wrk;
http_header_ht_t *header;
@@ -575,7 +673,6 @@ hc_cleanup ()
vec_free (hcm->uri);
vec_free (hcm->target);
- vec_free (hcm->headers_buf);
vec_free (hcm->data);
vec_free (hcm->resp_headers);
vec_free (hcm->http_response);
@@ -604,12 +701,14 @@ hc_command_fn (vlib_main_t *vm, unformat_input_t *input,
u8 *value;
int rv;
hcm->timeout = 10;
+ hcm->repeat_count = 0;
+ hcm->duration = 0;
+ hcm->repeat = false;
+ hc_stats.request_count = 0;
if (hcm->attached)
return clib_error_return (0, "failed: already running!");
- hcm->use_ptr = 0;
-
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, "expected required arguments");
@@ -652,6 +751,12 @@ hc_command_fn (vlib_main_t *vm, unformat_input_t *input,
hcm->verbose = true;
else if (unformat (line_input, "timeout %f", &hcm->timeout))
;
+ else if (unformat (line_input, "repeat %d", &hcm->repeat_count))
+ {
+ hcm->repeat = true;
+ }
+ else if (unformat (line_input, "duration %f", &hcm->duration))
+ hcm->repeat = true;
else
{
err = clib_error_return (0, "unknown input `%U'",
@@ -685,6 +790,12 @@ hc_command_fn (vlib_main_t *vm, unformat_input_t *input,
goto done;
}
}
+ if (hcm->duration && hcm->repeat_count)
+ {
+ err = clib_error_return (
+ 0, "combining duration and repeat is not supported");
+ goto done;
+ }
if ((rv = parse_uri ((char *) hcm->uri, &hcm->connect_sep)))
{
@@ -693,6 +804,9 @@ hc_command_fn (vlib_main_t *vm, unformat_input_t *input,
goto done;
}
+ if (hcm->repeat)
+ vlib_cli_output (vm, "Running, please wait...");
+
session_enable_disable_args_t args = { .is_en = 1,
.rt_engine_type =
RT_BACKEND_ENGINE_RULE_TABLE };
@@ -701,7 +815,6 @@ hc_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_worker_thread_barrier_release (vm);
hcm->cli_node_index = vlib_get_current_process (vm)->node_runtime.node_index;
-
err = hc_run (vm);
if ((rv = hc_detach ()))
@@ -724,10 +837,11 @@ done:
VLIB_CLI_COMMAND (hc_command, static) = {
.path = "http client",
- .short_help = "[post] uri http://<ip-addr> target <origin-form> "
- "[data <form-urlencoded> | file <file-path>] [use-ptr] "
- "[save-to <filename>] [header <Key:Value>] [verbose] "
- "[timeout <seconds> (default = 10)]",
+ .short_help =
+ "[post] uri http://<ip-addr> target <origin-form> "
+ "[data <form-urlencoded> | file <file-path>] [use-ptr] "
+ "[save-to <filename>] [header <Key:Value>] [verbose] "
+ "[timeout <seconds> (default = 10)] [repeat <count> | duration <seconds>]",
.function = hc_command_fn,
.is_mp_safe = 1,
};
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c
index 4510bf85e1b..befb30851cd 100644
--- a/src/vcl/ldp.c
+++ b/src/vcl/ldp.c
@@ -105,6 +105,8 @@ typedef struct ldp_worker_ctx_
int vcl_mq_epfd;
} ldp_worker_ctx_t;
+__thread ldp_worker_ctx_t _ldp_worker = {};
+
/* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
* they are the same size */
STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
@@ -114,7 +116,6 @@ STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
typedef struct
{
- ldp_worker_ctx_t *workers;
int init;
char app_name[LDP_APP_NAME_MAX];
u32 vlsh_bit_val;
@@ -154,7 +155,7 @@ static ldp_main_t *ldp = &ldp_main;
static inline ldp_worker_ctx_t *
ldp_worker_get_current (void)
{
- return (ldp->workers + vppcom_worker_index ());
+ return &_ldp_worker;
}
/*
@@ -191,14 +192,6 @@ ldp_fd_to_vlsh (int fd)
}
static void
-ldp_alloc_workers (void)
-{
- if (ldp->workers)
- return;
- ldp->workers = vec_new (ldp_worker_ctx_t, LDP_MAX_NWORKERS);
-}
-
-static void
ldp_init_cfg (void)
{
char *env_var_str = getenv (LDP_ENV_DEBUG);
@@ -285,7 +278,6 @@ ldp_init_cfg (void)
static int
ldp_init (void)
{
- ldp_worker_ctx_t *ldpw;
int rv;
if (ldp->init)
@@ -311,10 +303,6 @@ ldp_init (void)
return rv;
}
ldp->vcl_needs_real_epoll = 0;
- ldp_alloc_workers ();
-
- vec_foreach (ldpw, ldp->workers)
- clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
LDBG (0, "LDP initialization: done!");
@@ -2397,14 +2385,9 @@ epoll_create1 (int flags)
if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
{
- /* Make sure workers have been allocated */
- if (!ldp->workers)
- {
- ldp_alloc_workers ();
- ldpw = ldp_worker_get_current ();
- }
rv = libc_epoll_create1 (flags);
ldp->vcl_needs_real_epoll = 0;
+ /* Assume this is a request to create the mq epfd */
ldpw->vcl_mq_epfd = rv;
LDBG (0, "created vcl epfd %u", rv);
return rv;
@@ -2665,6 +2648,7 @@ ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
if (PREDICT_FALSE (!ldpw->mq_epfd_added))
{
struct epoll_event e = { 0 };
+ ldpw->vcl_mq_epfd = vppcom_mq_epoll_fd ();
e.events = EPOLLIN;
e.data.fd = ldpw->vcl_mq_epfd;
if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c
index 23f70a770bf..b1198564754 100644
--- a/src/vnet/fib/ip4_fib.c
+++ b/src/vnet/fib/ip4_fib.c
@@ -354,8 +354,7 @@ ip4_show_fib (vlib_main_t * vm,
else if (unformat (input, "mtrie"))
mtrie = 1;
- else if (unformat (input, "mem") ||
- unformat (input, "memory"))
+ else if (unformat (input, "memory") || unformat (input, "mem"))
memory = 1;
else if (unformat (input, "%U/%d",
@@ -620,7 +619,7 @@ ip4_show_fib (vlib_main_t * vm,
?*/
VLIB_CLI_COMMAND (ip4_show_fib_command, static) = {
.path = "show ip fib",
- .short_help = "show ip fib [summary] [table <table-id>] [index <fib-id>] [<ip4-addr>[/<mask>]] [mtrie] [detail]",
+ .short_help = "show ip fib [summary] [table <table-id>] [index <fib-id>] [<ip4-addr>[/<mask>]] [mtrie] [detail] [memory]",
.function = ip4_show_fib,
};
diff --git a/src/vnet/pg/pg.h b/src/vnet/pg/pg.h
index 5e99d9af9f6..5e63b58caf6 100644
--- a/src/vnet/pg/pg.h
+++ b/src/vnet/pg/pg.h
@@ -182,14 +182,38 @@ typedef struct pg_stream_t
} pg_stream_t;
always_inline void
-pg_buffer_index_free (pg_buffer_index_t * bi)
+pg_free_buffers (pg_buffer_index_t *bi)
{
vlib_main_t *vm = vlib_get_main ();
- word n_alloc;
- vec_free (bi->edits);
- n_alloc = clib_fifo_elts (bi->buffer_fifo);
- vlib_buffer_free (vm, bi->buffer_fifo, n_alloc);
- clib_fifo_free (bi->buffer_fifo);
+ uword n_elts, head, len;
+
+ if (!bi || !bi->buffer_fifo)
+ return;
+
+ n_elts = clib_fifo_elts (bi->buffer_fifo);
+ if (n_elts)
+ {
+ len = clib_fifo_len (bi->buffer_fifo);
+ head = clib_fifo_head_index (bi->buffer_fifo);
+
+ if (head + n_elts <= len)
+ vlib_buffer_free (vm, &bi->buffer_fifo[head], n_elts);
+ else
+ {
+ vlib_buffer_free (vm, &bi->buffer_fifo[head], len - head);
+ vlib_buffer_free (vm, bi->buffer_fifo, n_elts - (len - head));
+ }
+ }
+}
+
+always_inline void
+pg_buffer_index_free (pg_buffer_index_t *bi)
+{
+ if (bi)
+ {
+ vec_free (bi->edits);
+ clib_fifo_free (bi->buffer_fifo);
+ }
}
always_inline void
@@ -220,11 +244,16 @@ pg_stream_free (pg_stream_t * s)
vec_free (s->replay_packet_templates);
vec_free (s->replay_packet_timestamps);
- {
- pg_buffer_index_t *bi;
- vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
- vec_free (s->buffer_indices);
- }
+ if (s->buffer_indices)
+ {
+ pg_buffer_index_t *bi;
+ // We only need to free the buffers from the first array, as the buffers
+ // are chained when packet-generator enable is issued.
+ pg_free_buffers (s->buffer_indices);
+ vec_foreach (bi, s->buffer_indices)
+ pg_buffer_index_free (bi);
+ vec_free (s->buffer_indices);
+ }
}
always_inline int
diff --git a/src/vpp-api/python/setup.py b/src/vpp-api/python/setup.py
index 784013fc606..832b6386352 100644
--- a/src/vpp-api/python/setup.py
+++ b/src/vpp-api/python/setup.py
@@ -21,7 +21,7 @@ requirements = []
setup(
name="vpp_papi",
- version="2.1.0",
+ version="2.2.0",
description="VPP Python binding",
author="Ole Troan",
author_email="ot@cisco.com",
diff --git a/src/vpp-api/python/vpp_papi/__init__.py b/src/vpp-api/python/vpp_papi/__init__.py
index dc58c1e18cb..80a374ce1bb 100644
--- a/src/vpp-api/python/vpp_papi/__init__.py
+++ b/src/vpp-api/python/vpp_papi/__init__.py
@@ -10,9 +10,10 @@ from .vpp_serializer import BaseTypes # noqa: F401
from .vpp_serializer import VPPEnumType, VPPType, VPPTypeAlias # noqa: F401
from .vpp_serializer import VPPMessage, VPPUnionType # noqa: F401
-import pkg_resources # part of setuptools
+import importlib.metadata as metadata
try:
- __version__ = pkg_resources.get_distribution("vpp_papi").version
-except pkg_resources.DistributionNotFound:
- """Can't find vpp_papi via setuptools"""
+ __version__ = metadata.version("vpp_papi")
+except metadata.PackageNotFoundError:
+ # Can't find vpp_papi via importlib.metadata
+ __version__ = "0.0.0"
diff --git a/src/vpp-api/python/vpp_papi/vpp_papi.py b/src/vpp-api/python/vpp_papi/vpp_papi.py
index 30c00cd8dd3..61e67d162be 100644
--- a/src/vpp-api/python/vpp_papi/vpp_papi.py
+++ b/src/vpp-api/python/vpp_papi/vpp_papi.py
@@ -29,7 +29,8 @@ import fnmatch
import weakref
import atexit
import time
-import pkg_resources
+import importlib.resources as resources
+
from .vpp_format import verify_enum_hint
from .vpp_serializer import VPPType, VPPEnumType, VPPEnumFlagType, VPPUnionType
from .vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias
@@ -502,10 +503,10 @@ class VPPApiClient:
raise e
else:
# Bootstrap the API (memclnt.api bundled with VPP PAPI)
- resource_path = "/".join(("data", "memclnt.api.json"))
- file_content = pkg_resources.resource_string(__name__, resource_path)
+ with resources.open_text("vpp_papi.data", "memclnt.api.json") as f:
+ resource_content = f.read()
self.messages, self.services = VPPApiJSONFiles.process_json_str(
- file_content
+ resource_content
)
# Basic sanity check