X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdpo%2Flookup_dpo.c;h=ec2cd02653b0e9b82af2e568708fecae657d36b2;hb=68b7e5888cbfc1fafd38971c725ce10268ad3841;hp=cf489d7eb355f6bde0d4c5d7f62e388a02b4fe39;hpb=31426c6fee43caf18602a2a7e2ce32c3dda75a29;p=vpp.git diff --git a/src/vnet/dpo/lookup_dpo.c b/src/vnet/dpo/lookup_dpo.c index cf489d7eb35..ec2cd02653b 100644 --- a/src/vnet/dpo/lookup_dpo.c +++ b/src/vnet/dpo/lookup_dpo.c @@ -15,8 +15,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -28,6 +28,12 @@ static const char *const lookup_input_names[] = LOOKUP_INPUTS; static const char *const lookup_cast_names[] = LOOKUP_CASTS; +/** + * If a packet encounters a lookup DPO more than the many times + * then we assume there is a loop in the forward graph and drop the packet + */ +#define MAX_LUKPS_PER_PACKET 4 + /** * @brief Enumeration of the lookup subtypes */ @@ -135,11 +141,15 @@ lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index, { if (LOOKUP_UNICAST == cast) { - fib_table_lock(fib_index, dpo_proto_to_fib(proto)); + fib_table_lock(fib_index, + dpo_proto_to_fib(proto), + FIB_SOURCE_RR); } else { - mfib_table_lock(fib_index, dpo_proto_to_fib(proto)); + mfib_table_lock(fib_index, + dpo_proto_to_fib(proto), + MFIB_SOURCE_RR); } } lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo); @@ -161,13 +171,15 @@ lookup_dpo_add_or_lock_w_table_id (u32 table_id, { fib_index = fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto), - table_id); + table_id, + FIB_SOURCE_RR); } else { fib_index = mfib_table_find_or_create_and_lock(dpo_proto_to_fib(proto), - table_id); + table_id, + MFIB_SOURCE_RR); } } @@ -238,12 +250,14 @@ lookup_dpo_unlock (dpo_id_t *dpo) if (LOOKUP_UNICAST == lkd->lkd_cast) { fib_table_unlock(lkd->lkd_fib_index, - dpo_proto_to_fib(lkd->lkd_proto)); + dpo_proto_to_fib(lkd->lkd_proto), + FIB_SOURCE_RR); } else { mfib_table_unlock(lkd->lkd_fib_index, - dpo_proto_to_fib(lkd->lkd_proto)); + dpo_proto_to_fib(lkd->lkd_proto), + MFIB_SOURCE_RR); } } pool_put(lookup_dpo_pool, lkd); @@ -463,6 +477,23 @@ lookup_dpo_ip4_inline (vlib_main_t * vm, (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, b1)); + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + if (!(b1->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b1)->loop_counter = 0; + b1->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + vnet_buffer2(b1)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = IP_LOOKUP_NEXT_DROP; + if (PREDICT_FALSE(vnet_buffer2(b1)->loop_counter > MAX_LUKPS_PER_PACKET)) + next1 = IP_LOOKUP_NEXT_DROP; + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { lookup_trace_t *tr = vlib_add_trace (vm, node, @@ -564,6 +595,16 @@ lookup_dpo_ip4_inline (vlib_main_t * vm, (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = IP_LOOKUP_NEXT_DROP; + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { lookup_trace_t *tr = vlib_add_trace (vm, node, @@ -587,7 +628,7 @@ format_lookup_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 *); lookup_trace_t * t = va_arg (*args, lookup_trace_t *); - uword indent = format_get_indent (s); + u32 indent = format_get_indent (s); s = format (s, "%U fib-index:%d addr:%U load-balance:%d", format_white_space, indent, t->fib_index, @@ -596,8 +637,7 @@ format_lookup_trace (u8 * s, va_list * args) return s; } -always_inline uword -lookup_ip4_dst (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip4_dst_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -605,16 +645,13 @@ lookup_ip4_dst (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip4_dst_node) = { - .function = lookup_ip4_dst, .name = "lookup-ip4-dst", .vector_size = sizeof (u32), .sibling_of = "ip4-lookup", .format_trace = format_lookup_trace, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_node, lookup_ip4_dst) -always_inline uword -lookup_ip4_dst_itf (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip4_dst_itf_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -622,16 +659,13 @@ lookup_ip4_dst_itf (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = { - .function = lookup_ip4_dst_itf, .name = "lookup-ip4-dst-itf", .vector_size = sizeof (u32), .sibling_of = "ip4-lookup", .format_trace = format_lookup_trace, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_itf_node, lookup_ip4_dst_itf) -always_inline uword -lookup_ip4_src (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip4_src_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -639,13 +673,11 @@ lookup_ip4_src (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip4_src_node) = { - .function = lookup_ip4_src, .name = "lookup-ip4-src", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .sibling_of = "ip4-lookup", }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_src_node, lookup_ip4_src) always_inline uword lookup_dpo_ip6_inline (vlib_main_t * vm, @@ -756,10 +788,10 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, } /* do src lookup */ - lbi0 = ip6_fib_table_fwding_lookup(&ip6_main, + lbi0 = ip6_fib_table_fwding_lookup( fib_index0, input_addr0); - lbi1 = ip6_fib_table_fwding_lookup(&ip6_main, + lbi1 = ip6_fib_table_fwding_lookup( fib_index1, input_addr1); lb0 = load_balance_get(lbi0); @@ -772,6 +804,23 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0; hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0; + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + if (!(b1->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b1)->loop_counter = 0; + b1->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + vnet_buffer2(b1)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = IP_LOOKUP_NEXT_DROP; + if (PREDICT_FALSE(vnet_buffer2(b1)->loop_counter > MAX_LUKPS_PER_PACKET)) + next1 = IP_LOOKUP_NEXT_DROP; + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) { flow_hash_config0 = lb0->lb_hash_config; @@ -878,7 +927,7 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, } /* do src lookup */ - lbi0 = ip6_fib_table_fwding_lookup(&ip6_main, + lbi0 = ip6_fib_table_fwding_lookup( fib_index0, input_addr0); lb0 = load_balance_get(lbi0); @@ -902,6 +951,16 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, next0 = dpo0->dpoi_next_node; vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = IP_LOOKUP_NEXT_DROP; + vlib_increment_combined_counter (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, b0)); @@ -922,8 +981,7 @@ lookup_dpo_ip6_inline (vlib_main_t * vm, return from_frame->n_vectors; } -always_inline uword -lookup_ip6_dst (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip6_dst_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -931,16 +989,13 @@ lookup_ip6_dst (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip6_dst_node) = { - .function = lookup_ip6_dst, .name = "lookup-ip6-dst", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .sibling_of = "ip6-lookup", }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_node, lookup_ip6_dst) -always_inline uword -lookup_ip6_dst_itf (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip6_dst_itf_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -948,16 +1003,13 @@ lookup_ip6_dst_itf (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = { - .function = lookup_ip6_dst_itf, .name = "lookup-ip6-dst-itf", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .sibling_of = "ip6-lookup", }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_itf_node, lookup_ip6_dst_itf) -always_inline uword -lookup_ip6_src (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip6_src_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -965,13 +1017,11 @@ lookup_ip6_src (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip6_src_node) = { - .function = lookup_ip6_src, .name = "lookup-ip6-src", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .sibling_of = "ip6-lookup", }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_src_node, lookup_ip6_src) always_inline uword lookup_dpo_mpls_inline (vlib_main_t * vm, @@ -999,7 +1049,7 @@ lookup_dpo_mpls_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, lkdi0, lbi0, fib_index0, next0; + u32 bi0, lkdi0, lbi0, fib_index0, next0, hash0; const mpls_unicast_header_t * hdr0; const load_balance_t *lb0; const lookup_dpo_t * lkd0; @@ -1043,9 +1093,54 @@ lookup_dpo_mpls_inline (vlib_main_t * vm, next0 = dpo0->dpoi_next_node; vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; - vlib_increment_combined_counter - (cm, thread_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, b0)); + + if (MPLS_IS_REPLICATE & lbi0) + { + next0 = mpls_lookup_to_replicate_edge; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = + (lbi0 & ~MPLS_IS_REPLICATE); + } + else + { + lb0 = load_balance_get(lbi0); + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + + if (PREDICT_FALSE(lb0->lb_n_buckets > 1)) + { + hash0 = vnet_buffer (b0)->ip.flow_hash = + mpls_compute_flow_hash(hdr0, lb0->lb_hash_config); + dpo0 = load_balance_get_fwd_bucket + (lb0, + (hash0 & (lb0->lb_n_buckets_minus_1))); + } + else + { + dpo0 = load_balance_get_bucket_i (lb0, 0); + } + next0 = dpo0->dpoi_next_node; + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + vlib_increment_combined_counter + (cm, thread_index, lbi0, 1, + vlib_buffer_length_in_chain (vm, b0)); + } + + vnet_buffer (b0)->mpls.ttl = ((char*)hdr0)[3]; + vnet_buffer (b0)->mpls.exp = (((char*)hdr0)[2] & 0xe) >> 1; + vnet_buffer (b0)->mpls.first = 1; + vlib_buffer_advance(b0, sizeof(*hdr0)); + + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = MPLS_LOOKUP_NEXT_DROP; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { @@ -1070,7 +1165,7 @@ format_lookup_mpls_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 *); lookup_trace_t * t = va_arg (*args, lookup_trace_t *); - uword indent = format_get_indent (s); + u32 indent = format_get_indent (s); mpls_unicast_header_t hdr; hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl); @@ -1083,8 +1178,7 @@ format_lookup_mpls_trace (u8 * s, va_list * args) return s; } -always_inline uword -lookup_mpls_dst (vlib_main_t * vm, +VLIB_NODE_FN (lookup_mpls_dst_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -1092,17 +1186,14 @@ lookup_mpls_dst (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_mpls_dst_node) = { - .function = lookup_mpls_dst, .name = "lookup-mpls-dst", .vector_size = sizeof (u32), .sibling_of = "mpls-lookup", .format_trace = format_lookup_mpls_trace, .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_node, lookup_mpls_dst) -always_inline uword -lookup_mpls_dst_itf (vlib_main_t * vm, +VLIB_NODE_FN (lookup_mpls_dst_itf_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -1110,16 +1201,15 @@ lookup_mpls_dst_itf (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = { - .function = lookup_mpls_dst_itf, .name = "lookup-mpls-dst-itf", .vector_size = sizeof (u32), .sibling_of = "mpls-lookup", .format_trace = format_lookup_mpls_trace, .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf) typedef enum lookup_ip_dst_mcast_next_t_ { + LOOKUP_IP_DST_MCAST_NEXT_DROP, LOOKUP_IP_DST_MCAST_NEXT_RPF, LOOKUP_IP_DST_MCAST_N_NEXT, } mfib_forward_lookup_next_t; @@ -1191,9 +1281,9 @@ lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm, ip6_header_t * ip0; ip0 = vlib_buffer_get_current (b0); - mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0), - &ip0->src_address, - &ip0->dst_address); + mfei0 = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index0), + &ip0->src_address, + &ip0->dst_address); if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { lookup_trace_t *tr = vlib_add_trace (vm, node, @@ -1206,6 +1296,16 @@ lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm, vnet_buffer (b0)->ip.adj_index[VLIB_TX] = mfei0; + if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) { + vnet_buffer2(b0)->loop_counter = 0; + b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID; + } + + vnet_buffer2(b0)->loop_counter++; + + if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET)) + next0 = LOOKUP_IP_DST_MCAST_NEXT_DROP; + vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0); } @@ -1214,8 +1314,7 @@ lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm, return from_frame->n_vectors; } -always_inline uword -lookup_ip4_dst_mcast (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip4_dst_mcast_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -1223,21 +1322,18 @@ lookup_ip4_dst_mcast (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node) = { - .function = lookup_ip4_dst_mcast, .name = "lookup-ip4-dst-mcast", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT, .next_nodes = { + [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip4-drop", [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf", }, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_mcast_node, - lookup_ip4_dst_mcast) -always_inline uword -lookup_ip6_dst_mcast (vlib_main_t * vm, +VLIB_NODE_FN (lookup_ip6_dst_mcast_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { @@ -1245,18 +1341,16 @@ lookup_ip6_dst_mcast (vlib_main_t * vm, } VLIB_REGISTER_NODE (lookup_ip6_dst_mcast_node) = { - .function = lookup_ip6_dst_mcast, .name = "lookup-ip6-dst-mcast", .vector_size = sizeof (u32), .format_trace = format_lookup_trace, .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT, .next_nodes = { + [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip6-drop", [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip6-mfib-forward-rpf", }, }; -VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_mcast_node, - lookup_ip6_dst_mcast) static void lookup_dpo_mem_show (void) @@ -1356,6 +1450,46 @@ const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes, }; +static clib_error_t * +lookup_dpo_show (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + index_t lkdi = INDEX_INVALID; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%d", &lkdi)) + ; + else + break; + } + + if (INDEX_INVALID != lkdi) + { + vlib_cli_output (vm, "%U", format_lookup_dpo, lkdi); + } + else + { + lookup_dpo_t *lkd; + + pool_foreach(lkd, lookup_dpo_pool, + ({ + vlib_cli_output (vm, "[@%d] %U", + lookup_dpo_get_index(lkd), + format_lookup_dpo, + lookup_dpo_get_index(lkd)); + })); + } + + return 0; +} + +VLIB_CLI_COMMAND (replicate_show_command, static) = { + .path = "show lookup-dpo", + .short_help = "show lookup-dpo []", + .function = lookup_dpo_show, +}; void lookup_dpo_module_init (void)