aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/dpo/load_balance.c
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2016-11-16 11:47:44 +0000
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-17 18:46:20 +0000
commit0bd36eac4758f785ae9e2c006894b6935f0f70f2 (patch)
tree227e36c8ef714012699486ea78890ca14d77ddad /vnet/vnet/dpo/load_balance.c
parent4ee3a65b93282aec6d2016f174529d7ac5e364e1 (diff)
Fixup Path weights of 0
A path wight of 0 is a meaningless value. We can either reject it and thus expect CLI/API clients to always write a non-zero value, or we can accept it and assume the intent was a weight of 1 - this fix does the latter. Change-Id: Ide736dbbb8376f85441f5a67388d5e3acad4d34e Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'vnet/vnet/dpo/load_balance.c')
-rw-r--r--vnet/vnet/dpo/load_balance.c61
1 files changed, 52 insertions, 9 deletions
diff --git a/vnet/vnet/dpo/load_balance.c b/vnet/vnet/dpo/load_balance.c
index 8abfc436d67..a244776ffb8 100644
--- a/vnet/vnet/dpo/load_balance.c
+++ b/vnet/vnet/dpo/load_balance.c
@@ -375,6 +375,19 @@ ip_multipath_normalize_next_hops (load_balance_path_t * raw_next_hops,
n_adj_left -= n;
error += fabs (nf - n);
nhs[i].path_weight = n;
+
+ if (0 == nhs[i].path_weight)
+ {
+ /*
+ * when the weight skew is high (norm is small) and n == nf.
+ * without this correction the path with a low weight would have
+ * no represenation in the load-balanace - don't want that.
+ * If the weight skew is high so the load-balance has many buckets
+ * to allow it. pays ya money takes ya choice.
+ */
+ error = n_adj;
+ break;
+ }
}
nhs[0].path_weight += n_adj_left;
@@ -565,15 +578,45 @@ load_balance_multipath_update (const dpo_id_t *dpo,
}
else
{
- /*
- * we are not crossing the threshold. we can write the new on the
- * old, whether they be inline or not.
- */
- load_balance_fill_buckets(lb, nhs,
- load_balance_get_buckets(lb),
- n_buckets);
- CLIB_MEMORY_BARRIER();
- load_balance_set_n_buckets(lb, n_buckets);
+ if (n_buckets <= LB_NUM_INLINE_BUCKETS)
+ {
+ /*
+ * we are not crossing the threshold and it's still inline buckets.
+ * we can write the new on the old..
+ */
+ load_balance_fill_buckets(lb, nhs,
+ load_balance_get_buckets(lb),
+ n_buckets);
+ CLIB_MEMORY_BARRIER();
+ load_balance_set_n_buckets(lb, n_buckets);
+ }
+ else
+ {
+ /*
+ * we are not crossing the threshold. We need a new bucket array to
+ * hold the increased number of choices.
+ */
+ dpo_id_t *new_buckets, *old_buckets, *tmp_dpo;
+
+ new_buckets = NULL;
+ old_buckets = load_balance_get_buckets(lb);
+
+ vec_validate_aligned(new_buckets,
+ n_buckets - 1,
+ CLIB_CACHE_LINE_BYTES);
+
+ load_balance_fill_buckets(lb, nhs, new_buckets, n_buckets);
+ CLIB_MEMORY_BARRIER();
+ lb->lb_buckets = new_buckets;
+ CLIB_MEMORY_BARRIER();
+ load_balance_set_n_buckets(lb, n_buckets);
+
+ vec_foreach(tmp_dpo, old_buckets)
+ {
+ dpo_reset(tmp_dpo);
+ }
+ vec_free(old_buckets);
+ }
}
/*