X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffib%2Ffib_walk.c;h=64c2527b7b6556d38b75dd40024463c05ebc2bfd;hb=28eedf4e890a258a7a68b4a5414c74a8d708e7a6;hp=938f7b8c1c69091f56f9a57e1ccbab0cdeb7d74d;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/fib/fib_walk.c b/src/vnet/fib/fib_walk.c index 938f7b8c1c6..64c2527b7b6 100644 --- a/src/vnet/fib/fib_walk.c +++ b/src/vnet/fib/fib_walk.c @@ -16,6 +16,8 @@ #include #include +vlib_log_class_t fib_walk_logger; + /** * The flags on a walk */ @@ -95,11 +97,6 @@ typedef struct fib_walk_t_ */ static fib_walk_t *fib_walk_pool; -/** - * @brief There's only one event type sent to the walk process - */ -#define FIB_WALK_EVENT 0 - /** * Statistics maintained per-walk queue */ @@ -189,19 +186,30 @@ typedef struct fib_walk_history_t_ { } fib_walk_history_t; static fib_walk_history_t fib_walk_history[HISTORY_N_WALKS]; +static u8* format_fib_walk (u8* s, va_list *ap); + +#define FIB_WALK_DBG(_walk, _fmt, _args...) \ +{ \ + vlib_log_debug(fib_walk_logger, \ + "[%U]:" _fmt, \ + format_fib_walk, \ + fib_walk_get_index(_walk), \ + ##_args); \ +} + u8* -format_fib_walk_priority (u8 *s, va_list ap) +format_fib_walk_priority (u8 *s, va_list *ap) { - fib_walk_priority_t prio = va_arg(ap, fib_walk_priority_t); + fib_walk_priority_t prio = va_arg(*ap, fib_walk_priority_t); ASSERT(prio < FIB_WALK_PRIORITY_NUM); return (format(s, "%s", fib_walk_priority_names[prio])); } static u8* -format_fib_walk_queue_stats (u8 *s, va_list ap) +format_fib_walk_queue_stats (u8 *s, va_list *ap) { - fib_walk_queue_stats_t wqs = va_arg(ap, fib_walk_queue_stats_t); + fib_walk_queue_stats_t wqs = va_arg(*ap, fib_walk_queue_stats_t); ASSERT(wqs < FIB_WALK_QUEUE_STATS_NUM); @@ -240,10 +248,13 @@ fib_walk_queue_get_front (fib_walk_priority_t prio) } static void -fib_walk_destroy (fib_walk_t *fwalk) +fib_walk_destroy (index_t fwi) { + fib_walk_t *fwalk; u32 bucket, ii; + fwalk = fib_walk_get(fwi); + if (FIB_NODE_INDEX_INVALID != fwalk->fw_prio_sibling) { fib_node_list_elt_remove(fwalk->fw_prio_sibling); @@ -252,6 +263,12 @@ fib_walk_destroy (fib_walk_t *fwalk) fwalk->fw_parent.fnp_index, fwalk->fw_dep_sibling); + /* + * refetch the walk object. More walks could have been spawned as a result + * of releasing the lock on the parent. + */ + fwalk = fib_walk_get(fwi); + /* * add the stats to the continuous histogram collection. */ @@ -318,10 +335,10 @@ typedef enum fib_walk_advance_rc_t_ static fib_walk_advance_rc_t fib_walk_advance (fib_node_index_t fwi) { - fib_node_back_walk_ctx_t *ctx, *old; fib_node_back_walk_rc_t wrc; fib_node_ptr_t sibling; fib_walk_t *fwalk; + uint n_ctxs, ii; int more_elts; /* @@ -335,12 +352,20 @@ fib_walk_advance (fib_node_index_t fwi) if (more_elts) { - old = fwalk->fw_ctx; - vec_foreach(ctx, fwalk->fw_ctx) - { - wrc = fib_node_back_walk_one(&sibling, ctx); + /* + * loop through the backwalk contexts. This can grow in length + * as walks on the same object meet each other. Order is preserved so the + * most recently started walk as at the back of the vector. + */ + ii = 0; + n_ctxs = vec_len(fwalk->fw_ctx); + while (ii < n_ctxs) + { + wrc = fib_node_back_walk_one(&sibling, &fwalk->fw_ctx[ii]); + + ii++; fwalk = fib_walk_get(fwi); fwalk->fw_n_visits++; @@ -352,14 +377,11 @@ fib_walk_advance (fib_node_index_t fwi) */ return (FIB_WALK_ADVANCE_MERGE); } - if (old != fwalk->fw_ctx) - { - /* - * nasty re-entrant addition of a walk has realloc'd the vector - * break out - */ - return (FIB_WALK_ADVANCE_MERGE); - } + + /* + * re-evaluate the number of backwalk contexts we need to process. + */ + n_ctxs = vec_len(fwalk->fw_ctx); } /* * move foward to the next node to visit @@ -390,7 +412,17 @@ typedef enum fib_walk_sleep_type_t_ * @brief Durations for the sleep types */ static f64 fib_walk_sleep_duration[] = { - [FIB_WALK_LONG_SLEEP] = 1e-3, + /** + * Long sleep when there is no more work, i.e. the queues are empty. + * This is a sleep (as opposed to a wait for event) just to be sure we + * are not missing events by sleeping forever. + */ + [FIB_WALK_LONG_SLEEP] = 2, + + /** + * Short sleep. There is work left in the queues. We are yielding the CPU + * momentarily. + */ [FIB_WALK_SHORT_SLEEP] = 1e-8, }; @@ -466,8 +498,7 @@ fib_walk_process_queues (vlib_main_t * vm, */ if (FIB_WALK_ADVANCE_MORE != rc) { - fwalk = fib_walk_get(fwi); - fib_walk_destroy(fwalk); + fib_walk_destroy(fwi); fib_walk_queues.fwqs_queues[prio].fwq_stats[FIB_WALK_COMPLETED]++; } else @@ -510,6 +541,16 @@ that_will_do_for_now: return (fib_walk_sleep_duration[sleep]); } +/** + * Events sent to the FIB walk process + */ +typedef enum fib_walk_process_event_t_ +{ + FIB_WALK_PROCESS_EVENT_DATA, + FIB_WALK_PROCESS_EVENT_ENABLE, + FIB_WALK_PROCESS_EVENT_DISABLE, +} fib_walk_process_event; + /** * @brief The 'fib-walk' process's main loop. */ @@ -518,22 +559,47 @@ fib_walk_process (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f) { + uword event_type, *event_data = 0; f64 sleep_time; + int enabled; + enabled = 1; sleep_time = fib_walk_sleep_duration[FIB_WALK_SHORT_SLEEP]; while (1) { - vlib_process_wait_for_event_or_clock(vm, sleep_time); + /* + * the feature to disable/enable this walk process is only + * for testing purposes + */ + if (enabled) + { + vlib_process_wait_for_event_or_clock(vm, sleep_time); + } + else + { + vlib_process_wait_for_event(vm); + } - /* - * there may be lots of event queued between the processes, - * but the walks we want to schedule are in the priority queues, - * so we ignore the process events. - */ - vlib_process_get_events(vm, NULL); + event_type = vlib_process_get_events(vm, &event_data); + vec_reset_length(event_data); + + switch (event_type) + { + case FIB_WALK_PROCESS_EVENT_ENABLE: + enabled = 1; + break; + case FIB_WALK_PROCESS_EVENT_DISABLE: + enabled = 0; + break; + default: + break; + } - sleep_time = fib_walk_process_queues(vm, quota); + if (enabled) + { + sleep_time = fib_walk_process_queues(vm, quota); + } } /* @@ -610,8 +676,8 @@ fib_walk_prio_queue_enquue (fib_walk_priority_t prio, */ vlib_process_signal_event(vlib_get_main(), fib_walk_process_node.index, - FIB_WALK_EVENT, - FIB_WALK_EVENT); + FIB_WALK_PROCESS_EVENT_DATA, + 0); return (sibling); } @@ -661,6 +727,9 @@ fib_walk_async (fib_node_type_t parent_type, fib_walk_get_index(fwalk)); fwalk->fw_prio_sibling = fib_walk_prio_queue_enquue(prio, fwalk); + + FIB_WALK_DBG(fwalk, "async-start: %U", + format_fib_node_bw_reason, ctx->fnbw_reason); } /** @@ -706,6 +775,8 @@ fib_walk_sync (fib_node_type_t parent_type, FIB_NODE_TYPE_WALK, fib_walk_get_index(fwalk)); fwi = fib_walk_get_index(fwalk); + FIB_WALK_DBG(fwalk, "sync-start: %U", + format_fib_node_bw_reason, ctx->fnbw_reason); while (1) { @@ -742,7 +813,7 @@ fib_walk_sync (fib_node_type_t parent_type, ASSERT(FIB_NODE_INDEX_INVALID != merged_walk.fnp_index); ASSERT(FIB_NODE_TYPE_WALK == merged_walk.fnp_type); - fib_walk_destroy(fwalk); + fib_walk_destroy(fwi); fwi = merged_walk.fnp_index; fwalk = fib_walk_get(fwi); @@ -759,6 +830,10 @@ fib_walk_sync (fib_node_type_t parent_type, * continue with it now, but let the stack unwind and along the * appropriate frame to read the depth count and bail. */ + FIB_WALK_DBG(fwalk, "sync-stop: %U", + format_fib_node_bw_reason, + ctx->fnbw_reason); + fwalk = NULL; break; } @@ -774,7 +849,10 @@ fib_walk_sync (fib_node_type_t parent_type, if (NULL != fwalk) { - fib_walk_destroy(fwalk); + FIB_WALK_DBG(fwalk, "sync-stop: %U", + format_fib_node_bw_reason, + ctx->fnbw_reason); + fib_walk_destroy(fwi); } } @@ -871,23 +949,38 @@ fib_walk_module_init (void) } fib_node_register_type(FIB_NODE_TYPE_WALK, &fib_walk_vft); + fib_walk_logger = vlib_log_register_class("fib", "walk"); } static u8* -format_fib_walk (u8* s, va_list ap) +format_fib_walk (u8* s, va_list *ap) { - fib_node_index_t fwi = va_arg(ap, fib_node_index_t); + fib_node_index_t fwi = va_arg(*ap, fib_node_index_t); fib_walk_t *fwalk; fwalk = fib_walk_get(fwi); - return (format(s, " parent:{%s:%d} visits:%d flags:%d", + return (format(s, "[@%d] parent:{%s:%d} visits:%d flags:%d", fwi, fib_node_type_get_name(fwalk->fw_parent.fnp_type), fwalk->fw_parent.fnp_index, fwalk->fw_n_visits, fwalk->fw_flags)); } +u8 * +format_fib_node_bw_reason (u8 *s, va_list *args) +{ + fib_node_bw_reason_flag_t flag = va_arg (*args, int); + fib_node_back_walk_reason_t reason; + + FOR_EACH_FIB_NODE_BW_REASON(reason) { + if ((1<