aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo
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
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')
-rw-r--r--src/vnet/dpo/dpo.h8
-rw-r--r--src/vnet/dpo/mpls_disposition.c316
-rw-r--r--src/vnet/dpo/mpls_disposition.h15
-rw-r--r--src/vnet/dpo/mpls_label_dpo.c1075
-rw-r--r--src/vnet/dpo/mpls_label_dpo.h65
5 files changed, 1150 insertions, 329 deletions
diff --git a/src/vnet/dpo/dpo.h b/src/vnet/dpo/dpo.h
index afee458c02f..4d484786fba 100644
--- a/src/vnet/dpo/dpo.h
+++ b/src/vnet/dpo/dpo.h
@@ -111,8 +111,8 @@ typedef enum dpo_type_t_ {
DPO_LOOKUP,
DPO_LISP_CP,
DPO_CLASSIFY,
- DPO_MPLS_LABEL,
- DPO_MPLS_DISPOSITION,
+ DPO_MPLS_DISPOSITION_PIPE,
+ DPO_MPLS_DISPOSITION_UNIFORM,
DPO_MFIB_ENTRY,
DPO_INTERFACE_RX,
DPO_INTERFACE_TX,
@@ -146,8 +146,8 @@ typedef enum dpo_type_t_ {
[DPO_REPLICATE] = "dpo-replicate", \
[DPO_LISP_CP] = "dpo-lisp-cp", \
[DPO_CLASSIFY] = "dpo-classify", \
- [DPO_MPLS_LABEL] = "dpo-mpls-label", \
- [DPO_MPLS_DISPOSITION] = "dpo-mpls-diposition", \
+ [DPO_MPLS_DISPOSITION_PIPE] = "dpo-mpls-diposition-pipe", \
+ [DPO_MPLS_DISPOSITION_UNIFORM] = "dpo-mpls-diposition-uniform", \
[DPO_MFIB_ENTRY] = "dpo-mfib-entry", \
[DPO_INTERFACE_RX] = "dpo-interface-rx", \
[DPO_INTERFACE_TX] = "dpo-interface-tx", \
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);
}
diff --git a/src/vnet/dpo/mpls_disposition.h b/src/vnet/dpo/mpls_disposition.h
index 9c0150830d2..9c3cc46ff30 100644
--- a/src/vnet/dpo/mpls_disposition.h
+++ b/src/vnet/dpo/mpls_disposition.h
@@ -45,6 +45,11 @@ typedef struct mpls_disp_dpo_t
* Number of locks/users of the label
*/
u16 mdd_locks;
+
+ /**
+ * LSP mode
+ */
+ fib_mpls_lsp_mode_t mdd_mode;
} mpls_disp_dpo_t;
/**
@@ -60,11 +65,15 @@ _Static_assert((sizeof(mpls_disp_dpo_t) <= CLIB_CACHE_LINE_BYTES),
*
* @param payload_proto The ptocool of the payload packets that will
* be imposed with this label header.
+ * @param rpf_id The RPF ID the packet will aquire - only for mcast
+ * @param mode The LSP mode; pipe or uniform
* @param dpo The parent of the created MPLS label object
*/
-extern index_t mpls_disp_dpo_create(dpo_proto_t payload_proto,
- fib_rpf_id_t rpf_id,
- const dpo_id_t *dpo);
+extern void mpls_disp_dpo_create(dpo_proto_t payload_proto,
+ fib_rpf_id_t rpf_id,
+ fib_mpls_lsp_mode_t mode,
+ const dpo_id_t *parent,
+ dpo_id_t *dpo);
extern u8* format_mpls_disp_dpo(u8 *s, va_list *args);
diff --git a/src/vnet/dpo/mpls_label_dpo.c b/src/vnet/dpo/mpls_label_dpo.c
index fa5177ab9ea..954d637937b 100644
--- a/src/vnet/dpo/mpls_label_dpo.c
+++ b/src/vnet/dpo/mpls_label_dpo.c
@@ -23,6 +23,17 @@
*/
mpls_label_dpo_t *mpls_label_dpo_pool;
+/**
+ * Strings for the flags
+ */
+const char* mpls_label_dpo_attr_names[] = MPLS_LABEL_DPO_ATTR_NAMES;
+
+/**
+ * registered DPO types for each of the label sub-types. And there's a
+ * subtype for each of the flag combinations.
+ */
+static dpo_type_t mpls_label_dpo_types[1 << MPLS_LABEL_DPO_ATTR_MAX];
+
static mpls_label_dpo_t *
mpls_label_dpo_alloc (void)
{
@@ -42,70 +53,138 @@ mpls_label_dpo_get_index (mpls_label_dpo_t *mld)
return (mld - mpls_label_dpo_pool);
}
-index_t
-mpls_label_dpo_create (mpls_label_t *label_stack,
+void
+mpls_label_dpo_create (fib_mpls_label_t *label_stack,
mpls_eos_bit_t eos,
- u8 ttl,
- u8 exp,
dpo_proto_t payload_proto,
- const dpo_id_t *dpo)
+ mpls_label_dpo_flags_t flags,
+ const dpo_id_t *parent,
+ dpo_id_t *dpo)
{
mpls_label_dpo_t *mld;
+ dpo_type_t dtype;
u32 ii;
+ if ((DPO_PROTO_IP4 != payload_proto) &&
+ (DPO_PROTO_IP6 != payload_proto))
+ {
+ /*
+ * remove unsupported configuration
+ */
+ flags &= ~MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR;
+ }
+
mld = mpls_label_dpo_alloc();
+ mld->mld_flags = flags;
+ dtype = mpls_label_dpo_types[flags];
if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
{
clib_warning("Label stack size exceeded");
- dpo_stack(DPO_MPLS_LABEL,
+ dpo_stack(dtype,
mld->mld_payload_proto,
&mld->mld_dpo,
drop_dpo_get(DPO_PROTO_MPLS));
- return (mpls_label_dpo_get_index(mld));
}
+ else
+ {
+ mld->mld_n_labels = vec_len(label_stack);
+ mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
+ mld->mld_payload_proto = payload_proto;
+
+ /*
+ * construct label rewrite headers for each value passed.
+ * get the header in network byte order since we will paint it
+ * on a packet in the data-plane
+ */
+ for (ii = 0; ii < mld->mld_n_labels-1; ii++)
+ {
+ vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_value);
+ vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_exp);
+ vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl,
+ MPLS_NON_EOS);
+ if (0 != label_stack[ii].fml_ttl)
+ {
+ vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_ttl);
+ }
+ else
+ {
+ vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
+ MPLS_LABEL_DEFAULT_TTL);
+ }
+ mld->mld_hdr[ii].label_exp_s_ttl =
+ clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
+ }
- mld->mld_n_labels = vec_len(label_stack);
- mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
- mld->mld_payload_proto = payload_proto;
+ /*
+ * the inner most label
+ */
+ ii = mld->mld_n_labels-1;
+
+ vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_value);
+ vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_exp);
+ vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
+ if (0 != label_stack[ii].fml_ttl)
+ {
+ vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
+ label_stack[ii].fml_ttl);
+ }
+ else
+ {
+ vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
+ MPLS_LABEL_DEFAULT_TTL);
+ }
+ mld->mld_hdr[ii].label_exp_s_ttl =
+ clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
- /*
- * construct label rewrite headers for each value value passed.
- * get the header in network byte order since we will paint it
- * on a packet in the data-plane
- */
+ /*
+ * pipe/uniform mode is only supported for the bottom of stack label
+ */
+ if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
+ {
+ mld->mld_flags |= MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
+ }
+ else
+ {
+ mld->mld_flags &= ~MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
+ }
+ dtype = mpls_label_dpo_types[mld->mld_flags];
- for (ii = 0; ii < mld->mld_n_labels-1; ii++)
- {
- vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
- vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl, 255);
- vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl, 0);
- vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, MPLS_NON_EOS);
- mld->mld_hdr[ii].label_exp_s_ttl =
- clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
+ /*
+ * stack this label object on its parent.
+ */
+ dpo_stack(dtype,
+ mld->mld_payload_proto,
+ &mld->mld_dpo,
+ parent);
}
- /*
- * the inner most label
- */
- ii = mld->mld_n_labels-1;
+ dpo_set(dpo,
+ dtype,
+ mld->mld_payload_proto,
+ mpls_label_dpo_get_index(mld));
+}
- vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
- vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl, ttl);
- vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl, exp);
- vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
- mld->mld_hdr[ii].label_exp_s_ttl =
- clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
+u8*
+format_mpls_label_dpo_flags (u8 *s, va_list *args)
+{
+ mpls_label_dpo_flags_t flags = va_arg (*args, int);
+ mpls_label_dpo_attr_t attr;
- /*
- * stack this label objct on its parent.
- */
- dpo_stack(DPO_MPLS_LABEL,
- mld->mld_payload_proto,
- &mld->mld_dpo,
- dpo);
+ FOR_EACH_MPLS_LABEL_DPO_ATTR(attr)
+ {
+ if ((1 << attr) & flags)
+ {
+ s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
+ }
+ }
- return (mpls_label_dpo_get_index(mld));
+ return (s);
}
u8*
@@ -117,17 +196,18 @@ format_mpls_label_dpo (u8 *s, va_list *args)
mpls_label_dpo_t *mld;
u32 ii;
- s = format(s, "mpls-label:[%d]:", index);
-
if (pool_is_free_index(mpls_label_dpo_pool, index))
{
/*
* the packet trace can be printed after the DPO has been deleted
*/
- return (s);
+ return (format(s, "mpls-label[???,%d]:", index));
}
mld = mpls_label_dpo_get(index);
+ s = format(s, "mpls-label[%U%d]:",
+ format_mpls_label_dpo_flags,
+ (int) mld->mld_flags, index);
for (ii = 0; ii < mld->mld_n_labels; ii++)
{
@@ -178,12 +258,21 @@ typedef struct mpls_label_imposition_trace_t_
* The MPLS header imposed
*/
mpls_unicast_header_t hdr;
+
+ /**
+ * TTL imposed - only valid for uniform LSPs
+ */
+ u8 ttl;
+
+ /**
+ * TTL imposed - only valid for uniform LSPs
+ */
+ u8 exp;
} mpls_label_imposition_trace_t;
always_inline mpls_unicast_header_t *
mpls_label_paint (vlib_buffer_t * b0,
- mpls_label_dpo_t *mld0,
- u8 ttl0)
+ mpls_label_dpo_t *mld0)
{
mpls_unicast_header_t *hdr0;
@@ -201,19 +290,74 @@ mpls_label_paint (vlib_buffer_t * b0,
clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
hdr0 = hdr0 + (mld0->mld_n_labels - 1);
}
+
+ return (hdr0);
+}
+
+/**
+ * Paint on an MPLS label and fixup the TTL
+ */
+always_inline mpls_unicast_header_t *
+mpls_label_paint_w_ttl (vlib_buffer_t * b0,
+ mpls_label_dpo_t *mld0,
+ u8 ttl0)
+{
+ mpls_unicast_header_t *hdr0;
+
+ hdr0 = mpls_label_paint(b0, mld0);
+
/* fixup the TTL for the inner most label */
((char*)hdr0)[3] = ttl0;
return (hdr0);
}
+/**
+ * Paint on an MPLS label and fixup the TTL and EXP bits.
+ */
+always_inline mpls_unicast_header_t *
+mpls_label_paint_w_ttl_exp (vlib_buffer_t * b0,
+ mpls_label_dpo_t *mld0,
+ u8 ttl0,
+ u8 exp0)
+{
+ mpls_unicast_header_t *hdr0;
+
+ hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
+
+ /* fixup the EXP for the inner most label */
+ ((char*)hdr0)[2] |= (exp0 << 1);
+
+ return (hdr0);
+}
+
+/**
+ * Paint on an MPLS label and fixup the TTL and EXP bits
+ * When the EXP bits are *already* bit shift to the correct place in
+ * in the 2nd byte (i.e. they were read from another label)
+ */
+always_inline mpls_unicast_header_t *
+mpls_label_paint_w_ttl_mpls_exp (vlib_buffer_t * b0,
+ mpls_label_dpo_t *mld0,
+ u8 ttl0,
+ u8 exp0)
+{
+ mpls_unicast_header_t *hdr0;
+
+ hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
+
+ /* fixup the EXP for the inner most label */
+ ((char*)hdr0)[2] |= exp0;
+
+ return (hdr0);
+}
+
always_inline uword
mpls_label_imposition_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame,
- u8 payload_is_ip4,
- u8 payload_is_ip6,
- u8 payload_is_ethernet)
+ const dpo_proto_t dproto,
+ const mpls_label_dpo_flags_t flags)
{
u32 n_left_from, next_index, * from, * to_next;
@@ -235,7 +379,8 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
vlib_buffer_t * b0, *b1, * b2, *b3;
u32 next0, next1, next2, next3;
- u8 ttl0, ttl1,ttl2, ttl3 ;
+ u8 ttl0, ttl1, ttl2, ttl3;
+ u8 exp0, exp1, exp2, exp3;
bi0 = to_next[0] = from[0];
bi1 = to_next[1] = from[1];
@@ -282,141 +427,247 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mld2 = mpls_label_dpo_get(mldi2);
mld3 = mpls_label_dpo_get(mldi3);
- if (payload_is_ip4)
+ if (DPO_PROTO_MPLS != dproto)
{
/*
- * decrement the TTL on ingress to the LSP
+ * These are the non-MPLS payload imposition cases
*/
- ip4_header_t * ip0 = vlib_buffer_get_current(b0);
- ip4_header_t * ip1 = vlib_buffer_get_current(b1);
- ip4_header_t * ip2 = vlib_buffer_get_current(b2);
- ip4_header_t * ip3 = vlib_buffer_get_current(b3);
- u32 checksum0;
- u32 checksum1;
- u32 checksum2;
- u32 checksum3;
-
- checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
- checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
- checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
- checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
-
- checksum0 += checksum0 >= 0xffff;
- checksum1 += checksum1 >= 0xffff;
- checksum2 += checksum2 >= 0xffff;
- checksum3 += checksum3 >= 0xffff;
-
- ip0->checksum = checksum0;
- ip1->checksum = checksum1;
- ip2->checksum = checksum2;
- ip3->checksum = checksum3;
-
- ip0->ttl -= 1;
- ip1->ttl -= 1;
- ip2->ttl -= 1;
- ip3->ttl -= 1;
-
- ttl1 = ip1->ttl;
- ttl0 = ip0->ttl;
- ttl3 = ip3->ttl;
- ttl2 = ip2->ttl;
- }
- else if (payload_is_ip6)
- {
- /*
- * decrement the TTL on ingress to the LSP
- */
- ip6_header_t * ip0 = vlib_buffer_get_current(b0);
- ip6_header_t * ip1 = vlib_buffer_get_current(b1);
- ip6_header_t * ip2 = vlib_buffer_get_current(b2);
- ip6_header_t * ip3 = vlib_buffer_get_current(b3);
-
- ip0->hop_limit -= 1;
- ip1->hop_limit -= 1;
- ip2->hop_limit -= 1;
- ip3->hop_limit -= 1;
-
- ttl0 = ip0->hop_limit;
- ttl1 = ip1->hop_limit;
- ttl2 = ip2->hop_limit;
- ttl3 = ip3->hop_limit;
- }
- else if (payload_is_ethernet)
- {
+ if (DPO_PROTO_IP4 == dproto)
+ {
+ ip4_header_t * ip0 = vlib_buffer_get_current(b0);
+ ip4_header_t * ip1 = vlib_buffer_get_current(b1);
+ ip4_header_t * ip2 = vlib_buffer_get_current(b2);
+ ip4_header_t * ip3 = vlib_buffer_get_current(b3);
+
+ if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
+ {
+ /*
+ * decrement the TTL on ingress to the LSP
+ */
+ u32 checksum0;
+ u32 checksum1;
+ u32 checksum2;
+ u32 checksum3;
+
+ checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
+ checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
+ checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
+ checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
+
+ checksum0 += checksum0 >= 0xffff;
+ checksum1 += checksum1 >= 0xffff;
+ checksum2 += checksum2 >= 0xffff;
+ checksum3 += checksum3 >= 0xffff;
+
+ ip0->checksum = checksum0;
+ ip1->checksum = checksum1;
+ ip2->checksum = checksum2;
+ ip3->checksum = checksum3;
+
+ ip0->ttl -= 1;
+ ip1->ttl -= 1;
+ ip2->ttl -= 1;
+ ip3->ttl -= 1;
+ }
+
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ ttl1 = ip1->ttl;
+ ttl0 = ip0->ttl;
+ ttl3 = ip3->ttl;
+ ttl2 = ip2->ttl;
+ /* by default copy the 3 most significant bits */
+ exp0 = ip_dscp_to_mpls_exp(ip0->tos);
+ exp1 = ip_dscp_to_mpls_exp(ip1->tos);
+ exp2 = ip_dscp_to_mpls_exp(ip2->tos);
+ exp3 = ip_dscp_to_mpls_exp(ip3->tos);
+ }
+ }
+ else if (DPO_PROTO_IP6 == dproto)
+ {
+ /*
+ * decrement the TTL on ingress to the LSP
+ */
+ ip6_header_t * ip0 = vlib_buffer_get_current(b0);
+ ip6_header_t * ip1 = vlib_buffer_get_current(b1);
+ ip6_header_t * ip2 = vlib_buffer_get_current(b2);
+ ip6_header_t * ip3 = vlib_buffer_get_current(b3);
+
+ if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
+ {
+ ip0->hop_limit -= 1;
+ ip1->hop_limit -= 1;
+ ip2->hop_limit -= 1;
+ ip3->hop_limit -= 1;
+ }
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ ttl0 = ip0->hop_limit;
+ ttl1 = ip1->hop_limit;
+ ttl2 = ip2->hop_limit;
+ ttl3 = ip3->hop_limit;
+ /* by default copy the 3 most significant bits */
+ exp0 = ip_dscp_to_mpls_exp(
+ ip6_traffic_class_network_order(ip0));
+ exp1 = ip_dscp_to_mpls_exp(
+ ip6_traffic_class_network_order(ip1));
+ exp2 = ip_dscp_to_mpls_exp(
+ ip6_traffic_class_network_order(ip2));
+ exp3 = ip_dscp_to_mpls_exp(
+ ip6_traffic_class_network_order(ip3));
+ }
+ }
+ else
+ {
+ /*
+ * nothing to change in the ethernet header
+ */
+ ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
+ exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
+ }
/*
- * nothing to chang ein the ethernet header
+ * These are the non-MPLS payload imposition cases.
+ * Based on the LSP mode either, for uniform, copy down the TTL
+ * and EXP from the payload or, for pipe mode, slap on the value
+ * requested from config
*/
- ttl0 = ttl1 = ttl2 = ttl3 = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
+ hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
+ hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
+ hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
+ }
+ else
+ {
+ hdr0 = mpls_label_paint(b0, mld0);
+ hdr1 = mpls_label_paint(b1, mld1);
+ hdr2 = mpls_label_paint(b2, mld2);
+ hdr3 = mpls_label_paint(b3, mld3);
+ }
}
else
{
/*
* else, the packet to be encapped is an MPLS packet
+ * there are two cases to consider:
+ * 1 - this is an MPLS label swap at an LSP midpoint.
+ * recognisable because mpls.first = 1. In this case the
+ * TTL must be set to the current value -1.
+ * 2 - The MPLS packet is recursing (or being injected into)
+ * this LSP, in which case the pipe/uniform rules apply
+ *
*/
if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
{
/*
- * The first label to be imposed on the packet. this is a label swap.
- * in which case we stashed the TTL and EXP bits in the
- * packet in the lookup node
+ * The first label to be imposed on the packet. this is a
+ * label swap.in which case we stashed the TTL and EXP bits
+ * in the packet in the lookup node
*/
ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
+ exp0 = vnet_buffer(b0)->mpls.exp;
+ hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
}
else
{
/*
- * not the first label. implying we are recusring down a chain of
- * output labels.
- * Each layer is considered a new LSP - hence the TTL is reset.
+ * not the first label. implying we are recusring down a
+ * chain of output labels. Each layer is considered a new
+ * LSP - hence the TTL/EXP are pipe/uniform handled
*/
- ttl0 = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr0 = vlib_buffer_get_current(b0);
+ ttl0 = ((u8*)hdr0)[3];
+ exp0 = ((u8*)hdr0)[2] & 0xe;
+ hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
+ }
+ else
+ {
+ hdr0 = mpls_label_paint(b0, mld0);
+ }
}
if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
{
- ASSERT(1 != vnet_buffer (b1)->mpls.ttl);
+ ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
+
ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
+ exp1 = vnet_buffer(b1)->mpls.exp;
+ hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
}
else
{
- ttl1 = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr1 = vlib_buffer_get_current(b1);
+ ttl1 = ((u8*)hdr1)[3];
+ exp1 = ((u8*)hdr1)[2] & 0xe;
+ hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
+ }
+ else
+ {
+ hdr1 = mpls_label_paint(b1, mld1);
+ }
}
if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
{
- ASSERT(1 != vnet_buffer (b2)->mpls.ttl);
+ ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
+ exp2 = vnet_buffer(b2)->mpls.exp;
+ hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
}
else
{
- ttl2 = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr2 = vlib_buffer_get_current(b2);
+ ttl2 = ((u8*)hdr2)[3];
+ exp2 = ((u8*)hdr2)[2] & 0xe;
+ hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
+ }
+ else
+ {
+ hdr2 = mpls_label_paint(b2, mld2);
+ }
}
if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
{
- ASSERT(1 != vnet_buffer (b3)->mpls.ttl);
+ ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
+
ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
+ exp3 = vnet_buffer(b0)->mpls.exp;
+ hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
}
else
{
- ttl3 = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr3 = vlib_buffer_get_current(b3);
+ ttl3 = ((u8*)hdr3)[3];
+ exp3 = ((u8*)hdr3)[2] & 0xe;
+ hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
+ }
+ else
+ {
+ hdr3 = mpls_label_paint(b3, mld3);
+ }
}
- }
- vnet_buffer(b0)->mpls.first = 0;
- vnet_buffer(b1)->mpls.first = 0;
- vnet_buffer(b2)->mpls.first = 0;
- vnet_buffer(b3)->mpls.first = 0;
- /* Paint the MPLS header */
- hdr0 = mpls_label_paint(b0, mld0, ttl0);
- hdr1 = mpls_label_paint(b1, mld1, ttl1);
- hdr2 = mpls_label_paint(b2, mld2, ttl2);
- hdr3 = mpls_label_paint(b3, mld3, ttl3);
+ vnet_buffer(b0)->mpls.first = 0;
+ vnet_buffer(b1)->mpls.first = 0;
+ vnet_buffer(b2)->mpls.first = 0;
+ vnet_buffer(b3)->mpls.first = 0;
+ }
next0 = mld0->mld_dpo.dpoi_next_node;
next1 = mld1->mld_dpo.dpoi_next_node;
next2 = mld2->mld_dpo.dpoi_next_node;
next3 = mld3->mld_dpo.dpoi_next_node;
+
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
@@ -427,24 +678,60 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mpls_label_imposition_trace_t *tr =
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->hdr = *hdr0;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ tr->ttl = ttl0;
+ tr->exp = exp0;
+ }
+ else
+ {
+ tr->ttl = tr->exp = 0;
+ }
}
if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_imposition_trace_t *tr =
vlib_add_trace (vm, node, b1, sizeof (*tr));
tr->hdr = *hdr1;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ tr->ttl = ttl1;
+ tr->exp = exp1;
+ }
+ else
+ {
+ tr->ttl = tr->exp = 0;
+ }
}
if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_imposition_trace_t *tr =
vlib_add_trace (vm, node, b2, sizeof (*tr));
tr->hdr = *hdr2;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ tr->ttl = ttl2;
+ tr->exp = exp2;
+ }
+ else
+ {
+ tr->ttl = tr->exp = 0;
+ }
}
if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
{
mpls_label_imposition_trace_t *tr =
vlib_add_trace (vm, node, b3, sizeof (*tr));
tr->hdr = *hdr3;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ tr->ttl = ttl3;
+ tr->exp = exp3;
+ }
+ else
+ {
+ tr->ttl = tr->exp = 0;
+ }
}
vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
@@ -459,8 +746,8 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mpls_label_dpo_t *mld0;
vlib_buffer_t * b0;
u32 bi0, mldi0;
+ u8 ttl0, exp0;
u32 next0;
- u8 ttl;
bi0 = from[0];
to_next[0] = bi0;
@@ -475,67 +762,99 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
mld0 = mpls_label_dpo_get(mldi0);
- if (payload_is_ip4)
+ if (DPO_PROTO_MPLS != dproto)
{
- /*
- * decrement the TTL on ingress to the LSP
- */
- ip4_header_t * ip0 = vlib_buffer_get_current(b0);
- u32 checksum0;
-
- checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
- checksum0 += checksum0 >= 0xffff;
+ if (DPO_PROTO_IP4 == dproto)
+ {
+ /*
+ * decrement the TTL on ingress to the LSP
+ */
+ ip4_header_t * ip0 = vlib_buffer_get_current(b0);
+ if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
+ {
+ u32 checksum0;
+
+ checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
+ checksum0 += checksum0 >= 0xffff;
+
+ ip0->checksum = checksum0;
+ ip0->ttl -= 1;
+ }
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ ttl0 = ip0->ttl;
+ exp0 = ip_dscp_to_mpls_exp(ip0->tos);
+ }
+ }
+ else if (DPO_PROTO_IP6 == dproto)
+ {
+ /*
+ * decrement the TTL on ingress to the LSP
+ */
+ ip6_header_t * ip0 = vlib_buffer_get_current(b0);
+
+ if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
+ {
+ ip0->hop_limit -= 1;
+ }
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ ttl0 = ip0->hop_limit;
+ exp0 = ip_dscp_to_mpls_exp(
+ ip6_traffic_class_network_order(ip0));
+ }
+ }
+ else
+ {
+ /*
+ * nothing to change in the ethernet header
+ */
+ ttl0 = MPLS_LABEL_DEFAULT_TTL;
+ exp0 = MPLS_LABEL_DEFAULT_EXP;
+ }
- ip0->checksum = checksum0;
- ip0->ttl -= 1;
- ttl = ip0->ttl;
- }
- else if (payload_is_ip6)
- {
/*
- * decrement the TTL on ingress to the LSP
+ * These are the non-MPLS payload imposition cases.
+ * Based on the LSP mode either, for uniform, copy down the TTL
+ * from the payload or, for pipe mode, slap on the value
+ * requested from config
*/
- ip6_header_t * ip0 = vlib_buffer_get_current(b0);
-
- ip0->hop_limit -= 1;
- ttl = ip0->hop_limit;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
+ }
+ else
+ {
+ hdr0 = mpls_label_paint(b0, mld0);
+ }
}
else
{
- /*
- * else, the packet to be encapped is an MPLS packet
- */
- if (vnet_buffer(b0)->mpls.first)
+ if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
{
- /*
- * The first label to be imposed on the packet. this is a label swap.
- * in which case we stashed the TTL and EXP bits in the
- * packet in the lookup node
- */
ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
- ttl = vnet_buffer(b0)->mpls.ttl - 1;
+ ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
+ exp0 = vnet_buffer(b0)->mpls.exp;
+ hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
}
else
{
- /*
- * not the first label. implying we are recusring down a chain of
- * output labels.
- * Each layer is considered a new LSP - hence the TTL is reset.
- */
- ttl = 255;
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ hdr0 = vlib_buffer_get_current(b0);
+ ttl0 = ((u8*)hdr0)[3];
+ exp0 = ((u8*)hdr0)[2] & 0xe;
+ hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
+ }
+ else
+ {
+ hdr0 = mpls_label_paint(b0, mld0);
+ }
}
- }
- vnet_buffer(b0)->mpls.first = 0;
-
- /* Paint the MPLS header */
- vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
- hdr0 = vlib_buffer_get_current(b0);
- clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
- /* fixup the TTL for the inner most label */
- hdr0 = hdr0 + (mld0->mld_n_labels - 1);
- ((char*)hdr0)[3] = ttl;
+ vnet_buffer(b0)->mpls.first = 0;
+ }
next0 = mld0->mld_dpo.dpoi_next_node;
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
@@ -545,7 +864,16 @@ mpls_label_imposition_inline (vlib_main_t * vm,
mpls_label_imposition_trace_t *tr =
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->hdr = *hdr0;
- }
+ if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
+ {
+ tr->ttl = ttl0;
+ tr->exp = exp0;
+ }
+ else
+ {
+ tr->ttl = tr->exp = 0;
+ }
+ }
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
n_left_to_next, bi0, next0);
@@ -575,16 +903,18 @@ format_mpls_label_imposition_trace (u8 * s, va_list * args)
}
static uword
-mpls_label_imposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+mpls_mpls_label_imposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_imposition_inline(vm, node, frame, 0, 0, 0));
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_MPLS,
+ MPLS_LABEL_DPO_FLAG_NONE));
}
-VLIB_REGISTER_NODE (mpls_label_imposition_node) = {
- .function = mpls_label_imposition,
- .name = "mpls-label-imposition",
+VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
+ .function = mpls_mpls_label_imposition_pipe,
+ .name = "mpls-label-imposition-pipe",
.vector_size = sizeof (u32),
.format_trace = format_mpls_label_imposition_trace,
@@ -593,20 +923,22 @@ VLIB_REGISTER_NODE (mpls_label_imposition_node) = {
[0] = "mpls-drop",
}
};
-VLIB_NODE_FUNCTION_MULTIARCH (mpls_label_imposition_node,
- mpls_label_imposition)
+VLIB_NODE_FUNCTION_MULTIARCH (mpls_mpls_label_imposition_pipe_node,
+ mpls_mpls_label_imposition_pipe)
static uword
-ip4_mpls_label_imposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ip4_mpls_label_imposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_imposition_inline(vm, node, frame, 1, 0, 0));
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP4,
+ MPLS_LABEL_DPO_FLAG_NONE));
}
-VLIB_REGISTER_NODE (ip4_mpls_label_imposition_node) = {
- .function = ip4_mpls_label_imposition,
- .name = "ip4-mpls-label-imposition",
+VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node) = {
+ .function = ip4_mpls_label_imposition_pipe,
+ .name = "ip4-mpls-label-imposition-pipe",
.vector_size = sizeof (u32),
.format_trace = format_mpls_label_imposition_trace,
@@ -615,20 +947,22 @@ VLIB_REGISTER_NODE (ip4_mpls_label_imposition_node) = {
[0] = "ip4-drop",
}
};
-VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_node,
- ip4_mpls_label_imposition)
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_pipe_node,
+ ip4_mpls_label_imposition_pipe)
static uword
-ip6_mpls_label_imposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ip6_mpls_label_imposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_imposition_inline(vm, node, frame, 0, 1, 0));
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP6,
+ MPLS_LABEL_DPO_FLAG_NONE));
}
-VLIB_REGISTER_NODE (ip6_mpls_label_imposition_node) = {
- .function = ip6_mpls_label_imposition,
- .name = "ip6-mpls-label-imposition",
+VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
+ .function = ip6_mpls_label_imposition_pipe,
+ .name = "ip6-mpls-label-imposition-pipe",
.vector_size = sizeof (u32),
.format_trace = format_mpls_label_imposition_trace,
@@ -637,20 +971,22 @@ VLIB_REGISTER_NODE (ip6_mpls_label_imposition_node) = {
[0] = "ip6-drop",
}
};
-VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_node,
- ip6_mpls_label_imposition)
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_pipe_node,
+ ip6_mpls_label_imposition_pipe)
static uword
-ethernet_mpls_label_imposition (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ethernet_mpls_label_imposition_pipe (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
- return (mpls_label_imposition_inline(vm, node, frame, 0, 0, 1));
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_ETHERNET,
+ MPLS_LABEL_DPO_FLAG_NONE));
}
-VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_node) = {
- .function = ethernet_mpls_label_imposition,
- .name = "ethernet-mpls-label-imposition",
+VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
+ .function = ethernet_mpls_label_imposition_pipe,
+ .name = "ethernet-mpls-label-imposition-pipe",
.vector_size = sizeof (u32),
.format_trace = format_mpls_label_imposition_trace,
@@ -659,8 +995,205 @@ VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_node) = {
[0] = "error-drop",
}
};
-VLIB_NODE_FUNCTION_MULTIARCH (ethernet_mpls_label_imposition_node,
- ethernet_mpls_label_imposition)
+
+VLIB_NODE_FUNCTION_MULTIARCH (ethernet_mpls_label_imposition_pipe_node,
+ ethernet_mpls_label_imposition_pipe)
+
+static uword
+mpls_mpls_label_imposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_MPLS,
+ MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
+}
+
+VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
+ .function = mpls_mpls_label_imposition_uniform,
+ .name = "mpls-label-imposition-uniform",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "mpls-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (mpls_mpls_label_imposition_uniform_node,
+ mpls_mpls_label_imposition_uniform)
+
+static uword
+ip4_mpls_label_imposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP4,
+ MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
+}
+
+VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
+ .function = ip4_mpls_label_imposition_uniform,
+ .name = "ip4-mpls-label-imposition-uniform",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip4-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_uniform_node,
+ ip4_mpls_label_imposition_uniform)
+
+static uword
+ip6_mpls_label_imposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP6,
+ MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
+}
+
+VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
+ .function = ip6_mpls_label_imposition_uniform,
+ .name = "ip6-mpls-label-imposition-uniform",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip6-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_uniform_node,
+ ip6_mpls_label_imposition_uniform)
+
+static uword
+ethernet_mpls_label_imposition_uniform (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_ETHERNET,
+ MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
+}
+
+VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
+ .function = ethernet_mpls_label_imposition_uniform,
+ .name = "ethernet-mpls-label-imposition-uniform",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "error-drop",
+ }
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (ethernet_mpls_label_imposition_uniform_node,
+ ethernet_mpls_label_imposition_uniform)
+
+static uword
+ip4_mpls_label_imposition_pipe_no_ip_ttl_decr (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP4,
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
+}
+
+VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
+ .function = ip4_mpls_label_imposition_pipe_no_ip_ttl_decr,
+ .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip4-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node,
+ ip4_mpls_label_imposition_pipe_no_ip_ttl_decr)
+
+static uword
+ip6_mpls_label_imposition_pipe_no_ip_ttl_decr (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP6,
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
+}
+
+VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
+ .function = ip6_mpls_label_imposition_pipe_no_ip_ttl_decr,
+ .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip6-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node,
+ ip6_mpls_label_imposition_pipe_no_ip_ttl_decr)
+
+static uword
+ip4_mpls_label_imposition_uniform_no_ip_ttl_decr (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP4,
+ (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
+}
+
+VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
+ .function = ip4_mpls_label_imposition_uniform_no_ip_ttl_decr,
+ .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip4-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node,
+ ip4_mpls_label_imposition_uniform_no_ip_ttl_decr)
+
+static uword
+ip6_mpls_label_imposition_uniform_no_ip_ttl_decr (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (mpls_label_imposition_inline(vm, node, frame,
+ DPO_PROTO_IP6,
+ (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
+}
+
+VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
+ .function = ip6_mpls_label_imposition_uniform_no_ip_ttl_decr,
+ .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_mpls_label_imposition_trace,
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "ip6-drop",
+ }
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node,
+ ip6_mpls_label_imposition_uniform_no_ip_ttl_decr)
+
static void
mpls_label_dpo_mem_show (void)
@@ -678,38 +1211,118 @@ const static dpo_vft_t mld_vft = {
.dv_mem_show = mpls_label_dpo_mem_show,
};
-const static char* const mpls_label_imp_ip4_nodes[] =
+const static char* const mpls_label_imp_pipe_ip4_nodes[] =
{
- "ip4-mpls-label-imposition",
+ "ip4-mpls-label-imposition-pipe",
NULL,
};
-const static char* const mpls_label_imp_ip6_nodes[] =
+const static char* const mpls_label_imp_pipe_ip6_nodes[] =
{
- "ip6-mpls-label-imposition",
+ "ip6-mpls-label-imposition-pipe",
NULL,
};
-const static char* const mpls_label_imp_mpls_nodes[] =
+const static char* const mpls_label_imp_pipe_mpls_nodes[] =
{
- "mpls-label-imposition",
+ "mpls-label-imposition-pipe",
NULL,
};
-const static char* const mpls_label_imp_ethernet_nodes[] =
+const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
{
- "ethernet-mpls-label-imposition",
+ "ethernet-mpls-label-imposition-pipe",
NULL,
};
-const static char* const * const mpls_label_imp_nodes[DPO_PROTO_NUM] =
+const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
{
- [DPO_PROTO_IP4] = mpls_label_imp_ip4_nodes,
- [DPO_PROTO_IP6] = mpls_label_imp_ip6_nodes,
- [DPO_PROTO_MPLS] = mpls_label_imp_mpls_nodes,
- [DPO_PROTO_ETHERNET] = mpls_label_imp_ethernet_nodes,
+ [DPO_PROTO_IP4] = mpls_label_imp_pipe_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_imp_pipe_ip6_nodes,
+ [DPO_PROTO_MPLS] = mpls_label_imp_pipe_mpls_nodes,
+ [DPO_PROTO_ETHERNET] = mpls_label_imp_pipe_ethernet_nodes,
};
+const static char* const mpls_label_imp_uniform_ip4_nodes[] =
+{
+ "ip4-mpls-label-imposition-uniform",
+ NULL,
+};
+const static char* const mpls_label_imp_uniform_ip6_nodes[] =
+{
+ "ip6-mpls-label-imposition-uniform",
+ NULL,
+};
+const static char* const mpls_label_imp_uniform_mpls_nodes[] =
+{
+ "mpls-label-imposition-uniform",
+ NULL,
+};
+const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
+{
+ "ethernet-mpls-label-imposition-uniform",
+ NULL,
+};
+
+const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = mpls_label_imp_uniform_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_imp_uniform_ip6_nodes,
+ [DPO_PROTO_MPLS] = mpls_label_imp_uniform_mpls_nodes,
+ [DPO_PROTO_ETHERNET] = mpls_label_imp_uniform_ethernet_nodes,
+};
+
+const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[] =
+{
+ "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
+ NULL,
+};
+const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[] =
+{
+ "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
+ NULL,
+};
+
+const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes,
+};
+
+const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[] =
+{
+ "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
+ NULL,
+};
+const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[] =
+{
+ "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
+ NULL,
+};
+
+const static char* const * const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes,
+ [DPO_PROTO_IP6] = mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes,
+};
void
mpls_label_dpo_module_init (void)
{
- dpo_register(DPO_MPLS_LABEL, &mld_vft, mpls_label_imp_nodes);
+ mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE] =
+ dpo_register_new_type(&mld_vft,
+ mpls_label_imp_pipe_nodes);
+ mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
+ dpo_register_new_type(&mld_vft,
+ mpls_label_imp_pipe_no_ip_tll_decr_nodes);
+ mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE] =
+ dpo_register_new_type(&mld_vft,
+ mpls_label_imp_uniform_nodes);
+ mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
+ dpo_register_new_type(&mld_vft,
+ mpls_label_imp_uniform_no_ip_tll_decr_nodes);
+}
+
+dpo_type_t
+mpls_label_dpo_get_type (mpls_label_dpo_flags_t flags)
+{
+ return (mpls_label_dpo_types[flags]);
}
diff --git a/src/vnet/dpo/mpls_label_dpo.h b/src/vnet/dpo/mpls_label_dpo.h
index 8494d26b495..98c88f7d812 100644
--- a/src/vnet/dpo/mpls_label_dpo.h
+++ b/src/vnet/dpo/mpls_label_dpo.h
@@ -20,11 +20,47 @@
#include <vnet/mpls/packet.h>
#include <vnet/dpo/dpo.h>
+/**
+ * Flags present on an MPLS label sourced path-extension
+ */
+typedef enum mpls_label_dpo_attr_t_
+{
+ /**
+ * Do not decrement the TTL of IP packet during imposition
+ */
+ MPLS_LABEL_DPO_ATTR_NO_IP_TTL_DECR,
+ MPLS_LABEL_DPO_ATTR_UNIFORM_MODE,
+} mpls_label_dpo_attr_t;
+
+#define MPLS_LABEL_DPO_ATTR_MAX (MPLS_LABEL_DPO_ATTR_UNIFORM_MODE+1)
+
+typedef enum mpls_label_dpo_flags_t_
+{
+ MPLS_LABEL_DPO_FLAG_NONE = 0,
+ MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR = (1 << MPLS_LABEL_DPO_ATTR_NO_IP_TTL_DECR),
+ MPLS_LABEL_DPO_FLAG_UNIFORM_MODE = (1 << MPLS_LABEL_DPO_ATTR_UNIFORM_MODE),
+} __attribute__ ((packed)) mpls_label_dpo_flags_t;
+
+#define MPLS_LABEL_DPO_ATTR_NAMES { \
+ [MPLS_LABEL_DPO_ATTR_NO_IP_TTL_DECR] = "no-ip-tll-decr", \
+ [MPLS_LABEL_DPO_ATTR_UNIFORM_MODE] = "uniform-mode", \
+}
+
+#define FOR_EACH_MPLS_LABEL_DPO_ATTR(_item) \
+ for (_item = MPLS_LABEL_DPO_ATTR_NO_IP_TTL_DECR; \
+ _item <= MPLS_LABEL_DPO_ATTR_UNIFORM_MODE; \
+ _item++)
+
+/**
+ * Format the flags variable
+ */
+extern u8* format_mpls_label_dpo_flags(u8 *s, va_list *args);
/**
* Maximum number of labels in one DPO
*/
#define MPLS_LABEL_DPO_MAX_N_LABELS 12
+
/**
* A representation of an MPLS label for imposition in the data-path
*/
@@ -47,9 +83,14 @@ typedef struct mpls_label_dpo_t
dpo_proto_t mld_payload_proto;
/**
+ * Flags
+ */
+ mpls_label_dpo_flags_t mld_flags;
+
+ /**
* Size of the label stack
*/
- u16 mld_n_labels;
+ u8 mld_n_labels;
/**
* Cached amount of header bytes to paint
@@ -75,18 +116,17 @@ STATIC_ASSERT((sizeof(mpls_label_dpo_t) <= CLIB_CACHE_LINE_BYTES),
*
* @param label_stack The stack if labels to impose, outer most label first
* @param eos The inner most label's EOS bit
- * @param ttl The inner most label's TTL bit
- * @param exp The inner most label's EXP bit
* @param payload_proto The ptocool of the payload packets that will
* be imposed with this label header.
- * @param dpo The parent of the created MPLS label object
+ * @param parent The parent of the created MPLS label object
+ * @param dpo The MPLS label DPO created
*/
-extern index_t mpls_label_dpo_create(mpls_label_t *label_stack,
- mpls_eos_bit_t eos,
- u8 ttl,
- u8 exp,
- dpo_proto_t payload_proto,
- const dpo_id_t *dpo);
+extern void mpls_label_dpo_create(fib_mpls_label_t *label_stack,
+ mpls_eos_bit_t eos,
+ dpo_proto_t payload_proto,
+ mpls_label_dpo_flags_t flags,
+ const dpo_id_t *paremt,
+ dpo_id_t *dpo);
extern u8* format_mpls_label_dpo(u8 *s, va_list *args);
@@ -104,4 +144,9 @@ mpls_label_dpo_get (index_t index)
extern void mpls_label_dpo_module_init(void);
+/*
+ * test function to get the registered DPO type for the flags
+ */
+extern dpo_type_t mpls_label_dpo_get_type(mpls_label_dpo_flags_t flags);
+
#endif