X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdpo%2Fload_balance.c;h=b48702ae3f2bdcaf2852ee3822ff3cc4ad19a660;hb=d792d9c01e60656cbfe1b0f1fd6a9b125f5dab0c;hp=a244776ffb86a549d104e21286049562e74ec1b8;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/dpo/load_balance.c b/src/vnet/dpo/load_balance.c index a244776ffb8..b48702ae3f2 100644 --- a/src/vnet/dpo/load_balance.c +++ b/src/vnet/dpo/load_balance.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * distribution error tolerance for load-balancing @@ -118,7 +119,8 @@ load_balance_format (index_t lbi, buckets = load_balance_get_buckets(lb); s = format(s, "%U: ", format_dpo_type, DPO_LOAD_BALANCE); - s = format(s, "[index:%d buckets:%d ", lbi, lb->lb_n_buckets); + 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); s = format(s, "to:[%Ld:%Ld]", to.packets, to.bytes); if (0 != via.packets) @@ -238,6 +240,17 @@ load_balance_is_drop (const dpo_id_t *dpo) return (0); } +void +load_balance_set_fib_entry_flags (index_t lbi, + fib_entry_flag_t flags) +{ + load_balance_t *lb; + + lb = load_balance_get(lbi); + lb->lb_fib_entry_flags = flags; +} + + void load_balance_set_urpf (index_t lbi, index_t urpf) @@ -279,8 +292,8 @@ load_balance_get_bucket (index_t lbi, } static int -next_hop_sort_by_weight (load_balance_path_t * n1, - load_balance_path_t * n2) +next_hop_sort_by_weight (const load_balance_path_t * n1, + const load_balance_path_t * n2) { return ((int) n1->path_weight - (int) n2->path_weight); } @@ -289,7 +302,7 @@ next_hop_sort_by_weight (load_balance_path_t * n1, with weights corresponding to the number of adjacencies for each next hop. Returns number of adjacencies in block. */ u32 -ip_multipath_normalize_next_hops (load_balance_path_t * raw_next_hops, +ip_multipath_normalize_next_hops (const load_balance_path_t * raw_next_hops, load_balance_path_t ** normalized_next_hops, u32 *sum_weight_in, f64 multipath_next_hop_error_tolerance) @@ -409,23 +422,25 @@ done: } static load_balance_path_t * -load_balance_multipath_next_hop_fixup (load_balance_path_t *nhs, +load_balance_multipath_next_hop_fixup (const load_balance_path_t *nhs, dpo_proto_t drop_proto) { if (0 == vec_len(nhs)) { - load_balance_path_t *nh; + load_balance_path_t *new_nhs = NULL, *nh; /* * we need something for the load-balance. so use the drop */ - vec_add2(nhs, nh, 1); + vec_add2(new_nhs, nh, 1); nh->path_weight = 1; dpo_copy(&nh->path_dpo, drop_dpo_get(drop_proto)); + + return (new_nhs); } - return (nhs); + return (NULL); } /* @@ -467,11 +482,11 @@ load_balance_set_n_buckets (load_balance_t *lb, void load_balance_multipath_update (const dpo_id_t *dpo, - load_balance_path_t * raw_next_hops, + const load_balance_path_t * raw_nhs, load_balance_flags_t flags) { - u32 sum_of_weights,n_buckets, ii; - load_balance_path_t * nh, * nhs; + load_balance_path_t *nh, *nhs, *fixed_nhs; + u32 sum_of_weights, n_buckets, ii; index_t lbmi, old_lbmi; load_balance_t *lb; dpo_id_t *tmp_dpo; @@ -480,16 +495,16 @@ load_balance_multipath_update (const dpo_id_t *dpo, ASSERT(DPO_LOAD_BALANCE == dpo->dpoi_type); lb = load_balance_get(dpo->dpoi_index); - raw_next_hops = - load_balance_multipath_next_hop_fixup(raw_next_hops, - lb->lb_proto); + fixed_nhs = load_balance_multipath_next_hop_fixup(raw_nhs, lb->lb_proto); n_buckets = - ip_multipath_normalize_next_hops(raw_next_hops, + ip_multipath_normalize_next_hops((NULL == fixed_nhs ? + raw_nhs : + fixed_nhs), &nhs, &sum_of_weights, multipath_next_hop_error_tolerance); - ASSERT (n_buckets >= vec_len (raw_next_hops)); + ASSERT (n_buckets >= vec_len (raw_nhs)); /* * Save the old load-balance map used, and get a new one if required. @@ -681,7 +696,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, buckets, n_buckets); - for (ii = old_n_buckets-n_buckets; ii < old_n_buckets; ii++) + for (ii = n_buckets; ii < old_n_buckets; ii++) { dpo_reset(&buckets[ii]); } @@ -694,6 +709,7 @@ load_balance_multipath_update (const dpo_id_t *dpo, dpo_reset(&nh->path_dpo); } vec_free(nhs); + vec_free(fixed_nhs); load_balance_map_unlock(old_lbmi); } @@ -796,19 +812,41 @@ const static char* const load_balance_l2_nodes[] = "l2-load-balance", NULL, }; +const static char* const load_balance_nsh_nodes[] = +{ + "nsh-load-balance", +}; +const static char* const load_balance_bier_nodes[] = +{ + "bier-load-balance", + NULL, +}; const static char* const * const load_balance_nodes[DPO_PROTO_NUM] = { [DPO_PROTO_IP4] = load_balance_ip4_nodes, [DPO_PROTO_IP6] = load_balance_ip6_nodes, [DPO_PROTO_MPLS] = load_balance_mpls_nodes, [DPO_PROTO_ETHERNET] = load_balance_l2_nodes, + [DPO_PROTO_NSH] = load_balance_nsh_nodes, + [DPO_PROTO_BIER] = load_balance_bier_nodes, }; void load_balance_module_init (void) { + index_t lbi; + dpo_register(DPO_LOAD_BALANCE, &lb_vft, load_balance_nodes); + /* + * Special LB with index zero. we need to define this since the v4 mtrie + * assumes an index of 0 implies the ply is empty. therefore all 'real' + * adjs need a non-zero index. + * This should never be used, but just in case, stack it on a drop. + */ + lbi = load_balance_create(1, DPO_PROTO_IP4, 0); + load_balance_set_bucket(lbi, 0, drop_dpo_get(DPO_PROTO_IP4)); + load_balance_map_module_init(); } @@ -903,10 +941,11 @@ typedef struct load_balance_trace_t_ index_t lb_index; } load_balance_trace_t; -static uword -l2_load_balance (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +always_inline uword +load_balance_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, + int is_l2) { u32 n_left_from, next_index, *from, *to_next; @@ -941,7 +980,16 @@ l2_load_balance (vlib_main_t * vm, lbi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; lb0 = load_balance_get(lbi0); - vnet_buffer(b0)->ip.flow_hash = l2_flow_hash(b0); + if (is_l2) + { + vnet_buffer(b0)->ip.flow_hash = l2_flow_hash(b0); + } + else + { + /* it's BIER */ + const bier_hdr_t *bh0 = vlib_buffer_get_current(b0); + vnet_buffer(b0)->ip.flow_hash = bier_hdr_get_entropy(bh0); + } dpo0 = load_balance_get_bucket_i(lb0, vnet_buffer(b0)->ip.flow_hash & @@ -966,8 +1014,16 @@ l2_load_balance (vlib_main_t * vm, return frame->n_vectors; } +static uword +l2_load_balance (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (load_balance_inline(vm, node, frame, 1)); +} + static u8 * -format_load_balance_trace (u8 * s, va_list * args) +format_l2_load_balance_trace (u8 * s, va_list * args) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); @@ -985,9 +1041,130 @@ VLIB_REGISTER_NODE (l2_load_balance_node) = { .name = "l2-load-balance", .vector_size = sizeof (u32), - .format_trace = format_load_balance_trace, + .format_trace = format_l2_load_balance_trace, .n_next_nodes = 1, .next_nodes = { [0] = "error-drop", }, }; + +static uword +nsh_load_balance (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, next_index, *from, *to_next; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0, lbi0, next0, *nsh0; + const dpo_id_t *dpo0; + const load_balance_t *lb0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + lbi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; + lb0 = load_balance_get(lbi0); + + /* SPI + SI are the second word of the NSH header */ + nsh0 = vlib_buffer_get_current (b0); + vnet_buffer(b0)->ip.flow_hash = nsh0[1] % lb0->lb_n_buckets; + + dpo0 = load_balance_get_bucket_i(lb0, + vnet_buffer(b0)->ip.flow_hash & + (lb0->lb_n_buckets_minus_1)); + + next0 = dpo0->dpoi_next_node; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + load_balance_trace_t *tr = vlib_add_trace (vm, node, b0, + sizeof (*tr)); + tr->lb_index = lbi0; + } + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return frame->n_vectors; +} + +static u8 * +format_nsh_load_balance_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + load_balance_trace_t *t = va_arg (*args, load_balance_trace_t *); + + s = format (s, "NSH-load-balance: index %d", t->lb_index); + return s; +} + +/** + * @brief + */ +VLIB_REGISTER_NODE (nsh_load_balance_node) = { + .function = nsh_load_balance, + .name = "nsh-load-balance", + .vector_size = sizeof (u32), + + .format_trace = format_nsh_load_balance_trace, + .n_next_nodes = 1, + .next_nodes = { + [0] = "error-drop", + }, +}; + +static u8 * +format_bier_load_balance_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + load_balance_trace_t *t = va_arg (*args, load_balance_trace_t *); + + s = format (s, "BIER-load-balance: index %d", t->lb_index); + return s; +} + +static uword +bier_load_balance (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (load_balance_inline(vm, node, frame, 0)); +} + +/** + * @brief + */ +VLIB_REGISTER_NODE (bier_load_balance_node) = { + .function = bier_load_balance, + .name = "bier-load-balance", + .vector_size = sizeof (u32), + + .format_trace = format_bier_load_balance_trace, + .sibling_of = "mpls-load-balance", +};