+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);
+ }
+}