X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fipsec%2Fipsec_tun.c;h=543be8a7faaf210d900a3b5fdfb55626ec5b4ade;hb=98ca76ab87c63a43b9bba6366ee5ca405709b6bc;hp=63e063fcee3649e363cd0c351a1daa91dbf6fe38;hpb=751bb131ef504b64fe82f393df21dba95ca92e97;p=vpp.git diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c index 63e063fcee3..543be8a7faa 100644 --- a/src/vnet/ipsec/ipsec_tun.c +++ b/src/vnet/ipsec/ipsec_tun.c @@ -22,6 +22,7 @@ #include #include #include +#include /* instantiate the bihash functions */ #include @@ -137,12 +138,14 @@ ipsec_tun_protect_from_const_base (const adj_delegate_t * ad) static u32 ipsec_tun_protect_get_adj_next (vnet_link_t linkt, - const ipsec_tun_protect_t * itp) + const ipsec_tun_protect_t *itp) { ipsec_main_t *im; - ipsec_sa_t *sa; u32 next; + im = &ipsec_main; + next = 0; + if (!(itp->itp_flags & IPSEC_PROTECT_ITF)) { if (ip46_address_is_ip4 (&itp->itp_tun.src)) @@ -151,41 +154,41 @@ ipsec_tun_protect_get_adj_next (vnet_link_t linkt, linkt = VNET_LINK_IP6; } - sa = ipsec_sa_get (itp->itp_out_sa); - im = &ipsec_main; - next = 0; - - if ((sa->crypto_alg == IPSEC_CRYPTO_ALG_NONE && - sa->integ_alg == IPSEC_INTEG_ALG_NONE) && - !(itp->itp_flags & IPSEC_PROTECT_ITF)) - next = (VNET_LINK_IP4 == linkt ? im->esp4_no_crypto_tun_node_index : - im->esp6_no_crypto_tun_node_index); - else if (itp->itp_flags & IPSEC_PROTECT_L2) - next = (VNET_LINK_IP4 == linkt ? im->esp4_encrypt_l2_tun_node_index : - im->esp6_encrypt_l2_tun_node_index); - else + switch (linkt) { - switch (linkt) - { - case VNET_LINK_IP4: - next = im->esp4_encrypt_tun_node_index; - break; - case VNET_LINK_IP6: - next = im->esp6_encrypt_tun_node_index; - break; - case VNET_LINK_MPLS: - next = im->esp_mpls_encrypt_tun_node_index; - break; - case VNET_LINK_ARP: - case VNET_LINK_NSH: - case VNET_LINK_ETHERNET: - ASSERT (0); - break; - } + case VNET_LINK_IP4: + next = im->esp4_encrypt_tun_node_index; + break; + case VNET_LINK_IP6: + next = im->esp6_encrypt_tun_node_index; + break; + case VNET_LINK_MPLS: + next = im->esp_mpls_encrypt_tun_node_index; + break; + case VNET_LINK_ARP: + case VNET_LINK_NSH: + case VNET_LINK_ETHERNET: + ASSERT (0); + break; } + return (next); } +static void +ipsec_tun_setup_tx_nodes (u32 sw_if_index, const ipsec_tun_protect_t *itp) +{ + vnet_feature_modify_end_node ( + ip4_main.lookup_main.output_feature_arc_index, sw_if_index, + ipsec_tun_protect_get_adj_next (VNET_LINK_IP4, itp)); + vnet_feature_modify_end_node ( + ip6_main.lookup_main.output_feature_arc_index, sw_if_index, + ipsec_tun_protect_get_adj_next (VNET_LINK_IP6, itp)); + vnet_feature_modify_end_node ( + mpls_main.output_feature_arc_index, sw_if_index, + ipsec_tun_protect_get_adj_next (VNET_LINK_MPLS, itp)); +} + static void ipsec_tun_protect_add_adj (adj_index_t ai, const ipsec_tun_protect_t * itp) { @@ -200,8 +203,8 @@ ipsec_tun_protect_add_adj (adj_index_t ai, const ipsec_tun_protect_t * itp) else { ipsec_tun_protect_sa_by_adj_index[ai] = itp->itp_out_sa; - adj_nbr_midchain_update_next_node - (ai, ipsec_tun_protect_get_adj_next (adj_get_link_type (ai), itp)); + adj_nbr_midchain_update_next_node ( + ai, ipsec_tun_protect_get_adj_next (adj_get_link_type (ai), itp)); } } @@ -329,7 +332,7 @@ ipsec_tun_protect_tx_db_add (ipsec_tun_protect_t * itp) { if (INDEX_INVALID == idi->id_itp) { - // ipsec_tun_protect_feature_set (itp, 1); + ipsec_tun_setup_tx_nodes (itp->itp_sw_if_index, itp); } idi->id_itp = itp - ipsec_tun_protect_pool; @@ -347,7 +350,7 @@ ipsec_tun_protect_tx_db_add (ipsec_tun_protect_t * itp) * enable the encrypt feature for egress if this is the first addition * on this interface */ - // ipsec_tun_protect_feature_set (itp, 1); + ipsec_tun_setup_tx_nodes (itp->itp_sw_if_index, itp); } hash_set_mem (idi->id_hash, itp->itp_key, itp - ipsec_tun_protect_pool); @@ -435,7 +438,7 @@ ipsec_tun_protect_tx_db_remove (ipsec_tun_protect_t * itp) if (vnet_sw_interface_is_p2p (vnet_get_main (), itp->itp_sw_if_index)) { - // ipsec_tun_protect_feature_set (itp, 0); + ipsec_itf_reset_tx_nodes (itp->itp_sw_if_index); idi->id_itp = INDEX_INVALID; FOR_EACH_FIB_IP_PROTOCOL (nh_proto) @@ -451,7 +454,7 @@ ipsec_tun_protect_tx_db_remove (ipsec_tun_protect_t * itp) if (0 == hash_elts (idi->id_hash)) { - // ipsec_tun_protect_feature_set (itp, 0); + ipsec_itf_reset_tx_nodes (itp->itp_sw_if_index); hash_free (idi->id_hash); idi->id_hash = NULL; } @@ -470,13 +473,13 @@ ipsec_tun_protect_set_crypto_addr (ipsec_tun_protect_t * itp) ({ if (ipsec_sa_is_set_IS_TUNNEL (sa)) { - itp->itp_crypto.src = sa->tunnel_dst_addr; - itp->itp_crypto.dst = sa->tunnel_src_addr; - if (!(itp->itp_flags & IPSEC_PROTECT_ITF)) - { - ipsec_sa_set_IS_PROTECT (sa); - itp->itp_flags |= IPSEC_PROTECT_ENCAPED; - } + itp->itp_crypto.src = ip_addr_46 (&sa->tunnel.t_dst); + itp->itp_crypto.dst = ip_addr_46 (&sa->tunnel.t_src); + if (!(itp->itp_flags & IPSEC_PROTECT_ITF)) + { + ipsec_sa_set_IS_PROTECT (sa); + itp->itp_flags |= IPSEC_PROTECT_ENCAPED; + } } else { @@ -502,6 +505,9 @@ ipsec_tun_protect_config (ipsec_main_t * im, ipsec_sa_lock (itp->itp_out_sa); + if (itp->itp_flags & IPSEC_PROTECT_ITF) + ipsec_sa_set_NO_ALGO_NO_DROP (ipsec_sa_get (itp->itp_out_sa)); + /* *INDENT-OFF* */ FOR_EACH_IPSEC_PROTECT_INPUT_SAI(itp, sai, ({ @@ -534,6 +540,7 @@ ipsec_tun_protect_unconfig (ipsec_main_t * im, ipsec_tun_protect_t * itp) ipsec_tun_protect_rx_db_remove (im, itp); ipsec_tun_protect_tx_db_remove (itp); + ipsec_sa_unset_NO_ALGO_NO_DROP (ipsec_sa_get (itp->itp_out_sa)); ipsec_sa_unlock(itp->itp_out_sa); FOR_EACH_IPSEC_PROTECT_INPUT_SAI(itp, sai, @@ -569,6 +576,9 @@ ipsec_tun_protect_update (u32 sw_if_index, ipsec_main_t *im; int rv; + if (NULL == nh) + nh = &IP_ADDR_ALL_0; + ITP_DBG2 ("update: %U/%U", format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index, format_ip_address, nh); @@ -581,8 +591,6 @@ ipsec_tun_protect_update (u32 sw_if_index, rv = 0; im = &ipsec_main; - if (NULL == nh) - nh = &IP_ADDR_ALL_0; itpi = ipsec_tun_protect_find (sw_if_index, nh); vec_foreach_index (ii, sas_in) @@ -778,6 +786,57 @@ ipsec_tun_protect_walk_itf (u32 sw_if_index, fn (idi->id_itp, ctx); } +static void +ipsec_tun_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable, + void *data) +{ + ipsec_tun_protect_t *itp; + index_t itpi; + + if (arc_index != feature_main.device_input_feature_arc_index) + return; + + /* Only p2p tunnels supported */ + itpi = ipsec_tun_protect_find (sw_if_index, &IP_ADDR_ALL_0); + if (itpi == INDEX_INVALID) + return; + + itp = ipsec_tun_protect_get (itpi); + + if (is_enable) + { + u32 decrypt_tun = ip46_address_is_ip4 (&itp->itp_crypto.dst) ? + ipsec_main.esp4_decrypt_tun_node_index : + ipsec_main.esp6_decrypt_tun_node_index; + + if (!(itp->itp_flags & IPSEC_PROTECT_FEAT)) + { + itp->itp_flags |= IPSEC_PROTECT_FEAT; + vnet_feature_modify_end_node ( + feature_main.device_input_feature_arc_index, sw_if_index, + decrypt_tun); + } + } + else + { + if (itp->itp_flags & IPSEC_PROTECT_FEAT) + { + itp->itp_flags &= ~IPSEC_PROTECT_FEAT; + + u32 eth_in = + vlib_get_node_by_name (vlib_get_main (), (u8 *) "ethernet-input") + ->index; + + vnet_feature_modify_end_node ( + feature_main.device_input_feature_arc_index, sw_if_index, eth_in); + } + } + + /* Propagate flag change into lookup entries */ + ipsec_tun_protect_rx_db_remove (&ipsec_main, itp); + ipsec_tun_protect_rx_db_add (&ipsec_main, itp); +} + static void ipsec_tun_protect_adj_delegate_adj_deleted (adj_delegate_t * ad) { @@ -804,6 +863,9 @@ ipsec_tun_protect_adj_delegate_adj_created (adj_index_t ai) if (!adj_is_midchain (ai)) return; + vec_validate_init_empty (ipsec_tun_protect_sa_by_adj_index, ai, + INDEX_INVALID); + adj = adj_get (ai); ip_address_from_46 (&adj->sub_type.midchain.next_hop, @@ -882,7 +944,7 @@ const static teib_vft_t ipsec_tun_teib_vft = { .nv_deleted = ipsec_tun_teib_entry_deleted, }; -static void +void ipsec_tun_table_init (ip_address_family_t af, uword table_size, u32 n_buckets) { ipsec_main_t *im; @@ -912,16 +974,6 @@ ipsec_tunnel_protect_init (vlib_main_t *vm) IPSEC_TUN_DEFAULT_HASH_NUM_BUCKETS, IPSEC_TUN_DEFAULT_HASH_MEMORY_SIZE); - /* set up feature nodes to drop outbound packets with no crypto alg set */ - im->esp4_no_crypto_tun_node_index = - vlib_get_node_by_name (vm, (u8 *) "esp4-no-crypto")->index; - im->esp6_no_crypto_tun_node_index = - vlib_get_node_by_name (vm, (u8 *) "esp6-no-crypto")->index; - im->esp6_encrypt_l2_tun_node_index = - vlib_get_node_by_name (vm, (u8 *) "esp6-encrypt-tun")->index; - im->esp4_encrypt_l2_tun_node_index = - vlib_get_node_by_name (vm, (u8 *) "esp4-encrypt-tun")->index; - ipsec_tun_adj_delegate_type = adj_delegate_register_new_type (&ipsec_tun_adj_delegate_vft); @@ -929,60 +981,12 @@ ipsec_tunnel_protect_init (vlib_main_t *vm) teib_register (&ipsec_tun_teib_vft); - return 0; -} - -VLIB_INIT_FUNCTION (ipsec_tunnel_protect_init); - -static clib_error_t * -ipsec_config (vlib_main_t * vm, unformat_input_t * input) -{ - unformat_input_t sub_input; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "ip4 %U", unformat_vlib_cli_sub_input, &sub_input)) - { - uword table_size = ~0; - u32 n_buckets = ~0; - - while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&sub_input, "num-buckets %u", &n_buckets)) - ; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, &sub_input); - } - - ipsec_tun_table_init (AF_IP4, table_size, n_buckets); - } - else if (unformat (input, "ip6 %U", unformat_vlib_cli_sub_input, - &sub_input)) - { - uword table_size = ~0; - u32 n_buckets = ~0; - - while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&sub_input, "num-buckets %u", &n_buckets)) - ; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, &sub_input); - } - - ipsec_tun_table_init (AF_IP6, table_size, n_buckets); - } - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } + vnet_feature_register (ipsec_tun_feature_update, NULL); return 0; } -VLIB_CONFIG_FUNCTION (ipsec_config, "ipsec"); +VLIB_INIT_FUNCTION (ipsec_tunnel_protect_init); /* * fd.io coding-style-patch-verification: ON