aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo/load_balance.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/dpo/load_balance.c')
-rw-r--r--src/vnet/dpo/load_balance.c45
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.
*/