diff options
author | 2016-10-03 09:40:25 +0100 | |
---|---|---|
committer | 2016-10-03 11:45:15 +0000 | |
commit | 5e575b1d59a5a4c1590ca09d6383a876fb9fdd25 (patch) | |
tree | fcba6d058fe32d9b32fe246577565020d10455ff /vnet/vnet/mpls | |
parent | 553d808fc44e61846e4cda108083dd88beb338e3 (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.c | 194 | ||||
-rw-r--r-- | vnet/vnet/mpls/mpls.h | 23 | ||||
-rw-r--r-- | vnet/vnet/mpls/mpls_features.c | 155 | ||||
-rw-r--r-- | vnet/vnet/mpls/node.c | 2 |
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); |