aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo/mpls_label_dpo.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_label_dpo.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_label_dpo.c')
-rw-r--r--src/vnet/dpo/mpls_label_dpo.c1075
1 files changed, 844 insertions, 231 deletions
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]);
}