aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo/mpls_disposition.c
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2018-02-23 05:29:09 -0800
committerDamjan Marion <dmarion.lists@gmail.com>2018-03-09 11:59:58 +0000
commit31ed74407643595fdce206e9d7487108fb8b33ab (patch)
treec22c3703c30b7d457b858fe899f56e57613cbb52 /src/vnet/dpo/mpls_disposition.c
parent8f931a47b0fa58d5d33a792062650a42ff8bef70 (diff)
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 <nranns@cisco.com>
Diffstat (limited to 'src/vnet/dpo/mpls_disposition.c')
-rw-r--r--src/vnet/dpo/mpls_disposition.c316
1 files changed, 235 insertions, 81 deletions
diff --git a/src/vnet/dpo/mpls_disposition.c b/src/vnet/dpo/mpls_disposition.c
index 77429de4116..2956e541d57 100644
--- a/src/vnet/dpo/mpls_disposition.c
+++ b/src/vnet/dpo/mpls_disposition.c
@@ -42,38 +42,55 @@ mpls_disp_dpo_get_index (mpls_disp_dpo_t *mdd)
return (mdd - mpls_disp_dpo_pool);
}
-index_t
+void
mpls_disp_dpo_create (dpo_proto_t payload_proto,
fib_rpf_id_t rpf_id,
- const dpo_id_t *dpo)
+ fib_mpls_lsp_mode_t mode,
+ const dpo_id_t *parent,
+ dpo_id_t *dpo)
{
mpls_disp_dpo_t *mdd;
+ dpo_type_t dtype;
mdd = mpls_disp_dpo_alloc();
mdd->mdd_payload_proto = payload_proto;
mdd->mdd_rpf_id = rpf_id;
-
- dpo_stack(DPO_MPLS_DISPOSITION,
+ mdd->mdd_mode = mode;
+ dtype = (FIB_MPLS_LSP_MODE_PIPE == mode ?
+ DPO_MPLS_DISPOSITION_PIPE :
+ DPO_MPLS_DISPOSITION_UNIFORM);
+
+ /*
+ * stack this disposition object on the parent given
+ */
+ dpo_stack(dtype,
mdd->mdd_payload_proto,
&mdd->mdd_dpo,
- dpo);
-
- return (mpls_disp_dpo_get_index(mdd));
+ parent);
+
+ /*
+ * set up the return DPO to refer to this object
+ */
+ dpo_set(dpo,
+ dtype,
+ payload_proto,
+ mpls_disp_dpo_get_index(mdd));
}
u8*
format_mpls_disp_dpo (u8 *s, va_list *args)
{
- index_t index = va_arg (*args, index_t);
- u32 indent = va_arg (*args, u32);
+ index_t index = va_arg(*args, index_t);
+ u32 indent = va_arg(*args, u32);
mpls_disp_dpo_t *mdd;
mdd = mpls_disp_dpo_get(index);
- s = format(s, "mpls-disposition:[%d]:[%U]",
+ s = format(s, "mpls-disposition:[%d]:[%U, %U]",
index,
- format_dpo_proto, mdd->mdd_payload_proto);
+ format_dpo_proto, mdd->mdd_payload_proto,
+ format_fib_mpls_lsp_mode, mdd->mdd_mode);
s = format(s, "\n%U", format_white_space, indent);
s = format(s, "%U", format_dpo_id, &mdd->mdd_dpo, indent+2);
@@ -116,25 +133,41 @@ typedef struct mpls_label_disposition_trace_t_
index_t mdd;
} mpls_label_disposition_trace_t;
-extern vlib_node_registration_t ip4_mpls_label_disposition_node;
-extern vlib_node_registration_t ip6_mpls_label_disposition_node;
+extern vlib_node_registration_t ip4_mpls_label_disposition_pipe_node;
+extern vlib_node_registration_t ip6_mpls_label_disposition_pipe_node;
+extern vlib_node_registration_t ip4_mpls_label_disposition_uniform_node;
+extern vlib_node_registration_t ip6_mpls_label_disposition_uniform_node;
always_inline uword
mpls_label_disposition_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame,
- u8 payload_is_ip4,
- u8 payload_is_ip6)
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame,
+ u8 payload_is_ip4,
+ u8 payload_is_ip6,
+ fib_mpls_lsp_mode_t mode)
{
u32 n_left_from, next_index, * from, * to_next;
vlib_node_runtime_t *error_node;
if (payload_is_ip4)
- error_node = vlib_node_get_runtime (vm, ip4_mpls_label_disposition_node.index);
+ {
+ if (FIB_MPLS_LSP_MODE_PIPE == mode)
+ error_node =
+ vlib_node_get_runtime(vm, ip4_mpls_label_disposition_pipe_node.index);
+ else
+ error_node =
+ vlib_node_get_runtime(vm, ip4_mpls_label_disposition_uniform_node.index);
+ }
else
- error_node = vlib_node_get_runtime (vm, ip6_mpls_label_disposition_node.index);
-
- from = vlib_frame_vector_args (from_frame);
+ {
+ if (FIB_MPLS_LSP_MODE_PIPE == mode)
+ error_node =
+ vlib_node_get_runtime(vm, ip6_mpls_label_disposition_uniform_node.index);
+ else
+ error_node =
+ vlib_node_get_runtime(vm, ip6_mpls_label_disposition_uniform_node.index);
+ }
+ from = vlib_frame_vector_args(from_frame);
n_left_from = from_frame->n_vectors;
next_index = node->cached_next_index;
@@ -159,14 +192,14 @@ mpls_label_disposition_inline (vlib_main_t * vm,
{
vlib_buffer_t * p2, * p3;
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
+ p2 = vlib_get_buffer(vm, from[2]);
+ p3 = vlib_get_buffer(vm, from[3]);
- vlib_prefetch_buffer_header (p2, STORE);
- vlib_prefetch_buffer_header (p3, STORE);
+ vlib_prefetch_buffer_header(p2, STORE);
+ vlib_prefetch_buffer_header(p3, STORE);
- CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), STORE);
- CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), STORE);
+ CLIB_PREFETCH(p2->data, sizeof(ip6_header_t), STORE);
+ CLIB_PREFETCH(p3->data, sizeof(ip6_header_t), STORE);
}
from += 2;
@@ -174,8 +207,8 @@ mpls_label_disposition_inline (vlib_main_t * vm,
n_left_from -= 2;
n_left_to_next -= 2;
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
+ b0 = vlib_get_buffer(vm, bi0);
+ b1 = vlib_get_buffer(vm, bi1);
/* dst lookup was done by ip4 lookup */
mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
@@ -190,30 +223,62 @@ mpls_label_disposition_inline (vlib_main_t * vm,
{
ip4_header_t *ip0, *ip1;
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
+ ip0 = vlib_buffer_get_current(b0);
+ ip1 = vlib_buffer_get_current(b1);
/*
* IPv4 input checks on the exposed IP header
* including checksum
*/
- ip4_input_check_x2 (vm, error_node,
- b0, b1, ip0, ip1,
- &next0, &next1, 1);
+ ip4_input_check_x2(vm, error_node,
+ b0, b1, ip0, ip1,
+ &next0, &next1, 1);
+
+ if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
+ {
+ /*
+ * Copy the TTL from the MPLS packet into the
+ * exposed IP. recalc the chksum
+ */
+ ip0->ttl = vnet_buffer(b0)->mpls.ttl;
+ ip1->ttl = vnet_buffer(b1)->mpls.ttl;
+ ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp);
+ ip1->tos = mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp);
+
+ ip0->checksum = ip4_header_checksum(ip0);
+ ip1->checksum = ip4_header_checksum(ip1);
+ }
}
else if (payload_is_ip6)
{
ip6_header_t *ip0, *ip1;
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
+ ip0 = vlib_buffer_get_current(b0);
+ ip1 = vlib_buffer_get_current(b1);
/*
* IPv6 input checks on the exposed IP header
*/
- ip6_input_check_x2 (vm, error_node,
- b0, b1, ip0, ip1,
- &next0, &next1);
+ ip6_input_check_x2(vm, error_node,
+ b0, b1, ip0, ip1,
+ &next0, &next1);
+
+ if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
+ {
+ /*
+ * Copy the TTL from the MPLS packet into the
+ * exposed IP
+ */
+ ip0->hop_limit = vnet_buffer(b0)->mpls.ttl;
+ ip1->hop_limit = vnet_buffer(b1)->mpls.ttl;
+
+ ip6_set_traffic_class_network_order(
+ ip0,
+ mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp));
+ ip6_set_traffic_class_network_order(
+ ip1,
+ mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp));
+ }
}
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
@@ -224,14 +289,14 @@ mpls_label_disposition_inline (vlib_main_t * vm,
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_disposition_trace_t *tr =
- vlib_add_trace (vm, node, b0, sizeof (*tr));
+ vlib_add_trace(vm, node, b0, sizeof(*tr));
tr->mdd = mddi0;
}
if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_disposition_trace_t *tr =
- vlib_add_trace (vm, node, b1, sizeof (*tr));
+ vlib_add_trace(vm, node, b1, sizeof(*tr));
tr->mdd = mddi1;
}
@@ -254,7 +319,7 @@ mpls_label_disposition_inline (vlib_main_t * vm,
n_left_from -= 1;
n_left_to_next -= 1;
- b0 = vlib_get_buffer (vm, bi0);
+ b0 = vlib_get_buffer(vm, bi0);
/* dst lookup was done by ip4 lookup */
mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
@@ -265,24 +330,48 @@ mpls_label_disposition_inline (vlib_main_t * vm,
{
ip4_header_t *ip0;
- ip0 = vlib_buffer_get_current (b0);
+ ip0 = vlib_buffer_get_current(b0);
/*
* IPv4 input checks on the exposed IP header
* including checksum
*/
- ip4_input_check_x1 (vm, error_node, b0, ip0, &next0, 1);
+ ip4_input_check_x1(vm, error_node, b0, ip0, &next0, 1);
+
+ if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
+ {
+ /*
+ * Copy the TTL from the MPLS packet into the
+ * exposed IP. recalc the chksum
+ */
+ ip0->ttl = vnet_buffer(b0)->mpls.ttl;
+ ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp);
+ ip0->checksum = ip4_header_checksum(ip0);
+ }
}
else if (payload_is_ip6)
{
ip6_header_t *ip0;
- ip0 = vlib_buffer_get_current (b0);
+ ip0 = vlib_buffer_get_current(b0);
/*
* IPv6 input checks on the exposed IP header
*/
- ip6_input_check_x1 (vm, error_node, b0, ip0, &next0);
+ ip6_input_check_x1(vm, error_node, b0, ip0, &next0);
+
+ if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
+ {
+ /*
+ * Copy the TTL from the MPLS packet into the
+ * exposed IP
+ */
+ ip0->hop_limit = vnet_buffer(b0)->mpls.ttl;
+
+ ip6_set_traffic_class_network_order(
+ ip0,
+ mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp));
+ }
}
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
@@ -291,14 +380,14 @@ mpls_label_disposition_inline (vlib_main_t * vm,
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_disposition_trace_t *tr =
- vlib_add_trace (vm, node, b0, sizeof (*tr));
+ vlib_add_trace(vm, node, b0, sizeof(*tr));
tr->mdd = mddi0;
}
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);
+ vlib_put_next_frame(vm, node, next_index, n_left_to_next);
}
return from_frame->n_vectors;
}
@@ -306,57 +395,103 @@ mpls_label_disposition_inline (vlib_main_t * vm,
static u8 *
format_mpls_label_disposition_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 *);
- CLIB_UNUSED (mpls_label_disposition_trace_t * t);
+ CLIB_UNUSED(vlib_main_t * vm) = va_arg(*args, vlib_main_t *);
+ CLIB_UNUSED(vlib_node_t * node) = va_arg(*args, vlib_node_t *);
+ CLIB_UNUSED(mpls_label_disposition_trace_t * t);
- t = va_arg (*args, mpls_label_disposition_trace_t *);
+ t = va_arg(*args, mpls_label_disposition_trace_t *);
s = format(s, "disp:%d", t->mdd);
return (s);
}
static uword
-ip4_mpls_label_disposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ip4_mpls_label_disposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_disposition_inline(vm, node, frame, 1, 0));
+ return (mpls_label_disposition_inline(vm, node, frame, 1, 0,
+ FIB_MPLS_LSP_MODE_PIPE));
}
-VLIB_REGISTER_NODE (ip4_mpls_label_disposition_node) = {
- .function = ip4_mpls_label_disposition,
- .name = "ip4-mpls-label-disposition",
- .vector_size = sizeof (u32),
+VLIB_REGISTER_NODE(ip4_mpls_label_disposition_pipe_node) = {
+ .function = ip4_mpls_label_disposition_pipe,
+ .name = "ip4-mpls-label-disposition-pipe",
+ .vector_size = sizeof(u32),
.format_trace = format_mpls_label_disposition_trace,
.sibling_of = "ip4-input",
.n_errors = IP4_N_ERROR,
.error_strings = ip4_error_strings,
};
-VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_disposition_node,
- ip4_mpls_label_disposition)
+VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_pipe_node,
+ ip4_mpls_label_disposition_pipe)
static uword
-ip6_mpls_label_disposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ip6_mpls_label_disposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_disposition_inline(vm, node, frame, 0, 1));
+ return (mpls_label_disposition_inline(vm, node, frame, 0, 1,
+ FIB_MPLS_LSP_MODE_PIPE));
}
-VLIB_REGISTER_NODE (ip6_mpls_label_disposition_node) = {
- .function = ip6_mpls_label_disposition,
- .name = "ip6-mpls-label-disposition",
- .vector_size = sizeof (u32),
+VLIB_REGISTER_NODE(ip6_mpls_label_disposition_pipe_node) = {
+ .function = ip6_mpls_label_disposition_pipe,
+ .name = "ip6-mpls-label-disposition-pipe",
+ .vector_size = sizeof(u32),
.format_trace = format_mpls_label_disposition_trace,
.sibling_of = "ip6-input",
.n_errors = IP6_N_ERROR,
.error_strings = ip6_error_strings,
};
-VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_disposition_node,
- ip6_mpls_label_disposition)
+VLIB_NODE_FUNCTION_MULTIARCH(ip6_mpls_label_disposition_pipe_node,
+ ip6_mpls_label_disposition_pipe)
+
+static uword
+ip4_mpls_label_disposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_disposition_inline(vm, node, frame, 1, 0,
+ FIB_MPLS_LSP_MODE_UNIFORM));
+}
+
+VLIB_REGISTER_NODE(ip4_mpls_label_disposition_uniform_node) = {
+ .function = ip4_mpls_label_disposition_uniform,
+ .name = "ip4-mpls-label-disposition-uniform",
+ .vector_size = sizeof(u32),
+
+ .format_trace = format_mpls_label_disposition_trace,
+ .sibling_of = "ip4-input",
+ .n_errors = IP4_N_ERROR,
+ .error_strings = ip4_error_strings,
+};
+VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_uniform_node,
+ ip4_mpls_label_disposition_uniform)
+
+static uword
+ip6_mpls_label_disposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_disposition_inline(vm, node, frame, 0, 1,
+ FIB_MPLS_LSP_MODE_UNIFORM));
+}
+
+VLIB_REGISTER_NODE(ip6_mpls_label_disposition_uniform_node) = {
+ .function = ip6_mpls_label_disposition_uniform,
+ .name = "ip6-mpls-label-disposition-uniform",
+ .vector_size = sizeof(u32),
+
+ .format_trace = format_mpls_label_disposition_trace,
+ .sibling_of = "ip6-input",
+ .n_errors = IP6_N_ERROR,
+ .error_strings = ip6_error_strings,
+};
+VLIB_NODE_FUNCTION_MULTIARCH(ip6_mpls_label_disposition_uniform_node,
+ ip6_mpls_label_disposition_uniform)
static void
mpls_disp_dpo_mem_show (void)
@@ -374,25 +509,44 @@ const static dpo_vft_t mdd_vft = {
.dv_mem_show = mpls_disp_dpo_mem_show,
};
-const static char* const mpls_label_disp_ip4_nodes[] =
+const static char* const mpls_label_disp_pipe_ip4_nodes[] =
+{
+ "ip4-mpls-label-disposition-pipe",
+ NULL,
+};
+const static char* const mpls_label_disp_pipe_ip6_nodes[] =
+{
+ "ip6-mpls-label-disposition-pipe",
+ NULL,
+};
+const static char* const * const mpls_label_disp_pipe_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = mpls_label_disp_pipe_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_disp_pipe_ip6_nodes,
+};
+
+const static char* const mpls_label_disp_uniform_ip4_nodes[] =
{
- "ip4-mpls-label-disposition",
+ "ip4-mpls-label-disposition-uniform",
NULL,
};
-const static char* const mpls_label_disp_ip6_nodes[] =
+const static char* const mpls_label_disp_uniform_ip6_nodes[] =
{
- "ip6-mpls-label-disposition",
+ "ip6-mpls-label-disposition-uniform",
NULL,
};
-const static char* const * const mpls_label_disp_nodes[DPO_PROTO_NUM] =
+const static char* const * const mpls_label_disp_uniform_nodes[DPO_PROTO_NUM] =
{
- [DPO_PROTO_IP4] = mpls_label_disp_ip4_nodes,
- [DPO_PROTO_IP6] = mpls_label_disp_ip6_nodes,
+ [DPO_PROTO_IP4] = mpls_label_disp_uniform_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_disp_uniform_ip6_nodes,
};
void
-mpls_disp_dpo_module_init (void)
+mpls_disp_dpo_module_init(void)
{
- dpo_register(DPO_MPLS_DISPOSITION, &mdd_vft, mpls_label_disp_nodes);
+ dpo_register(DPO_MPLS_DISPOSITION_PIPE, &mdd_vft,
+ mpls_label_disp_pipe_nodes);
+ dpo_register(DPO_MPLS_DISPOSITION_UNIFORM, &mdd_vft,
+ mpls_label_disp_uniform_nodes);
}