From 31ed74407643595fdce206e9d7487108fb8b33ab Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 23 Feb 2018 05:29:09 -0800 Subject: MPLS Unifom mode - support both pipe and uniform modes for all MPLS LSP - all API programming for output-labels requires that the mode (and associated data) is specificed - API changes in MPLS, BIER and IP are involved - new DPO [sub] types for MPLS labels to handle the two modes. Change-Id: I87b76401e996f10dfbdbe4552ff6b19af958783c Signed-off-by: Neale Ranns --- src/vnet/fib/fib_api.h | 2 +- src/vnet/fib/fib_entry_src.c | 4 +- src/vnet/fib/fib_path.c | 20 ++--- src/vnet/fib/fib_path.h | 1 + src/vnet/fib/fib_path_ext.c | 77 +++++++++++----- src/vnet/fib/fib_path_ext.h | 34 ++++++- src/vnet/fib/fib_table.c | 4 +- src/vnet/fib/fib_table.h | 4 +- src/vnet/fib/fib_test.c | 205 ++++++++++++++++++++++++++++++++----------- src/vnet/fib/fib_test.h | 5 +- src/vnet/fib/fib_types.api | 18 +++- src/vnet/fib/fib_types.c | 53 ++++++++++- src/vnet/fib/fib_types.h | 67 +++++++++++++- 13 files changed, 399 insertions(+), 95 deletions(-) (limited to 'src/vnet/fib') diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h index bbe4eaac74b..d10ba00913b 100644 --- a/src/vnet/fib/fib_api.h +++ b/src/vnet/fib/fib_api.h @@ -53,7 +53,7 @@ add_del_route_t_handler (u8 is_multipath, u16 next_hop_weight, u16 next_hop_preference, mpls_label_t next_hop_via_label, - mpls_label_t * next_hop_out_label_stack); + fib_mpls_label_t * next_hop_out_label_stack); void copy_fib_next_hop (fib_route_path_encode_t * api_rpath, diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index 6dc0c73a305..ec8c7393030 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -212,6 +212,7 @@ static int fib_entry_src_valid_out_label (mpls_label_t label) { return ((MPLS_LABEL_IS_REAL(label) || + MPLS_LABEL_POP == label || MPLS_IETF_IPV4_EXPLICIT_NULL_LABEL == label || MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL == label || MPLS_IETF_IMPLICIT_NULL_LABEL == label)); @@ -330,6 +331,7 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index, &nh->path_dpo); fib_path_stack_mpls_disp(path_index, fib_prefix_get_payload_proto(&ctx->fib_entry->fe_prefix), + FIB_MPLS_LSP_MODE_PIPE, &nh->path_dpo); break; @@ -391,7 +393,7 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index, switch (path_ext->fpe_type) { case FIB_PATH_EXT_MPLS: - if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0])) + if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0].fml_value)) { /* * found a matching extension. stack it to obtain the forwarding diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index b4f9971f52e..a8593905438 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -1349,7 +1349,8 @@ fib_path_create (fib_node_index_t pl_index, { path->fp_type = FIB_PATH_TYPE_DEAG; path->deag.fp_tbl_id = rpath->frp_fib_index; - } + path->deag.fp_rpf_id = ~0; + } } else { @@ -2238,6 +2239,7 @@ fib_path_contribute_urpf (fib_node_index_t path_index, void fib_path_stack_mpls_disp (fib_node_index_t path_index, dpo_proto_t payload_proto, + fib_mpls_lsp_mode_t mode, dpo_id_t *dpo) { fib_path_t *path; @@ -2253,10 +2255,8 @@ fib_path_stack_mpls_disp (fib_node_index_t path_index, dpo_id_t tmp = DPO_INVALID; dpo_copy(&tmp, dpo); - dpo_set(dpo, - DPO_MPLS_DISPOSITION, - payload_proto, - mpls_disp_dpo_create(payload_proto, ~0, &tmp)); + + mpls_disp_dpo_create(payload_proto, ~0, mode, &tmp, dpo); dpo_reset(&tmp); break; } @@ -2265,12 +2265,10 @@ fib_path_stack_mpls_disp (fib_node_index_t path_index, dpo_id_t tmp = DPO_INVALID; dpo_copy(&tmp, dpo); - dpo_set(dpo, - DPO_MPLS_DISPOSITION, - payload_proto, - mpls_disp_dpo_create(payload_proto, - path->deag.fp_rpf_id, - &tmp)); + + mpls_disp_dpo_create(payload_proto, + path->deag.fp_rpf_id, + mode, &tmp, dpo); dpo_reset(&tmp); break; } diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h index 70b2f503aa8..28ec10a98d5 100644 --- a/src/vnet/fib/fib_path.h +++ b/src/vnet/fib/fib_path.h @@ -159,6 +159,7 @@ extern load_balance_path_t * fib_path_append_nh_for_multipath_hash( load_balance_path_t *hash_key); extern void fib_path_stack_mpls_disp(fib_node_index_t path_index, dpo_proto_t payload_proto, + fib_mpls_lsp_mode_t mode, dpo_id_t *dpo); extern void fib_path_contribute_forwarding(fib_node_index_t path_index, fib_forward_chain_type_t type, diff --git a/src/vnet/fib/fib_path_ext.c b/src/vnet/fib/fib_path_ext.c index a285ba07f7c..6b5b841c2ac 100644 --- a/src/vnet/fib/fib_path_ext.c +++ b/src/vnet/fib/fib_path_ext.c @@ -25,6 +25,7 @@ #include const char *fib_path_ext_adj_flags_names[] = FIB_PATH_EXT_ADJ_ATTR_NAMES; +const char *fib_path_ext_mpls_flags_names[] = FIB_PATH_EXT_MPLS_ATTR_NAMES; u8 * format_fib_path_ext (u8 * s, va_list * args) @@ -38,30 +39,46 @@ format_fib_path_ext (u8 * s, va_list * args) switch (path_ext->fpe_type) { - case FIB_PATH_EXT_MPLS: - s = format(s, "labels:", + case FIB_PATH_EXT_MPLS: { + fib_path_ext_mpls_attr_t attr; + + if (path_ext->fpe_mpls_flags) + { + s = format(s, "mpls-flags:["); + + FOR_EACH_PATH_EXT_MPLS_ATTR(attr) + { + if ((1<fpe_mpls_flags) { + s = format(s, "%s", fib_path_ext_mpls_flags_names[attr]); + } + } + s = format(s, "]"); + } + s = format(s, " labels:[", path_ext->fpe_path_index); for (ii = 0; ii < vec_len(path_ext->fpe_path.frp_label_stack); ii++) { - s = format(s, "%U ", - format_mpls_unicast_label, - path_ext->fpe_path.frp_label_stack[ii]); + s = format(s, "[%U]", + format_fib_mpls_label, + &path_ext->fpe_path.frp_label_stack[ii]); } + s = format(s, "]"); break; + } case FIB_PATH_EXT_ADJ: { fib_path_ext_adj_attr_t attr; - s = format(s, "adj-flags:"); if (path_ext->fpe_adj_flags) { + s = format(s, "adj-flags:["); FOR_EACH_PATH_EXT_ADJ_ATTR(attr) { - s = format(s, "%s", fib_path_ext_adj_flags_names[attr]); + if ((1<fpe_adj_flags) + { + s = format(s, "%s", fib_path_ext_adj_flags_names[attr]); + } } - } - else - { - s = format(s, "None"); + s = format(s, "]"); } break; } @@ -121,12 +138,28 @@ fib_path_ext_init (fib_path_ext_t *path_ext, /** * @brief Return true if the label stack is implicit null + * imp-null and pop equate to the same this as this level - + * the label is coming off. */ static int fib_path_ext_is_imp_null (fib_path_ext_t *path_ext) { return ((1 == vec_len(path_ext->fpe_label_stack)) && - (MPLS_IETF_IMPLICIT_NULL_LABEL == path_ext->fpe_label_stack[0])); + ((MPLS_IETF_IMPLICIT_NULL_LABEL == path_ext->fpe_label_stack[0].fml_value) || + (MPLS_LABEL_POP == path_ext->fpe_label_stack[0].fml_value))); +} + +mpls_label_dpo_flags_t +fib_path_ext_mpls_flags_to_mpls_label (fib_path_ext_mpls_flags_t fpe_flags) +{ + mpls_label_dpo_flags_t ml_flags = MPLS_LABEL_DPO_FLAG_NONE; + + if (fpe_flags &FIB_PATH_EXT_MPLS_FLAG_NO_IP_TTL_DECR) + { + ml_flags |= MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR; + } + + return (ml_flags); } load_balance_path_t * @@ -236,24 +269,25 @@ fib_path_ext_stack (fib_path_ext_t *path_ext, * we pickup the correct MPLS imposition nodes to do * ip[46] processing. */ + dpo_id_t parent = DPO_INVALID; dpo_proto_t chain_proto; mpls_eos_bit_t eos; - index_t mldi; eos = (child_fct == FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS ? MPLS_NON_EOS : MPLS_EOS); chain_proto = fib_forw_chain_type_to_dpo_proto(child_fct); - mldi = mpls_label_dpo_create(path_ext->fpe_label_stack, - eos, 255, 0, - chain_proto, - &nh->path_dpo); + dpo_copy(&parent, &nh->path_dpo); + mpls_label_dpo_create(path_ext->fpe_label_stack, + eos, + chain_proto, + fib_path_ext_mpls_flags_to_mpls_label( + path_ext->fpe_mpls_flags), + &parent, + &nh->path_dpo); - dpo_set(&nh->path_dpo, - DPO_MPLS_LABEL, - chain_proto, - mldi); + dpo_reset(&parent); } else if (child_fct == FIB_FORW_CHAIN_TYPE_MPLS_EOS) { @@ -262,6 +296,7 @@ fib_path_ext_stack (fib_path_ext_t *path_ext, */ fib_path_stack_mpls_disp(nh->path_index, fib_forw_chain_type_to_dpo_proto(parent_fct), + path_ext->fpe_label_stack[0].fml_mode, &nh->path_dpo); } } diff --git a/src/vnet/fib/fib_path_ext.h b/src/vnet/fib/fib_path_ext.h index d07941c108b..b49fd977a20 100644 --- a/src/vnet/fib/fib_path_ext.h +++ b/src/vnet/fib/fib_path_ext.h @@ -59,6 +59,32 @@ typedef enum fib_path_ext_adj_flags_t_ _item <= FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER; \ _item++) +/** + * Flags present on an MPLS label sourced path-extension + */ +typedef enum fib_path_ext_mpls_attr_t_ +{ + /** + * Do not decrement the TTL of IP packet during imposition + */ + FIB_PATH_EXT_MPLS_ATTR_NO_IP_TTL_DECR, +} fib_path_ext_mpls_attr_t; + +typedef enum fib_path_ext_mpls_flags_t_ +{ + FIB_PATH_EXT_MPLS_FLAG_NONE = 0, + FIB_PATH_EXT_MPLS_FLAG_NO_IP_TTL_DECR = (1 << FIB_PATH_EXT_MPLS_ATTR_NO_IP_TTL_DECR), +} fib_path_ext_mpls_flags_t; + +#define FIB_PATH_EXT_MPLS_ATTR_NAMES { \ + [FIB_PATH_EXT_MPLS_ATTR_NO_IP_TTL_DECR] = "no-ip-tll-decr", \ +} + +#define FOR_EACH_PATH_EXT_MPLS_ATTR(_item) \ + for (_item = FIB_PATH_EXT_MPLS_ATTR_NO_IP_TTL_DECR; \ + _item <= FIB_PATH_EXT_MPLS_ATTR_NO_IP_TTL_DECR; \ + _item++) + /** * A path extension is a per-entry addition to the forwarding information * when packets are sent for that entry over that path. @@ -86,6 +112,12 @@ typedef struct fib_path_ext_t_ * Flags describing the adj state */ fib_path_ext_adj_flags_t fpe_adj_flags; + /** + * For an MPLS type extension + * + * Flags describing the mpls state + */ + fib_path_ext_mpls_flags_t fpe_mpls_flags; }; /** @@ -98,7 +130,7 @@ typedef struct fib_path_ext_t_ * position in the path-list. */ fib_node_index_t fpe_path_index; -} __attribute__ ((packed)) fib_path_ext_t; +} __attribute__ ((packed)) fib_path_ext_t; extern u8 * format_fib_path_ext(u8 * s, va_list * args); diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c index e9173484dec..324a35fe1e8 100644 --- a/src/vnet/fib/fib_table.c +++ b/src/vnet/fib/fib_table.c @@ -520,7 +520,7 @@ fib_table_entry_path_add (u32 fib_index, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, - mpls_label_t *next_hop_labels, + fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags) { fib_route_path_t path = { @@ -770,7 +770,7 @@ fib_table_entry_update_one_path (u32 fib_index, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, - mpls_label_t *next_hop_labels, + fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags) { fib_node_index_t fib_entry_index; diff --git a/src/vnet/fib/fib_table.h b/src/vnet/fib/fib_table.h index ddc00e537c2..ffad3c43d3e 100644 --- a/src/vnet/fib/fib_table.h +++ b/src/vnet/fib/fib_table.h @@ -338,7 +338,7 @@ extern fib_node_index_t fib_table_entry_path_add(u32 fib_index, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, - mpls_label_t *next_hop_label_stack, + fib_mpls_label_t *next_hop_label_stack, fib_route_path_flags_t pf); /** * @brief @@ -521,7 +521,7 @@ extern fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, - mpls_label_t *next_hop_label_stack, + fib_mpls_label_t *next_hop_label_stack, fib_route_path_flags_t pf); /** diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index 2a30b3cd4cf..8f7bba0369a 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -301,7 +301,8 @@ fib_test_validate_rep_v (const replicate_t *rep, { const mpls_label_dpo_t *mld; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE) + == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); @@ -375,14 +376,19 @@ fib_test_validate_lb_v (const load_balance_t *lb, case FT_LB_LABEL_STACK_O_ADJ: { const mpls_label_dpo_t *mld; + mpls_label_dpo_flags_t mf; mpls_label_t hdr; u32 ii; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + mf = ((exp->label_stack_o_adj.mode == + FIB_MPLS_LSP_MODE_UNIFORM) ? + MPLS_LABEL_DPO_FLAG_UNIFORM_MODE : + MPLS_LABEL_DPO_FLAG_NONE); + FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); - + mld = mpls_label_dpo_get(dpo->dpoi_index); FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels, @@ -433,7 +439,8 @@ fib_test_validate_lb_v (const load_balance_t *lb, { const mpls_label_dpo_t *mld; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + FIB_TEST_LB((mpls_label_dpo_get_type(MPLS_LABEL_DPO_FLAG_NONE) + == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); @@ -468,13 +475,18 @@ fib_test_validate_lb_v (const load_balance_t *lb, case FT_LB_LABEL_O_LB: { const mpls_label_dpo_t *mld; + mpls_label_dpo_flags_t mf; mpls_label_t hdr; - FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type), + mf = ((exp->label_o_lb.mode == + FIB_MPLS_LSP_MODE_UNIFORM) ? + MPLS_LABEL_DPO_FLAG_UNIFORM_MODE : + MPLS_LABEL_DPO_FLAG_NONE); + FIB_TEST_LB((mpls_label_dpo_get_type(mf) == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); - + mld = mpls_label_dpo_get(dpo->dpoi_index); hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl); @@ -515,15 +527,15 @@ fib_test_validate_lb_v (const load_balance_t *lb, bucket, exp->adj.adj); break; - case FT_LB_MPLS_DISP_O_ADJ: + case FT_LB_MPLS_DISP_PIPE_O_ADJ: { const mpls_disp_dpo_t *mdd; - FIB_TEST_I((DPO_MPLS_DISPOSITION == dpo->dpoi_type), + FIB_TEST_I((DPO_MPLS_DISPOSITION_PIPE == dpo->dpoi_type), "bucket %d stacks on %U", bucket, format_dpo_type, dpo->dpoi_type); - + mdd = mpls_disp_dpo_get(dpo->dpoi_index); dpo = &mdd->mdd_dpo; @@ -6332,8 +6344,10 @@ fib_test_label (void) .eos = MPLS_NON_EOS, }, }; - mpls_label_t *l99 = NULL; - vec_add1(l99, 99); + fib_mpls_label_t *l99 = NULL, fml99 = { + .fml_value = 99, + }; + vec_add1(l99, fml99); fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_1_s_32, @@ -6371,8 +6385,10 @@ fib_test_label (void) .adj = ai_mpls_10_10_11_1, }, }; - mpls_label_t *l_imp_null = NULL; - vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL); + fib_mpls_label_t *l_imp_null = NULL, fml_imp_null = { + .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL, + }; + vec_add1(l_imp_null, fml_imp_null); fei = fib_table_entry_path_add(fib_index, &pfx_1_1_1_1_s_32, @@ -6413,7 +6429,7 @@ fib_test_label (void) .fp_eos = MPLS_NON_EOS, }; fib_test_lb_bucket_t disp_o_10_10_11_1 = { - .type = FT_LB_MPLS_DISP_O_ADJ, + .type = FT_LB_MPLS_DISP_PIPE_O_ADJ, .adj = { .adj = ai_v4_10_10_11_1, }, @@ -6458,7 +6474,7 @@ fib_test_label (void) }, }; fib_test_lb_bucket_t disp_o_10_10_11_2 = { - .type = FT_LB_MPLS_DISP_O_ADJ, + .type = FT_LB_MPLS_DISP_PIPE_O_ADJ, .adj = { .adj = ai_v4_10_10_11_2, }, @@ -6540,24 +6556,27 @@ fib_test_label (void) .lb = non_eos_1_1_1_1.dpoi_index, .label = 1600, .eos = MPLS_EOS, + .mode = FIB_MPLS_LSP_MODE_UNIFORM, }, }; - mpls_label_t *l1600 = NULL; - vec_add1(l1600, 1600); + fib_mpls_label_t *l1600 = NULL, fml1600 = { + .fml_value = 1600, + .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM, + }; + vec_add1(l1600, fml1600); - fib_table_entry_update_one_path(fib_index, - &pfx_2_2_2_2_s_32, - FIB_SOURCE_API, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &pfx_1_1_1_1_s_32.fp_addr, - ~0, - fib_index, - 1, - l1600, - FIB_ROUTE_PATH_FLAG_NONE); + fei = fib_table_entry_update_one_path(fib_index, + &pfx_2_2_2_2_s_32, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &pfx_1_1_1_1_s_32.fp_addr, + ~0, + fib_index, + 1, + l1600, + FIB_ROUTE_PATH_FLAG_NONE); - fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32); FIB_TEST(fib_test_validate_entry(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, @@ -6811,7 +6830,7 @@ fib_test_label (void) * add back the path with the valid label */ l99 = NULL; - vec_add1(l99, 99); + vec_add1(l99, fml99); fib_table_entry_path_add(fib_index, &pfx_1_1_1_1_s_32, @@ -6941,8 +6960,10 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *l101 = NULL; - vec_add1(l101, 101); + fib_mpls_label_t *l101 = NULL, fml101 = { + .fml_value = 101, + }; + vec_add1(l101, fml101); fei = fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_2_s_32, @@ -6981,8 +7002,10 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *l1601 = NULL; - vec_add1(l1601, 1601); + fib_mpls_label_t *l1601 = NULL, fml1601 = { + .fml_value = 1601, + }; + vec_add1(l1601, fml1601); l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index; @@ -7012,7 +7035,7 @@ fib_test_label (void) * the LB for the recursive can use an imp-null */ l_imp_null = NULL; - vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL); + vec_add1(l_imp_null, fml_imp_null); fei = fib_table_entry_update_one_path(fib_index, &pfx_1_1_1_2_s_32, @@ -7176,11 +7199,11 @@ fib_test_label (void) .eos = MPLS_EOS, }, }; - mpls_label_t *label_stack = NULL; + fib_mpls_label_t *label_stack = NULL; vec_validate(label_stack, 7); for (ii = 0; ii < 8; ii++) { - label_stack[ii] = ii + 200; + label_stack[ii].fml_value = ii + 200; } fei = fib_table_entry_update_one_path(fib_index, @@ -8255,12 +8278,13 @@ static int lfib_test (void) { const mpls_label_t deag_label = 50; + dpo_id_t dpo = DPO_INVALID; + const mpls_disp_dpo_t *mdd; const u32 lfib_index = 0; const u32 fib_index = 0; - dpo_id_t dpo = DPO_INVALID; + const lookup_dpo_t *lkd; const dpo_id_t *dpo1; fib_node_index_t lfe; - lookup_dpo_t *lkd; test_main_t *tm; int lb_count; adj_index_t ai_mpls_10_10_10_1; @@ -8327,7 +8351,6 @@ lfib_test (void) format_mpls_eos_bit, MPLS_EOS, format_dpo_proto, lkd->lkd_proto); - /* * A route deag route for EOS */ @@ -8358,7 +8381,14 @@ lfib_test (void) FIB_FORW_CHAIN_TYPE_MPLS_EOS, &dpo); dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); - lkd = lookup_dpo_get(dpo1->dpoi_index); + mdd = mpls_disp_dpo_get(dpo1->dpoi_index); + + FIB_TEST((FIB_MPLS_LSP_MODE_PIPE == mdd->mdd_mode), + "%U/%U disp is pipe mode", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index); FIB_TEST((fib_index == lkd->lkd_fib_index), "%U/%U is deag in %d %U", @@ -8383,6 +8413,70 @@ lfib_test (void) "%U/%U not present", format_mpls_unicast_label, deag_label, format_mpls_eos_bit, MPLS_EOS); + dpo_reset(&dpo); + + /* + * A route deag route for EOS with LSP mode uniform + */ + fib_mpls_label_t *l_pops = NULL, l_pop = { + .fml_value = MPLS_LABEL_POP, + .fml_mode = FIB_MPLS_LSP_MODE_UNIFORM, + }; + vec_add1(l_pops, l_pop); + lfe = fib_table_entry_path_add(lfib_index, + &pfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + ~0, + fib_index, + 1, + l_pops, + FIB_ROUTE_PATH_FLAG_NONE); + + FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)), + "%U/%U present", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + fib_entry_contribute_forwarding(lfe, + FIB_FORW_CHAIN_TYPE_MPLS_EOS, + &dpo); + dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0); + mdd = mpls_disp_dpo_get(dpo1->dpoi_index); + + FIB_TEST((FIB_MPLS_LSP_MODE_UNIFORM == mdd->mdd_mode), + "%U/%U disp is uniform mode", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + + lkd = lookup_dpo_get(mdd->mdd_dpo.dpoi_index); + + FIB_TEST((fib_index == lkd->lkd_fib_index), + "%U/%U is deag in %d %U", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS, + lkd->lkd_fib_index, + format_dpo_id, &dpo, 0); + FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input), + "%U/%U is dst deag", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto), + "%U/%U is %U dst deag", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS, + format_dpo_proto, lkd->lkd_proto); + + fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI); + + FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index, + &pfx)), + "%U/%U not present", + format_mpls_unicast_label, deag_label, + format_mpls_eos_bit, MPLS_EOS); + dpo_reset(&dpo); /* * A route deag route for non-EOS @@ -8460,11 +8554,15 @@ lfib_test (void) }; dpo_id_t neos_1200 = DPO_INVALID; dpo_id_t ip_1200 = DPO_INVALID; - mpls_label_t *l200 = NULL; - vec_add1(l200, 200); - vec_add1(l200, 300); - vec_add1(l200, 400); - vec_add1(l200, 500); + fib_mpls_label_t *l200 = NULL; + u32 ii; + for (ii = 0; ii < 4; ii++) + { + fib_mpls_label_t fml = { + .fml_value = 200 + (ii * 100), + }; + vec_add1(l200, fml); + }; lfe = fib_table_entry_update_one_path(fib_index, &pfx_1200, @@ -8523,8 +8621,10 @@ lfib_test (void) .ip4.as_u32 = clib_host_to_net_u32(0x02020204), }, }; - mpls_label_t *l999 = NULL; - vec_add1(l999, 999); + fib_mpls_label_t *l999 = NULL, fml_999 = { + .fml_value = 999, + }; + vec_add1(l999, fml_999); rpaths[0].frp_label_stack = l999, fib_table_entry_path_add2(fib_index, @@ -8690,8 +8790,10 @@ lfib_test (void) .adj = idpo.dpoi_index, }, }; - mpls_label_t *l3300 = NULL; - vec_add1(l3300, 3300); + fib_mpls_label_t *l3300 = NULL, fml_3300 = { + .fml_value = 3300, + }; + vec_add1(l3300, fml_3300); lfe = fib_table_entry_update_one_path(lfib_index, &pfx_3500, @@ -8772,6 +8874,9 @@ lfib_test (void) 0, 1); mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API); + FIB_TEST(0 == pool_elts(mpls_disp_dpo_pool), + "mpls_disp_dpo resources freed %d of %d", + 0, pool_elts(mpls_disp_dpo_pool)); FIB_TEST(lb_count == pool_elts(load_balance_pool), "Load-balance resources freed %d of %d", lb_count, pool_elts(load_balance_pool)); diff --git a/src/vnet/fib/fib_test.h b/src/vnet/fib/fib_test.h index 0309b3f2311..8ac068350c4 100644 --- a/src/vnet/fib/fib_test.h +++ b/src/vnet/fib/fib_test.h @@ -29,7 +29,7 @@ typedef enum fib_test_lb_bucket_type_t_ { FT_LB_LABEL_STACK_O_ADJ, FT_LB_LABEL_O_LB, FT_LB_O_LB, - FT_LB_MPLS_DISP_O_ADJ, + FT_LB_MPLS_DISP_PIPE_O_ADJ, FT_LB_INTF, FT_LB_L2, FT_LB_BIER_TABLE, @@ -47,6 +47,7 @@ typedef struct fib_test_lb_bucket_t_ { { mpls_eos_bit_t eos; mpls_label_t label; + fib_mpls_lsp_mode_t mode; u8 ttl; adj_index_t adj; } label_o_adj; @@ -54,6 +55,7 @@ typedef struct fib_test_lb_bucket_t_ { { mpls_eos_bit_t eos; mpls_label_t label_stack[8]; + fib_mpls_lsp_mode_t mode; u8 label_stack_size; u8 ttl; adj_index_t adj; @@ -62,6 +64,7 @@ typedef struct fib_test_lb_bucket_t_ { { mpls_eos_bit_t eos; mpls_label_t label; + fib_mpls_lsp_mode_t mode; u8 ttl; index_t lb; } label_o_lb; diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api index 61a0898819d..fde2c337190 100644 --- a/src/vnet/fib/fib_types.api +++ b/src/vnet/fib/fib_types.api @@ -12,6 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** \brief MPLS label +*/ +typeonly define fib_mpls_label +{ + u8 is_uniform; + u32 label; + u8 ttl; + u8 exp; +}; /** \brief FIB path @param sw_if_index - index of the interface @@ -20,6 +30,8 @@ is prefered @param is_local - local if non-zero, else remote @param is_drop - Drop the packet + @param is_unreach - Drop the packet and rate limit send ICMP unreachable + @param is_prohibit - Drop the packet and rate limit send ICMP prohibited @param is_udp_encap - The path describes a UDP-o-IP encapsulation. @param afi - the afi of the next hop, IP46_TYPE_IP4=1, IP46_TYPE_IP6=2 @param next_hop[16] - the next hop address @@ -27,7 +39,7 @@ that has a unique identifier. e.g. the UDP encap object */ -typeonly define fib_path3 +typeonly define fib_path { u32 sw_if_index; u32 table_id; @@ -36,10 +48,12 @@ typeonly define fib_path3 u8 is_local; u8 is_drop; u8 is_udp_encap; + u8 is_unreach; + u8 is_prohibit; u8 afi; u8 next_hop[16]; u32 next_hop_id; u32 rpf_id; u8 n_labels; - u32 label_stack[16]; + vl_api_fib_mpls_label_t label_stack[16]; }; diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c index f38c8154e0c..8b1faf5fa86 100644 --- a/src/vnet/fib/fib_types.c +++ b/src/vnet/fib/fib_types.c @@ -25,6 +25,7 @@ static const char* fib_protocol_names[] = FIB_PROTOCOLS; static const char* vnet_link_names[] = VNET_LINKS; static const char* fib_forw_chain_names[] = FIB_FORW_CHAINS; +static const char* fib_mpls_lsp_mode_names[] = FIB_MPLS_LSP_MODES; u8 * format_fib_protocol (u8 * s, va_list * ap) @@ -50,6 +51,30 @@ format_fib_forw_chain_type (u8 * s, va_list * args) return (format (s, "%s", fib_forw_chain_names[fct])); } +u8 * +format_fib_mpls_lsp_mode(u8 *s, va_list *ap) +{ + fib_mpls_lsp_mode_t mode = va_arg(*ap, int); + + return (format (s, "%s", fib_mpls_lsp_mode_names[mode])); +} + +u8 * +format_fib_mpls_label (u8 *s, va_list *ap) +{ + fib_mpls_label_t *label = va_arg(*ap, fib_mpls_label_t *); + + s = format(s, "%U %U ttl:%d exp:%d", + format_mpls_unicast_label, + label->fml_value, + format_fib_mpls_lsp_mode, + label->fml_mode, + label->fml_ttl, + label->fml_exp); + + return (s); +} + void fib_prefix_from_ip46_addr (const ip46_address_t *addr, fib_prefix_t *pfx) @@ -307,6 +332,29 @@ fib_forw_chain_type_to_link_type (fib_forward_chain_type_t fct) return (VNET_LINK_IP4); } +fib_forward_chain_type_t +fib_forw_chain_type_from_link_type (vnet_link_t link_type) +{ + switch (link_type) + { + case VNET_LINK_IP4: + return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); + case VNET_LINK_IP6: + return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6); + case VNET_LINK_MPLS: + return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS); + case VNET_LINK_ETHERNET: + return (FIB_FORW_CHAIN_TYPE_ETHERNET); + case VNET_LINK_NSH: + return (FIB_FORW_CHAIN_TYPE_NSH); + case VNET_LINK_ARP: + break; + } + + ASSERT(0); + return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); +} + dpo_proto_t fib_forw_chain_type_to_dpo_proto (fib_forward_chain_type_t fct) { @@ -475,7 +523,10 @@ unformat_fib_route_path (unformat_input_t * input, va_list * args) while (unformat (input, "%U", unformat_mpls_unicast_label, &out_label)) { - vec_add1(rpath->frp_label_stack, out_label); + fib_mpls_label_t fml = { + .fml_value = out_label, + }; + vec_add1(rpath->frp_label_stack, fml); } } else if (unformat (input, "%U", diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index 75ed7799f12..7f186ac6f6a 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -163,10 +163,15 @@ typedef enum fib_forward_chain_type_t_ { _item++) /** - * @brief Convert from a chain type to the adjacencies link type + * @brief Convert from a chain type to the adjacency's link type */ extern vnet_link_t fib_forw_chain_type_to_link_type(fib_forward_chain_type_t fct); +/** + * @brief Convert from a adjacency's link type to chain type + */ +extern fib_forward_chain_type_t fib_forw_chain_type_from_link_type(vnet_link_t lt); + /** * @brief Convert from a payload-protocol to a chain type. */ @@ -372,6 +377,64 @@ typedef u32 fib_rpf_id_t; #define MFIB_RPF_ID_NONE (0) +/** + * MPLS LSP mode - only valid at the head and tail + */ +typedef enum fib_mpls_lsp_mode_t_ +{ + /** + * Pipe Mode - the default. + * TTL and DSCP markings are not carried between the layers + */ + FIB_MPLS_LSP_MODE_PIPE, + /** + * Uniform mode. + * TTL and DSCP are copied between the layers + */ + FIB_MPLS_LSP_MODE_UNIFORM, +} __attribute__((packed)) fib_mpls_lsp_mode_t; + +#define FIB_MPLS_LSP_MODES { \ + [FIB_MPLS_LSP_MODE_PIPE] = "pipe", \ + [FIB_MPLS_LSP_MODE_UNIFORM] = "uniform", \ +} + +/** + * Format an LSP mode type + */ +extern u8 * format_fib_mpls_lsp_mode(u8 *s, va_list *ap); + +/** + * Configuration for each label value in the output-stack + */ +typedef struct fib_mpls_label_t_ +{ + /** + * The label value + */ + mpls_label_t fml_value; + + /** + * The LSP mode + */ + fib_mpls_lsp_mode_t fml_mode; + + /** + * TTL. valid only at imposition. + */ + u8 fml_ttl; + + /** + * EXP bits; valid only at imposition. + */ + u8 fml_exp; +} fib_mpls_label_t; + +/** + * Format an MPLS label + */ +extern u8 * format_fib_mpls_label(u8 *s, va_list *ap); + /** * @brief * A representation of a path as described by a route producer. @@ -444,7 +507,7 @@ typedef struct fib_route_path_t_ { /** * The outgoing MPLS label Stack. NULL implies no label. */ - mpls_label_t *frp_label_stack; + fib_mpls_label_t *frp_label_stack; }; /** * A path that resolves via a BIER Table. -- cgit 1.2.3-korg