diff options
Diffstat (limited to 'src/vlib')
-rw-r--r-- | src/vlib/buffer_node.h | 53 | ||||
-rw-r--r-- | src/vlib/threads.c | 15 | ||||
-rw-r--r-- | src/vlib/threads.h | 10 |
3 files changed, 57 insertions, 21 deletions
diff --git a/src/vlib/buffer_node.h b/src/vlib/buffer_node.h index cfdb0567a0c..93ffb1e9dce 100644 --- a/src/vlib/buffer_node.h +++ b/src/vlib/buffer_node.h @@ -443,28 +443,23 @@ vlib_buffer_enqueue_to_next (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_put_next_frame (vm, node, next_index, n_left_to_next); } -static_always_inline void +static_always_inline u32 vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, u32 * buffer_indices, u16 * thread_indices, - u32 n_left) + u32 n_packets, int drop_on_congestion) { vlib_thread_main_t *tm = vlib_get_thread_main (); - static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_thread_index = - 0; - static __thread vlib_frame_queue_t **congested_handoff_queue_by_thread_index - = 0; + vlib_frame_queue_main_t *fqm; + vlib_frame_queue_per_thread_data_t *ptd; + u32 n_left = n_packets; + u32 drop_list[VLIB_FRAME_SIZE], *dbi = drop_list, n_drop = 0; vlib_frame_queue_elt_t *hf = 0; u32 n_left_to_next_thread = 0, *to_next_thread = 0; u32 next_thread_index, current_thread_index = ~0; int i; - if (PREDICT_FALSE (handoff_queue_elt_by_thread_index == 0)) - { - vec_validate (handoff_queue_elt_by_thread_index, tm->n_vlib_mains - 1); - vec_validate_init_empty (congested_handoff_queue_by_thread_index, - tm->n_vlib_mains - 1, - (vlib_frame_queue_t *) (~0)); - } + fqm = vec_elt_at_index (tm->frame_queue_mains, frame_queue_index); + ptd = vec_elt_at_index (fqm->per_thread_data, vm->thread_index); while (n_left) { @@ -472,12 +467,24 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, if (next_thread_index != current_thread_index) { + + if (drop_on_congestion && + is_vlib_frame_queue_congested + (frame_queue_index, next_thread_index, fqm->queue_hi_thresh, + ptd->congested_handoff_queue_by_thread_index)) + { + dbi[0] = buffer_indices[0]; + dbi++; + n_drop++; + goto next; + } + if (hf) hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_thread; hf = vlib_get_worker_handoff_queue_elt (frame_queue_index, next_thread_index, - handoff_queue_elt_by_thread_index); + ptd->handoff_queue_elt_by_thread_index); n_left_to_next_thread = VLIB_FRAME_SIZE - hf->n_vectors; to_next_thread = &hf->buffer_index[hf->n_vectors]; @@ -493,11 +500,12 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, hf->n_vectors = VLIB_FRAME_SIZE; vlib_put_frame_queue_elt (hf); current_thread_index = ~0; - handoff_queue_elt_by_thread_index[next_thread_index] = 0; + ptd->handoff_queue_elt_by_thread_index[next_thread_index] = 0; hf = 0; } /* next */ + next: thread_indices += 1; buffer_indices += 1; n_left -= 1; @@ -507,11 +515,11 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_thread; /* Ship frames to the thread nodes */ - for (i = 0; i < vec_len (handoff_queue_elt_by_thread_index); i++) + for (i = 0; i < vec_len (ptd->handoff_queue_elt_by_thread_index); i++) { - if (handoff_queue_elt_by_thread_index[i]) + if (ptd->handoff_queue_elt_by_thread_index[i]) { - hf = handoff_queue_elt_by_thread_index[i]; + hf = ptd->handoff_queue_elt_by_thread_index[i]; /* * It works better to let the handoff node * rate-adapt, always ship the handoff queue element. @@ -519,14 +527,19 @@ vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, if (1 || hf->n_vectors == hf->last_n_vectors) { vlib_put_frame_queue_elt (hf); - handoff_queue_elt_by_thread_index[i] = 0; + ptd->handoff_queue_elt_by_thread_index[i] = 0; } else hf->last_n_vectors = hf->n_vectors; } - congested_handoff_queue_by_thread_index[i] = + ptd->congested_handoff_queue_by_thread_index[i] = (vlib_frame_queue_t *) (~0); } + + if (drop_on_congestion && n_drop) + vlib_buffer_free (vm, drop_list, n_drop); + + return n_packets - n_drop; } #endif /* included_vlib_buffer_node_h */ diff --git a/src/vlib/threads.c b/src/vlib/threads.c index c53c5d6c170..70f22b10fa1 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -24,7 +24,7 @@ DECLARE_CJ_GLOBAL_LOG; -#define FRAME_QUEUE_NELTS 32 +#define FRAME_QUEUE_NELTS 64 u32 vl (void *p) @@ -1795,16 +1795,29 @@ vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts) if (frame_queue_nelts == 0) frame_queue_nelts = FRAME_QUEUE_NELTS; + ASSERT (frame_queue_nelts >= 8); + vec_add2 (tm->frame_queue_mains, fqm, 1); fqm->node_index = node_index; + fqm->frame_queue_nelts = frame_queue_nelts; + fqm->queue_hi_thresh = frame_queue_nelts - 2; vec_validate (fqm->vlib_frame_queues, tm->n_vlib_mains - 1); + vec_validate (fqm->per_thread_data, tm->n_vlib_mains - 1); _vec_len (fqm->vlib_frame_queues) = 0; for (i = 0; i < tm->n_vlib_mains; i++) { + vlib_frame_queue_per_thread_data_t *ptd; fq = vlib_frame_queue_alloc (frame_queue_nelts); vec_add1 (fqm->vlib_frame_queues, fq); + + ptd = vec_elt_at_index (fqm->per_thread_data, i); + vec_validate (ptd->handoff_queue_elt_by_thread_index, + tm->n_vlib_mains - 1); + vec_validate_init_empty (ptd->congested_handoff_queue_by_thread_index, + tm->n_vlib_mains - 1, + (vlib_frame_queue_t *) (~0)); } return (fqm - tm->frame_queue_mains); diff --git a/src/vlib/threads.h b/src/vlib/threads.h index f78ec1b9fa5..b47a633c2cc 100644 --- a/src/vlib/threads.h +++ b/src/vlib/threads.h @@ -163,8 +163,18 @@ vlib_frame_queue_t; typedef struct { + vlib_frame_queue_elt_t **handoff_queue_elt_by_thread_index; + vlib_frame_queue_t **congested_handoff_queue_by_thread_index; +} vlib_frame_queue_per_thread_data_t; + +typedef struct +{ u32 node_index; + u32 frame_queue_nelts; + u32 queue_hi_thresh; + vlib_frame_queue_t **vlib_frame_queues; + vlib_frame_queue_per_thread_data_t *per_thread_data; /* for frame queue tracing */ frame_queue_trace_t *frame_queue_traces; |