summaryrefslogtreecommitdiffstats
path: root/vnet/vnet/fib/fib_path_ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/fib/fib_path_ext.c')
-rw-r--r--vnet/vnet/fib/fib_path_ext.c103
1 files changed, 75 insertions, 28 deletions
diff --git a/vnet/vnet/fib/fib_path_ext.c b/vnet/vnet/fib/fib_path_ext.c
index 6603b64f02f..f75b5626c04 100644
--- a/vnet/vnet/fib/fib_path_ext.c
+++ b/vnet/vnet/fib/fib_path_ext.c
@@ -18,23 +18,28 @@
#include <vnet/dpo/load_balance.h>
#include <vnet/dpo/drop_dpo.h>
-#include "fib_path_ext.h"
-#include "fib_path.h"
-#include "fib_path_list.h"
-#include "fib_internal.h"
+#include <vnet/fib/fib_path_ext.h>
+#include <vnet/fib/fib_entry_src.h>
+#include <vnet/fib/fib_path.h>
+#include <vnet/fib/fib_path_list.h>
+#include <vnet/fib/fib_internal.h>
u8 *
format_fib_path_ext (u8 * s, va_list * args)
{
fib_path_ext_t *path_ext;
+ u32 ii;
path_ext = va_arg (*args, fib_path_ext_t *);
- s = format(s, "path:%d label:%U",
- path_ext->fpe_path_index,
- format_mpls_unicast_label,
- path_ext->fpe_path.frp_label);
-
+ s = format(s, "path:%d labels:",
+ path_ext->fpe_path_index);
+ for (ii = 0; ii < vec_len(path_ext->fpe_path.frp_label_stack); ii++)
+ {
+ s = format(s, "%U ",
+ format_mpls_unicast_label,
+ path_ext->fpe_path.frp_label_stack[ii]);
+ }
return (s);
}
@@ -86,12 +91,23 @@ fib_path_ext_init (fib_path_ext_t *path_ext,
fib_path_ext_resolve(path_ext, path_list_index);
}
+/**
+ * @brief Return true if the label stack is implicit null
+ */
+static int
+fib_path_ext_is_imp_null (fib_path_ext_t *path_ext)
+{
+ return ((1 == vec_len(path_ext->fpe_label_stack)) &&
+ (MPLS_IETF_IMPLICIT_NULL_LABEL == path_ext->fpe_label_stack[0]));
+}
+
load_balance_path_t *
fib_path_ext_stack (fib_path_ext_t *path_ext,
- fib_forward_chain_type_t parent_fct,
+ const fib_entry_t *entry,
+ fib_forward_chain_type_t child_fct,
load_balance_path_t *nhs)
{
- fib_forward_chain_type_t child_fct;
+ fib_forward_chain_type_t parent_fct;
load_balance_path_t *nh;
if (!fib_path_is_resolved(path_ext->fpe_path_index))
@@ -102,33 +118,50 @@ fib_path_ext_stack (fib_path_ext_t *path_ext,
* label. From the chain type request by the child, determine what
* chain type we will request from the parent.
*/
- switch (parent_fct)
+ switch (child_fct)
{
case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
- ASSERT(0);
- return (nhs);
+ {
+ /*
+ * The EOS chain is a tricky since, when the path has an imp NULL one cannot know
+ * the adjacency to link to without knowing what the packets payload protocol
+ * will be once the label is popped.
+ */
+ if (fib_path_ext_is_imp_null(path_ext))
+ {
+ parent_fct = fib_entry_chain_type_fixup(entry, child_fct);
+ }
+ else
+ {
+ /*
+ * we have a label to stack. packets will thus be labelled when
+ * they encounter the child, ergo, non-eos.
+ */
+ parent_fct = FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS;
+ }
break;
+ }
case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
- if (MPLS_IETF_IMPLICIT_NULL_LABEL == path_ext->fpe_label)
+ if (fib_path_ext_is_imp_null(path_ext))
{
/*
* implicit-null label for the eos or IP chain, need to pick up
* the IP adj
*/
- child_fct = parent_fct;
+ parent_fct = child_fct;
}
else
{
/*
* we have a label to stack. packets will thus be labelled when
- * they encounter th child, ergo, non-eos.
+ * they encounter the child, ergo, non-eos.
*/
- child_fct = FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS;
+ parent_fct = FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS;
}
break;
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
- child_fct = parent_fct;
+ parent_fct = child_fct;
break;
default:
return (nhs);
@@ -143,7 +176,7 @@ fib_path_ext_stack (fib_path_ext_t *path_ext,
* are to be sent. We stack the MPLS Label DPO on this path DPO
*/
fib_path_contribute_forwarding(path_ext->fpe_path_index,
- child_fct,
+ parent_fct,
&via_dpo);
if (dpo_is_drop(&via_dpo) ||
@@ -165,17 +198,31 @@ fib_path_ext_stack (fib_path_ext_t *path_ext,
* The label is stackable for this chain type
* construct the mpls header that will be imposed in the data-path
*/
- if (MPLS_IETF_IMPLICIT_NULL_LABEL != path_ext->fpe_label)
+ if (!fib_path_ext_is_imp_null(path_ext))
{
+ /*
+ * we use the parent protocol for the label so that
+ * we pickup the correct MPLS imposition nodes to do
+ * ip[46] processing.
+ */
+ dpo_proto_t chain_proto;
+ mpls_eos_bit_t eos;
+ index_t mldi;
+
+ eos = (child_fct == FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS ?
+ MPLS_NON_EOS :
+ MPLS_EOS);
+ chain_proto = fib_forw_chain_type_to_dpo_proto(child_fct);
+
+ mldi = mpls_label_dpo_create(path_ext->fpe_label_stack,
+ eos, 255, 0,
+ chain_proto,
+ &nh->path_dpo);
+
dpo_set(&nh->path_dpo,
DPO_MPLS_LABEL,
- DPO_PROTO_MPLS,
- mpls_label_dpo_create(path_ext->fpe_label,
- (parent_fct == FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS ?
- MPLS_NON_EOS :
- MPLS_EOS),
- 255, 0,
- &nh->path_dpo));
+ chain_proto,
+ mldi);
}
}
dpo_reset(&via_dpo);