summaryrefslogtreecommitdiffstats
path: root/src/vnet/fib
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/fib')
-rw-r--r--src/vnet/fib/fib_api.h2
-rw-r--r--src/vnet/fib/fib_entry_src.c4
-rw-r--r--src/vnet/fib/fib_path.c20
-rw-r--r--src/vnet/fib/fib_path.h1
-rw-r--r--src/vnet/fib/fib_path_ext.c77
-rw-r--r--src/vnet/fib/fib_path_ext.h34
-rw-r--r--src/vnet/fib/fib_table.c4
-rw-r--r--src/vnet/fib/fib_table.h4
-rw-r--r--src/vnet/fib/fib_test.c205
-rw-r--r--src/vnet/fib/fib_test.h5
-rw-r--r--src/vnet/fib/fib_types.api18
-rw-r--r--src/vnet/fib/fib_types.c53
-rw-r--r--src/vnet/fib/fib_types.h67
13 files changed, 399 insertions, 95 deletions
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 <vnet/fib/fib_internal.h>
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<<attr) & path_ext->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<<attr) & path_ext->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
@@ -60,6 +60,32 @@ typedef enum fib_path_ext_adj_flags_t_
_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,11 +163,16 @@ 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.
*/
extern fib_forward_chain_type_t fib_forw_chain_type_from_dpo_proto(dpo_proto_t proto);
@@ -373,6 +378,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.
* These paramenters will determine the path 'type', of which there are:
@@ -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.