aboutsummaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/adj/adj_midchain.c3
-rw-r--r--vnet/vnet/fib/fib_entry_src_mpls.c13
-rw-r--r--vnet/vnet/fib/fib_node.h2
-rw-r--r--vnet/vnet/fib/fib_table.c19
-rw-r--r--vnet/vnet/fib/fib_test.c51
-rw-r--r--vnet/vnet/mpls/interface.c943
-rw-r--r--vnet/vnet/mpls/mpls.c330
-rw-r--r--vnet/vnet/mpls/mpls.h96
-rw-r--r--vnet/vnet/mpls/mpls_lookup.c6
-rw-r--r--vnet/vnet/mpls/mpls_output.c1
-rw-r--r--vnet/vnet/mpls/node.c2
-rw-r--r--vnet/vnet/mpls/pg.c2
-rw-r--r--vnet/vnet/mpls/policy_encap.c1
13 files changed, 110 insertions, 1359 deletions
diff --git a/vnet/vnet/adj/adj_midchain.c b/vnet/vnet/adj/adj_midchain.c
index 2fbedae2..9f6c8e47 100644
--- a/vnet/vnet/adj/adj_midchain.c
+++ b/vnet/vnet/adj/adj_midchain.c
@@ -116,9 +116,6 @@ adj_mdichain_tx_inline (vlib_main_t * vm,
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- vlib_node_increment_counter (vm, gre_input_node.index,
- GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
return frame->n_vectors;
}
diff --git a/vnet/vnet/fib/fib_entry_src_mpls.c b/vnet/vnet/fib/fib_entry_src_mpls.c
index 4f4a023f..4079d8fc 100644
--- a/vnet/vnet/fib/fib_entry_src_mpls.c
+++ b/vnet/vnet/fib/fib_entry_src_mpls.c
@@ -118,6 +118,19 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
else
{
fib_index = mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID);
+
+ /*
+ * if this is a change in label, reomve the old one first
+ */
+ if (src->mpls.fesm_label != label)
+ {
+ FOR_EACH_MPLS_EOS_BIT(eos)
+ {
+ ASSERT(FIB_NODE_INDEX_INVALID != src->mpls.fesm_lfes[eos]);
+ fib_table_entry_delete_index(src->mpls.fesm_lfes[eos],
+ FIB_SOURCE_SPECIAL);
+ }
+ }
}
src->mpls.fesm_label = label;
diff --git a/vnet/vnet/fib/fib_node.h b/vnet/vnet/fib/fib_node.h
index 2f9a107a..253c42dd 100644
--- a/vnet/vnet/fib/fib_node.h
+++ b/vnet/vnet/fib/fib_node.h
@@ -37,7 +37,6 @@ typedef enum fib_node_type_t_ {
FIB_NODE_TYPE_MPLS_ENTRY,
FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY,
FIB_NODE_TYPE_LISP_ADJ,
- FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
FIB_NODE_TYPE_GRE_TUNNEL,
/**
* Marker. New types before this one. leave the test last.
@@ -57,7 +56,6 @@ typedef enum fib_node_type_t_ {
[FIB_NODE_TYPE_ADJ] = "adj", \
[FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY] = "lisp-gpe-fwd-entry", \
[FIB_NODE_TYPE_LISP_ADJ] = "lisp-adj", \
- [FIB_NODE_TYPE_MPLS_GRE_TUNNEL] = "mpls-gre-tunnel", \
[FIB_NODE_TYPE_GRE_TUNNEL] = "gre-tunnel", \
}
diff --git a/vnet/vnet/fib/fib_table.c b/vnet/vnet/fib/fib_table.c
index 84c87088..d293d815 100644
--- a/vnet/vnet/fib/fib_table.c
+++ b/vnet/vnet/fib/fib_table.c
@@ -805,10 +805,21 @@ fib_table_entry_local_label_add (u32 fib_index,
{
fib_node_index_t fib_entry_index;
- fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
- FIB_SOURCE_MPLS,
- FIB_ENTRY_FLAG_NONE,
- NULL);
+ fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
+
+ if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
+ !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
+ {
+ /*
+ * only source the prefix once. this allows the label change
+ * operation to work
+ */
+ fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
+ FIB_SOURCE_MPLS,
+ FIB_ENTRY_FLAG_NONE,
+ NULL);
+ }
+
fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
return (fib_entry_index);
diff --git a/vnet/vnet/fib/fib_test.c b/vnet/vnet/fib/fib_test.c
index 1e459cf1..bdd6e95f 100644
--- a/vnet/vnet/fib/fib_test.c
+++ b/vnet/vnet/fib/fib_test.c
@@ -5558,11 +5558,58 @@ fib_test_label (void)
"label 99 over 10.10.10.1");
/*
- * remove the local label
+ * change the local label
+ */
+ fib_table_entry_local_label_add(fib_index,
+ &pfx_1_1_1_1_s_32,
+ 25005);
+
+ fib_prefix_t pfx_25005_eos = {
+ .fp_proto = FIB_PROTOCOL_MPLS,
+ .fp_label = 25005,
+ .fp_eos = MPLS_EOS,
+ };
+ fib_prefix_t pfx_25005_neos = {
+ .fp_proto = FIB_PROTOCOL_MPLS,
+ .fp_label = 25005,
+ .fp_eos = MPLS_NON_EOS,
+ };
+
+ FIB_TEST((FIB_NODE_INDEX_INVALID ==
+ fib_table_lookup(fib_index, &pfx_24001_eos)),
+ "24001/eos removed after label change");
+ FIB_TEST((FIB_NODE_INDEX_INVALID ==
+ fib_table_lookup(fib_index, &pfx_24001_neos)),
+ "24001/eos removed after label change");
+
+ fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
+ &pfx_25005_eos);
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ 2,
+ &l99_eos_o_10_10_10_1,
+ &adj_o_10_10_11_2),
+ "25005/eos LB 2 buckets via: "
+ "label 99 over 10.10.10.1, "
+ "adj over 10.10.11.2");
+
+ fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
+ &pfx_25005_neos);
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
+ 1,
+ &l99_neos_o_10_10_10_1),
+ "25005/neos LB 1 buckets via: "
+ "label 99 over 10.10.10.1");
+
+ /*
+ * remove the local label.
+ * the check that the MPLS entries are gone is done by the fact the
+ * MPLS table is no longer present.
*/
fib_table_entry_local_label_remove(fib_index,
&pfx_1_1_1_1_s_32,
- 24001);
+ 25005);
fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
FIB_TEST(fib_test_validate_entry(fei,
diff --git a/vnet/vnet/mpls/interface.c b/vnet/vnet/mpls/interface.c
index 0baf2d3b..fc297cd1 100644
--- a/vnet/vnet/mpls/interface.c
+++ b/vnet/vnet/mpls/interface.c
@@ -17,249 +17,12 @@
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
-#include <vnet/gre/gre.h>
#include <vnet/mpls/mpls.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/adj/adj_midchain.h>
#include <vnet/dpo/classify_dpo.h>
/* manually added to the interface output node */
-#define MPLS_GRE_OUTPUT_NEXT_POST_REWRITE 1
-
-static uword
-mpls_gre_interface_tx (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- mpls_main_t * gm = &mpls_main;
- vnet_main_t * vnm = gm->vnet_main;
- u32 next_index;
- u32 * from, * to_next, n_left_from, n_left_to_next;
-
- /* Vector of buffer / pkt indices we're supposed to process */
- from = vlib_frame_vector_args (frame);
-
- /* Number of buffers / pkts */
- n_left_from = frame->n_vectors;
-
- /* Speculatively send the first buffer to the last disposition we used */
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- /* set up to enqueue to our disposition with index = next_index */
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- /*
- * As long as we have enough pkts left to process two pkts
- * and prefetch two pkts...
- */
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- vlib_buffer_t * b0, * b1;
- u32 bi0, next0, bi1, next1;
- mpls_gre_tunnel_t * t0, * t1;
- u32 sw_if_index0, sw_if_index1;
- vnet_hw_interface_t * hi0, * hi1;
- u8 * dst0, * dst1;
-
- /* Prefetch the next iteration */
- {
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- /*
- * Prefetch packet data. We expect to overwrite
- * the inbound L2 header with an ip header and a
- * gre header. Might want to prefetch the last line
- * of rewrite space as well; need profile data
- */
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
-
- /* Pick up the next two buffer indices */
- bi0 = from[0];
- bi1 = from[1];
-
- /* Speculatively enqueue them where we sent the last buffer */
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_to_next -= 2;
- n_left_from -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
- sw_if_index1 = vnet_buffer(b1)->sw_if_index [VLIB_TX];
-
- /* get h/w intfcs */
- hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
- hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1);
-
- /* hw_instance = tunnel pool index */
- t0 = pool_elt_at_index (gm->gre_tunnels, hi0->hw_instance);
- t1 = pool_elt_at_index (gm->gre_tunnels, hi1->hw_instance);
-
- /* Apply rewrite - $$$$$ fixme don't use memcpy */
- vlib_buffer_advance (b0, -(word)vec_len(t0->rewrite_data));
- vlib_buffer_advance (b1, -(word)vec_len(t1->rewrite_data));
-
- dst0 = vlib_buffer_get_current (b0);
- dst1 = vlib_buffer_get_current (b1);
-
- clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
- clib_memcpy (dst1, t1->rewrite_data, vec_len(t1->rewrite_data));
-
- /* Fix TX fib indices */
- vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->outer_fib_index;
- vnet_buffer(b1)->sw_if_index [VLIB_TX] = t1->outer_fib_index;
-
- /* mpls-post-rewrite takes it from here... */
- next0 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
- next1 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->tunnel_id = t0 - gm->gre_tunnels;
- tr->length = b0->current_length;
- tr->src.as_u32 = t0->tunnel_src.as_u32;
- tr->dst.as_u32 = t0->tunnel_dst.as_u32;
- tr->lookup_miss = 0;
- tr->mpls_encap_index = t0->encap_index;
- }
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node,
- b1, sizeof (*tr));
- tr->tunnel_id = t1 - gm->gre_tunnels;
- tr->length = b1->current_length;
- tr->src.as_u32 = t1->tunnel_src.as_u32;
- tr->dst.as_u32 = t1->tunnel_dst.as_u32;
- tr->lookup_miss = 0;
- tr->mpls_encap_index = t1->encap_index;
- }
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t * b0;
- u32 bi0, next0;
- mpls_gre_tunnel_t * t0;
- u32 sw_if_index0;
- vnet_hw_interface_t * hi0;
- u8 * dst0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
-
- hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
-
- t0 = pool_elt_at_index (gm->gre_tunnels, hi0->hw_instance);
-
- /* Apply rewrite - $$$$$ fixme don't use memcpy */
- vlib_buffer_advance (b0, -(word)vec_len(t0->rewrite_data));
-
- dst0 = vlib_buffer_get_current (b0);
-
- clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
-
- /* Fix the TX fib index */
- vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->outer_fib_index;
-
- /* mpls-post-rewrite takes it from here... */
- next0 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->tunnel_id = t0 - gm->gre_tunnels;
- tr->length = b0->current_length;
- tr->src.as_u32 = t0->tunnel_src.as_u32;
- tr->dst.as_u32 = t0->tunnel_dst.as_u32;
- tr->lookup_miss = 0;
- tr->mpls_encap_index = t0->encap_index;
- }
-
- 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_node_increment_counter (vm, gre_input_node.index,
- GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
- return frame->n_vectors;
-}
-
-static u8 * format_mpls_gre_tunnel_name (u8 * s, va_list * args)
-{
- u32 dev_instance = va_arg (*args, u32);
- return format (s, "mpls-gre%d", dev_instance);
-}
-
-static u8 * format_mpls_gre_device (u8 * s, va_list * args)
-{
- u32 dev_instance = va_arg (*args, u32);
- CLIB_UNUSED (int verbose) = va_arg (*args, int);
-
- s = format (s, "MPLS-GRE tunnel: id %d\n", dev_instance);
- return s;
-}
-
-VNET_DEVICE_CLASS (mpls_gre_device_class) = {
- .name = "MPLS-GRE tunnel device",
- .format_device_name = format_mpls_gre_tunnel_name,
- .format_device = format_mpls_gre_device,
- .format_tx_trace = format_mpls_gre_tx_trace,
- .tx_function = mpls_gre_interface_tx,
- .no_flatten_output_chains = 1,
-#ifdef SOON
- .clear counter = 0;
- .admin_up_down_function = 0;
-#endif
-};
-
-VLIB_DEVICE_TX_FUNCTION_MULTIARCH (mpls_gre_device_class,
- mpls_gre_interface_tx)
-
-VNET_HW_INTERFACE_CLASS (mpls_gre_hw_interface_class) = {
- .name = "MPLS-GRE",
- .format_header = format_mpls_gre_header_with_length,
-#if 0
- .unformat_header = unformat_mpls_gre_header,
-#endif
- .build_rewrite = default_build_rewrite,
- .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
-};
-
-/* manually added to the interface output node */
#define MPLS_ETH_OUTPUT_NEXT_OUTPUT 1
static uword
@@ -497,63 +260,6 @@ VNET_HW_INTERFACE_CLASS (mpls_eth_hw_interface_class) = {
.flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
};
-static void
-mpls_gre_fixup (vlib_main_t *vm,
- ip_adjacency_t *adj,
- vlib_buffer_t * b0)
-{
- ip4_header_t * ip0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- /* Fixup the checksum and len fields in the GRE tunnel encap
- * that was applied at the midchain node */
- ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
- ip0->checksum = ip4_header_checksum (ip0);
-}
-
-static u8 * mpls_gre_rewrite (mpls_main_t *mm, mpls_gre_tunnel_t * t)
-{
- ip4_header_t * ip0;
- ip4_gre_and_mpls_header_t * h0;
- u8 * rewrite_data = 0;
- mpls_encap_t * e;
- mpls_unicast_header_t *lp0;
- int i;
-
- /* look up the encap label stack using the RX FIB */
- e = mpls_encap_by_fib_and_dest (mm, t->inner_fib_index, t->tunnel_dst.as_u32);
-
- if (e == 0)
- {
- clib_warning ("no label for inner fib index %d, dst %U",
- t->inner_fib_index, format_ip4_address,
- &t->tunnel_dst);
- return 0;
- }
-
- vec_validate (rewrite_data, sizeof (*h0)
- + sizeof (mpls_unicast_header_t) * vec_len(e->labels) -1);
- memset (rewrite_data, 0, sizeof (*h0));
-
- h0 = (ip4_gre_and_mpls_header_t *) rewrite_data;
- /* Copy the encap label stack */
- lp0 = h0->labels;
- for (i = 0; i < vec_len(e->labels); i++)
- lp0[i] = e->labels[i];
- ip0 = &h0->ip4;
- h0->gre.protocol = clib_host_to_net_u16(GRE_PROTOCOL_mpls_unicast);
- ip0->ip_version_and_header_length = 0x45;
- ip0->ttl = 254;
- ip0->protocol = IP_PROTOCOL_GRE;
- /* $$$ fixup ip4 header length and checksum after-the-fact */
- ip0->src_address.as_u32 = t->tunnel_src.as_u32;
- ip0->dst_address.as_u32 = t->tunnel_dst.as_u32;
- ip0->checksum = ip4_header_checksum (ip0);
-
- return (rewrite_data);
-}
-
u8
mpls_sw_interface_is_enabled (u32 sw_if_index)
{
@@ -622,606 +328,6 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
cm->config_index_by_sw_if_index[sw_if_index] = ci;
}
-static mpls_gre_tunnel_t *
-mpls_gre_tunnel_from_fib_node (fib_node_t *node)
-{
-#if (CLIB_DEBUG > 0)
- ASSERT(FIB_NODE_TYPE_MPLS_GRE_TUNNEL == node->fn_type);
-#endif
- return ((mpls_gre_tunnel_t*)node);
-}
-
-/*
- * mpls_gre_tunnel_stack
- *
- * 'stack' (resolve the recursion for) the tunnel's midchain adjacency
- */
-static void
-mpls_gre_tunnel_stack (mpls_gre_tunnel_t *mgt)
-{
- /*
- * find the adjacency that is contributed by the FIB entry
- * that this tunnel resovles via, and use it as the next adj
- * in the midchain
- */
- adj_nbr_midchain_stack(mgt->adj_index,
- fib_entry_contribute_ip_forwarding(mgt->fei));
-}
-
-/**
- * Function definition to backwalk a FIB node
- */
-static fib_node_back_walk_rc_t
-mpls_gre_tunnel_back_walk (fib_node_t *node,
- fib_node_back_walk_ctx_t *ctx)
-{
- mpls_gre_tunnel_stack(mpls_gre_tunnel_from_fib_node(node));
-
- return (FIB_NODE_BACK_WALK_CONTINUE);
-}
-
-/**
- * Function definition to get a FIB node from its index
- */
-static fib_node_t*
-mpls_gre_tunnel_fib_node_get (fib_node_index_t index)
-{
- mpls_gre_tunnel_t * mgt;
- mpls_main_t * mm;
-
- mm = &mpls_main;
- mgt = pool_elt_at_index(mm->gre_tunnels, index);
-
- return (&mgt->mgt_node);
-}
-
-/**
- * Function definition to inform the FIB node that its last lock has gone.
- */
-static void
-mpls_gre_tunnel_last_lock_gone (fib_node_t *node)
-{
- /*
- * The MPLS GRE tunnel is a root of the graph. As such
- * it never has children and thus is never locked.
- */
- ASSERT(0);
-}
-
-/*
- * Virtual function table registered by MPLS GRE tunnels
- * for participation in the FIB object graph.
- */
-const static fib_node_vft_t mpls_gre_vft = {
- .fnv_get = mpls_gre_tunnel_fib_node_get,
- .fnv_last_lock = mpls_gre_tunnel_last_lock_gone,
- .fnv_back_walk = mpls_gre_tunnel_back_walk,
-};
-
-static mpls_gre_tunnel_t *
-mpls_gre_tunnel_find (ip4_address_t *src,
- ip4_address_t *dst,
- ip4_address_t *intfc,
- u32 inner_fib_index)
-{
- mpls_main_t * mm = &mpls_main;
- mpls_gre_tunnel_t *tp;
- int found_tunnel = 0;
-
- /* suppress duplicate mpls interface generation. */
- pool_foreach (tp, mm->gre_tunnels,
- ({
- /*
- * If we have a tunnel which matches (src, dst, intfc/mask)
- * AND the expected route is in the FIB, it's a dup
- */
- if (!memcmp (&tp->tunnel_src, src, sizeof (*src))
- && !memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
- && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
- && tp->inner_fib_index == inner_fib_index)
- {
- found_tunnel = 1;
- goto found;
- }
- }));
-
-found:
- if (found_tunnel)
- {
- return (tp);
- }
- return (NULL);
-}
-
-int mpls_gre_tunnel_add (ip4_address_t *src,
- ip4_address_t *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_index,
- u32 outer_fib_index,
- u32 * tunnel_sw_if_index,
- u8 l2_only)
-{
- mpls_main_t * mm = &mpls_main;
- gre_main_t * gm = &gre_main;
- vnet_main_t * vnm = vnet_get_main();
- mpls_gre_tunnel_t *tp;
- ip_adjacency_t adj;
- u8 * rewrite_data;
- mpls_encap_t * e = 0;
- u32 hw_if_index = ~0;
- vnet_hw_interface_t * hi;
- u32 slot;
- const ip46_address_t zero_nh = {
- .ip4.as_u32 = 0,
- };
-
- tp = mpls_gre_tunnel_find(src,dst,intfc,inner_fib_index);
-
- /* Add, duplicate */
- if (NULL != tp)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- e = mpls_encap_by_fib_and_dest (mm, inner_fib_index, dst->as_u32);
- if (e == 0)
- return VNET_API_ERROR_NO_SUCH_LABEL;
-
- pool_get(mm->gre_tunnels, tp);
- memset (tp, 0, sizeof (*tp));
- fib_node_init(&tp->mgt_node,
- FIB_NODE_TYPE_MPLS_GRE_TUNNEL);
-
- if (vec_len (mm->free_gre_sw_if_indices) > 0)
- {
- hw_if_index =
- mm->free_gre_sw_if_indices[vec_len(mm->free_gre_sw_if_indices)-1];
- _vec_len (mm->free_gre_sw_if_indices) -= 1;
- hi = vnet_get_hw_interface (vnm, hw_if_index);
- hi->dev_instance = tp - mm->gre_tunnels;
- hi->hw_instance = tp - mm->gre_tunnels;
- }
- else
- {
- hw_if_index = vnet_register_interface
- (vnm, mpls_gre_device_class.index, tp - mm->gre_tunnels,
- mpls_gre_hw_interface_class.index,
- tp - mm->gre_tunnels);
- hi = vnet_get_hw_interface (vnm, hw_if_index);
-
- /* ... to make the IP and L2 x-connect cases identical */
- slot = vlib_node_add_named_next_with_slot
- (vnm->vlib_main, hi->tx_node_index,
- "mpls-post-rewrite", MPLS_GRE_OUTPUT_NEXT_POST_REWRITE);
-
- ASSERT (slot == MPLS_GRE_OUTPUT_NEXT_POST_REWRITE);
- }
-
- *tunnel_sw_if_index = hi->sw_if_index;
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
- vec_validate(ip4_main.fib_index_by_sw_if_index, *tunnel_sw_if_index);
- ip4_main.fib_index_by_sw_if_index[*tunnel_sw_if_index] = outer_fib_index;
-
- tp->hw_if_index = hw_if_index;
-
- /* bind the MPLS and IPv4 FIBs to the interface and enable */
- vec_validate(mm->fib_index_by_sw_if_index, hi->sw_if_index);
- mm->fib_index_by_sw_if_index[hi->sw_if_index] = inner_fib_index;
- mpls_sw_interface_enable_disable(mm, hi->sw_if_index, 1);
- ip4_main.fib_index_by_sw_if_index[hi->sw_if_index] = inner_fib_index;
- ip4_sw_interface_enable_disable(hi->sw_if_index, 1);
-
- tp->tunnel_src.as_u32 = src->as_u32;
- tp->tunnel_dst.as_u32 = dst->as_u32;
- tp->intfc_address.as_u32 = intfc->as_u32;
- tp->mask_width = mask_width;
- tp->inner_fib_index = inner_fib_index;
- tp->outer_fib_index = outer_fib_index;
- tp->encap_index = e - mm->encaps;
- tp->l2_only = l2_only;
-
- /* Add the tunnel to the hash table of all GRE tunnels */
- u64 key = (u64)src->as_u32 << 32 | (u64)dst->as_u32;
-
- ASSERT(NULL == hash_get (gm->tunnel_by_key, key));
- hash_set (gm->tunnel_by_key, key, tp - mm->gre_tunnels);
-
- /* Create the adjacency and add to v4 fib */
- memset(&adj, 0, sizeof (adj));
- adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
-
- rewrite_data = mpls_gre_rewrite (mm, tp);
- if (rewrite_data == 0)
- {
- if (*tunnel_sw_if_index != ~0)
- {
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
- }
- pool_put (mm->gre_tunnels, tp);
- return VNET_API_ERROR_NO_SUCH_LABEL;
- }
-
- /* Save a copy of the rewrite data for L2 x-connect */
- vec_free (tp->rewrite_data);
-
- tp->rewrite_data = rewrite_data;
-
- if (!l2_only)
- {
- /*
- * source the FIB entry for the tunnel's destination
- * and become a child thereof. The tunnel will then get poked
- * when the forwarding for the entry updates, and the tunnel can
- * re-stack accordingly
- */
- const fib_prefix_t tun_dst_pfx = {
- .fp_len = 32,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = *dst,
- }
- };
-
- tp->fei = fib_table_entry_special_add(outer_fib_index,
- &tun_dst_pfx,
- FIB_SOURCE_RR,
- FIB_ENTRY_FLAG_NONE,
- ADJ_INDEX_INVALID);
- tp->sibling_index = fib_entry_child_add(tp->fei,
- FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
- tp - mm->gre_tunnels);
-
- /*
- * create and update the midchain adj this tunnel sources.
- * This is the adj the route we add below will resolve to.
- */
- tp->adj_index = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
- FIB_LINK_IP4,
- &zero_nh,
- hi->sw_if_index);
-
- adj_nbr_midchain_update_rewrite(tp->adj_index,
- mpls_gre_fixup,
- ADJ_MIDCHAIN_FLAG_NONE,
- rewrite_data);
- mpls_gre_tunnel_stack(tp);
-
- /*
- * Update the route for the tunnel's subnet to point through the tunnel
- */
- const fib_prefix_t tun_sub_net_pfx = {
- .fp_len = tp->mask_width,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = tp->intfc_address,
- },
- };
-
- fib_table_entry_update_one_path(inner_fib_index,
- &tun_sub_net_pfx,
- FIB_SOURCE_INTERFACE,
- (FIB_ENTRY_FLAG_CONNECTED |
- FIB_ENTRY_FLAG_ATTACHED),
- FIB_PROTOCOL_IP4,
- &zero_nh,
- hi->sw_if_index,
- ~0, // invalid fib index
- 1,
- MPLS_LABEL_INVALID,
- FIB_ROUTE_PATH_FLAG_NONE);
- }
-
- return 0;
-}
-
-static int
-mpls_gre_tunnel_del (ip4_address_t *src,
- ip4_address_t *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_index,
- u32 outer_fib_index,
- u32 * tunnel_sw_if_index,
- u8 l2_only)
-{
- mpls_main_t * mm = &mpls_main;
- vnet_main_t * vnm = vnet_get_main();
- gre_main_t * gm = &gre_main;
- mpls_gre_tunnel_t *tp;
- vnet_hw_interface_t * hi;
-
- tp = mpls_gre_tunnel_find(src,dst,intfc,inner_fib_index);
-
- /* Delete, and we can't find the tunnel */
- if (NULL == tp)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
-
- if (!l2_only)
- {
- /*
- * unsource the FIB entry for the tunnel's destination
- */
- const fib_prefix_t tun_dst_pfx = {
- .fp_len = 32,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = *dst,
- }
- };
-
- fib_entry_child_remove(tp->fei,
- tp->sibling_index);
- fib_table_entry_special_remove(outer_fib_index,
- &tun_dst_pfx,
- FIB_SOURCE_RR);
- tp->fei = FIB_NODE_INDEX_INVALID;
- adj_unlock(tp->adj_index);
-
- /*
- * unsource the route for the tunnel's subnet
- */
- const fib_prefix_t tun_sub_net_pfx = {
- .fp_len = tp->mask_width,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = tp->intfc_address,
- },
- };
-
- fib_table_entry_delete(inner_fib_index,
- &tun_sub_net_pfx,
- FIB_SOURCE_INTERFACE);
- }
-
- u64 key = ((u64)tp->tunnel_src.as_u32 << 32 |
- (u64)tp->tunnel_src.as_u32);
-
- hash_unset (gm->tunnel_by_key, key);
- mpls_sw_interface_enable_disable(mm, hi->sw_if_index, 0);
- ip4_sw_interface_enable_disable(hi->sw_if_index, 0);
-
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
- vec_free (tp->rewrite_data);
- fib_node_deinit(&tp->mgt_node);
- pool_put (mm->gre_tunnels, tp);
-
- return 0;
-}
-
-int
-vnet_mpls_gre_add_del_tunnel (ip4_address_t *src,
- ip4_address_t *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_id, u32 outer_fib_id,
- u32 * tunnel_sw_if_index,
- u8 l2_only,
- u8 is_add)
-{
- u32 inner_fib_index = 0;
- u32 outer_fib_index = 0;
- u32 dummy;
- ip4_main_t * im = &ip4_main;
-
- /* No questions, no answers */
- if (NULL == tunnel_sw_if_index)
- tunnel_sw_if_index = &dummy;
-
- *tunnel_sw_if_index = ~0;
-
- if (inner_fib_id != (u32)~0)
- {
- uword * p;
-
- p = hash_get (im->fib_index_by_table_id, inner_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_INNER_FIB;
- inner_fib_index = p[0];
- }
-
- if (outer_fib_id != 0)
- {
- uword * p;
-
- p = hash_get (im->fib_index_by_table_id, outer_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- outer_fib_index = p[0];
- }
-
- if (is_add)
- {
- return (mpls_gre_tunnel_add(src,dst,intfc, mask_width,
- inner_fib_index,
- outer_fib_index,
- tunnel_sw_if_index,
- l2_only));
- }
- else
- {
- return (mpls_gre_tunnel_del(src,dst,intfc, mask_width,
- inner_fib_index,
- outer_fib_index,
- tunnel_sw_if_index,
- l2_only));
- }
-}
-
-/*
- * Remove all mpls tunnels in the specified fib
- */
-int vnet_mpls_gre_delete_fib_tunnels (u32 fib_id)
-{
- mpls_main_t * mm = &mpls_main;
- vnet_main_t * vnm = mm->vnet_main;
- mpls_gre_tunnel_t *tp;
- u32 fib_index = 0;
- u32 * tunnels_to_delete = 0;
- vnet_hw_interface_t * hi;
- int i;
-
- fib_index = ip4_fib_index_from_table_id(fib_id);
- if (~0 == fib_index)
- return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-
- pool_foreach (tp, mm->gre_tunnels,
- ({
- if (tp->inner_fib_index == fib_index)
- vec_add1 (tunnels_to_delete, tp - mm->gre_tunnels);
- }));
-
- for (i = 0; i < vec_len(tunnels_to_delete); i++) {
- tp = pool_elt_at_index (mm->gre_tunnels, tunnels_to_delete[i]);
-
- /* Delete, the route if not already gone */
- if (FIB_NODE_INDEX_INVALID != tp->fei && !tp->l2_only)
- {
- const fib_prefix_t tun_dst_pfx = {
- .fp_len = 32,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = tp->tunnel_dst,
- }
- };
-
- fib_entry_child_remove(tp->fei,
- tp->sibling_index);
- fib_table_entry_special_remove(tp->outer_fib_index,
- &tun_dst_pfx,
- FIB_SOURCE_RR);
- tp->fei = FIB_NODE_INDEX_INVALID;
- adj_unlock(tp->adj_index);
-
- const fib_prefix_t tun_sub_net_pfx = {
- .fp_len = tp->mask_width,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4 = tp->intfc_address,
- },
- };
-
- fib_table_entry_delete(tp->inner_fib_index,
- &tun_sub_net_pfx,
- FIB_SOURCE_INTERFACE);
- }
-
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
- vec_free (tp->rewrite_data);
- pool_put (mm->gre_tunnels, tp);
- }
-
- vec_free(tunnels_to_delete);
-
- return (0);
-}
-
-static clib_error_t *
-create_mpls_gre_tunnel_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, * line_input = &_line_input;
- ip4_address_t src, dst, intfc;
- int src_set = 0, dst_set = 0, intfc_set = 0;
- u32 mask_width;
- u32 inner_fib_id = (u32)~0;
- u32 outer_fib_id = 0;
- int rv;
- u8 is_del = 0;
- u8 l2_only = 0;
- u32 tunnel_intfc_sw_if_index = ~0;
-
- /* Get a line of input. */
- if (! unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "src %U",
- unformat_ip4_address, &src))
- src_set = 1;
- else if (unformat (line_input, "dst %U",
- unformat_ip4_address, &dst))
- dst_set = 1;
- else if (unformat (line_input, "intfc %U/%d",
- unformat_ip4_address, &intfc, &mask_width))
- intfc_set = 1;
- else if (unformat (line_input, "inner-fib-id %d", &inner_fib_id))
- ;
- else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
- ;
- else if (unformat (line_input, "del"))
- is_del = 1;
- else if (unformat (line_input, "l2-only"))
- l2_only = 1;
- else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- }
-
- if (!src_set)
- return clib_error_return (0, "missing: src <ip-address>");
-
- if (!dst_set)
- return clib_error_return (0, "missing: dst <ip-address>");
-
- if (!intfc_set)
- return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
-
-
- rv = vnet_mpls_gre_add_del_tunnel (&src, &dst, &intfc, mask_width,
- inner_fib_id, outer_fib_id,
- &tunnel_intfc_sw_if_index,
- l2_only, !is_del);
-
- switch (rv)
- {
- case 0:
- if (!is_del)
- vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), tunnel_intfc_sw_if_index);
- break;
-
- case VNET_API_ERROR_NO_SUCH_INNER_FIB:
- return clib_error_return (0, "inner fib ID %d doesn't exist\n",
- inner_fib_id);
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "outer fib ID %d doesn't exist\n",
- outer_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "tunnel not found\n");
-
- case VNET_API_ERROR_NO_SUCH_LABEL:
- /*
- * This happens when there's no MPLS label for the dst address
- * no need for two error messages.
- */
- break;
-
- default:
- return clib_error_return (0, "vnet_mpls_gre_add_del_tunnel returned %d",
- rv);
- }
- return 0;
-}
-
-VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = {
- .path = "create mpls gre tunnel",
- .short_help =
- "create mpls gre tunnel [del] src <addr> dst <addr> intfc <addr>/<mw>",
- .function = create_mpls_gre_tunnel_command_fn,
-};
-
u8 * format_mpls_encap_index (u8 * s, va_list * args)
{
mpls_main_t * mm = va_arg (*args, mpls_main_t *);
@@ -1239,40 +345,6 @@ u8 * format_mpls_encap_index (u8 * s, va_list * args)
return s;
}
-u8 * format_mpls_gre_tunnel (u8 * s, va_list * args)
-{
- mpls_gre_tunnel_t * t = va_arg (*args, mpls_gre_tunnel_t *);
- mpls_main_t * mm = &mpls_main;
-
- if (t->l2_only == 0)
- {
- s = format (s, "[%d]: src %U, dst %U, adj %U/%d, labels %U\n",
- t - mm->gre_tunnels,
- format_ip4_address, &t->tunnel_src,
- format_ip4_address, &t->tunnel_dst,
- format_ip4_address, &t->intfc_address,
- t->mask_width,
- format_mpls_encap_index, mm, t->encap_index);
-
- s = format (s, " inner fib index %d, outer fib index %d",
- t->inner_fib_index, t->outer_fib_index);
- }
- else
- {
- s = format (s, "[%d]: src %U, dst %U, key %U, labels %U\n",
- t - mm->gre_tunnels,
- format_ip4_address, &t->tunnel_src,
- format_ip4_address, &t->tunnel_dst,
- format_ip4_address, &t->intfc_address,
- format_mpls_encap_index, mm, t->encap_index);
-
- s = format (s, " l2 interface %d, outer fib index %d",
- t->hw_if_index, t->outer_fib_index);
- }
-
- return s;
-}
-
u8 * format_mpls_ethernet_tunnel (u8 * s, va_list * args)
{
mpls_eth_tunnel_t * t = va_arg (*args, mpls_eth_tunnel_t *);
@@ -1299,20 +371,8 @@ show_mpls_tunnel_command_fn (vlib_main_t * vm,
vlib_cli_command_t * cmd)
{
mpls_main_t * mm = &mpls_main;
- mpls_gre_tunnel_t * gt;
mpls_eth_tunnel_t * et;
- if (pool_elts (mm->gre_tunnels))
- {
- vlib_cli_output (vm, "MPLS-GRE tunnels");
- pool_foreach (gt, mm->gre_tunnels,
- ({
- vlib_cli_output (vm, "%U", format_mpls_gre_tunnel, gt);
- }));
- }
- else
- vlib_cli_output (vm, "No MPLS-GRE tunnels");
-
if (pool_elts (mm->eth_tunnels))
{
vlib_cli_output (vm, "MPLS-Ethernet tunnels");
@@ -1339,9 +399,6 @@ clib_error_t *mpls_interface_init (vlib_main_t *vm)
{
clib_error_t * error;
- fib_node_register_type(FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
- &mpls_gre_vft);
-
if ((error = vlib_call_init_function (vm, mpls_policy_encap_init)))
return error;
diff --git a/vnet/vnet/mpls/mpls.c b/vnet/vnet/mpls/mpls.c
index b28736ba..ac35e5d4 100644
--- a/vnet/vnet/mpls/mpls.c
+++ b/vnet/vnet/mpls/mpls.c
@@ -96,25 +96,29 @@ u8 * format_mpls_header (u8 * s, va_list * args)
vnet_mpls_uc_get_s(hdr.label_exp_s_ttl)));
}
-u8 * format_mpls_gre_tx_trace (u8 * s, va_list * args)
+uword
+unformat_mpls_header (unformat_input_t * input, 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 *);
- mpls_gre_tx_trace_t * t = va_arg (*args, mpls_gre_tx_trace_t *);
- mpls_main_t * mm = &mpls_main;
-
- if (t->lookup_miss)
- s = format (s, "MPLS: lookup miss");
- else
- {
- s = format (s, "MPLS: tunnel %d labels %U len %d src %U dst %U",
- t->tunnel_id,
- format_mpls_encap_index, mm, t->mpls_encap_index,
- clib_net_to_host_u16 (t->length),
- format_ip4_address, &t->src.as_u8,
- format_ip4_address, &t->dst.as_u8);
- }
- return s;
+ u8 ** result = va_arg (*args, u8 **);
+ mpls_unicast_header_t _h, * h = &_h;
+ u32 label, label_exp_s_ttl;
+
+ if (! unformat (input, "MPLS %d", &label))
+ return 0;
+
+ label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
+ h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
+
+ /* Add gre, mpls headers to result. */
+ {
+ void * p;
+ u32 h_n_bytes = sizeof (h[0]);
+
+ vec_add2 (*result, p, h_n_bytes);
+ clib_memcpy (p, h, h_n_bytes);
+ }
+
+ return 1;
}
u8 * format_mpls_eth_tx_trace (u8 * s, va_list * args)
@@ -156,62 +160,6 @@ u8 * format_mpls_eth_header_with_length (u8 * s, va_list * args)
return s;
}
-u8 * format_mpls_gre_header_with_length (u8 * s, va_list * args)
-{
- gre_header_t * h = va_arg (*args, gre_header_t *);
- mpls_unicast_header_t * m = (mpls_unicast_header_t *)(h+1);
- u32 max_header_bytes = va_arg (*args, u32);
- uword header_bytes;
-
- header_bytes = sizeof (h[0]);
- if (max_header_bytes != 0 && header_bytes > max_header_bytes)
- return format (s, "gre header truncated");
-
- s = format
- (s, "GRE-MPLS label %d",
- vnet_mpls_uc_get_label (clib_net_to_host_u32 (m->label_exp_s_ttl)));
-
- return s;
-}
-
-u8 * format_mpls_gre_header (u8 * s, va_list * args)
-{
- gre_header_t * h = va_arg (*args, gre_header_t *);
- return format (s, "%U", format_mpls_gre_header_with_length, h, 0);
-}
-
-uword
-unformat_mpls_gre_header (unformat_input_t * input, va_list * args)
-{
- u8 ** result = va_arg (*args, u8 **);
- gre_header_t _g, * g = &_g;
- mpls_unicast_header_t _h, * h = &_h;
- u32 label, label_exp_s_ttl;
-
- if (! unformat (input, "MPLS %d", &label))
- return 0;
-
- g->protocol = clib_host_to_net_u16 (GRE_PROTOCOL_mpls_unicast);
-
- label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
- h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
-
- /* Add gre, mpls headers to result. */
- {
- void * p;
- u32 g_n_bytes = sizeof (g[0]);
- u32 h_n_bytes = sizeof (h[0]);
-
- vec_add2 (*result, p, g_n_bytes);
- clib_memcpy (p, g, g_n_bytes);
-
- vec_add2 (*result, p, h_n_bytes);
- clib_memcpy (p, h, h_n_bytes);
- }
-
- return 1;
-}
-
uword
unformat_mpls_label_net_byte_order (unformat_input_t * input,
va_list * args)
@@ -443,217 +391,6 @@ VLIB_CLI_COMMAND (mpls_del_encap_command, static) = {
.function = mpls_del_encap_command_fn,
};
-int vnet_mpls_add_del_decap (u32 rx_fib_id,
- u32 tx_fib_id,
- u32 label_host_byte_order,
- int s_bit, int next_index, int is_add)
-{
- mpls_main_t * mm = &mpls_main;
- ip4_main_t * im = &ip4_main;
- mpls_decap_t * d;
- u32 rx_fib_index, tx_fib_index_or_output_swif_index;
- uword *p;
- u64 key;
-
- p = hash_get (im->fib_index_by_table_id, rx_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_FIB;
-
- rx_fib_index = p[0];
-
- /* L3 decap => transform fib ID to fib index */
- if (next_index == MPLS_LOOKUP_NEXT_IP4_INPUT)
- {
- p = hash_get (im->fib_index_by_table_id, tx_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-
- tx_fib_index_or_output_swif_index = p[0];
- }
- else
- {
- /* L2 decap, tx_fib_id is actually the output sw_if_index */
- tx_fib_index_or_output_swif_index = tx_fib_id;
- }
-
- key = ((u64) rx_fib_index<<32) | ((u64) label_host_byte_order<<12)
- | ((u64) s_bit<<8);
-
- p = hash_get (mm->mpls_decap_by_rx_fib_and_label, key);
-
- /* If deleting, or replacing an old entry */
- if (is_add == 0 || p)
- {
- if (is_add == 0 && p == 0)
- return VNET_API_ERROR_NO_SUCH_LABEL;
-
- d = pool_elt_at_index (mm->decaps, p[0]);
- hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
- pool_put (mm->decaps, d);
- /* Deleting, we're done... */
- if (is_add == 0)
- return 0;
- }
-
- /* add decap entry... */
- pool_get (mm->decaps, d);
- memset (d, 0, sizeof (*d));
- d->tx_fib_index = tx_fib_index_or_output_swif_index;
- d->next_index = next_index;
-
- hash_set (mm->mpls_decap_by_rx_fib_and_label, key, d - mm->decaps);
-
- return 0;
-}
-
-uword
-unformat_mpls_gre_input_next (unformat_input_t * input, va_list * args)
-{
- u32 * result = va_arg (*args, u32 *);
- int rv = 0;
-
- if (unformat (input, "lookup"))
- {
- *result = MPLS_LOOKUP_NEXT_IP4_INPUT;
- rv = 1;
- }
- else if (unformat (input, "output"))
- {
- *result = MPLS_LOOKUP_NEXT_L2_OUTPUT;
- rv = 1;
- }
- return rv;
-}
-
-static clib_error_t *
-mpls_add_decap_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vnet_main_t * vnm = vnet_get_main();
- u32 rx_fib_id = 0;
- u32 tx_fib_or_sw_if_index;
- u32 label;
- int s_bit = 1;
- u32 next_index = 1; /* ip4_lookup, see node.c */
- int tx_fib_id_set = 0;
- int label_set = 0;
- int rv;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "fib %d", &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "sw_if_index %d", &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
- &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "rx-fib %d", &rx_fib_id))
- ;
- else if (unformat (input, "label %d", &label))
- label_set = 1;
- else if (unformat (input, "s-bit-clear"))
- s_bit = 0;
- else if (unformat (input, "next %U", unformat_mpls_gre_input_next,
- &next_index))
- ;
- else
- break;
- }
-
- if (tx_fib_id_set == 0)
- return clib_error_return (0, "lookup FIB ID not set");
- if (label_set == 0)
- return clib_error_return (0, "missing label");
-
- rv = vnet_mpls_add_del_decap (rx_fib_id, tx_fib_or_sw_if_index,
- label, s_bit, next_index, 1 /* is_add */);
- switch (rv)
- {
- case 0:
- break;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_INNER_FIB:
- return clib_error_return (0, "no such tx fib / swif %d",
- tx_fib_or_sw_if_index);
-
- default:
- return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
- rv);
- }
- return 0;
-}
-
-VLIB_CLI_COMMAND (mpls_add_decap_command, static) = {
- .path = "mpls decap add",
- .short_help =
- "mpls decap add fib <id> label <nn> [s-bit-clear] [next-index <nn>]",
- .function = mpls_add_decap_command_fn,
-};
-
-static clib_error_t *
-mpls_del_decap_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- u32 rx_fib_id = 0;
- u32 tx_fib_id = 0;
- u32 label;
- int s_bit = 1;
- int label_set = 0;
- int rv;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "rx-fib %d", &rx_fib_id))
- ;
- else if (unformat (input, "label %d", &label))
- label_set = 1;
- else if (unformat (input, "s-bit-clear"))
- s_bit = 0;
- }
-
- if (!label_set)
- return clib_error_return (0, "label not set");
-
- rv = vnet_mpls_add_del_decap (rx_fib_id,
- tx_fib_id /* not interesting */,
- label, s_bit,
- 0 /* next_index not interesting */,
- 0 /* is_add */);
- switch (rv)
- {
- case 0:
- break;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_INNER_FIB:
- return clib_error_return (0, "no such lookup fib id %d", tx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_LABEL:
- return clib_error_return (0, "no such label %d rx fib id %d",
- label, rx_fib_id);
-
- default:
- return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
- rv);
- }
- return 0;
-}
-
-
-VLIB_CLI_COMMAND (mpls_del_decap_command, static) = {
- .path = "mpls decap delete",
- .short_help = "mpls decap delete label <label> rx-fib <id> [s-bit-clear]",
- .function = mpls_del_decap_command_fn,
-};
-
int
mpls_dest_cmp(void * a1, void * a2)
{
@@ -943,28 +680,6 @@ int mpls_fib_reset_labels (u32 fib_id)
pool_put_index (mm->encaps, s->entry_index);
}
- vec_reset_length(records);
-
- hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
- ({
- if (fib_index == (u32) (key>>32)) {
- vec_add2 (records, s, 1);
- s->entry_index = value;
- s->fib_index = fib_index;
- s->s_bit = key & (1<<8);
- s->dest = (u32)((key & 0xFFFFFFFF)>>12);
- }
- }));
-
- vec_foreach (s, records)
- {
- key = ((u64) fib_index <<32) | ((u64) s->dest<<12) |
- ((u64) s->s_bit);
-
- hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
- pool_put_index (mm->decaps, s->entry_index);
- }
-
vec_free(records);
return 0;
}
@@ -981,7 +696,6 @@ static clib_error_t * mpls_init (vlib_main_t * vm)
return error;
mm->mpls_encap_by_fib_and_dest = hash_create (0, sizeof (uword));
- mm->mpls_decap_by_rx_fib_and_label = hash_create (0, sizeof (uword));
return vlib_call_init_function (vm, mpls_input_init);
}
diff --git a/vnet/vnet/mpls/mpls.h b/vnet/vnet/mpls/mpls.h
index 35755333..da663b0b 100644
--- a/vnet/vnet/mpls/mpls.h
+++ b/vnet/vnet/mpls/mpls.h
@@ -12,11 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef included_vnet_mpls_gre_h
-#define included_vnet_mpls_gre_h
+#ifndef included_vnet_mpls_h
+#define included_vnet_mpls_h
#include <vnet/vnet.h>
-#include <vnet/gre/gre.h>
#include <vnet/mpls/packet.h>
#include <vnet/mpls/mpls_types.h>
#include <vnet/ip/ip4_packet.h>
@@ -24,43 +23,17 @@
#include <vnet/fib/fib_node.h>
#include <vnet/adj/adj.h>
-typedef CLIB_PACKED (struct {
- ip4_header_t ip4; /* 20 bytes */
- gre_header_t gre; /* 4 bytes */
- mpls_unicast_header_t labels[0]; /* 4 bytes each */
-}) ip4_gre_and_mpls_header_t;
-
-extern vnet_hw_interface_class_t mpls_gre_hw_interface_class;
-
typedef enum {
#define mpls_error(n,s) MPLS_ERROR_##n,
#include <vnet/mpls/error.def>
#undef mpls_error
MPLS_N_ERROR,
-} mpls_gre_error_t;
+} mpls_error_t;
/*
* No protocol info, MPLS labels don't have a next-header field
* presumably the label field tells all...
*/
-
-typedef struct {
- fib_node_t mgt_node;
- ip4_address_t tunnel_src;
- ip4_address_t tunnel_dst;
- ip4_address_t intfc_address;
- u32 mask_width;
- u32 inner_fib_index;
- u32 outer_fib_index;
- u32 encap_index;
- u32 hw_if_index; /* L2 x-connect capable tunnel intfc */
- u8 * rewrite_data;
- u8 l2_only;
- fib_node_index_t fei; /* FIB Entry index for the tunnel's destination */
- adj_index_t adj_index; /* The midchain adj this tunnel creates */
- u32 sibling_index;
-} mpls_gre_tunnel_t;
-
typedef struct {
u8 tunnel_dst[6];
ip4_address_t intfc_address;
@@ -81,11 +54,6 @@ typedef struct {
u32 output_next_index;
} mpls_encap_t;
-typedef struct {
- u32 tx_fib_index;
- u32 next_index; /* e.g. ip4/6-input, l2-input */
-} mpls_decap_t;
-
#define MPLS_FIB_DEFAULT_TABLE_ID 0
/**
@@ -134,10 +102,6 @@ typedef struct {
u32 mpls_rx_feature_not_enabled;
u32 mpls_tx_feature_interface_output;
- /* pool of gre tunnel instances */
- mpls_gre_tunnel_t *gre_tunnels;
- u32 * free_gre_sw_if_indices;
-
/* pool of ethernet tunnel instances */
mpls_eth_tunnel_t *eth_tunnels;
u32 * free_eth_sw_if_indices;
@@ -146,10 +110,6 @@ typedef struct {
mpls_encap_t * encaps;
uword * mpls_encap_by_fib_and_dest;
- /* Decap side: map rx label to FIB */
- mpls_decap_t * decaps;
- uword * mpls_decap_by_rx_fib_and_label;
-
/* mpls-o-e policy tunnel next index for ip4/ip6-classify */
u32 ip4_classify_mpls_policy_encap_next_index;
u32 ip6_classify_mpls_policy_encap_next_index;
@@ -197,7 +157,6 @@ __VA_ARGS__ vnet_feature_registration_t tx_##x
extern clib_error_t * mpls_feature_init(vlib_main_t * vm);
format_function_t format_mpls_protocol;
-format_function_t format_mpls_gre_header_with_length;
format_function_t format_mpls_eth_header_with_length;
format_function_t format_mpls_encap_index;
@@ -211,25 +170,17 @@ extern vlib_node_registration_t mpls_policy_encap_node;
extern vlib_node_registration_t mpls_output_node;
extern vlib_node_registration_t mpls_midchain_node;
-extern vnet_device_class_t mpls_gre_device_class;
-
/* Parse mpls protocol as 0xXXXX or protocol name.
In either host or network byte order. */
unformat_function_t unformat_mpls_protocol_host_byte_order;
unformat_function_t unformat_mpls_protocol_net_byte_order;
unformat_function_t unformat_mpls_label_net_byte_order;
-unformat_function_t unformat_mpls_gre_header;
-unformat_function_t unformat_pg_mpls_gre_header;
unformat_function_t unformat_mpls_unicast_label;
/* Parse mpls header. */
unformat_function_t unformat_mpls_header;
unformat_function_t unformat_pg_mpls_header;
-/* manually added to the interface output node in mpls.c */
-#define MPLS_GRE_OUTPUT_NEXT_LOOKUP 1
-#define MPLS_GRE_OUTPUT_NEXT_DROP VNET_INTERFACE_TX_NEXT_DROP
-
void mpls_sw_interface_enable_disable (mpls_main_t * mm,
u32 sw_if_index,
u8 is_enable);
@@ -239,18 +190,6 @@ u8 mpls_sw_interface_is_enabled (u32 sw_if_index);
mpls_encap_t *
mpls_encap_by_fib_and_dest (mpls_main_t * mm, u32 rx_fib, u32 dst_address);
-int mpls_label_from_fib_id_and_dest (mpls_main_t *gm, u32 fib_id,
- u32 dst_address, u32 *labelp);
-
-int vnet_mpls_gre_add_del_tunnel (ip4_address_t *src,
- ip4_address_t *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_id, u32 outer_fib_id,
- u32 * tunnel_intfc_sw_if_index,
- u8 l2_only,
- u8 is_add);
-
int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
ip4_address_t *intfc,
u32 mask_width,
@@ -260,15 +199,8 @@ int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
u8 l2_only,
u8 is_add);
-int vnet_mpls_gre_delete_fib_tunnels (u32 fib_id);
-
int mpls_fib_reset_labels (u32 fib_id);
-int vnet_mpls_add_del_decap (u32 rx_fib_id,
- u32 tx_fib_id,
- u32 label_host_byte_order,
- int s_bit, int next_index, int is_add);
-
int vnet_mpls_add_del_encap (ip4_address_t *dest, u32 fib_id,
u32 *labels_host_byte_order,
u32 policy_tunnel_index,
@@ -278,26 +210,6 @@ int vnet_mpls_policy_tunnel_add_rewrite (mpls_main_t * mm,
mpls_encap_t * e,
u32 policy_tunnel_index);
-typedef struct {
- u32 lookup_miss;
-
- /* Tunnel-id / index in tunnel vector */
- u32 tunnel_id;
-
- /* mpls encap index */
- u32 mpls_encap_index;
-
- /* pkt length */
- u32 length;
-
- /* tunnel ip4 addresses */
- ip4_address_t src;
- ip4_address_t dst;
-} mpls_gre_tx_trace_t;
-
-u8 * format_mpls_gre_tx_trace (u8 * s, va_list * args);
-u8 * format_mpls_gre_header (u8 * s, va_list * args);
-
#define foreach_mpls_input_next \
_(DROP, "error-drop") \
_(LOOKUP, "mpls-lookup")
@@ -369,4 +281,4 @@ mpls_fib_index_cmp(void * a1, void * a2);
int
mpls_label_cmp(void * a1, void * a2);
-#endif /* included_vnet_mpls_gre_h */
+#endif /* included_vnet_mpls_h */
diff --git a/vnet/vnet/mpls/mpls_lookup.c b/vnet/vnet/mpls/mpls_lookup.c
index 31ad68c4..9d29cecf 100644
--- a/vnet/vnet/mpls/mpls_lookup.c
+++ b/vnet/vnet/mpls/mpls_lookup.c
@@ -1,5 +1,5 @@
/*
- * node.c: mpls-o-gre decap processing
+ * mpls_lookup.c: MPLS lookup
*
* Copyright (c) 2012-2014 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -167,9 +167,9 @@ VLIB_REGISTER_NODE (mpls_lookup_node) = {
.sibling_of = "ip4-lookup",
- .format_buffer = format_mpls_gre_header_with_length,
+ .format_buffer = format_mpls_header,
.format_trace = format_mpls_lookup_trace,
- .unformat_buffer = unformat_mpls_gre_header,
+ .unformat_buffer = unformat_mpls_header,
};
VLIB_NODE_FUNCTION_MULTIARCH (mpls_lookup_node, mpls_lookup)
diff --git a/vnet/vnet/mpls/mpls_output.c b/vnet/vnet/mpls/mpls_output.c
index 1d5d1822..739e85db 100644
--- a/vnet/vnet/mpls/mpls_output.c
+++ b/vnet/vnet/mpls/mpls_output.c
@@ -17,6 +17,7 @@
#include <vlib/vlib.h>
#include <vnet/pg/pg.h>
+#include <vnet/ip/ip.h>
#include <vnet/mpls/mpls.h>
typedef struct {
diff --git a/vnet/vnet/mpls/node.c b/vnet/vnet/mpls/node.c
index 1b435f31..5b8f2569 100644
--- a/vnet/vnet/mpls/node.c
+++ b/vnet/vnet/mpls/node.c
@@ -1,5 +1,5 @@
/*
- * node.c: mpls-o-gre decap processing
+ * node.c: MPLS input
*
* Copyright (c) 2012-2014 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/vnet/vnet/mpls/pg.c b/vnet/vnet/mpls/pg.c
index f04b5307..6ff86e32 100644
--- a/vnet/vnet/mpls/pg.c
+++ b/vnet/vnet/mpls/pg.c
@@ -1,5 +1,5 @@
/*
- * pg.c: packet generator mpls/gre interface
+ * pg.c: packet generator mpls interface
*
* Copyright (c) 2012 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/vnet/vnet/mpls/policy_encap.c b/vnet/vnet/mpls/policy_encap.c
index 278e8e6d..d48a153b 100644
--- a/vnet/vnet/mpls/policy_encap.c
+++ b/vnet/vnet/mpls/policy_encap.c
@@ -18,6 +18,7 @@
#include <vlib/vlib.h>
#include <vnet/pg/pg.h>
#include <vnet/mpls/mpls.h>
+#include <vnet/classify/vnet_classify.h>
typedef struct {
u32 next_index;