X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fipsec%2Fipsec_tun.c;h=ca0091b35455b69a3398a480fbc2d898fa605dda;hb=12989b538881f9681f078cf1485c51df1251877a;hp=a389cefc9917d19f04070ae311019d49db0cd868;hpb=c87b66c86201458c0475d50c6e93f1497f9eec2e;p=vpp.git diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c index a389cefc991..ca0091b3545 100644 --- a/src/vnet/ipsec/ipsec_tun.c +++ b/src/vnet/ipsec/ipsec_tun.c @@ -39,38 +39,29 @@ static int ipsec_tun_protect_feature_set (ipsec_tun_protect_t * itp, u8 enable) { u32 sai = itp->itp_out_sa; - int is_ip4, is_l2, rv; + int rv; - is_ip4 = ip46_address_is_ip4 (&itp->itp_tun.src); - is_l2 = itp->itp_flags & IPSEC_PROTECT_L2; + const char *enc_node = (ip46_address_is_ip4 (&itp->itp_tun.src) ? + "esp4-encrypt-tun" : "esp6-encrypt-tun"); - if (is_ip4) + if (itp->itp_flags & IPSEC_PROTECT_L2) { - if (is_l2) - rv = vnet_feature_enable_disable ("ethernet-output", - "esp4-encrypt-tun", - itp->itp_sw_if_index, enable, - &sai, sizeof (sai)); - else - rv = vnet_feature_enable_disable ("ip4-output", - "esp4-encrypt-tun", - itp->itp_sw_if_index, enable, - &sai, sizeof (sai)); + rv = vnet_feature_enable_disable ("ethernet-output", + enc_node, + itp->itp_sw_if_index, enable, + &sai, sizeof (sai)); } else { - if (is_l2) - rv = vnet_feature_enable_disable ("ethernet-output", - "esp6-encrypt-tun", - itp->itp_sw_if_index, enable, - &sai, sizeof (sai)); - else - rv = vnet_feature_enable_disable ("ip6-output", - "esp6-encrypt-tun", - itp->itp_sw_if_index, enable, - &sai, sizeof (sai)); + rv = vnet_feature_enable_disable ("ip4-output", + enc_node, + itp->itp_sw_if_index, enable, + &sai, sizeof (sai)); + rv = vnet_feature_enable_disable ("ip6-output", + enc_node, + itp->itp_sw_if_index, enable, + &sai, sizeof (sai)); } - ASSERT (!rv); return (rv); } @@ -98,10 +89,14 @@ ipsec_tun_protect_db_add (ipsec_main_t * im, const ipsec_tun_protect_t * itp) if (ip46_address_is_ip4 (&itp->itp_crypto.dst)) { ipsec4_tunnel_key_t key = { - .remote_ip = itp->itp_crypto.dst.ip4.as_u32, + .remote_ip = itp->itp_crypto.dst.ip4, .spi = clib_host_to_net_u32 (sa->spi), }; hash_set (im->tun4_protect_by_key, key.as_u64, res.as_u64); + if (1 == hash_elts(im->tun4_protect_by_key)) + udp_register_dst_port (vlib_get_main(), + UDP_DST_PORT_ipsec, + ipsec4_tun_input_node.index, 1); } else { @@ -127,10 +122,14 @@ ipsec_tun_protect_db_remove (ipsec_main_t * im, if (ip46_address_is_ip4 (&itp->itp_crypto.dst)) { ipsec4_tunnel_key_t key = { - .remote_ip = itp->itp_crypto.dst.ip4.as_u32, + .remote_ip = itp->itp_crypto.dst.ip4, .spi = clib_host_to_net_u32 (sa->spi), }; - hash_unset (im->tun4_protect_by_key, &key); + hash_unset (im->tun4_protect_by_key, key.as_u64); + if (0 == hash_elts(im->tun4_protect_by_key)) + udp_unregister_dst_port (vlib_get_main(), + UDP_DST_PORT_ipsec, + 1); } else { @@ -149,6 +148,7 @@ ipsec_tun_protect_config (ipsec_main_t * im, ipsec_tun_protect_t * itp, u32 sa_out, u32 * sas_in) { ipsec_sa_t *sa; + index_t sai; u32 ii; itp->itp_n_sa_in = vec_len (sas_in); @@ -156,7 +156,13 @@ ipsec_tun_protect_config (ipsec_main_t * im, itp->itp_in_sas[ii] = sas_in[ii]; itp->itp_out_sa = sa_out; + ipsec_sa_lock (itp->itp_out_sa); + /* *INDENT-OFF* */ + FOR_EACH_IPSEC_PROTECT_INPUT_SAI(itp, sai, + ({ + ipsec_sa_lock(sai); + })); FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa, ({ if (ipsec_sa_is_set_IS_TUNNEL (sa)) @@ -184,13 +190,13 @@ ipsec_tun_protect_config (ipsec_main_t * im, * enable the encrypt feature for egress. */ ipsec_tun_protect_feature_set (itp, 1); - } static void ipsec_tun_protect_unconfig (ipsec_main_t * im, ipsec_tun_protect_t * itp) { ipsec_sa_t *sa; + index_t sai; ipsec_tun_protect_feature_set (itp, 0); @@ -199,9 +205,16 @@ ipsec_tun_protect_unconfig (ipsec_main_t * im, ipsec_tun_protect_t * itp) ({ ipsec_sa_unset_IS_PROTECT (sa); })); - /* *INDENT-ON* */ ipsec_tun_protect_db_remove (im, itp); + + ipsec_sa_unlock(itp->itp_out_sa); + + FOR_EACH_IPSEC_PROTECT_INPUT_SAI(itp, sai, + ({ + ipsec_sa_unlock(sai); + })); + /* *INDENT-ON* */ } index_t @@ -213,11 +226,117 @@ ipsec_tun_protect_find (u32 sw_if_index) return (ipsec_protect_db.tunnels[sw_if_index]); } +int +ipsec_tun_protect_update_one (u32 sw_if_index, u32 sa_out, u32 sa_in) +{ + u32 *sas_in = NULL; + int rv; + + vec_add1 (sas_in, sa_in); + rv = ipsec_tun_protect_update (sw_if_index, sa_out, sas_in); + + return (rv); +} + +int +ipsec_tun_protect_update_out (u32 sw_if_index, u32 sa_out) +{ + u32 itpi, *sas_in, sai, *saip; + ipsec_tun_protect_t *itp; + ipsec_main_t *im; + int rv; + + sas_in = NULL; + rv = 0; + im = &ipsec_main; + vec_validate_init_empty (ipsec_protect_db.tunnels, sw_if_index, + INDEX_INVALID); + itpi = ipsec_protect_db.tunnels[sw_if_index]; + + if (INDEX_INVALID == itpi) + { + return (VNET_API_ERROR_INVALID_INTERFACE); + } + + itp = pool_elt_at_index (ipsec_protect_pool, itpi); + + /* *INDENT-0FF* */ + FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai, ( + { + ipsec_sa_lock (sai); + vec_add1 (sas_in, sai); + } + )); + /* *INDENT-ON* */ + + sa_out = ipsec_sa_find_and_lock (sa_out); + + if (~0 == sa_out) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + ipsec_tun_protect_unconfig (im, itp); + ipsec_tun_protect_config (im, itp, sa_out, sas_in); + + ipsec_sa_unlock (sa_out); + vec_foreach (saip, sas_in) ipsec_sa_unlock (*saip); + +out: + vec_free (sas_in); + return (rv); +} + +int +ipsec_tun_protect_update_in (u32 sw_if_index, u32 sa_in) +{ + u32 itpi, *sas_in, sa_out; + ipsec_tun_protect_t *itp; + ipsec_main_t *im; + int rv; + + sas_in = NULL; + rv = 0; + im = &ipsec_main; + vec_validate_init_empty (ipsec_protect_db.tunnels, sw_if_index, + INDEX_INVALID); + itpi = ipsec_protect_db.tunnels[sw_if_index]; + + if (INDEX_INVALID == itpi) + { + return (VNET_API_ERROR_INVALID_INTERFACE); + } + + sa_in = ipsec_sa_find_and_lock (sa_in); + + if (~0 == sa_in) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + vec_add1 (sas_in, sa_in); + + itp = pool_elt_at_index (ipsec_protect_pool, itpi); + sa_out = itp->itp_out_sa; + + ipsec_sa_lock (sa_out); + + ipsec_tun_protect_unconfig (im, itp); + ipsec_tun_protect_config (im, itp, sa_out, sas_in); + + ipsec_sa_unlock (sa_out); + ipsec_sa_unlock (sa_in); +out: + vec_free (sas_in); + return (rv); +} + int ipsec_tun_protect_update (u32 sw_if_index, u32 sa_out, u32 * sas_in) { - u32 itpi, ii; ipsec_tun_protect_t *itp; + u32 itpi, ii, *saip; ipsec_main_t *im; int rv; @@ -229,7 +348,7 @@ ipsec_tun_protect_update (u32 sw_if_index, u32 sa_out, u32 * sas_in) vec_foreach_index (ii, sas_in) { - sas_in[ii] = ipsec_get_sa_index_by_sa_id (sas_in[ii]); + sas_in[ii] = ipsec_sa_find_and_lock (sas_in[ii]); if (~0 == sas_in[ii]) { rv = VNET_API_ERROR_INVALID_VALUE; @@ -237,7 +356,7 @@ ipsec_tun_protect_update (u32 sw_if_index, u32 sa_out, u32 * sas_in) } } - sa_out = ipsec_get_sa_index_by_sa_id (sa_out); + sa_out = ipsec_sa_find_and_lock (sa_out); if (~0 == sa_out) { @@ -323,7 +442,10 @@ ipsec_tun_protect_update (u32 sw_if_index, u32 sa_out, u32 * sas_in) ipsec_tun_protect_config (im, itp, sa_out, sas_in); } + ipsec_sa_unlock (sa_out); + vec_foreach (saip, sas_in) ipsec_sa_unlock (*saip); vec_free (sas_in); + out: return (rv); } @@ -351,10 +473,10 @@ ipsec_tun_protect_del (u32 sw_if_index) pool_put (ipsec_protect_pool, itp); - /* if (0 == hash_elts (im->tun4_protect_by_key)) */ - /* ip4_unregister_protocol (IP_PROTOCOL_IPSEC_ESP); */ - /* if (0 == hash_elts (im->tun6_protect_by_key)) */ - /* ip6_unregister_protocol (IP_PROTOCOL_IPSEC_ESP); */ + if (0 == hash_elts (im->tun4_protect_by_key)) + ip4_unregister_protocol (IP_PROTOCOL_IPSEC_ESP); + if (0 == hash_elts (im->tun6_protect_by_key)) + ip6_unregister_protocol (IP_PROTOCOL_IPSEC_ESP); return (0); }