aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/mpls
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2016-10-03 09:40:25 +0100
committerFlorin Coras <florin.coras@gmail.com>2016-10-03 11:45:15 +0000
commit5e575b1d59a5a4c1590ca09d6383a876fb9fdd25 (patch)
treefcba6d058fe32d9b32fe246577565020d10455ff /vnet/vnet/mpls
parent553d808fc44e61846e4cda108083dd88beb338e3 (diff)
L2 over LISP and GRE (VPP-457)
Change-Id: I0d7f9c7f41a9f9e0acb0950adedb90d45df08c2a Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'vnet/vnet/mpls')
-rw-r--r--vnet/vnet/mpls/interface.c194
-rw-r--r--vnet/vnet/mpls/mpls.h23
-rw-r--r--vnet/vnet/mpls/mpls_features.c155
-rw-r--r--vnet/vnet/mpls/node.c2
4 files changed, 118 insertions, 256 deletions
diff --git a/vnet/vnet/mpls/interface.c b/vnet/vnet/mpls/interface.c
index 9ef4c293..dd40fc29 100644
--- a/vnet/vnet/mpls/interface.c
+++ b/vnet/vnet/mpls/interface.c
@@ -536,190 +536,21 @@ static const int dpo_next_2_mpls_post_rewrite[DPO_LAST] = {
[DPO_LOAD_BALANCE] = IP_LOOKUP_NEXT_LOAD_BALANCE,
};
-static uword
-mpls_post_rewrite (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
+static void
+mpls_gre_fixup (vlib_main_t *vm,
+ ip_adjacency_t *adj,
+ vlib_buffer_t * b0)
{
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- u32 n_left_from, next_index, * from, * to_next;
- u16 old_l0 = 0; //, old_l1 = 0;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- /* while (n_left_from >= 4 && n_left_to_next >= 2) */
- /* { */
- /* u32 bi0, bi1; */
- /* vlib_buffer_t * b0, * b1; */
- /* ip4_header_t * ip0, * ip1; */
- /* u32 next0; */
- /* u32 next1; */
- /* u16 new_l0, new_l1, adj_index0, adj_index1; */
- /* ip_csum_t sum0, sum1; */
- /* ip_adjacency_t *adj0, *adj1; */
-
- /* /\* Prefetch 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); */
-
- /* CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); */
- /* CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); */
- /* } */
-
- /* bi0 = from[0]; */
- /* bi1 = from[1]; */
- /* 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); */
- /* ip0 = vlib_buffer_get_current (b0); */
- /* ip1 = vlib_buffer_get_current (b1); */
-
- /* /\* Note: the tunnel rewrite sets up sw_if_index[VLIB_TX] *\/ */
-
- /* /\* set the GRE (outer) ip packet length, fix the bloody checksum *\/ */
- /* sum0 = ip0->checksum; */
- /* sum1 = ip1->checksum; */
-
- /* /\* old_l0, old_l1 always 0, see the rewrite setup *\/ */
- /* new_l0 = */
- /* clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); */
- /* new_l1 = */
- /* clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)); */
-
- /* sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, */
- /* length /\* changed member *\/); */
- /* sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t, */
- /* length /\* changed member *\/); */
- /* ip0->checksum = ip_csum_fold (sum0); */
- /* ip1->checksum = ip_csum_fold (sum1); */
- /* ip0->length = new_l0; */
- /* ip1->length = new_l1; */
+ ip4_header_t * ip0;
- /* /\* replace the TX adj in the packet with the next in the chain *\/ */
- /* adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; */
- /* adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; */
+ ip0 = vlib_buffer_get_current (b0);
- /* adj0 = ip_get_adjacency (lm, adj_index0); */
- /* adj1 = ip_get_adjacency (lm, adj_index1); */
-
- /* ASSERT(adj0->sub_type.midchain.adj_index != ADJ_INDEX_INVALID); */
- /* ASSERT(adj1->sub_type.midchain.adj_index != ADJ_INDEX_INVALID); */
-
- /* adj_index0 = adj0->sub_type.midchain.adj_index; */
- /* adj_index1 = adj1->sub_type.midchain.adj_index; */
-
- /* vnet_buffer (b0)->ip.adj_index[VLIB_TX] = adj_index0; */
- /* vnet_buffer (b1)->ip.adj_index[VLIB_TX] = adj_index1; */
-
- /* /\* get the next adj in the chain to determine the next graph node *\/ */
- /* adj0 = ip_get_adjacency (lm, adj_index0); */
- /* adj1 = ip_get_adjacency (lm, adj_index1); */
-
- /* next0 = adj0->lookup_next_index; */
- /* next1 = adj1->lookup_next_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)
- {
- ip_adjacency_t * adj0;
- u32 bi0;
- vlib_buffer_t * b0;
- ip4_header_t * ip0;
- u32 next0;
- u16 new_l0, adj_index0;
- ip_csum_t sum0;
-
- 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);
- ip0 = vlib_buffer_get_current (b0);
-
- /* Note: the tunnel rewrite sets up sw_if_index[VLIB_TX] */
-
- /* set the GRE (outer) ip packet length, fix the bloody checksum */
- sum0 = ip0->checksum;
- /* old_l0 always 0, see the rewrite setup */
- new_l0 =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
-
- sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
- length /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
- ip0->length = new_l0;
-
- /* replace the TX adj in the packet with the next in the chain */
- adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
-
- ASSERT(adj_index0);
-
- adj0 = ip_get_adjacency (lm, adj_index0);
- ASSERT(adj0->sub_type.midchain.next_dpo.dpoi_index != ADJ_INDEX_INVALID);
- adj_index0 = adj0->sub_type.midchain.next_dpo.dpoi_index;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = adj_index0;
-
- /* get the next adj in the chain to determine the next graph node */
- ASSERT(0);
- next0 = 0; //adj0->sub_type.midchain.next_dpo.dpoi_next;
-
- 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, mpls_input_node.index,
- MPLS_ERROR_PKTS_ENCAP, from_frame->n_vectors);
- return from_frame->n_vectors;
+ /* 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);
}
-VLIB_REGISTER_NODE (mpls_post_rewrite_node) = {
- .function = mpls_post_rewrite,
- .name = "mpls-post-rewrite",
- /* Takes a vector of packets. */
- .vector_size = sizeof (u32),
-
- .runtime_data_bytes = 0,
-
- .n_next_nodes = IP_LOOKUP_N_NEXT,
- .next_nodes = IP4_LOOKUP_NEXT_NODES,
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (mpls_post_rewrite_node, mpls_post_rewrite)
-
static u8 * mpls_gre_rewrite (mpls_main_t *mm, mpls_gre_tunnel_t * t)
{
ip4_header_t * ip0;
@@ -780,7 +611,7 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
{
mpls_interface_state_change_callback_t *callback;
vlib_main_t * vm = vlib_get_main();
- ip_config_main_t * cm = &mm->rx_config_mains;
+ ip_config_main_t * cm = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
vnet_config_main_t * vcm = &cm->config_main;
u32 lookup_feature_index;
fib_node_index_t lfib_index;
@@ -1101,7 +932,8 @@ int mpls_gre_tunnel_add (ip4_address_t *src,
hi->sw_if_index);
adj_nbr_midchain_update_rewrite(tp->adj_index,
- mpls_post_rewrite_node.index,
+ mpls_gre_fixup,
+ ADJ_MIDCHAIN_FLAG_NONE,
rewrite_data);
mpls_gre_tunnel_stack(tp);
diff --git a/vnet/vnet/mpls/mpls.h b/vnet/vnet/mpls/mpls.h
index 2aeae49d..e7fed192 100644
--- a/vnet/vnet/mpls/mpls.h
+++ b/vnet/vnet/mpls/mpls.h
@@ -127,11 +127,12 @@ typedef struct {
uword *fib_index_by_table_id;
/* rx/tx interface/feature configuration. */
- ip_config_main_t rx_config_mains, tx_config_main;
+ ip_config_main_t feature_config_mains[VNET_N_IP_FEAT];
/* Built-in unicast feature path indices, see ip_feature_init_cast(...) */
u32 mpls_rx_feature_lookup;
u32 mpls_rx_feature_not_enabled;
+ u32 mpls_tx_feature_interface_output;
/* pool of gre tunnel instances */
mpls_gre_tunnel_t *gre_tunnels;
@@ -154,10 +155,10 @@ typedef struct {
u32 ip6_classify_mpls_policy_encap_next_index;
/* feature path configuration lists */
- vnet_ip_feature_registration_t * next_feature;
+ vnet_ip_feature_registration_t * next_feature[VNET_N_IP_FEAT];
/* Save feature results for show command */
- char **feature_nodes;
+ char **feature_nodes[VNET_N_IP_FEAT];
/* IP4 enabled count by software interface */
u8 * mpls_enabled_by_sw_if_index;
@@ -179,11 +180,23 @@ static void __vnet_add_feature_registration_uc_##x (void) \
static void __vnet_add_feature_registration_uc_##x (void) \
{ \
mpls_main_t * mm = &mpls_main; \
- uc_##x.next = mm->next_feature; \
- mm->next_feature = &uc_##x; \
+ uc_##x.next = mm->next_feature[VNET_IP_RX_UNICAST_FEAT]; \
+ mm->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \
} \
__VA_ARGS__ vnet_ip_feature_registration_t uc_##x
+#define VNET_MPLS_TX_FEATURE_INIT(x,...) \
+ __VA_ARGS__ vnet_ip_feature_registration_t tx_##x; \
+static void __vnet_add_feature_registration_tx_##x (void) \
+ __attribute__((__constructor__)) ; \
+static void __vnet_add_feature_registration_tx_##x (void) \
+{ \
+ mpls_main_t * mm = &mpls_main; \
+ tx_##x.next = mm->next_feature[VNET_IP_TX_FEAT]; \
+ mm->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \
+} \
+__VA_ARGS__ vnet_ip_feature_registration_t tx_##x
+
extern clib_error_t * mpls_feature_init(vlib_main_t * vm);
format_function_t format_mpls_protocol;
diff --git a/vnet/vnet/mpls/mpls_features.c b/vnet/vnet/mpls/mpls_features.c
index d3a726af..80002fcb 100644
--- a/vnet/vnet/mpls/mpls_features.c
+++ b/vnet/vnet/mpls/mpls_features.c
@@ -112,22 +112,49 @@ VNET_MPLS_FEATURE_INIT (mpls_not_enabled, static) = {
.feature_index = &mpls_main.mpls_rx_feature_not_enabled,
};
-static char * feature_start_nodes[] =
+/* Built-in ip4 tx feature path definition */
+VNET_MPLS_TX_FEATURE_INIT (interface_output, static) = {
+ .node_name = "interface-output",
+ .runs_before = 0, /* not before any other features */
+ .feature_index = &mpls_main.mpls_tx_feature_interface_output,
+};
+
+
+static char * rx_feature_start_nodes[] =
{
"mpls-input",
};
+static char * tx_feature_start_nodes[] =
+{
+ "mpls-output",
+ "mpls-midchain",
+};
clib_error_t *
mpls_feature_init (vlib_main_t * vm)
{
- ip_config_main_t * cm = &mpls_main.rx_config_mains;
+ ip_config_main_t * cm = &mpls_main.feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
vnet_config_main_t * vcm = &cm->config_main;
+ clib_error_t *error;
+
+ if ((error = ip_feature_init_cast (vm, cm, vcm,
+ rx_feature_start_nodes,
+ ARRAY_LEN(rx_feature_start_nodes),
+ mpls_main.next_feature[VNET_IP_RX_UNICAST_FEAT],
+ &mpls_main.feature_nodes[VNET_IP_RX_UNICAST_FEAT])))
+ return error;
- return (ip_feature_init_cast (vm, cm, vcm,
- feature_start_nodes,
- ARRAY_LEN(feature_start_nodes),
- VNET_IP_RX_UNICAST_FEAT,
- VNET_L3_PACKET_TYPE_MPLS_UNICAST));
+ cm = &mpls_main.feature_config_mains[VNET_IP_TX_FEAT];
+ vcm = &cm->config_main;
+
+ if ((error = ip_feature_init_cast (vm, cm, vcm,
+ tx_feature_start_nodes,
+ ARRAY_LEN(tx_feature_start_nodes),
+ mpls_main.next_feature[VNET_IP_TX_FEAT],
+ &mpls_main.feature_nodes[VNET_IP_TX_FEAT])))
+ return error;
+
+ return error;
}
static clib_error_t *
@@ -137,39 +164,53 @@ mpls_sw_interface_add_del (vnet_main_t * vnm,
{
vlib_main_t * vm = vnm->vlib_main;
mpls_main_t * mm = &mpls_main;
- ip_config_main_t * cm = &mm->rx_config_mains;
- vnet_config_main_t * vcm = &cm->config_main;
- u32 drop_feature_index;
- u32 ci;
-
- vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
- vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
- vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
- ci = cm->config_index_by_sw_if_index[sw_if_index];
-
- drop_feature_index = mm->mpls_rx_feature_not_enabled;
-
- if (is_add)
- ci = vnet_config_add_feature (vm, vcm, ci,
- drop_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- {
- ci = vnet_config_del_feature (vm, vcm, ci,
- drop_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;;
- }
-
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ u32 feature_index;
+ u32 ci, cast;
+
+ for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
+ {
+ ip_config_main_t * cm = &mm->feature_config_mains[cast];
+ vnet_config_main_t * vcm = &cm->config_main;
+
+ if (VNET_IP_RX_MULTICAST_FEAT == cast)
+ continue;
+
+ vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
+ vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
+ vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
+ ci = cm->config_index_by_sw_if_index[sw_if_index];
+
+ if (cast == VNET_IP_RX_UNICAST_FEAT)
+ feature_index = mm->mpls_rx_feature_not_enabled;
+ else
+ feature_index = mm->mpls_tx_feature_interface_output;
+
+
+ if (is_add)
+ ci = vnet_config_add_feature (vm, vcm, ci,
+ feature_index,
+ /* config data */ 0,
+ /* # bytes of config data */ 0);
+ else
+ {
+ ci = vnet_config_del_feature (vm, vcm, ci,
+ feature_index,
+ /* config data */ 0,
+ /* # bytes of config data */ 0);
+ mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;;
+ }
+ cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ }
return /* no error */ 0;
}
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del);
+#define foreach_af_cast \
+_(VNET_IP_RX_UNICAST_FEAT, "mpls input") \
+_(VNET_IP_TX_FEAT, "mpls output") \
+
static clib_error_t *
show_mpls_features_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -181,11 +222,15 @@ show_mpls_features_command_fn (vlib_main_t * vm,
vlib_cli_output (vm, "Available MPLS feature nodes");
- do {
- features = mm->feature_nodes;
- for (i = 0; i < vec_len(features); i++)
- vlib_cli_output (vm, " %s\n", features[i]);
+#define _(c,s) \
+ do { \
+ features = mm->feature_nodes[c]; \
+ vlib_cli_output (vm, "%s:", s); \
+ for (i = 0; i < vec_len(features); i++) \
+ vlib_cli_output (vm, " %s\n", features[i]); \
} while(0);
+ foreach_af_cast;
+#undef _
return 0;
}
@@ -202,18 +247,7 @@ show_mpls_interface_features_command_fn (vlib_main_t * vm,
vlib_cli_command_t * cmd)
{
vnet_main_t * vnm = vnet_get_main();
- mpls_main_t * mm = &mpls_main;
-
- ip_config_main_t * cm;
- vnet_config_main_t * vcm;
- vnet_config_t * cfg;
- u32 cfg_index;
- vnet_config_feature_t * feat;
- vlib_node_t * n;
u32 sw_if_index;
- u32 node_index;
- u32 current_config_index;
- int i;
if (! unformat (input, "%U", unformat_vnet_sw_interface,
vnm, &sw_if_index))
@@ -222,26 +256,9 @@ show_mpls_interface_features_command_fn (vlib_main_t * vm,
vlib_cli_output (vm, "MPLS feature paths configured on %U...",
format_vnet_sw_if_index_name, vnm, sw_if_index);
- cm = &mm->rx_config_mains;
- vcm = &cm->config_main;
-
- current_config_index = vec_elt (cm->config_index_by_sw_if_index,
- sw_if_index);
-
- ASSERT(current_config_index
- < vec_len (vcm->config_pool_index_by_user_index));
-
- cfg_index =
- vcm->config_pool_index_by_user_index[current_config_index];
- cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
-
- for (i = 0; i < vec_len(cfg->features); i++)
- {
- feat = cfg->features + i;
- node_index = feat->node_index;
- n = vlib_get_node (vm, node_index);
- vlib_cli_output (vm, " %v", n->name);
- }
+ ip_interface_features_show (vm, "MPLS",
+ mpls_main.feature_config_mains,
+ sw_if_index);
return 0;
}
diff --git a/vnet/vnet/mpls/node.c b/vnet/vnet/mpls/node.c
index 6801cc7b..1b435f31 100644
--- a/vnet/vnet/mpls/node.c
+++ b/vnet/vnet/mpls/node.c
@@ -110,7 +110,7 @@ mpls_input_inline (vlib_main_t * vm,
h0 = vlib_buffer_get_current (b0);
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- cm0 = &mm->rx_config_mains;
+ cm0 = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
b0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index,
sw_if_index0);