From ac64b71b2893341b2e342865c209ee63c2dc3138 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 8 Oct 2018 14:51:11 +0000 Subject: Sticky Load-balance keep the number of buckets in the load-balanced fixed. If a path goes dwon fill its buckets with those from the next available up path. Change-Id: I15603ccb899fa9b77556b898c99136379cf32eae Signed-off-by: Neale Ranns --- src/vnet/dpo/load_balance.c | 119 ++++++++++++++++++++++++++++++++++++++------ src/vnet/dpo/load_balance.h | 35 ++++++++++--- 2 files changed, 130 insertions(+), 24 deletions(-) (limited to 'src/vnet/dpo') diff --git a/src/vnet/dpo/load_balance.c b/src/vnet/dpo/load_balance.c index 37f8ca1d89d..48f77986f57 100644 --- a/src/vnet/dpo/load_balance.c +++ b/src/vnet/dpo/load_balance.c @@ -28,8 +28,9 @@ */ const f64 multipath_next_hop_error_tolerance = 0.1; -#undef LB_DEBUG +static const char *load_balance_attr_names[] = LOAD_BALANCE_ATTR_NAMES; +#undef LB_DEBUG #ifdef LB_DEBUG #define LB_DBG(_lb, _fmt, _args...) \ { \ @@ -131,6 +132,21 @@ load_balance_format (index_t lbi, s = format(s, "[proto:%U ", format_dpo_proto, lb->lb_proto); s = format(s, "index:%d buckets:%d ", lbi, lb->lb_n_buckets); s = format(s, "uRPF:%d ", lb->lb_urpf); + if (lb->lb_flags) + { + load_balance_attr_t attr; + + s = format(s, "flags:["); + + FOR_EACH_LOAD_BALANCE_ATTR(attr) + { + if (lb->lb_flags & (1 << attr)) + { + s = format (s, "%s", load_balance_attr_names[attr]); + } + } + s = format(s, "] "); + } s = format(s, "to:[%Ld:%Ld]", to.packets, to.bytes); if (0 != via.packets) { @@ -467,12 +483,12 @@ load_balance_multipath_next_hop_fixup (const load_balance_path_t *nhs, * next hop adjacencies. */ static void -load_balance_fill_buckets (load_balance_t *lb, - load_balance_path_t *nhs, - dpo_id_t *buckets, - u32 n_buckets) +load_balance_fill_buckets_norm (load_balance_t *lb, + load_balance_path_t *nhs, + dpo_id_t *buckets, + u32 n_buckets) { - load_balance_path_t * nh; + load_balance_path_t *nh; u16 ii, bucket; bucket = 0; @@ -490,6 +506,69 @@ load_balance_fill_buckets (load_balance_t *lb, } } } +static void +load_balance_fill_buckets_sticky (load_balance_t *lb, + load_balance_path_t *nhs, + dpo_id_t *buckets, + u32 n_buckets) +{ + load_balance_path_t *nh, *fwding_paths; + u16 ii, bucket, fpath; + + fpath = bucket = 0; + fwding_paths = NULL; + + vec_foreach (nh, nhs) + { + if (!dpo_is_drop(&nh->path_dpo)) + { + vec_add1(fwding_paths, *nh); + } + } + if (vec_len(fwding_paths) == 0) + fwding_paths = vec_dup(nhs); + + /* + * the next-hops have normalised weights. that means their sum is the number + * of buckets we need to fill. + */ + vec_foreach (nh, nhs) + { + for (ii = 0; ii < nh->path_weight; ii++) + { + ASSERT(bucket < n_buckets); + if (!dpo_is_drop(&nh->path_dpo)) + { + load_balance_set_bucket_i(lb, bucket++, buckets, &nh->path_dpo); + } + else + { + /* fill the bucks from the next up path */ + load_balance_set_bucket_i(lb, bucket++, buckets, &fwding_paths[fpath].path_dpo); + fpath = (fpath + 1) % vec_len(fwding_paths); + } + } + } + + vec_free(fwding_paths); +} + +static void +load_balance_fill_buckets (load_balance_t *lb, + load_balance_path_t *nhs, + dpo_id_t *buckets, + u32 n_buckets, + load_balance_flags_t flags) +{ + if (flags & LOAD_BALANCE_FLAG_STICKY) + { + load_balance_fill_buckets_sticky(lb, nhs, buckets, n_buckets); + } + else + { + load_balance_fill_buckets_norm(lb, nhs, buckets, n_buckets); + } +} static inline void load_balance_set_n_buckets (load_balance_t *lb, @@ -514,6 +593,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, ASSERT(DPO_LOAD_BALANCE == dpo->dpoi_type); lb = load_balance_get(dpo->dpoi_index); + lb->lb_flags = flags; fixed_nhs = load_balance_multipath_next_hop_fixup(raw_nhs, lb->lb_proto); n_buckets = ip_multipath_normalize_next_hops((NULL == fixed_nhs ? @@ -553,7 +633,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, load_balance_fill_buckets(lb, nhs, load_balance_get_buckets(lb), - n_buckets); + n_buckets, flags); lb->lb_map = lbmi; } else @@ -574,7 +654,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, */ load_balance_fill_buckets(lb, nhs, load_balance_get_buckets(lb), - n_buckets); + n_buckets, flags); lb->lb_map = lbmi; } else if (n_buckets > lb->lb_n_buckets) @@ -599,7 +679,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, load_balance_fill_buckets(lb, nhs, lb->lb_buckets, - n_buckets); + n_buckets, flags); CLIB_MEMORY_BARRIER(); load_balance_set_n_buckets(lb, n_buckets); @@ -620,7 +700,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, */ load_balance_fill_buckets(lb, nhs, load_balance_get_buckets(lb), - n_buckets); + n_buckets, flags); CLIB_MEMORY_BARRIER(); load_balance_set_n_buckets(lb, n_buckets); } @@ -639,7 +719,8 @@ load_balance_multipath_update (const dpo_id_t *dpo, n_buckets - 1, CLIB_CACHE_LINE_BYTES); - load_balance_fill_buckets(lb, nhs, new_buckets, n_buckets); + load_balance_fill_buckets(lb, nhs, new_buckets, + n_buckets, flags); CLIB_MEMORY_BARRIER(); lb->lb_buckets = new_buckets; CLIB_MEMORY_BARRIER(); @@ -683,7 +764,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, */ load_balance_fill_buckets(lb, nhs, lb->lb_buckets_inline, - n_buckets); + n_buckets, flags); CLIB_MEMORY_BARRIER(); load_balance_set_n_buckets(lb, n_buckets); CLIB_MEMORY_BARRIER(); @@ -711,9 +792,8 @@ load_balance_multipath_update (const dpo_id_t *dpo, load_balance_set_n_buckets(lb, n_buckets); CLIB_MEMORY_BARRIER(); - load_balance_fill_buckets(lb, nhs, - buckets, - n_buckets); + load_balance_fill_buckets(lb, nhs, buckets, + n_buckets, flags); for (ii = n_buckets; ii < old_n_buckets; ii++) { @@ -887,8 +967,15 @@ load_balance_show (vlib_main_t * vm, if (INDEX_INVALID != lbi) { - vlib_cli_output (vm, "%U", format_load_balance, lbi, + if (pool_is_free_index(load_balance_pool, lbi)) + { + vlib_cli_output (vm, "no such load-balance:%d", lbi); + } + else + { + vlib_cli_output (vm, "%U", format_load_balance, lbi, LOAD_BALANCE_FORMAT_DETAIL); + } } else { diff --git a/src/vnet/dpo/load_balance.h b/src/vnet/dpo/load_balance.h index dd9589f9ee8..3f0d5ac2acb 100644 --- a/src/vnet/dpo/load_balance.h +++ b/src/vnet/dpo/load_balance.h @@ -76,6 +76,28 @@ typedef struct load_balance_path_t_ { u32 path_weight; } load_balance_path_t; +/** + * Flags controlling load-balance creation and modification + */ +typedef enum load_balance_attr_t_ { + LOAD_BALANCE_ATTR_USES_MAP = 0, + LOAD_BALANCE_ATTR_STICKY = 1, +} load_balance_attr_t; + +#define LOAD_BALANCE_ATTR_NAMES { \ + [LOAD_BALANCE_ATTR_USES_MAP] = "uses-map", \ + [LOAD_BALANCE_ATTR_STICKY] = "sticky", \ +} + +#define FOR_EACH_LOAD_BALANCE_ATTR(_attr) \ + for (_attr = 0; _attr <= LOAD_BALANCE_ATTR_STICKY; _attr++) + +typedef enum load_balance_flags_t_ { + LOAD_BALANCE_FLAG_NONE = 0, + LOAD_BALANCE_FLAG_USES_MAP = (1 << 0), + LOAD_BALANCE_FLAG_STICKY = (1 << 1), +} __attribute__((packed)) load_balance_flags_t; + /** * The FIB DPO provieds; * - load-balancing over the next DPOs in the chain/graph @@ -105,6 +127,11 @@ typedef struct load_balance_t_ { */ dpo_proto_t lb_proto; + /** + * Flags concenring the LB's creation and modification + */ + load_balance_flags_t lb_flags; + /** * Flags from the load-balance's associated fib_entry_t */ @@ -158,14 +185,6 @@ typedef enum load_balance_format_flags_t_ { LOAD_BALANCE_FORMAT_DETAIL = (1 << 0), } load_balance_format_flags_t; -/** - * Flags controlling load-balance creation and modification - */ -typedef enum load_balance_flags_t_ { - LOAD_BALANCE_FLAG_NONE = 0, - LOAD_BALANCE_FLAG_USES_MAP = (1 << 0), -} load_balance_flags_t; - extern index_t load_balance_create(u32 num_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc); -- cgit 1.2.3-korg