diff options
Diffstat (limited to 'src/vnet/dpo/load_balance.c')
-rw-r--r-- | src/vnet/dpo/load_balance.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/src/vnet/dpo/load_balance.c b/src/vnet/dpo/load_balance.c index a212532dffd..8f2a0de6ea8 100644 --- a/src/vnet/dpo/load_balance.c +++ b/src/vnet/dpo/load_balance.c @@ -100,8 +100,8 @@ load_balance_alloc_i (void) vlib_main_t *vm = vlib_get_main(); ASSERT (vm->thread_index == 0); - pool_get_aligned_will_expand (load_balance_pool, need_barrier_sync, - CLIB_CACHE_LINE_BYTES); + need_barrier_sync = pool_get_will_expand (load_balance_pool); + if (need_barrier_sync) vlib_worker_thread_barrier_sync (vm); @@ -149,7 +149,13 @@ load_balance_format (index_t lbi, dpo_id_t *buckets; u32 i; - lb = load_balance_get(lbi); + lb = load_balance_get_or_null(lbi); + if (lb == NULL) + { + s = format(s, "DELETED lb:%u", lbi); + return (s); + } + vlib_get_combined_counter(&(load_balance_main.lbm_to_counters), lbi, &to); vlib_get_combined_counter(&(load_balance_main.lbm_via_counters), lbi, &via); buckets = load_balance_get_buckets(lb); @@ -244,6 +250,8 @@ load_balance_create_i (u32 num_buckets, { load_balance_t *lb; + ASSERT (num_buckets <= LB_MAX_BUCKETS); + lb = load_balance_alloc_i(); lb->lb_hash_config = fhc; lb->lb_n_buckets = num_buckets; @@ -408,7 +416,7 @@ ip_multipath_normalize_next_hops (const load_balance_path_t * raw_next_hops, { nhs[0] = raw_next_hops[0]; nhs[0].path_weight = 1; - _vec_len (nhs) = 1; + vec_set_len (nhs, 1); sum_weight = 1; goto done; } @@ -425,7 +433,7 @@ ip_multipath_normalize_next_hops (const load_balance_path_t * raw_next_hops, if (nhs[0].path_weight == nhs[1].path_weight) { nhs[0].path_weight = nhs[1].path_weight = 1; - _vec_len (nhs) = 2; + vec_set_len (nhs, 2); sum_weight = 2; goto done; } @@ -455,8 +463,9 @@ ip_multipath_normalize_next_hops (const load_balance_path_t * raw_next_hops, /* Try larger and larger power of 2 sized adjacency blocks until we find one where traffic flows to within 1% of specified weights. */ - for (n_adj = max_pow2 (n_nhs); ; n_adj *= 2) + for (n_adj = clib_min(max_pow2 (n_nhs), LB_MAX_BUCKETS); ; n_adj *= 2) { + ASSERT (n_adj <= LB_MAX_BUCKETS); error = 0; norm = n_adj / ((f64) sum_weight); @@ -487,12 +496,22 @@ ip_multipath_normalize_next_hops (const load_balance_path_t * raw_next_hops, nhs[0].path_weight += n_adj_left; - /* Less than 5% average error per adjacency with this size adjacency block? */ - if (error <= multipath_next_hop_error_tolerance*n_adj) + /* Less than 1% average error per adjacency with this size adjacency block, + * or did we reached the maximum number of buckets we support? */ + if (error <= multipath_next_hop_error_tolerance*n_adj || + n_adj >= LB_MAX_BUCKETS) { - /* Truncate any next hops with zero weight. */ - _vec_len (nhs) = i; - break; + if (i < n_nhs) + { + /* Truncate any next hops in excess */ + vlib_log_err(load_balance_logger, + "Too many paths for load-balance, truncating %d -> %d", + n_nhs, i); + for (int j = i; j < n_nhs; j++) + dpo_reset (&vec_elt(nhs, j).path_dpo); + } + vec_set_len (nhs, i); + break; } } @@ -592,6 +611,7 @@ load_balance_fill_buckets_sticky (load_balance_t *lb, { /* fill the bucks from the next up path */ load_balance_set_bucket_i(lb, bucket++, buckets, &fwding_paths[fpath].path_dpo); + ASSERT(vec_len(fwding_paths) > 0); fpath = (fpath + 1) % vec_len(fwding_paths); } } @@ -621,6 +641,7 @@ static inline void load_balance_set_n_buckets (load_balance_t *lb, u32 n_buckets) { + ASSERT (n_buckets <= LB_MAX_BUCKETS); lb->lb_n_buckets = n_buckets; lb->lb_n_buckets_minus_1 = n_buckets-1; } @@ -650,8 +671,6 @@ load_balance_multipath_update (const dpo_id_t *dpo, &sum_of_weights, multipath_next_hop_error_tolerance); - ASSERT (n_buckets >= vec_len (raw_nhs)); - /* * Save the old load-balance map used, and get a new one if required. */ |